From 00e55a790706223c903ce6a450c18596a7bc9be0 Mon Sep 17 00:00:00 2001 From: Wedson Almeida Filho Date: Fri, 28 Jun 2013 04:50:45 -0700 Subject: [PATCH 0001/3400] x86: Use asm-goto to implement mutex fast path on x86-64 The new implementation allows the compiler to better optimize the code; the original implementation is still used when the kernel is compiled with older versions of gcc that don't support asm-goto. Compiling with gcc 4.7.3, the original mutex_lock() is 60 bytes with the fast path taking 16 instructions; the new mutex_lock() is 42 bytes, with the fast path taking 12 instructions. The original mutex_unlock() is 24 bytes with the fast path taking 7 instructions; the new mutex_unlock() is 25 bytes (because the compiler used a 2-byte ret) with the fast path taking 4 instructions. The two versions of the functions are included below for reference. Old: ffffffff817742a0 : ffffffff817742a0: 55 push %rbp ffffffff817742a1: 48 89 e5 mov %rsp,%rbp ffffffff817742a4: 48 83 ec 10 sub $0x10,%rsp ffffffff817742a8: 48 89 5d f0 mov %rbx,-0x10(%rbp) ffffffff817742ac: 48 89 fb mov %rdi,%rbx ffffffff817742af: 4c 89 65 f8 mov %r12,-0x8(%rbp) ffffffff817742b3: e8 28 15 00 00 callq ffffffff817757e0 <_cond_resched> ffffffff817742b8: 48 89 df mov %rbx,%rdi ffffffff817742bb: f0 ff 0f lock decl (%rdi) ffffffff817742be: 79 05 jns ffffffff817742c5 ffffffff817742c0: e8 cb 04 00 00 callq ffffffff81774790 <__mutex_lock_slowpath> ffffffff817742c5: 65 48 8b 04 25 c0 b7 mov %gs:0xb7c0,%rax ffffffff817742cc: 00 00 ffffffff817742ce: 4c 8b 65 f8 mov -0x8(%rbp),%r12 ffffffff817742d2: 48 89 43 18 mov %rax,0x18(%rbx) ffffffff817742d6: 48 8b 5d f0 mov -0x10(%rbp),%rbx ffffffff817742da: c9 leaveq ffffffff817742db: c3 retq ffffffff81774250 : ffffffff81774250: 55 push %rbp ffffffff81774251: 48 c7 47 18 00 00 00 movq $0x0,0x18(%rdi) ffffffff81774258: 00 ffffffff81774259: 48 89 e5 mov %rsp,%rbp ffffffff8177425c: f0 ff 07 lock incl (%rdi) ffffffff8177425f: 7f 05 jg ffffffff81774266 ffffffff81774261: e8 ea 04 00 00 callq ffffffff81774750 <__mutex_unlock_slowpath> ffffffff81774266: 5d pop %rbp ffffffff81774267: c3 retq New: ffffffff81774920 : ffffffff81774920: 55 push %rbp ffffffff81774921: 48 89 e5 mov %rsp,%rbp ffffffff81774924: 53 push %rbx ffffffff81774925: 48 89 fb mov %rdi,%rbx ffffffff81774928: e8 a3 0e 00 00 callq ffffffff817757d0 <_cond_resched> ffffffff8177492d: f0 ff 0b lock decl (%rbx) ffffffff81774930: 79 08 jns ffffffff8177493a ffffffff81774932: 48 89 df mov %rbx,%rdi ffffffff81774935: e8 16 fe ff ff callq ffffffff81774750 <__mutex_lock_slowpath> ffffffff8177493a: 65 48 8b 04 25 c0 b7 mov %gs:0xb7c0,%rax ffffffff81774941: 00 00 ffffffff81774943: 48 89 43 18 mov %rax,0x18(%rbx) ffffffff81774947: 5b pop %rbx ffffffff81774948: 5d pop %rbp ffffffff81774949: c3 retq ffffffff81774730 : ffffffff81774730: 48 c7 47 18 00 00 00 movq $0x0,0x18(%rdi) ffffffff81774737: 00 ffffffff81774738: f0 ff 07 lock incl (%rdi) ffffffff8177473b: 7f 0a jg ffffffff81774747 ffffffff8177473d: 55 push %rbp ffffffff8177473e: 48 89 e5 mov %rsp,%rbp ffffffff81774741: e8 aa ff ff ff callq ffffffff817746f0 <__mutex_unlock_slowpath> ffffffff81774746: 5d pop %rbp ffffffff81774747: f3 c3 repz retq Signed-off-by: Wedson Almeida Filho Link: http://lkml.kernel.org/r/1372420245-60021-1-git-send-email-wedsonaf@gmail.com Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/mutex_64.h | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/arch/x86/include/asm/mutex_64.h b/arch/x86/include/asm/mutex_64.h index 68a87b0f8e29..c030bee7690a 100644 --- a/arch/x86/include/asm/mutex_64.h +++ b/arch/x86/include/asm/mutex_64.h @@ -16,6 +16,20 @@ * * Atomically decrements @v and calls if the result is negative. */ +#ifdef CC_HAVE_ASM_GOTO +static inline void __mutex_fastpath_lock(atomic_t *v, + void (*fail_fn)(atomic_t *)) +{ + asm volatile goto(LOCK_PREFIX " decl %0\n" + " jns %l[exit]\n" + : : "m" (v->counter) + : "memory", "cc" + : exit); + fail_fn(v); +exit: + return; +} +#else #define __mutex_fastpath_lock(v, fail_fn) \ do { \ unsigned long dummy; \ @@ -32,6 +46,7 @@ do { \ : "rax", "rsi", "rdx", "rcx", \ "r8", "r9", "r10", "r11", "memory"); \ } while (0) +#endif /** * __mutex_fastpath_lock_retval - try to take the lock by moving the count @@ -59,6 +74,20 @@ static inline int __mutex_fastpath_lock_retval(atomic_t *count, * * Atomically increments @v and calls if the result is nonpositive. */ +#ifdef CC_HAVE_ASM_GOTO +static inline void __mutex_fastpath_unlock(atomic_t *v, + void (*fail_fn)(atomic_t *)) +{ + asm volatile goto(LOCK_PREFIX " incl %0\n" + " jg %l[exit]\n" + : : "m" (v->counter) + : "memory", "cc" + : exit); + fail_fn(v); +exit: + return; +} +#else #define __mutex_fastpath_unlock(v, fail_fn) \ do { \ unsigned long dummy; \ @@ -75,6 +104,7 @@ do { \ : "rax", "rsi", "rdx", "rcx", \ "r8", "r9", "r10", "r11", "memory"); \ } while (0) +#endif #define __mutex_slowpath_needs_to_unlock() 1 From 62122fd7dadac09704782d8bc051fb898a0272bd Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Fri, 28 Jun 2013 18:41:41 +0200 Subject: [PATCH 0002/3400] x86, cpufeature: Use new CC_HAVE_ASM_GOTO ... for checking for "asm goto" compiler support. It is more explicit this way and we cover the cases where distros have backported that support even to gcc versions < 4.5. Signed-off-by: Borislav Petkov Link: http://lkml.kernel.org/r/1372437701-13351-1-git-send-email-bp@alien8.de Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/cpufeature.h | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 47538a61c91b..d3f5c63078d8 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -366,9 +366,10 @@ extern bool __static_cpu_has_safe(u16 bit); */ static __always_inline __pure bool __static_cpu_has(u16 bit) { -#if __GNUC__ > 4 || __GNUC_MINOR__ >= 5 +#ifdef CC_HAVE_ASM_GOTO #ifdef CONFIG_X86_DEBUG_STATIC_CPU_HAS + /* * Catch too early usage of this before alternatives * have run. @@ -384,6 +385,7 @@ static __always_inline __pure bool __static_cpu_has(u16 bit) ".previous\n" /* skipping size check since replacement size = 0 */ : : "i" (X86_FEATURE_ALWAYS) : : t_warn); + #endif asm goto("1: jmp %l[t_no]\n" @@ -406,7 +408,9 @@ static __always_inline __pure bool __static_cpu_has(u16 bit) warn_pre_alternatives(); return false; #endif -#else /* GCC_VERSION >= 40500 */ + +#else /* CC_HAVE_ASM_GOTO */ + u8 flag; /* Open-coded due to __stringify() in ALTERNATIVE() */ asm volatile("1: movb $0,%0\n" @@ -427,7 +431,8 @@ static __always_inline __pure bool __static_cpu_has(u16 bit) ".previous\n" : "=qm" (flag) : "i" (bit)); return flag; -#endif + +#endif /* CC_HAVE_ASM_GOTO */ } #define static_cpu_has(bit) \ @@ -441,7 +446,7 @@ static __always_inline __pure bool __static_cpu_has(u16 bit) static __always_inline __pure bool _static_cpu_has_safe(u16 bit) { -#if __GNUC__ > 4 || __GNUC_MINOR__ >= 5 +#ifdef CC_HAVE_ASM_GOTO /* * We need to spell the jumps to the compiler because, depending on the offset, * the replacement jump can be bigger than the original jump, and this we cannot @@ -475,7 +480,7 @@ static __always_inline __pure bool _static_cpu_has_safe(u16 bit) return false; t_dynamic: return __static_cpu_has_safe(bit); -#else /* GCC_VERSION >= 40500 */ +#else u8 flag; /* Open-coded due to __stringify() in ALTERNATIVE() */ asm volatile("1: movb $2,%0\n" @@ -511,7 +516,7 @@ static __always_inline __pure bool _static_cpu_has_safe(u16 bit) : "=qm" (flag) : "i" (bit), "i" (X86_FEATURE_ALWAYS)); return (flag == 2 ? __static_cpu_has_safe(bit) : flag); -#endif +#endif /* CC_HAVE_ASM_GOTO */ } #define static_cpu_has_safe(bit) \ From 237d1548543312fcc8c99d302ab68fbf8ef6f97f Mon Sep 17 00:00:00 2001 From: Wang YanQing Date: Fri, 28 Jun 2013 22:45:16 +0800 Subject: [PATCH 0003/3400] x86: Fix override new_cpu_data.x86 with 486 We should set X86 to 486 before use cpuid to detect the cpu type, if we set X86 to 486 after cpuid, then we will get 486 until cpu_detect runs. Signed-off-by: Wang YanQing Link: http://lkml.kernel.org/r/20130628144516.GA2177@udknight Acked-by: Borislav Petkov Signed-off-by: H. Peter Anvin --- arch/x86/kernel/head_32.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index e65ddc62e113..fe79573c84b9 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S @@ -410,6 +410,7 @@ enable_paging: /* * Check if it is 486 */ + movb $4,X86 # at least 486 cmpl $-1,X86_CPUID je is486 @@ -437,7 +438,6 @@ enable_paging: movl %edx,X86_CAPABILITY is486: - movb $4,X86 movl $0x50022,%ecx # set AM, WP, NE and MP movl %cr0,%eax andl $0x80000011,%eax # Save PG,PE,ET From 56a942e9315877b8a9a3d2482d4c3b0da840d713 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 2 Jul 2013 23:57:35 +0100 Subject: [PATCH 0004/3400] regulator: lp8755: Provide map_voltage() Improve performance when setting voltages by avoiding a scan through the selectors when we can simply calculate the selector we want. Signed-off-by: Mark Brown --- drivers/regulator/lp8755.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/regulator/lp8755.c b/drivers/regulator/lp8755.c index f0f6ea05065b..e29634148ed2 100644 --- a/drivers/regulator/lp8755.c +++ b/drivers/regulator/lp8755.c @@ -229,6 +229,7 @@ err_i2c: } static struct regulator_ops lp8755_buck_ops = { + .map_voltage = regulator_map_voltage_linear, .list_voltage = regulator_list_voltage_linear, .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, From 761a86b10725d314cad73a75020a2544c38d5a83 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 10 Jul 2013 17:34:43 +0300 Subject: [PATCH 0005/3400] spi: tle62x0: dump small buffers using %*ph We have nice specifier in kernel for that. It changes separator from ',' (comma) to space, though it's not a big deal since it's just a debug message. Signed-off-by: Andy Shevchenko Signed-off-by: Mark Brown --- drivers/spi/spi-tle62x0.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/spi/spi-tle62x0.c b/drivers/spi/spi-tle62x0.c index 6b0874d782ed..3e528c0396e7 100644 --- a/drivers/spi/spi-tle62x0.c +++ b/drivers/spi/spi-tle62x0.c @@ -52,8 +52,7 @@ static inline int tle62x0_write(struct tle62x0_state *st) buff[1] = gpio_state; } - dev_dbg(&st->us->dev, "buff %02x,%02x,%02x\n", - buff[0], buff[1], buff[2]); + dev_dbg(&st->us->dev, "buff %3ph\n", buff); return spi_write(st->us, buff, (st->nr_gpio == 16) ? 3 : 2); } From 67516844625f45f0ce148a01c27bf41f591872b2 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 9 Jul 2013 18:56:31 +0200 Subject: [PATCH 0006/3400] perf: Remove the 'match' callback for auxiliary events processing It gives the following benefits: - only one function pointer is passed along the way - the 'match' function is called within output function and could be inlined by the compiler Suggested-by: Peter Zijlstra Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Arnaldo Carvalho de Melo Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1373388991-9711-1-git-send-email-jolsa@redhat.com Signed-off-by: Ingo Molnar --- kernel/events/core.c | 79 ++++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 40 deletions(-) diff --git a/kernel/events/core.c b/kernel/events/core.c index eba8fb5834ae..708ab70ca442 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -4680,12 +4680,10 @@ perf_event_read_event(struct perf_event *event, perf_output_end(&handle); } -typedef int (perf_event_aux_match_cb)(struct perf_event *event, void *data); typedef void (perf_event_aux_output_cb)(struct perf_event *event, void *data); static void perf_event_aux_ctx(struct perf_event_context *ctx, - perf_event_aux_match_cb match, perf_event_aux_output_cb output, void *data) { @@ -4696,15 +4694,12 @@ perf_event_aux_ctx(struct perf_event_context *ctx, continue; if (!event_filter_match(event)) continue; - if (match(event, data)) - output(event, data); + output(event, data); } } static void -perf_event_aux(perf_event_aux_match_cb match, - perf_event_aux_output_cb output, - void *data, +perf_event_aux(perf_event_aux_output_cb output, void *data, struct perf_event_context *task_ctx) { struct perf_cpu_context *cpuctx; @@ -4717,7 +4712,7 @@ perf_event_aux(perf_event_aux_match_cb match, cpuctx = get_cpu_ptr(pmu->pmu_cpu_context); if (cpuctx->unique_pmu != pmu) goto next; - perf_event_aux_ctx(&cpuctx->ctx, match, output, data); + perf_event_aux_ctx(&cpuctx->ctx, output, data); if (task_ctx) goto next; ctxn = pmu->task_ctx_nr; @@ -4725,14 +4720,14 @@ perf_event_aux(perf_event_aux_match_cb match, goto next; ctx = rcu_dereference(current->perf_event_ctxp[ctxn]); if (ctx) - perf_event_aux_ctx(ctx, match, output, data); + perf_event_aux_ctx(ctx, output, data); next: put_cpu_ptr(pmu->pmu_cpu_context); } if (task_ctx) { preempt_disable(); - perf_event_aux_ctx(task_ctx, match, output, data); + perf_event_aux_ctx(task_ctx, output, data); preempt_enable(); } rcu_read_unlock(); @@ -4759,6 +4754,12 @@ struct perf_task_event { } event_id; }; +static int perf_event_task_match(struct perf_event *event) +{ + return event->attr.comm || event->attr.mmap || + event->attr.mmap_data || event->attr.task; +} + static void perf_event_task_output(struct perf_event *event, void *data) { @@ -4768,6 +4769,9 @@ static void perf_event_task_output(struct perf_event *event, struct task_struct *task = task_event->task; int ret, size = task_event->event_id.header.size; + if (!perf_event_task_match(event)) + return; + perf_event_header__init_id(&task_event->event_id.header, &sample, event); ret = perf_output_begin(&handle, event, @@ -4790,13 +4794,6 @@ out: task_event->event_id.header.size = size; } -static int perf_event_task_match(struct perf_event *event, - void *data __maybe_unused) -{ - return event->attr.comm || event->attr.mmap || - event->attr.mmap_data || event->attr.task; -} - static void perf_event_task(struct task_struct *task, struct perf_event_context *task_ctx, int new) @@ -4825,8 +4822,7 @@ static void perf_event_task(struct task_struct *task, }, }; - perf_event_aux(perf_event_task_match, - perf_event_task_output, + perf_event_aux(perf_event_task_output, &task_event, task_ctx); } @@ -4853,6 +4849,11 @@ struct perf_comm_event { } event_id; }; +static int perf_event_comm_match(struct perf_event *event) +{ + return event->attr.comm; +} + static void perf_event_comm_output(struct perf_event *event, void *data) { @@ -4862,6 +4863,9 @@ static void perf_event_comm_output(struct perf_event *event, int size = comm_event->event_id.header.size; int ret; + if (!perf_event_comm_match(event)) + return; + perf_event_header__init_id(&comm_event->event_id.header, &sample, event); ret = perf_output_begin(&handle, event, comm_event->event_id.header.size); @@ -4883,12 +4887,6 @@ out: comm_event->event_id.header.size = size; } -static int perf_event_comm_match(struct perf_event *event, - void *data __maybe_unused) -{ - return event->attr.comm; -} - static void perf_event_comm_event(struct perf_comm_event *comm_event) { char comm[TASK_COMM_LEN]; @@ -4903,8 +4901,7 @@ static void perf_event_comm_event(struct perf_comm_event *comm_event) comm_event->event_id.header.size = sizeof(comm_event->event_id) + size; - perf_event_aux(perf_event_comm_match, - perf_event_comm_output, + perf_event_aux(perf_event_comm_output, comm_event, NULL); } @@ -4967,6 +4964,17 @@ struct perf_mmap_event { } event_id; }; +static int perf_event_mmap_match(struct perf_event *event, + void *data) +{ + struct perf_mmap_event *mmap_event = data; + struct vm_area_struct *vma = mmap_event->vma; + int executable = vma->vm_flags & VM_EXEC; + + return (!executable && event->attr.mmap_data) || + (executable && event->attr.mmap); +} + static void perf_event_mmap_output(struct perf_event *event, void *data) { @@ -4976,6 +4984,9 @@ static void perf_event_mmap_output(struct perf_event *event, int size = mmap_event->event_id.header.size; int ret; + if (!perf_event_mmap_match(event, data)) + return; + perf_event_header__init_id(&mmap_event->event_id.header, &sample, event); ret = perf_output_begin(&handle, event, mmap_event->event_id.header.size); @@ -4996,17 +5007,6 @@ out: mmap_event->event_id.header.size = size; } -static int perf_event_mmap_match(struct perf_event *event, - void *data) -{ - struct perf_mmap_event *mmap_event = data; - struct vm_area_struct *vma = mmap_event->vma; - int executable = vma->vm_flags & VM_EXEC; - - return (!executable && event->attr.mmap_data) || - (executable && event->attr.mmap); -} - static void perf_event_mmap_event(struct perf_mmap_event *mmap_event) { struct vm_area_struct *vma = mmap_event->vma; @@ -5070,8 +5070,7 @@ got_name: mmap_event->event_id.header.size = sizeof(mmap_event->event_id) + size; - perf_event_aux(perf_event_mmap_match, - perf_event_mmap_output, + perf_event_aux(perf_event_mmap_output, mmap_event, NULL); From a51805efae5dda0da66f79268ffcf0715f9dbea4 Mon Sep 17 00:00:00 2001 From: Michel Lespinasse Date: Mon, 8 Jul 2013 14:23:49 -0700 Subject: [PATCH 0007/3400] lockdep: Introduce lock_acquire_exclusive()/shared() helper macros In lockdep.h, the spinlock/mutex/rwsem/rwlock/lock_map acquire macros have different definitions based on the value of CONFIG_PROVE_LOCKING. We have separate ifdefs for each of these definitions, which seems redundant. Introduce lock_acquire_{exclusive,shared,shared_recursive} helpers which will have different definitions based on CONFIG_PROVE_LOCKING. Then all other helper macros can be defined based on the above ones, which reduces the amount of ifdefined code. Signed-off-by: Michel Lespinasse Signed-off-by: Andrew Morton Signed-off-by: Peter Zijlstra Cc: Oleg Nesterov Cc: Lai Jiangshan Cc: "Srivatsa S. Bhat" Cc: Rusty Russell Cc: Andi Kleen Cc: "Paul E. McKenney" Cc: Steven Rostedt Link: http://lkml.kernel.org/r/20130708212350.6DD1931C15E@corp2gmr1-1.hot.corp.google.com Signed-off-by: Ingo Molnar --- include/linux/lockdep.h | 92 +++++++++++------------------------------ 1 file changed, 23 insertions(+), 69 deletions(-) diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h index f1e877b79ed8..cfc2f119779a 100644 --- a/include/linux/lockdep.h +++ b/include/linux/lockdep.h @@ -365,7 +365,7 @@ extern void lockdep_trace_alloc(gfp_t mask); #define lockdep_recursing(tsk) ((tsk)->lockdep_recursion) -#else /* !LOCKDEP */ +#else /* !CONFIG_LOCKDEP */ static inline void lockdep_off(void) { @@ -479,82 +479,36 @@ static inline void print_irqtrace_events(struct task_struct *curr) * on the per lock-class debug mode: */ -#ifdef CONFIG_DEBUG_LOCK_ALLOC -# ifdef CONFIG_PROVE_LOCKING -# define spin_acquire(l, s, t, i) lock_acquire(l, s, t, 0, 2, NULL, i) -# define spin_acquire_nest(l, s, t, n, i) lock_acquire(l, s, t, 0, 2, n, i) -# else -# define spin_acquire(l, s, t, i) lock_acquire(l, s, t, 0, 1, NULL, i) -# define spin_acquire_nest(l, s, t, n, i) lock_acquire(l, s, t, 0, 1, NULL, i) -# endif -# define spin_release(l, n, i) lock_release(l, n, i) +#ifdef CONFIG_PROVE_LOCKING + #define lock_acquire_exclusive(l, s, t, n, i) lock_acquire(l, s, t, 0, 2, n, i) + #define lock_acquire_shared(l, s, t, n, i) lock_acquire(l, s, t, 1, 2, n, i) + #define lock_acquire_shared_recursive(l, s, t, n, i) lock_acquire(l, s, t, 2, 2, n, i) #else -# define spin_acquire(l, s, t, i) do { } while (0) -# define spin_release(l, n, i) do { } while (0) + #define lock_acquire_exclusive(l, s, t, n, i) lock_acquire(l, s, t, 0, 1, n, i) + #define lock_acquire_shared(l, s, t, n, i) lock_acquire(l, s, t, 1, 1, n, i) + #define lock_acquire_shared_recursive(l, s, t, n, i) lock_acquire(l, s, t, 2, 1, n, i) #endif -#ifdef CONFIG_DEBUG_LOCK_ALLOC -# ifdef CONFIG_PROVE_LOCKING -# define rwlock_acquire(l, s, t, i) lock_acquire(l, s, t, 0, 2, NULL, i) -# define rwlock_acquire_read(l, s, t, i) lock_acquire(l, s, t, 2, 2, NULL, i) -# else -# define rwlock_acquire(l, s, t, i) lock_acquire(l, s, t, 0, 1, NULL, i) -# define rwlock_acquire_read(l, s, t, i) lock_acquire(l, s, t, 2, 1, NULL, i) -# endif -# define rwlock_release(l, n, i) lock_release(l, n, i) -#else -# define rwlock_acquire(l, s, t, i) do { } while (0) -# define rwlock_acquire_read(l, s, t, i) do { } while (0) -# define rwlock_release(l, n, i) do { } while (0) -#endif +#define spin_acquire(l, s, t, i) lock_acquire_exclusive(l, s, t, NULL, i) +#define spin_acquire_nest(l, s, t, n, i) lock_acquire_exclusive(l, s, t, n, i) +#define spin_release(l, n, i) lock_release(l, n, i) -#ifdef CONFIG_DEBUG_LOCK_ALLOC -# ifdef CONFIG_PROVE_LOCKING -# define mutex_acquire(l, s, t, i) lock_acquire(l, s, t, 0, 2, NULL, i) -# define mutex_acquire_nest(l, s, t, n, i) lock_acquire(l, s, t, 0, 2, n, i) -# else -# define mutex_acquire(l, s, t, i) lock_acquire(l, s, t, 0, 1, NULL, i) -# define mutex_acquire_nest(l, s, t, n, i) lock_acquire(l, s, t, 0, 1, n, i) -# endif -# define mutex_release(l, n, i) lock_release(l, n, i) -#else -# define mutex_acquire(l, s, t, i) do { } while (0) -# define mutex_acquire_nest(l, s, t, n, i) do { } while (0) -# define mutex_release(l, n, i) do { } while (0) -#endif +#define rwlock_acquire(l, s, t, i) lock_acquire_exclusive(l, s, t, NULL, i) +#define rwlock_acquire_read(l, s, t, i) lock_acquire_shared_recursive(l, s, t, NULL, i) +#define rwlock_release(l, n, i) lock_release(l, n, i) -#ifdef CONFIG_DEBUG_LOCK_ALLOC -# ifdef CONFIG_PROVE_LOCKING -# define rwsem_acquire(l, s, t, i) lock_acquire(l, s, t, 0, 2, NULL, i) -# define rwsem_acquire_nest(l, s, t, n, i) lock_acquire(l, s, t, 0, 2, n, i) -# define rwsem_acquire_read(l, s, t, i) lock_acquire(l, s, t, 1, 2, NULL, i) -# else -# define rwsem_acquire(l, s, t, i) lock_acquire(l, s, t, 0, 1, NULL, i) -# define rwsem_acquire_nest(l, s, t, n, i) lock_acquire(l, s, t, 0, 1, n, i) -# define rwsem_acquire_read(l, s, t, i) lock_acquire(l, s, t, 1, 1, NULL, i) -# endif +#define mutex_acquire(l, s, t, i) lock_acquire_exclusive(l, s, t, NULL, i) +#define mutex_acquire_nest(l, s, t, n, i) lock_acquire_exclusive(l, s, t, n, i) +#define mutex_release(l, n, i) lock_release(l, n, i) + +#define rwsem_acquire(l, s, t, i) lock_acquire_exclusive(l, s, t, NULL, i) +#define rwsem_acquire_nest(l, s, t, n, i) lock_acquire_exclusive(l, s, t, n, i) +#define rwsem_acquire_read(l, s, t, i) lock_acquire_shared(l, s, t, NULL, i) # define rwsem_release(l, n, i) lock_release(l, n, i) -#else -# define rwsem_acquire(l, s, t, i) do { } while (0) -# define rwsem_acquire_nest(l, s, t, n, i) do { } while (0) -# define rwsem_acquire_read(l, s, t, i) do { } while (0) -# define rwsem_release(l, n, i) do { } while (0) -#endif -#ifdef CONFIG_DEBUG_LOCK_ALLOC -# ifdef CONFIG_PROVE_LOCKING -# define lock_map_acquire(l) lock_acquire(l, 0, 0, 0, 2, NULL, _THIS_IP_) -# define lock_map_acquire_read(l) lock_acquire(l, 0, 0, 2, 2, NULL, _THIS_IP_) -# else -# define lock_map_acquire(l) lock_acquire(l, 0, 0, 0, 1, NULL, _THIS_IP_) -# define lock_map_acquire_read(l) lock_acquire(l, 0, 0, 2, 1, NULL, _THIS_IP_) -# endif +#define lock_map_acquire(l) lock_acquire_exclusive(l, 0, 0, NULL, _THIS_IP_) +#define lock_map_acquire_read(l) lock_acquire_shared_recursive(l, 0, 0, NULL, _THIS_IP_) # define lock_map_release(l) lock_release(l, 1, _THIS_IP_) -#else -# define lock_map_acquire(l) do { } while (0) -# define lock_map_acquire_read(l) do { } while (0) -# define lock_map_release(l) do { } while (0) -#endif #ifdef CONFIG_PROVE_LOCKING # define might_lock(lock) \ From c4be9cb4f19cbd534a6c4c334cd48d8bb483e17a Mon Sep 17 00:00:00 2001 From: Michel Lespinasse Date: Mon, 8 Jul 2013 14:23:51 -0700 Subject: [PATCH 0008/3400] lglock: Update lockdep annotations to report recursive local locks Oleg Nesterov recently noticed that the lockdep annotations in lglock.c are not sufficient to detect some obvious deadlocks, such as lg_local_lock(LOCK) + lg_local_lock(LOCK) or spin_lock(X) + lg_local_lock(Y) vs lg_local_lock(Y) + spin_lock(X). Both issues are easily fixed by indicating to lockdep that lglock's local locks are not recursive. We shouldn't use the rwlock acquire/release functions here, as lglock doesn't share the same semantics. Instead we can base our lockdep annotations on the lock_acquire_shared (for local lglock) and lock_acquire_exclusive (for global lglock) helpers. I am not proposing new lglock specific helpers as I don't see the point of the existing second level of helpers :) Noticed-by: Oleg Nesterov Signed-off-by: Michel Lespinasse Cc: Lai Jiangshan Cc: "Srivatsa S. Bhat" Cc: Rusty Russell Cc: Andi Kleen Cc: "Paul E. McKenney" Cc: Steven Rostedt Signed-off-by: Andrew Morton Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/20130708212352.1769031C15E@corp2gmr1-1.hot.corp.google.com Signed-off-by: Ingo Molnar --- kernel/lglock.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/kernel/lglock.c b/kernel/lglock.c index 6535a667a5a7..86ae2aebf004 100644 --- a/kernel/lglock.c +++ b/kernel/lglock.c @@ -21,7 +21,7 @@ void lg_local_lock(struct lglock *lg) arch_spinlock_t *lock; preempt_disable(); - rwlock_acquire_read(&lg->lock_dep_map, 0, 0, _RET_IP_); + lock_acquire_shared(&lg->lock_dep_map, 0, 0, NULL, _RET_IP_); lock = this_cpu_ptr(lg->lock); arch_spin_lock(lock); } @@ -31,7 +31,7 @@ void lg_local_unlock(struct lglock *lg) { arch_spinlock_t *lock; - rwlock_release(&lg->lock_dep_map, 1, _RET_IP_); + lock_release(&lg->lock_dep_map, 1, _RET_IP_); lock = this_cpu_ptr(lg->lock); arch_spin_unlock(lock); preempt_enable(); @@ -43,7 +43,7 @@ void lg_local_lock_cpu(struct lglock *lg, int cpu) arch_spinlock_t *lock; preempt_disable(); - rwlock_acquire_read(&lg->lock_dep_map, 0, 0, _RET_IP_); + lock_acquire_shared(&lg->lock_dep_map, 0, 0, NULL, _RET_IP_); lock = per_cpu_ptr(lg->lock, cpu); arch_spin_lock(lock); } @@ -53,7 +53,7 @@ void lg_local_unlock_cpu(struct lglock *lg, int cpu) { arch_spinlock_t *lock; - rwlock_release(&lg->lock_dep_map, 1, _RET_IP_); + lock_release(&lg->lock_dep_map, 1, _RET_IP_); lock = per_cpu_ptr(lg->lock, cpu); arch_spin_unlock(lock); preempt_enable(); @@ -65,7 +65,7 @@ void lg_global_lock(struct lglock *lg) int i; preempt_disable(); - rwlock_acquire(&lg->lock_dep_map, 0, 0, _RET_IP_); + lock_acquire_exclusive(&lg->lock_dep_map, 0, 0, NULL, _RET_IP_); for_each_possible_cpu(i) { arch_spinlock_t *lock; lock = per_cpu_ptr(lg->lock, i); @@ -78,7 +78,7 @@ void lg_global_unlock(struct lglock *lg) { int i; - rwlock_release(&lg->lock_dep_map, 1, _RET_IP_); + lock_release(&lg->lock_dep_map, 1, _RET_IP_); for_each_possible_cpu(i) { arch_spinlock_t *lock; lock = per_cpu_ptr(lg->lock, i); From cedce3e730833d26a37826a96e1905b6ef387df9 Mon Sep 17 00:00:00 2001 From: Kirill Tkhai Date: Thu, 4 Jul 2013 22:48:20 +0400 Subject: [PATCH 0009/3400] sched/__wake_up_sync_key(): Fix nr_exclusive tasks which lead to WF_SYNC clearing Only one task can replace the waker. Signed-off-by: Kirill Tkhai CC: Steven Rostedt Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/512421372963700@web25f.yandex.ru Signed-off-by: Ingo Molnar --- kernel/sched/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 0d8eb4525e76..f73787159188 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -2660,7 +2660,7 @@ void __wake_up_sync_key(wait_queue_head_t *q, unsigned int mode, if (unlikely(!q)) return; - if (unlikely(!nr_exclusive)) + if (unlikely(nr_exclusive != 1)) wake_flags = 0; spin_lock_irqsave(&q->lock, flags); From ec1e7e437ac47ecf7b4e07241036b1e1c3366012 Mon Sep 17 00:00:00 2001 From: Sukadev Bhattiprolu Date: Wed, 22 May 2013 17:42:38 -0700 Subject: [PATCH 0010/3400] perf tools: Rename cpu_map__all() to cpu_map__empty() The CPU map is in an "empty" (or not-applicable) state when monitoring specific threads. cpu_map__all() returns true if the CPU map is in this empty state (i.e for the 'empty_cpu_map' or if we created the map via cpu_map__dummy_new(). The name, cpu_map__all(), is misleading, because even when monitoring all CPUs, (eg: perf record -a), cpu_map__all() returns false. Rename cpu_map__all() to cpu_map__empty(). Signed-off-by: Sukadev Bhattiprolu Cc: Jiri Olsa Link: http://lkml.kernel.org/r/20130523012620.GA27733@us.ibm.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/cpumap.h | 2 +- tools/perf/util/evlist.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h index 9bed02e5fb3d..b123bb9d6f55 100644 --- a/tools/perf/util/cpumap.h +++ b/tools/perf/util/cpumap.h @@ -41,7 +41,7 @@ static inline int cpu_map__nr(const struct cpu_map *map) return map ? map->nr : 1; } -static inline bool cpu_map__all(const struct cpu_map *map) +static inline bool cpu_map__empty(const struct cpu_map *map) { return map ? map->map[0] == -1 : true; } diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 8065ce8fa9a5..4a901be599ed 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -421,7 +421,7 @@ void perf_evlist__munmap(struct perf_evlist *evlist) static int perf_evlist__alloc_mmap(struct perf_evlist *evlist) { evlist->nr_mmaps = cpu_map__nr(evlist->cpus); - if (cpu_map__all(evlist->cpus)) + if (cpu_map__empty(evlist->cpus)) evlist->nr_mmaps = thread_map__nr(evlist->threads); evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap)); return evlist->mmap != NULL ? 0 : -ENOMEM; @@ -573,7 +573,7 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, return -ENOMEM; } - if (cpu_map__all(cpus)) + if (cpu_map__empty(cpus)) return perf_evlist__mmap_per_thread(evlist, prot, mask); return perf_evlist__mmap_per_cpu(evlist, prot, mask); From 0d3942dbcf7f7e8955ba89deed4749b0ad64d721 Mon Sep 17 00:00:00 2001 From: Sukadev Bhattiprolu Date: Tue, 14 May 2013 22:56:51 -0700 Subject: [PATCH 0011/3400] perf top: Add --objdump option perf: Add objdump option to 'perf top' Like with 'perf annotate' add the --objdump option to perf top so users can specify an alternate path to the /usr/bin/objdump binary. Reported-by: David A. Gilbert Signed-off-by: Sukadev Bhattiprolu Cc: DavidAGilbert@uk.ibm.com Cc: Jiri Olsa Cc: Maynard Johnson Link: http://lkml.kernel.org/r/20130515055651.GA9985@us.ibm.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-top.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index e06c4f869330..a237059f51cf 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -40,6 +40,7 @@ #include "util/xyarray.h" #include "util/sort.h" #include "util/intlist.h" +#include "arch/common.h" #include "util/debug.h" @@ -939,6 +940,12 @@ static int __cmd_top(struct perf_top *top) if (top->session == NULL) return -ENOMEM; + if (!objdump_path) { + ret = perf_session_env__lookup_objdump(&top->session->header.env); + if (ret) + goto out_delete; + } + ret = perf_top__setup_sample_type(top); if (ret) goto out_delete; @@ -1114,6 +1121,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) "Interleave source code with assembly code (default)"), OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw, "Display raw encoding of assembly instructions (default)"), + OPT_STRING(0, "objdump", &objdump_path, "path", + "objdump binary to use for disassembly and annotations"), OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", "Specify disassembler style (e.g. -M intel for intel syntax)"), OPT_STRING('u', "uid", &target->uid_str, "user", "user to profile"), From eb4fe9cbb1599a673bde0d6dad50e609404275c7 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 7 Jun 2013 15:37:01 +0200 Subject: [PATCH 0012/3400] perf tools: Remove cwd from perf_session struct Removing 'cwd' from perf_session struct as it's no longer needed. Signed-off-by: Jiri Olsa Cc: Andi Kleen Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1370612223-19188-1-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/session.h | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index f3b235ec7bf4..ad8d3d4ef14e 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -37,7 +37,6 @@ struct perf_session { int fd; bool fd_pipe; bool repipe; - char *cwd; struct ordered_samples ordered_samples; char filename[1]; }; From 5888a8c26e5f8e76334d579637f9ed55036cec5a Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 7 Jun 2013 15:37:02 +0200 Subject: [PATCH 0013/3400] perf tests: Omit end of the symbol check failure for test 1 Omitting end of the function check failure for test 1, since there's no way to get exact symbol end via kallsyms. Leaving the debug message. Signed-off-by: Jiri Olsa Cc: Andi Kleen Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1370612223-19188-2-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/vmlinux-kallsyms.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/tools/perf/tests/vmlinux-kallsyms.c b/tools/perf/tests/vmlinux-kallsyms.c index 7b4c4d26d1ba..add15392c622 100644 --- a/tools/perf/tests/vmlinux-kallsyms.c +++ b/tools/perf/tests/vmlinux-kallsyms.c @@ -139,11 +139,18 @@ next_pair: * _really_ have a problem. */ s64 skew = sym->end - pair->end; - if (llabs(skew) < page_size) - continue; + if (llabs(skew) >= page_size) + pr_debug("%#" PRIx64 ": diff end addr for %s v: %#" PRIx64 " k: %#" PRIx64 "\n", + sym->start, sym->name, sym->end, pair->end); + + /* + * Do not count this as a failure, because we + * could really find a case where it's not + * possible to get proper function end from + * kallsyms. + */ + continue; - pr_debug("%#" PRIx64 ": diff end addr for %s v: %#" PRIx64 " k: %#" PRIx64 "\n", - sym->start, sym->name, sym->end, pair->end); } else { struct rb_node *nnd; detour: From 450ac18d8f8076f0c522af1afb8519614a3b32f5 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 7 Jun 2013 15:37:03 +0200 Subject: [PATCH 0014/3400] perf tests: Make TEST_ASSERT_VAL global Making TEST_ASSERT_VAL global as it's used in multiple objects. Signed-off-by: Jiri Olsa Cc: Andi Kleen Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1370612223-19188-3-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/dso-data.c | 8 -------- tools/perf/tests/parse-events.c | 8 -------- tools/perf/tests/tests.h | 8 ++++++++ 3 files changed, 8 insertions(+), 16 deletions(-) diff --git a/tools/perf/tests/dso-data.c b/tools/perf/tests/dso-data.c index 5eaffa2de9c5..dffe0551acaa 100644 --- a/tools/perf/tests/dso-data.c +++ b/tools/perf/tests/dso-data.c @@ -10,14 +10,6 @@ #include "symbol.h" #include "tests.h" -#define TEST_ASSERT_VAL(text, cond) \ -do { \ - if (!(cond)) { \ - pr_debug("FAILED %s:%d %s\n", __FILE__, __LINE__, text); \ - return -1; \ - } \ -} while (0) - static char *test_file(int size) { static char buf_templ[] = "/tmp/test-XXXXXX"; diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c index 0275bab4ea9e..ad950f57d85b 100644 --- a/tools/perf/tests/parse-events.c +++ b/tools/perf/tests/parse-events.c @@ -7,14 +7,6 @@ #include "tests.h" #include -#define TEST_ASSERT_VAL(text, cond) \ -do { \ - if (!(cond)) { \ - pr_debug("FAILED %s:%d %s\n", __FILE__, __LINE__, text); \ - return -1; \ - } \ -} while (0) - #define PERF_TP_SAMPLE_TYPE (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | \ PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD) diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index dd7feae2d37b..07a92f9c6712 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -1,6 +1,14 @@ #ifndef TESTS_H #define TESTS_H +#define TEST_ASSERT_VAL(text, cond) \ +do { \ + if (!(cond)) { \ + pr_debug("FAILED %s:%d %s\n", __FILE__, __LINE__, text); \ + return -1; \ + } \ +} while (0) + enum { TEST_OK = 0, TEST_FAIL = -1, From 4e319027a7aee58ce8d409f5597b418f08307841 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 11 Jun 2013 17:29:18 +0200 Subject: [PATCH 0015/3400] perf tools: Use default include path notation for libtraceevent headers Header files of libtraceevent or no longer local headers. Thus, use default path notation for them. Also removing extra traceevent include path and instead handle this similar to liblk. Signed-off-by: Robert Richter Signed-off-by: Robert Richter Cc: Ingo Molnar Cc: Jiri Olsa Cc: Robert Richter Link: http://lkml.kernel.org/r/1370964558-8599-1-git-send-email-rric@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile | 2 +- tools/perf/builtin-trace.c | 2 +- tools/perf/config/Makefile | 5 +++-- tools/perf/tests/evsel-tp-sched.c | 2 +- tools/perf/util/evsel.c | 8 ++++---- tools/perf/util/session.c | 2 +- tools/perf/util/trace-event.h | 2 +- 7 files changed, 12 insertions(+), 11 deletions(-) diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 641fccddb249..5b7c6db87fde 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -281,7 +281,7 @@ LIB_H += util/cpumap.h LIB_H += util/top.h LIB_H += $(ARCH_INCLUDE) LIB_H += util/cgroup.h -LIB_H += $(TRACE_EVENT_DIR)event-parse.h +LIB_H += $(LIB_INCLUDE)traceevent/event-parse.h LIB_H += util/target.h LIB_H += util/rblist.h LIB_H += util/intlist.h diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index ab3ed4af1466..87fc7d08ca02 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1,3 +1,4 @@ +#include #include "builtin.h" #include "util/color.h" #include "util/evlist.h" @@ -5,7 +6,6 @@ #include "util/thread.h" #include "util/parse-options.h" #include "util/thread_map.h" -#include "event-parse.h" #include #include diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index b5d9238cb181..214e17e97e5c 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile @@ -46,6 +46,8 @@ ifneq ($(obj-perf),) obj-perf := $(abspath $(obj-perf))/ endif +LIB_INCLUDE := $(srctree)/tools/lib/ + # include ARCH specific config -include $(src-perf)/arch/$(ARCH)/Makefile @@ -121,8 +123,7 @@ endif CFLAGS += -I$(src-perf)/util CFLAGS += -I$(src-perf) -CFLAGS += -I$(TRACE_EVENT_DIR) -CFLAGS += -I$(srctree)/tools/lib/ +CFLAGS += -I$(LIB_INCLUDE) CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE diff --git a/tools/perf/tests/evsel-tp-sched.c b/tools/perf/tests/evsel-tp-sched.c index a5d2fcc5ae35..f79e7d059820 100644 --- a/tools/perf/tests/evsel-tp-sched.c +++ b/tools/perf/tests/evsel-tp-sched.c @@ -1,6 +1,6 @@ +#include #include "evsel.h" #include "tests.h" -#include "event-parse.h" static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name, int size, bool should_be_signed) diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index c9c7494506a1..a6354619fa5d 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -9,17 +9,17 @@ #include #include -#include "asm/bug.h" #include -#include "event-parse.h" +#include +#include +#include +#include "asm/bug.h" #include "evsel.h" #include "evlist.h" #include "util.h" #include "cpumap.h" #include "thread_map.h" #include "target.h" -#include -#include #include "perf_regs.h" static struct { diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index cf1fe01b7e89..ad47fb9d0204 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1,4 +1,5 @@ #include +#include #include #include @@ -12,7 +13,6 @@ #include "sort.h" #include "util.h" #include "cpumap.h" -#include "event-parse.h" #include "perf_regs.h" #include "vdso.h" diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h index 1978c398ad87..11eb7fd37608 100644 --- a/tools/perf/util/trace-event.h +++ b/tools/perf/util/trace-event.h @@ -1,8 +1,8 @@ #ifndef _PERF_UTIL_TRACE_EVENT_H #define _PERF_UTIL_TRACE_EVENT_H +#include #include "parse-events.h" -#include "event-parse.h" #include "session.h" struct machine; From ba58041a8f0f0437c6c33414aa0d3fcf62ba90a5 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Fri, 7 Jun 2013 16:22:12 -0600 Subject: [PATCH 0016/3400] perf tools: Add methods for setting/retrieving priv element of thread struct Signed-off-by: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1370643734-9579-3-git-send-email-dsahern@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/thread.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index eeb7ac62b9e3..5e7ba35a5517 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h @@ -47,4 +47,14 @@ void thread__find_addr_location(struct thread *thread, struct machine *machine, u8 cpumode, enum map_type type, u64 addr, struct addr_location *al, symbol_filter_t filter); + +static inline void *thread__priv(struct thread *thread) +{ + return thread->priv; +} + +static inline void thread__set_priv(struct thread *thread, void *p) +{ + thread->priv = p; +} #endif /* __PERF_THREAD_H */ From fa1531fdd7b6332aa61bcc9fda495583acba460d Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 10 Jun 2013 16:31:28 -0400 Subject: [PATCH 0017/3400] perf tools: Remove callchain_cursor_reset call Removing callchain_cursor_reset call as it is called in subsequent machine__resolve_callchain_sample function. Signed-off-by: Jiri Olsa Cc: Andi Kleen Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-ic53wabwmmgvvwve2ymv3yf7@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/machine.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index b2ecad6ec46b..93527afb09d5 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -1242,8 +1242,6 @@ int machine__resolve_callchain(struct machine *machine, { int ret; - callchain_cursor_reset(&callchain_cursor); - ret = machine__resolve_callchain_sample(machine, thread, sample->callchain, parent); if (ret) From 167aedc44e1743777e6aee71b0fe7ed94c6298cd Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 26 Jun 2013 16:14:04 +0900 Subject: [PATCH 0018/3400] perf util: Move debugfs/tracing helper functions to util.c Since they're generic helpers move them to util.c so that they can be used by others. Signed-off-by: Namhyung Kim Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1372230862-15861-2-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/trace-event-info.c | 59 ------------------------------ tools/perf/util/util.c | 59 ++++++++++++++++++++++++++++++ tools/perf/util/util.h | 3 ++ 3 files changed, 62 insertions(+), 59 deletions(-) diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c index 3917eb9a8479..615c0628678b 100644 --- a/tools/perf/util/trace-event-info.c +++ b/tools/perf/util/trace-event-info.c @@ -46,65 +46,6 @@ static int output_fd; -static const char *find_debugfs(void) -{ - const char *path = perf_debugfs_mount(NULL); - - if (!path) - pr_debug("Your kernel does not support the debugfs filesystem"); - - return path; -} - -/* - * Finds the path to the debugfs/tracing - * Allocates the string and stores it. - */ -static const char *find_tracing_dir(void) -{ - static char *tracing; - static int tracing_found; - const char *debugfs; - - if (tracing_found) - return tracing; - - debugfs = find_debugfs(); - if (!debugfs) - return NULL; - - tracing = malloc(strlen(debugfs) + 9); - if (!tracing) - return NULL; - - sprintf(tracing, "%s/tracing", debugfs); - - tracing_found = 1; - return tracing; -} - -static char *get_tracing_file(const char *name) -{ - const char *tracing; - char *file; - - tracing = find_tracing_dir(); - if (!tracing) - return NULL; - - file = malloc(strlen(tracing) + strlen(name) + 2); - if (!file) - return NULL; - - sprintf(file, "%s/%s", tracing, name); - return file; -} - -static void put_tracing_file(char *file) -{ - free(file); -} - int bigendian(void) { unsigned char str[] = { 0x1, 0x2, 0x3, 0x4, 0x0, 0x0, 0x0, 0x0}; diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c index 59d868add275..9a0658405760 100644 --- a/tools/perf/util/util.c +++ b/tools/perf/util/util.c @@ -269,3 +269,62 @@ void perf_debugfs_set_path(const char *mntpt) snprintf(debugfs_mountpoint, strlen(debugfs_mountpoint), "%s", mntpt); set_tracing_events_path(mntpt); } + +static const char *find_debugfs(void) +{ + const char *path = perf_debugfs_mount(NULL); + + if (!path) + fprintf(stderr, "Your kernel does not support the debugfs filesystem"); + + return path; +} + +/* + * Finds the path to the debugfs/tracing + * Allocates the string and stores it. + */ +const char *find_tracing_dir(void) +{ + static char *tracing; + static int tracing_found; + const char *debugfs; + + if (tracing_found) + return tracing; + + debugfs = find_debugfs(); + if (!debugfs) + return NULL; + + tracing = malloc(strlen(debugfs) + 9); + if (!tracing) + return NULL; + + sprintf(tracing, "%s/tracing", debugfs); + + tracing_found = 1; + return tracing; +} + +char *get_tracing_file(const char *name) +{ + const char *tracing; + char *file; + + tracing = find_tracing_dir(); + if (!tracing) + return NULL; + + file = malloc(strlen(tracing) + strlen(name) + 2); + if (!file) + return NULL; + + sprintf(file, "%s/%s", tracing, name); + return file; +} + +void put_tracing_file(char *file) +{ + free(file); +} diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index 2732fad03908..cc1574edcd9a 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h @@ -80,6 +80,9 @@ extern char buildid_dir[]; extern char tracing_events_path[]; extern void perf_debugfs_set_path(const char *mountpoint); const char *perf_debugfs_mount(const char *mountpoint); +const char *find_tracing_dir(void); +char *get_tracing_file(const char *name); +void put_tracing_file(char *file); /* On most systems would have given us this, but * not on some systems (e.g. GNU/Hurd). From e7c93f09b83be25281cf129674e0035664715033 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 26 Jun 2013 16:14:05 +0900 Subject: [PATCH 0019/3400] perf util: Use evsel->name to get tracepoint_paths Most tracepoint events already have their system and event name in ->name field so that searching whole event tracing directory for each evsel to match given id is suboptimal. Factor out this routine into tracepoint_name_to_path(). In case of en invalid name, it'll try to find path using id again. Signed-off-by: Namhyung Kim Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1372230862-15861-3-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/parse-events.c | 23 +++++++++++++++++++++++ tools/perf/util/parse-events.h | 1 + tools/perf/util/trace-event-info.c | 15 +++++++++++++++ 3 files changed, 39 insertions(+) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 995fc25db8c6..ef72e98a07a6 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -217,6 +217,29 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config) return NULL; } +struct tracepoint_path *tracepoint_name_to_path(const char *name) +{ + struct tracepoint_path *path = zalloc(sizeof(*path)); + char *str = strchr(name, ':'); + + if (path == NULL || str == NULL) { + free(path); + return NULL; + } + + path->system = strndup(name, str - name); + path->name = strdup(str+1); + + if (path->system == NULL || path->name == NULL) { + free(path->system); + free(path->name); + free(path); + path = NULL; + } + + return path; +} + const char *event_type(int type) { switch (type) { diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index 8a4859315fd9..080f7cf25d99 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -23,6 +23,7 @@ struct tracepoint_path { }; extern struct tracepoint_path *tracepoint_id_to_path(u64 config); +extern struct tracepoint_path *tracepoint_name_to_path(const char *name); extern bool have_tracepoints(struct list_head *evlist); const char *event_type(int type); diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c index 615c0628678b..a42624a6cb5c 100644 --- a/tools/perf/util/trace-event-info.c +++ b/tools/perf/util/trace-event-info.c @@ -414,12 +414,27 @@ get_tracepoints_path(struct list_head *pattrs) if (pos->attr.type != PERF_TYPE_TRACEPOINT) continue; ++nr_tracepoints; + + if (pos->name) { + ppath->next = tracepoint_name_to_path(pos->name); + if (ppath->next) + goto next; + + if (strchr(pos->name, ':') == NULL) + goto try_id; + + goto error; + } + +try_id: ppath->next = tracepoint_id_to_path(pos->attr.config); if (!ppath->next) { +error: pr_debug("No memory to alloc tracepoints list\n"); put_tracepoints_path(&path); return NULL; } +next: ppath = ppath->next; } From ad3d6f508738323c0e843c4dbdd421c1aeb59cd8 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 17 Jun 2013 18:02:43 +0200 Subject: [PATCH 0020/3400] perf tools: Do not elide parent symbol column I found the parent symbol column data interesting even if there's another sorting enabled. Switching it on. Previous behaviour: $ perf report -i perf.data.delete -p perf_session__delete -x + 3.60% perf perf [.] __rb_change_child + 1.89% perf perf [.] rb_erase + 1.89% perf perf [.] rb_erase + 1.83% perf perf [.] free@plt Current behaviour: $ perf report -i perf.data.delete -p perf_session__delete -x + 3.60% perf perf [.] __rb_change_child perf_session__delete + 1.89% perf perf [.] rb_erase perf_session__delete_dead_threads + 1.89% perf perf [.] rb_erase perf_session__delete_threads + 1.83% perf perf [.] free@plt perf_session__delete Signed-off-by: Jiri Olsa Cc: Andi Kleen Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-r79fn89bhqz16ixa5zmyflrd@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-report.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 3662047cc6b1..6ab49dafef25 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -931,14 +931,6 @@ repeat: if (parent_pattern != default_parent_pattern) { if (sort_dimension__add("parent") < 0) goto error; - - /* - * Only show the parent fields if we explicitly - * sort that way. If we only use parent machinery - * for filtering, we don't want it. - */ - if (!strstr(sort_order, "parent")) - sort_parent.elide = 1; } if (argc) { From d4ae0a6f7c79be64c8f3551dd149189f8c4480eb Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 25 Jun 2013 13:54:13 +0200 Subject: [PATCH 0021/3400] perf report: Fix perf_session__delete removal There's no point of having out_delete label with perf_session__delete call within __cmd_report function, because it's called at the end of the cmd_report function. The speed up due to commenting out the perf_session__delete at the end does not seem relevant anymore. Measured speedup for ~1GB data file with 222466 FORKS events is around 0.5%. $ perf report -i perf.data.delete -P perf_session__delete -s parent + 99.51% [other] + 0.49% perf_session__delete Signed-off-by: Jiri Olsa Cc: Andi Kleen Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1372161253-22081-6-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-report.c | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 6ab49dafef25..ee2ca3eb22df 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -497,7 +497,7 @@ static int __cmd_report(struct perf_report *rep) ret = perf_session__cpu_bitmap(session, rep->cpu_list, rep->cpu_bitmap); if (ret) - goto out_delete; + return ret; } if (use_browser <= 0) @@ -508,11 +508,11 @@ static int __cmd_report(struct perf_report *rep) ret = perf_report__setup_sample_type(rep); if (ret) - goto out_delete; + return ret; ret = perf_session__process_events(session, &rep->tool); if (ret) - goto out_delete; + return ret; kernel_map = session->machines.host.vmlinux_maps[MAP__FUNCTION]; kernel_kmap = map__kmap(kernel_map); @@ -547,7 +547,7 @@ static int __cmd_report(struct perf_report *rep) if (dump_trace) { perf_session__fprintf_nr_events(session, stdout); - goto out_delete; + return 0; } nr_samples = 0; @@ -572,7 +572,7 @@ static int __cmd_report(struct perf_report *rep) if (nr_samples == 0) { ui__error("The %s file has no samples!\n", session->filename); - goto out_delete; + return 0; } list_for_each_entry(pos, &session->evlist->entries, node) @@ -598,19 +598,6 @@ static int __cmd_report(struct perf_report *rep) } else perf_evlist__tty_browse_hists(session->evlist, rep, help); -out_delete: - /* - * Speed up the exit process, for large files this can - * take quite a while. - * - * XXX Enable this when using valgrind or if we ever - * librarize this command. - * - * Also experiment with obstacks to see how much speed - * up we'll get here. - * - * perf_session__delete(session); - */ return ret; } From cfe0d8ba14a1d98245b371e486c68f37eba1ca52 Mon Sep 17 00:00:00 2001 From: Runzhen Wang Date: Fri, 28 Jun 2013 16:14:57 +0800 Subject: [PATCH 0022/3400] perf tools: Make Power7 events available for perf Power7 supports over 530 different perf events but only a small subset of these can be specified by name, for the remaining events, we must specify them by their raw code: perf stat -e r2003c This patch makes all the POWER7 events available in sysfs. So we can instead specify these as: perf stat -e 'cpu/PM_CMPLU_STALL_DFU/' where PM_CMPLU_STALL_DFU is the r2003c in previous example. Before this patch is applied, the size of power7-pmu.o is: $ size arch/powerpc/perf/power7-pmu.o text data bss dec hex filename 3073 2720 0 5793 16a1 arch/powerpc/perf/power7-pmu.o and after the patch is applied, it is: $ size arch/powerpc/perf/power7-pmu.o text data bss dec hex filename 15950 31112 0 47062 b7d6 arch/powerpc/perf/power7-pmu.o For the run time overhead, I use two scripts, one is "event_name.sh", which contains 50 event names, it looks like: # ./perf record -e 'cpu/PM_CMPLU_STALL_DFU/' -e ..... /bin/sleep 1 the other one is named "event_code.sh" which use corresponding events raw code instead of events names, it looks like: # ./perf record -e r2003c -e ...... /bin/sleep 1 below is the result. Using events name: [root@localhost perf]# time ./event_name.sh [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.002 MB perf.data (~102 samples) ] real 0m1.192s user 0m0.028s sys 0m0.106s Using events raw code: [root@localhost perf]# time ./event_code.sh [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.003 MB perf.data (~112 samples) ] real 0m1.198s user 0m0.028s sys 0m0.105s Signed-off-by: Runzhen Wang Acked-by: Michael Ellerman Cc: icycoder@gmail.com Cc: linuxppc-dev@lists.ozlabs.org Cc: Michael Ellerman Cc: Paul Mackerras Cc: Runzhen Wang Cc: Sukadev Bhattiprolu Cc: Xiao Guangrong Link: http://lkml.kernel.org/r/1372407297-6996-3-git-send-email-runzhen@linux.vnet.ibm.com Signed-off-by: Arnaldo Carvalho de Melo --- arch/powerpc/include/asm/perf_event_server.h | 4 +- arch/powerpc/perf/power7-events-list.h | 548 +++++++++++++++++++ arch/powerpc/perf/power7-pmu.c | 140 +---- 3 files changed, 578 insertions(+), 114 deletions(-) create mode 100644 arch/powerpc/perf/power7-events-list.h diff --git a/arch/powerpc/include/asm/perf_event_server.h b/arch/powerpc/include/asm/perf_event_server.h index f265049dd7d6..d9270d8eb087 100644 --- a/arch/powerpc/include/asm/perf_event_server.h +++ b/arch/powerpc/include/asm/perf_event_server.h @@ -136,11 +136,11 @@ extern ssize_t power_events_sysfs_show(struct device *dev, #define EVENT_PTR(_id, _suffix) &EVENT_VAR(_id, _suffix).attr.attr #define EVENT_ATTR(_name, _id, _suffix) \ - PMU_EVENT_ATTR(_name, EVENT_VAR(_id, _suffix), PME_PM_##_id, \ + PMU_EVENT_ATTR(_name, EVENT_VAR(_id, _suffix), PME_##_id, \ power_events_sysfs_show) #define GENERIC_EVENT_ATTR(_name, _id) EVENT_ATTR(_name, _id, _g) #define GENERIC_EVENT_PTR(_id) EVENT_PTR(_id, _g) -#define POWER_EVENT_ATTR(_name, _id) EVENT_ATTR(PM_##_name, _id, _p) +#define POWER_EVENT_ATTR(_name, _id) EVENT_ATTR(_name, _id, _p) #define POWER_EVENT_PTR(_id) EVENT_PTR(_id, _p) diff --git a/arch/powerpc/perf/power7-events-list.h b/arch/powerpc/perf/power7-events-list.h new file mode 100644 index 000000000000..687790a2c0b8 --- /dev/null +++ b/arch/powerpc/perf/power7-events-list.h @@ -0,0 +1,548 @@ +/* + * Performance counter support for POWER7 processors. + * + * Copyright 2013 Runzhen Wang, IBM 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; either version + * 2 of the License, or (at your option) any later version. + */ + +EVENT(PM_IC_DEMAND_L2_BR_ALL, 0x04898) +EVENT(PM_GCT_UTIL_7_TO_10_SLOTS, 0x020a0) +EVENT(PM_PMC2_SAVED, 0x10022) +EVENT(PM_CMPLU_STALL_DFU, 0x2003c) +EVENT(PM_VSU0_16FLOP, 0x0a0a4) +EVENT(PM_MRK_LSU_DERAT_MISS, 0x3d05a) +EVENT(PM_MRK_ST_CMPL, 0x10034) +EVENT(PM_NEST_PAIR3_ADD, 0x40881) +EVENT(PM_L2_ST_DISP, 0x46180) +EVENT(PM_L2_CASTOUT_MOD, 0x16180) +EVENT(PM_ISEG, 0x020a4) +EVENT(PM_MRK_INST_TIMEO, 0x40034) +EVENT(PM_L2_RCST_DISP_FAIL_ADDR, 0x36282) +EVENT(PM_LSU1_DC_PREF_STREAM_CONFIRM, 0x0d0b6) +EVENT(PM_IERAT_WR_64K, 0x040be) +EVENT(PM_MRK_DTLB_MISS_16M, 0x4d05e) +EVENT(PM_IERAT_MISS, 0x100f6) +EVENT(PM_MRK_PTEG_FROM_LMEM, 0x4d052) +EVENT(PM_FLOP, 0x100f4) +EVENT(PM_THRD_PRIO_4_5_CYC, 0x040b4) +EVENT(PM_BR_PRED_TA, 0x040aa) +EVENT(PM_CMPLU_STALL_FXU, 0x20014) +EVENT(PM_EXT_INT, 0x200f8) +EVENT(PM_VSU_FSQRT_FDIV, 0x0a888) +EVENT(PM_MRK_LD_MISS_EXPOSED_CYC, 0x1003e) +EVENT(PM_LSU1_LDF, 0x0c086) +EVENT(PM_IC_WRITE_ALL, 0x0488c) +EVENT(PM_LSU0_SRQ_STFWD, 0x0c0a0) +EVENT(PM_PTEG_FROM_RL2L3_MOD, 0x1c052) +EVENT(PM_MRK_DATA_FROM_L31_SHR, 0x1d04e) +EVENT(PM_DATA_FROM_L21_MOD, 0x3c046) +EVENT(PM_VSU1_SCAL_DOUBLE_ISSUED, 0x0b08a) +EVENT(PM_VSU0_8FLOP, 0x0a0a0) +EVENT(PM_POWER_EVENT1, 0x1006e) +EVENT(PM_DISP_CLB_HELD_BAL, 0x02092) +EVENT(PM_VSU1_2FLOP, 0x0a09a) +EVENT(PM_LWSYNC_HELD, 0x0209a) +EVENT(PM_PTEG_FROM_DL2L3_SHR, 0x3c054) +EVENT(PM_INST_FROM_L21_MOD, 0x34046) +EVENT(PM_IERAT_XLATE_WR_16MPLUS, 0x040bc) +EVENT(PM_IC_REQ_ALL, 0x04888) +EVENT(PM_DSLB_MISS, 0x0d090) +EVENT(PM_L3_MISS, 0x1f082) +EVENT(PM_LSU0_L1_PREF, 0x0d0b8) +EVENT(PM_VSU_SCALAR_SINGLE_ISSUED, 0x0b884) +EVENT(PM_LSU1_DC_PREF_STREAM_CONFIRM_STRIDE, 0x0d0be) +EVENT(PM_L2_INST, 0x36080) +EVENT(PM_VSU0_FRSP, 0x0a0b4) +EVENT(PM_FLUSH_DISP, 0x02082) +EVENT(PM_PTEG_FROM_L2MISS, 0x4c058) +EVENT(PM_VSU1_DQ_ISSUED, 0x0b09a) +EVENT(PM_CMPLU_STALL_LSU, 0x20012) +EVENT(PM_MRK_DATA_FROM_DMEM, 0x1d04a) +EVENT(PM_LSU_FLUSH_ULD, 0x0c8b0) +EVENT(PM_PTEG_FROM_LMEM, 0x4c052) +EVENT(PM_MRK_DERAT_MISS_16M, 0x3d05c) +EVENT(PM_THRD_ALL_RUN_CYC, 0x2000c) +EVENT(PM_MEM0_PREFETCH_DISP, 0x20083) +EVENT(PM_MRK_STALL_CMPLU_CYC_COUNT, 0x3003f) +EVENT(PM_DATA_FROM_DL2L3_MOD, 0x3c04c) +EVENT(PM_VSU_FRSP, 0x0a8b4) +EVENT(PM_MRK_DATA_FROM_L21_MOD, 0x3d046) +EVENT(PM_PMC1_OVERFLOW, 0x20010) +EVENT(PM_VSU0_SINGLE, 0x0a0a8) +EVENT(PM_MRK_PTEG_FROM_L3MISS, 0x2d058) +EVENT(PM_MRK_PTEG_FROM_L31_SHR, 0x2d056) +EVENT(PM_VSU0_VECTOR_SP_ISSUED, 0x0b090) +EVENT(PM_VSU1_FEST, 0x0a0ba) +EVENT(PM_MRK_INST_DISP, 0x20030) +EVENT(PM_VSU0_COMPLEX_ISSUED, 0x0b096) +EVENT(PM_LSU1_FLUSH_UST, 0x0c0b6) +EVENT(PM_INST_CMPL, 0x00002) +EVENT(PM_FXU_IDLE, 0x1000e) +EVENT(PM_LSU0_FLUSH_ULD, 0x0c0b0) +EVENT(PM_MRK_DATA_FROM_DL2L3_MOD, 0x3d04c) +EVENT(PM_LSU_LMQ_SRQ_EMPTY_ALL_CYC, 0x3001c) +EVENT(PM_LSU1_REJECT_LMQ_FULL, 0x0c0a6) +EVENT(PM_INST_PTEG_FROM_L21_MOD, 0x3e056) +EVENT(PM_INST_FROM_RL2L3_MOD, 0x14042) +EVENT(PM_SHL_CREATED, 0x05082) +EVENT(PM_L2_ST_HIT, 0x46182) +EVENT(PM_DATA_FROM_DMEM, 0x1c04a) +EVENT(PM_L3_LD_MISS, 0x2f082) +EVENT(PM_FXU1_BUSY_FXU0_IDLE, 0x4000e) +EVENT(PM_DISP_CLB_HELD_RES, 0x02094) +EVENT(PM_L2_SN_SX_I_DONE, 0x36382) +EVENT(PM_GRP_CMPL, 0x30004) +EVENT(PM_STCX_CMPL, 0x0c098) +EVENT(PM_VSU0_2FLOP, 0x0a098) +EVENT(PM_L3_PREF_MISS, 0x3f082) +EVENT(PM_LSU_SRQ_SYNC_CYC, 0x0d096) +EVENT(PM_LSU_REJECT_ERAT_MISS, 0x20064) +EVENT(PM_L1_ICACHE_MISS, 0x200fc) +EVENT(PM_LSU1_FLUSH_SRQ, 0x0c0be) +EVENT(PM_LD_REF_L1_LSU0, 0x0c080) +EVENT(PM_VSU0_FEST, 0x0a0b8) +EVENT(PM_VSU_VECTOR_SINGLE_ISSUED, 0x0b890) +EVENT(PM_FREQ_UP, 0x4000c) +EVENT(PM_DATA_FROM_LMEM, 0x3c04a) +EVENT(PM_LSU1_LDX, 0x0c08a) +EVENT(PM_PMC3_OVERFLOW, 0x40010) +EVENT(PM_MRK_BR_MPRED, 0x30036) +EVENT(PM_SHL_MATCH, 0x05086) +EVENT(PM_MRK_BR_TAKEN, 0x10036) +EVENT(PM_CMPLU_STALL_BRU, 0x4004e) +EVENT(PM_ISLB_MISS, 0x0d092) +EVENT(PM_CYC, 0x0001e) +EVENT(PM_DISP_HELD_THERMAL, 0x30006) +EVENT(PM_INST_PTEG_FROM_RL2L3_SHR, 0x2e054) +EVENT(PM_LSU1_SRQ_STFWD, 0x0c0a2) +EVENT(PM_GCT_NOSLOT_BR_MPRED, 0x4001a) +EVENT(PM_1PLUS_PPC_CMPL, 0x100f2) +EVENT(PM_PTEG_FROM_DMEM, 0x2c052) +EVENT(PM_VSU_2FLOP, 0x0a898) +EVENT(PM_GCT_FULL_CYC, 0x04086) +EVENT(PM_MRK_DATA_FROM_L3_CYC, 0x40020) +EVENT(PM_LSU_SRQ_S0_ALLOC, 0x0d09d) +EVENT(PM_MRK_DERAT_MISS_4K, 0x1d05c) +EVENT(PM_BR_MPRED_TA, 0x040ae) +EVENT(PM_INST_PTEG_FROM_L2MISS, 0x4e058) +EVENT(PM_DPU_HELD_POWER, 0x20006) +EVENT(PM_RUN_INST_CMPL, 0x400fa) +EVENT(PM_MRK_VSU_FIN, 0x30032) +EVENT(PM_LSU_SRQ_S0_VALID, 0x0d09c) +EVENT(PM_GCT_EMPTY_CYC, 0x20008) +EVENT(PM_IOPS_DISP, 0x30014) +EVENT(PM_RUN_SPURR, 0x10008) +EVENT(PM_PTEG_FROM_L21_MOD, 0x3c056) +EVENT(PM_VSU0_1FLOP, 0x0a080) +EVENT(PM_SNOOP_TLBIE, 0x0d0b2) +EVENT(PM_DATA_FROM_L3MISS, 0x2c048) +EVENT(PM_VSU_SINGLE, 0x0a8a8) +EVENT(PM_DTLB_MISS_16G, 0x1c05e) +EVENT(PM_CMPLU_STALL_VECTOR, 0x2001c) +EVENT(PM_FLUSH, 0x400f8) +EVENT(PM_L2_LD_HIT, 0x36182) +EVENT(PM_NEST_PAIR2_AND, 0x30883) +EVENT(PM_VSU1_1FLOP, 0x0a082) +EVENT(PM_IC_PREF_REQ, 0x0408a) +EVENT(PM_L3_LD_HIT, 0x2f080) +EVENT(PM_GCT_NOSLOT_IC_MISS, 0x2001a) +EVENT(PM_DISP_HELD, 0x10006) +EVENT(PM_L2_LD, 0x16080) +EVENT(PM_LSU_FLUSH_SRQ, 0x0c8bc) +EVENT(PM_BC_PLUS_8_CONV, 0x040b8) +EVENT(PM_MRK_DATA_FROM_L31_MOD_CYC, 0x40026) +EVENT(PM_CMPLU_STALL_VECTOR_LONG, 0x4004a) +EVENT(PM_L2_RCST_BUSY_RC_FULL, 0x26282) +EVENT(PM_TB_BIT_TRANS, 0x300f8) +EVENT(PM_THERMAL_MAX, 0x40006) +EVENT(PM_LSU1_FLUSH_ULD, 0x0c0b2) +EVENT(PM_LSU1_REJECT_LHS, 0x0c0ae) +EVENT(PM_LSU_LRQ_S0_ALLOC, 0x0d09f) +EVENT(PM_L3_CO_L31, 0x4f080) +EVENT(PM_POWER_EVENT4, 0x4006e) +EVENT(PM_DATA_FROM_L31_SHR, 0x1c04e) +EVENT(PM_BR_UNCOND, 0x0409e) +EVENT(PM_LSU1_DC_PREF_STREAM_ALLOC, 0x0d0aa) +EVENT(PM_PMC4_REWIND, 0x10020) +EVENT(PM_L2_RCLD_DISP, 0x16280) +EVENT(PM_THRD_PRIO_2_3_CYC, 0x040b2) +EVENT(PM_MRK_PTEG_FROM_L2MISS, 0x4d058) +EVENT(PM_IC_DEMAND_L2_BHT_REDIRECT, 0x04098) +EVENT(PM_LSU_DERAT_MISS, 0x200f6) +EVENT(PM_IC_PREF_CANCEL_L2, 0x04094) +EVENT(PM_MRK_FIN_STALL_CYC_COUNT, 0x1003d) +EVENT(PM_BR_PRED_CCACHE, 0x040a0) +EVENT(PM_GCT_UTIL_1_TO_2_SLOTS, 0x0209c) +EVENT(PM_MRK_ST_CMPL_INT, 0x30034) +EVENT(PM_LSU_TWO_TABLEWALK_CYC, 0x0d0a6) +EVENT(PM_MRK_DATA_FROM_L3MISS, 0x2d048) +EVENT(PM_GCT_NOSLOT_CYC, 0x100f8) +EVENT(PM_LSU_SET_MPRED, 0x0c0a8) +EVENT(PM_FLUSH_DISP_TLBIE, 0x0208a) +EVENT(PM_VSU1_FCONV, 0x0a0b2) +EVENT(PM_DERAT_MISS_16G, 0x4c05c) +EVENT(PM_INST_FROM_LMEM, 0x3404a) +EVENT(PM_IC_DEMAND_L2_BR_REDIRECT, 0x0409a) +EVENT(PM_CMPLU_STALL_SCALAR_LONG, 0x20018) +EVENT(PM_INST_PTEG_FROM_L2, 0x1e050) +EVENT(PM_PTEG_FROM_L2, 0x1c050) +EVENT(PM_MRK_DATA_FROM_L21_SHR_CYC, 0x20024) +EVENT(PM_MRK_DTLB_MISS_4K, 0x2d05a) +EVENT(PM_VSU0_FPSCR, 0x0b09c) +EVENT(PM_VSU1_VECT_DOUBLE_ISSUED, 0x0b082) +EVENT(PM_MRK_PTEG_FROM_RL2L3_MOD, 0x1d052) +EVENT(PM_MEM0_RQ_DISP, 0x10083) +EVENT(PM_L2_LD_MISS, 0x26080) +EVENT(PM_VMX_RESULT_SAT_1, 0x0b0a0) +EVENT(PM_L1_PREF, 0x0d8b8) +EVENT(PM_MRK_DATA_FROM_LMEM_CYC, 0x2002c) +EVENT(PM_GRP_IC_MISS_NONSPEC, 0x1000c) +EVENT(PM_PB_NODE_PUMP, 0x10081) +EVENT(PM_SHL_MERGED, 0x05084) +EVENT(PM_NEST_PAIR1_ADD, 0x20881) +EVENT(PM_DATA_FROM_L3, 0x1c048) +EVENT(PM_LSU_FLUSH, 0x0208e) +EVENT(PM_LSU_SRQ_SYNC_COUNT, 0x0d097) +EVENT(PM_PMC2_OVERFLOW, 0x30010) +EVENT(PM_LSU_LDF, 0x0c884) +EVENT(PM_POWER_EVENT3, 0x3006e) +EVENT(PM_DISP_WT, 0x30008) +EVENT(PM_CMPLU_STALL_REJECT, 0x40016) +EVENT(PM_IC_BANK_CONFLICT, 0x04082) +EVENT(PM_BR_MPRED_CR_TA, 0x048ae) +EVENT(PM_L2_INST_MISS, 0x36082) +EVENT(PM_CMPLU_STALL_ERAT_MISS, 0x40018) +EVENT(PM_NEST_PAIR2_ADD, 0x30881) +EVENT(PM_MRK_LSU_FLUSH, 0x0d08c) +EVENT(PM_L2_LDST, 0x16880) +EVENT(PM_INST_FROM_L31_SHR, 0x1404e) +EVENT(PM_VSU0_FIN, 0x0a0bc) +EVENT(PM_LARX_LSU, 0x0c894) +EVENT(PM_INST_FROM_RMEM, 0x34042) +EVENT(PM_DISP_CLB_HELD_TLBIE, 0x02096) +EVENT(PM_MRK_DATA_FROM_DMEM_CYC, 0x2002e) +EVENT(PM_BR_PRED_CR, 0x040a8) +EVENT(PM_LSU_REJECT, 0x10064) +EVENT(PM_GCT_UTIL_3_TO_6_SLOTS, 0x0209e) +EVENT(PM_CMPLU_STALL_END_GCT_NOSLOT, 0x10028) +EVENT(PM_LSU0_REJECT_LMQ_FULL, 0x0c0a4) +EVENT(PM_VSU_FEST, 0x0a8b8) +EVENT(PM_NEST_PAIR0_AND, 0x10883) +EVENT(PM_PTEG_FROM_L3, 0x2c050) +EVENT(PM_POWER_EVENT2, 0x2006e) +EVENT(PM_IC_PREF_CANCEL_PAGE, 0x04090) +EVENT(PM_VSU0_FSQRT_FDIV, 0x0a088) +EVENT(PM_MRK_GRP_CMPL, 0x40030) +EVENT(PM_VSU0_SCAL_DOUBLE_ISSUED, 0x0b088) +EVENT(PM_GRP_DISP, 0x3000a) +EVENT(PM_LSU0_LDX, 0x0c088) +EVENT(PM_DATA_FROM_L2, 0x1c040) +EVENT(PM_MRK_DATA_FROM_RL2L3_MOD, 0x1d042) +EVENT(PM_LD_REF_L1, 0x0c880) +EVENT(PM_VSU0_VECT_DOUBLE_ISSUED, 0x0b080) +EVENT(PM_VSU1_2FLOP_DOUBLE, 0x0a08e) +EVENT(PM_THRD_PRIO_6_7_CYC, 0x040b6) +EVENT(PM_BC_PLUS_8_RSLV_TAKEN, 0x040ba) +EVENT(PM_BR_MPRED_CR, 0x040ac) +EVENT(PM_L3_CO_MEM, 0x4f082) +EVENT(PM_LD_MISS_L1, 0x400f0) +EVENT(PM_DATA_FROM_RL2L3_MOD, 0x1c042) +EVENT(PM_LSU_SRQ_FULL_CYC, 0x1001a) +EVENT(PM_TABLEWALK_CYC, 0x10026) +EVENT(PM_MRK_PTEG_FROM_RMEM, 0x3d052) +EVENT(PM_LSU_SRQ_STFWD, 0x0c8a0) +EVENT(PM_INST_PTEG_FROM_RMEM, 0x3e052) +EVENT(PM_FXU0_FIN, 0x10004) +EVENT(PM_LSU1_L1_SW_PREF, 0x0c09e) +EVENT(PM_PTEG_FROM_L31_MOD, 0x1c054) +EVENT(PM_PMC5_OVERFLOW, 0x10024) +EVENT(PM_LD_REF_L1_LSU1, 0x0c082) +EVENT(PM_INST_PTEG_FROM_L21_SHR, 0x4e056) +EVENT(PM_CMPLU_STALL_THRD, 0x1001c) +EVENT(PM_DATA_FROM_RMEM, 0x3c042) +EVENT(PM_VSU0_SCAL_SINGLE_ISSUED, 0x0b084) +EVENT(PM_BR_MPRED_LSTACK, 0x040a6) +EVENT(PM_MRK_DATA_FROM_RL2L3_MOD_CYC, 0x40028) +EVENT(PM_LSU0_FLUSH_UST, 0x0c0b4) +EVENT(PM_LSU_NCST, 0x0c090) +EVENT(PM_BR_TAKEN, 0x20004) +EVENT(PM_INST_PTEG_FROM_LMEM, 0x4e052) +EVENT(PM_GCT_NOSLOT_BR_MPRED_IC_MISS, 0x4001c) +EVENT(PM_DTLB_MISS_4K, 0x2c05a) +EVENT(PM_PMC4_SAVED, 0x30022) +EVENT(PM_VSU1_PERMUTE_ISSUED, 0x0b092) +EVENT(PM_SLB_MISS, 0x0d890) +EVENT(PM_LSU1_FLUSH_LRQ, 0x0c0ba) +EVENT(PM_DTLB_MISS, 0x300fc) +EVENT(PM_VSU1_FRSP, 0x0a0b6) +EVENT(PM_VSU_VECTOR_DOUBLE_ISSUED, 0x0b880) +EVENT(PM_L2_CASTOUT_SHR, 0x16182) +EVENT(PM_DATA_FROM_DL2L3_SHR, 0x3c044) +EVENT(PM_VSU1_STF, 0x0b08e) +EVENT(PM_ST_FIN, 0x200f0) +EVENT(PM_PTEG_FROM_L21_SHR, 0x4c056) +EVENT(PM_L2_LOC_GUESS_WRONG, 0x26480) +EVENT(PM_MRK_STCX_FAIL, 0x0d08e) +EVENT(PM_LSU0_REJECT_LHS, 0x0c0ac) +EVENT(PM_IC_PREF_CANCEL_HIT, 0x04092) +EVENT(PM_L3_PREF_BUSY, 0x4f080) +EVENT(PM_MRK_BRU_FIN, 0x2003a) +EVENT(PM_LSU1_NCLD, 0x0c08e) +EVENT(PM_INST_PTEG_FROM_L31_MOD, 0x1e054) +EVENT(PM_LSU_NCLD, 0x0c88c) +EVENT(PM_LSU_LDX, 0x0c888) +EVENT(PM_L2_LOC_GUESS_CORRECT, 0x16480) +EVENT(PM_THRESH_TIMEO, 0x10038) +EVENT(PM_L3_PREF_ST, 0x0d0ae) +EVENT(PM_DISP_CLB_HELD_SYNC, 0x02098) +EVENT(PM_VSU_SIMPLE_ISSUED, 0x0b894) +EVENT(PM_VSU1_SINGLE, 0x0a0aa) +EVENT(PM_DATA_TABLEWALK_CYC, 0x3001a) +EVENT(PM_L2_RC_ST_DONE, 0x36380) +EVENT(PM_MRK_PTEG_FROM_L21_MOD, 0x3d056) +EVENT(PM_LARX_LSU1, 0x0c096) +EVENT(PM_MRK_DATA_FROM_RMEM, 0x3d042) +EVENT(PM_DISP_CLB_HELD, 0x02090) +EVENT(PM_DERAT_MISS_4K, 0x1c05c) +EVENT(PM_L2_RCLD_DISP_FAIL_ADDR, 0x16282) +EVENT(PM_SEG_EXCEPTION, 0x028a4) +EVENT(PM_FLUSH_DISP_SB, 0x0208c) +EVENT(PM_L2_DC_INV, 0x26182) +EVENT(PM_PTEG_FROM_DL2L3_MOD, 0x4c054) +EVENT(PM_DSEG, 0x020a6) +EVENT(PM_BR_PRED_LSTACK, 0x040a2) +EVENT(PM_VSU0_STF, 0x0b08c) +EVENT(PM_LSU_FX_FIN, 0x10066) +EVENT(PM_DERAT_MISS_16M, 0x3c05c) +EVENT(PM_MRK_PTEG_FROM_DL2L3_MOD, 0x4d054) +EVENT(PM_GCT_UTIL_11_PLUS_SLOTS, 0x020a2) +EVENT(PM_INST_FROM_L3, 0x14048) +EVENT(PM_MRK_IFU_FIN, 0x3003a) +EVENT(PM_ITLB_MISS, 0x400fc) +EVENT(PM_VSU_STF, 0x0b88c) +EVENT(PM_LSU_FLUSH_UST, 0x0c8b4) +EVENT(PM_L2_LDST_MISS, 0x26880) +EVENT(PM_FXU1_FIN, 0x40004) +EVENT(PM_SHL_DEALLOCATED, 0x05080) +EVENT(PM_L2_SN_M_WR_DONE, 0x46382) +EVENT(PM_LSU_REJECT_SET_MPRED, 0x0c8a8) +EVENT(PM_L3_PREF_LD, 0x0d0ac) +EVENT(PM_L2_SN_M_RD_DONE, 0x46380) +EVENT(PM_MRK_DERAT_MISS_16G, 0x4d05c) +EVENT(PM_VSU_FCONV, 0x0a8b0) +EVENT(PM_ANY_THRD_RUN_CYC, 0x100fa) +EVENT(PM_LSU_LMQ_FULL_CYC, 0x0d0a4) +EVENT(PM_MRK_LSU_REJECT_LHS, 0x0d082) +EVENT(PM_MRK_LD_MISS_L1_CYC, 0x4003e) +EVENT(PM_MRK_DATA_FROM_L2_CYC, 0x20020) +EVENT(PM_INST_IMC_MATCH_DISP, 0x30016) +EVENT(PM_MRK_DATA_FROM_RMEM_CYC, 0x4002c) +EVENT(PM_VSU0_SIMPLE_ISSUED, 0x0b094) +EVENT(PM_CMPLU_STALL_DIV, 0x40014) +EVENT(PM_MRK_PTEG_FROM_RL2L3_SHR, 0x2d054) +EVENT(PM_VSU_FMA_DOUBLE, 0x0a890) +EVENT(PM_VSU_4FLOP, 0x0a89c) +EVENT(PM_VSU1_FIN, 0x0a0be) +EVENT(PM_NEST_PAIR1_AND, 0x20883) +EVENT(PM_INST_PTEG_FROM_RL2L3_MOD, 0x1e052) +EVENT(PM_RUN_CYC, 0x200f4) +EVENT(PM_PTEG_FROM_RMEM, 0x3c052) +EVENT(PM_LSU_LRQ_S0_VALID, 0x0d09e) +EVENT(PM_LSU0_LDF, 0x0c084) +EVENT(PM_FLUSH_COMPLETION, 0x30012) +EVENT(PM_ST_MISS_L1, 0x300f0) +EVENT(PM_L2_NODE_PUMP, 0x36480) +EVENT(PM_INST_FROM_DL2L3_SHR, 0x34044) +EVENT(PM_MRK_STALL_CMPLU_CYC, 0x3003e) +EVENT(PM_VSU1_DENORM, 0x0a0ae) +EVENT(PM_MRK_DATA_FROM_L31_SHR_CYC, 0x20026) +EVENT(PM_NEST_PAIR0_ADD, 0x10881) +EVENT(PM_INST_FROM_L3MISS, 0x24048) +EVENT(PM_EE_OFF_EXT_INT, 0x02080) +EVENT(PM_INST_PTEG_FROM_DMEM, 0x2e052) +EVENT(PM_INST_FROM_DL2L3_MOD, 0x3404c) +EVENT(PM_PMC6_OVERFLOW, 0x30024) +EVENT(PM_VSU_2FLOP_DOUBLE, 0x0a88c) +EVENT(PM_TLB_MISS, 0x20066) +EVENT(PM_FXU_BUSY, 0x2000e) +EVENT(PM_L2_RCLD_DISP_FAIL_OTHER, 0x26280) +EVENT(PM_LSU_REJECT_LMQ_FULL, 0x0c8a4) +EVENT(PM_IC_RELOAD_SHR, 0x04096) +EVENT(PM_GRP_MRK, 0x10031) +EVENT(PM_MRK_ST_NEST, 0x20034) +EVENT(PM_VSU1_FSQRT_FDIV, 0x0a08a) +EVENT(PM_LSU0_FLUSH_LRQ, 0x0c0b8) +EVENT(PM_LARX_LSU0, 0x0c094) +EVENT(PM_IBUF_FULL_CYC, 0x04084) +EVENT(PM_MRK_DATA_FROM_DL2L3_SHR_CYC, 0x2002a) +EVENT(PM_LSU_DC_PREF_STREAM_ALLOC, 0x0d8a8) +EVENT(PM_GRP_MRK_CYC, 0x10030) +EVENT(PM_MRK_DATA_FROM_RL2L3_SHR_CYC, 0x20028) +EVENT(PM_L2_GLOB_GUESS_CORRECT, 0x16482) +EVENT(PM_LSU_REJECT_LHS, 0x0c8ac) +EVENT(PM_MRK_DATA_FROM_LMEM, 0x3d04a) +EVENT(PM_INST_PTEG_FROM_L3, 0x2e050) +EVENT(PM_FREQ_DOWN, 0x3000c) +EVENT(PM_PB_RETRY_NODE_PUMP, 0x30081) +EVENT(PM_INST_FROM_RL2L3_SHR, 0x1404c) +EVENT(PM_MRK_INST_ISSUED, 0x10032) +EVENT(PM_PTEG_FROM_L3MISS, 0x2c058) +EVENT(PM_RUN_PURR, 0x400f4) +EVENT(PM_MRK_GRP_IC_MISS, 0x40038) +EVENT(PM_MRK_DATA_FROM_L3, 0x1d048) +EVENT(PM_CMPLU_STALL_DCACHE_MISS, 0x20016) +EVENT(PM_PTEG_FROM_RL2L3_SHR, 0x2c054) +EVENT(PM_LSU_FLUSH_LRQ, 0x0c8b8) +EVENT(PM_MRK_DERAT_MISS_64K, 0x2d05c) +EVENT(PM_INST_PTEG_FROM_DL2L3_MOD, 0x4e054) +EVENT(PM_L2_ST_MISS, 0x26082) +EVENT(PM_MRK_PTEG_FROM_L21_SHR, 0x4d056) +EVENT(PM_LWSYNC, 0x0d094) +EVENT(PM_LSU0_DC_PREF_STREAM_CONFIRM_STRIDE, 0x0d0bc) +EVENT(PM_MRK_LSU_FLUSH_LRQ, 0x0d088) +EVENT(PM_INST_IMC_MATCH_CMPL, 0x100f0) +EVENT(PM_NEST_PAIR3_AND, 0x40883) +EVENT(PM_PB_RETRY_SYS_PUMP, 0x40081) +EVENT(PM_MRK_INST_FIN, 0x30030) +EVENT(PM_MRK_PTEG_FROM_DL2L3_SHR, 0x3d054) +EVENT(PM_INST_FROM_L31_MOD, 0x14044) +EVENT(PM_MRK_DTLB_MISS_64K, 0x3d05e) +EVENT(PM_LSU_FIN, 0x30066) +EVENT(PM_MRK_LSU_REJECT, 0x40064) +EVENT(PM_L2_CO_FAIL_BUSY, 0x16382) +EVENT(PM_MEM0_WQ_DISP, 0x40083) +EVENT(PM_DATA_FROM_L31_MOD, 0x1c044) +EVENT(PM_THERMAL_WARN, 0x10016) +EVENT(PM_VSU0_4FLOP, 0x0a09c) +EVENT(PM_BR_MPRED_CCACHE, 0x040a4) +EVENT(PM_CMPLU_STALL_IFU, 0x4004c) +EVENT(PM_L1_DEMAND_WRITE, 0x0408c) +EVENT(PM_FLUSH_BR_MPRED, 0x02084) +EVENT(PM_MRK_DTLB_MISS_16G, 0x1d05e) +EVENT(PM_MRK_PTEG_FROM_DMEM, 0x2d052) +EVENT(PM_L2_RCST_DISP, 0x36280) +EVENT(PM_CMPLU_STALL, 0x4000a) +EVENT(PM_LSU_PARTIAL_CDF, 0x0c0aa) +EVENT(PM_DISP_CLB_HELD_SB, 0x020a8) +EVENT(PM_VSU0_FMA_DOUBLE, 0x0a090) +EVENT(PM_FXU0_BUSY_FXU1_IDLE, 0x3000e) +EVENT(PM_IC_DEMAND_CYC, 0x10018) +EVENT(PM_MRK_DATA_FROM_L21_SHR, 0x3d04e) +EVENT(PM_MRK_LSU_FLUSH_UST, 0x0d086) +EVENT(PM_INST_PTEG_FROM_L3MISS, 0x2e058) +EVENT(PM_VSU_DENORM, 0x0a8ac) +EVENT(PM_MRK_LSU_PARTIAL_CDF, 0x0d080) +EVENT(PM_INST_FROM_L21_SHR, 0x3404e) +EVENT(PM_IC_PREF_WRITE, 0x0408e) +EVENT(PM_BR_PRED, 0x0409c) +EVENT(PM_INST_FROM_DMEM, 0x1404a) +EVENT(PM_IC_PREF_CANCEL_ALL, 0x04890) +EVENT(PM_LSU_DC_PREF_STREAM_CONFIRM, 0x0d8b4) +EVENT(PM_MRK_LSU_FLUSH_SRQ, 0x0d08a) +EVENT(PM_MRK_FIN_STALL_CYC, 0x1003c) +EVENT(PM_L2_RCST_DISP_FAIL_OTHER, 0x46280) +EVENT(PM_VSU1_DD_ISSUED, 0x0b098) +EVENT(PM_PTEG_FROM_L31_SHR, 0x2c056) +EVENT(PM_DATA_FROM_L21_SHR, 0x3c04e) +EVENT(PM_LSU0_NCLD, 0x0c08c) +EVENT(PM_VSU1_4FLOP, 0x0a09e) +EVENT(PM_VSU1_8FLOP, 0x0a0a2) +EVENT(PM_VSU_8FLOP, 0x0a8a0) +EVENT(PM_LSU_LMQ_SRQ_EMPTY_CYC, 0x2003e) +EVENT(PM_DTLB_MISS_64K, 0x3c05e) +EVENT(PM_THRD_CONC_RUN_INST, 0x300f4) +EVENT(PM_MRK_PTEG_FROM_L2, 0x1d050) +EVENT(PM_PB_SYS_PUMP, 0x20081) +EVENT(PM_VSU_FIN, 0x0a8bc) +EVENT(PM_MRK_DATA_FROM_L31_MOD, 0x1d044) +EVENT(PM_THRD_PRIO_0_1_CYC, 0x040b0) +EVENT(PM_DERAT_MISS_64K, 0x2c05c) +EVENT(PM_PMC2_REWIND, 0x30020) +EVENT(PM_INST_FROM_L2, 0x14040) +EVENT(PM_GRP_BR_MPRED_NONSPEC, 0x1000a) +EVENT(PM_INST_DISP, 0x200f2) +EVENT(PM_MEM0_RD_CANCEL_TOTAL, 0x30083) +EVENT(PM_LSU0_DC_PREF_STREAM_CONFIRM, 0x0d0b4) +EVENT(PM_L1_DCACHE_RELOAD_VALID, 0x300f6) +EVENT(PM_VSU_SCALAR_DOUBLE_ISSUED, 0x0b888) +EVENT(PM_L3_PREF_HIT, 0x3f080) +EVENT(PM_MRK_PTEG_FROM_L31_MOD, 0x1d054) +EVENT(PM_CMPLU_STALL_STORE, 0x2004a) +EVENT(PM_MRK_FXU_FIN, 0x20038) +EVENT(PM_PMC4_OVERFLOW, 0x10010) +EVENT(PM_MRK_PTEG_FROM_L3, 0x2d050) +EVENT(PM_LSU0_LMQ_LHR_MERGE, 0x0d098) +EVENT(PM_BTAC_HIT, 0x0508a) +EVENT(PM_L3_RD_BUSY, 0x4f082) +EVENT(PM_LSU0_L1_SW_PREF, 0x0c09c) +EVENT(PM_INST_FROM_L2MISS, 0x44048) +EVENT(PM_LSU0_DC_PREF_STREAM_ALLOC, 0x0d0a8) +EVENT(PM_L2_ST, 0x16082) +EVENT(PM_VSU0_DENORM, 0x0a0ac) +EVENT(PM_MRK_DATA_FROM_DL2L3_SHR, 0x3d044) +EVENT(PM_BR_PRED_CR_TA, 0x048aa) +EVENT(PM_VSU0_FCONV, 0x0a0b0) +EVENT(PM_MRK_LSU_FLUSH_ULD, 0x0d084) +EVENT(PM_BTAC_MISS, 0x05088) +EVENT(PM_MRK_LD_MISS_EXPOSED_CYC_COUNT, 0x1003f) +EVENT(PM_MRK_DATA_FROM_L2, 0x1d040) +EVENT(PM_LSU_DCACHE_RELOAD_VALID, 0x0d0a2) +EVENT(PM_VSU_FMA, 0x0a884) +EVENT(PM_LSU0_FLUSH_SRQ, 0x0c0bc) +EVENT(PM_LSU1_L1_PREF, 0x0d0ba) +EVENT(PM_IOPS_CMPL, 0x10014) +EVENT(PM_L2_SYS_PUMP, 0x36482) +EVENT(PM_L2_RCLD_BUSY_RC_FULL, 0x46282) +EVENT(PM_LSU_LMQ_S0_ALLOC, 0x0d0a1) +EVENT(PM_FLUSH_DISP_SYNC, 0x02088) +EVENT(PM_MRK_DATA_FROM_DL2L3_MOD_CYC, 0x4002a) +EVENT(PM_L2_IC_INV, 0x26180) +EVENT(PM_MRK_DATA_FROM_L21_MOD_CYC, 0x40024) +EVENT(PM_L3_PREF_LDST, 0x0d8ac) +EVENT(PM_LSU_SRQ_EMPTY_CYC, 0x40008) +EVENT(PM_LSU_LMQ_S0_VALID, 0x0d0a0) +EVENT(PM_FLUSH_PARTIAL, 0x02086) +EVENT(PM_VSU1_FMA_DOUBLE, 0x0a092) +EVENT(PM_1PLUS_PPC_DISP, 0x400f2) +EVENT(PM_DATA_FROM_L2MISS, 0x200fe) +EVENT(PM_SUSPENDED, 0x00000) +EVENT(PM_VSU0_FMA, 0x0a084) +EVENT(PM_CMPLU_STALL_SCALAR, 0x40012) +EVENT(PM_STCX_FAIL, 0x0c09a) +EVENT(PM_VSU0_FSQRT_FDIV_DOUBLE, 0x0a094) +EVENT(PM_DC_PREF_DST, 0x0d0b0) +EVENT(PM_VSU1_SCAL_SINGLE_ISSUED, 0x0b086) +EVENT(PM_L3_HIT, 0x1f080) +EVENT(PM_L2_GLOB_GUESS_WRONG, 0x26482) +EVENT(PM_MRK_DFU_FIN, 0x20032) +EVENT(PM_INST_FROM_L1, 0x04080) +EVENT(PM_BRU_FIN, 0x10068) +EVENT(PM_IC_DEMAND_REQ, 0x04088) +EVENT(PM_VSU1_FSQRT_FDIV_DOUBLE, 0x0a096) +EVENT(PM_VSU1_FMA, 0x0a086) +EVENT(PM_MRK_LD_MISS_L1, 0x20036) +EVENT(PM_VSU0_2FLOP_DOUBLE, 0x0a08c) +EVENT(PM_LSU_DC_PREF_STRIDED_STREAM_CONFIRM, 0x0d8bc) +EVENT(PM_INST_PTEG_FROM_L31_SHR, 0x2e056) +EVENT(PM_MRK_LSU_REJECT_ERAT_MISS, 0x30064) +EVENT(PM_MRK_DATA_FROM_L2MISS, 0x4d048) +EVENT(PM_DATA_FROM_RL2L3_SHR, 0x1c04c) +EVENT(PM_INST_FROM_PREF, 0x14046) +EVENT(PM_VSU1_SQ, 0x0b09e) +EVENT(PM_L2_LD_DISP, 0x36180) +EVENT(PM_L2_DISP_ALL, 0x46080) +EVENT(PM_THRD_GRP_CMPL_BOTH_CYC, 0x10012) +EVENT(PM_VSU_FSQRT_FDIV_DOUBLE, 0x0a894) +EVENT(PM_BR_MPRED, 0x400f6) +EVENT(PM_INST_PTEG_FROM_DL2L3_SHR, 0x3e054) +EVENT(PM_VSU_1FLOP, 0x0a880) +EVENT(PM_HV_CYC, 0x2000a) +EVENT(PM_MRK_LSU_FIN, 0x40032) +EVENT(PM_MRK_DATA_FROM_RL2L3_SHR, 0x1d04c) +EVENT(PM_DTLB_MISS_16M, 0x4c05e) +EVENT(PM_LSU1_LMQ_LHR_MERGE, 0x0d09a) +EVENT(PM_IFU_FIN, 0x40066) diff --git a/arch/powerpc/perf/power7-pmu.c b/arch/powerpc/perf/power7-pmu.c index d1821b8bbc4c..56c67bca2f75 100644 --- a/arch/powerpc/perf/power7-pmu.c +++ b/arch/powerpc/perf/power7-pmu.c @@ -53,37 +53,13 @@ /* * Power7 event codes. */ -#define PME_PM_CYC 0x1e -#define PME_PM_GCT_NOSLOT_CYC 0x100f8 -#define PME_PM_CMPLU_STALL 0x4000a -#define PME_PM_INST_CMPL 0x2 -#define PME_PM_LD_REF_L1 0xc880 -#define PME_PM_LD_MISS_L1 0x400f0 -#define PME_PM_BRU_FIN 0x10068 -#define PME_PM_BR_MPRED 0x400f6 +#define EVENT(_name, _code) \ + PME_##_name = _code, -#define PME_PM_CMPLU_STALL_FXU 0x20014 -#define PME_PM_CMPLU_STALL_DIV 0x40014 -#define PME_PM_CMPLU_STALL_SCALAR 0x40012 -#define PME_PM_CMPLU_STALL_SCALAR_LONG 0x20018 -#define PME_PM_CMPLU_STALL_VECTOR 0x2001c -#define PME_PM_CMPLU_STALL_VECTOR_LONG 0x4004a -#define PME_PM_CMPLU_STALL_LSU 0x20012 -#define PME_PM_CMPLU_STALL_REJECT 0x40016 -#define PME_PM_CMPLU_STALL_ERAT_MISS 0x40018 -#define PME_PM_CMPLU_STALL_DCACHE_MISS 0x20016 -#define PME_PM_CMPLU_STALL_STORE 0x2004a -#define PME_PM_CMPLU_STALL_THRD 0x1001c -#define PME_PM_CMPLU_STALL_IFU 0x4004c -#define PME_PM_CMPLU_STALL_BRU 0x4004e -#define PME_PM_GCT_NOSLOT_IC_MISS 0x2001a -#define PME_PM_GCT_NOSLOT_BR_MPRED 0x4001a -#define PME_PM_GCT_NOSLOT_BR_MPRED_IC_MISS 0x4001c -#define PME_PM_GRP_CMPL 0x30004 -#define PME_PM_1PLUS_PPC_CMPL 0x100f2 -#define PME_PM_CMPLU_STALL_DFU 0x2003c -#define PME_PM_RUN_CYC 0x200f4 -#define PME_PM_RUN_INST_CMPL 0x400fa +enum { +#include "power7-events-list.h" +}; +#undef EVENT /* * Layout of constraint bits: @@ -398,96 +374,36 @@ static int power7_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = { }; -GENERIC_EVENT_ATTR(cpu-cycles, CYC); -GENERIC_EVENT_ATTR(stalled-cycles-frontend, GCT_NOSLOT_CYC); -GENERIC_EVENT_ATTR(stalled-cycles-backend, CMPLU_STALL); -GENERIC_EVENT_ATTR(instructions, INST_CMPL); -GENERIC_EVENT_ATTR(cache-references, LD_REF_L1); -GENERIC_EVENT_ATTR(cache-misses, LD_MISS_L1); -GENERIC_EVENT_ATTR(branch-instructions, BRU_FIN); -GENERIC_EVENT_ATTR(branch-misses, BR_MPRED); +GENERIC_EVENT_ATTR(cpu-cycles, PM_CYC); +GENERIC_EVENT_ATTR(stalled-cycles-frontend, PM_GCT_NOSLOT_CYC); +GENERIC_EVENT_ATTR(stalled-cycles-backend, PM_CMPLU_STALL); +GENERIC_EVENT_ATTR(instructions, PM_INST_CMPL); +GENERIC_EVENT_ATTR(cache-references, PM_LD_REF_L1); +GENERIC_EVENT_ATTR(cache-misses, PM_LD_MISS_L1); +GENERIC_EVENT_ATTR(branch-instructions, PM_BRU_FIN); +GENERIC_EVENT_ATTR(branch-misses, PM_BR_MPRED); -POWER_EVENT_ATTR(CYC, CYC); -POWER_EVENT_ATTR(GCT_NOSLOT_CYC, GCT_NOSLOT_CYC); -POWER_EVENT_ATTR(CMPLU_STALL, CMPLU_STALL); -POWER_EVENT_ATTR(INST_CMPL, INST_CMPL); -POWER_EVENT_ATTR(LD_REF_L1, LD_REF_L1); -POWER_EVENT_ATTR(LD_MISS_L1, LD_MISS_L1); -POWER_EVENT_ATTR(BRU_FIN, BRU_FIN) -POWER_EVENT_ATTR(BR_MPRED, BR_MPRED); +#define EVENT(_name, _code) POWER_EVENT_ATTR(_name, _name); +#include "power7-events-list.h" +#undef EVENT -POWER_EVENT_ATTR(CMPLU_STALL_FXU, CMPLU_STALL_FXU); -POWER_EVENT_ATTR(CMPLU_STALL_DIV, CMPLU_STALL_DIV); -POWER_EVENT_ATTR(CMPLU_STALL_SCALAR, CMPLU_STALL_SCALAR); -POWER_EVENT_ATTR(CMPLU_STALL_SCALAR_LONG, CMPLU_STALL_SCALAR_LONG); -POWER_EVENT_ATTR(CMPLU_STALL_VECTOR, CMPLU_STALL_VECTOR); -POWER_EVENT_ATTR(CMPLU_STALL_VECTOR_LONG, CMPLU_STALL_VECTOR_LONG); -POWER_EVENT_ATTR(CMPLU_STALL_LSU, CMPLU_STALL_LSU); -POWER_EVENT_ATTR(CMPLU_STALL_REJECT, CMPLU_STALL_REJECT); - -POWER_EVENT_ATTR(CMPLU_STALL_ERAT_MISS, CMPLU_STALL_ERAT_MISS); -POWER_EVENT_ATTR(CMPLU_STALL_DCACHE_MISS, CMPLU_STALL_DCACHE_MISS); -POWER_EVENT_ATTR(CMPLU_STALL_STORE, CMPLU_STALL_STORE); -POWER_EVENT_ATTR(CMPLU_STALL_THRD, CMPLU_STALL_THRD); -POWER_EVENT_ATTR(CMPLU_STALL_IFU, CMPLU_STALL_IFU); -POWER_EVENT_ATTR(CMPLU_STALL_BRU, CMPLU_STALL_BRU); -POWER_EVENT_ATTR(GCT_NOSLOT_IC_MISS, GCT_NOSLOT_IC_MISS); - -POWER_EVENT_ATTR(GCT_NOSLOT_BR_MPRED, GCT_NOSLOT_BR_MPRED); -POWER_EVENT_ATTR(GCT_NOSLOT_BR_MPRED_IC_MISS, GCT_NOSLOT_BR_MPRED_IC_MISS); -POWER_EVENT_ATTR(GRP_CMPL, GRP_CMPL); -POWER_EVENT_ATTR(1PLUS_PPC_CMPL, 1PLUS_PPC_CMPL); -POWER_EVENT_ATTR(CMPLU_STALL_DFU, CMPLU_STALL_DFU); -POWER_EVENT_ATTR(RUN_CYC, RUN_CYC); -POWER_EVENT_ATTR(RUN_INST_CMPL, RUN_INST_CMPL); +#define EVENT(_name, _code) POWER_EVENT_PTR(_name), static struct attribute *power7_events_attr[] = { - GENERIC_EVENT_PTR(CYC), - GENERIC_EVENT_PTR(GCT_NOSLOT_CYC), - GENERIC_EVENT_PTR(CMPLU_STALL), - GENERIC_EVENT_PTR(INST_CMPL), - GENERIC_EVENT_PTR(LD_REF_L1), - GENERIC_EVENT_PTR(LD_MISS_L1), - GENERIC_EVENT_PTR(BRU_FIN), - GENERIC_EVENT_PTR(BR_MPRED), + GENERIC_EVENT_PTR(PM_CYC), + GENERIC_EVENT_PTR(PM_GCT_NOSLOT_CYC), + GENERIC_EVENT_PTR(PM_CMPLU_STALL), + GENERIC_EVENT_PTR(PM_INST_CMPL), + GENERIC_EVENT_PTR(PM_LD_REF_L1), + GENERIC_EVENT_PTR(PM_LD_MISS_L1), + GENERIC_EVENT_PTR(PM_BRU_FIN), + GENERIC_EVENT_PTR(PM_BR_MPRED), - POWER_EVENT_PTR(CYC), - POWER_EVENT_PTR(GCT_NOSLOT_CYC), - POWER_EVENT_PTR(CMPLU_STALL), - POWER_EVENT_PTR(INST_CMPL), - POWER_EVENT_PTR(LD_REF_L1), - POWER_EVENT_PTR(LD_MISS_L1), - POWER_EVENT_PTR(BRU_FIN), - POWER_EVENT_PTR(BR_MPRED), - - POWER_EVENT_PTR(CMPLU_STALL_FXU), - POWER_EVENT_PTR(CMPLU_STALL_DIV), - POWER_EVENT_PTR(CMPLU_STALL_SCALAR), - POWER_EVENT_PTR(CMPLU_STALL_SCALAR_LONG), - POWER_EVENT_PTR(CMPLU_STALL_VECTOR), - POWER_EVENT_PTR(CMPLU_STALL_VECTOR_LONG), - POWER_EVENT_PTR(CMPLU_STALL_LSU), - POWER_EVENT_PTR(CMPLU_STALL_REJECT), - - POWER_EVENT_PTR(CMPLU_STALL_ERAT_MISS), - POWER_EVENT_PTR(CMPLU_STALL_DCACHE_MISS), - POWER_EVENT_PTR(CMPLU_STALL_STORE), - POWER_EVENT_PTR(CMPLU_STALL_THRD), - POWER_EVENT_PTR(CMPLU_STALL_IFU), - POWER_EVENT_PTR(CMPLU_STALL_BRU), - POWER_EVENT_PTR(GCT_NOSLOT_IC_MISS), - POWER_EVENT_PTR(GCT_NOSLOT_BR_MPRED), - - POWER_EVENT_PTR(GCT_NOSLOT_BR_MPRED_IC_MISS), - POWER_EVENT_PTR(GRP_CMPL), - POWER_EVENT_PTR(1PLUS_PPC_CMPL), - POWER_EVENT_PTR(CMPLU_STALL_DFU), - POWER_EVENT_PTR(RUN_CYC), - POWER_EVENT_PTR(RUN_INST_CMPL), + #include "power7-events-list.h" + #undef EVENT NULL }; - static struct attribute_group power7_pmu_events_group = { .name = "events", .attrs = power7_events_attr, From b3824404ebbd489858f3a7097c715120118fa5cd Mon Sep 17 00:00:00 2001 From: David Ahern Date: Tue, 2 Jul 2013 13:27:21 -0600 Subject: [PATCH 0023/3400] perf evlist: Fix use of uninitialized variable Fixes valgrind complaint: ==1870== Syscall param write(buf) points to uninitialised byte(s) ==1870== at 0x4E3F5B0: __write_nocancel (in /lib64/libpthread-2.14.90.so) ==1870== by 0x449D7C: perf_evlist__start_workload (evlist.c:846) ==1870== by 0x427BC1: cmd_record (builtin-record.c:561) ==1870== by 0x419D72: run_builtin (perf.c:319) ==1870== by 0x4195F2: main (perf.c:376) ==1870== Address 0x7feffcdd7 is on thread 1's stack Signed-off-by: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1372793245-4136-3-git-send-email-dsahern@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evlist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 4a901be599ed..d8f34e0afbfb 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -838,7 +838,7 @@ out_close_ready_pipe: int perf_evlist__start_workload(struct perf_evlist *evlist) { if (evlist->workload.cork_fd > 0) { - char bf; + char bf = 0; int ret; /* * Remove the cork, let it rip! From 0142dab01cd690f6e376f1fb4d4462beb054dfaf Mon Sep 17 00:00:00 2001 From: David Ahern Date: Tue, 2 Jul 2013 13:27:23 -0600 Subject: [PATCH 0024/3400] perf tools: Don't free list head in parse_events__free_terms Function should only be freeing the entries in the list in case of failure, as those were allocated there, not the list_head itself. Signed-off-by: David Ahern Cc: Adrian Hunter Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1372793245-4136-5-git-send-email-dsahern@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/parse-events.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index ef72e98a07a6..bcf83ee97e92 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -1260,6 +1260,4 @@ void parse_events__free_terms(struct list_head *terms) list_for_each_entry_safe(term, h, terms, list) free(term); - - free(terms); } From c549aca50134640537bf0fbae43c08fd5ff91932 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Tue, 2 Jul 2013 13:27:24 -0600 Subject: [PATCH 0025/3400] perf tests: Make terms a stack variable in test_term No need to malloc the memory for it. Signed-off-by: David Ahern Cc: Adrian Hunter Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1372793245-4136-6-git-send-email-dsahern@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/parse-events.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c index ad950f57d85b..344c844ffc1e 100644 --- a/tools/perf/tests/parse-events.c +++ b/tools/perf/tests/parse-events.c @@ -1246,24 +1246,20 @@ static int test_events(struct evlist_test *events, unsigned cnt) static int test_term(struct terms_test *t) { - struct list_head *terms; + struct list_head terms; int ret; - terms = malloc(sizeof(*terms)); - if (!terms) - return -ENOMEM; + INIT_LIST_HEAD(&terms); - INIT_LIST_HEAD(terms); - - ret = parse_events_terms(terms, t->str); + ret = parse_events_terms(&terms, t->str); if (ret) { pr_debug("failed to parse terms '%s', err %d\n", t->str , ret); return ret; } - ret = t->check(terms); - parse_events__free_terms(terms); + ret = t->check(&terms); + parse_events__free_terms(&terms); return ret; } From c5cd8ac07e7ad5f21b1930b23b2e1bb231958430 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Tue, 2 Jul 2013 13:27:25 -0600 Subject: [PATCH 0026/3400] perf parse events: Demystify memory allocations List heads are currently allocated way down the function chain in __add_event and add_tracepoint and then freed when the scanner code calls parse_events_update_lists. Be more explicit with where memory is allocated and who should free it. With this patch the list_head is allocated in the scanner code and freed when the scanner code calls parse_events_update_lists. Signed-off-by: David Ahern Cc: Adrian Hunter Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1372793245-4136-7-git-send-email-dsahern@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/parse-events.c | 52 +++++++++------------------- tools/perf/util/parse-events.h | 10 +++--- tools/perf/util/parse-events.y | 62 ++++++++++++++++++++++------------ 3 files changed, 61 insertions(+), 63 deletions(-) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index bcf83ee97e92..e85376999efc 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -264,40 +264,29 @@ const char *event_type(int type) -static int __add_event(struct list_head **_list, int *idx, +static int __add_event(struct list_head *list, int *idx, struct perf_event_attr *attr, char *name, struct cpu_map *cpus) { struct perf_evsel *evsel; - struct list_head *list = *_list; - - if (!list) { - list = malloc(sizeof(*list)); - if (!list) - return -ENOMEM; - INIT_LIST_HEAD(list); - } event_attr_init(attr); evsel = perf_evsel__new(attr, (*idx)++); - if (!evsel) { - free(list); + if (!evsel) return -ENOMEM; - } evsel->cpus = cpus; if (name) evsel->name = strdup(name); list_add_tail(&evsel->node, list); - *_list = list; return 0; } -static int add_event(struct list_head **_list, int *idx, +static int add_event(struct list_head *list, int *idx, struct perf_event_attr *attr, char *name) { - return __add_event(_list, idx, attr, name, NULL); + return __add_event(list, idx, attr, name, NULL); } static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size) @@ -318,7 +307,7 @@ static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES] return -1; } -int parse_events_add_cache(struct list_head **list, int *idx, +int parse_events_add_cache(struct list_head *list, int *idx, char *type, char *op_result1, char *op_result2) { struct perf_event_attr attr; @@ -379,31 +368,21 @@ int parse_events_add_cache(struct list_head **list, int *idx, return add_event(list, idx, &attr, name); } -static int add_tracepoint(struct list_head **listp, int *idx, +static int add_tracepoint(struct list_head *list, int *idx, char *sys_name, char *evt_name) { struct perf_evsel *evsel; - struct list_head *list = *listp; - - if (!list) { - list = malloc(sizeof(*list)); - if (!list) - return -ENOMEM; - INIT_LIST_HEAD(list); - } evsel = perf_evsel__newtp(sys_name, evt_name, (*idx)++); - if (!evsel) { - free(list); + if (!evsel) return -ENOMEM; - } list_add_tail(&evsel->node, list); - *listp = list; + return 0; } -static int add_tracepoint_multi_event(struct list_head **list, int *idx, +static int add_tracepoint_multi_event(struct list_head *list, int *idx, char *sys_name, char *evt_name) { char evt_path[MAXPATHLEN]; @@ -435,7 +414,7 @@ static int add_tracepoint_multi_event(struct list_head **list, int *idx, return ret; } -static int add_tracepoint_event(struct list_head **list, int *idx, +static int add_tracepoint_event(struct list_head *list, int *idx, char *sys_name, char *evt_name) { return strpbrk(evt_name, "*?") ? @@ -443,7 +422,7 @@ static int add_tracepoint_event(struct list_head **list, int *idx, add_tracepoint(list, idx, sys_name, evt_name); } -static int add_tracepoint_multi_sys(struct list_head **list, int *idx, +static int add_tracepoint_multi_sys(struct list_head *list, int *idx, char *sys_name, char *evt_name) { struct dirent *events_ent; @@ -475,7 +454,7 @@ static int add_tracepoint_multi_sys(struct list_head **list, int *idx, return ret; } -int parse_events_add_tracepoint(struct list_head **list, int *idx, +int parse_events_add_tracepoint(struct list_head *list, int *idx, char *sys, char *event) { int ret; @@ -530,7 +509,7 @@ do { \ return 0; } -int parse_events_add_breakpoint(struct list_head **list, int *idx, +int parse_events_add_breakpoint(struct list_head *list, int *idx, void *ptr, char *type) { struct perf_event_attr attr; @@ -611,7 +590,7 @@ static int config_attr(struct perf_event_attr *attr, return 0; } -int parse_events_add_numeric(struct list_head **list, int *idx, +int parse_events_add_numeric(struct list_head *list, int *idx, u32 type, u64 config, struct list_head *head_config) { @@ -644,7 +623,7 @@ static char *pmu_event_name(struct list_head *head_terms) return NULL; } -int parse_events_add_pmu(struct list_head **list, int *idx, +int parse_events_add_pmu(struct list_head *list, int *idx, char *name, struct list_head *head_config) { struct perf_event_attr attr; @@ -687,6 +666,7 @@ void parse_events__set_leader(char *name, struct list_head *list) leader->group_name = name ? strdup(name) : NULL; } +/* list_event is assumed to point to malloc'ed memory */ void parse_events_update_lists(struct list_head *list_event, struct list_head *list_all) { diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index 080f7cf25d99..f1cb4c4b3c70 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -85,16 +85,16 @@ void parse_events__free_terms(struct list_head *terms); int parse_events__modifier_event(struct list_head *list, char *str, bool add); int parse_events__modifier_group(struct list_head *list, char *event_mod); int parse_events_name(struct list_head *list, char *name); -int parse_events_add_tracepoint(struct list_head **list, int *idx, +int parse_events_add_tracepoint(struct list_head *list, int *idx, char *sys, char *event); -int parse_events_add_numeric(struct list_head **list, int *idx, +int parse_events_add_numeric(struct list_head *list, int *idx, u32 type, u64 config, struct list_head *head_config); -int parse_events_add_cache(struct list_head **list, int *idx, +int parse_events_add_cache(struct list_head *list, int *idx, char *type, char *op_result1, char *op_result2); -int parse_events_add_breakpoint(struct list_head **list, int *idx, +int parse_events_add_breakpoint(struct list_head *list, int *idx, void *ptr, char *type); -int parse_events_add_pmu(struct list_head **list, int *idx, +int parse_events_add_pmu(struct list_head *list, int *idx, char *pmu , struct list_head *head_config); void parse_events__set_leader(char *name, struct list_head *list); void parse_events_update_lists(struct list_head *list_event, diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y index afc44c18dfe1..4eb67ec333f1 100644 --- a/tools/perf/util/parse-events.y +++ b/tools/perf/util/parse-events.y @@ -22,6 +22,13 @@ do { \ YYABORT; \ } while (0) +#define ALLOC_LIST(list) \ +do { \ + list = malloc(sizeof(*list)); \ + ABORT_ON(!list); \ + INIT_LIST_HEAD(list); \ +} while (0) + static inc_group_count(struct list_head *list, struct parse_events_evlist *data) { @@ -196,9 +203,10 @@ event_pmu: PE_NAME '/' event_config '/' { struct parse_events_evlist *data = _data; - struct list_head *list = NULL; + struct list_head *list; - ABORT_ON(parse_events_add_pmu(&list, &data->idx, $1, $3)); + ALLOC_LIST(list); + ABORT_ON(parse_events_add_pmu(list, &data->idx, $1, $3)); parse_events__free_terms($3); $$ = list; } @@ -212,11 +220,12 @@ event_legacy_symbol: value_sym '/' event_config '/' { struct parse_events_evlist *data = _data; - struct list_head *list = NULL; + struct list_head *list; int type = $1 >> 16; int config = $1 & 255; - ABORT_ON(parse_events_add_numeric(&list, &data->idx, + ALLOC_LIST(list); + ABORT_ON(parse_events_add_numeric(list, &data->idx, type, config, $3)); parse_events__free_terms($3); $$ = list; @@ -225,11 +234,12 @@ value_sym '/' event_config '/' value_sym sep_slash_dc { struct parse_events_evlist *data = _data; - struct list_head *list = NULL; + struct list_head *list; int type = $1 >> 16; int config = $1 & 255; - ABORT_ON(parse_events_add_numeric(&list, &data->idx, + ALLOC_LIST(list); + ABORT_ON(parse_events_add_numeric(list, &data->idx, type, config, NULL)); $$ = list; } @@ -238,27 +248,30 @@ event_legacy_cache: PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT { struct parse_events_evlist *data = _data; - struct list_head *list = NULL; + struct list_head *list; - ABORT_ON(parse_events_add_cache(&list, &data->idx, $1, $3, $5)); + ALLOC_LIST(list); + ABORT_ON(parse_events_add_cache(list, &data->idx, $1, $3, $5)); $$ = list; } | PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT { struct parse_events_evlist *data = _data; - struct list_head *list = NULL; + struct list_head *list; - ABORT_ON(parse_events_add_cache(&list, &data->idx, $1, $3, NULL)); + ALLOC_LIST(list); + ABORT_ON(parse_events_add_cache(list, &data->idx, $1, $3, NULL)); $$ = list; } | PE_NAME_CACHE_TYPE { struct parse_events_evlist *data = _data; - struct list_head *list = NULL; + struct list_head *list; - ABORT_ON(parse_events_add_cache(&list, &data->idx, $1, NULL, NULL)); + ALLOC_LIST(list); + ABORT_ON(parse_events_add_cache(list, &data->idx, $1, NULL, NULL)); $$ = list; } @@ -266,9 +279,10 @@ event_legacy_mem: PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc { struct parse_events_evlist *data = _data; - struct list_head *list = NULL; + struct list_head *list; - ABORT_ON(parse_events_add_breakpoint(&list, &data->idx, + ALLOC_LIST(list); + ABORT_ON(parse_events_add_breakpoint(list, &data->idx, (void *) $2, $4)); $$ = list; } @@ -276,9 +290,10 @@ PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc PE_PREFIX_MEM PE_VALUE sep_dc { struct parse_events_evlist *data = _data; - struct list_head *list = NULL; + struct list_head *list; - ABORT_ON(parse_events_add_breakpoint(&list, &data->idx, + ALLOC_LIST(list); + ABORT_ON(parse_events_add_breakpoint(list, &data->idx, (void *) $2, NULL)); $$ = list; } @@ -287,9 +302,10 @@ event_legacy_tracepoint: PE_NAME ':' PE_NAME { struct parse_events_evlist *data = _data; - struct list_head *list = NULL; + struct list_head *list; - ABORT_ON(parse_events_add_tracepoint(&list, &data->idx, $1, $3)); + ALLOC_LIST(list); + ABORT_ON(parse_events_add_tracepoint(list, &data->idx, $1, $3)); $$ = list; } @@ -297,9 +313,10 @@ event_legacy_numeric: PE_VALUE ':' PE_VALUE { struct parse_events_evlist *data = _data; - struct list_head *list = NULL; + struct list_head *list; - ABORT_ON(parse_events_add_numeric(&list, &data->idx, (u32)$1, $3, NULL)); + ALLOC_LIST(list); + ABORT_ON(parse_events_add_numeric(list, &data->idx, (u32)$1, $3, NULL)); $$ = list; } @@ -307,9 +324,10 @@ event_legacy_raw: PE_RAW { struct parse_events_evlist *data = _data; - struct list_head *list = NULL; + struct list_head *list; - ABORT_ON(parse_events_add_numeric(&list, &data->idx, + ALLOC_LIST(list); + ABORT_ON(parse_events_add_numeric(list, &data->idx, PERF_TYPE_RAW, $1, NULL)); $$ = list; } From 9f1efa82640b4f06c8f6c847f088c53e4100395c Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 4 Jun 2013 14:20:16 +0900 Subject: [PATCH 0027/3400] tools lib traceevent: Remove unused install targets The html_install, img_install, install_plugin and install_python are unused in the Makefile. Get rid of them. Signed-off-by: Namhyung Kim Acked-by: Steven Rostedt Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1370323231-14022-2-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Makefile | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index 0b0a90787db6..fd7510d99583 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile @@ -39,13 +39,8 @@ bindir_relative = bin bindir = $(prefix)/$(bindir_relative) man_dir = $(prefix)/share/man man_dir_SQ = '$(subst ','\'',$(man_dir))' -html_install = $(prefix)/share/kernelshark/html -html_install_SQ = '$(subst ','\'',$(html_install))' -img_install = $(prefix)/share/kernelshark/html/images -img_install_SQ = '$(subst ','\'',$(img_install))' -export man_dir man_dir_SQ html_install html_install_SQ INSTALL -export img_install img_install_SQ +export man_dir man_dir_SQ INSTALL export DESTDIR DESTDIR_SQ # copy a bit from Linux kbuild @@ -300,7 +295,7 @@ define do_install $(INSTALL) $1 '$(DESTDIR_SQ)$2' endef -install_lib: all_cmd install_plugins install_python +install_lib: all_cmd $(Q)$(call do_install,$(LIB_FILE),$(bindir_SQ)) install: install_lib From 4ccdf57d46843f5c03e390bdb652c9744e30ee20 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 4 Jun 2013 14:20:17 +0900 Subject: [PATCH 0028/3400] tools lib traceevent: Get rid of unused gui target It's came from trace-cmd's kernelshark which is not a part of libtraceevent. Signed-off-by: Namhyung Kim Acked-by: Steven Rostedt Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1370323231-14022-3-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Makefile | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index fd7510d99583..4505de874929 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile @@ -71,10 +71,7 @@ $(if $(BUILD_OUTPUT),, \ all: sub-make -gui: force - $(call build_output, all_cmd) - -$(filter-out gui,$(MAKECMDGOALS)): sub-make +$(MAKECMDGOALS): sub-make sub-make: force $(call build_output, $(MAKECMDGOALS)) @@ -253,9 +250,6 @@ define check_deps $(RM) $@.$$$$ endef -$(gui_deps): ks_version.h -$(non_gui_deps): tc_version.h - $(all_deps): .%.d: $(src)/%.c $(Q)$(call check_deps) From 79d5adf06dd530fe6a9ab3d086b2d23eb7560491 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 4 Jun 2013 14:20:18 +0900 Subject: [PATCH 0029/3400] tools lib traceevent: Add const qualifier to string arguments If pevent_register_event_handler() received a string literal as @sys_name or @event_name parameter, it emitted a warning about const qualifier removal. Since they're not modified in the function we can make it have const qualifier. Signed-off-by: Namhyung Kim Acked-by: Steven Rostedt Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1370323231-14022-4-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.c | 7 +++---- tools/lib/traceevent/event-parse.h | 3 ++- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index 82b0606dcb8a..d1c2a6a4cd32 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c @@ -5450,10 +5450,9 @@ int pevent_register_print_function(struct pevent *pevent, * If @id is >= 0, then it is used to find the event. * else @sys_name and @event_name are used. */ -int pevent_register_event_handler(struct pevent *pevent, - int id, char *sys_name, char *event_name, - pevent_event_handler_func func, - void *context) +int pevent_register_event_handler(struct pevent *pevent, int id, + const char *sys_name, const char *event_name, + pevent_event_handler_func func, void *context) { struct event_format *event; struct event_handler *handle; diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index 7be7e89533e4..bfceab948f22 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -561,7 +561,8 @@ int pevent_print_num_field(struct trace_seq *s, const char *fmt, struct event_format *event, const char *name, struct pevent_record *record, int err); -int pevent_register_event_handler(struct pevent *pevent, int id, char *sys_name, char *event_name, +int pevent_register_event_handler(struct pevent *pevent, int id, + const char *sys_name, const char *event_name, pevent_event_handler_func func, void *context); int pevent_register_print_function(struct pevent *pevent, pevent_func_handler func, From 6a48aec3a7179b0cdae2339d5a4072214ee6c6fe Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 4 Jun 2013 14:20:19 +0900 Subject: [PATCH 0030/3400] tools lib traceevent: Add trace_seq_reset() Sometimes it'd be useful if existing trace_seq can be reused. But currently it's impossible since there's no API to reset the trace_seq. Let's add trace_seq_reset() for this case. Signed-off-by: Namhyung Kim Acked-by: Steven Rostedt Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1370323231-14022-5-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.h | 1 + tools/lib/traceevent/trace-seq.c | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index bfceab948f22..39f0c1dca915 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -69,6 +69,7 @@ struct trace_seq { }; void trace_seq_init(struct trace_seq *s); +void trace_seq_reset(struct trace_seq *s); void trace_seq_destroy(struct trace_seq *s); extern int trace_seq_printf(struct trace_seq *s, const char *fmt, ...) diff --git a/tools/lib/traceevent/trace-seq.c b/tools/lib/traceevent/trace-seq.c index a57db805136a..d7f2e68bc5b9 100644 --- a/tools/lib/traceevent/trace-seq.c +++ b/tools/lib/traceevent/trace-seq.c @@ -48,6 +48,19 @@ void trace_seq_init(struct trace_seq *s) s->buffer = malloc_or_die(s->buffer_size); } +/** + * trace_seq_reset - re-initialize the trace_seq structure + * @s: a pointer to the trace_seq structure to reset + */ +void trace_seq_reset(struct trace_seq *s) +{ + if (!s) + return; + TRACE_SEQ_CHECK(s); + s->len = 0; + s->readpos = 0; +} + /** * trace_seq_destroy - free up memory of a trace_seq * @s: a pointer to the trace_seq to free the buffer From 012ac692575b1ea6ed930871850584e4c64f1382 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 4 Jun 2013 14:20:20 +0900 Subject: [PATCH 0031/3400] tools lib traceevent: Add page_size field to pevent The page size of traced system can be different than current system's because the recorded data file might be analyzed in a different machine. In this case we should use original page size of traced system when accessing the data file, so this information needs to be saved. Signed-off-by: Namhyung Kim Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1370323231-14022-6-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/event-parse.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index 39f0c1dca915..c37b2026d04a 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h @@ -400,6 +400,7 @@ struct pevent { int cpus; int long_size; + int page_size; struct cmdline *cmdlines; struct cmdline_list *cmdlist; @@ -621,6 +622,16 @@ static inline void pevent_set_long_size(struct pevent *pevent, int long_size) pevent->long_size = long_size; } +static inline int pevent_get_page_size(struct pevent *pevent) +{ + return pevent->page_size; +} + +static inline void pevent_set_page_size(struct pevent *pevent, int _page_size) +{ + pevent->page_size = _page_size; +} + static inline int pevent_is_file_bigendian(struct pevent *pevent) { return pevent->file_bigendian; From d6c25223f6067c6889d8fc3f9576d34bbac161b0 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 4 Jun 2013 14:20:21 +0900 Subject: [PATCH 0032/3400] tools lib traceevent: Port kbuffer parser routines kbuffer code is for parsing ftrace ring-buffer binary data and used for trace-cmd. Move the code here in order to be used more widely. Signed-off-by: Namhyung Kim Original-patch-by: Steven Rostedt Acked-by: Steven Rostedt Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1370323231-14022-7-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/traceevent/Makefile | 1 + tools/lib/traceevent/kbuffer-parse.c | 732 +++++++++++++++++++++++++++ tools/lib/traceevent/kbuffer.h | 67 +++ 3 files changed, 800 insertions(+) create mode 100644 tools/lib/traceevent/kbuffer-parse.c create mode 100644 tools/lib/traceevent/kbuffer.h diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index 4505de874929..0794acca46a3 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile @@ -181,6 +181,7 @@ $(obj)/%.o: $(src)/%.c $(Q)$(call do_compile) PEVENT_LIB_OBJS = event-parse.o trace-seq.o parse-filter.o parse-utils.o +PEVENT_LIB_OBJS += kbuffer-parse.o ALL_OBJS = $(PEVENT_LIB_OBJS) diff --git a/tools/lib/traceevent/kbuffer-parse.c b/tools/lib/traceevent/kbuffer-parse.c new file mode 100644 index 000000000000..dcc665228c71 --- /dev/null +++ b/tools/lib/traceevent/kbuffer-parse.c @@ -0,0 +1,732 @@ +/* + * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * 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; + * version 2.1 of the License (not later!) + * + * 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 program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ +#include +#include +#include + +#include "kbuffer.h" + +#define MISSING_EVENTS (1 << 31) +#define MISSING_STORED (1 << 30) + +#define COMMIT_MASK ((1 << 27) - 1) + +enum { + KBUFFER_FL_HOST_BIG_ENDIAN = (1<<0), + KBUFFER_FL_BIG_ENDIAN = (1<<1), + KBUFFER_FL_LONG_8 = (1<<2), + KBUFFER_FL_OLD_FORMAT = (1<<3), +}; + +#define ENDIAN_MASK (KBUFFER_FL_HOST_BIG_ENDIAN | KBUFFER_FL_BIG_ENDIAN) + +/** kbuffer + * @timestamp - timestamp of current event + * @lost_events - # of lost events between this subbuffer and previous + * @flags - special flags of the kbuffer + * @subbuffer - pointer to the sub-buffer page + * @data - pointer to the start of data on the sub-buffer page + * @index - index from @data to the @curr event data + * @curr - offset from @data to the start of current event + * (includes metadata) + * @next - offset from @data to the start of next event + * @size - The size of data on @data + * @start - The offset from @subbuffer where @data lives + * + * @read_4 - Function to read 4 raw bytes (may swap) + * @read_8 - Function to read 8 raw bytes (may swap) + * @read_long - Function to read a long word (4 or 8 bytes with needed swap) + */ +struct kbuffer { + unsigned long long timestamp; + long long lost_events; + unsigned long flags; + void *subbuffer; + void *data; + unsigned int index; + unsigned int curr; + unsigned int next; + unsigned int size; + unsigned int start; + + unsigned int (*read_4)(void *ptr); + unsigned long long (*read_8)(void *ptr); + unsigned long long (*read_long)(struct kbuffer *kbuf, void *ptr); + int (*next_event)(struct kbuffer *kbuf); +}; + +static void *zmalloc(size_t size) +{ + return calloc(1, size); +} + +static int host_is_bigendian(void) +{ + unsigned char str[] = { 0x1, 0x2, 0x3, 0x4 }; + unsigned int *ptr; + + ptr = (unsigned int *)str; + return *ptr == 0x01020304; +} + +static int do_swap(struct kbuffer *kbuf) +{ + return ((kbuf->flags & KBUFFER_FL_HOST_BIG_ENDIAN) + kbuf->flags) & + ENDIAN_MASK; +} + +static unsigned long long __read_8(void *ptr) +{ + unsigned long long data = *(unsigned long long *)ptr; + + return data; +} + +static unsigned long long __read_8_sw(void *ptr) +{ + unsigned long long data = *(unsigned long long *)ptr; + unsigned long long swap; + + swap = ((data & 0xffULL) << 56) | + ((data & (0xffULL << 8)) << 40) | + ((data & (0xffULL << 16)) << 24) | + ((data & (0xffULL << 24)) << 8) | + ((data & (0xffULL << 32)) >> 8) | + ((data & (0xffULL << 40)) >> 24) | + ((data & (0xffULL << 48)) >> 40) | + ((data & (0xffULL << 56)) >> 56); + + return swap; +} + +static unsigned int __read_4(void *ptr) +{ + unsigned int data = *(unsigned int *)ptr; + + return data; +} + +static unsigned int __read_4_sw(void *ptr) +{ + unsigned int data = *(unsigned int *)ptr; + unsigned int swap; + + swap = ((data & 0xffULL) << 24) | + ((data & (0xffULL << 8)) << 8) | + ((data & (0xffULL << 16)) >> 8) | + ((data & (0xffULL << 24)) >> 24); + + return swap; +} + +static unsigned long long read_8(struct kbuffer *kbuf, void *ptr) +{ + return kbuf->read_8(ptr); +} + +static unsigned int read_4(struct kbuffer *kbuf, void *ptr) +{ + return kbuf->read_4(ptr); +} + +static unsigned long long __read_long_8(struct kbuffer *kbuf, void *ptr) +{ + return kbuf->read_8(ptr); +} + +static unsigned long long __read_long_4(struct kbuffer *kbuf, void *ptr) +{ + return kbuf->read_4(ptr); +} + +static unsigned long long read_long(struct kbuffer *kbuf, void *ptr) +{ + return kbuf->read_long(kbuf, ptr); +} + +static int calc_index(struct kbuffer *kbuf, void *ptr) +{ + return (unsigned long)ptr - (unsigned long)kbuf->data; +} + +static int __next_event(struct kbuffer *kbuf); + +/** + * kbuffer_alloc - allocat a new kbuffer + * @size; enum to denote size of word + * @endian: enum to denote endianness + * + * Allocates and returns a new kbuffer. + */ +struct kbuffer * +kbuffer_alloc(enum kbuffer_long_size size, enum kbuffer_endian endian) +{ + struct kbuffer *kbuf; + int flags = 0; + + switch (size) { + case KBUFFER_LSIZE_4: + break; + case KBUFFER_LSIZE_8: + flags |= KBUFFER_FL_LONG_8; + break; + default: + return NULL; + } + + switch (endian) { + case KBUFFER_ENDIAN_LITTLE: + break; + case KBUFFER_ENDIAN_BIG: + flags |= KBUFFER_FL_BIG_ENDIAN; + break; + default: + return NULL; + } + + kbuf = zmalloc(sizeof(*kbuf)); + if (!kbuf) + return NULL; + + kbuf->flags = flags; + + if (host_is_bigendian()) + kbuf->flags |= KBUFFER_FL_HOST_BIG_ENDIAN; + + if (do_swap(kbuf)) { + kbuf->read_8 = __read_8_sw; + kbuf->read_4 = __read_4_sw; + } else { + kbuf->read_8 = __read_8; + kbuf->read_4 = __read_4; + } + + if (kbuf->flags & KBUFFER_FL_LONG_8) + kbuf->read_long = __read_long_8; + else + kbuf->read_long = __read_long_4; + + /* May be changed by kbuffer_set_old_format() */ + kbuf->next_event = __next_event; + + return kbuf; +} + +/** kbuffer_free - free an allocated kbuffer + * @kbuf: The kbuffer to free + * + * Can take NULL as a parameter. + */ +void kbuffer_free(struct kbuffer *kbuf) +{ + free(kbuf); +} + +static unsigned int type4host(struct kbuffer *kbuf, + unsigned int type_len_ts) +{ + if (kbuf->flags & KBUFFER_FL_BIG_ENDIAN) + return (type_len_ts >> 29) & 3; + else + return type_len_ts & 3; +} + +static unsigned int len4host(struct kbuffer *kbuf, + unsigned int type_len_ts) +{ + if (kbuf->flags & KBUFFER_FL_BIG_ENDIAN) + return (type_len_ts >> 27) & 7; + else + return (type_len_ts >> 2) & 7; +} + +static unsigned int type_len4host(struct kbuffer *kbuf, + unsigned int type_len_ts) +{ + if (kbuf->flags & KBUFFER_FL_BIG_ENDIAN) + return (type_len_ts >> 27) & ((1 << 5) - 1); + else + return type_len_ts & ((1 << 5) - 1); +} + +static unsigned int ts4host(struct kbuffer *kbuf, + unsigned int type_len_ts) +{ + if (kbuf->flags & KBUFFER_FL_BIG_ENDIAN) + return type_len_ts & ((1 << 27) - 1); + else + return type_len_ts >> 5; +} + +/* + * Linux 2.6.30 and earlier (not much ealier) had a different + * ring buffer format. It should be obsolete, but we handle it anyway. + */ +enum old_ring_buffer_type { + OLD_RINGBUF_TYPE_PADDING, + OLD_RINGBUF_TYPE_TIME_EXTEND, + OLD_RINGBUF_TYPE_TIME_STAMP, + OLD_RINGBUF_TYPE_DATA, +}; + +static unsigned int old_update_pointers(struct kbuffer *kbuf) +{ + unsigned long long extend; + unsigned int type_len_ts; + unsigned int type; + unsigned int len; + unsigned int delta; + unsigned int length; + void *ptr = kbuf->data + kbuf->curr; + + type_len_ts = read_4(kbuf, ptr); + ptr += 4; + + type = type4host(kbuf, type_len_ts); + len = len4host(kbuf, type_len_ts); + delta = ts4host(kbuf, type_len_ts); + + switch (type) { + case OLD_RINGBUF_TYPE_PADDING: + kbuf->next = kbuf->size; + return 0; + + case OLD_RINGBUF_TYPE_TIME_EXTEND: + extend = read_4(kbuf, ptr); + extend <<= TS_SHIFT; + extend += delta; + delta = extend; + ptr += 4; + break; + + case OLD_RINGBUF_TYPE_TIME_STAMP: + /* should never happen! */ + kbuf->curr = kbuf->size; + kbuf->next = kbuf->size; + kbuf->index = kbuf->size; + return -1; + default: + if (len) + length = len * 4; + else { + length = read_4(kbuf, ptr); + length -= 4; + ptr += 4; + } + break; + } + + kbuf->timestamp += delta; + kbuf->index = calc_index(kbuf, ptr); + kbuf->next = kbuf->index + length; + + return type; +} + +static int __old_next_event(struct kbuffer *kbuf) +{ + int type; + + do { + kbuf->curr = kbuf->next; + if (kbuf->next >= kbuf->size) + return -1; + type = old_update_pointers(kbuf); + } while (type == OLD_RINGBUF_TYPE_TIME_EXTEND || type == OLD_RINGBUF_TYPE_PADDING); + + return 0; +} + +static unsigned int +translate_data(struct kbuffer *kbuf, void *data, void **rptr, + unsigned long long *delta, int *length) +{ + unsigned long long extend; + unsigned int type_len_ts; + unsigned int type_len; + + type_len_ts = read_4(kbuf, data); + data += 4; + + type_len = type_len4host(kbuf, type_len_ts); + *delta = ts4host(kbuf, type_len_ts); + + switch (type_len) { + case KBUFFER_TYPE_PADDING: + *length = read_4(kbuf, data); + data += *length; + break; + + case KBUFFER_TYPE_TIME_EXTEND: + extend = read_4(kbuf, data); + data += 4; + extend <<= TS_SHIFT; + extend += *delta; + *delta = extend; + *length = 0; + break; + + case KBUFFER_TYPE_TIME_STAMP: + data += 12; + *length = 0; + break; + case 0: + *length = read_4(kbuf, data) - 4; + *length = (*length + 3) & ~3; + data += 4; + break; + default: + *length = type_len * 4; + break; + } + + *rptr = data; + + return type_len; +} + +static unsigned int update_pointers(struct kbuffer *kbuf) +{ + unsigned long long delta; + unsigned int type_len; + int length; + void *ptr = kbuf->data + kbuf->curr; + + type_len = translate_data(kbuf, ptr, &ptr, &delta, &length); + + kbuf->timestamp += delta; + kbuf->index = calc_index(kbuf, ptr); + kbuf->next = kbuf->index + length; + + return type_len; +} + +/** + * kbuffer_translate_data - read raw data to get a record + * @swap: Set to 1 if bytes in words need to be swapped when read + * @data: The raw data to read + * @size: Address to store the size of the event data. + * + * Returns a pointer to the event data. To determine the entire + * record size (record metadata + data) just add the difference between + * @data and the returned value to @size. + */ +void *kbuffer_translate_data(int swap, void *data, unsigned int *size) +{ + unsigned long long delta; + struct kbuffer kbuf; + int type_len; + int length; + void *ptr; + + if (swap) { + kbuf.read_8 = __read_8_sw; + kbuf.read_4 = __read_4_sw; + kbuf.flags = host_is_bigendian() ? 0 : KBUFFER_FL_BIG_ENDIAN; + } else { + kbuf.read_8 = __read_8; + kbuf.read_4 = __read_4; + kbuf.flags = host_is_bigendian() ? KBUFFER_FL_BIG_ENDIAN: 0; + } + + type_len = translate_data(&kbuf, data, &ptr, &delta, &length); + switch (type_len) { + case KBUFFER_TYPE_PADDING: + case KBUFFER_TYPE_TIME_EXTEND: + case KBUFFER_TYPE_TIME_STAMP: + return NULL; + }; + + *size = length; + + return ptr; +} + +static int __next_event(struct kbuffer *kbuf) +{ + int type; + + do { + kbuf->curr = kbuf->next; + if (kbuf->next >= kbuf->size) + return -1; + type = update_pointers(kbuf); + } while (type == KBUFFER_TYPE_TIME_EXTEND || type == KBUFFER_TYPE_PADDING); + + return 0; +} + +static int next_event(struct kbuffer *kbuf) +{ + return kbuf->next_event(kbuf); +} + +/** + * kbuffer_next_event - increment the current pointer + * @kbuf: The kbuffer to read + * @ts: Address to store the next record's timestamp (may be NULL to ignore) + * + * Increments the pointers into the subbuffer of the kbuffer to point to the + * next event so that the next kbuffer_read_event() will return a + * new event. + * + * Returns the data of the next event if a new event exists on the subbuffer, + * NULL otherwise. + */ +void *kbuffer_next_event(struct kbuffer *kbuf, unsigned long long *ts) +{ + int ret; + + if (!kbuf || !kbuf->subbuffer) + return NULL; + + ret = next_event(kbuf); + if (ret < 0) + return NULL; + + if (ts) + *ts = kbuf->timestamp; + + return kbuf->data + kbuf->index; +} + +/** + * kbuffer_load_subbuffer - load a new subbuffer into the kbuffer + * @kbuf: The kbuffer to load + * @subbuffer: The subbuffer to load into @kbuf. + * + * Load a new subbuffer (page) into @kbuf. This will reset all + * the pointers and update the @kbuf timestamp. The next read will + * return the first event on @subbuffer. + * + * Returns 0 on succes, -1 otherwise. + */ +int kbuffer_load_subbuffer(struct kbuffer *kbuf, void *subbuffer) +{ + unsigned long long flags; + void *ptr = subbuffer; + + if (!kbuf || !subbuffer) + return -1; + + kbuf->subbuffer = subbuffer; + + kbuf->timestamp = read_8(kbuf, ptr); + ptr += 8; + + kbuf->curr = 0; + + if (kbuf->flags & KBUFFER_FL_LONG_8) + kbuf->start = 16; + else + kbuf->start = 12; + + kbuf->data = subbuffer + kbuf->start; + + flags = read_long(kbuf, ptr); + kbuf->size = (unsigned int)flags & COMMIT_MASK; + + if (flags & MISSING_EVENTS) { + if (flags & MISSING_STORED) { + ptr = kbuf->data + kbuf->size; + kbuf->lost_events = read_long(kbuf, ptr); + } else + kbuf->lost_events = -1; + } else + kbuf->lost_events = 0; + + kbuf->index = 0; + kbuf->next = 0; + + next_event(kbuf); + + return 0; +} + +/** + * kbuffer_read_event - read the next event in the kbuffer subbuffer + * @kbuf: The kbuffer to read from + * @ts: The address to store the timestamp of the event (may be NULL to ignore) + * + * Returns a pointer to the data part of the current event. + * NULL if no event is left on the subbuffer. + */ +void *kbuffer_read_event(struct kbuffer *kbuf, unsigned long long *ts) +{ + if (!kbuf || !kbuf->subbuffer) + return NULL; + + if (kbuf->curr >= kbuf->size) + return NULL; + + if (ts) + *ts = kbuf->timestamp; + return kbuf->data + kbuf->index; +} + +/** + * kbuffer_timestamp - Return the timestamp of the current event + * @kbuf: The kbuffer to read from + * + * Returns the timestamp of the current (next) event. + */ +unsigned long long kbuffer_timestamp(struct kbuffer *kbuf) +{ + return kbuf->timestamp; +} + +/** + * kbuffer_read_at_offset - read the event that is at offset + * @kbuf: The kbuffer to read from + * @offset: The offset into the subbuffer + * @ts: The address to store the timestamp of the event (may be NULL to ignore) + * + * The @offset must be an index from the @kbuf subbuffer beginning. + * If @offset is bigger than the stored subbuffer, NULL will be returned. + * + * Returns the data of the record that is at @offset. Note, @offset does + * not need to be the start of the record, the offset just needs to be + * in the record (or beginning of it). + * + * Note, the kbuf timestamp and pointers are updated to the + * returned record. That is, kbuffer_read_event() will return the same + * data and timestamp, and kbuffer_next_event() will increment from + * this record. + */ +void *kbuffer_read_at_offset(struct kbuffer *kbuf, int offset, + unsigned long long *ts) +{ + void *data; + + if (offset < kbuf->start) + offset = 0; + else + offset -= kbuf->start; + + /* Reset the buffer */ + kbuffer_load_subbuffer(kbuf, kbuf->subbuffer); + + while (kbuf->curr < offset) { + data = kbuffer_next_event(kbuf, ts); + if (!data) + break; + } + + return data; +} + +/** + * kbuffer_subbuffer_size - the size of the loaded subbuffer + * @kbuf: The kbuffer to read from + * + * Returns the size of the subbuffer. Note, this size is + * where the last event resides. The stored subbuffer may actually be + * bigger due to padding and such. + */ +int kbuffer_subbuffer_size(struct kbuffer *kbuf) +{ + return kbuf->size; +} + +/** + * kbuffer_curr_index - Return the index of the record + * @kbuf: The kbuffer to read from + * + * Returns the index from the start of the data part of + * the subbuffer to the current location. Note this is not + * from the start of the subbuffer. An index of zero will + * point to the first record. Use kbuffer_curr_offset() for + * the actually offset (that can be used by kbuffer_read_at_offset()) + */ +int kbuffer_curr_index(struct kbuffer *kbuf) +{ + return kbuf->curr; +} + +/** + * kbuffer_curr_offset - Return the offset of the record + * @kbuf: The kbuffer to read from + * + * Returns the offset from the start of the subbuffer to the + * current location. + */ +int kbuffer_curr_offset(struct kbuffer *kbuf) +{ + return kbuf->curr + kbuf->start; +} + +/** + * kbuffer_event_size - return the size of the event data + * @kbuf: The kbuffer to read + * + * Returns the size of the event data (the payload not counting + * the meta data of the record) of the current event. + */ +int kbuffer_event_size(struct kbuffer *kbuf) +{ + return kbuf->next - kbuf->index; +} + +/** + * kbuffer_curr_size - return the size of the entire record + * @kbuf: The kbuffer to read + * + * Returns the size of the entire record (meta data and payload) + * of the current event. + */ +int kbuffer_curr_size(struct kbuffer *kbuf) +{ + return kbuf->next - kbuf->curr; +} + +/** + * kbuffer_missed_events - return the # of missed events from last event. + * @kbuf: The kbuffer to read from + * + * Returns the # of missed events (if recorded) before the current + * event. Note, only events on the beginning of a subbuffer can + * have missed events, all other events within the buffer will be + * zero. + */ +int kbuffer_missed_events(struct kbuffer *kbuf) +{ + /* Only the first event can have missed events */ + if (kbuf->curr) + return 0; + + return kbuf->lost_events; +} + +/** + * kbuffer_set_old_forma - set the kbuffer to use the old format parsing + * @kbuf: The kbuffer to set + * + * This is obsolete (or should be). The first kernels to use the + * new ring buffer had a slightly different ring buffer format + * (2.6.30 and earlier). It is still somewhat supported by kbuffer, + * but should not be counted on in the future. + */ +void kbuffer_set_old_format(struct kbuffer *kbuf) +{ + kbuf->flags |= KBUFFER_FL_OLD_FORMAT; + + kbuf->next_event = __old_next_event; +} diff --git a/tools/lib/traceevent/kbuffer.h b/tools/lib/traceevent/kbuffer.h new file mode 100644 index 000000000000..c831f64b17a0 --- /dev/null +++ b/tools/lib/traceevent/kbuffer.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2012 Red Hat Inc, Steven Rostedt + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * 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; + * version 2.1 of the License (not later!) + * + * 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 program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ +#ifndef _KBUFFER_H +#define _KBUFFER_H + +#ifndef TS_SHIFT +#define TS_SHIFT 27 +#endif + +enum kbuffer_endian { + KBUFFER_ENDIAN_BIG, + KBUFFER_ENDIAN_LITTLE, +}; + +enum kbuffer_long_size { + KBUFFER_LSIZE_4, + KBUFFER_LSIZE_8, +}; + +enum { + KBUFFER_TYPE_PADDING = 29, + KBUFFER_TYPE_TIME_EXTEND = 30, + KBUFFER_TYPE_TIME_STAMP = 31, +}; + +struct kbuffer; + +struct kbuffer *kbuffer_alloc(enum kbuffer_long_size size, enum kbuffer_endian endian); +void kbuffer_free(struct kbuffer *kbuf); +int kbuffer_load_subbuffer(struct kbuffer *kbuf, void *subbuffer); +void *kbuffer_read_event(struct kbuffer *kbuf, unsigned long long *ts); +void *kbuffer_next_event(struct kbuffer *kbuf, unsigned long long *ts); +unsigned long long kbuffer_timestamp(struct kbuffer *kbuf); + +void *kbuffer_translate_data(int swap, void *data, unsigned int *size); + +void *kbuffer_read_at_offset(struct kbuffer *kbuf, int offset, unsigned long long *ts); + +int kbuffer_curr_index(struct kbuffer *kbuf); + +int kbuffer_curr_offset(struct kbuffer *kbuf); +int kbuffer_curr_size(struct kbuffer *kbuf); +int kbuffer_event_size(struct kbuffer *kbuf); +int kbuffer_missed_events(struct kbuffer *kbuf); +int kbuffer_subbuffer_size(struct kbuffer *kbuf); + +void kbuffer_set_old_format(struct kbuffer *kbuf); + +#endif /* _K_BUFFER_H */ From 30f36762aab575f2894f7528d91ecd0b6e26e3e4 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 4 Jun 2013 14:20:22 +0900 Subject: [PATCH 0033/3400] perf util: Save page size in a trace file to pevent We now have page_size field in struct pevent, save the actual size of the system. Signed-off-by: Namhyung Kim Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1370323231-14022-8-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/trace-event-read.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c index af215c0d2379..c6b491bcb8cd 100644 --- a/tools/perf/util/trace-event-read.c +++ b/tools/perf/util/trace-event-read.c @@ -349,6 +349,7 @@ ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe) int show_funcs = 0; int show_printk = 0; ssize_t size = -1; + int file_page_size; struct pevent *pevent; int err; @@ -393,10 +394,12 @@ ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe) goto out; long_size = buf[0]; - page_size = read4(pevent); - if (!page_size) + file_page_size = read4(pevent); + if (!file_page_size) goto out; + pevent_set_page_size(pevent, file_page_size); + err = read_header_files(pevent); if (err) goto out; From 59657f9c8dd91363f1c94c1f749b33ecf626cfc2 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 4 Jun 2013 14:20:23 +0900 Subject: [PATCH 0034/3400] perf util: Save long size of traced system Save size of long type of system to struct pevent. Since original static variable was not used anywhere, just get rid of it. Signed-off-by: Namhyung Kim Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1370323231-14022-9-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/trace-event-read.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c index c6b491bcb8cd..6166294d7f22 100644 --- a/tools/perf/util/trace-event-read.c +++ b/tools/perf/util/trace-event-read.c @@ -41,7 +41,6 @@ static int input_fd; int file_bigendian; int host_bigendian; -static int long_size; static ssize_t trace_data_size; static bool repipe; @@ -231,12 +230,6 @@ static int read_header_files(struct pevent *pevent) size = read8(pevent); skip(size); - /* - * The size field in the page is of type long, - * use that instead, since it represents the kernel. - */ - long_size = header_page_size_size; - if (do_read(buf, 13) < 0) return -1; @@ -349,6 +342,7 @@ ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe) int show_funcs = 0; int show_printk = 0; ssize_t size = -1; + int file_long_size; int file_page_size; struct pevent *pevent; int err; @@ -392,12 +386,13 @@ ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe) if (do_read(buf, 1) < 0) goto out; - long_size = buf[0]; + file_long_size = buf[0]; file_page_size = read4(pevent); if (!file_page_size) goto out; + pevent_set_long_size(pevent, file_long_size); pevent_set_page_size(pevent, file_page_size); err = read_header_files(pevent); From 63af28fa167374e470c32570b7c955c4d973dda4 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 4 Jun 2013 14:20:24 +0900 Subject: [PATCH 0035/3400] perf util: Make file/host_bigendian variable local They're not used anywhere, just make them local variables. Signed-off-by: Namhyung Kim Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1370323231-14022-10-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/trace-event-read.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c index 6166294d7f22..0dd9fbda88eb 100644 --- a/tools/perf/util/trace-event-read.c +++ b/tools/perf/util/trace-event-read.c @@ -39,9 +39,6 @@ static int input_fd; -int file_bigendian; -int host_bigendian; - static ssize_t trace_data_size; static bool repipe; @@ -342,6 +339,8 @@ ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe) int show_funcs = 0; int show_printk = 0; ssize_t size = -1; + int file_bigendian; + int host_bigendian; int file_long_size; int file_page_size; struct pevent *pevent; From 2b2efc7fb8a3ede936580e870c5f809e491c925c Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 4 Jun 2013 14:20:25 +0900 Subject: [PATCH 0036/3400] perf util: Skip reading header_event file It seems perf does not parse header_event file so we can skip it as we do for header_page file. Signed-off-by: Namhyung Kim Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1370323231-14022-11-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/trace-event-read.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c index 0dd9fbda88eb..fa45fca2a2d3 100644 --- a/tools/perf/util/trace-event-read.c +++ b/tools/perf/util/trace-event-read.c @@ -212,7 +212,6 @@ static int read_ftrace_printk(struct pevent *pevent) static int read_header_files(struct pevent *pevent) { unsigned long long size; - char *header_event; char buf[BUFSIZ]; int ret = 0; @@ -236,14 +235,8 @@ static int read_header_files(struct pevent *pevent) } size = read8(pevent); - header_event = malloc(size); - if (header_event == NULL) - return -1; + skip(size); - if (do_read(header_event, size) < 0) - ret = -1; - - free(header_event); return ret; } From 94b4d89e0021fe3e10415feede364a3fccaa2f89 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 4 Jun 2013 14:20:26 +0900 Subject: [PATCH 0037/3400] perf util: Parse header_page to get proper long size The header_page file describes the format of the ring buffer page which is used by ftrace (not perf). And size of "commit" field (I guess it's older name was 'size') represents the real size of long type used for kernel. So update the pevent's long size. Signed-off-by: Namhyung Kim Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1370323231-14022-12-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/trace-event-read.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c index fa45fca2a2d3..f2112270c663 100644 --- a/tools/perf/util/trace-event-read.c +++ b/tools/perf/util/trace-event-read.c @@ -212,6 +212,7 @@ static int read_ftrace_printk(struct pevent *pevent) static int read_header_files(struct pevent *pevent) { unsigned long long size; + char *header_page; char buf[BUFSIZ]; int ret = 0; @@ -224,7 +225,26 @@ static int read_header_files(struct pevent *pevent) } size = read8(pevent); - skip(size); + + header_page = malloc(size); + if (header_page == NULL) + return -1; + + if (do_read(header_page, size) < 0) { + pr_debug("did not read header page"); + free(header_page); + return -1; + } + + if (!pevent_parse_header_page(pevent, header_page, size, + pevent_get_long_size(pevent))) { + /* + * The commit field in the page is of type long, + * use that instead, since it represents the kernel. + */ + pevent_set_long_size(pevent, pevent->header_page_size_size); + } + free(header_page); if (do_read(buf, 13) < 0) return -1; From 9515b2eb7670a98fb9bdd8ceeefeea6ffb9f53fc Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 4 Jun 2013 14:20:27 +0900 Subject: [PATCH 0038/3400] perf util: Get rid of unused header_page_* variables They're not used anywhere and same information is kept in a pevent already. So let's get rid of them. Signed-off-by: Namhyung Kim Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1370323231-14022-13-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/trace-event-parse.c | 4 ---- tools/perf/util/trace-event.h | 4 ---- 2 files changed, 8 deletions(-) diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index 4454835a9ebc..0deae885c7ba 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c @@ -28,10 +28,6 @@ #include "util.h" #include "trace-event.h" -int header_page_size_size; -int header_page_ts_size; -int header_page_data_offset; - bool latency_format; struct pevent *read_trace_init(int file_bigendian, int host_bigendian) diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h index 11eb7fd37608..761c4846e0c7 100644 --- a/tools/perf/util/trace-event.h +++ b/tools/perf/util/trace-event.h @@ -10,10 +10,6 @@ struct perf_sample; union perf_event; struct perf_tool; -extern int header_page_size_size; -extern int header_page_ts_size; -extern int header_page_data_offset; - extern bool latency_format; extern struct pevent *perf_pevent; From 47390ae2afb6695c56810a9fc74fb930266addd0 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 4 Jun 2013 14:20:28 +0900 Subject: [PATCH 0039/3400] perf script: Adopt latency_format variable It's the only user of the variable, so move it. Signed-off-by: Namhyung Kim Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1370323231-14022-14-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 1 + tools/perf/util/trace-event-parse.c | 2 -- tools/perf/util/trace-event.h | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 92d4658f56fb..3de8979fe87d 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -24,6 +24,7 @@ static u64 last_timestamp; static u64 nr_unordered; extern const struct option record_options[]; static bool no_callchain; +static bool latency_format; static bool system_wide; static const char *cpu_list; static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index 0deae885c7ba..fe7a27d67d2b 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c @@ -28,8 +28,6 @@ #include "util.h" #include "trace-event.h" -bool latency_format; - struct pevent *read_trace_init(int file_bigendian, int host_bigendian) { struct pevent *pevent = pevent_alloc(); diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h index 761c4846e0c7..ed30c9c09cd0 100644 --- a/tools/perf/util/trace-event.h +++ b/tools/perf/util/trace-event.h @@ -10,7 +10,6 @@ struct perf_sample; union perf_event; struct perf_tool; -extern bool latency_format; extern struct pevent *perf_pevent; enum { From 077f159d0402ac90a3ea9975f4089a042e0be065 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 4 Jun 2013 14:20:29 +0900 Subject: [PATCH 0040/3400] perf util: Rename read_*() functions in trace-event-info.c It's confusing to have same name for two difference functions which does something opposite way. Since what they do in this file is read *AND* writing some of tracing metadata files, rename them to record_*() looks better to me. Signed-off-by: Namhyung Kim Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1370323231-14022-15-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/trace-event-info.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c index a42624a6cb5c..a800f2b8ccfc 100644 --- a/tools/perf/util/trace-event-info.c +++ b/tools/perf/util/trace-event-info.c @@ -101,7 +101,7 @@ out: return err; } -static int read_header_files(void) +static int record_header_files(void) { char *path; struct stat st; @@ -240,7 +240,7 @@ out: return err; } -static int read_ftrace_files(struct tracepoint_path *tps) +static int record_ftrace_files(struct tracepoint_path *tps) { char *path; int ret; @@ -269,7 +269,7 @@ static bool system_in_tp_list(char *sys, struct tracepoint_path *tps) return false; } -static int read_event_files(struct tracepoint_path *tps) +static int record_event_files(struct tracepoint_path *tps) { struct dirent *dent; struct stat st; @@ -344,7 +344,7 @@ out: return err; } -static int read_proc_kallsyms(void) +static int record_proc_kallsyms(void) { unsigned int size; const char *path = "/proc/kallsyms"; @@ -362,7 +362,7 @@ static int read_proc_kallsyms(void) return record_file(path, 4); } -static int read_ftrace_printk(void) +static int record_ftrace_printk(void) { unsigned int size; char *path; @@ -539,19 +539,19 @@ struct tracing_data *tracing_data_get(struct list_head *pattrs, err = tracing_data_header(); if (err) goto out; - err = read_header_files(); + err = record_header_files(); if (err) goto out; - err = read_ftrace_files(tps); + err = record_ftrace_files(tps); if (err) goto out; - err = read_event_files(tps); + err = record_event_files(tps); if (err) goto out; - err = read_proc_kallsyms(); + err = record_proc_kallsyms(); if (err) goto out; - err = read_ftrace_printk(); + err = record_ftrace_printk(); out: /* From cfd0e8cf7fe7ad6f6c08e23ca4410bd718eeaf0b Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 4 Jun 2013 14:20:30 +0900 Subject: [PATCH 0041/3400] perf util: No need to call read_trace_init() in tracing_data_header() It's useless to call the read_trace_init() function at this time as we don't need a returned pevent and it makes me confusing. :) Signed-off-by: Namhyung Kim Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1370323231-14022-16-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/trace-event-info.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c index a800f2b8ccfc..f3c9e551bd35 100644 --- a/tools/perf/util/trace-event-info.c +++ b/tools/perf/util/trace-event-info.c @@ -476,8 +476,6 @@ static int tracing_data_header(void) else buf[0] = 0; - read_trace_init(buf[0], buf[0]); - if (write(output_fd, buf, 1) != 1) return -1; From 45a9ee1b3fa2d8c3fb7a0c7e5a7b77281a4239a6 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 4 Jun 2013 14:20:31 +0900 Subject: [PATCH 0042/3400] perf util: Remove unused enum and macro in trace-event.h They're internals of ftrace ring-buffer and not used in perf code directly. As it now resides on libtraceevent/kbuffer.h, just get rid of them. Signed-off-by: Namhyung Kim Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1370323231-14022-17-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/trace-event.h | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h index ed30c9c09cd0..669a64a660d7 100644 --- a/tools/perf/util/trace-event.h +++ b/tools/perf/util/trace-event.h @@ -12,16 +12,6 @@ struct perf_tool; extern struct pevent *perf_pevent; -enum { - RINGBUF_TYPE_PADDING = 29, - RINGBUF_TYPE_TIME_EXTEND = 30, - RINGBUF_TYPE_TIME_STAMP = 31, -}; - -#ifndef TS_SHIFT -#define TS_SHIFT 27 -#endif - int bigendian(void); struct pevent *read_trace_init(int file_bigendian, int host_bigendian); From f36f83f947ede547833e462696893f866df77324 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 4 Jun 2013 14:46:19 +0900 Subject: [PATCH 0043/3400] perf sched: Move struct perf_sched definition out of cmd_sched() For some reason it consumed quite amount of compile time when declared as local variable, and it disappeared when moved out of the function. Moving other variables/tables didn't help. On my system this single-file-change build time reduced from 11s to 3s. Signed-off-by: Namhyung Kim Cc: David Ahern Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1370324779-16921-1-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-sched.c | 41 +++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index fed9ae432c16..fba4a940ba31 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -1662,28 +1662,29 @@ static int __cmd_record(int argc, const char **argv) return cmd_record(i, rec_argv, NULL); } +static const char default_sort_order[] = "avg, max, switch, runtime"; +static struct perf_sched sched = { + .tool = { + .sample = perf_sched__process_tracepoint_sample, + .comm = perf_event__process_comm, + .lost = perf_event__process_lost, + .fork = perf_event__process_fork, + .ordered_samples = true, + }, + .cmp_pid = LIST_HEAD_INIT(sched.cmp_pid), + .sort_list = LIST_HEAD_INIT(sched.sort_list), + .start_work_mutex = PTHREAD_MUTEX_INITIALIZER, + .work_done_wait_mutex = PTHREAD_MUTEX_INITIALIZER, + .curr_pid = { [0 ... MAX_CPUS - 1] = -1 }, + .sort_order = default_sort_order, + .replay_repeat = 10, + .profile_cpu = -1, + .next_shortname1 = 'A', + .next_shortname2 = '0', +}; + int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused) { - const char default_sort_order[] = "avg, max, switch, runtime"; - struct perf_sched sched = { - .tool = { - .sample = perf_sched__process_tracepoint_sample, - .comm = perf_event__process_comm, - .lost = perf_event__process_lost, - .fork = perf_event__process_fork, - .ordered_samples = true, - }, - .cmp_pid = LIST_HEAD_INIT(sched.cmp_pid), - .sort_list = LIST_HEAD_INIT(sched.sort_list), - .start_work_mutex = PTHREAD_MUTEX_INITIALIZER, - .work_done_wait_mutex = PTHREAD_MUTEX_INITIALIZER, - .curr_pid = { [0 ... MAX_CPUS - 1] = -1 }, - .sort_order = default_sort_order, - .replay_repeat = 10, - .profile_cpu = -1, - .next_shortname1 = 'A', - .next_shortname2 = '0', - }; const struct option latency_options[] = { OPT_STRING('s', "sort", &sched.sort_order, "key[,key2...]", "sort by key(s): runtime, switch, avg, max"), From f1d9a530553eed9e598d1597a2a348f01810dd4a Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 4 Jun 2013 18:22:12 +0900 Subject: [PATCH 0044/3400] perf gtk/hists: Use GtkTreeStore instead of GtkListStore The GtkTreeStore can save items in a tree-like way. This is a preparation for supporting callgraphs in the hist browser. Reviewed-by: Pekka Enberg Signed-off-by: Namhyung Kim Cc: David Ahern Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Pekka Enberg Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1370337737-30812-2-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/gtk/hists.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c index 9708dd5fb8f3..cb6a9b45f789 100644 --- a/tools/perf/ui/gtk/hists.c +++ b/tools/perf/ui/gtk/hists.c @@ -131,7 +131,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists, GType col_types[MAX_COLUMNS]; GtkCellRenderer *renderer; struct sort_entry *se; - GtkListStore *store; + GtkTreeStore *store; struct rb_node *nd; GtkWidget *view; int col_idx; @@ -156,7 +156,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists, col_types[nr_cols++] = G_TYPE_STRING; } - store = gtk_list_store_newv(nr_cols, col_types); + store = gtk_tree_store_newv(nr_cols, col_types); view = gtk_tree_view_new(); @@ -199,7 +199,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists, if (percent < min_pcnt) continue; - gtk_list_store_append(store, &iter); + gtk_tree_store_append(store, &iter, NULL); col_idx = 0; @@ -209,7 +209,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists, else fmt->entry(&hpp, h); - gtk_list_store_set(store, &iter, col_idx++, s, -1); + gtk_tree_store_set(store, &iter, col_idx++, s, -1); } list_for_each_entry(se, &hist_entry__sort_list, list) { @@ -219,7 +219,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists, se->se_snprintf(h, s, ARRAY_SIZE(s), hists__col_len(hists, se->se_width_idx)); - gtk_list_store_set(store, &iter, col_idx++, s, -1); + gtk_tree_store_set(store, &iter, col_idx++, s, -1); } } From 2bbc5874251830fee170a0fc97fa5788717d2fd9 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 4 Jun 2013 18:22:13 +0900 Subject: [PATCH 0045/3400] perf gtk/hists: Add support for callchains Display callchain information in the symbol column. It's only enabled when recorded with -g and has symbol sort key. Reviewed-by: Pekka Enberg Signed-off-by: Namhyung Kim Cc: David Ahern Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Pekka Enberg Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1370337737-30812-3-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/gtk/hists.c | 65 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c index cb6a9b45f789..226c7e10f3cc 100644 --- a/tools/perf/ui/gtk/hists.c +++ b/tools/perf/ui/gtk/hists.c @@ -124,6 +124,55 @@ void perf_gtk__init_hpp(void) perf_gtk__hpp_color_overhead_guest_us; } +static void callchain_list__sym_name(struct callchain_list *cl, + char *bf, size_t bfsize) +{ + if (cl->ms.sym) + scnprintf(bf, bfsize, "%s", cl->ms.sym->name); + else + scnprintf(bf, bfsize, "%#" PRIx64, cl->ip); +} + +static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store, + GtkTreeIter *parent, int col) +{ + struct rb_node *nd; + bool has_single_node = (rb_first(root) == rb_last(root)); + + for (nd = rb_first(root); nd; nd = rb_next(nd)) { + struct callchain_node *node; + struct callchain_list *chain; + GtkTreeIter iter, new_parent; + bool need_new_parent; + + node = rb_entry(nd, struct callchain_node, rb_node); + + new_parent = *parent; + need_new_parent = !has_single_node && (node->val_nr > 1); + + list_for_each_entry(chain, &node->val, list) { + char buf[128]; + + gtk_tree_store_append(store, &iter, &new_parent); + + callchain_list__sym_name(chain, buf, sizeof(buf)); + gtk_tree_store_set(store, &iter, col, buf, -1); + + if (need_new_parent) { + /* + * Only show the top-most symbol in a callchain + * if it's not the only callchain. + */ + new_parent = iter; + need_new_parent = false; + } + } + + /* Now 'iter' contains info of the last callchain_list */ + perf_gtk__add_callchain(&node->rb_root, store, &iter, col); + } +} + static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists, float min_pcnt) { @@ -135,6 +184,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists, struct rb_node *nd; GtkWidget *view; int col_idx; + int sym_col = -1; int nr_cols; char s[512]; @@ -153,6 +203,9 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists, if (se->elide) continue; + if (se == &sort_sym) + sym_col = nr_cols; + col_types[nr_cols++] = G_TYPE_STRING; } @@ -183,6 +236,13 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists, col_idx++, NULL); } + if (symbol_conf.use_callchain && sort__has_sym) { + GtkTreeViewColumn *column; + + column = gtk_tree_view_get_column(GTK_TREE_VIEW(view), sym_col); + gtk_tree_view_set_expander_column(GTK_TREE_VIEW(view), column); + } + gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store)); g_object_unref(GTK_TREE_MODEL(store)); @@ -221,6 +281,11 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists, gtk_tree_store_set(store, &iter, col_idx++, s, -1); } + + if (symbol_conf.use_callchain && sort__has_sym) { + perf_gtk__add_callchain(&h->sorted_chain, store, &iter, + sym_col); + } } gtk_container_add(GTK_CONTAINER(window), view); From cc60f24e225e50a0b57398f9ba105fd8ffcf4bb3 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 4 Jun 2013 18:22:14 +0900 Subject: [PATCH 0046/3400] perf gtk/hists: Display callchain overhead also Display callchain percent value in the overhead column. Signed-off-by: Namhyung Kim Reviewed-by: Pekka Enberg Cc: David Ahern Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Pekka Enberg Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1370337737-30812-4-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/gtk/hists.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c index 226c7e10f3cc..fa9f8a09233e 100644 --- a/tools/perf/ui/gtk/hists.c +++ b/tools/perf/ui/gtk/hists.c @@ -134,7 +134,7 @@ static void callchain_list__sym_name(struct callchain_list *cl, } static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store, - GtkTreeIter *parent, int col) + GtkTreeIter *parent, int col, u64 total) { struct rb_node *nd; bool has_single_node = (rb_first(root) == rb_last(root)); @@ -144,9 +144,14 @@ static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store, struct callchain_list *chain; GtkTreeIter iter, new_parent; bool need_new_parent; + double percent; + u64 hits, child_total; node = rb_entry(nd, struct callchain_node, rb_node); + hits = callchain_cumul_hits(node); + percent = 100.0 * hits / total; + new_parent = *parent; need_new_parent = !has_single_node && (node->val_nr > 1); @@ -155,6 +160,9 @@ static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store, gtk_tree_store_append(store, &iter, &new_parent); + scnprintf(buf, sizeof(buf), "%5.2f%%", percent); + gtk_tree_store_set(store, &iter, 0, buf, -1); + callchain_list__sym_name(chain, buf, sizeof(buf)); gtk_tree_store_set(store, &iter, col, buf, -1); @@ -168,8 +176,14 @@ static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store, } } + if (callchain_param.mode == CHAIN_GRAPH_REL) + child_total = node->children_hit; + else + child_total = total; + /* Now 'iter' contains info of the last callchain_list */ - perf_gtk__add_callchain(&node->rb_root, store, &iter, col); + perf_gtk__add_callchain(&node->rb_root, store, &iter, col, + child_total); } } @@ -283,8 +297,15 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists, } if (symbol_conf.use_callchain && sort__has_sym) { + u64 total; + + if (callchain_param.mode == CHAIN_GRAPH_REL) + total = h->stat.period; + else + total = hists->stats.total_period; + perf_gtk__add_callchain(&h->sorted_chain, store, &iter, - sym_col); + sym_col, total); } } From 1a309426b4fae258dbd86ac0c575a849bf163b7b Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 4 Jun 2013 18:22:15 +0900 Subject: [PATCH 0047/3400] perf gtk/hists: Make column headers resizable Sometimes it's annoying to see when some symbols have very wierd long names. So it might be a good idea to make column size changable. Reviewed-by: Pekka Enberg Signed-off-by: Namhyung Kim Cc: David Ahern Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Pekka Enberg Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1370337737-30812-5-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/gtk/hists.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c index fa9f8a09233e..b4a0dd2404a2 100644 --- a/tools/perf/ui/gtk/hists.c +++ b/tools/perf/ui/gtk/hists.c @@ -250,11 +250,16 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists, col_idx++, NULL); } - if (symbol_conf.use_callchain && sort__has_sym) { + for (col_idx = 0; col_idx < nr_cols; col_idx++) { GtkTreeViewColumn *column; - column = gtk_tree_view_get_column(GTK_TREE_VIEW(view), sym_col); - gtk_tree_view_set_expander_column(GTK_TREE_VIEW(view), column); + column = gtk_tree_view_get_column(GTK_TREE_VIEW(view), col_idx); + gtk_tree_view_column_set_resizable(column, TRUE); + + if (col_idx == sym_col) { + gtk_tree_view_set_expander_column(GTK_TREE_VIEW(view), + column); + } } gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store)); From 450f390ad2538c5e35d830fa5c624708a77dce0a Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 4 Jun 2013 18:22:16 +0900 Subject: [PATCH 0048/3400] perf gtk/hists: Add a double-click handler for callchains If callchain is displayed, add "row-activated" signal handler for handling double-click or pressing ENTER key action. Reviewed-by: Pekka Enberg Signed-off-by: Namhyung Kim Cc: David Ahern Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Pekka Enberg Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1370337737-30812-6-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/gtk/hists.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c index b4a0dd2404a2..3a5d01319988 100644 --- a/tools/perf/ui/gtk/hists.c +++ b/tools/perf/ui/gtk/hists.c @@ -187,6 +187,18 @@ static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store, } } +static void on_row_activated(GtkTreeView *view, GtkTreePath *path, + GtkTreeViewColumn *col __maybe_unused, + gpointer user_data __maybe_unused) +{ + bool expanded = gtk_tree_view_row_expanded(view, path); + + if (expanded) + gtk_tree_view_collapse_row(view, path); + else + gtk_tree_view_expand_row(view, path, FALSE); +} + static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists, float min_pcnt) { @@ -314,6 +326,8 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists, } } + g_signal_connect(view, "row-activated", + G_CALLBACK(on_row_activated), NULL); gtk_container_add(GTK_CONTAINER(window), view); } From 9d58d2f66c92fe47dd395947a3d51b9ace7dcc92 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 4 Jun 2013 18:22:17 +0900 Subject: [PATCH 0049/3400] perf gtk/hists: Set rules hint for the hist browser The 'rules' means that every second line of the tree view has a shaded background, which makes it easier to see which cell belongs to which row in the tree view. It can be useful for a tree view that has a lot of rows. Reviewed-by: Pekka Enberg Signed-off-by: Namhyung Kim Cc: David Ahern Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Pekka Enberg Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1370337737-30812-7-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/gtk/hists.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c index 3a5d01319988..32549035f50d 100644 --- a/tools/perf/ui/gtk/hists.c +++ b/tools/perf/ui/gtk/hists.c @@ -326,6 +326,8 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists, } } + gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(view), TRUE); + g_signal_connect(view, "row-activated", G_CALLBACK(on_row_activated), NULL); gtk_container_add(GTK_CONTAINER(window), view); From 63c2c9f8f24378ebf46d4a9d542863bb733ef05c Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 4 Jul 2013 16:20:20 +0300 Subject: [PATCH 0050/3400] perf inject: Remove unused parameter The 'machine' parameter is unused in 'perf_event__repipe_synth()' and some callers pass NULL anyway. So remove it. Signed-off-by: Adrian Hunter Acked-by: Jiri Olsa Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1372944040-32690-2-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-inject.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index 84ad6abe4258..f299ddf29967 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -38,8 +38,7 @@ struct event_entry { }; static int perf_event__repipe_synth(struct perf_tool *tool, - union perf_event *event, - struct machine *machine __maybe_unused) + union perf_event *event) { struct perf_inject *inject = container_of(tool, struct perf_inject, tool); uint32_t size; @@ -65,20 +64,20 @@ static int perf_event__repipe_op2_synth(struct perf_tool *tool, struct perf_session *session __maybe_unused) { - return perf_event__repipe_synth(tool, event, NULL); + return perf_event__repipe_synth(tool, event); } static int perf_event__repipe_event_type_synth(struct perf_tool *tool, union perf_event *event) { - return perf_event__repipe_synth(tool, event, NULL); + return perf_event__repipe_synth(tool, event); } static int perf_event__repipe_tracing_data_synth(union perf_event *event, struct perf_session *session __maybe_unused) { - return perf_event__repipe_synth(NULL, event, NULL); + return perf_event__repipe_synth(NULL, event); } static int perf_event__repipe_attr(union perf_event *event, @@ -89,15 +88,15 @@ static int perf_event__repipe_attr(union perf_event *event, if (ret) return ret; - return perf_event__repipe_synth(NULL, event, NULL); + return perf_event__repipe_synth(NULL, event); } static int perf_event__repipe(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample __maybe_unused, - struct machine *machine) + struct machine *machine __maybe_unused) { - return perf_event__repipe_synth(tool, event, machine); + return perf_event__repipe_synth(tool, event); } typedef int (*inject_handler)(struct perf_tool *tool, @@ -119,7 +118,7 @@ static int perf_event__repipe_sample(struct perf_tool *tool, build_id__mark_dso_hit(tool, event, sample, evsel, machine); - return perf_event__repipe_synth(tool, event, machine); + return perf_event__repipe_synth(tool, event); } static int perf_event__repipe_mmap(struct perf_tool *tool, @@ -153,7 +152,7 @@ static int perf_event__repipe_tracing_data(union perf_event *event, { int err; - perf_event__repipe_synth(NULL, event, NULL); + perf_event__repipe_synth(NULL, event); err = perf_event__process_tracing_data(event, session); return err; From 47c3d1091cb68e727b840efd6fa3709d5b1ddfc2 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 4 Jul 2013 16:20:21 +0300 Subject: [PATCH 0051/3400] perf tools: Fix missing tool parameter The 'inject' command expects to get a reference to 'struct perf_inject' from its 'tool' member. For that to work, 'tool' needs to be a parameter of all tool callbacks. Make it so. Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1372944040-32690-3-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-inject.c | 26 +++++++++++--------------- tools/perf/util/header.c | 6 ++++-- tools/perf/util/header.h | 6 ++++-- tools/perf/util/session.c | 11 +++++++---- tools/perf/util/tool.h | 9 ++++----- 5 files changed, 30 insertions(+), 28 deletions(-) diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index f299ddf29967..c943513d06be 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -73,22 +73,17 @@ static int perf_event__repipe_event_type_synth(struct perf_tool *tool, return perf_event__repipe_synth(tool, event); } -static int perf_event__repipe_tracing_data_synth(union perf_event *event, - struct perf_session *session - __maybe_unused) -{ - return perf_event__repipe_synth(NULL, event); -} - -static int perf_event__repipe_attr(union perf_event *event, - struct perf_evlist **pevlist __maybe_unused) +static int perf_event__repipe_attr(struct perf_tool *tool, + union perf_event *event, + struct perf_evlist **pevlist) { int ret; - ret = perf_event__process_attr(event, pevlist); + + ret = perf_event__process_attr(tool, event, pevlist); if (ret) return ret; - return perf_event__repipe_synth(NULL, event); + return perf_event__repipe_synth(tool, event); } static int perf_event__repipe(struct perf_tool *tool, @@ -147,13 +142,14 @@ static int perf_event__repipe_fork(struct perf_tool *tool, return err; } -static int perf_event__repipe_tracing_data(union perf_event *event, +static int perf_event__repipe_tracing_data(struct perf_tool *tool, + union perf_event *event, struct perf_session *session) { int err; - perf_event__repipe_synth(NULL, event); - err = perf_event__process_tracing_data(event, session); + perf_event__repipe_synth(tool, event); + err = perf_event__process_tracing_data(tool, event, session); return err; } @@ -407,7 +403,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) .unthrottle = perf_event__repipe, .attr = perf_event__repipe_attr, .event_type = perf_event__repipe_event_type_synth, - .tracing_data = perf_event__repipe_tracing_data_synth, + .tracing_data = perf_event__repipe_op2_synth, .build_id = perf_event__repipe_op2_synth, }, .input_name = "-", diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index a4dafbee2511..d12d79cf8d32 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -2922,7 +2922,8 @@ int perf_event__synthesize_attrs(struct perf_tool *tool, return err; } -int perf_event__process_attr(union perf_event *event, +int perf_event__process_attr(struct perf_tool *tool __maybe_unused, + union perf_event *event, struct perf_evlist **pevlist) { u32 i, ids, n_ids; @@ -3065,7 +3066,8 @@ int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd, return aligned_size; } -int perf_event__process_tracing_data(union perf_event *event, +int perf_event__process_tracing_data(struct perf_tool *tool __maybe_unused, + union perf_event *event, struct perf_session *session) { ssize_t size_read, padding, size = event->tracing_data.size; diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index 16a3e83c584e..2d1ca7d3ca9c 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h @@ -130,7 +130,8 @@ int perf_event__synthesize_attr(struct perf_tool *tool, int perf_event__synthesize_attrs(struct perf_tool *tool, struct perf_session *session, perf_event__handler_t process); -int perf_event__process_attr(union perf_event *event, struct perf_evlist **pevlist); +int perf_event__process_attr(struct perf_tool *tool, union perf_event *event, + struct perf_evlist **pevlist); int perf_event__synthesize_event_type(struct perf_tool *tool, u64 event_id, char *name, @@ -145,7 +146,8 @@ int perf_event__process_event_type(struct perf_tool *tool, int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd, struct perf_evlist *evlist, perf_event__handler_t process); -int perf_event__process_tracing_data(union perf_event *event, +int perf_event__process_tracing_data(struct perf_tool *tool, + union perf_event *event, struct perf_session *session); int perf_event__synthesize_build_id(struct perf_tool *tool, diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index ad47fb9d0204..6b71b88f95fa 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -193,7 +193,9 @@ void perf_session__delete(struct perf_session *self) vdso__exit(); } -static int process_event_synth_tracing_data_stub(union perf_event *event +static int process_event_synth_tracing_data_stub(struct perf_tool *tool + __maybe_unused, + union perf_event *event __maybe_unused, struct perf_session *session __maybe_unused) @@ -202,7 +204,8 @@ static int process_event_synth_tracing_data_stub(union perf_event *event return 0; } -static int process_event_synth_attr_stub(union perf_event *event __maybe_unused, +static int process_event_synth_attr_stub(struct perf_tool *tool __maybe_unused, + union perf_event *event __maybe_unused, struct perf_evlist **pevlist __maybe_unused) { @@ -921,7 +924,7 @@ static int perf_session__process_user_event(struct perf_session *session, union /* These events are processed right away */ switch (event->header.type) { case PERF_RECORD_HEADER_ATTR: - err = tool->attr(event, &session->evlist); + err = tool->attr(tool, event, &session->evlist); if (err == 0) perf_session__set_id_hdr_size(session); return err; @@ -930,7 +933,7 @@ static int perf_session__process_user_event(struct perf_session *session, union case PERF_RECORD_HEADER_TRACING_DATA: /* setup for reading amidst mmap */ lseek(session->fd, file_offset, SEEK_SET); - return tool->tracing_data(event, session); + return tool->tracing_data(tool, event, session); case PERF_RECORD_HEADER_BUILD_ID: return tool->build_id(tool, event, session); case PERF_RECORD_FINISHED_ROUND: diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h index b0e1aadba8d5..88f8cbdb8a34 100644 --- a/tools/perf/util/tool.h +++ b/tools/perf/util/tool.h @@ -18,12 +18,11 @@ typedef int (*event_sample)(struct perf_tool *tool, union perf_event *event, typedef int (*event_op)(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct machine *machine); -typedef int (*event_attr_op)(union perf_event *event, +typedef int (*event_attr_op)(struct perf_tool *tool, + union perf_event *event, struct perf_evlist **pevlist); -typedef int (*event_simple_op)(struct perf_tool *tool, union perf_event *event); -typedef int (*event_synth_op)(union perf_event *event, - struct perf_session *session); +typedef int (*event_simple_op)(struct perf_tool *tool, union perf_event *event); typedef int (*event_op2)(struct perf_tool *tool, union perf_event *event, struct perf_session *session); @@ -39,7 +38,7 @@ struct perf_tool { throttle, unthrottle; event_attr_op attr; - event_synth_op tracing_data; + event_op2 tracing_data; event_simple_op event_type; event_op2 finished_round, build_id; From a609bda78203a21fb0e78b9d5b4ab911678e4ebb Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 4 Jul 2013 16:20:22 +0300 Subject: [PATCH 0052/3400] perf inject: Add missing 'finished_round' By default, perf inject should "repipe" all events including 'finished_round'. Signed-off-by: Adrian Hunter Acked-by: Jiri Olsa Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1372944040-32690-4-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-inject.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index c943513d06be..ad1296c6f88c 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -404,6 +404,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) .attr = perf_event__repipe_attr, .event_type = perf_event__repipe_event_type_synth, .tracing_data = perf_event__repipe_op2_synth, + .finished_round = perf_event__repipe_op2_synth, .build_id = perf_event__repipe_op2_synth, }, .input_name = "-", From b6b96fb48f75d62858b39baf13c83c4504642f15 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 4 Jul 2013 16:20:25 +0300 Subject: [PATCH 0053/3400] perf tools: Add const specifier to perf_pmu__find name parameter The name parameter is constant, declare it so. Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1372944040-32690-7-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/pmu.c | 14 +++++++------- tools/perf/util/pmu.h | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 4c6f9c490a8d..1d1862dcbbbc 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -73,7 +73,7 @@ int perf_pmu__format_parse(char *dir, struct list_head *head) * located at: * /sys/bus/event_source/devices//format as sysfs group attributes. */ -static int pmu_format(char *name, struct list_head *format) +static int pmu_format(const char *name, struct list_head *format) { struct stat st; char path[PATH_MAX]; @@ -162,7 +162,7 @@ static int pmu_aliases_parse(char *dir, struct list_head *head) * Reading the pmu event aliases definition, which should be located at: * /sys/bus/event_source/devices//events as sysfs group attributes. */ -static int pmu_aliases(char *name, struct list_head *head) +static int pmu_aliases(const char *name, struct list_head *head) { struct stat st; char path[PATH_MAX]; @@ -208,7 +208,7 @@ static int pmu_alias_terms(struct perf_pmu_alias *alias, * located at: * /sys/bus/event_source/devices//type as sysfs attribute. */ -static int pmu_type(char *name, __u32 *type) +static int pmu_type(const char *name, __u32 *type) { struct stat st; char path[PATH_MAX]; @@ -266,7 +266,7 @@ static void pmu_read_sysfs(void) closedir(dir); } -static struct cpu_map *pmu_cpumask(char *name) +static struct cpu_map *pmu_cpumask(const char *name) { struct stat st; char path[PATH_MAX]; @@ -293,7 +293,7 @@ static struct cpu_map *pmu_cpumask(char *name) return cpus; } -static struct perf_pmu *pmu_lookup(char *name) +static struct perf_pmu *pmu_lookup(const char *name) { struct perf_pmu *pmu; LIST_HEAD(format); @@ -330,7 +330,7 @@ static struct perf_pmu *pmu_lookup(char *name) return pmu; } -static struct perf_pmu *pmu_find(char *name) +static struct perf_pmu *pmu_find(const char *name) { struct perf_pmu *pmu; @@ -356,7 +356,7 @@ struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu) return NULL; } -struct perf_pmu *perf_pmu__find(char *name) +struct perf_pmu *perf_pmu__find(const char *name) { struct perf_pmu *pmu; diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h index 32fe55b659fa..d17b5656bacf 100644 --- a/tools/perf/util/pmu.h +++ b/tools/perf/util/pmu.h @@ -21,7 +21,7 @@ struct perf_pmu { struct list_head list; }; -struct perf_pmu *perf_pmu__find(char *name); +struct perf_pmu *perf_pmu__find(const char *name); int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, struct list_head *head_terms); int perf_pmu__config_terms(struct list_head *formats, From 93edcbd91d888c7530c7fc749176fc935b8e2287 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 4 Jul 2013 16:20:26 +0300 Subject: [PATCH 0054/3400] perf evlist: Tidy duplicated munmap code The same lines of code are used in three places. Make it a new function '__perf_evlist__munmap()'. Signed-off-by: Adrian Hunter Acked-by: Jiri Olsa Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1372944040-32690-8-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evlist.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index d8f34e0afbfb..42ea4e947eb8 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -403,16 +403,20 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx) return event; } +static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx) +{ + if (evlist->mmap[idx].base != NULL) { + munmap(evlist->mmap[idx].base, evlist->mmap_len); + evlist->mmap[idx].base = NULL; + } +} + void perf_evlist__munmap(struct perf_evlist *evlist) { int i; - for (i = 0; i < evlist->nr_mmaps; i++) { - if (evlist->mmap[i].base != NULL) { - munmap(evlist->mmap[i].base, evlist->mmap_len); - evlist->mmap[i].base = NULL; - } - } + for (i = 0; i < evlist->nr_mmaps; i++) + __perf_evlist__munmap(evlist, i); free(evlist->mmap); evlist->mmap = NULL; @@ -477,12 +481,8 @@ static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot, int m return 0; out_unmap: - for (cpu = 0; cpu < nr_cpus; cpu++) { - if (evlist->mmap[cpu].base != NULL) { - munmap(evlist->mmap[cpu].base, evlist->mmap_len); - evlist->mmap[cpu].base = NULL; - } - } + for (cpu = 0; cpu < nr_cpus; cpu++) + __perf_evlist__munmap(evlist, cpu); return -1; } @@ -517,12 +517,8 @@ static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot, in return 0; out_unmap: - for (thread = 0; thread < nr_threads; thread++) { - if (evlist->mmap[thread].base != NULL) { - munmap(evlist->mmap[thread].base, evlist->mmap_len); - evlist->mmap[thread].base = NULL; - } - } + for (thread = 0; thread < nr_threads; thread++) + __perf_evlist__munmap(evlist, thread); return -1; } From 27389d7823f573be8eaff32fb4abe564e181eb71 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 4 Jul 2013 16:20:27 +0300 Subject: [PATCH 0055/3400] perf tools: Validate perf event header size The 'size' variable includes the header so must be at least 'sizeof(struct perf_event_header)'. Error out immediately if that is not the case. Also don't byte-swap the header until it is actually "fetched" from the mmap region. Signed-off-by: Adrian Hunter Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1372944040-32690-9-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/session.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 6b71b88f95fa..951a1cfb317c 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1094,8 +1094,10 @@ more: perf_event_header__bswap(&event->header); size = event->header.size; - if (size == 0) - size = 8; + if (size < sizeof(struct perf_event_header)) { + pr_err("bad event header size\n"); + goto out_err; + } if (size > cur_size) { void *new = realloc(buf, size); @@ -1164,8 +1166,12 @@ fetch_mmaped_event(struct perf_session *session, if (session->header.needs_swap) perf_event_header__bswap(&event->header); - if (head + event->header.size > mmap_size) + if (head + event->header.size > mmap_size) { + /* We're not fetching the event so swap back again */ + if (session->header.needs_swap) + perf_event_header__bswap(&event->header); return NULL; + } return event; } @@ -1245,7 +1251,7 @@ more: size = event->header.size; - if (size == 0 || + if (size < sizeof(struct perf_event_header) || perf_session__process_event(session, event, tool, file_pos) < 0) { pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n", file_offset + head, event->header.size, From 380512345e13c3af64e59627f1b993c4faa94a84 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 4 Jul 2013 16:20:31 +0300 Subject: [PATCH 0056/3400] perf tools: struct thread has a tid not a pid As evident from 'machine__process_fork_event()' and 'machine__process_exit_event()' the 'pid' member of struct thread is actually the tid. Rename 'pid' to 'tid' in struct thread accordingly. Signed-off-by: Adrian Hunter Acked-by: David Ahern Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/r/1372944040-32690-13-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-kmem.c | 2 +- tools/perf/builtin-sched.c | 12 ++++++------ tools/perf/builtin-trace.c | 4 ++-- tools/perf/ui/browsers/hists.c | 6 +++--- tools/perf/util/event.c | 2 +- tools/perf/util/machine.c | 20 ++++++++++---------- tools/perf/util/machine.h | 4 ++-- tools/perf/util/sort.c | 6 +++--- tools/perf/util/thread.c | 10 +++++----- tools/perf/util/thread.h | 4 ++-- 10 files changed, 35 insertions(+), 35 deletions(-) diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index 0259502638b4..b49f5c58e152 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c @@ -313,7 +313,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused, return -1; } - dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); + dump_printf(" ... thread: %s:%d\n", thread->comm, thread->tid); if (evsel->handler.func != NULL) { tracepoint_handler f = evsel->handler.func; diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index fba4a940ba31..948183adb6e5 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -1075,7 +1075,7 @@ static int latency_migrate_task_event(struct perf_sched *sched, if (!atoms) { if (thread_atoms_insert(sched, migrant)) return -1; - register_pid(sched, migrant->pid, migrant->comm); + register_pid(sched, migrant->tid, migrant->comm); atoms = thread_atoms_search(&sched->atom_root, migrant, &sched->cmp_pid); if (!atoms) { pr_err("migration-event: Internal tree error"); @@ -1115,7 +1115,7 @@ static void output_lat_thread(struct perf_sched *sched, struct work_atoms *work_ sched->all_runtime += work_list->total_runtime; sched->all_count += work_list->nb_atoms; - ret = printf(" %s:%d ", work_list->thread->comm, work_list->thread->pid); + ret = printf(" %s:%d ", work_list->thread->comm, work_list->thread->tid); for (i = 0; i < 24 - ret; i++) printf(" "); @@ -1131,9 +1131,9 @@ static void output_lat_thread(struct perf_sched *sched, struct work_atoms *work_ static int pid_cmp(struct work_atoms *l, struct work_atoms *r) { - if (l->thread->pid < r->thread->pid) + if (l->thread->tid < r->thread->tid) return -1; - if (l->thread->pid > r->thread->pid) + if (l->thread->tid > r->thread->tid) return 1; return 0; @@ -1321,7 +1321,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, printf("*"); if (sched->curr_thread[cpu]) { - if (sched->curr_thread[cpu]->pid) + if (sched->curr_thread[cpu]->tid) printf("%2s ", sched->curr_thread[cpu]->shortname); else printf(". "); @@ -1332,7 +1332,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, printf(" %12.6f secs ", (double)timestamp/1e9); if (new_shortname) { printf("%s => %s:%d\n", - sched_in->shortname, sched_in->comm, sched_in->pid); + sched_in->shortname, sched_in->comm, sched_in->tid); } else { printf("\n"); } diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 87fc7d08ca02..0e4b67f6bbd1 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -142,7 +142,7 @@ static size_t trace__fprintf_entry_head(struct trace *trace, struct thread *thre printed += fprintf_duration(duration, fp); if (trace->multiple_threads) - printed += fprintf(fp, "%d ", thread->pid); + printed += fprintf(fp, "%d ", thread->tid); return printed; } @@ -593,7 +593,7 @@ static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp) color = PERF_COLOR_YELLOW; printed += color_fprintf(fp, color, "%20s", thread->comm); - printed += fprintf(fp, " - %-5d :%11lu [", thread->pid, ttrace->nr_events); + printed += fprintf(fp, " - %-5d :%11lu [", thread->tid, ttrace->nr_events); printed += color_fprintf(fp, color, "%5.1f%%", ratio); printed += fprintf(fp, " ] %10.3f ms\n", ttrace->runtime_ms); } diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index fc0bd3843d34..06e892f1f8ca 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -1256,7 +1256,7 @@ static int hists__browser_title(struct hists *hists, char *bf, size_t size, printed += scnprintf(bf + printed, size - printed, ", Thread: %s(%d)", (thread->comm_set ? thread->comm : ""), - thread->pid); + thread->tid); if (dso) printed += scnprintf(bf + printed, size - printed, ", DSO: %s", dso->short_name); @@ -1579,7 +1579,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, asprintf(&options[nr_options], "Zoom %s %s(%d) thread", (browser->hists->thread_filter ? "out of" : "into"), (thread->comm_set ? thread->comm : ""), - thread->pid) > 0) + thread->tid) > 0) zoom_thread = nr_options++; if (dso != NULL && @@ -1702,7 +1702,7 @@ zoom_out_thread: } else { ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s(%d) thread\"", thread->comm_set ? thread->comm : "", - thread->pid); + thread->tid); browser->hists->thread_filter = thread; sort_thread.elide = true; pstack__push(fstack, &browser->hists->thread_filter); diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 5cd13d768cec..95412705d0d2 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -686,7 +686,7 @@ int perf_event__preprocess_sample(const union perf_event *event, !strlist__has_entry(symbol_conf.comm_list, thread->comm)) goto out_filtered; - dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); + dump_printf(" ... thread: %s:%d\n", thread->comm, thread->tid); /* * Have we already created the kernel maps for this machine? * diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 93527afb09d5..5dd5026a82ef 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -233,7 +233,7 @@ void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size) return; } -static struct thread *__machine__findnew_thread(struct machine *machine, pid_t pid, +static struct thread *__machine__findnew_thread(struct machine *machine, pid_t tid, bool create) { struct rb_node **p = &machine->threads.rb_node; @@ -241,23 +241,23 @@ static struct thread *__machine__findnew_thread(struct machine *machine, pid_t p struct thread *th; /* - * Font-end cache - PID lookups come in blocks, + * Front-end cache - TID lookups come in blocks, * so most of the time we dont have to look up * the full rbtree: */ - if (machine->last_match && machine->last_match->pid == pid) + if (machine->last_match && machine->last_match->tid == tid) return machine->last_match; while (*p != NULL) { parent = *p; th = rb_entry(parent, struct thread, rb_node); - if (th->pid == pid) { + if (th->tid == tid) { machine->last_match = th; return th; } - if (pid < th->pid) + if (tid < th->tid) p = &(*p)->rb_left; else p = &(*p)->rb_right; @@ -266,7 +266,7 @@ static struct thread *__machine__findnew_thread(struct machine *machine, pid_t p if (!create) return NULL; - th = thread__new(pid); + th = thread__new(tid); if (th != NULL) { rb_link_node(&th->rb_node, parent, p); rb_insert_color(&th->rb_node, &machine->threads); @@ -276,14 +276,14 @@ static struct thread *__machine__findnew_thread(struct machine *machine, pid_t p return th; } -struct thread *machine__findnew_thread(struct machine *machine, pid_t pid) +struct thread *machine__findnew_thread(struct machine *machine, pid_t tid) { - return __machine__findnew_thread(machine, pid, true); + return __machine__findnew_thread(machine, tid, true); } -struct thread *machine__find_thread(struct machine *machine, pid_t pid) +struct thread *machine__find_thread(struct machine *machine, pid_t tid) { - return __machine__findnew_thread(machine, pid, false); + return __machine__findnew_thread(machine, tid, false); } int machine__process_comm_event(struct machine *machine, union perf_event *event) diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h index 77940680f1fc..e49ba01b7937 100644 --- a/tools/perf/util/machine.h +++ b/tools/perf/util/machine.h @@ -36,7 +36,7 @@ struct map *machine__kernel_map(struct machine *machine, enum map_type type) return machine->vmlinux_maps[type]; } -struct thread *machine__find_thread(struct machine *machine, pid_t pid); +struct thread *machine__find_thread(struct machine *machine, pid_t tid); int machine__process_comm_event(struct machine *machine, union perf_event *event); int machine__process_exit_event(struct machine *machine, union perf_event *event); @@ -99,7 +99,7 @@ static inline bool machine__is_host(struct machine *machine) return machine ? machine->pid == HOST_KERNEL_ID : false; } -struct thread *machine__findnew_thread(struct machine *machine, pid_t pid); +struct thread *machine__findnew_thread(struct machine *machine, pid_t tid); size_t machine__fprintf(struct machine *machine, FILE *fp); diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 313a5a730112..8deee19d2e7f 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -55,14 +55,14 @@ static int64_t cmp_null(void *l, void *r) static int64_t sort__thread_cmp(struct hist_entry *left, struct hist_entry *right) { - return right->thread->pid - left->thread->pid; + return right->thread->tid - left->thread->tid; } static int hist_entry__thread_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width) { return repsep_snprintf(bf, size, "%*s:%5d", width - 6, - self->thread->comm ?: "", self->thread->pid); + self->thread->comm ?: "", self->thread->tid); } struct sort_entry sort_thread = { @@ -77,7 +77,7 @@ struct sort_entry sort_thread = { static int64_t sort__comm_cmp(struct hist_entry *left, struct hist_entry *right) { - return right->thread->pid - left->thread->pid; + return right->thread->tid - left->thread->tid; } static int64_t diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index 40399cbcca77..6feeb88eb5b0 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c @@ -7,17 +7,17 @@ #include "util.h" #include "debug.h" -struct thread *thread__new(pid_t pid) +struct thread *thread__new(pid_t tid) { struct thread *self = zalloc(sizeof(*self)); if (self != NULL) { map_groups__init(&self->mg); - self->pid = pid; + self->tid = tid; self->ppid = -1; self->comm = malloc(32); if (self->comm) - snprintf(self->comm, 32, ":%d", self->pid); + snprintf(self->comm, 32, ":%d", self->tid); } return self; @@ -57,7 +57,7 @@ int thread__comm_len(struct thread *self) size_t thread__fprintf(struct thread *thread, FILE *fp) { - return fprintf(fp, "Thread %d %s\n", thread->pid, thread->comm) + + return fprintf(fp, "Thread %d %s\n", thread->tid, thread->comm) + map_groups__fprintf(&thread->mg, verbose, fp); } @@ -84,7 +84,7 @@ int thread__fork(struct thread *self, struct thread *parent) if (map_groups__clone(&self->mg, &parent->mg, i) < 0) return -ENOMEM; - self->ppid = parent->pid; + self->ppid = parent->tid; return 0; } diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index 5e7ba35a5517..0fe1f9c05865 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h @@ -12,7 +12,7 @@ struct thread { struct list_head node; }; struct map_groups mg; - pid_t pid; + pid_t tid; pid_t ppid; char shortname[3]; bool comm_set; @@ -24,7 +24,7 @@ struct thread { struct machine; -struct thread *thread__new(pid_t pid); +struct thread *thread__new(pid_t tid); void thread__delete(struct thread *self); int thread__set_comm(struct thread *self, const char *comm); From 50e200f07948400694238e08e7add73df5ba8f83 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Sat, 20 Apr 2013 11:02:28 -0700 Subject: [PATCH 0057/3400] perf tools: Default to cpu// for events v5 When an event fails to parse and it's not in a new style format, try to parse it again as a cpu event. This allows to use sysfs exported events directly without //, so you can use perf record -e mem-loads ... instead of perf record -e cpu/mem-loads/ Signed-off-by: Andi Kleen Link: http://lkml.kernel.org/r/1366480949-32292-1-git-send-email-andi@firstfloor.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/include/linux/string.h | 1 + tools/perf/util/parse-events.c | 30 +++++++++++++++++++++++++- tools/perf/util/string.c | 24 +++++++++++++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/include/linux/string.h b/tools/perf/util/include/linux/string.h index 6f19c548ecc0..97a800738226 100644 --- a/tools/perf/util/include/linux/string.h +++ b/tools/perf/util/include/linux/string.h @@ -1,3 +1,4 @@ #include void *memdup(const void *src, size_t len); +int str_append(char **s, int *len, const char *a); diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index e85376999efc..a5076f4f6016 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -6,7 +6,7 @@ #include "parse-options.h" #include "parse-events.h" #include "exec_cmd.h" -#include "string.h" +#include "linux/string.h" #include "symbol.h" #include "cache.h" #include "header.h" @@ -823,6 +823,32 @@ int parse_events_name(struct list_head *list, char *name) return 0; } +static int parse_events__scanner(const char *str, void *data, int start_token); + +static int parse_events_fixup(int ret, const char *str, void *data, + int start_token) +{ + char *o = strdup(str); + char *s = NULL; + char *t = o; + char *p; + int len = 0; + + if (!o) + return ret; + while ((p = strsep(&t, ",")) != NULL) { + if (s) + str_append(&s, &len, ","); + str_append(&s, &len, "cpu/"); + str_append(&s, &len, p); + str_append(&s, &len, "/"); + } + free(o); + if (!s) + return -ENOMEM; + return parse_events__scanner(s, data, start_token); +} + static int parse_events__scanner(const char *str, void *data, int start_token) { YY_BUFFER_STATE buffer; @@ -843,6 +869,8 @@ static int parse_events__scanner(const char *str, void *data, int start_token) parse_events__flush_buffer(buffer, scanner); parse_events__delete_buffer(buffer, scanner); parse_events_lex_destroy(scanner); + if (ret && !strchr(str, '/')) + ret = parse_events_fixup(ret, str, data, start_token); return ret; } diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c index 29c7b2cb2521..f0b0c008c507 100644 --- a/tools/perf/util/string.c +++ b/tools/perf/util/string.c @@ -387,3 +387,27 @@ void *memdup(const void *src, size_t len) return p; } + +/** + * str_append - reallocate string and append another + * @s: pointer to string pointer + * @len: pointer to len (initialized) + * @a: string to append. + */ +int str_append(char **s, int *len, const char *a) +{ + int olen = *s ? strlen(*s) : 0; + int nlen = olen + strlen(a) + 1; + if (*len < nlen) { + *len = *len * 2; + if (*len < nlen) + *len = nlen; + *s = realloc(*s, *len); + if (!*s) + return -ENOMEM; + if (olen == 0) + **s = 0; + } + strcat(*s, a); + return 0; +} From dc098b35b56f83ae088e4291a4e389a6ff126965 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Sat, 20 Apr 2013 11:02:29 -0700 Subject: [PATCH 0058/3400] perf list: List kernel supplied event aliases List the kernel supplied pmu event aliases in perf list It's better when the users can actually see them. Signed-off-by: Andi Kleen Link: http://lkml.kernel.org/r/1366480949-32292-2-git-send-email-andi@firstfloor.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-list.txt | 4 +- tools/perf/builtin-list.c | 3 ++ tools/perf/util/parse-events.c | 5 +- tools/perf/util/pmu.c | 73 ++++++++++++++++++++++++++ tools/perf/util/pmu.h | 3 ++ 5 files changed, 86 insertions(+), 2 deletions(-) diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt index d1e39dc8c810..826f3d6d1d28 100644 --- a/tools/perf/Documentation/perf-list.txt +++ b/tools/perf/Documentation/perf-list.txt @@ -8,7 +8,7 @@ perf-list - List all symbolic event types SYNOPSIS -------- [verse] -'perf list' [hw|sw|cache|tracepoint|event_glob] +'perf list' [hw|sw|cache|tracepoint|pmu|event_glob] DESCRIPTION ----------- @@ -104,6 +104,8 @@ To limit the list use: 'subsys_glob:event_glob' to filter by tracepoint subsystems such as sched, block, etc. +. 'pmu' to print the kernel supplied PMU events. + . If none of the above is matched, it will apply the supplied glob to all events, printing the ones that match. diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c index 1948eceb517a..e79f423cc302 100644 --- a/tools/perf/builtin-list.c +++ b/tools/perf/builtin-list.c @@ -13,6 +13,7 @@ #include "util/parse-events.h" #include "util/cache.h" +#include "util/pmu.h" int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused) { @@ -37,6 +38,8 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused) else if (strcmp(argv[i], "cache") == 0 || strcmp(argv[i], "hwcache") == 0) print_hwcache_events(NULL, false); + else if (strcmp(argv[i], "pmu") == 0) + print_pmu_events(NULL, false); else if (strcmp(argv[i], "--raw-dump") == 0) print_events(NULL, true); else { diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index a5076f4f6016..2c460ede0a69 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -1110,6 +1110,8 @@ int print_hwcache_events(const char *event_glob, bool name_only) } } + if (printed) + printf("\n"); return printed; } @@ -1164,11 +1166,12 @@ void print_events(const char *event_glob, bool name_only) print_hwcache_events(event_glob, name_only); + print_pmu_events(event_glob, name_only); + if (event_glob != NULL) return; if (!name_only) { - printf("\n"); printf(" %-50s [%s]\n", "rNNN", event_type_descriptors[PERF_TYPE_RAW]); diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 1d1862dcbbbc..bc9d8069d376 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -564,3 +564,76 @@ void perf_pmu__set_format(unsigned long *bits, long from, long to) for (b = from; b <= to; b++) set_bit(b, bits); } + +static char *format_alias(char *buf, int len, struct perf_pmu *pmu, + struct perf_pmu_alias *alias) +{ + snprintf(buf, len, "%s/%s/", pmu->name, alias->name); + return buf; +} + +static char *format_alias_or(char *buf, int len, struct perf_pmu *pmu, + struct perf_pmu_alias *alias) +{ + snprintf(buf, len, "%s OR %s/%s/", alias->name, pmu->name, alias->name); + return buf; +} + +static int cmp_string(const void *a, const void *b) +{ + const char * const *as = a; + const char * const *bs = b; + return strcmp(*as, *bs); +} + +void print_pmu_events(const char *event_glob, bool name_only) +{ + struct perf_pmu *pmu; + struct perf_pmu_alias *alias; + char buf[1024]; + int printed = 0; + int len, j; + char **aliases; + + pmu = NULL; + len = 0; + while ((pmu = perf_pmu__scan(pmu)) != NULL) + list_for_each_entry(alias, &pmu->aliases, list) + len++; + aliases = malloc(sizeof(char *) * len); + if (!aliases) + return; + pmu = NULL; + j = 0; + while ((pmu = perf_pmu__scan(pmu)) != NULL) + list_for_each_entry(alias, &pmu->aliases, list) { + char *name = format_alias(buf, sizeof(buf), pmu, alias); + bool is_cpu = !strcmp(pmu->name, "cpu"); + + if (event_glob != NULL && + !(strglobmatch(name, event_glob) || + (!is_cpu && strglobmatch(alias->name, + event_glob)))) + continue; + aliases[j] = name; + if (is_cpu && !name_only) + aliases[j] = format_alias_or(buf, sizeof(buf), + pmu, alias); + aliases[j] = strdup(aliases[j]); + j++; + } + len = j; + qsort(aliases, len, sizeof(char *), cmp_string); + for (j = 0; j < len; j++) { + if (name_only) { + printf("%s ", aliases[j]); + continue; + } + printf(" %-50s [Kernel PMU event]\n", aliases[j]); + free(aliases[j]); + printed++; + } + if (printed) + printf("\n"); + free(aliases); +} diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h index d17b5656bacf..6b2cbe2d4cc3 100644 --- a/tools/perf/util/pmu.h +++ b/tools/perf/util/pmu.h @@ -3,6 +3,7 @@ #include #include +#include enum { PERF_PMU_FORMAT_VALUE_CONFIG, @@ -40,5 +41,7 @@ int perf_pmu__format_parse(char *dir, struct list_head *head); struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu); +void print_pmu_events(const char *event_glob, bool name_only); + int perf_pmu__test(void); #endif /* __PMU_H */ From b21484f1a1f300d422cfe5d4f8f50015e22cea24 Mon Sep 17 00:00:00 2001 From: Greg Price Date: Thu, 6 Dec 2012 21:48:05 -0800 Subject: [PATCH 0059/3400] perf report/top: Add option to collapse undesired parts of call graph For example, in an application with an expensive function implemented with deeply nested recursive calls, the default call-graph presentation is dominated by the different callchains within that function. By ignoring these callees, we can collect the callchains leading into the function and compactly identify what to blame for expensive calls. For example, in this report the callers of garbage_collect() are scattered across the tree: $ perf report -d ruby 2>- | grep -m10 ^[^#]*[a-z] 22.03% ruby [.] gc_mark --- gc_mark |--59.40%-- mark_keyvalue | st_foreach | gc_mark_children | |--99.75%-- rb_gc_mark | | rb_vm_mark | | gc_mark_children | | gc_marks | | |--99.00%-- garbage_collect If we ignore the callees of garbage_collect(), its callers are coalesced: $ perf report --ignore-callees garbage_collect -d ruby 2>- | grep -m10 ^[^#]*[a-z] 72.92% ruby [.] garbage_collect --- garbage_collect vm_xmalloc |--47.08%-- ruby_xmalloc | st_insert2 | rb_hash_aset | |--98.45%-- features_index_add | | rb_provide_feature | | rb_require_safe | | vm_call_method Signed-off-by: Greg Price Tested-by: Jiri Olsa Cc: David Ahern Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20130623031720.GW22203@biohazard-cafe.mit.edu Link: http://lkml.kernel.org/r/20130708115746.GO22203@biohazard-cafe.mit.edu Cc: Fengguang Wu [ remove spaces at beginning of line, reported by Fengguang Wu ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-report.txt | 5 +++++ tools/perf/Documentation/perf-top.txt | 5 +++++ tools/perf/builtin-report.c | 27 +++++++++++++++++++++--- tools/perf/builtin-top.c | 6 ++++-- tools/perf/util/machine.c | 24 +++++++++++++-------- tools/perf/util/machine.h | 4 +++- tools/perf/util/session.c | 3 +-- tools/perf/util/sort.c | 2 ++ tools/perf/util/sort.h | 4 ++++ 9 files changed, 63 insertions(+), 17 deletions(-) diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index 66dab7410c1d..747ff50284b7 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt @@ -135,6 +135,11 @@ OPTIONS --inverted:: alias for inverted caller based call graph. +--ignore-callees=:: + Ignore callees of the function(s) matching the given regex. + This has the effect of collecting the callers of each such + function into one place in the call-graph tree. + --pretty=:: Pretty printing style. key: normal, raw diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt index 7fdd1909e376..58d6598a9686 100644 --- a/tools/perf/Documentation/perf-top.txt +++ b/tools/perf/Documentation/perf-top.txt @@ -155,6 +155,11 @@ Default is to monitor all CPUS. Default: fractal,0.5,callee. +--ignore-callees=:: + Ignore callees of the function(s) matching the given regex. + This has the effect of collecting the callers of each such + function into one place in the call-graph tree. + --percent-limit:: Do not show entries which have an overhead under that percent. (Default: 0). diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index ee2ca3eb22df..9a7e54d701cf 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -89,7 +89,7 @@ static int perf_report__add_mem_hist_entry(struct perf_tool *tool, if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) { err = machine__resolve_callchain(machine, evsel, al->thread, - sample, &parent); + sample, &parent, al); if (err) return err; } @@ -180,7 +180,7 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool, if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) { err = machine__resolve_callchain(machine, evsel, al->thread, - sample, &parent); + sample, &parent, al); if (err) return err; } @@ -254,7 +254,7 @@ static int perf_evsel__add_hist_entry(struct perf_evsel *evsel, if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) { err = machine__resolve_callchain(machine, evsel, al->thread, - sample, &parent); + sample, &parent, al); if (err) return err; } @@ -681,6 +681,24 @@ setup: return 0; } +int +report_parse_ignore_callees_opt(const struct option *opt __maybe_unused, + const char *arg, int unset __maybe_unused) +{ + if (arg) { + int err = regcomp(&ignore_callees_regex, arg, REG_EXTENDED); + if (err) { + char buf[BUFSIZ]; + regerror(err, &ignore_callees_regex, buf, sizeof(buf)); + pr_err("Invalid --ignore-callees regex: %s\n%s", arg, buf); + return -1; + } + have_ignore_callees = 1; + } + + return 0; +} + static int parse_branch_mode(const struct option *opt __maybe_unused, const char *str __maybe_unused, int unset) @@ -771,6 +789,9 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) "Default: fractal,0.5,callee", &parse_callchain_opt, callchain_default_opt), OPT_BOOLEAN('G', "inverted", &report.inverted_callchain, "alias for inverted call graph"), + OPT_CALLBACK(0, "ignore-callees", NULL, "regex", + "ignore callees of these functions in call graphs", + report_parse_ignore_callees_opt), OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]", "only consider symbols in these dsos"), OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]", diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index a237059f51cf..bbf463572777 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -773,8 +773,7 @@ static void perf_event__process_sample(struct perf_tool *tool, sample->callchain) { err = machine__resolve_callchain(machine, evsel, al.thread, sample, - &parent); - + &parent, &al); if (err) return; } @@ -1109,6 +1108,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) OPT_CALLBACK_DEFAULT('G', "call-graph", &top.record_opts, "mode[,dump_size]", record_callchain_help, &parse_callchain_opt, "fp"), + OPT_CALLBACK(0, "ignore-callees", NULL, "regex", + "ignore callees of these functions in call graphs", + report_parse_ignore_callees_opt), OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period, "Show a column with the sum of periods"), OPT_STRING(0, "dsos", &symbol_conf.dso_list_str, "dso[,dso...]", diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 5dd5026a82ef..f9f9d6381b9a 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -1058,11 +1058,10 @@ int machine__process_event(struct machine *machine, union perf_event *event) return ret; } -static bool symbol__match_parent_regex(struct symbol *sym) +static bool symbol__match_regex(struct symbol *sym, regex_t *regex) { - if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0)) + if (sym->name && !regexec(regex, sym->name, 0, NULL, 0)) return 1; - return 0; } @@ -1159,8 +1158,8 @@ struct branch_info *machine__resolve_bstack(struct machine *machine, static int machine__resolve_callchain_sample(struct machine *machine, struct thread *thread, struct ip_callchain *chain, - struct symbol **parent) - + struct symbol **parent, + struct addr_location *root_al) { u8 cpumode = PERF_RECORD_MISC_USER; unsigned int i; @@ -1211,8 +1210,15 @@ static int machine__resolve_callchain_sample(struct machine *machine, MAP__FUNCTION, ip, &al, NULL); if (al.sym != NULL) { if (sort__has_parent && !*parent && - symbol__match_parent_regex(al.sym)) + symbol__match_regex(al.sym, &parent_regex)) *parent = al.sym; + else if (have_ignore_callees && root_al && + symbol__match_regex(al.sym, &ignore_callees_regex)) { + /* Treat this symbol as the root, + forgetting its callees. */ + *root_al = al; + callchain_cursor_reset(&callchain_cursor); + } if (!symbol_conf.use_callchain) break; } @@ -1237,13 +1243,13 @@ int machine__resolve_callchain(struct machine *machine, struct perf_evsel *evsel, struct thread *thread, struct perf_sample *sample, - struct symbol **parent) - + struct symbol **parent, + struct addr_location *root_al) { int ret; ret = machine__resolve_callchain_sample(machine, thread, - sample->callchain, parent); + sample->callchain, parent, root_al); if (ret) return ret; diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h index e49ba01b7937..5bb6244194d5 100644 --- a/tools/perf/util/machine.h +++ b/tools/perf/util/machine.h @@ -5,6 +5,7 @@ #include #include "map.h" +struct addr_location; struct branch_stack; struct perf_evsel; struct perf_sample; @@ -83,7 +84,8 @@ int machine__resolve_callchain(struct machine *machine, struct perf_evsel *evsel, struct thread *thread, struct perf_sample *sample, - struct symbol **parent); + struct symbol **parent, + struct addr_location *root_al); /* * Default guest kernel is defined by parameter --guestkallsyms diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 951a1cfb317c..1eb58eedcac1 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1406,9 +1406,8 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event, if (symbol_conf.use_callchain && sample->callchain) { - if (machine__resolve_callchain(machine, evsel, al.thread, - sample, NULL) != 0) { + sample, NULL, NULL) != 0) { if (verbose) error("Failed to resolve callchain. Skipping\n"); return; diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 8deee19d2e7f..cb2b108635ee 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -7,6 +7,8 @@ const char default_parent_pattern[] = "^sys_|^do_page_fault"; const char *parent_pattern = default_parent_pattern; const char default_sort_order[] = "comm,dso,symbol"; const char *sort_order = default_sort_order; +regex_t ignore_callees_regex; +int have_ignore_callees = 0; int sort__need_collapse = 0; int sort__has_parent = 0; int sort__has_sym = 0; diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index 45ac84c1e037..a4a6d0b1ea0e 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h @@ -29,6 +29,8 @@ extern const char *sort_order; extern const char default_parent_pattern[]; extern const char *parent_pattern; extern const char default_sort_order[]; +extern regex_t ignore_callees_regex; +extern int have_ignore_callees; extern int sort__need_collapse; extern int sort__has_parent; extern int sort__has_sym; @@ -183,4 +185,6 @@ int setup_sorting(void); extern int sort_dimension__add(const char *); void sort__setup_elide(FILE *fp); +int report_parse_ignore_callees_opt(const struct option *opt, const char *arg, int unset); + #endif /* __PERF_SORT_H */ From 2c5d4b4a087c448d7818b89294c98d4977dfe76c Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 31 Jan 2013 23:31:11 +0100 Subject: [PATCH 0060/3400] perf tools: Add struct perf_hpp_fmt into hpp callbacks Adding 'struct perf_hpp_fmt' into hpp callbacks, so commands can access their private data. It'll be handy for diff command in future to be able to access file related data for each column. Signed-off-by: Jiri Olsa Reviewed-by: Namhyung Kim Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-7vy2m18574b1bicoljn8e9lw@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/hists.c | 10 +++-- tools/perf/ui/gtk/hists.c | 9 ++-- tools/perf/ui/hist.c | 79 ++++++++++++++++++++++------------ tools/perf/ui/stdio/hist.c | 4 +- tools/perf/util/hist.h | 10 +++-- 5 files changed, 71 insertions(+), 41 deletions(-) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 06e892f1f8ca..2cb39164a1cd 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -685,8 +685,10 @@ static u64 __hpp_get_##_field(struct hist_entry *he) \ return he->stat._field; \ } \ \ -static int hist_browser__hpp_color_##_type(struct perf_hpp *hpp, \ - struct hist_entry *he) \ +static int \ +hist_browser__hpp_color_##_type(struct perf_hpp_fmt *fmt __maybe_unused,\ + struct perf_hpp *hpp, \ + struct hist_entry *he) \ { \ return __hpp__color_fmt(hpp, he, __hpp_get_##_field, _cb); \ } @@ -762,9 +764,9 @@ static int hist_browser__show_entry(struct hist_browser *browser, first = false; if (fmt->color) { - width -= fmt->color(&hpp, entry); + width -= fmt->color(fmt, &hpp, entry); } else { - width -= fmt->entry(&hpp, entry); + width -= fmt->entry(fmt, &hpp, entry); slsmg_printf("%s", s); } } diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c index 32549035f50d..cb2ed1980147 100644 --- a/tools/perf/ui/gtk/hists.c +++ b/tools/perf/ui/gtk/hists.c @@ -91,7 +91,8 @@ static u64 he_get_##_field(struct hist_entry *he) \ return he->stat._field; \ } \ \ -static int perf_gtk__hpp_color_##_type(struct perf_hpp *hpp, \ +static int perf_gtk__hpp_color_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \ + struct perf_hpp *hpp, \ struct hist_entry *he) \ { \ return __hpp__color_fmt(hpp, he, he_get_##_field); \ @@ -244,7 +245,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists, col_idx = 0; perf_hpp__for_each_format(fmt) { - fmt->header(&hpp); + fmt->header(fmt, &hpp); gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), -1, ltrim(s), @@ -296,9 +297,9 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists, perf_hpp__for_each_format(fmt) { if (fmt->color) - fmt->color(&hpp, h); + fmt->color(fmt, &hpp, h); else - fmt->entry(&hpp, h); + fmt->entry(fmt, &hpp, h); gtk_tree_store_set(store, &iter, col_idx++, s, -1); } diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 4bf91b09d62d..5440d56d884a 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -1,4 +1,5 @@ #include +#include #include "../util/hist.h" #include "../util/util.h" @@ -79,7 +80,8 @@ static int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he, } #define __HPP_HEADER_FN(_type, _str, _min_width, _unit_width) \ -static int hpp__header_##_type(struct perf_hpp *hpp) \ +static int hpp__header_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \ + struct perf_hpp *hpp) \ { \ int len = _min_width; \ \ @@ -92,7 +94,8 @@ static int hpp__header_##_type(struct perf_hpp *hpp) \ } #define __HPP_WIDTH_FN(_type, _min_width, _unit_width) \ -static int hpp__width_##_type(struct perf_hpp *hpp __maybe_unused) \ +static int hpp__width_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \ + struct perf_hpp *hpp __maybe_unused) \ { \ int len = _min_width; \ \ @@ -110,14 +113,16 @@ static u64 he_get_##_field(struct hist_entry *he) \ return he->stat._field; \ } \ \ -static int hpp__color_##_type(struct perf_hpp *hpp, struct hist_entry *he) \ +static int hpp__color_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \ + struct perf_hpp *hpp, struct hist_entry *he) \ { \ return __hpp__fmt(hpp, he, he_get_##_field, " %6.2f%%", \ (hpp_snprint_fn)percent_color_snprintf, true); \ } #define __HPP_ENTRY_PERCENT_FN(_type, _field) \ -static int hpp__entry_##_type(struct perf_hpp *hpp, struct hist_entry *he) \ +static int hpp__entry_##_type(struct perf_hpp_fmt *_fmt __maybe_unused, \ + struct perf_hpp *hpp, struct hist_entry *he) \ { \ const char *fmt = symbol_conf.field_sep ? " %.2f" : " %6.2f%%"; \ return __hpp__fmt(hpp, he, he_get_##_field, fmt, \ @@ -130,7 +135,8 @@ static u64 he_get_raw_##_field(struct hist_entry *he) \ return he->stat._field; \ } \ \ -static int hpp__entry_##_type(struct perf_hpp *hpp, struct hist_entry *he) \ +static int hpp__entry_##_type(struct perf_hpp_fmt *_fmt __maybe_unused, \ + struct perf_hpp *hpp, struct hist_entry *he) \ { \ const char *fmt = symbol_conf.field_sep ? " %"PRIu64 : " %11"PRIu64; \ return __hpp__fmt(hpp, he, he_get_raw_##_field, fmt, scnprintf, false); \ @@ -158,12 +164,14 @@ HPP_RAW_FNS(samples, "Samples", nr_events, 12, 12) HPP_RAW_FNS(period, "Period", period, 12, 12) -static int hpp__header_baseline(struct perf_hpp *hpp) +static int hpp__header_baseline(struct perf_hpp_fmt *fmt __maybe_unused, + struct perf_hpp *hpp) { return scnprintf(hpp->buf, hpp->size, "Baseline"); } -static int hpp__width_baseline(struct perf_hpp *hpp __maybe_unused) +static int hpp__width_baseline(struct perf_hpp_fmt *fmt __maybe_unused, + struct perf_hpp *hpp __maybe_unused) { return 8; } @@ -184,7 +192,8 @@ static double baseline_percent(struct hist_entry *he) return percent; } -static int hpp__color_baseline(struct perf_hpp *hpp, struct hist_entry *he) +static int hpp__color_baseline(struct perf_hpp_fmt *fmt __maybe_unused, + struct perf_hpp *hpp, struct hist_entry *he) { double percent = baseline_percent(he); @@ -194,7 +203,8 @@ static int hpp__color_baseline(struct perf_hpp *hpp, struct hist_entry *he) return scnprintf(hpp->buf, hpp->size, " "); } -static int hpp__entry_baseline(struct perf_hpp *hpp, struct hist_entry *he) +static int hpp__entry_baseline(struct perf_hpp_fmt *_fmt __maybe_unused, + struct perf_hpp *hpp, struct hist_entry *he) { double percent = baseline_percent(he); const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%"; @@ -205,19 +215,22 @@ static int hpp__entry_baseline(struct perf_hpp *hpp, struct hist_entry *he) return scnprintf(hpp->buf, hpp->size, " "); } -static int hpp__header_period_baseline(struct perf_hpp *hpp) +static int hpp__header_period_baseline(struct perf_hpp_fmt *_fmt __maybe_unused, + struct perf_hpp *hpp) { const char *fmt = symbol_conf.field_sep ? "%s" : "%12s"; return scnprintf(hpp->buf, hpp->size, fmt, "Period Base"); } -static int hpp__width_period_baseline(struct perf_hpp *hpp __maybe_unused) +static int hpp__width_period_baseline(struct perf_hpp_fmt *fmt __maybe_unused, + struct perf_hpp *hpp __maybe_unused) { return 12; } -static int hpp__entry_period_baseline(struct perf_hpp *hpp, struct hist_entry *he) +static int hpp__entry_period_baseline(struct perf_hpp_fmt *_fmt __maybe_unused, + struct perf_hpp *hpp, struct hist_entry *he) { struct hist_entry *pair = hist_entry__next_pair(he); u64 period = pair ? pair->stat.period : 0; @@ -226,19 +239,22 @@ static int hpp__entry_period_baseline(struct perf_hpp *hpp, struct hist_entry *h return scnprintf(hpp->buf, hpp->size, fmt, period); } -static int hpp__header_delta(struct perf_hpp *hpp) +static int hpp__header_delta(struct perf_hpp_fmt *_fmt __maybe_unused, + struct perf_hpp *hpp) { const char *fmt = symbol_conf.field_sep ? "%s" : "%7s"; return scnprintf(hpp->buf, hpp->size, fmt, "Delta"); } -static int hpp__width_delta(struct perf_hpp *hpp __maybe_unused) +static int hpp__width_delta(struct perf_hpp_fmt *fmt __maybe_unused, + struct perf_hpp *hpp __maybe_unused) { return 7; } -static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he) +static int hpp__entry_delta(struct perf_hpp_fmt *_fmt __maybe_unused, + struct perf_hpp *hpp, struct hist_entry *he) { struct hist_entry *pair = hist_entry__next_pair(he); const char *fmt = symbol_conf.field_sep ? "%s" : "%7.7s"; @@ -259,19 +275,22 @@ static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he) return scnprintf(hpp->buf, hpp->size, fmt, buf); } -static int hpp__header_ratio(struct perf_hpp *hpp) +static int hpp__header_ratio(struct perf_hpp_fmt *_fmt __maybe_unused, + struct perf_hpp *hpp) { const char *fmt = symbol_conf.field_sep ? "%s" : "%14s"; return scnprintf(hpp->buf, hpp->size, fmt, "Ratio"); } -static int hpp__width_ratio(struct perf_hpp *hpp __maybe_unused) +static int hpp__width_ratio(struct perf_hpp_fmt *fmt __maybe_unused, + struct perf_hpp *hpp __maybe_unused) { return 14; } -static int hpp__entry_ratio(struct perf_hpp *hpp, struct hist_entry *he) +static int hpp__entry_ratio(struct perf_hpp_fmt *_fmt __maybe_unused, + struct perf_hpp *hpp, struct hist_entry *he) { struct hist_entry *pair = hist_entry__next_pair(he); const char *fmt = symbol_conf.field_sep ? "%s" : "%14s"; @@ -291,19 +310,22 @@ static int hpp__entry_ratio(struct perf_hpp *hpp, struct hist_entry *he) return scnprintf(hpp->buf, hpp->size, fmt, buf); } -static int hpp__header_wdiff(struct perf_hpp *hpp) +static int hpp__header_wdiff(struct perf_hpp_fmt *_fmt __maybe_unused, + struct perf_hpp *hpp) { const char *fmt = symbol_conf.field_sep ? "%s" : "%14s"; return scnprintf(hpp->buf, hpp->size, fmt, "Weighted diff"); } -static int hpp__width_wdiff(struct perf_hpp *hpp __maybe_unused) +static int hpp__width_wdiff(struct perf_hpp_fmt *fmt __maybe_unused, + struct perf_hpp *hpp __maybe_unused) { return 14; } -static int hpp__entry_wdiff(struct perf_hpp *hpp, struct hist_entry *he) +static int hpp__entry_wdiff(struct perf_hpp_fmt *_fmt __maybe_unused, + struct perf_hpp *hpp, struct hist_entry *he) { struct hist_entry *pair = hist_entry__next_pair(he); const char *fmt = symbol_conf.field_sep ? "%s" : "%14s"; @@ -323,19 +345,22 @@ static int hpp__entry_wdiff(struct perf_hpp *hpp, struct hist_entry *he) return scnprintf(hpp->buf, hpp->size, fmt, buf); } -static int hpp__header_formula(struct perf_hpp *hpp) +static int hpp__header_formula(struct perf_hpp_fmt *_fmt __maybe_unused, + struct perf_hpp *hpp) { const char *fmt = symbol_conf.field_sep ? "%s" : "%70s"; return scnprintf(hpp->buf, hpp->size, fmt, "Formula"); } -static int hpp__width_formula(struct perf_hpp *hpp __maybe_unused) +static int hpp__width_formula(struct perf_hpp_fmt *fmt __maybe_unused, + struct perf_hpp *hpp __maybe_unused) { return 70; } -static int hpp__entry_formula(struct perf_hpp *hpp, struct hist_entry *he) +static int hpp__entry_formula(struct perf_hpp_fmt *_fmt __maybe_unused, + struct perf_hpp *hpp, struct hist_entry *he) { struct hist_entry *pair = hist_entry__next_pair(he); const char *fmt = symbol_conf.field_sep ? "%s" : "%-70s"; @@ -454,9 +479,9 @@ int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he, first = false; if (color && fmt->color) - ret = fmt->color(hpp, he); + ret = fmt->color(fmt, hpp, he); else - ret = fmt->entry(hpp, he); + ret = fmt->entry(fmt, hpp, he); advance_hpp(hpp, ret); } @@ -499,7 +524,7 @@ unsigned int hists__sort_list_width(struct hists *hists) if (i) ret += 2; - ret += fmt->width(&dummy_hpp); + ret += fmt->width(fmt, &dummy_hpp); } list_for_each_entry(se, &hist_entry__sort_list, list) diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c index ae7a75432249..ee703720649d 100644 --- a/tools/perf/ui/stdio/hist.c +++ b/tools/perf/ui/stdio/hist.c @@ -365,7 +365,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, else first = false; - fmt->header(&dummy_hpp); + fmt->header(fmt, &dummy_hpp); fprintf(fp, "%s", bf); } @@ -410,7 +410,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, else first = false; - width = fmt->width(&dummy_hpp); + width = fmt->width(fmt, &dummy_hpp); for (i = 0; i < width; i++) fprintf(fp, "."); } diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 2d3790fd99bb..0c62116d4d3a 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -141,10 +141,12 @@ struct perf_hpp { }; struct perf_hpp_fmt { - int (*header)(struct perf_hpp *hpp); - int (*width)(struct perf_hpp *hpp); - int (*color)(struct perf_hpp *hpp, struct hist_entry *he); - int (*entry)(struct perf_hpp *hpp, struct hist_entry *he); + int (*header)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp); + int (*width)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp); + int (*color)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, + struct hist_entry *he); + int (*entry)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, + struct hist_entry *he); struct list_head list; }; From 2b8bfa6bb8a7d26935207710397386759b42125c Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 31 Jan 2013 23:34:25 +0100 Subject: [PATCH 0061/3400] perf tools: Centralize default columns init in perf_hpp__init Now when diff command is separated from other standard outputs, we can use perf_hpp__init to initialize all standard columns. Moving PERF_HPP__OVERHEAD column init back to perf_hpp__init, and removing extra enable calls. Signed-off-by: Jiri Olsa Reviewed-by: Namhyung Kim Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-nj2xk89tj972tbqswfs498ex@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-report.c | 1 - tools/perf/ui/browsers/hists.c | 2 -- tools/perf/ui/hist.c | 2 ++ tools/perf/ui/setup.c | 1 - 4 files changed, 2 insertions(+), 4 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 9a7e54d701cf..188c265751c8 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -861,7 +861,6 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) setup_browser(true); else { use_browser = 0; - perf_hpp__column_enable(PERF_HPP__OVERHEAD); perf_hpp__init(); } diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 2cb39164a1cd..7ef36c360471 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -703,8 +703,6 @@ __HPP_COLOR_PERCENT_FN(overhead_guest_us, period_guest_us, NULL) void hist_browser__init_hpp(void) { - perf_hpp__column_enable(PERF_HPP__OVERHEAD); - perf_hpp__init(); perf_hpp__format[PERF_HPP__OVERHEAD].color = diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 5440d56d884a..f45c97f694da 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -421,6 +421,8 @@ LIST_HEAD(perf_hpp__list); void perf_hpp__init(void) { + perf_hpp__column_enable(PERF_HPP__OVERHEAD); + if (symbol_conf.show_cpu_utilization) { perf_hpp__column_enable(PERF_HPP__OVERHEAD_SYS); perf_hpp__column_enable(PERF_HPP__OVERHEAD_US); diff --git a/tools/perf/ui/setup.c b/tools/perf/ui/setup.c index ae6a789cb0f6..47d9a571f261 100644 --- a/tools/perf/ui/setup.c +++ b/tools/perf/ui/setup.c @@ -30,7 +30,6 @@ void setup_browser(bool fallback_to_pager) if (fallback_to_pager) setup_pager(); - perf_hpp__column_enable(PERF_HPP__OVERHEAD); perf_hpp__init(); break; } From ec308426ea743469ec6c2b0e06e20b3671546e8f Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 25 Mar 2013 00:02:01 +0100 Subject: [PATCH 0062/3400] perf diff: Introducing diff_data object to hold files Introducing struct diff_data to hold data file specifics. It will be handy when dealing with more than 2 data files. Signed-off-by: Jiri Olsa Reviewed-by: Namhyung Kim Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-981q265sf6h05zuu8fnvw842@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-diff.c | 145 +++++++++++++++++++++++++------------- 1 file changed, 96 insertions(+), 49 deletions(-) diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 0aac5f3e594d..015ca2d4fe90 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -19,10 +19,24 @@ #include -static char const *input_old = "perf.data.old", - *input_new = "perf.data"; -static char diff__default_sort_order[] = "dso,symbol"; -static bool force; +struct data__file { + struct perf_session *session; + const char *file; + int idx; +}; + +static struct data__file *data__files; +static int data__files_cnt; + +#define data__for_each_file_start(i, d, s) \ + for (i = s, d = &data__files[s]; \ + i < data__files_cnt; \ + i++, d = &data__files[i]) + +#define data__for_each_file(i, d) data__for_each_file_start(i, d, 0) + +static char diff__default_sort_order[] = "dso,symbol"; +static bool force; static bool show_period; static bool show_formula; static bool show_baseline_only; @@ -467,56 +481,62 @@ static void hists__process(struct hists *old, struct hists *new) hists__fprintf(new, true, 0, 0, 0, stdout); } -static int __cmd_diff(void) +static void data_process(void) { - int ret, i; -#define older (session[0]) -#define newer (session[1]) - struct perf_session *session[2]; - struct perf_evlist *evlist_new, *evlist_old; - struct perf_evsel *evsel; + struct perf_evlist *evlist_old = data__files[0].session->evlist; + struct perf_evlist *evlist_new = data__files[1].session->evlist; + struct perf_evsel *evsel_old; bool first = true; - older = perf_session__new(input_old, O_RDONLY, force, false, - &tool); - newer = perf_session__new(input_new, O_RDONLY, force, false, - &tool); - if (session[0] == NULL || session[1] == NULL) - return -ENOMEM; + list_for_each_entry(evsel_old, &evlist_old->entries, node) { + struct perf_evsel *evsel_new; - for (i = 0; i < 2; ++i) { - ret = perf_session__process_events(session[i], &tool); - if (ret) - goto out_delete; - } - - evlist_old = older->evlist; - evlist_new = newer->evlist; - - perf_evlist__collapse_resort(evlist_old); - perf_evlist__collapse_resort(evlist_new); - - list_for_each_entry(evsel, &evlist_new->entries, node) { - struct perf_evsel *evsel_old; - - evsel_old = evsel_match(evsel, evlist_old); - if (!evsel_old) + evsel_new = evsel_match(evsel_old, evlist_new); + if (!evsel_new) continue; fprintf(stdout, "%s# Event '%s'\n#\n", first ? "" : "\n", - perf_evsel__name(evsel)); + perf_evsel__name(evsel_old)); first = false; - hists__process(&evsel_old->hists, &evsel->hists); + hists__process(&evsel_old->hists, &evsel_new->hists); + } +} + +static int __cmd_diff(void) +{ + struct data__file *d; + int ret = -EINVAL, i; + + data__for_each_file(i, d) { + d->session = perf_session__new(d->file, O_RDONLY, force, + false, &tool); + if (!d->session) { + pr_err("Failed to open %s\n", d->file); + ret = -ENOMEM; + goto out_delete; + } + + ret = perf_session__process_events(d->session, &tool); + if (ret) { + pr_err("Failed to process %s\n", d->file); + goto out_delete; + } + + perf_evlist__collapse_resort(d->session->evlist); } -out_delete: - for (i = 0; i < 2; ++i) - perf_session__delete(session[i]); + data_process(); + + out_delete: + data__for_each_file(i, d) { + if (d->session) + perf_session__delete(d->session); + } + + free(data__files); return ret; -#undef older -#undef newer } static const char * const diff_usage[] = { @@ -589,27 +609,54 @@ static void ui_init(void) } } -int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused) +static int data_init(int argc, const char **argv) { - sort_order = diff__default_sort_order; - argc = parse_options(argc, argv, options, diff_usage, 0); + struct data__file *d; + static const char *defaults[] = { + "perf.data.old", + "perf.data", + }; + int i; + + data__files_cnt = 2; + if (argc) { if (argc > 2) usage_with_options(diff_usage, options); if (argc == 2) { - input_old = argv[0]; - input_new = argv[1]; + defaults[0] = argv[0]; + defaults[1] = argv[1]; } else - input_new = argv[0]; + defaults[1] = argv[0]; } else if (symbol_conf.default_guest_vmlinux_name || symbol_conf.default_guest_kallsyms) { - input_old = "perf.data.host"; - input_new = "perf.data.guest"; + defaults[0] = "perf.data.host"; + defaults[1] = "perf.data.guest"; } + data__files = zalloc(sizeof(*data__files) * data__files_cnt); + if (!data__files) + return -ENOMEM; + + data__for_each_file(i, d) { + d->file = defaults[i]; + d->idx = i; + } + + return 0; +} + +int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused) +{ + sort_order = diff__default_sort_order; + argc = parse_options(argc, argv, options, diff_usage, 0); + if (symbol__init() < 0) return -1; + if (data_init(argc, argv) < 0) + return -1; + ui_init(); if (setup_sorting() < 0) From 9af303e22a317d1cc6f440e08f72428830708b37 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sat, 1 Dec 2012 21:15:40 +0100 Subject: [PATCH 0063/3400] perf diff: Switching the base hists to be pairs head Making the baseline hists to act as a pairs head. So far we don't care which hists act as a pairs head, because we have only 2 files to deal with and any of them is suitable to do the job. But if we want to process more files, we need to pick up one hists to act as pairs head, and the baseline hists is the most suitable. Signed-off-by: Jiri Olsa Reviewed-by: Namhyung Kim Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-cklmt2o4j87i9viz900245ae@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-diff.c | 60 +++++++++++++++++++-------------------- tools/perf/ui/hist.c | 25 ++++------------ 2 files changed, 35 insertions(+), 50 deletions(-) diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 015ca2d4fe90..0cfe99ea9056 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -167,34 +167,34 @@ double perf_diff__period_percent(struct hist_entry *he, u64 period) double perf_diff__compute_delta(struct hist_entry *he, struct hist_entry *pair) { - double new_percent = perf_diff__period_percent(he, he->stat.period); - double old_percent = perf_diff__period_percent(pair, pair->stat.period); + double old_percent = perf_diff__period_percent(he, he->stat.period); + double new_percent = perf_diff__period_percent(pair, pair->stat.period); - he->diff.period_ratio_delta = new_percent - old_percent; - he->diff.computed = true; - return he->diff.period_ratio_delta; + pair->diff.period_ratio_delta = new_percent - old_percent; + pair->diff.computed = true; + return pair->diff.period_ratio_delta; } double perf_diff__compute_ratio(struct hist_entry *he, struct hist_entry *pair) { - double new_period = he->stat.period; - double old_period = pair->stat.period; + double old_period = he->stat.period ?: 1; + double new_period = pair->stat.period; - he->diff.computed = true; - he->diff.period_ratio = new_period / old_period; - return he->diff.period_ratio; + pair->diff.computed = true; + pair->diff.period_ratio = new_period / old_period; + return pair->diff.period_ratio; } s64 perf_diff__compute_wdiff(struct hist_entry *he, struct hist_entry *pair) { - u64 new_period = he->stat.period; - u64 old_period = pair->stat.period; + u64 old_period = he->stat.period; + u64 new_period = pair->stat.period; - he->diff.computed = true; - he->diff.wdiff = new_period * compute_wdiff_w2 - - old_period * compute_wdiff_w1; + pair->diff.computed = true; + pair->diff.wdiff = new_period * compute_wdiff_w2 - + old_period * compute_wdiff_w1; - return he->diff.wdiff; + return pair->diff.wdiff; } static int formula_delta(struct hist_entry *he, struct hist_entry *pair, @@ -203,15 +203,15 @@ static int formula_delta(struct hist_entry *he, struct hist_entry *pair, return scnprintf(buf, size, "(%" PRIu64 " * 100 / %" PRIu64 ") - " "(%" PRIu64 " * 100 / %" PRIu64 ")", - he->stat.period, he->hists->stats.total_period, - pair->stat.period, pair->hists->stats.total_period); + pair->stat.period, pair->hists->stats.total_period, + he->stat.period, he->hists->stats.total_period); } static int formula_ratio(struct hist_entry *he, struct hist_entry *pair, char *buf, size_t size) { - double new_period = he->stat.period; - double old_period = pair->stat.period; + double old_period = he->stat.period; + double new_period = pair->stat.period; return scnprintf(buf, size, "%.0F / %.0F", new_period, old_period); } @@ -219,8 +219,8 @@ static int formula_ratio(struct hist_entry *he, struct hist_entry *pair, static int formula_wdiff(struct hist_entry *he, struct hist_entry *pair, char *buf, size_t size) { - u64 new_period = he->stat.period; - u64 old_period = pair->stat.period; + u64 old_period = he->stat.period; + u64 new_period = pair->stat.period; return scnprintf(buf, size, "(%" PRIu64 " * " "%" PRId64 ") - (%" PRIu64 " * " "%" PRId64 ")", @@ -462,23 +462,23 @@ static void hists__compute_resort(struct hists *hists) } } -static void hists__process(struct hists *old, struct hists *new) +static void hists__process(struct hists *base, struct hists *new) { - hists__match(new, old); + hists__match(base, new); if (show_baseline_only) - hists__baseline_only(new); + hists__baseline_only(base); else - hists__link(new, old); + hists__link(base, new); if (sort_compute) { - hists__precompute(new); - hists__compute_resort(new); + hists__precompute(base); + hists__compute_resort(base); } else { - hists__output_resort(new); + hists__output_resort(base); } - hists__fprintf(new, true, 0, 0, 0, stdout); + hists__fprintf(base, true, 0, 0, 0, stdout); } static void data_process(void) diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index f45c97f694da..02313a9c4682 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -178,18 +178,8 @@ static int hpp__width_baseline(struct perf_hpp_fmt *fmt __maybe_unused, static double baseline_percent(struct hist_entry *he) { - struct hist_entry *pair = hist_entry__next_pair(he); - struct hists *pair_hists = pair ? pair->hists : NULL; - double percent = 0.0; - - if (pair) { - u64 total_period = pair_hists->stats.total_period; - u64 base_period = pair->stat.period; - - percent = 100.0 * base_period / total_period; - } - - return percent; + struct hists *hists = he->hists; + return 100.0 * he->stat.period / hists->stats.total_period; } static int hpp__color_baseline(struct perf_hpp_fmt *fmt __maybe_unused, @@ -197,10 +187,8 @@ static int hpp__color_baseline(struct perf_hpp_fmt *fmt __maybe_unused, { double percent = baseline_percent(he); - if (hist_entry__has_pairs(he) || symbol_conf.field_sep) - return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent); - else - return scnprintf(hpp->buf, hpp->size, " "); + return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", + percent); } static int hpp__entry_baseline(struct perf_hpp_fmt *_fmt __maybe_unused, @@ -209,10 +197,7 @@ static int hpp__entry_baseline(struct perf_hpp_fmt *_fmt __maybe_unused, double percent = baseline_percent(he); const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%"; - if (hist_entry__has_pairs(he) || symbol_conf.field_sep) - return scnprintf(hpp->buf, hpp->size, fmt, percent); - else - return scnprintf(hpp->buf, hpp->size, " "); + return scnprintf(hpp->buf, hpp->size, fmt, percent); } static int hpp__header_period_baseline(struct perf_hpp_fmt *_fmt __maybe_unused, From e0af43d2486fc50208076cfd93af55615fd4adfd Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sat, 1 Dec 2012 21:18:20 +0100 Subject: [PATCH 0064/3400] perf hists: Marking dummy hists entries It does not make sense to make some computation (ratio, wdiff), when the hist_entry is 'dummy' - added via hists__link. Adding dummy field to struct hist_entry which indicates that it was added by hists__link and avoiding some of the processing for such entries. Signed-off-by: Jiri Olsa Reviewed-by: Namhyung Kim Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-g8bxml0n0pnqsrpyd98p0ird@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/hist.c | 21 ++++++++++++++------- tools/perf/util/hist.c | 1 + tools/perf/util/sort.h | 3 +++ 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 02313a9c4682..a359b75ce800 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -187,8 +187,11 @@ static int hpp__color_baseline(struct perf_hpp_fmt *fmt __maybe_unused, { double percent = baseline_percent(he); - return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", - percent); + if (!he->dummy) + return percent_color_snprintf(hpp->buf, hpp->size, + " %6.2f%%", percent); + else + return scnprintf(hpp->buf, hpp->size, " "); } static int hpp__entry_baseline(struct perf_hpp_fmt *_fmt __maybe_unused, @@ -197,7 +200,10 @@ static int hpp__entry_baseline(struct perf_hpp_fmt *_fmt __maybe_unused, double percent = baseline_percent(he); const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%"; - return scnprintf(hpp->buf, hpp->size, fmt, percent); + if (!he->dummy) + return scnprintf(hpp->buf, hpp->size, fmt, percent); + else + return scnprintf(hpp->buf, hpp->size, " "); } static int hpp__header_period_baseline(struct perf_hpp_fmt *_fmt __maybe_unused, @@ -251,8 +257,7 @@ static int hpp__entry_delta(struct perf_hpp_fmt *_fmt __maybe_unused, diff = he->diff.period_ratio_delta; else diff = perf_diff__compute_delta(he, pair); - } else - diff = perf_diff__period_percent(he, he->stat.period); + } if (fabs(diff) >= 0.01) scnprintf(buf, sizeof(buf), "%+4.2F%%", diff); @@ -282,7 +287,8 @@ static int hpp__entry_ratio(struct perf_hpp_fmt *_fmt __maybe_unused, char buf[32] = " "; double ratio = 0.0; - if (pair) { + /* No point for ratio number if we are dummy.. */ + if (!he->dummy && pair) { if (he->diff.computed) ratio = he->diff.period_ratio; else @@ -317,7 +323,8 @@ static int hpp__entry_wdiff(struct perf_hpp_fmt *_fmt __maybe_unused, char buf[32] = " "; s64 wdiff = 0; - if (pair) { + /* No point for wdiff number if we are dummy.. */ + if (!he->dummy && pair) { if (he->diff.computed) wdiff = he->diff.wdiff; else diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index b11a6cfdb414..a9dd1b9d8907 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -912,6 +912,7 @@ static struct hist_entry *hists__add_dummy_entry(struct hists *hists, rb_link_node(&he->rb_node_in, parent, p); rb_insert_color(&he->rb_node_in, root); hists__inc_nr_entries(hists, he); + he->dummy = true; } out: return he; diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index a4a6d0b1ea0e..586022dc3264 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h @@ -89,6 +89,9 @@ struct hist_entry { struct hist_entry_diff diff; + /* We are added by hists__add_dummy_entry. */ + bool dummy; + /* XXX These two should move to some tree widget lib */ u16 row_offset; u16 nr_rows; From 1d81c7fc25c0f0559e3306fc73ecfe78b740c9e8 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sat, 1 Dec 2012 21:56:03 +0100 Subject: [PATCH 0065/3400] perf diff: Display data file info ahead of the diff output Data files are referenced through the index of the file on the command line. Adding list of data files for each index to ease up navigation for user. It's displayed only if in verbose mode. Signed-off-by: Jiri Olsa Reviewed-by: Namhyung Kim Cc: Peter Zijlstra Cc: Paul Mackerras Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Namhyung Kim Link: http://lkml.kernel.org/n/tip-dfjxa6n116ughjjxohpkuvi8@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-diff.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 0cfe99ea9056..9574ba18bc7b 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -481,6 +481,21 @@ static void hists__process(struct hists *base, struct hists *new) hists__fprintf(base, true, 0, 0, 0, stdout); } +static void data__fprintf(void) +{ + struct data__file *d; + int i; + + fprintf(stdout, "# Data files:\n"); + + data__for_each_file(i, d) + fprintf(stdout, "# [%d] %s %s\n", + d->idx, d->file, + !d->idx ? "(Baseline)" : ""); + + fprintf(stdout, "#\n"); +} + static void data_process(void) { struct perf_evlist *evlist_old = data__files[0].session->evlist; @@ -500,6 +515,9 @@ static void data_process(void) first = false; + if (verbose) + data__fprintf(); + hists__process(&evsel_old->hists, &evsel_new->hists); } } From 345dc0b45ecc37a239723f2b6392cab04d8b0eff Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 3 Feb 2013 20:08:34 +0100 Subject: [PATCH 0066/3400] perf diff: Move diff related columns into diff command Moving diff related columns into diff command, because they are not used by any other command. Also moving the column entry functions under generic one with baseline as an exception. Signed-off-by: Jiri Olsa Reviewed-by: Namhyung Kim Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-v58qfl75xkqojz54h1v5fy6p@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-diff.c | 306 ++++++++++++++++++++++++++++++++++++-- tools/perf/ui/hist.c | 209 +------------------------- tools/perf/util/hist.h | 7 +- 3 files changed, 292 insertions(+), 230 deletions(-) diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 9574ba18bc7b..8734f1cee6dc 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -18,6 +18,27 @@ #include "util/util.h" #include +#include + +/* Diff command specific HPP columns. */ +enum { + PERF_HPP_DIFF__BASELINE, + PERF_HPP_DIFF__PERIOD, + PERF_HPP_DIFF__PERIOD_BASELINE, + PERF_HPP_DIFF__DELTA, + PERF_HPP_DIFF__RATIO, + PERF_HPP_DIFF__WEIGHTED_DIFF, + PERF_HPP_DIFF__FORMULA, + + PERF_HPP_DIFF__MAX_INDEX +}; + +struct diff_hpp_fmt { + struct perf_hpp_fmt fmt; + int idx; + char *header; + int header_width; +}; struct data__file { struct perf_session *session; @@ -60,6 +81,47 @@ const char *compute_names[COMPUTE_MAX] = { static int compute; +static int compute_2_hpp[COMPUTE_MAX] = { + [COMPUTE_DELTA] = PERF_HPP_DIFF__DELTA, + [COMPUTE_RATIO] = PERF_HPP_DIFF__RATIO, + [COMPUTE_WEIGHTED_DIFF] = PERF_HPP_DIFF__WEIGHTED_DIFF, +}; + +#define MAX_COL_WIDTH 70 + +static struct header_column { + const char *name; + int width; +} columns[PERF_HPP_DIFF__MAX_INDEX] = { + [PERF_HPP_DIFF__BASELINE] = { + .name = "Baseline", + }, + [PERF_HPP_DIFF__PERIOD] = { + .name = "Period", + .width = 14, + }, + [PERF_HPP_DIFF__PERIOD_BASELINE] = { + .name = "Base period", + .width = 14, + }, + [PERF_HPP_DIFF__DELTA] = { + .name = "Delta", + .width = 7, + }, + [PERF_HPP_DIFF__RATIO] = { + .name = "Ratio", + .width = 14, + }, + [PERF_HPP_DIFF__WEIGHTED_DIFF] = { + .name = "Weighted diff", + .width = 14, + }, + [PERF_HPP_DIFF__FORMULA] = { + .name = "Formula", + .width = MAX_COL_WIDTH, + } +}; + static int setup_compute_opt_wdiff(char *opt) { char *w1_str = opt; @@ -596,34 +658,246 @@ static const struct option options[] = { OPT_END() }; -static void ui_init(void) +static double baseline_percent(struct hist_entry *he) { - /* - * Display baseline/delta/ratio - * formula/periods columns. - */ - perf_hpp__column_enable(PERF_HPP__BASELINE); + struct hists *hists = he->hists; + return 100.0 * he->stat.period / hists->stats.total_period; +} - switch (compute) { - case COMPUTE_DELTA: - perf_hpp__column_enable(PERF_HPP__DELTA); +static int hpp__color_baseline(struct perf_hpp_fmt *fmt, + struct perf_hpp *hpp, struct hist_entry *he) +{ + struct diff_hpp_fmt *dfmt = + container_of(fmt, struct diff_hpp_fmt, fmt); + double percent = baseline_percent(he); + char pfmt[20] = " "; + + if (!he->dummy) { + scnprintf(pfmt, 20, "%%%d.2f%%%%", dfmt->header_width - 1); + return percent_color_snprintf(hpp->buf, hpp->size, + pfmt, percent); + } else + return scnprintf(hpp->buf, hpp->size, "%*s", + dfmt->header_width, pfmt); +} + +static int hpp__entry_baseline(struct hist_entry *he, char *buf, size_t size) +{ + double percent = baseline_percent(he); + const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%"; + int ret = 0; + + if (!he->dummy) + ret = scnprintf(buf, size, fmt, percent); + + return ret; +} + +static void +hpp__entry_unpair(struct hist_entry *he, int idx, char *buf, size_t size) +{ + switch (idx) { + case PERF_HPP_DIFF__PERIOD_BASELINE: + scnprintf(buf, size, "%" PRIu64, he->stat.period); break; - case COMPUTE_RATIO: - perf_hpp__column_enable(PERF_HPP__RATIO); + + default: break; - case COMPUTE_WEIGHTED_DIFF: - perf_hpp__column_enable(PERF_HPP__WEIGHTED_DIFF); + } +} + +static void +hpp__entry_pair(struct hist_entry *he, struct hist_entry *pair, + int idx, char *buf, size_t size) +{ + double diff; + double ratio; + s64 wdiff; + + switch (idx) { + case PERF_HPP_DIFF__DELTA: + if (pair->diff.computed) + diff = pair->diff.period_ratio_delta; + else + diff = perf_diff__compute_delta(he, pair); + + if (fabs(diff) >= 0.01) + scnprintf(buf, size, "%+4.2F%%", diff); break; + + case PERF_HPP_DIFF__RATIO: + /* No point for ratio number if we are dummy.. */ + if (he->dummy) + break; + + if (pair->diff.computed) + ratio = pair->diff.period_ratio; + else + ratio = perf_diff__compute_ratio(he, pair); + + if (ratio > 0.0) + scnprintf(buf, size, "%14.6F", ratio); + break; + + case PERF_HPP_DIFF__WEIGHTED_DIFF: + /* No point for wdiff number if we are dummy.. */ + if (he->dummy) + break; + + if (pair->diff.computed) + wdiff = pair->diff.wdiff; + else + wdiff = perf_diff__compute_wdiff(he, pair); + + if (wdiff != 0) + scnprintf(buf, size, "%14ld", wdiff); + break; + + case PERF_HPP_DIFF__FORMULA: + perf_diff__formula(he, pair, buf, size); + break; + + case PERF_HPP_DIFF__PERIOD: + scnprintf(buf, size, "%" PRIu64, pair->stat.period); + break; + default: BUG_ON(1); }; +} + +static void +__hpp__entry_global(struct hist_entry *he, int idx, char *buf, size_t size) +{ + struct hist_entry *pair = hist_entry__next_pair(he); + + /* baseline is special */ + if (idx == PERF_HPP_DIFF__BASELINE) + hpp__entry_baseline(he, buf, size); + else { + if (pair) + hpp__entry_pair(he, pair, idx, buf, size); + else + hpp__entry_unpair(he, idx, buf, size); + } +} + +static int hpp__entry_global(struct perf_hpp_fmt *_fmt, struct perf_hpp *hpp, + struct hist_entry *he) +{ + struct diff_hpp_fmt *dfmt = + container_of(_fmt, struct diff_hpp_fmt, fmt); + char buf[MAX_COL_WIDTH] = " "; + + __hpp__entry_global(he, dfmt->idx, buf, MAX_COL_WIDTH); + + if (symbol_conf.field_sep) + return scnprintf(hpp->buf, hpp->size, "%s", buf); + else + return scnprintf(hpp->buf, hpp->size, "%*s", + dfmt->header_width, buf); +} + +static int hpp__header(struct perf_hpp_fmt *fmt, + struct perf_hpp *hpp) +{ + struct diff_hpp_fmt *dfmt = + container_of(fmt, struct diff_hpp_fmt, fmt); + + BUG_ON(!dfmt->header); + return scnprintf(hpp->buf, hpp->size, dfmt->header); +} + +static int hpp__width(struct perf_hpp_fmt *fmt, + struct perf_hpp *hpp __maybe_unused) +{ + struct diff_hpp_fmt *dfmt = + container_of(fmt, struct diff_hpp_fmt, fmt); + + BUG_ON(dfmt->header_width <= 0); + return dfmt->header_width; +} + +#define hpp__color_global hpp__entry_global + +#define FMT(_i, _entry, _color) \ + [_i] = { \ + .fmt = { \ + .header = hpp__header, \ + .width = hpp__width, \ + .entry = hpp__entry_ ## _entry, \ + .color = hpp__color_ ## _color, \ + }, \ + .idx = _i, \ + } + +#define FMT_GLOBAL(_i) FMT(_i, global, global) +#define FMT_BASELINE(_i) FMT(_i, global, baseline) + +static struct diff_hpp_fmt diff_fmt[] = { + FMT_BASELINE(PERF_HPP_DIFF__BASELINE), + FMT_GLOBAL(PERF_HPP_DIFF__PERIOD), + FMT_GLOBAL(PERF_HPP_DIFF__PERIOD_BASELINE), + FMT_GLOBAL(PERF_HPP_DIFF__DELTA), + FMT_GLOBAL(PERF_HPP_DIFF__RATIO), + FMT_GLOBAL(PERF_HPP_DIFF__WEIGHTED_DIFF), + FMT_GLOBAL(PERF_HPP_DIFF__FORMULA), +}; + +static void init_header(struct diff_hpp_fmt *dfmt) +{ +#define MAX_HEADER_NAME 100 + char buf_indent[MAX_HEADER_NAME]; + char buf[MAX_HEADER_NAME]; + const char *header = NULL; + int width = 0; + + BUG_ON(dfmt->idx >= PERF_HPP_DIFF__MAX_INDEX); + header = columns[dfmt->idx].name; + width = columns[dfmt->idx].width; + + /* Only our defined HPP fmts should appear here. */ + BUG_ON(!header); + +#define NAME (data__files_cnt > 2 ? buf : header) + dfmt->header_width = width; + width = (int) strlen(NAME); + if (dfmt->header_width < width) + dfmt->header_width = width; + + scnprintf(buf_indent, MAX_HEADER_NAME, "%*s", + dfmt->header_width, NAME); + + dfmt->header = strdup(buf_indent); +#undef MAX_HEADER_NAME +#undef NAME +} + +static void column_enable(unsigned col) +{ + struct diff_hpp_fmt *dfmt; + + BUG_ON(col >= PERF_HPP_DIFF__MAX_INDEX); + dfmt = &diff_fmt[col]; + init_header(dfmt); + perf_hpp__column_register(&dfmt->fmt); +} + +static void ui_init(void) +{ + /* + * Display baseline/delta/ratio/ + * formula/periods columns. + */ + column_enable(PERF_HPP_DIFF__BASELINE); + column_enable(compute_2_hpp[compute]); if (show_formula) - perf_hpp__column_enable(PERF_HPP__FORMULA); + column_enable(PERF_HPP_DIFF__FORMULA); if (show_period) { - perf_hpp__column_enable(PERF_HPP__PERIOD); - perf_hpp__column_enable(PERF_HPP__PERIOD_BASELINE); + column_enable(PERF_HPP_DIFF__PERIOD); + column_enable(PERF_HPP_DIFF__PERIOD_BASELINE); } } diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index a359b75ce800..dc900d7a190e 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -163,207 +163,6 @@ HPP_PERCENT_FNS(overhead_guest_us, "guest usr", period_guest_us, 9, 8) HPP_RAW_FNS(samples, "Samples", nr_events, 12, 12) HPP_RAW_FNS(period, "Period", period, 12, 12) - -static int hpp__header_baseline(struct perf_hpp_fmt *fmt __maybe_unused, - struct perf_hpp *hpp) -{ - return scnprintf(hpp->buf, hpp->size, "Baseline"); -} - -static int hpp__width_baseline(struct perf_hpp_fmt *fmt __maybe_unused, - struct perf_hpp *hpp __maybe_unused) -{ - return 8; -} - -static double baseline_percent(struct hist_entry *he) -{ - struct hists *hists = he->hists; - return 100.0 * he->stat.period / hists->stats.total_period; -} - -static int hpp__color_baseline(struct perf_hpp_fmt *fmt __maybe_unused, - struct perf_hpp *hpp, struct hist_entry *he) -{ - double percent = baseline_percent(he); - - if (!he->dummy) - return percent_color_snprintf(hpp->buf, hpp->size, - " %6.2f%%", percent); - else - return scnprintf(hpp->buf, hpp->size, " "); -} - -static int hpp__entry_baseline(struct perf_hpp_fmt *_fmt __maybe_unused, - struct perf_hpp *hpp, struct hist_entry *he) -{ - double percent = baseline_percent(he); - const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%"; - - if (!he->dummy) - return scnprintf(hpp->buf, hpp->size, fmt, percent); - else - return scnprintf(hpp->buf, hpp->size, " "); -} - -static int hpp__header_period_baseline(struct perf_hpp_fmt *_fmt __maybe_unused, - struct perf_hpp *hpp) -{ - const char *fmt = symbol_conf.field_sep ? "%s" : "%12s"; - - return scnprintf(hpp->buf, hpp->size, fmt, "Period Base"); -} - -static int hpp__width_period_baseline(struct perf_hpp_fmt *fmt __maybe_unused, - struct perf_hpp *hpp __maybe_unused) -{ - return 12; -} - -static int hpp__entry_period_baseline(struct perf_hpp_fmt *_fmt __maybe_unused, - struct perf_hpp *hpp, struct hist_entry *he) -{ - struct hist_entry *pair = hist_entry__next_pair(he); - u64 period = pair ? pair->stat.period : 0; - const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%12" PRIu64; - - return scnprintf(hpp->buf, hpp->size, fmt, period); -} - -static int hpp__header_delta(struct perf_hpp_fmt *_fmt __maybe_unused, - struct perf_hpp *hpp) -{ - const char *fmt = symbol_conf.field_sep ? "%s" : "%7s"; - - return scnprintf(hpp->buf, hpp->size, fmt, "Delta"); -} - -static int hpp__width_delta(struct perf_hpp_fmt *fmt __maybe_unused, - struct perf_hpp *hpp __maybe_unused) -{ - return 7; -} - -static int hpp__entry_delta(struct perf_hpp_fmt *_fmt __maybe_unused, - struct perf_hpp *hpp, struct hist_entry *he) -{ - struct hist_entry *pair = hist_entry__next_pair(he); - const char *fmt = symbol_conf.field_sep ? "%s" : "%7.7s"; - char buf[32] = " "; - double diff = 0.0; - - if (pair) { - if (he->diff.computed) - diff = he->diff.period_ratio_delta; - else - diff = perf_diff__compute_delta(he, pair); - } - - if (fabs(diff) >= 0.01) - scnprintf(buf, sizeof(buf), "%+4.2F%%", diff); - - return scnprintf(hpp->buf, hpp->size, fmt, buf); -} - -static int hpp__header_ratio(struct perf_hpp_fmt *_fmt __maybe_unused, - struct perf_hpp *hpp) -{ - const char *fmt = symbol_conf.field_sep ? "%s" : "%14s"; - - return scnprintf(hpp->buf, hpp->size, fmt, "Ratio"); -} - -static int hpp__width_ratio(struct perf_hpp_fmt *fmt __maybe_unused, - struct perf_hpp *hpp __maybe_unused) -{ - return 14; -} - -static int hpp__entry_ratio(struct perf_hpp_fmt *_fmt __maybe_unused, - struct perf_hpp *hpp, struct hist_entry *he) -{ - struct hist_entry *pair = hist_entry__next_pair(he); - const char *fmt = symbol_conf.field_sep ? "%s" : "%14s"; - char buf[32] = " "; - double ratio = 0.0; - - /* No point for ratio number if we are dummy.. */ - if (!he->dummy && pair) { - if (he->diff.computed) - ratio = he->diff.period_ratio; - else - ratio = perf_diff__compute_ratio(he, pair); - } - - if (ratio > 0.0) - scnprintf(buf, sizeof(buf), "%+14.6F", ratio); - - return scnprintf(hpp->buf, hpp->size, fmt, buf); -} - -static int hpp__header_wdiff(struct perf_hpp_fmt *_fmt __maybe_unused, - struct perf_hpp *hpp) -{ - const char *fmt = symbol_conf.field_sep ? "%s" : "%14s"; - - return scnprintf(hpp->buf, hpp->size, fmt, "Weighted diff"); -} - -static int hpp__width_wdiff(struct perf_hpp_fmt *fmt __maybe_unused, - struct perf_hpp *hpp __maybe_unused) -{ - return 14; -} - -static int hpp__entry_wdiff(struct perf_hpp_fmt *_fmt __maybe_unused, - struct perf_hpp *hpp, struct hist_entry *he) -{ - struct hist_entry *pair = hist_entry__next_pair(he); - const char *fmt = symbol_conf.field_sep ? "%s" : "%14s"; - char buf[32] = " "; - s64 wdiff = 0; - - /* No point for wdiff number if we are dummy.. */ - if (!he->dummy && pair) { - if (he->diff.computed) - wdiff = he->diff.wdiff; - else - wdiff = perf_diff__compute_wdiff(he, pair); - } - - if (wdiff != 0) - scnprintf(buf, sizeof(buf), "%14ld", wdiff); - - return scnprintf(hpp->buf, hpp->size, fmt, buf); -} - -static int hpp__header_formula(struct perf_hpp_fmt *_fmt __maybe_unused, - struct perf_hpp *hpp) -{ - const char *fmt = symbol_conf.field_sep ? "%s" : "%70s"; - - return scnprintf(hpp->buf, hpp->size, fmt, "Formula"); -} - -static int hpp__width_formula(struct perf_hpp_fmt *fmt __maybe_unused, - struct perf_hpp *hpp __maybe_unused) -{ - return 70; -} - -static int hpp__entry_formula(struct perf_hpp_fmt *_fmt __maybe_unused, - struct perf_hpp *hpp, struct hist_entry *he) -{ - struct hist_entry *pair = hist_entry__next_pair(he); - const char *fmt = symbol_conf.field_sep ? "%s" : "%-70s"; - char buf[96] = " "; - - if (pair) - perf_diff__formula(he, pair, buf, sizeof(buf)); - - return scnprintf(hpp->buf, hpp->size, fmt, buf); -} - #define HPP__COLOR_PRINT_FNS(_name) \ { \ .header = hpp__header_ ## _name, \ @@ -380,19 +179,13 @@ static int hpp__entry_formula(struct perf_hpp_fmt *_fmt __maybe_unused, } struct perf_hpp_fmt perf_hpp__format[] = { - HPP__COLOR_PRINT_FNS(baseline), HPP__COLOR_PRINT_FNS(overhead), HPP__COLOR_PRINT_FNS(overhead_sys), HPP__COLOR_PRINT_FNS(overhead_us), HPP__COLOR_PRINT_FNS(overhead_guest_sys), HPP__COLOR_PRINT_FNS(overhead_guest_us), HPP__PRINT_FNS(samples), - HPP__PRINT_FNS(period), - HPP__PRINT_FNS(period_baseline), - HPP__PRINT_FNS(delta), - HPP__PRINT_FNS(ratio), - HPP__PRINT_FNS(wdiff), - HPP__PRINT_FNS(formula) + HPP__PRINT_FNS(period) }; LIST_HEAD(perf_hpp__list); diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 0c62116d4d3a..79681f62ef2b 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -159,7 +159,7 @@ extern struct list_head perf_hpp__list; extern struct perf_hpp_fmt perf_hpp__format[]; enum { - PERF_HPP__BASELINE, + /* Matches perf_hpp__format array. */ PERF_HPP__OVERHEAD, PERF_HPP__OVERHEAD_SYS, PERF_HPP__OVERHEAD_US, @@ -167,11 +167,6 @@ enum { PERF_HPP__OVERHEAD_GUEST_US, PERF_HPP__SAMPLES, PERF_HPP__PERIOD, - PERF_HPP__PERIOD_BASELINE, - PERF_HPP__DELTA, - PERF_HPP__RATIO, - PERF_HPP__WEIGHTED_DIFF, - PERF_HPP__FORMULA, PERF_HPP__MAX_INDEX }; From c818b49820aea96d6a1b43815bae0ee38b09ca0d Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sat, 1 Dec 2012 21:57:04 +0100 Subject: [PATCH 0067/3400] perf diff: Move columns into struct data__file Another step towards multiple data files support. Having columns definition within struct data__file force each data file having its own columns. Signed-off-by: Jiri Olsa Reviewed-by: Namhyung Kim Cc: Peter Zijlstra Cc: Paul Mackerras Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Namhyung Kim Link: http://lkml.kernel.org/n/tip-lnfqj7k7fqw8bz07pupi5464@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-diff.c | 97 ++++++++++++++++++++++----------------- 1 file changed, 55 insertions(+), 42 deletions(-) diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 8734f1cee6dc..7787ee24a18a 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -44,6 +44,7 @@ struct data__file { struct perf_session *session; const char *file; int idx; + struct diff_hpp_fmt fmt[PERF_HPP_DIFF__MAX_INDEX]; }; static struct data__file *data__files; @@ -584,6 +585,17 @@ static void data_process(void) } } +static void data__free(struct data__file *d) +{ + int col; + + for (col = 0; col < PERF_HPP_DIFF__MAX_INDEX; col++) { + struct diff_hpp_fmt *fmt = &d->fmt[col]; + + free(fmt->header); + } +} + static int __cmd_diff(void) { struct data__file *d; @@ -613,6 +625,8 @@ static int __cmd_diff(void) data__for_each_file(i, d) { if (d->session) perf_session__delete(d->session); + + data__free(d); } free(data__files); @@ -818,32 +832,6 @@ static int hpp__width(struct perf_hpp_fmt *fmt, return dfmt->header_width; } -#define hpp__color_global hpp__entry_global - -#define FMT(_i, _entry, _color) \ - [_i] = { \ - .fmt = { \ - .header = hpp__header, \ - .width = hpp__width, \ - .entry = hpp__entry_ ## _entry, \ - .color = hpp__color_ ## _color, \ - }, \ - .idx = _i, \ - } - -#define FMT_GLOBAL(_i) FMT(_i, global, global) -#define FMT_BASELINE(_i) FMT(_i, global, baseline) - -static struct diff_hpp_fmt diff_fmt[] = { - FMT_BASELINE(PERF_HPP_DIFF__BASELINE), - FMT_GLOBAL(PERF_HPP_DIFF__PERIOD), - FMT_GLOBAL(PERF_HPP_DIFF__PERIOD_BASELINE), - FMT_GLOBAL(PERF_HPP_DIFF__DELTA), - FMT_GLOBAL(PERF_HPP_DIFF__RATIO), - FMT_GLOBAL(PERF_HPP_DIFF__WEIGHTED_DIFF), - FMT_GLOBAL(PERF_HPP_DIFF__FORMULA), -}; - static void init_header(struct diff_hpp_fmt *dfmt) { #define MAX_HEADER_NAME 100 @@ -873,31 +861,56 @@ static void init_header(struct diff_hpp_fmt *dfmt) #undef NAME } -static void column_enable(unsigned col) +static void data__hpp_register(struct data__file *d, int idx) { - struct diff_hpp_fmt *dfmt; + struct diff_hpp_fmt *dfmt = &d->fmt[idx]; + struct perf_hpp_fmt *fmt = &dfmt->fmt; + + dfmt->idx = idx; + + fmt->header = hpp__header; + fmt->width = hpp__width; + fmt->entry = hpp__entry_global; + + /* TODO more colors */ + if (idx == PERF_HPP_DIFF__BASELINE) + fmt->color = hpp__color_baseline; - BUG_ON(col >= PERF_HPP_DIFF__MAX_INDEX); - dfmt = &diff_fmt[col]; init_header(dfmt); - perf_hpp__column_register(&dfmt->fmt); + perf_hpp__column_register(fmt); } static void ui_init(void) { - /* - * Display baseline/delta/ratio/ - * formula/periods columns. - */ - column_enable(PERF_HPP_DIFF__BASELINE); - column_enable(compute_2_hpp[compute]); + struct data__file *d; + int i; - if (show_formula) - column_enable(PERF_HPP_DIFF__FORMULA); + data__for_each_file(i, d) { - if (show_period) { - column_enable(PERF_HPP_DIFF__PERIOD); - column_enable(PERF_HPP_DIFF__PERIOD_BASELINE); + /* + * Baseline or compute realted columns: + * + * PERF_HPP_DIFF__BASELINE + * PERF_HPP_DIFF__DELTA + * PERF_HPP_DIFF__RATIO + * PERF_HPP_DIFF__WEIGHTED_DIFF + */ + data__hpp_register(d, i ? compute_2_hpp[compute] : + PERF_HPP_DIFF__BASELINE); + + /* + * And the rest: + * + * PERF_HPP_DIFF__FORMULA + * PERF_HPP_DIFF__PERIOD + * PERF_HPP_DIFF__PERIOD_BASELINE + */ + if (show_formula && i) + data__hpp_register(d, PERF_HPP_DIFF__FORMULA); + + if (show_period) + data__hpp_register(d, i ? PERF_HPP_DIFF__PERIOD : + PERF_HPP_DIFF__PERIOD_BASELINE); } } From 22aeb7f597650284591ad0f61b069ded3ecf91db Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sat, 1 Dec 2012 22:00:00 +0100 Subject: [PATCH 0068/3400] perf diff: Change diff command to work over multiple data files Adding diff command the flexibility to specify multiple data files on input. If not input file is given the standard behaviour stands and diff inspects 'perf.data' and 'perf.data.old' files. Signed-off-by: Jiri Olsa Reviewed-by: Namhyung Kim Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-8j3xer54ltvs76t0fh01gcvu@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-diff.c | 101 +++++++++++++++++++++++++------------- 1 file changed, 67 insertions(+), 34 deletions(-) diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 7787ee24a18a..cc7bf4faacd4 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -44,6 +44,7 @@ struct data__file { struct perf_session *session; const char *file; int idx; + struct hists *hists; struct diff_hpp_fmt fmt[PERF_HPP_DIFF__MAX_INDEX]; }; @@ -56,6 +57,7 @@ static int data__files_cnt; i++, d = &data__files[i]) #define data__for_each_file(i, d) data__for_each_file_start(i, d, 0) +#define data__for_each_file_new(i, d) data__for_each_file_start(i, d, 1) static char diff__default_sort_order[] = "dso,symbol"; static bool force; @@ -525,23 +527,19 @@ static void hists__compute_resort(struct hists *hists) } } -static void hists__process(struct hists *base, struct hists *new) +static void hists__process(struct hists *hists) { - hists__match(base, new); - if (show_baseline_only) - hists__baseline_only(base); - else - hists__link(base, new); + hists__baseline_only(hists); if (sort_compute) { - hists__precompute(base); - hists__compute_resort(base); + hists__precompute(hists); + hists__compute_resort(hists); } else { - hists__output_resort(base); + hists__output_resort(hists); } - hists__fprintf(base, true, 0, 0, 0, stdout); + hists__fprintf(hists, true, 0, 0, 0, stdout); } static void data__fprintf(void) @@ -561,27 +559,40 @@ static void data__fprintf(void) static void data_process(void) { - struct perf_evlist *evlist_old = data__files[0].session->evlist; - struct perf_evlist *evlist_new = data__files[1].session->evlist; - struct perf_evsel *evsel_old; + struct perf_evlist *evlist_base = data__files[0].session->evlist; + struct perf_evsel *evsel_base; bool first = true; - list_for_each_entry(evsel_old, &evlist_old->entries, node) { - struct perf_evsel *evsel_new; + list_for_each_entry(evsel_base, &evlist_base->entries, node) { + struct data__file *d; + int i; - evsel_new = evsel_match(evsel_old, evlist_new); - if (!evsel_new) - continue; + data__for_each_file_new(i, d) { + struct perf_evlist *evlist = d->session->evlist; + struct perf_evsel *evsel; + + evsel = evsel_match(evsel_base, evlist); + if (!evsel) + continue; + + d->hists = &evsel->hists; + + hists__match(&evsel_base->hists, &evsel->hists); + + if (!show_baseline_only) + hists__link(&evsel_base->hists, + &evsel->hists); + } fprintf(stdout, "%s# Event '%s'\n#\n", first ? "" : "\n", - perf_evsel__name(evsel_old)); + perf_evsel__name(evsel_base)); first = false; - if (verbose) + if (verbose || data__files_cnt > 2) data__fprintf(); - hists__process(&evsel_old->hists, &evsel_new->hists); + hists__process(&evsel_base->hists); } } @@ -780,10 +791,29 @@ hpp__entry_pair(struct hist_entry *he, struct hist_entry *pair, }; } -static void -__hpp__entry_global(struct hist_entry *he, int idx, char *buf, size_t size) +static struct hist_entry *get_pair(struct hist_entry *he, + struct diff_hpp_fmt *dfmt) { - struct hist_entry *pair = hist_entry__next_pair(he); + void *ptr = dfmt - dfmt->idx; + struct data__file *d = container_of(ptr, struct data__file, fmt); + + if (hist_entry__has_pairs(he)) { + struct hist_entry *pair; + + list_for_each_entry(pair, &he->pairs.head, pairs.node) + if (pair->hists == d->hists) + return pair; + } + + return NULL; +} + +static void +__hpp__entry_global(struct hist_entry *he, struct diff_hpp_fmt *dfmt, + char *buf, size_t size) +{ + struct hist_entry *pair = get_pair(he, dfmt); + int idx = dfmt->idx; /* baseline is special */ if (idx == PERF_HPP_DIFF__BASELINE) @@ -803,7 +833,7 @@ static int hpp__entry_global(struct perf_hpp_fmt *_fmt, struct perf_hpp *hpp, container_of(_fmt, struct diff_hpp_fmt, fmt); char buf[MAX_COL_WIDTH] = " "; - __hpp__entry_global(he, dfmt->idx, buf, MAX_COL_WIDTH); + __hpp__entry_global(he, dfmt, buf, MAX_COL_WIDTH); if (symbol_conf.field_sep) return scnprintf(hpp->buf, hpp->size, "%s", buf); @@ -832,7 +862,7 @@ static int hpp__width(struct perf_hpp_fmt *fmt, return dfmt->header_width; } -static void init_header(struct diff_hpp_fmt *dfmt) +static void init_header(struct data__file *d, struct diff_hpp_fmt *dfmt) { #define MAX_HEADER_NAME 100 char buf_indent[MAX_HEADER_NAME]; @@ -847,6 +877,9 @@ static void init_header(struct diff_hpp_fmt *dfmt) /* Only our defined HPP fmts should appear here. */ BUG_ON(!header); + if (data__files_cnt > 2) + scnprintf(buf, MAX_HEADER_NAME, "%s/%d", header, d->idx); + #define NAME (data__files_cnt > 2 ? buf : header) dfmt->header_width = width; width = (int) strlen(NAME); @@ -876,7 +909,7 @@ static void data__hpp_register(struct data__file *d, int idx) if (idx == PERF_HPP_DIFF__BASELINE) fmt->color = hpp__color_baseline; - init_header(dfmt); + init_header(d, dfmt); perf_hpp__column_register(fmt); } @@ -921,18 +954,18 @@ static int data_init(int argc, const char **argv) "perf.data.old", "perf.data", }; + bool use_default = true; int i; data__files_cnt = 2; if (argc) { - if (argc > 2) - usage_with_options(diff_usage, options); - if (argc == 2) { - defaults[0] = argv[0]; - defaults[1] = argv[1]; - } else + if (argc == 1) defaults[1] = argv[0]; + else { + data__files_cnt = argc; + use_default = false; + } } else if (symbol_conf.default_guest_vmlinux_name || symbol_conf.default_guest_kallsyms) { defaults[0] = "perf.data.host"; @@ -944,7 +977,7 @@ static int data_init(int argc, const char **argv) return -ENOMEM; data__for_each_file(i, d) { - d->file = defaults[i]; + d->file = use_default ? defaults[i] : argv[i]; d->idx = i; } From 3a3beae81dae4960cac99fb6deeaca371f0790eb Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Wed, 24 Oct 2012 14:56:51 +0200 Subject: [PATCH 0069/3400] perf diff: Update perf diff documentation for multiple data comparison Updating perf diff documentation to include multiple perf data files comparison. Signed-off-by: Jiri Olsa Reviewed-by: Namhyung Kim Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-tr6su3wfm20k2m5npjggyvtw@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-diff.txt | 73 ++++++++++++++++++++++---- 1 file changed, 64 insertions(+), 9 deletions(-) diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt index 5b3123d5721f..2d134f3f1c9d 100644 --- a/tools/perf/Documentation/perf-diff.txt +++ b/tools/perf/Documentation/perf-diff.txt @@ -3,17 +3,17 @@ perf-diff(1) NAME ---- -perf-diff - Read two perf.data files and display the differential profile +perf-diff - Read perf.data files and display the differential profile SYNOPSIS -------- [verse] -'perf diff' [oldfile] [newfile] +'perf diff' [baseline file] [data file1] [[data file2] ... ] DESCRIPTION ----------- -This command displays the performance difference amongst two perf.data files -captured via perf record. +This command displays the performance difference amongst two or more perf.data +files captured via perf record. If no parameters are passed it will assume perf.data.old and perf.data. @@ -87,6 +87,59 @@ OPTIONS --formula:: Show formula for given computation. +COMPARISON +---------- +The comparison is governed by the baseline file. The baseline perf.data +file is iterated for samples. All other perf.data files specified on +the command line are searched for the baseline sample pair. If the pair +is found, specified computation is made and result is displayed. + +All samples from non-baseline perf.data files, that do not match any +baseline entry, are displayed with empty space within baseline column +and possible computation results (delta) in their related column. + +Example files samples: +- file A with samples f1, f2, f3, f4, f6 +- file B with samples f2, f4, f5 +- file C with samples f1, f2, f5 + +Example output: + x - computation takes place for pair + b - baseline sample percentage + +- perf diff A B C + + baseline/A compute/B compute/C samples + --------------------------------------- + b x f1 + b x x f2 + b f3 + b x f4 + b f6 + x x f5 + +- perf diff B A C + + baseline/B compute/A compute/C samples + --------------------------------------- + b x x f2 + b x f4 + b x f5 + x x f1 + x f3 + x f6 + +- perf diff C B A + + baseline/C compute/B compute/A samples + --------------------------------------- + b x f1 + b x x f2 + b x f5 + x f3 + x x f4 + x f6 + COMPARISON METHODS ------------------ delta @@ -96,7 +149,7 @@ If specified the 'Delta' column is displayed with value 'd' computed as: d = A->period_percent - B->period_percent with: - - A/B being matching hist entry from first/second file specified + - A/B being matching hist entry from data/baseline file specified (or perf.data/perf.data.old) respectively. - period_percent being the % of the hist entry period value within @@ -109,24 +162,26 @@ If specified the 'Ratio' column is displayed with value 'r' computed as: r = A->period / B->period with: - - A/B being matching hist entry from first/second file specified + - A/B being matching hist entry from data/baseline file specified (or perf.data/perf.data.old) respectively. - period being the hist entry period value -wdiff -~~~~~ +wdiff:WEIGHT-B,WEIGHT-A +~~~~~~~~~~~~~~~~~~~~~~~ If specified the 'Weighted diff' column is displayed with value 'd' computed as: d = B->period * WEIGHT-A - A->period * WEIGHT-B - - A/B being matching hist entry from first/second file specified + - A/B being matching hist entry from data/baseline file specified (or perf.data/perf.data.old) respectively. - period being the hist entry period value - WEIGHT-A/WEIGHT-B being user suplied weights in the the '-c' option behind ':' separator like '-c wdiff:1,2'. + - WIEGHT-A being the weight of the data file + - WIEGHT-B being the weight of the baseline data file SEE ALSO -------- From ef358e6dcaba76d1c00dba5fc6cd4cde1d1a2f13 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 21 Oct 2012 23:31:51 +0200 Subject: [PATCH 0070/3400] perf diff: Making compute functions static All compute functions are now local to the diff command, making them static. Signed-off-by: Jiri Olsa Reviewed-by: Namhyung Kim Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-mpmm8l71mnlp7139voba3aak@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-diff.c | 30 +++++++++++++++--------------- tools/perf/util/hist.h | 7 ------- 2 files changed, 15 insertions(+), 22 deletions(-) diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index cc7bf4faacd4..f2fbf69ad984 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -224,23 +224,23 @@ static int setup_compute(const struct option *opt, const char *str, return -EINVAL; } -double perf_diff__period_percent(struct hist_entry *he, u64 period) +static double period_percent(struct hist_entry *he, u64 period) { u64 total = he->hists->stats.total_period; return (period * 100.0) / total; } -double perf_diff__compute_delta(struct hist_entry *he, struct hist_entry *pair) +static double compute_delta(struct hist_entry *he, struct hist_entry *pair) { - double old_percent = perf_diff__period_percent(he, he->stat.period); - double new_percent = perf_diff__period_percent(pair, pair->stat.period); + double old_percent = period_percent(he, he->stat.period); + double new_percent = period_percent(pair, pair->stat.period); pair->diff.period_ratio_delta = new_percent - old_percent; pair->diff.computed = true; return pair->diff.period_ratio_delta; } -double perf_diff__compute_ratio(struct hist_entry *he, struct hist_entry *pair) +static double compute_ratio(struct hist_entry *he, struct hist_entry *pair) { double old_period = he->stat.period ?: 1; double new_period = pair->stat.period; @@ -250,7 +250,7 @@ double perf_diff__compute_ratio(struct hist_entry *he, struct hist_entry *pair) return pair->diff.period_ratio; } -s64 perf_diff__compute_wdiff(struct hist_entry *he, struct hist_entry *pair) +static s64 compute_wdiff(struct hist_entry *he, struct hist_entry *pair) { u64 old_period = he->stat.period; u64 new_period = pair->stat.period; @@ -292,8 +292,8 @@ static int formula_wdiff(struct hist_entry *he, struct hist_entry *pair, new_period, compute_wdiff_w2, old_period, compute_wdiff_w1); } -int perf_diff__formula(struct hist_entry *he, struct hist_entry *pair, - char *buf, size_t size) +static int formula_fprintf(struct hist_entry *he, struct hist_entry *pair, + char *buf, size_t size) { switch (compute) { case COMPUTE_DELTA: @@ -421,13 +421,13 @@ static void hists__precompute(struct hists *hists) switch (compute) { case COMPUTE_DELTA: - perf_diff__compute_delta(he, pair); + compute_delta(he, pair); break; case COMPUTE_RATIO: - perf_diff__compute_ratio(he, pair); + compute_ratio(he, pair); break; case COMPUTE_WEIGHTED_DIFF: - perf_diff__compute_wdiff(he, pair); + compute_wdiff(he, pair); break; default: BUG_ON(1); @@ -744,7 +744,7 @@ hpp__entry_pair(struct hist_entry *he, struct hist_entry *pair, if (pair->diff.computed) diff = pair->diff.period_ratio_delta; else - diff = perf_diff__compute_delta(he, pair); + diff = compute_delta(he, pair); if (fabs(diff) >= 0.01) scnprintf(buf, size, "%+4.2F%%", diff); @@ -758,7 +758,7 @@ hpp__entry_pair(struct hist_entry *he, struct hist_entry *pair, if (pair->diff.computed) ratio = pair->diff.period_ratio; else - ratio = perf_diff__compute_ratio(he, pair); + ratio = compute_ratio(he, pair); if (ratio > 0.0) scnprintf(buf, size, "%14.6F", ratio); @@ -772,14 +772,14 @@ hpp__entry_pair(struct hist_entry *he, struct hist_entry *pair, if (pair->diff.computed) wdiff = pair->diff.wdiff; else - wdiff = perf_diff__compute_wdiff(he, pair); + wdiff = compute_wdiff(he, pair); if (wdiff != 0) scnprintf(buf, size, "%14ld", wdiff); break; case PERF_HPP_DIFF__FORMULA: - perf_diff__formula(he, pair, buf, size); + formula_fprintf(he, pair, buf, size); break; case PERF_HPP_DIFF__PERIOD: diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 79681f62ef2b..bfcbb11c2648 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -242,11 +242,4 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused, #endif unsigned int hists__sort_list_width(struct hists *self); - -double perf_diff__compute_delta(struct hist_entry *he, struct hist_entry *pair); -double perf_diff__compute_ratio(struct hist_entry *he, struct hist_entry *pair); -s64 perf_diff__compute_wdiff(struct hist_entry *he, struct hist_entry *pair); -int perf_diff__formula(struct hist_entry *he, struct hist_entry *pair, - char *buf, size_t size); -double perf_diff__period_percent(struct hist_entry *he, u64 period); #endif /* __PERF_HIST_H */ From 5f3f8d3b1207cba3664d57a33de43f5ee11c8a06 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 25 Nov 2012 23:10:20 +0100 Subject: [PATCH 0071/3400] perf diff: Add generic order option for compute sorting Adding option 'o' to allow sorting based on the input file number. By default (without -o option) the output is sorted on baseline. Also removing '+' sorting support from -c option, because it's not needed anymore. Signed-off-by: Jiri Olsa Reviewed-by: Namhyung Kim Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-l7dvhgt0azm7yiqg3fbn4dxw@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-diff.txt | 6 +- tools/perf/builtin-diff.c | 95 ++++++++++++++++++-------- 2 files changed, 70 insertions(+), 31 deletions(-) diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt index 2d134f3f1c9d..fdfceee0ffd0 100644 --- a/tools/perf/Documentation/perf-diff.txt +++ b/tools/perf/Documentation/perf-diff.txt @@ -75,8 +75,6 @@ OPTIONS -c:: --compute:: Differential computation selection - delta,ratio,wdiff (default is delta). - If '+' is specified as a first character, the output is sorted based - on the computation results. See COMPARISON METHODS section for more info. -p:: @@ -87,6 +85,10 @@ OPTIONS --formula:: Show formula for given computation. +-o:: +--order:: + Specify compute sorting column number. + COMPARISON ---------- The comparison is governed by the baseline file. The baseline perf.data diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index f2fbf69ad984..93de3ac177c5 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -64,7 +64,7 @@ static bool force; static bool show_period; static bool show_formula; static bool show_baseline_only; -static bool sort_compute; +static unsigned int sort_compute; static s64 compute_wdiff_w1; static s64 compute_wdiff_w2; @@ -188,13 +188,6 @@ static int setup_compute(const struct option *opt, const char *str, return 0; } - if (*str == '+') { - sort_compute = true; - cstr = (char *) ++str; - if (!*str) - return 0; - } - option = strchr(str, ':'); if (option) { unsigned len = option++ - str; @@ -378,6 +371,29 @@ static void perf_evlist__collapse_resort(struct perf_evlist *evlist) } } +static struct hist_entry* +get_pair_data(struct hist_entry *he, struct data__file *d) +{ + if (hist_entry__has_pairs(he)) { + struct hist_entry *pair; + + list_for_each_entry(pair, &he->pairs.head, pairs.node) + if (pair->hists == d->hists) + return pair; + } + + return NULL; +} + +static struct hist_entry* +get_pair_fmt(struct hist_entry *he, struct diff_hpp_fmt *dfmt) +{ + void *ptr = dfmt - dfmt->idx; + struct data__file *d = container_of(ptr, struct data__file, fmt); + + return get_pair_data(he, d); +} + static void hists__baseline_only(struct hists *hists) { struct rb_root *root; @@ -412,10 +428,12 @@ static void hists__precompute(struct hists *hists) next = rb_first(root); while (next != NULL) { - struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node_in); - struct hist_entry *pair = hist_entry__next_pair(he); + struct hist_entry *he, *pair; + he = rb_entry(next, struct hist_entry, rb_node_in); next = rb_next(&he->rb_node_in); + + pair = get_pair_data(he, &data__files[sort_compute]); if (!pair) continue; @@ -446,7 +464,7 @@ static int64_t cmp_doubles(double l, double r) } static int64_t -hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right, +__hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right, int c) { switch (c) { @@ -478,6 +496,36 @@ hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right, return 0; } +static int64_t +hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right, + int c) +{ + bool pairs_left = hist_entry__has_pairs(left); + bool pairs_right = hist_entry__has_pairs(right); + struct hist_entry *p_right, *p_left; + + if (!pairs_left && !pairs_right) + return 0; + + if (!pairs_left || !pairs_right) + return pairs_left ? -1 : 1; + + p_left = get_pair_data(left, &data__files[sort_compute]); + p_right = get_pair_data(right, &data__files[sort_compute]); + + if (!p_left && !p_right) + return 0; + + if (!p_left || !p_right) + return p_left ? -1 : 1; + + /* + * We have 2 entries of same kind, let's + * make the data comparison. + */ + return __hist_entry__cmp_compute(p_left, p_right, c); +} + static void insert_hist_entry_by_compute(struct rb_root *root, struct hist_entry *he, int c) @@ -680,6 +728,7 @@ static const struct option options[] = { "columns '.' is reserved."), OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", "Look for files with symbols relative to this directory"), + OPT_UINTEGER('o', "order", &sort_compute, "Specify compute sorting."), OPT_END() }; @@ -791,28 +840,11 @@ hpp__entry_pair(struct hist_entry *he, struct hist_entry *pair, }; } -static struct hist_entry *get_pair(struct hist_entry *he, - struct diff_hpp_fmt *dfmt) -{ - void *ptr = dfmt - dfmt->idx; - struct data__file *d = container_of(ptr, struct data__file, fmt); - - if (hist_entry__has_pairs(he)) { - struct hist_entry *pair; - - list_for_each_entry(pair, &he->pairs.head, pairs.node) - if (pair->hists == d->hists) - return pair; - } - - return NULL; -} - static void __hpp__entry_global(struct hist_entry *he, struct diff_hpp_fmt *dfmt, char *buf, size_t size) { - struct hist_entry *pair = get_pair(he, dfmt); + struct hist_entry *pair = get_pair_fmt(he, dfmt); int idx = dfmt->idx; /* baseline is special */ @@ -972,6 +1004,11 @@ static int data_init(int argc, const char **argv) defaults[1] = "perf.data.guest"; } + if (sort_compute >= (unsigned int) data__files_cnt) { + pr_err("Order option out of limit.\n"); + return -EINVAL; + } + data__files = zalloc(sizeof(*data__files) * data__files_cnt); if (!data__files) return -ENOMEM; From be0e6d105d31a5818608ae243411aef5c976147a Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 4 Feb 2013 16:33:19 +0100 Subject: [PATCH 0072/3400] perf tools: Move hist_entry__period_snprintf into stdio code Moving hist_entry__period_snprintf function into stdio code and making it static, as it's no longer used anywhere else. Signed-off-by: Jiri Olsa Reviewed-by: Namhyung Kim Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-ah8ms343h8xygt20iqz91kz4@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/hist.c | 40 ------------------------------------- tools/perf/ui/stdio/hist.c | 41 ++++++++++++++++++++++++++++++++++++++ tools/perf/util/hist.h | 2 -- 3 files changed, 41 insertions(+), 42 deletions(-) diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index dc900d7a190e..0a193281eba8 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -236,46 +236,6 @@ void perf_hpp__column_enable(unsigned col) perf_hpp__column_register(&perf_hpp__format[col]); } -static inline void advance_hpp(struct perf_hpp *hpp, int inc) -{ - hpp->buf += inc; - hpp->size -= inc; -} - -int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he, - bool color) -{ - const char *sep = symbol_conf.field_sep; - struct perf_hpp_fmt *fmt; - char *start = hpp->buf; - int ret; - bool first = true; - - if (symbol_conf.exclude_other && !he->parent) - return 0; - - perf_hpp__for_each_format(fmt) { - /* - * If there's no field_sep, we still need - * to display initial ' '. - */ - if (!sep || !first) { - ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: " "); - advance_hpp(hpp, ret); - } else - first = false; - - if (color && fmt->color) - ret = fmt->color(fmt, hpp, he); - else - ret = fmt->entry(fmt, hpp, he); - - advance_hpp(hpp, ret); - } - - return hpp->buf - start; -} - int hist_entry__sort_snprintf(struct hist_entry *he, char *s, size_t size, struct hists *hists) { diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c index ee703720649d..5b4fb330f656 100644 --- a/tools/perf/ui/stdio/hist.c +++ b/tools/perf/ui/stdio/hist.c @@ -308,6 +308,47 @@ static size_t hist_entry__callchain_fprintf(struct hist_entry *he, return hist_entry_callchain__fprintf(he, total_period, left_margin, fp); } +static inline void advance_hpp(struct perf_hpp *hpp, int inc) +{ + hpp->buf += inc; + hpp->size -= inc; +} + +static int hist_entry__period_snprintf(struct perf_hpp *hpp, + struct hist_entry *he, + bool color) +{ + const char *sep = symbol_conf.field_sep; + struct perf_hpp_fmt *fmt; + char *start = hpp->buf; + int ret; + bool first = true; + + if (symbol_conf.exclude_other && !he->parent) + return 0; + + perf_hpp__for_each_format(fmt) { + /* + * If there's no field_sep, we still need + * to display initial ' '. + */ + if (!sep || !first) { + ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: " "); + advance_hpp(hpp, ret); + } else + first = false; + + if (color && fmt->color) + ret = fmt->color(fmt, hpp, he); + else + ret = fmt->entry(fmt, hpp, he); + + advance_hpp(hpp, ret); + } + + return hpp->buf - start; +} + static int hist_entry__fprintf(struct hist_entry *he, size_t size, struct hists *hists, FILE *fp) { diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index bfcbb11c2648..1329b6b6ffe6 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -174,8 +174,6 @@ enum { void perf_hpp__init(void); void perf_hpp__column_register(struct perf_hpp_fmt *format); void perf_hpp__column_enable(unsigned col); -int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he, - bool color); struct perf_evlist; From 8f89140ae41ccd9c63344e6823faa862aa7435e3 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 28 Jun 2013 16:24:10 -0700 Subject: [PATCH 0073/3400] cgroup: minor updates around cgroup_clear_directory() * Rename it to cgroup_clear_dir() and make it take the pointer to the target cgroup instead of the the dentry. This makes the function consistent with its counterpart - cgroup_populate_dir(). * Move cgroup_clear_directory() invocation from cgroup_d_remove_dir() to cgroup_remount() so that the function doesn't have to determine the cgroup pointer back from the dentry. cgroup_d_remove_dir() now only deals with vfs, which is slightly cleaner. This patch doesn't introduce any functional differences. Signed-off-by: Tejun Heo Acked-by: Li Zefan --- kernel/cgroup.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index e5583d10a325..09bfa870e698 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -957,15 +957,14 @@ static void cgroup_rm_file(struct cgroup *cgrp, const struct cftype *cft) } /** - * cgroup_clear_directory - selective removal of base and subsystem files - * @dir: directory containing the files + * cgroup_clear_dir - selective removal of base and subsystem files + * @cgrp: target cgroup * @base_files: true if the base files should be removed * @subsys_mask: mask of the subsystem ids whose files should be removed */ -static void cgroup_clear_directory(struct dentry *dir, bool base_files, - unsigned long subsys_mask) +static void cgroup_clear_dir(struct cgroup *cgrp, bool base_files, + unsigned long subsys_mask) { - struct cgroup *cgrp = __d_cgrp(dir); struct cgroup_subsys *ss; for_each_root_subsys(cgrp->root, ss) { @@ -987,9 +986,6 @@ static void cgroup_clear_directory(struct dentry *dir, bool base_files, static void cgroup_d_remove_dir(struct dentry *dentry) { struct dentry *parent; - struct cgroupfs_root *root = dentry->d_sb->s_fs_info; - - cgroup_clear_directory(dentry, true, root->subsys_mask); parent = dentry->d_parent; spin_lock(&parent->d_lock); @@ -1376,7 +1372,7 @@ static int cgroup_remount(struct super_block *sb, int *flags, char *data) * this before rebind_subsystems, since rebind_subsystems may * change this hierarchy's subsys_list. */ - cgroup_clear_directory(cgrp->dentry, false, removed_mask); + cgroup_clear_dir(cgrp, false, removed_mask); ret = rebind_subsystems(root, added_mask, removed_mask); if (ret) { @@ -4541,9 +4537,10 @@ static int cgroup_destroy_locked(struct cgroup *cgrp) raw_spin_unlock(&release_list_lock); /* - * Remove @cgrp directory. The removal puts the base ref but we - * aren't quite done with @cgrp yet, so hold onto it. + * Clear and remove @cgrp directory. The removal puts the base ref + * but we aren't quite done with @cgrp yet, so hold onto it. */ + cgroup_clear_dir(cgrp, true, cgrp->root->subsys_mask); dget(d); cgroup_d_remove_dir(d); From b1f28d3109349899e87377e89f9d8ab5bc95ec57 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 28 Jun 2013 16:24:10 -0700 Subject: [PATCH 0074/3400] cgroup: fix error path of cgroup_addrm_files() cgroup_addrm_files() mishandled error return value from cgroup_add_file() and returns error iff the last file fails to create. As we're in the process of cleaning up file add/rm error handling and will reliably propagate file creation failures, there's no point in keeping adding files after a failure. Replace the broken error collection logic with immediate error return. While at it, add lockdep assertions and function comment. Signed-off-by: Tejun Heo Acked-by: Li Zefan --- kernel/cgroup.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 09bfa870e698..9b16d75bec63 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -2780,11 +2780,26 @@ out: return error; } +/** + * cgroup_addrm_files - add or remove files to a cgroup directory + * @cgrp: the target cgroup + * @subsys: the subsystem of files to be added + * @cfts: array of cftypes to be added + * @is_add: whether to add or remove + * + * Depending on @is_add, add or remove files defined by @cfts on @cgrp. + * All @cfts should belong to @subsys. For removals, this function never + * fails. If addition fails, this function doesn't remove files already + * added. The caller is responsible for cleaning up. + */ static int cgroup_addrm_files(struct cgroup *cgrp, struct cgroup_subsys *subsys, struct cftype cfts[], bool is_add) { struct cftype *cft; - int err, ret = 0; + int ret; + + lockdep_assert_held(&cgrp->dentry->d_inode->i_mutex); + lockdep_assert_held(&cgroup_mutex); for (cft = cfts; cft->name[0] != '\0'; cft++) { /* does cft->flags tell us to skip this file on @cgrp? */ @@ -2796,16 +2811,17 @@ static int cgroup_addrm_files(struct cgroup *cgrp, struct cgroup_subsys *subsys, continue; if (is_add) { - err = cgroup_add_file(cgrp, subsys, cft); - if (err) + ret = cgroup_add_file(cgrp, subsys, cft); + if (ret) { pr_warn("cgroup_addrm_files: failed to add %s, err=%d\n", - cft->name, err); - ret = err; + cft->name, ret); + return ret; + } } else { cgroup_rm_file(cgrp, cft); } } - return ret; + return 0; } static void cgroup_cfts_prepare(void) From 9ccece80ae19ed42439fc0ced76858f189cd41e8 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 28 Jun 2013 16:24:11 -0700 Subject: [PATCH 0075/3400] cgroup: fix cgroup_add_cftypes() error handling cgroup_add_cftypes() uses cgroup_cfts_commit() to actually create the files; however, both functions ignore actual file creation errors and just assume success. This can lead to, for example, blkio hierarchy with some of the cgroups with only subset of interface files populated after cfq-iosched is loaded under heavy memory pressure, which is nasty. This patch updates cgroup_cfts_commit() and cgroup_add_cftypes() to guarantee that all files are created on success and no file is created on failure. Signed-off-by: Tejun Heo Acked-by: Li Zefan --- kernel/cgroup.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 9b16d75bec63..36c0ccc921f4 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -2836,8 +2836,8 @@ static void cgroup_cfts_prepare(void) mutex_lock(&cgroup_mutex); } -static void cgroup_cfts_commit(struct cgroup_subsys *ss, - struct cftype *cfts, bool is_add) +static int cgroup_cfts_commit(struct cgroup_subsys *ss, + struct cftype *cfts, bool is_add) __releases(&cgroup_mutex) { LIST_HEAD(pending); @@ -2846,12 +2846,13 @@ static void cgroup_cfts_commit(struct cgroup_subsys *ss, struct dentry *prev = NULL; struct inode *inode; u64 update_before; + int ret = 0; /* %NULL @cfts indicates abort and don't bother if @ss isn't attached */ if (!cfts || ss->root == &cgroup_dummy_root || !atomic_inc_not_zero(&sb->s_active)) { mutex_unlock(&cgroup_mutex); - return; + return 0; } /* @@ -2867,10 +2868,13 @@ static void cgroup_cfts_commit(struct cgroup_subsys *ss, inode = root->dentry->d_inode; mutex_lock(&inode->i_mutex); mutex_lock(&cgroup_mutex); - cgroup_addrm_files(root, ss, cfts, is_add); + ret = cgroup_addrm_files(root, ss, cfts, is_add); mutex_unlock(&cgroup_mutex); mutex_unlock(&inode->i_mutex); + if (ret) + goto out_deact; + /* add/rm files for all cgroups created before */ rcu_read_lock(); cgroup_for_each_descendant_pre(cgrp, root) { @@ -2887,15 +2891,19 @@ static void cgroup_cfts_commit(struct cgroup_subsys *ss, mutex_lock(&inode->i_mutex); mutex_lock(&cgroup_mutex); if (cgrp->serial_nr < update_before && !cgroup_is_dead(cgrp)) - cgroup_addrm_files(cgrp, ss, cfts, is_add); + ret = cgroup_addrm_files(cgrp, ss, cfts, is_add); mutex_unlock(&cgroup_mutex); mutex_unlock(&inode->i_mutex); rcu_read_lock(); + if (ret) + break; } rcu_read_unlock(); dput(prev); +out_deact: deactivate_super(sb); + return ret; } /** @@ -2915,6 +2923,7 @@ static void cgroup_cfts_commit(struct cgroup_subsys *ss, int cgroup_add_cftypes(struct cgroup_subsys *ss, struct cftype *cfts) { struct cftype_set *set; + int ret; set = kzalloc(sizeof(*set), GFP_KERNEL); if (!set) @@ -2923,9 +2932,10 @@ int cgroup_add_cftypes(struct cgroup_subsys *ss, struct cftype *cfts) cgroup_cfts_prepare(); set->cfts = cfts; list_add_tail(&set->node, &ss->cftsets); - cgroup_cfts_commit(ss, cfts, true); - - return 0; + ret = cgroup_cfts_commit(ss, cfts, true); + if (ret) + cgroup_rm_cftypes(ss, cfts); + return ret; } EXPORT_SYMBOL_GPL(cgroup_add_cftypes); From 628f7cd47ab758cae0353d1a6decf3d1459dca24 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 28 Jun 2013 16:24:11 -0700 Subject: [PATCH 0076/3400] cgroup: separate out cgroup_base_files[] handling out of cgroup_populate/clear_dir() cgroup_populate/clear_dir() currently take @base_files and adds and removes, respectively, cgroup_base_files[] to the directory. File additions and removals are being reorganized for proper error handling and more dynamic handling for the unified hierarchy, and mixing base and subsys file handling into the same functions gets a bit confusing. This patch moves base file handling out of cgroup_populate/clear_dir() into their users - cgroup_mount(), cgroup_create() and cgroup_destroy_locked(). Note that this changes the behavior of base file removal. If @base_files is %true, cgroup_clear_dir() used to delete files regardless of cftype until there's no files left. Now, only files with matching cfts are removed. As files can only be created by the base or registered cftypes, this shouldn't result in any behavior difference. Signed-off-by: Tejun Heo Acked-by: Li Zefan --- kernel/cgroup.c | 46 +++++++++++++++++++--------------------------- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 36c0ccc921f4..9835a097f3c0 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -215,6 +215,8 @@ static u64 cgroup_serial_nr_next = 1; */ static int need_forkexit_callback __read_mostly; +static struct cftype cgroup_base_files[]; + static void cgroup_offline_fn(struct work_struct *work); static int cgroup_destroy_locked(struct cgroup *cgrp); static int cgroup_addrm_files(struct cgroup *cgrp, struct cgroup_subsys *subsys, @@ -804,8 +806,7 @@ static struct cgroup *task_cgroup_from_root(struct task_struct *task, static int cgroup_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode); static struct dentry *cgroup_lookup(struct inode *, struct dentry *, unsigned int); static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry); -static int cgroup_populate_dir(struct cgroup *cgrp, bool base_files, - unsigned long subsys_mask); +static int cgroup_populate_dir(struct cgroup *cgrp, unsigned long subsys_mask); static const struct inode_operations cgroup_dir_inode_operations; static const struct file_operations proc_cgroupstats_operations; @@ -957,13 +958,11 @@ static void cgroup_rm_file(struct cgroup *cgrp, const struct cftype *cft) } /** - * cgroup_clear_dir - selective removal of base and subsystem files + * cgroup_clear_dir - remove subsys files in a cgroup directory * @cgrp: target cgroup - * @base_files: true if the base files should be removed * @subsys_mask: mask of the subsystem ids whose files should be removed */ -static void cgroup_clear_dir(struct cgroup *cgrp, bool base_files, - unsigned long subsys_mask) +static void cgroup_clear_dir(struct cgroup *cgrp, unsigned long subsys_mask) { struct cgroup_subsys *ss; @@ -974,10 +973,6 @@ static void cgroup_clear_dir(struct cgroup *cgrp, bool base_files, list_for_each_entry(set, &ss->cftsets, node) cgroup_addrm_files(cgrp, NULL, set->cfts, false); } - if (base_files) { - while (!list_empty(&cgrp->files)) - cgroup_rm_file(cgrp, NULL); - } } /* @@ -1372,17 +1367,17 @@ static int cgroup_remount(struct super_block *sb, int *flags, char *data) * this before rebind_subsystems, since rebind_subsystems may * change this hierarchy's subsys_list. */ - cgroup_clear_dir(cgrp, false, removed_mask); + cgroup_clear_dir(cgrp, removed_mask); ret = rebind_subsystems(root, added_mask, removed_mask); if (ret) { /* rebind_subsystems failed, re-populate the removed files */ - cgroup_populate_dir(cgrp, false, removed_mask); + cgroup_populate_dir(cgrp, removed_mask); goto out_unlock; } /* re-populate subsystem files */ - cgroup_populate_dir(cgrp, false, added_mask); + cgroup_populate_dir(cgrp, added_mask); if (opts.release_agent) strcpy(root->release_agent_path, opts.release_agent); @@ -1687,7 +1682,8 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type, BUG_ON(root->number_of_cgroups != 1); cred = override_creds(&init_cred); - cgroup_populate_dir(root_cgrp, true, root->subsys_mask); + cgroup_addrm_files(root_cgrp, NULL, cgroup_base_files, true); + cgroup_populate_dir(root_cgrp, root->subsys_mask); revert_creds(cred); mutex_unlock(&cgroup_root_mutex); mutex_unlock(&cgroup_mutex); @@ -4172,23 +4168,14 @@ static struct cftype cgroup_base_files[] = { }; /** - * cgroup_populate_dir - selectively creation of files in a directory + * cgroup_populate_dir - create subsys files in a cgroup directory * @cgrp: target cgroup - * @base_files: true if the base files should be added * @subsys_mask: mask of the subsystem ids whose files should be added */ -static int cgroup_populate_dir(struct cgroup *cgrp, bool base_files, - unsigned long subsys_mask) +static int cgroup_populate_dir(struct cgroup *cgrp, unsigned long subsys_mask) { - int err; struct cgroup_subsys *ss; - if (base_files) { - err = cgroup_addrm_files(cgrp, NULL, cgroup_base_files, true); - if (err < 0) - return err; - } - /* process cftsets of each subsystem */ for_each_root_subsys(cgrp->root, ss) { struct cftype_set *set; @@ -4410,7 +4397,11 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry, } } - err = cgroup_populate_dir(cgrp, true, root->subsys_mask); + err = cgroup_addrm_files(cgrp, NULL, cgroup_base_files, true); + if (err) + goto err_destroy; + + err = cgroup_populate_dir(cgrp, root->subsys_mask); if (err) goto err_destroy; @@ -4566,7 +4557,8 @@ static int cgroup_destroy_locked(struct cgroup *cgrp) * Clear and remove @cgrp directory. The removal puts the base ref * but we aren't quite done with @cgrp yet, so hold onto it. */ - cgroup_clear_dir(cgrp, true, cgrp->root->subsys_mask); + cgroup_clear_dir(cgrp, cgrp->root->subsys_mask); + cgroup_addrm_files(cgrp, NULL, cgroup_base_files, false); dget(d); cgroup_d_remove_dir(d); From bee550994f6b0c1179bd3ccea58dc5c2c4ccf842 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 28 Jun 2013 16:24:11 -0700 Subject: [PATCH 0077/3400] cgroup: update error handling in cgroup_populate_dir() cgroup_populate_dir() didn't use to check whether the actual file creations were successful and could return success with only subset of the requested files created, which is nasty. This patch udpates cgroup_populate_dir() so that it either succeeds with all files or fails with no file. v2: The original patch also converted for_each_root_subsys() usages to for_each_subsys() without explaining why. That part has been moved to a separate patch. Signed-off-by: Tejun Heo Acked-by: Li Zefan --- kernel/cgroup.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 9835a097f3c0..6b7324431b99 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -4171,10 +4171,13 @@ static struct cftype cgroup_base_files[] = { * cgroup_populate_dir - create subsys files in a cgroup directory * @cgrp: target cgroup * @subsys_mask: mask of the subsystem ids whose files should be added + * + * On failure, no file is added. */ static int cgroup_populate_dir(struct cgroup *cgrp, unsigned long subsys_mask) { struct cgroup_subsys *ss; + int ret = 0; /* process cftsets of each subsystem */ for_each_root_subsys(cgrp->root, ss) { @@ -4182,8 +4185,11 @@ static int cgroup_populate_dir(struct cgroup *cgrp, unsigned long subsys_mask) if (!test_bit(ss->subsys_id, &subsys_mask)) continue; - list_for_each_entry(set, &ss->cftsets, node) - cgroup_addrm_files(cgrp, ss, set->cfts, true); + list_for_each_entry(set, &ss->cftsets, node) { + ret = cgroup_addrm_files(cgrp, ss, set->cfts, true); + if (ret < 0) + goto err; + } } /* This cgroup is ready now */ @@ -4201,6 +4207,9 @@ static int cgroup_populate_dir(struct cgroup *cgrp, unsigned long subsys_mask) } return 0; +err: + cgroup_clear_dir(cgrp, subsys_mask); + return ret; } static void css_dput_fn(struct work_struct *work) From b420ba7db15659253d4f286a0ba479d336371999 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 12 Jul 2013 12:34:02 -0700 Subject: [PATCH 0078/3400] cgroup: use for_each_subsys() instead of for_each_root_subsys() in cgroup_populate/clear_dir() rebind_subsystems() will be updated to handle file creations and removals with proper error handling and to do that will need to perform file operations before actually adding the subsystem to the hierarchy. To enable such usage, update cgroup_populate/clear_dir() to use for_each_subsys() instead of for_each_root_subsys() so that they operate on all subsystems specified by @subsys_mask whether that subsystem is currently bound to the hierarchy or not. Signed-off-by: Tejun Heo Acked-by: Li Zefan --- kernel/cgroup.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 6b7324431b99..8f70dc0c0c79 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -965,10 +965,12 @@ static void cgroup_rm_file(struct cgroup *cgrp, const struct cftype *cft) static void cgroup_clear_dir(struct cgroup *cgrp, unsigned long subsys_mask) { struct cgroup_subsys *ss; + int i; - for_each_root_subsys(cgrp->root, ss) { + for_each_subsys(ss, i) { struct cftype_set *set; - if (!test_bit(ss->subsys_id, &subsys_mask)) + + if (!test_bit(i, &subsys_mask)) continue; list_for_each_entry(set, &ss->cftsets, node) cgroup_addrm_files(cgrp, NULL, set->cfts, false); @@ -4177,12 +4179,13 @@ static struct cftype cgroup_base_files[] = { static int cgroup_populate_dir(struct cgroup *cgrp, unsigned long subsys_mask) { struct cgroup_subsys *ss; - int ret = 0; + int i, ret = 0; /* process cftsets of each subsystem */ - for_each_root_subsys(cgrp->root, ss) { + for_each_subsys(ss, i) { struct cftype_set *set; - if (!test_bit(ss->subsys_id, &subsys_mask)) + + if (!test_bit(i, &subsys_mask)) continue; list_for_each_entry(set, &ss->cftsets, node) { From 3126121fb30941552b1a806c7c2e686bde57e270 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 28 Jun 2013 17:07:30 -0700 Subject: [PATCH 0079/3400] cgroup: make rebind_subsystems() handle file additions and removals with proper error handling Currently, creating and removing cgroup files in the root directory are handled separately from the actual subsystem binding and unbinding which happens in rebind_subsystems(). Also, rebind_subsystems() users aren't handling file creation errors properly. Let's integrate top_cgroup file handling into rebind_subsystems() so that it's simpler to use and everyone handles file creation errors correctly. * On a successful return, rebind_subsystems() is guaranteed to have created all files of the new subsystems and deleted the ones belonging to the removed subsystems. After a failure, no file is created or removed. * cgroup_remount() no longer needs to make explicit populate/clear calls as it's all handled by rebind_subsystems(), and it gets proper error handling automatically. * cgroup_mount() has been updated such that the root dentry and cgroup are linked before rebind_subsystems(). Also, the init_cred dancing and base file handling are moved right above rebind_subsystems() call and proper error handling for the base files is added. While at it, add a comment explaining what's going on with the cred thing. * cgroup_kill_sb() calls rebind_subsystems() to unbind all subsystems which now implies removing all subsystem files which requires the directory's i_mutex. Grab it. This means that files on the root cgroup are removed earlier - they used to be deleted from generic super_block cleanup from vfs. This doesn't lead to any functional difference and it's cleaner to do the clean up explicitly for all files. Combined with the previous changes, this makes all cgroup file creation errors handled correctly. v2: Added comment on init_cred. v3: Li spotted that cgroup_mount() wasn't freeing tmp_links after base file addition failure. Fix it by adding free_tmp_links error handling label. v4: v3 introduced build bugs which got noticed by Fengguang's awesome kbuild test robot. Fixed, and shame on me. Signed-off-by: Tejun Heo Acked-by: Li Zefan Cc: Fengguang Wu --- kernel/cgroup.c | 73 +++++++++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 32 deletions(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 8f70dc0c0c79..4ec8d2da94d1 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -1003,7 +1003,7 @@ static int rebind_subsystems(struct cgroupfs_root *root, { struct cgroup *cgrp = &root->top_cgroup; struct cgroup_subsys *ss; - int i; + int i, ret; BUG_ON(!mutex_is_locked(&cgroup_mutex)); BUG_ON(!mutex_is_locked(&cgroup_root_mutex)); @@ -1028,7 +1028,16 @@ static int rebind_subsystems(struct cgroupfs_root *root, if (root->number_of_cgroups > 1) return -EBUSY; - /* Process each subsystem */ + ret = cgroup_populate_dir(cgrp, added_mask); + if (ret) + return ret; + + /* + * Nothing can fail from this point on. Remove files for the + * removed subsystems and rebind each subsystem. + */ + cgroup_clear_dir(cgrp, removed_mask); + for_each_subsys(ss, i) { unsigned long bit = 1UL << i; @@ -1364,22 +1373,9 @@ static int cgroup_remount(struct super_block *sb, int *flags, char *data) goto out_unlock; } - /* - * Clear out the files of subsystems that should be removed, do - * this before rebind_subsystems, since rebind_subsystems may - * change this hierarchy's subsys_list. - */ - cgroup_clear_dir(cgrp, removed_mask); - ret = rebind_subsystems(root, added_mask, removed_mask); - if (ret) { - /* rebind_subsystems failed, re-populate the removed files */ - cgroup_populate_dir(cgrp, removed_mask); + if (ret) goto out_unlock; - } - - /* re-populate subsystem files */ - cgroup_populate_dir(cgrp, added_mask); if (opts.release_agent) strcpy(root->release_agent_path, opts.release_agent); @@ -1578,7 +1574,9 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type, int ret = 0; struct super_block *sb; struct cgroupfs_root *new_root; + struct list_head tmp_links; struct inode *inode; + const struct cred *cred; /* First find the desired set of subsystems */ mutex_lock(&cgroup_mutex); @@ -1610,10 +1608,8 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type, BUG_ON(!root); if (root == opts.new_root) { /* We used the new root structure, so this is a new hierarchy */ - struct list_head tmp_links; struct cgroup *root_cgrp = &root->top_cgroup; struct cgroupfs_root *existing_root; - const struct cred *cred; int i; struct css_set *cset; @@ -1651,26 +1647,37 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type, if (ret) goto unlock_drop; + sb->s_root->d_fsdata = root_cgrp; + root_cgrp->dentry = sb->s_root; + + /* + * We're inside get_sb() and will call lookup_one_len() to + * create the root files, which doesn't work if SELinux is + * in use. The following cred dancing somehow works around + * it. See 2ce9738ba ("cgroupfs: use init_cred when + * populating new cgroupfs mount") for more details. + */ + cred = override_creds(&init_cred); + + ret = cgroup_addrm_files(root_cgrp, NULL, cgroup_base_files, true); + if (ret) + goto rm_base_files; + ret = rebind_subsystems(root, root->subsys_mask, 0); - if (ret == -EBUSY) { - free_cgrp_cset_links(&tmp_links); - goto unlock_drop; - } + if (ret) + goto rm_base_files; + + revert_creds(cred); + /* * There must be no failure case after here, since rebinding * takes care of subsystems' refcounts, which are explicitly * dropped in the failure exit path. */ - /* EBUSY should be the only error here */ - BUG_ON(ret); - list_add(&root->root_list, &cgroup_roots); cgroup_root_count++; - sb->s_root->d_fsdata = root_cgrp; - root->top_cgroup.dentry = sb->s_root; - /* Link the top cgroup in this hierarchy into all * the css_set objects */ write_lock(&css_set_lock); @@ -1683,10 +1690,6 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type, BUG_ON(!list_empty(&root_cgrp->children)); BUG_ON(root->number_of_cgroups != 1); - cred = override_creds(&init_cred); - cgroup_addrm_files(root_cgrp, NULL, cgroup_base_files, true); - cgroup_populate_dir(root_cgrp, root->subsys_mask); - revert_creds(cred); mutex_unlock(&cgroup_root_mutex); mutex_unlock(&cgroup_mutex); mutex_unlock(&inode->i_mutex); @@ -1715,6 +1718,10 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type, kfree(opts.name); return dget(sb->s_root); + rm_base_files: + free_cgrp_cset_links(&tmp_links); + cgroup_addrm_files(&root->top_cgroup, NULL, cgroup_base_files, false); + revert_creds(cred); unlock_drop: cgroup_exit_root_id(root); mutex_unlock(&cgroup_root_mutex); @@ -1741,6 +1748,7 @@ static void cgroup_kill_sb(struct super_block *sb) { BUG_ON(root->number_of_cgroups != 1); BUG_ON(!list_empty(&cgrp->children)); + mutex_lock(&cgrp->dentry->d_inode->i_mutex); mutex_lock(&cgroup_mutex); mutex_lock(&cgroup_root_mutex); @@ -1773,6 +1781,7 @@ static void cgroup_kill_sb(struct super_block *sb) { mutex_unlock(&cgroup_root_mutex); mutex_unlock(&cgroup_mutex); + mutex_unlock(&cgrp->dentry->d_inode->i_mutex); simple_xattrs_free(&cgrp->xattrs); From f172e67cf9d842bc646d0f66792e38435a334b1e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 28 Jun 2013 17:07:30 -0700 Subject: [PATCH 0080/3400] cgroup: move number_of_cgroups test out of rebind_subsystems() into cgroup_remount() rebind_subsystems() currently fails if the hierarchy has any !root cgroups; however, on the planned unified hierarchy, rebind_subsystems() will be used while populated. Move the test to cgroup_remount(), which is the only place the test is necessary anyway. As it's impossible for the other two callers of rebind_subsystems() to have populated hierarchy, this doesn't make any behavior changes. Signed-off-by: Tejun Heo Acked-by: Li Zefan --- kernel/cgroup.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 4ec8d2da94d1..c108d3d1ea30 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -1021,13 +1021,6 @@ static int rebind_subsystems(struct cgroupfs_root *root, } } - /* Currently we don't handle adding/removing subsystems when - * any child cgroups exist. This is theoretically supportable - * but involves complex error handling, so it's being left until - * later */ - if (root->number_of_cgroups > 1) - return -EBUSY; - ret = cgroup_populate_dir(cgrp, added_mask); if (ret) return ret; @@ -1373,6 +1366,12 @@ static int cgroup_remount(struct super_block *sb, int *flags, char *data) goto out_unlock; } + /* remounting is not allowed for populated hierarchies */ + if (root->number_of_cgroups > 1) { + ret = -EBUSY; + goto out_unlock; + } + ret = rebind_subsystems(root, added_mask, removed_mask); if (ret) goto out_unlock; From f22ff5523af8b365167cb79189f8b91470d57c8c Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Sat, 29 Jun 2013 00:24:34 +0800 Subject: [PATCH 0081/3400] ACPI / dock: avoid initializing acpi_dock_notifier_list multiple times Function dock_add() will be called multiple times if there are multiple dock stations, which causes acpi_dock_notifier_list to be initialized multiple times. To avoid that, move the initialization of acpi_dock_notifier_list from dock_add() to acpi_dock_init(). [rjw: Changelog] Signed-off-by: Jiang Liu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/dock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 826560753389..c36de862fd50 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -1007,7 +1007,6 @@ static int __init dock_add(acpi_handle handle) mutex_init(&dock_station->hp_lock); spin_lock_init(&dock_station->dd_lock); INIT_LIST_HEAD(&dock_station->sibling); - ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list); INIT_LIST_HEAD(&dock_station->dependent_devices); /* we want the dock device to send uevents */ @@ -1078,6 +1077,7 @@ void __init acpi_dock_init(void) return; } + ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list); register_acpi_bus_notifier(&dock_acpi_notifier); pr_info(PREFIX "%s: %d docks/bays found\n", ACPI_DOCK_DRIVER_DESCRIPTION, dock_station_count); From ed633e709fa633c6bc24f4d6ecb55ad0c14fd335 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Sat, 29 Jun 2013 00:24:35 +0800 Subject: [PATCH 0082/3400] ACPI / dock: drop redundant spin lock in dock station object All dock station objects are created during initialization and don't change at runtime, so drop the redundant spin lock from struct dock_station. [rjw: Changelog] Signed-off-by: Jiang Liu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/dock.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index c36de862fd50..750f958ef0bf 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -63,7 +63,6 @@ struct dock_station { acpi_handle handle; unsigned long last_dock_time; u32 flags; - spinlock_t dd_lock; struct mutex hp_lock; struct list_head dependent_devices; @@ -112,10 +111,7 @@ add_dock_dependent_device(struct dock_station *ds, acpi_handle handle) dd->handle = handle; INIT_LIST_HEAD(&dd->list); - - spin_lock(&ds->dd_lock); list_add_tail(&dd->list, &ds->dependent_devices); - spin_unlock(&ds->dd_lock); return 0; } @@ -220,14 +216,10 @@ find_dock_dependent_device(struct dock_station *ds, acpi_handle handle) { struct dock_dependent_device *dd; - spin_lock(&ds->dd_lock); - list_for_each_entry(dd, &ds->dependent_devices, list) { - if (handle == dd->handle) { - spin_unlock(&ds->dd_lock); + list_for_each_entry(dd, &ds->dependent_devices, list) + if (handle == dd->handle) return dd; - } - } - spin_unlock(&ds->dd_lock); + return NULL; } @@ -1005,7 +997,6 @@ static int __init dock_add(acpi_handle handle) dock_station->last_dock_time = jiffies - HZ; mutex_init(&dock_station->hp_lock); - spin_lock_init(&dock_station->dd_lock); INIT_LIST_HEAD(&dock_station->sibling); INIT_LIST_HEAD(&dock_station->dependent_devices); From d423c083ff3b3adc1e42a2f2c03c8430a6e0220f Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Sat, 29 Jun 2013 00:24:36 +0800 Subject: [PATCH 0083/3400] ACPI / dock: mark initialization functions with __init Mark all initialization functions with __init to reduce runtime memory consumption. Signed-off-by: Jiang Liu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/dock.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 750f958ef0bf..f3ec722ae85a 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -100,7 +100,7 @@ struct dock_dependent_device { * * Add the dependent device to the dock's dependent device list. */ -static int +static int __init add_dock_dependent_device(struct dock_station *ds, acpi_handle handle) { struct dock_dependent_device *dd; @@ -244,7 +244,7 @@ static int is_dock(acpi_handle handle) return 1; } -static int is_ejectable(acpi_handle handle) +static int __init is_ejectable(acpi_handle handle) { acpi_status status; acpi_handle tmp; @@ -255,7 +255,7 @@ static int is_ejectable(acpi_handle handle) return 1; } -static int is_ata(acpi_handle handle) +static int __init is_ata(acpi_handle handle) { acpi_handle tmp; @@ -268,7 +268,7 @@ static int is_ata(acpi_handle handle) return 0; } -static int is_battery(acpi_handle handle) +static int __init is_battery(acpi_handle handle) { struct acpi_device_info *info; int ret = 1; @@ -284,7 +284,7 @@ static int is_battery(acpi_handle handle) return ret; } -static int is_ejectable_bay(acpi_handle handle) +static int __init is_ejectable_bay(acpi_handle handle) { acpi_handle phandle; @@ -848,7 +848,7 @@ static struct notifier_block dock_acpi_notifier = { * check to see if an object has an _EJD method. If it does, then it * will see if it is dependent on the dock station. */ -static acpi_status +static acpi_status __init find_dock_devices(acpi_handle handle, u32 lvl, void *context, void **rv) { acpi_status status; From 472d963befe28b8614ea2789757b27536c8d79eb Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Sat, 29 Jun 2013 00:24:37 +0800 Subject: [PATCH 0084/3400] ACPI / dock: simplify dock_create_acpi_device() The return value of dock_create_acpi_device() is not used at all, so change its signature to return void and simplify the implementation of it. Signed-off-by: Jiang Liu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/dock.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index f3ec722ae85a..1bdb1facc17b 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -351,10 +351,8 @@ static int dock_present(struct dock_station *ds) * handle if one does not exist already. This should cause * acpi to scan for drivers for the given devices, and call * matching driver's add routine. - * - * Returns a pointer to the acpi_device corresponding to the handle. */ -static struct acpi_device * dock_create_acpi_device(acpi_handle handle) +static void dock_create_acpi_device(acpi_handle handle) { struct acpi_device *device; int ret; @@ -367,10 +365,7 @@ static struct acpi_device * dock_create_acpi_device(acpi_handle handle) ret = acpi_bus_scan(handle); if (ret) pr_debug("error adding bus, %x\n", -ret); - - acpi_bus_get_device(handle, &device); } - return device; } /** From 952c63e9512b63220886105cfc791507046fa39a Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Sat, 29 Jun 2013 00:24:38 +0800 Subject: [PATCH 0085/3400] ACPI: introduce helper function acpi_has_method() Introduce helper function acpi_has_method() and use it in a number of places to simplify code. [rjw: Changelog] Signed-off-by: Jiang Liu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/battery.c | 11 +--- drivers/acpi/ec.c | 4 +- drivers/acpi/processor_perflib.c | 22 +++---- drivers/acpi/resource.c | 4 +- drivers/acpi/scan.c | 99 ++++++++++---------------------- drivers/acpi/utils.c | 15 +++++ drivers/acpi/video.c | 39 ++++--------- drivers/acpi/video_detect.c | 19 +++--- include/acpi/acpi_bus.h | 3 + 9 files changed, 80 insertions(+), 136 deletions(-) diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 082b4dd252a8..a7627166e18b 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -548,12 +548,8 @@ static int acpi_battery_set_alarm(struct acpi_battery *battery) static int acpi_battery_init_alarm(struct acpi_battery *battery) { - acpi_status status = AE_OK; - acpi_handle handle = NULL; - /* See if alarms are supported, and if so, set default */ - status = acpi_get_handle(battery->device->handle, "_BTP", &handle); - if (ACPI_FAILURE(status)) { + if (!acpi_has_method(battery->device->handle, "_BTP")) { clear_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags); return 0; } @@ -1066,7 +1062,7 @@ static int acpi_battery_add(struct acpi_device *device) { int result = 0; struct acpi_battery *battery = NULL; - acpi_handle handle; + if (!device) return -EINVAL; battery = kzalloc(sizeof(struct acpi_battery), GFP_KERNEL); @@ -1078,8 +1074,7 @@ static int acpi_battery_add(struct acpi_device *device) device->driver_data = battery; mutex_init(&battery->lock); mutex_init(&battery->sysfs_lock); - if (ACPI_SUCCESS(acpi_get_handle(battery->device->handle, - "_BIX", &handle))) + if (acpi_has_method(battery->device->handle, "_BIX")) set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags); result = acpi_battery_update(battery); if (result) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 80403c1a89f8..84bf06cec1f2 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -1049,10 +1049,8 @@ int __init acpi_ec_ecdt_probe(void) * which needs it, has fake EC._INI method, so use it as flag. * Keep boot_ec struct as it will be needed soon. */ - acpi_handle dummy; if (!dmi_name_in_vendors("ASUS") || - ACPI_FAILURE(acpi_get_handle(boot_ec->handle, "_INI", - &dummy))) + !acpi_has_method(boot_ec->handle, "_INI")) return -ENODEV; } install: diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 1e9732d809bf..51d7948611da 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -164,17 +164,12 @@ static void acpi_processor_ppc_ost(acpi_handle handle, int status) {.type = ACPI_TYPE_INTEGER,}, }; struct acpi_object_list arg_list = {2, params}; - acpi_handle temp; - params[0].integer.value = ACPI_PROCESSOR_NOTIFY_PERFORMANCE; - params[1].integer.value = status; - - /* when there is no _OST , skip it */ - if (ACPI_FAILURE(acpi_get_handle(handle, "_OST", &temp))) - return; - - acpi_evaluate_object(handle, "_OST", &arg_list, NULL); - return; + if (acpi_has_method(handle, "_OST")) { + params[0].integer.value = ACPI_PROCESSOR_NOTIFY_PERFORMANCE; + params[1].integer.value = status; + acpi_evaluate_object(handle, "_OST", &arg_list, NULL); + } } int acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag) @@ -468,14 +463,11 @@ static int acpi_processor_get_performance_states(struct acpi_processor *pr) int acpi_processor_get_performance_info(struct acpi_processor *pr) { int result = 0; - acpi_status status = AE_OK; - acpi_handle handle = NULL; if (!pr || !pr->performance || !pr->handle) return -EINVAL; - status = acpi_get_handle(pr->handle, "_PCT", &handle); - if (ACPI_FAILURE(status)) { + if (!acpi_has_method(pr->handle, "_PCT")) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI-based processor performance control unavailable\n")); return -ENODEV; @@ -501,7 +493,7 @@ int acpi_processor_get_performance_info(struct acpi_processor *pr) */ update_bios: #ifdef CONFIG_X86 - if (ACPI_SUCCESS(acpi_get_handle(pr->handle, "_PPC", &handle))){ + if (acpi_has_method(pr->handle, "_PPC")) { if(boot_cpu_has(X86_FEATURE_EST)) printk(KERN_WARNING FW_BUG "BIOS needs update for CPU " "frequency support\n"); diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index 3322b47ab7ca..b7201fc6f1e1 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -505,14 +505,12 @@ int acpi_dev_get_resources(struct acpi_device *adev, struct list_head *list, void *preproc_data) { struct res_proc_context c; - acpi_handle not_used; acpi_status status; if (!adev || !adev->handle || !list_empty(list)) return -EINVAL; - status = acpi_get_handle(adev->handle, METHOD_NAME__CRS, ¬_used); - if (ACPI_FAILURE(status)) + if (!acpi_has_method(adev->handle, METHOD_NAME__CRS)) return 0; c.list = list; diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 10985573aaa7..ada0b4cf2ba5 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -193,7 +193,6 @@ static acpi_status acpi_bus_online_companions(acpi_handle handle, u32 lvl, static int acpi_scan_hot_remove(struct acpi_device *device) { acpi_handle handle = device->handle; - acpi_handle not_used; struct acpi_object_list arg_list; union acpi_object arg; struct device *errdev; @@ -258,7 +257,7 @@ static int acpi_scan_hot_remove(struct acpi_device *device) put_device(&device->dev); device = NULL; - if (ACPI_SUCCESS(acpi_get_handle(handle, "_LCK", ¬_used))) { + if (acpi_has_method(handle, "_LCK")) { arg_list.count = 1; arg_list.pointer = &arg; arg.type = ACPI_TYPE_INTEGER; @@ -652,7 +651,6 @@ static int acpi_device_setup_files(struct acpi_device *dev) { struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; acpi_status status; - acpi_handle temp; unsigned long long sun; int result = 0; @@ -678,8 +676,7 @@ static int acpi_device_setup_files(struct acpi_device *dev) /* * If device has _STR, 'description' file is created */ - status = acpi_get_handle(dev->handle, "_STR", &temp); - if (ACPI_SUCCESS(status)) { + if (acpi_has_method(dev->handle, "_STR")) { status = acpi_evaluate_object(dev->handle, "_STR", NULL, &buffer); if (ACPI_FAILURE(status)) @@ -709,8 +706,7 @@ static int acpi_device_setup_files(struct acpi_device *dev) * If device has _EJ0, 'eject' file is created that is used to trigger * hot-removal function from userland. */ - status = acpi_get_handle(dev->handle, "_EJ0", &temp); - if (ACPI_SUCCESS(status)) { + if (acpi_has_method(dev->handle, "_EJ0")) { result = device_create_file(&dev->dev, &dev_attr_eject); if (result) return result; @@ -732,9 +728,6 @@ end: static void acpi_device_remove_files(struct acpi_device *dev) { - acpi_status status; - acpi_handle temp; - if (dev->flags.power_manageable) { device_remove_file(&dev->dev, &dev_attr_power_state); if (dev->power.flags.power_resources) @@ -745,20 +738,17 @@ static void acpi_device_remove_files(struct acpi_device *dev) /* * If device has _STR, remove 'description' file */ - status = acpi_get_handle(dev->handle, "_STR", &temp); - if (ACPI_SUCCESS(status)) { + if (acpi_has_method(dev->handle, "_STR")) { kfree(dev->pnp.str_obj); device_remove_file(&dev->dev, &dev_attr_description); } /* * If device has _EJ0, remove 'eject' file. */ - status = acpi_get_handle(dev->handle, "_EJ0", &temp); - if (ACPI_SUCCESS(status)) + if (acpi_has_method(dev->handle, "_EJ0")) device_remove_file(&dev->dev, &dev_attr_eject); - status = acpi_get_handle(dev->handle, "_SUN", &temp); - if (ACPI_SUCCESS(status)) + if (acpi_has_method(dev->handle, "_SUN")) device_remove_file(&dev->dev, &dev_attr_sun); if (dev->pnp.unique_id) @@ -1334,13 +1324,10 @@ static void acpi_bus_set_run_wake_flags(struct acpi_device *device) static void acpi_bus_get_wakeup_device_flags(struct acpi_device *device) { - acpi_handle temp; - acpi_status status = 0; int err; /* Presence of _PRW indicates wake capable */ - status = acpi_get_handle(device->handle, "_PRW", &temp); - if (ACPI_FAILURE(status)) + if (!acpi_has_method(device->handle, "_PRW")) return; err = acpi_bus_extract_wakeup_device_power_package(device->handle, @@ -1370,7 +1357,6 @@ static void acpi_bus_init_power_state(struct acpi_device *device, int state) struct acpi_device_power_state *ps = &device->power.states[state]; char pathname[5] = { '_', 'P', 'R', '0' + state, '\0' }; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - acpi_handle handle; acpi_status status; INIT_LIST_HEAD(&ps->resources); @@ -1393,8 +1379,7 @@ static void acpi_bus_init_power_state(struct acpi_device *device, int state) /* Evaluate "_PSx" to see if we can do explicit sets */ pathname[2] = 'S'; - status = acpi_get_handle(device->handle, pathname, &handle); - if (ACPI_SUCCESS(status)) + if (acpi_has_method(device->handle, pathname)) ps->flags.explicit_set = 1; /* @@ -1413,28 +1398,21 @@ static void acpi_bus_init_power_state(struct acpi_device *device, int state) static void acpi_bus_get_power_flags(struct acpi_device *device) { - acpi_status status; - acpi_handle handle; u32 i; /* Presence of _PS0|_PR0 indicates 'power manageable' */ - status = acpi_get_handle(device->handle, "_PS0", &handle); - if (ACPI_FAILURE(status)) { - status = acpi_get_handle(device->handle, "_PR0", &handle); - if (ACPI_FAILURE(status)) - return; - } + if (!acpi_has_method(device->handle, "_PS0") && + !acpi_has_method(device->handle, "_PR0")) + return; device->flags.power_manageable = 1; /* * Power Management Flags */ - status = acpi_get_handle(device->handle, "_PSC", &handle); - if (ACPI_SUCCESS(status)) + if (acpi_has_method(device->handle, "_PSC")) device->power.flags.explicit_get = 1; - status = acpi_get_handle(device->handle, "_IRC", &handle); - if (ACPI_SUCCESS(status)) + if (acpi_has_method(device->handle, "_IRC")) device->power.flags.inrush_current = 1; /* @@ -1468,28 +1446,18 @@ static void acpi_bus_get_power_flags(struct acpi_device *device) static void acpi_bus_get_flags(struct acpi_device *device) { - acpi_status status = AE_OK; - acpi_handle temp = NULL; - /* Presence of _STA indicates 'dynamic_status' */ - status = acpi_get_handle(device->handle, "_STA", &temp); - if (ACPI_SUCCESS(status)) + if (acpi_has_method(device->handle, "_STA")) device->flags.dynamic_status = 1; /* Presence of _RMV indicates 'removable' */ - status = acpi_get_handle(device->handle, "_RMV", &temp); - if (ACPI_SUCCESS(status)) + if (acpi_has_method(device->handle, "_RMV")) device->flags.removable = 1; /* Presence of _EJD|_EJ0 indicates 'ejectable' */ - status = acpi_get_handle(device->handle, "_EJD", &temp); - if (ACPI_SUCCESS(status)) + if (acpi_has_method(device->handle, "_EJD") || + acpi_has_method(device->handle, "_EJ0")) device->flags.ejectable = 1; - else { - status = acpi_get_handle(device->handle, "_EJ0", &temp); - if (ACPI_SUCCESS(status)) - device->flags.ejectable = 1; - } } static void acpi_device_get_busid(struct acpi_device *device) @@ -1538,27 +1506,24 @@ static void acpi_device_get_busid(struct acpi_device *device) */ static int acpi_bay_match(acpi_handle handle) { - acpi_status status; - acpi_handle tmp; acpi_handle phandle; - status = acpi_get_handle(handle, "_EJ0", &tmp); - if (ACPI_FAILURE(status)) + if (!acpi_has_method(handle, "_EJ0")) return -ENODEV; - if ((ACPI_SUCCESS(acpi_get_handle(handle, "_GTF", &tmp))) || - (ACPI_SUCCESS(acpi_get_handle(handle, "_GTM", &tmp))) || - (ACPI_SUCCESS(acpi_get_handle(handle, "_STM", &tmp))) || - (ACPI_SUCCESS(acpi_get_handle(handle, "_SDD", &tmp)))) + if (acpi_has_method(handle, "_GTF") || + acpi_has_method(handle, "_GTM") || + acpi_has_method(handle, "_STM") || + acpi_has_method(handle, "_SDD")) return 0; if (acpi_get_parent(handle, &phandle)) return -ENODEV; - if ((ACPI_SUCCESS(acpi_get_handle(phandle, "_GTF", &tmp))) || - (ACPI_SUCCESS(acpi_get_handle(phandle, "_GTM", &tmp))) || - (ACPI_SUCCESS(acpi_get_handle(phandle, "_STM", &tmp))) || - (ACPI_SUCCESS(acpi_get_handle(phandle, "_SDD", &tmp)))) + if (acpi_has_method(phandle, "_GTF") || + acpi_has_method(phandle, "_GTM") || + acpi_has_method(phandle, "_STM") || + acpi_has_method(phandle, "_SDD")) return 0; return -ENODEV; @@ -1610,7 +1575,6 @@ static void acpi_add_id(struct acpi_device_pnp *pnp, const char *dev_id) */ static int acpi_ibm_smbus_match(acpi_handle handle) { - acpi_handle h_dummy; struct acpi_buffer path = {ACPI_ALLOCATE_BUFFER, NULL}; int result; @@ -1629,9 +1593,9 @@ static int acpi_ibm_smbus_match(acpi_handle handle) /* Does it have the necessary (but misnamed) methods? */ result = -ENODEV; - if (ACPI_SUCCESS(acpi_get_handle(handle, "SBI", &h_dummy)) && - ACPI_SUCCESS(acpi_get_handle(handle, "SBR", &h_dummy)) && - ACPI_SUCCESS(acpi_get_handle(handle, "SBW", &h_dummy))) + if (acpi_has_method(handle, "SBI") && + acpi_has_method(handle, "SBR") && + acpi_has_method(handle, "SBW")) result = 0; out: kfree(path.pointer); @@ -1898,7 +1862,6 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, struct acpi_device *device = NULL; int type; unsigned long long sta; - acpi_status status; int result; acpi_bus_get_device(handle, &device); @@ -1919,10 +1882,8 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, if (!(sta & ACPI_STA_DEVICE_PRESENT) && !(sta & ACPI_STA_DEVICE_FUNCTIONING)) { struct acpi_device_wakeup wakeup; - acpi_handle temp; - status = acpi_get_handle(handle, "_PRW", &temp); - if (ACPI_SUCCESS(status)) { + if (acpi_has_method(handle, "_PRW")) { acpi_bus_extract_wakeup_device_power_package(handle, &wakeup); acpi_power_resources_list_free(&wakeup.resources); diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index 744371304313..b08d97376f84 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -495,3 +495,18 @@ acpi_handle_printk(const char *level, acpi_handle handle, const char *fmt, ...) kfree(buffer.pointer); } EXPORT_SYMBOL(acpi_handle_printk); + +/** + * acpi_has_method: Check whether @handle has a method named @name + * @handle: ACPI device handle + * @name: name of object or method + * + * Check whether @handle has a method named @name. + */ +bool acpi_has_method(acpi_handle handle, char *name) +{ + acpi_handle tmp; + + return ACPI_SUCCESS(acpi_get_handle(handle, name, &tmp)); +} +EXPORT_SYMBOL(acpi_has_method); diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 5d7075d25700..a84533e67b9d 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -875,28 +875,21 @@ out: static void acpi_video_device_find_cap(struct acpi_video_device *device) { - acpi_handle h_dummy1; - - if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_ADR", &h_dummy1))) { + if (acpi_has_method(device->dev->handle, "_ADR")) device->cap._ADR = 1; - } - if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_BCL", &h_dummy1))) { + if (acpi_has_method(device->dev->handle, "_BCL")) device->cap._BCL = 1; - } - if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_BCM", &h_dummy1))) { + if (acpi_has_method(device->dev->handle, "_BCM")) device->cap._BCM = 1; - } - if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle,"_BQC",&h_dummy1))) + if (acpi_has_method(device->dev->handle, "_BQC")) { device->cap._BQC = 1; - else if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_BCQ", - &h_dummy1))) { + } else if (acpi_has_method(device->dev->handle, "_BCQ")) { printk(KERN_WARNING FW_BUG "_BCQ is used instead of _BQC\n"); device->cap._BCQ = 1; } - if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DDC", &h_dummy1))) { + if (acpi_has_method(device->dev->handle, "_DDC")) device->cap._DDC = 1; - } if (acpi_video_backlight_support()) { struct backlight_properties props; @@ -984,26 +977,18 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) static void acpi_video_bus_find_cap(struct acpi_video_bus *video) { - acpi_handle h_dummy1; - - if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_DOS", &h_dummy1))) { + if (acpi_has_method(video->device->handle, "_DOS")) video->cap._DOS = 1; - } - if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_DOD", &h_dummy1))) { + if (acpi_has_method(video->device->handle, "_DOD")) video->cap._DOD = 1; - } - if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_ROM", &h_dummy1))) { + if (acpi_has_method(video->device->handle, "_ROM")) video->cap._ROM = 1; - } - if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_GPD", &h_dummy1))) { + if (acpi_has_method(video->device->handle, "_GPD")) video->cap._GPD = 1; - } - if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_SPD", &h_dummy1))) { + if (acpi_has_method(video->device->handle, "_SPD")) video->cap._SPD = 1; - } - if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_VPO", &h_dummy1))) { + if (acpi_has_method(video->device->handle, "_VPO")) video->cap._VPO = 1; - } } /* diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index e6bd910bc6ed..ddefa5f954e2 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -51,14 +51,13 @@ acpi_backlight_cap_match(acpi_handle handle, u32 level, void *context, void **retyurn_value) { long *cap = context; - acpi_handle h_dummy; - if (ACPI_SUCCESS(acpi_get_handle(handle, "_BCM", &h_dummy)) && - ACPI_SUCCESS(acpi_get_handle(handle, "_BCL", &h_dummy))) { + if (acpi_has_method(handle, "_BCM") && + acpi_has_method(handle, "_BCL")) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found generic backlight " "support\n")); *cap |= ACPI_VIDEO_BACKLIGHT; - if (ACPI_FAILURE(acpi_get_handle(handle, "_BQC", &h_dummy))) + if (!acpi_has_method(handle, "_BQC")) printk(KERN_WARNING FW_BUG PREFIX "No _BQC method, " "cannot determine initial brightness\n"); /* We have backlight support, no need to scan further */ @@ -77,22 +76,20 @@ acpi_backlight_cap_match(acpi_handle handle, u32 level, void *context, */ long acpi_is_video_device(acpi_handle handle) { - acpi_handle h_dummy; long video_caps = 0; /* Is this device able to support video switching ? */ - if (ACPI_SUCCESS(acpi_get_handle(handle, "_DOD", &h_dummy)) || - ACPI_SUCCESS(acpi_get_handle(handle, "_DOS", &h_dummy))) + if (acpi_has_method(handle, "_DOD") || acpi_has_method(handle, "_DOS")) video_caps |= ACPI_VIDEO_OUTPUT_SWITCHING; /* Is this device able to retrieve a video ROM ? */ - if (ACPI_SUCCESS(acpi_get_handle(handle, "_ROM", &h_dummy))) + if (acpi_has_method(handle, "_ROM")) video_caps |= ACPI_VIDEO_ROM_AVAILABLE; /* Is this device able to configure which video head to be POSTed ? */ - if (ACPI_SUCCESS(acpi_get_handle(handle, "_VPO", &h_dummy)) && - ACPI_SUCCESS(acpi_get_handle(handle, "_GPD", &h_dummy)) && - ACPI_SUCCESS(acpi_get_handle(handle, "_SPD", &h_dummy))) + if (acpi_has_method(handle, "_VPO") && + acpi_has_method(handle, "_GPD") && + acpi_has_method(handle, "_SPD")) video_caps |= ACPI_VIDEO_DEVICE_POSTING; /* Only check for backlight functionality if one of the above hit. */ diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 56e6b68c8d2f..62b2811bade4 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -56,6 +56,9 @@ acpi_evaluate_hotplug_ost(acpi_handle handle, u32 source_event, acpi_status acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld_info **pld); + +bool acpi_has_method(acpi_handle handle, char *name); + #ifdef CONFIG_ACPI #include From 0db98202605c3d32e023d43c30b5bd878f520976 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Sat, 29 Jun 2013 00:24:39 +0800 Subject: [PATCH 0086/3400] ACPI: introduce helper function acpi_execute_simple_method() Introduce helper function acpi_execute_simple_method() and use it in a number of places to simplify code. [rjw: Changelog] Signed-off-by: Jiang Liu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/battery.c | 8 ++------ drivers/acpi/bus.c | 6 +----- drivers/acpi/power.c | 4 +--- drivers/acpi/sleep.c | 7 ++----- drivers/acpi/thermal.c | 18 ++++-------------- drivers/acpi/utils.c | 12 ++++++++++++ drivers/acpi/video.c | 17 +++++------------ include/acpi/acpi_bus.h | 2 ++ 8 files changed, 29 insertions(+), 45 deletions(-) diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index a7627166e18b..74669ac4c615 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -525,18 +525,14 @@ static int acpi_battery_get_state(struct acpi_battery *battery) static int acpi_battery_set_alarm(struct acpi_battery *battery) { acpi_status status = 0; - union acpi_object arg0 = { .type = ACPI_TYPE_INTEGER }; - struct acpi_object_list arg_list = { 1, &arg0 }; if (!acpi_battery_present(battery) || !test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags)) return -ENODEV; - arg0.integer.value = battery->alarm; - mutex_lock(&battery->lock); - status = acpi_evaluate_object(battery->device->handle, "_BTP", - &arg_list, NULL); + status = acpi_execute_simple_method(battery->device->handle, "_BTP", + battery->alarm); mutex_unlock(&battery->lock); if (ACPI_FAILURE(status)) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index a5bb33bab448..a5a032e2344e 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -593,8 +593,6 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) static int __init acpi_bus_init_irq(void) { acpi_status status; - union acpi_object arg = { ACPI_TYPE_INTEGER }; - struct acpi_object_list arg_list = { 1, &arg }; char *message = NULL; @@ -623,9 +621,7 @@ static int __init acpi_bus_init_irq(void) printk(KERN_INFO PREFIX "Using %s for interrupt routing\n", message); - arg.integer.value = acpi_irq_model; - - status = acpi_evaluate_object(NULL, "\\_PIC", &arg_list, NULL); + status = acpi_execute_simple_method(NULL, "\\_PIC", acpi_irq_model); if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) { ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PIC")); return -ENODEV; diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 5c28c894c0fc..1460c88a7c0e 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -637,9 +637,7 @@ int acpi_device_sleep_wake(struct acpi_device *dev, } /* Execute _PSW */ - arg_list.count = 1; - in_arg[0].integer.value = enable; - status = acpi_evaluate_object(dev->handle, "_PSW", &arg_list, NULL); + status = acpi_execute_simple_method(dev->handle, "_PSW", enable); if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) { printk(KERN_ERR PREFIX "_PSW execution failed\n"); dev->wakeup.flags.valid = 0; diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 187ab61889e6..81b0f03d97db 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -31,12 +31,9 @@ static u8 sleep_states[ACPI_S_STATE_COUNT]; static void acpi_sleep_tts_switch(u32 acpi_state) { - union acpi_object in_arg = { ACPI_TYPE_INTEGER }; - struct acpi_object_list arg_list = { 1, &in_arg }; - acpi_status status = AE_OK; + acpi_status status; - in_arg.integer.value = acpi_state; - status = acpi_evaluate_object(NULL, "\\_TTS", &arg_list, NULL); + status = acpi_execute_simple_method(NULL, "\\_TTS", acpi_state); if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { /* * OS can't evaluate the _TTS object correctly. Some warning diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index a33821ca3895..94523c79dc5f 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -239,26 +239,16 @@ static int acpi_thermal_get_polling_frequency(struct acpi_thermal *tz) static int acpi_thermal_set_cooling_mode(struct acpi_thermal *tz, int mode) { - acpi_status status = AE_OK; - union acpi_object arg0 = { ACPI_TYPE_INTEGER }; - struct acpi_object_list arg_list = { 1, &arg0 }; - acpi_handle handle = NULL; - - if (!tz) return -EINVAL; - status = acpi_get_handle(tz->device->handle, "_SCP", &handle); - if (ACPI_FAILURE(status)) { + if (!acpi_has_method(tz->device->handle, "_SCP")) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "_SCP not present\n")); return -ENODEV; - } - - arg0.integer.value = mode; - - status = acpi_evaluate_object(handle, NULL, &arg_list, NULL); - if (ACPI_FAILURE(status)) + } else if (ACPI_FAILURE(acpi_execute_simple_method(tz->device->handle, + "_SCP", mode))) { return -ENODEV; + } return 0; } diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index b08d97376f84..87b85882b5df 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -510,3 +510,15 @@ bool acpi_has_method(acpi_handle handle, char *name) return ACPI_SUCCESS(acpi_get_handle(handle, name, &tmp)); } EXPORT_SYMBOL(acpi_has_method); + +acpi_status acpi_execute_simple_method(acpi_handle handle, char *method, + u64 arg) +{ + union acpi_object obj = { .type = ACPI_TYPE_INTEGER }; + struct acpi_object_list arg_list = { .count = 1, .pointer = &obj, }; + + obj.integer.value = arg; + + return acpi_evaluate_object(handle, method, &arg_list, NULL); +} +EXPORT_SYMBOL(acpi_execute_simple_method); diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index a84533e67b9d..b862c7f74941 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -353,14 +353,10 @@ static int acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level) { int status; - union acpi_object arg0 = { ACPI_TYPE_INTEGER }; - struct acpi_object_list args = { 1, &arg0 }; int state; - arg0.integer.value = level; - - status = acpi_evaluate_object(device->dev->handle, "_BCM", - &args, NULL); + status = acpi_execute_simple_method(device->dev->handle, + "_BCM", level); if (ACPI_FAILURE(status)) { ACPI_ERROR((AE_INFO, "Evaluating _BCM failed")); return -EIO; @@ -628,18 +624,15 @@ static int acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag) { acpi_status status; - union acpi_object arg0 = { ACPI_TYPE_INTEGER }; - struct acpi_object_list args = { 1, &arg0 }; if (!video->cap._DOS) return 0; if (bios_flag < 0 || bios_flag > 3 || lcd_flag < 0 || lcd_flag > 1) return -EINVAL; - arg0.integer.value = (lcd_flag << 2) | bios_flag; - video->dos_setting = arg0.integer.value; - status = acpi_evaluate_object(video->device->handle, "_DOS", - &args, NULL); + video->dos_setting = (lcd_flag << 2) | bios_flag; + status = acpi_execute_simple_method(video->device->handle, "_DOS", + (lcd_flag << 2) | bios_flag); if (ACPI_FAILURE(status)) return -EIO; diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 62b2811bade4..e3862587b9de 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -58,6 +58,8 @@ acpi_status acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld_info **pld); bool acpi_has_method(acpi_handle handle, char *name); +acpi_status acpi_execute_simple_method(acpi_handle handle, char *method, + u64 arg); #ifdef CONFIG_ACPI From 7d2421f84b445dc48c68d33911f1fd6ce6853ee3 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Sat, 29 Jun 2013 00:24:40 +0800 Subject: [PATCH 0087/3400] ACPI: introduce two helper functions for _EJ0 and _LCK Introduce two helper functions, acpi_evaluate_ej0() and acpi_evaluate_lck(), that will execute the _EJ0 and _LCK ACPI control methods, respectively, and use them to simplify the ACPI scan code. [rjw: Changelog] Signed-off-by: Jiang Liu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/scan.c | 31 ++++++----------------------- drivers/acpi/utils.c | 43 +++++++++++++++++++++++++++++++++++++++++ include/acpi/acpi_bus.h | 2 ++ 3 files changed, 51 insertions(+), 25 deletions(-) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index ada0b4cf2ba5..4c25c3b7ef81 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -193,8 +193,6 @@ static acpi_status acpi_bus_online_companions(acpi_handle handle, u32 lvl, static int acpi_scan_hot_remove(struct acpi_device *device) { acpi_handle handle = device->handle; - struct acpi_object_list arg_list; - union acpi_object arg; struct device *errdev; acpi_status status; unsigned long long sta; @@ -257,32 +255,15 @@ static int acpi_scan_hot_remove(struct acpi_device *device) put_device(&device->dev); device = NULL; - if (acpi_has_method(handle, "_LCK")) { - arg_list.count = 1; - arg_list.pointer = &arg; - arg.type = ACPI_TYPE_INTEGER; - arg.integer.value = 0; - acpi_evaluate_object(handle, "_LCK", &arg_list, NULL); - } - - arg_list.count = 1; - arg_list.pointer = &arg; - arg.type = ACPI_TYPE_INTEGER; - arg.integer.value = 1; - + acpi_evaluate_lck(handle, 0); /* * TBD: _EJD support. */ - status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL); - if (ACPI_FAILURE(status)) { - if (status == AE_NOT_FOUND) { - return -ENODEV; - } else { - acpi_handle_warn(handle, "Eject failed (0x%x)\n", - status); - return -EIO; - } - } + status = acpi_evaluate_ej0(handle); + if (status == AE_NOT_FOUND) + return -ENODEV; + else if (ACPI_FAILURE(status)) + return -EIO; /* * Verify if eject was indeed successful. If not, log an error diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index 87b85882b5df..552248b0005b 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -522,3 +522,46 @@ acpi_status acpi_execute_simple_method(acpi_handle handle, char *method, return acpi_evaluate_object(handle, method, &arg_list, NULL); } EXPORT_SYMBOL(acpi_execute_simple_method); + +/** + * acpi_evaluate_ej0: Evaluate _EJ0 method for hotplug operations + * @handle: ACPI device handle + * + * Evaluate device's _EJ0 method for hotplug operations. + */ +acpi_status acpi_evaluate_ej0(acpi_handle handle) +{ + acpi_status status; + + status = acpi_execute_simple_method(handle, "_EJ0", 1); + if (status == AE_NOT_FOUND) + acpi_handle_warn(handle, "No _EJ0 support for device\n"); + else if (ACPI_FAILURE(status)) + acpi_handle_warn(handle, "Eject failed (0x%x)\n", status); + + return status; +} + +/** + * acpi_evaluate_lck: Evaluate _LCK method to lock/unlock device + * @handle: ACPI device handle + * @lock: lock device if non-zero, otherwise unlock device + * + * Evaluate device's _LCK method if present to lock/unlock device + */ +acpi_status acpi_evaluate_lck(acpi_handle handle, int lock) +{ + acpi_status status; + + status = acpi_execute_simple_method(handle, "_LCK", !!lock); + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { + if (lock) + acpi_handle_warn(handle, + "Locking device failed (0x%x)\n", status); + else + acpi_handle_warn(handle, + "Unlocking device failed (0x%x)\n", status); + } + + return status; +} diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index e3862587b9de..f499157b04e8 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -60,6 +60,8 @@ acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld_info **pld bool acpi_has_method(acpi_handle handle, char *name); acpi_status acpi_execute_simple_method(acpi_handle handle, char *method, u64 arg); +acpi_status acpi_evaluate_ej0(acpi_handle handle); +acpi_status acpi_evaluate_lck(acpi_handle handle, int lock); #ifdef CONFIG_ACPI From ebf4df8db0e7e5db9f7fca5fcd0c2b90ac954385 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Sat, 29 Jun 2013 00:24:41 +0800 Subject: [PATCH 0088/3400] ACPI: Export acpi_(bay)|(dock)_match() from scan.c Functions acpi_dock_match() and acpi_bay_match() in scan.c can be shared with dock.c to reduce code duplication, so export them as global functions. Also add a new function acpi_ata_match() to check whether an ACPI device object represents an ATA device. [rjw: Changelog] Signed-off-by: Jiang Liu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/scan.c | 77 +++++++++++++++++++---------------------- include/acpi/acpi_bus.h | 3 ++ 2 files changed, 39 insertions(+), 41 deletions(-) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 4c25c3b7ef81..62e2055e8806 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1479,44 +1479,46 @@ static void acpi_device_get_busid(struct acpi_device *device) } } +/* + * acpi_ata_match - see if an acpi object is an ATA device + * + * If an acpi object has one of the ACPI ATA methods defined, + * then we can safely call it an ATA device. + */ +bool acpi_ata_match(acpi_handle handle) +{ + return acpi_has_method(handle, "_GTF") || + acpi_has_method(handle, "_GTM") || + acpi_has_method(handle, "_STM") || + acpi_has_method(handle, "_SDD"); +} + /* * acpi_bay_match - see if an acpi object is an ejectable driver bay * * If an acpi object is ejectable and has one of the ACPI ATA methods defined, * then we can safely call it an ejectable drive bay */ -static int acpi_bay_match(acpi_handle handle) +bool acpi_bay_match(acpi_handle handle) { acpi_handle phandle; if (!acpi_has_method(handle, "_EJ0")) - return -ENODEV; + return false; + if (acpi_ata_match(handle)) + return true; + if (ACPI_FAILURE(acpi_get_parent(handle, &phandle))) + return false; - if (acpi_has_method(handle, "_GTF") || - acpi_has_method(handle, "_GTM") || - acpi_has_method(handle, "_STM") || - acpi_has_method(handle, "_SDD")) - return 0; - - if (acpi_get_parent(handle, &phandle)) - return -ENODEV; - - if (acpi_has_method(phandle, "_GTF") || - acpi_has_method(phandle, "_GTM") || - acpi_has_method(phandle, "_STM") || - acpi_has_method(phandle, "_SDD")) - return 0; - - return -ENODEV; + return acpi_ata_match(phandle); } /* * acpi_dock_match - see if an acpi object has a _DCK method */ -static int acpi_dock_match(acpi_handle handle) +bool acpi_dock_match(acpi_handle handle) { - acpi_handle tmp; - return acpi_get_handle(handle, "_DCK", &tmp); + return acpi_has_method(handle, "_DCK"); } const char *acpi_device_hid(struct acpi_device *device) @@ -1554,33 +1556,26 @@ static void acpi_add_id(struct acpi_device_pnp *pnp, const char *dev_id) * lacks the SMBUS01 HID and the methods do not have the necessary "_" * prefix. Work around this. */ -static int acpi_ibm_smbus_match(acpi_handle handle) +static bool acpi_ibm_smbus_match(acpi_handle handle) { - struct acpi_buffer path = {ACPI_ALLOCATE_BUFFER, NULL}; - int result; + char node_name[ACPI_PATH_SEGMENT_LENGTH]; + struct acpi_buffer path = { sizeof(node_name), node_name }; if (!dmi_name_in_vendors("IBM")) - return -ENODEV; + return false; /* Look for SMBS object */ - result = acpi_get_name(handle, ACPI_SINGLE_NAME, &path); - if (result) - return result; - - if (strcmp("SMBS", path.pointer)) { - result = -ENODEV; - goto out; - } + if (ACPI_FAILURE(acpi_get_name(handle, ACPI_SINGLE_NAME, &path)) || + strcmp("SMBS", path.pointer)) + return false; /* Does it have the necessary (but misnamed) methods? */ - result = -ENODEV; if (acpi_has_method(handle, "SBI") && acpi_has_method(handle, "SBR") && acpi_has_method(handle, "SBW")) - result = 0; -out: - kfree(path.pointer); - return result; + return true; + + return false; } static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp, @@ -1628,11 +1623,11 @@ static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp, */ if (acpi_is_video_device(handle)) acpi_add_id(pnp, ACPI_VIDEO_HID); - else if (ACPI_SUCCESS(acpi_bay_match(handle))) + else if (acpi_bay_match(handle)) acpi_add_id(pnp, ACPI_BAY_HID); - else if (ACPI_SUCCESS(acpi_dock_match(handle))) + else if (acpi_dock_match(handle)) acpi_add_id(pnp, ACPI_DOCK_HID); - else if (!acpi_ibm_smbus_match(handle)) + else if (acpi_ibm_smbus_match(handle)) acpi_add_id(pnp, ACPI_SMBUS_IBM_HID); else if (list_empty(&pnp->ids) && handle == ACPI_ROOT_OBJECT) { acpi_add_id(pnp, ACPI_BUS_HID); /* \_SB, LNXSYBUS */ diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index f499157b04e8..facc0ba6dd21 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -62,6 +62,9 @@ acpi_status acpi_execute_simple_method(acpi_handle handle, char *method, u64 arg); acpi_status acpi_evaluate_ej0(acpi_handle handle); acpi_status acpi_evaluate_lck(acpi_handle handle, int lock); +bool acpi_ata_match(acpi_handle handle); +bool acpi_bay_match(acpi_handle handle); +bool acpi_dock_match(acpi_handle handle); #ifdef CONFIG_ACPI From c9b5471f8866956919955b70ab27b4737b8bce30 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Sat, 29 Jun 2013 00:24:42 +0800 Subject: [PATCH 0089/3400] ACPI: simplify dock driver with new helper functions Use helper functions introduced previously to simplify the ACPI dock driver. [rjw: Changelog] Signed-off-by: Jiang Liu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/dock.c | 122 +++++--------------------------------------- 1 file changed, 12 insertions(+), 110 deletions(-) diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 1bdb1facc17b..810d1d720b1f 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -226,48 +226,6 @@ find_dock_dependent_device(struct dock_station *ds, acpi_handle handle) /***************************************************************************** * Dock functions * *****************************************************************************/ -/** - * is_dock - see if a device is a dock station - * @handle: acpi handle of the device - * - * If an acpi object has a _DCK method, then it is by definition a dock - * station, so return true. - */ -static int is_dock(acpi_handle handle) -{ - acpi_status status; - acpi_handle tmp; - - status = acpi_get_handle(handle, "_DCK", &tmp); - if (ACPI_FAILURE(status)) - return 0; - return 1; -} - -static int __init is_ejectable(acpi_handle handle) -{ - acpi_status status; - acpi_handle tmp; - - status = acpi_get_handle(handle, "_EJ0", &tmp); - if (ACPI_FAILURE(status)) - return 0; - return 1; -} - -static int __init is_ata(acpi_handle handle) -{ - acpi_handle tmp; - - if ((ACPI_SUCCESS(acpi_get_handle(handle, "_GTF", &tmp))) || - (ACPI_SUCCESS(acpi_get_handle(handle, "_GTM", &tmp))) || - (ACPI_SUCCESS(acpi_get_handle(handle, "_STM", &tmp))) || - (ACPI_SUCCESS(acpi_get_handle(handle, "_SDD", &tmp)))) - return 1; - - return 0; -} - static int __init is_battery(acpi_handle handle) { struct acpi_device_info *info; @@ -284,17 +242,13 @@ static int __init is_battery(acpi_handle handle) return ret; } -static int __init is_ejectable_bay(acpi_handle handle) +/* Check whether ACPI object is an ejectable battery or disk bay */ +static bool __init is_ejectable_bay(acpi_handle handle) { - acpi_handle phandle; + if (acpi_has_method(handle, "_EJ0") && is_battery(handle)) + return true; - if (!is_ejectable(handle)) - return 0; - if (is_battery(handle) || is_ata(handle)) - return 1; - if (!acpi_get_parent(handle, &phandle) && is_ata(phandle)) - return 1; - return 0; + return acpi_bay_match(handle); } /** @@ -312,7 +266,7 @@ int is_dock_device(acpi_handle handle) if (!dock_station_count) return 0; - if (is_dock(handle)) + if (acpi_dock_match(handle)) return 1; list_for_each_entry(dock_station, &dock_stations, sibling) @@ -446,37 +400,6 @@ static void dock_event(struct dock_station *ds, u32 event, int num) kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp); } -/** - * eject_dock - respond to a dock eject request - * @ds: the dock station - * - * This is called after _DCK is called, to execute the dock station's - * _EJ0 method. - */ -static void eject_dock(struct dock_station *ds) -{ - struct acpi_object_list arg_list; - union acpi_object arg; - acpi_status status; - acpi_handle tmp; - - /* all dock devices should have _EJ0, but check anyway */ - status = acpi_get_handle(ds->handle, "_EJ0", &tmp); - if (ACPI_FAILURE(status)) { - pr_debug("No _EJ0 support for dock device\n"); - return; - } - - arg_list.count = 1; - arg_list.pointer = &arg; - arg.type = ACPI_TYPE_INTEGER; - arg.integer.value = 1; - - status = acpi_evaluate_object(ds->handle, "_EJ0", &arg_list, NULL); - if (ACPI_FAILURE(status)) - pr_debug("Failed to evaluate _EJ0!\n"); -} - /** * handle_dock - handle a dock event * @ds: the dock station @@ -537,27 +460,6 @@ static inline void complete_undock(struct dock_station *ds) ds->flags &= ~(DOCK_UNDOCKING); } -static void dock_lock(struct dock_station *ds, int lock) -{ - struct acpi_object_list arg_list; - union acpi_object arg; - acpi_status status; - - arg_list.count = 1; - arg_list.pointer = &arg; - arg.type = ACPI_TYPE_INTEGER; - arg.integer.value = !!lock; - status = acpi_evaluate_object(ds->handle, "_LCK", &arg_list, NULL); - if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { - if (lock) - acpi_handle_warn(ds->handle, - "Locking device failed (0x%x)\n", status); - else - acpi_handle_warn(ds->handle, - "Unlocking device failed (0x%x)\n", status); - } -} - /** * dock_in_progress - see if we are in the middle of handling a dock event * @ds: the dock station @@ -692,8 +594,8 @@ static int handle_eject_request(struct dock_station *ds, u32 event) hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST); undock(ds); - dock_lock(ds, 0); - eject_dock(ds); + acpi_evaluate_lck(ds->handle, 0); + acpi_evaluate_ej0(ds->handle); if (dock_present(ds)) { acpi_handle_err(ds->handle, "Unable to undock!\n"); return -EBUSY; @@ -752,7 +654,7 @@ static void dock_notify(acpi_handle handle, u32 event, void *data) hotplug_dock_devices(ds, event); complete_dock(ds); dock_event(ds, event, DOCK_EVENT); - dock_lock(ds, 1); + acpi_evaluate_lck(ds->handle, 1); acpi_update_all_gpes(); break; } @@ -998,9 +900,9 @@ static int __init dock_add(acpi_handle handle) /* we want the dock device to send uevents */ dev_set_uevent_suppress(&dd->dev, 0); - if (is_dock(handle)) + if (acpi_dock_match(handle)) dock_station->flags |= DOCK_IS_DOCK; - if (is_ata(handle)) + if (acpi_ata_match(handle)) dock_station->flags |= DOCK_IS_ATA; if (is_battery(handle)) dock_station->flags |= DOCK_IS_BAT; @@ -1043,7 +945,7 @@ err_unregister: static __init acpi_status find_dock_and_bay(acpi_handle handle, u32 lvl, void *context, void **rv) { - if (is_dock(handle) || is_ejectable_bay(handle)) + if (acpi_dock_match(handle) || is_ejectable_bay(handle)) dock_add(handle); return AE_OK; From ecd046da57d3327367b930478234e58f01bc9f0f Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Sat, 29 Jun 2013 00:24:43 +0800 Subject: [PATCH 0090/3400] ACPI: simplify acpiphp driver with new helper functions Use the new helper functions introduced previously to simplify the ACPI-based PCI hotplug (acpiphp) driver. [rjw: Changelog] Signed-off-by: Jiang Liu Acked-by: Bjorn Helgaas Signed-off-by: Rafael J. Wysocki --- drivers/pci/hotplug/acpiphp_glue.c | 30 ++++++++---------------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 59df8575a48c..a0a7133a1d12 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -201,7 +201,6 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) struct acpiphp_bridge *bridge = (struct acpiphp_bridge *)context; struct acpiphp_slot *slot; struct acpiphp_func *newfunc; - acpi_handle tmp; acpi_status status = AE_OK; unsigned long long adr, sun; int device, function, retval, found = 0; @@ -232,19 +231,19 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) newfunc->handle = handle; newfunc->function = function; - if (ACPI_SUCCESS(acpi_get_handle(handle, "_EJ0", &tmp))) + if (acpi_has_method(handle, "_EJ0")) newfunc->flags = FUNC_HAS_EJ0; - if (ACPI_SUCCESS(acpi_get_handle(handle, "_STA", &tmp))) + if (acpi_has_method(handle, "_STA")) newfunc->flags |= FUNC_HAS_STA; - if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS0", &tmp))) + if (acpi_has_method(handle, "_PS0")) newfunc->flags |= FUNC_HAS_PS0; - if (ACPI_SUCCESS(acpi_get_handle(handle, "_PS3", &tmp))) + if (acpi_has_method(handle, "_PS3")) newfunc->flags |= FUNC_HAS_PS3; - if (ACPI_SUCCESS(acpi_get_handle(handle, "_DCK", &tmp))) + if (acpi_has_method(handle, "_DCK")) newfunc->flags |= FUNC_HAS_DCK; status = acpi_evaluate_integer(handle, "_SUN", NULL, &sun); @@ -843,25 +842,14 @@ static unsigned int get_slot_status(struct acpiphp_slot *slot) */ int acpiphp_eject_slot(struct acpiphp_slot *slot) { - acpi_status status; struct acpiphp_func *func; - struct acpi_object_list arg_list; - union acpi_object arg; list_for_each_entry(func, &slot->funcs, sibling) { /* We don't want to call _EJ0 on non-existing functions. */ if ((func->flags & FUNC_HAS_EJ0)) { - /* _EJ0 method take one argument */ - arg_list.count = 1; - arg_list.pointer = &arg; - arg.type = ACPI_TYPE_INTEGER; - arg.integer.value = 1; - - status = acpi_evaluate_object(func->handle, "_EJ0", &arg_list, NULL); - if (ACPI_FAILURE(status)) { - warn("%s: _EJ0 failed\n", __func__); + if (ACPI_FAILURE(acpi_evaluate_ej0(func->handle))) return -1; - } else + else break; } } @@ -1171,7 +1159,6 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type, */ void acpiphp_enumerate_slots(struct pci_bus *bus, acpi_handle handle) { - acpi_handle dummy_handle; struct acpiphp_bridge *bridge; if (acpiphp_disabled) @@ -1200,8 +1187,7 @@ void acpiphp_enumerate_slots(struct pci_bus *bus, acpi_handle handle) get_device(&bus->dev); if (!pci_is_root_bus(bridge->pci_bus) && - ACPI_SUCCESS(acpi_get_handle(bridge->handle, - "_EJ0", &dummy_handle))) { + acpi_has_method(bridge->handle, "_EJ0")) { dbg("found ejectable p2p bridge\n"); bridge->flags |= BRIDGE_HAS_EJ0; bridge->func = acpiphp_bridge_handle_to_function(handle); From d460acebd7959cc91e7edc594d90adb9b72a0b05 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 30 Jun 2013 23:42:51 +0200 Subject: [PATCH 0091/3400] ACPI / dock: Drop the hp_lock mutex from struct dock_station The only existing user of the hp_lock mutex in struct dock_station, hotplug_dock_devices(), is always called under acpi_scan_lock and cannot race with another instance of itself, so drop the mutex which is not necessary. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/dock.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 810d1d720b1f..c10761533d6f 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -63,7 +63,6 @@ struct dock_station { acpi_handle handle; unsigned long last_dock_time; u32 flags; - struct mutex hp_lock; struct list_head dependent_devices; struct list_head sibling; @@ -351,8 +350,6 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event) { struct dock_dependent_device *dd; - mutex_lock(&ds->hp_lock); - /* * First call driver specific hotplug functions */ @@ -371,7 +368,6 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event) else dock_create_acpi_device(dd->handle); } - mutex_unlock(&ds->hp_lock); } static void dock_event(struct dock_station *ds, u32 event, int num) @@ -893,7 +889,6 @@ static int __init dock_add(acpi_handle handle) dock_station->dock_device = dd; dock_station->last_dock_time = jiffies - HZ; - mutex_init(&dock_station->hp_lock); INIT_LIST_HEAD(&dock_station->sibling); INIT_LIST_HEAD(&dock_station->dependent_devices); From 96c0a4d4902c3d5f56bde95d3e2d96689ca64b6d Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 30 Jun 2013 23:46:02 +0200 Subject: [PATCH 0092/3400] ACPI / dock: Rework and simplify find_dock_devices() Since acpi_walk_namespace() calls find_dock_devices() during tree pre-order visit, the latter doesn't need to add devices whose parents have _EJD pointing to the docking station to the list of that station's dependent devices, because those parents are going to be added to that list anyway and the removal of a parent will take care of the removal of its children in those cases. For this reason, rework find_dock_devices() to only call add_dock_dependent_device() for devices whose _EJD point directy to the docking station represented by its context argument and simplify it slightly. Signed-off-by: Rafael J. Wysocki Acked-by: Yinghai Lu --- drivers/acpi/dock.c | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index c10761533d6f..7c86d01346e6 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -741,29 +741,16 @@ static struct notifier_block dock_acpi_notifier = { * check to see if an object has an _EJD method. If it does, then it * will see if it is dependent on the dock station. */ -static acpi_status __init -find_dock_devices(acpi_handle handle, u32 lvl, void *context, void **rv) +static acpi_status __init find_dock_devices(acpi_handle handle, u32 lvl, + void *context, void **rv) { - acpi_status status; - acpi_handle tmp, parent; struct dock_station *ds = context; + acpi_handle ejd = NULL; - status = acpi_bus_get_ejd(handle, &tmp); - if (ACPI_FAILURE(status)) { - /* try the parent device as well */ - status = acpi_get_parent(handle, &parent); - if (ACPI_FAILURE(status)) - goto fdd_out; - /* see if parent is dependent on dock */ - status = acpi_bus_get_ejd(parent, &tmp); - if (ACPI_FAILURE(status)) - goto fdd_out; - } - - if (tmp == ds->handle) + acpi_bus_get_ejd(handle, &ejd); + if (ejd == ds->handle) add_dock_dependent_device(ds, handle); -fdd_out: return AE_OK; } From 37f908778f20bbcc35ab9a98a5b584329c6abf08 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 30 Jun 2013 23:46:42 +0200 Subject: [PATCH 0093/3400] ACPI / dock: Walk list in reverse order during removal of devices If there are indirect dependencies between devices in a dock station's dependent devices list, they may be broken if the devices are removed in the same order in which they have been added. For this reason, make the code in handle_eject_request() walk the list of dependent devices in reverse order. Signed-off-by: Rafael J. Wysocki Acked-by: Yinghai Lu --- drivers/acpi/dock.c | 45 +++++++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 7c86d01346e6..41c5d04a89c1 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -337,9 +337,29 @@ static void dock_remove_acpi_device(acpi_handle handle) } /** - * hotplug_dock_devices - insert or remove devices on the dock station + * hot_remove_dock_devices - Remove dock station devices. + * @ds: Dock station. + */ +static void hot_remove_dock_devices(struct dock_station *ds) +{ + struct dock_dependent_device *dd; + + /* + * Walk the list in reverse order so that devices that have been added + * last are removed first (in case there are some indirect dependencies + * between them). + */ + list_for_each_entry_reverse(dd, &ds->dependent_devices, list) + dock_hotplug_event(dd, ACPI_NOTIFY_EJECT_REQUEST, false); + + list_for_each_entry_reverse(dd, &ds->dependent_devices, list) + dock_remove_acpi_device(dd->handle); +} + +/** + * hotplug_dock_devices - Insert devices on a dock station. * @ds: the dock station - * @event: either bus check or eject request + * @event: either bus check or device check request * * Some devices on the dock station need to have drivers called * to perform hotplug operations after a dock event has occurred. @@ -350,24 +370,17 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event) { struct dock_dependent_device *dd; - /* - * First call driver specific hotplug functions - */ + /* Call driver specific hotplug functions. */ list_for_each_entry(dd, &ds->dependent_devices, list) dock_hotplug_event(dd, event, false); /* - * Now make sure that an acpi_device is created for each - * dependent device, or removed if this is an eject request. - * This will cause acpi_drivers to be stopped/started if they - * exist + * Now make sure that an acpi_device is created for each dependent + * device. That will cause scan handlers to be attached to device + * objects or acpi_drivers to be stopped/started if they are present. */ - list_for_each_entry(dd, &ds->dependent_devices, list) { - if (event == ACPI_NOTIFY_EJECT_REQUEST) - dock_remove_acpi_device(dd->handle); - else - dock_create_acpi_device(dd->handle); - } + list_for_each_entry(dd, &ds->dependent_devices, list) + dock_create_acpi_device(dd->handle); } static void dock_event(struct dock_station *ds, u32 event, int num) @@ -588,7 +601,7 @@ static int handle_eject_request(struct dock_station *ds, u32 event) */ dock_event(ds, event, UNDOCK_EVENT); - hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST); + hot_remove_dock_devices(ds); undock(ds); acpi_evaluate_lck(ds->handle, 0); acpi_evaluate_ej0(ds->handle); From 4ec24065a65b4debfdeb591cc01a4aa092651f53 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 30 Jun 2013 23:47:14 +0200 Subject: [PATCH 0094/3400] ACPI / dock: Simplify dock_init_hotplug() and dock_release_hotplug() Make dock_init_hotplug() and dock_release_hotplug() slightly simpler and move some checks in those functions to the code paths where they are needed. Signed-off-by: Rafael J. Wysocki Acked-by: Yinghai Lu --- drivers/acpi/dock.c | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 41c5d04a89c1..b1170d60a836 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -130,19 +130,16 @@ static int dock_init_hotplug(struct dock_dependent_device *dd, int ret = 0; mutex_lock(&hotplug_lock); - - if (dd->hp_context) { + if (WARN_ON(dd->hp_context)) { ret = -EEXIST; } else { dd->hp_refcount = 1; dd->hp_ops = ops; dd->hp_context = context; dd->hp_release = release; + if (init) + init(context); } - - if (!WARN_ON(ret) && init) - init(context); - mutex_unlock(&hotplug_lock); return ret; } @@ -157,22 +154,17 @@ static int dock_init_hotplug(struct dock_dependent_device *dd, */ static void dock_release_hotplug(struct dock_dependent_device *dd) { - void (*release)(void *) = NULL; - void *context = NULL; - mutex_lock(&hotplug_lock); - if (dd->hp_context && !--dd->hp_refcount) { + void (*release)(void *) = dd->hp_release; + void *context = dd->hp_context; + dd->hp_ops = NULL; - context = dd->hp_context; dd->hp_context = NULL; - release = dd->hp_release; dd->hp_release = NULL; + if (release) + release(context); } - - if (release && context) - release(context); - mutex_unlock(&hotplug_lock); } From 59401ccce8729e5c43f9781cc5570da5ca470e27 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 30 Jun 2013 23:48:49 +0200 Subject: [PATCH 0095/3400] ACPI / dock: Rework the handling of notifications The ACPI dock driver uses register_acpi_bus_notifier() which installs a notifier triggered globally for all system notifications. That first of all is inefficient, because the dock driver is only interested in notifications associated with the devices it handles, but it has to handle all system notifies for all devices. Moreover, it does that even if no docking stations are present in the system (CONFIG_ACPI_DOCK set is sufficient for that to happen). Besides, that is inconvenient, because it requires the driver to do extra work for each notification to find the target dock station object. For these reasons, rework the dock driver to install a notify handler individually for each dock station in the system using acpi_install_notify_handler(). This allows the dock station object to be passed directly to the notify handler and makes it possible to simplify the dock driver quite a bit. It also reduces the overhead related to the handling of all system notifies when CONFIG_ACPI_DOCK is set. Signed-off-by: Rafael J. Wysocki Acked-by: Yinghai Lu --- drivers/acpi/dock.c | 67 ++++++++++++++++----------------------------- 1 file changed, 24 insertions(+), 43 deletions(-) diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index b1170d60a836..a326c7993f4f 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -607,18 +607,17 @@ static int handle_eject_request(struct dock_station *ds, u32 event) /** * dock_notify - act upon an acpi dock notification - * @handle: the dock station handle + * @ds: dock station * @event: the acpi event - * @data: our driver data struct * * If we are notified to dock, then check to see if the dock is * present and then dock. Notify all drivers of the dock event, * and then hotplug and devices that may need hotplugging. */ -static void dock_notify(acpi_handle handle, u32 event, void *data) +static void dock_notify(struct dock_station *ds, u32 event) { - struct dock_station *ds = data; - struct acpi_device *tmp; + acpi_handle handle = ds->handle; + struct acpi_device *ad; int surprise_removal = 0; /* @@ -641,8 +640,7 @@ static void dock_notify(acpi_handle handle, u32 event, void *data) switch (event) { case ACPI_NOTIFY_BUS_CHECK: case ACPI_NOTIFY_DEVICE_CHECK: - if (!dock_in_progress(ds) && acpi_bus_get_device(ds->handle, - &tmp)) { + if (!dock_in_progress(ds) && acpi_bus_get_device(handle, &ad)) { begin_dock(ds); dock(ds); if (!dock_present(ds)) { @@ -679,9 +677,8 @@ static void dock_notify(acpi_handle handle, u32 event, void *data) } struct dock_data { - acpi_handle handle; - unsigned long event; struct dock_station *ds; + u32 event; }; static void acpi_dock_deferred_cb(void *context) @@ -689,52 +686,31 @@ static void acpi_dock_deferred_cb(void *context) struct dock_data *data = context; acpi_scan_lock_acquire(); - dock_notify(data->handle, data->event, data->ds); + dock_notify(data->ds, data->event); acpi_scan_lock_release(); kfree(data); } -static int acpi_dock_notifier_call(struct notifier_block *this, - unsigned long event, void *data) +static void dock_notify_handler(acpi_handle handle, u32 event, void *data) { - struct dock_station *dock_station; - acpi_handle handle = data; + struct dock_data *dd; if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK && event != ACPI_NOTIFY_EJECT_REQUEST) - return 0; + return; - acpi_scan_lock_acquire(); + dd = kmalloc(sizeof(*dd), GFP_KERNEL); + if (dd) { + acpi_status status; - list_for_each_entry(dock_station, &dock_stations, sibling) { - if (dock_station->handle == handle) { - struct dock_data *dd; - acpi_status status; - - dd = kmalloc(sizeof(*dd), GFP_KERNEL); - if (!dd) - break; - - dd->handle = handle; - dd->event = event; - dd->ds = dock_station; - status = acpi_os_hotplug_execute(acpi_dock_deferred_cb, - dd); - if (ACPI_FAILURE(status)) - kfree(dd); - - break; - } + dd->ds = data; + dd->event = event; + status = acpi_os_hotplug_execute(acpi_dock_deferred_cb, dd); + if (ACPI_FAILURE(status)) + kfree(dd); } - - acpi_scan_lock_release(); - return 0; } -static struct notifier_block dock_acpi_notifier = { - .notifier_call = acpi_dock_notifier_call, -}; - /** * find_dock_devices - find devices on the dock station * @handle: the handle of the device we are examining @@ -868,6 +844,7 @@ static int __init dock_add(acpi_handle handle) int ret, id; struct dock_station ds, *dock_station; struct platform_device *dd; + acpi_status status; id = dock_station_count; memset(&ds, 0, sizeof(ds)); @@ -908,6 +885,11 @@ static int __init dock_add(acpi_handle handle) if (ret) goto err_rmgroup; + status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, + dock_notify_handler, dock_station); + if (ACPI_FAILURE(status)) + goto err_rmgroup; + dock_station_count++; list_add(&dock_station->sibling, &dock_stations); return 0; @@ -953,7 +935,6 @@ void __init acpi_dock_init(void) } ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list); - register_acpi_bus_notifier(&dock_acpi_notifier); pr_info(PREFIX "%s: %d docks/bays found\n", ACPI_DOCK_DRIVER_DESCRIPTION, dock_station_count); } From f716fc2ac037c45a6c641eb9f20ec602e8d04e14 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 30 Jun 2013 23:49:55 +0200 Subject: [PATCH 0096/3400] ACPI: Drop ACPI bus notifier call chain There are no users of the ACPI bus notifier call chain, acpi_bus_notify_list, any more, so drop it. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/bus.c | 16 ---------------- include/acpi/acpi_bus.h | 2 -- 2 files changed, 18 deletions(-) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index a5a032e2344e..6fd27a9abcda 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -499,19 +499,6 @@ static void acpi_bus_check_scope(acpi_handle handle) */ } -static BLOCKING_NOTIFIER_HEAD(acpi_bus_notify_list); -int register_acpi_bus_notifier(struct notifier_block *nb) -{ - return blocking_notifier_chain_register(&acpi_bus_notify_list, nb); -} -EXPORT_SYMBOL_GPL(register_acpi_bus_notifier); - -void unregister_acpi_bus_notifier(struct notifier_block *nb) -{ - blocking_notifier_chain_unregister(&acpi_bus_notify_list, nb); -} -EXPORT_SYMBOL_GPL(unregister_acpi_bus_notifier); - /** * acpi_bus_notify * --------------- @@ -525,9 +512,6 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Notification %#02x to handle %p\n", type, handle)); - blocking_notifier_call_chain(&acpi_bus_notify_list, - type, (void *)handle); - switch (type) { case ACPI_NOTIFY_BUS_CHECK: diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index facc0ba6dd21..71f3fd429fd1 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -366,8 +366,6 @@ extern int acpi_notifier_call_chain(struct acpi_device *, u32, u32); extern int register_acpi_notifier(struct notifier_block *); extern int unregister_acpi_notifier(struct notifier_block *); -extern int register_acpi_bus_notifier(struct notifier_block *nb); -extern void unregister_acpi_bus_notifier(struct notifier_block *nb); /* * External Functions */ From a30c4c5ee85680bb66ed8a6c0b0bf4921125c378 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 30 Jun 2013 23:50:24 +0200 Subject: [PATCH 0097/3400] ACPI / dock: Do not leak memory on falilures to add a dock station The function creating and registering dock station objects, dock_add(), leaks memory if there's an error after it's walked the ACPI namespace calling find_dock_devices(), because it doesn't free the list of dependent devices it's just created in those cases. Fix that issue by adding the missing code to free the list of dependent devices on errors. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/dock.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index a326c7993f4f..3e20b13fa272 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -115,6 +115,16 @@ add_dock_dependent_device(struct dock_station *ds, acpi_handle handle) return 0; } +static void remove_dock_dependent_devices(struct dock_station *ds) +{ + struct dock_dependent_device *dd, *aux; + + list_for_each_entry_safe(dd, aux, &ds->dependent_devices, list) { + list_del(&dd->list); + kfree(dd); + } +} + /** * dock_init_hotplug - Initialize a hotplug device on a docking station. * @dd: Dock-dependent device. @@ -895,6 +905,7 @@ static int __init dock_add(acpi_handle handle) return 0; err_rmgroup: + remove_dock_dependent_devices(dock_station); sysfs_remove_group(&dd->dev.kobj, &dock_attribute_group); err_unregister: platform_device_unregister(dd); From e6c215f15a1cbf4cdd6996d95fba0c0d6c0f3ccc Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 5 Jul 2013 03:02:25 +0200 Subject: [PATCH 0098/3400] ACPI / dock: Do not check CONFIG_ACPI_DOCK_MODULE Since commit 94add0f (ACPI / dock: Initialize ACPI dock subsystem upfront) the ACPI dock driver cannot be a module, so CONFIG_ACPI_DOCK_MODULE is never set. For this reason, simplify the preprocessor conditional in include/acpi/acpi_drivers.h referring to that sybbol unnecessarily. Signed-off-by: Rafael J. Wysocki --- include/acpi/acpi_drivers.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h index b420939f5eb5..0cf85786ed21 100644 --- a/include/acpi/acpi_drivers.h +++ b/include/acpi/acpi_drivers.h @@ -117,7 +117,7 @@ struct acpi_dock_ops { acpi_notify_handler uevent; }; -#if defined(CONFIG_ACPI_DOCK) || defined(CONFIG_ACPI_DOCK_MODULE) +#ifdef CONFIG_ACPI_DOCK extern int is_dock_device(acpi_handle handle); extern int register_dock_notifier(struct notifier_block *nb); extern void unregister_dock_notifier(struct notifier_block *nb); @@ -150,6 +150,6 @@ static inline int register_hotplug_dock_device(acpi_handle handle, static inline void unregister_hotplug_dock_device(acpi_handle handle) { } -#endif +#endif /* CONFIG_ACPI_DOCK */ #endif /*__ACPI_DRIVERS_H__*/ From f09ce741a03ad7de591aa47e760fbeee28567b63 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 5 Jul 2013 03:03:25 +0200 Subject: [PATCH 0099/3400] ACPI / dock / PCI: Drop ACPI dock notifier chain The only user of the ACPI dock notifier chain is the ACPI-based PCI hotplug (acpiphp) driver that uses it to carry out post-dock fixups needed by some systems with broken _DCK. However, it is not necessary to use a separate notifier chain for that, as it can be simply replaced with a new callback in struct acpi_dock_ops. For this reason, add a new .fixup() callback to struct acpi_dock_ops and make hotplug_dock_devices() execute it for all dock devices with hotplug operations registered. Accordingly, make acpiphp point that callback to the function carrying out the post-dock fixups and do not register a separate dock notifier for each device registering dock operations. Finally, drop the ACPI dock notifier chain that has no more users. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/dock.c | 66 +++++++++++------------------- drivers/pci/hotplug/acpiphp.h | 1 - drivers/pci/hotplug/acpiphp_glue.c | 18 ++------ include/acpi/acpi_drivers.h | 10 +---- 4 files changed, 30 insertions(+), 65 deletions(-) diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 3e20b13fa272..c89a9c3b48b4 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -51,8 +51,6 @@ MODULE_PARM_DESC(immediate_undock, "1 (default) will cause the driver to " " the driver to wait for userspace to write the undock sysfs file " " before undocking"); -static struct atomic_notifier_head dock_notifier_list; - static const struct acpi_device_id dock_device_ids[] = { {"LNXDOCK", 0}, {"", 0}, @@ -89,6 +87,12 @@ struct dock_dependent_device { #define DOCK_EVENT 3 #define UNDOCK_EVENT 2 +enum dock_callback_type { + DOCK_CALL_HANDLER, + DOCK_CALL_FIXUP, + DOCK_CALL_UEVENT, +}; + /***************************************************************************** * Dock Dependent device functions * *****************************************************************************/ @@ -179,7 +183,7 @@ static void dock_release_hotplug(struct dock_dependent_device *dd) } static void dock_hotplug_event(struct dock_dependent_device *dd, u32 event, - bool uevent) + enum dock_callback_type cb_type) { acpi_notify_handler cb = NULL; bool run = false; @@ -189,8 +193,18 @@ static void dock_hotplug_event(struct dock_dependent_device *dd, u32 event, if (dd->hp_context) { run = true; dd->hp_refcount++; - if (dd->hp_ops) - cb = uevent ? dd->hp_ops->uevent : dd->hp_ops->handler; + if (dd->hp_ops) { + switch (cb_type) { + case DOCK_CALL_FIXUP: + cb = dd->hp_ops->fixup; + break; + case DOCK_CALL_UEVENT: + cb = dd->hp_ops->uevent; + break; + default: + cb = dd->hp_ops->handler; + } + } } mutex_unlock(&hotplug_lock); @@ -372,9 +386,13 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event) { struct dock_dependent_device *dd; + /* Call driver specific post-dock fixups. */ + list_for_each_entry(dd, &ds->dependent_devices, list) + dock_hotplug_event(dd, event, DOCK_CALL_FIXUP); + /* Call driver specific hotplug functions. */ list_for_each_entry(dd, &ds->dependent_devices, list) - dock_hotplug_event(dd, event, false); + dock_hotplug_event(dd, event, DOCK_CALL_HANDLER); /* * Now make sure that an acpi_device is created for each dependent @@ -405,7 +423,7 @@ static void dock_event(struct dock_station *ds, u32 event, int num) kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp); list_for_each_entry(dd, &ds->dependent_devices, list) - dock_hotplug_event(dd, event, true); + dock_hotplug_event(dd, event, DOCK_CALL_UEVENT); if (num != DOCK_EVENT) kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp); @@ -487,37 +505,6 @@ static int dock_in_progress(struct dock_station *ds) return 0; } -/** - * register_dock_notifier - add yourself to the dock notifier list - * @nb: the callers notifier block - * - * If a driver wishes to be notified about dock events, they can - * use this function to put a notifier block on the dock notifier list. - * this notifier call chain will be called after a dock event, but - * before hotplugging any new devices. - */ -int register_dock_notifier(struct notifier_block *nb) -{ - if (!dock_station_count) - return -ENODEV; - - return atomic_notifier_chain_register(&dock_notifier_list, nb); -} -EXPORT_SYMBOL_GPL(register_dock_notifier); - -/** - * unregister_dock_notifier - remove yourself from the dock notifier list - * @nb: the callers notifier block - */ -void unregister_dock_notifier(struct notifier_block *nb) -{ - if (!dock_station_count) - return; - - atomic_notifier_chain_unregister(&dock_notifier_list, nb); -} -EXPORT_SYMBOL_GPL(unregister_dock_notifier); - /** * register_hotplug_dock_device - register a hotplug function * @handle: the handle of the device @@ -658,8 +645,6 @@ static void dock_notify(struct dock_station *ds, u32 event) complete_dock(ds); break; } - atomic_notifier_call_chain(&dock_notifier_list, - event, NULL); hotplug_dock_devices(ds, event); complete_dock(ds); dock_event(ds, event, DOCK_EVENT); @@ -945,7 +930,6 @@ void __init acpi_dock_init(void) return; } - ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list); pr_info(PREFIX "%s: %d docks/bays found\n", ACPI_DOCK_DRIVER_DESCRIPTION, dock_station_count); } diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 6fdd49c6f0b9..6c781edabcc6 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -122,7 +122,6 @@ struct acpiphp_func { struct acpiphp_slot *slot; /* parent */ struct list_head sibling; - struct notifier_block nb; acpi_handle handle; u8 function; /* pci function# */ diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index a0a7133a1d12..8bfad0dc29ab 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -119,15 +119,14 @@ static void free_bridge(struct kref *kref) * TBD - figure out a way to only call fixups for * systems that require them. */ -static int post_dock_fixups(struct notifier_block *nb, unsigned long val, - void *v) +static void post_dock_fixups(acpi_handle not_used, u32 event, void *data) { - struct acpiphp_func *func = container_of(nb, struct acpiphp_func, nb); + struct acpiphp_func *func = data; struct pci_bus *bus = func->slot->bridge->pci_bus; u32 buses; if (!bus->self) - return NOTIFY_OK; + return; /* fixup bad _DCK function that rewrites * secondary bridge on slot @@ -143,11 +142,11 @@ static int post_dock_fixups(struct notifier_block *nb, unsigned long val, | ((unsigned int)(bus->busn_res.end) << 16); pci_write_config_dword(bus->self, PCI_PRIMARY_BUS, buses); } - return NOTIFY_OK; } static const struct acpi_dock_ops acpiphp_dock_ops = { + .fixup = post_dock_fixups, .handler = hotplug_event_func, }; @@ -315,14 +314,6 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) &acpiphp_dock_ops, newfunc, acpiphp_dock_init, acpiphp_dock_release)) dbg("failed to register dock device\n"); - - /* we need to be notified when dock events happen - * outside of the hotplug operation, since we may - * need to do fixups before we can hotplug. - */ - newfunc->nb.notifier_call = post_dock_fixups; - if (register_dock_notifier(&newfunc->nb)) - dbg("failed to register a dock notifier"); } /* install notify handler */ @@ -472,7 +463,6 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) list_for_each_entry(func, &slot->funcs, sibling) { if (is_dock_device(func->handle)) { unregister_hotplug_dock_device(func->handle); - unregister_dock_notifier(&func->nb); } if (!(func->flags & FUNC_HAS_DCK)) { status = acpi_remove_notify_handler(func->handle, diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h index 0cf85786ed21..1cedfcb1bd88 100644 --- a/include/acpi/acpi_drivers.h +++ b/include/acpi/acpi_drivers.h @@ -113,14 +113,13 @@ void pci_acpi_crs_quirks(void); Dock Station -------------------------------------------------------------------------- */ struct acpi_dock_ops { + acpi_notify_handler fixup; acpi_notify_handler handler; acpi_notify_handler uevent; }; #ifdef CONFIG_ACPI_DOCK extern int is_dock_device(acpi_handle handle); -extern int register_dock_notifier(struct notifier_block *nb); -extern void unregister_dock_notifier(struct notifier_block *nb); extern int register_hotplug_dock_device(acpi_handle handle, const struct acpi_dock_ops *ops, void *context, @@ -132,13 +131,6 @@ static inline int is_dock_device(acpi_handle handle) { return 0; } -static inline int register_dock_notifier(struct notifier_block *nb) -{ - return -ENODEV; -} -static inline void unregister_dock_notifier(struct notifier_block *nb) -{ -} static inline int register_hotplug_dock_device(acpi_handle handle, const struct acpi_dock_ops *ops, void *context, From 2efbca4dfc7b43951de6dd1647f9eebda9d4372b Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 5 Jul 2013 03:23:36 +0200 Subject: [PATCH 0100/3400] ACPI / dock: Drop unnecessary local variable from dock_add() The local variable id in dock_add() is not necessary, so drop it. While we're at it, use an initializer to clear the local variable ds and drop the memset() used for this purpose. Signed-off-by: Rafael J. Wysocki --- drivers/acpi/dock.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index c89a9c3b48b4..f601658a4ad2 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -836,14 +836,13 @@ static struct attribute_group dock_attribute_group = { */ static int __init dock_add(acpi_handle handle) { - int ret, id; - struct dock_station ds, *dock_station; + struct dock_station *dock_station, ds = { NULL, }; struct platform_device *dd; acpi_status status; + int ret; - id = dock_station_count; - memset(&ds, 0, sizeof(ds)); - dd = platform_device_register_data(NULL, "dock", id, &ds, sizeof(ds)); + dd = platform_device_register_data(NULL, "dock", dock_station_count, + &ds, sizeof(ds)); if (IS_ERR(dd)) return PTR_ERR(dd); From 137b944e100278d696826cf25c83014ac17473fe Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Wed, 12 Jun 2013 15:08:48 +0200 Subject: [PATCH 0101/3400] cpuidle: Make it clear that governors cannot be modules cpufreq governors are defined as modules in the code, but the Kconfig options do not allow them to be built as modules. This is not really a problem, but the cpuidle init ordering is: the cpuidle init functions (framework and driver) and then the governors. That leads to some weirdness in the cpuidle framework. Namely, cpuidle_register_device() calls cpuidle_enable_device() which fails at the first attempt, because governors have not been registered yet. When a governor is registered, the framework calls cpuidle_enable_device() again which runs __cpuidle_register_device() only then. Of course, for that to work, the cpuidle_enable_device() return value has to be ignored by cpuidle_register_device(). Instead of having this cyclic call graph and relying on a positive side effects of the hackish back and forth cpuidle_enable_device() calls it is better to fix the cpuidle init ordering. To that end, replace the module init code with postcore_initcall() so we have: * cpuidle framework : core_initcall * cpuidle governors : postcore_initcall * cpuidle drivers : device_initcall and remove the corresponding module exit code as it is dead anyway (governors can't be built as modules). [rjw: Changelog] Signed-off-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/governors/ladder.c | 12 +----------- drivers/cpuidle/governors/menu.c | 12 +----------- 2 files changed, 2 insertions(+), 22 deletions(-) diff --git a/drivers/cpuidle/governors/ladder.c b/drivers/cpuidle/governors/ladder.c index 9b784051ec12..9f08e8cce1af 100644 --- a/drivers/cpuidle/governors/ladder.c +++ b/drivers/cpuidle/governors/ladder.c @@ -192,14 +192,4 @@ static int __init init_ladder(void) return cpuidle_register_governor(&ladder_governor); } -/** - * exit_ladder - exits the governor - */ -static void __exit exit_ladder(void) -{ - cpuidle_unregister_governor(&ladder_governor); -} - -MODULE_LICENSE("GPL"); -module_init(init_ladder); -module_exit(exit_ladder); +postcore_initcall(init_ladder); diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index fe343a06b7da..743138c309a1 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -540,14 +540,4 @@ static int __init init_menu(void) return cpuidle_register_governor(&menu_governor); } -/** - * exit_menu - exits the governor - */ -static void __exit exit_menu(void) -{ - cpuidle_unregister_governor(&menu_governor); -} - -MODULE_LICENSE("GPL"); -module_init(init_menu); -module_exit(exit_menu); +postcore_initcall(init_menu); From 10b9d3f8a4d5c82bff5b232a0063669dc0e0d725 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Wed, 12 Jun 2013 15:08:49 +0200 Subject: [PATCH 0102/3400] cpuidle: Check cpuidle_enable_device() return value We previously changed the ordering of the cpuidle framework initialization so that the governors are registered before the drivers which can register their devices right from the start. Now, we can safely remove the __cpuidle_register_device() call hack in cpuidle_enable_device() and check if the driver has been registered before enabling it. Then, cpuidle_register_device() can consistently check the cpuidle_enable_device() return value when enabling the device. [rjw: Changelog] Signed-off-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/cpuidle.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index fdc432f18022..4deed977f209 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -292,15 +292,12 @@ int cpuidle_enable_device(struct cpuidle_device *dev) if (!drv || !cpuidle_curr_governor) return -EIO; + if (!dev->registered) + return -EINVAL; + if (!dev->state_count) dev->state_count = drv->state_count; - if (dev->registered == 0) { - ret = __cpuidle_register_device(dev); - if (ret) - return ret; - } - poll_idle_init(drv); ret = cpuidle_add_device_sysfs(dev); @@ -415,13 +412,17 @@ int cpuidle_register_device(struct cpuidle_device *dev) return ret; } - cpuidle_enable_device(dev); + ret = cpuidle_enable_device(dev); + if (ret) { + mutex_unlock(&cpuidle_lock); + return ret; + } + cpuidle_install_idle_handler(); mutex_unlock(&cpuidle_lock); return 0; - } EXPORT_SYMBOL_GPL(cpuidle_register_device); From f89ae89e2790341587f7132f0552c941342115e9 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Wed, 12 Jun 2013 15:08:50 +0200 Subject: [PATCH 0103/3400] cpuidle: Fix white space to follow CodingStyle Fix white space in the cpuidle code to follow the rules described in CodingStyle. No changes in behavior should result from this. [rjw: Changelog] Signed-off-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/sysfs.c | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c index 428754af6236..7d4448a9fbbd 100644 --- a/drivers/cpuidle/sysfs.c +++ b/drivers/cpuidle/sysfs.c @@ -33,7 +33,8 @@ static ssize_t show_available_governors(struct device *dev, mutex_lock(&cpuidle_lock); list_for_each_entry(tmp, &cpuidle_governors, governor_list) { - if (i >= (ssize_t) ((PAGE_SIZE/sizeof(char)) - CPUIDLE_NAME_LEN - 2)) + if (i >= (ssize_t) ((PAGE_SIZE/sizeof(char)) - + CPUIDLE_NAME_LEN - 2)) goto out; i += scnprintf(&buf[i], CPUIDLE_NAME_LEN, "%s ", tmp->name); } @@ -168,11 +169,13 @@ struct cpuidle_attr { #define kobj_to_cpuidledev(k) container_of(k, struct cpuidle_device, kobj) #define attr_to_cpuidleattr(a) container_of(a, struct cpuidle_attr, attr) -static ssize_t cpuidle_show(struct kobject * kobj, struct attribute * attr ,char * buf) + +static ssize_t cpuidle_show(struct kobject *kobj, struct attribute *attr, + char *buf) { int ret = -EIO; struct cpuidle_device *dev = kobj_to_cpuidledev(kobj); - struct cpuidle_attr * cattr = attr_to_cpuidleattr(attr); + struct cpuidle_attr *cattr = attr_to_cpuidleattr(attr); if (cattr->show) { mutex_lock(&cpuidle_lock); @@ -182,12 +185,12 @@ static ssize_t cpuidle_show(struct kobject * kobj, struct attribute * attr ,char return ret; } -static ssize_t cpuidle_store(struct kobject * kobj, struct attribute * attr, - const char * buf, size_t count) +static ssize_t cpuidle_store(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) { int ret = -EIO; struct cpuidle_device *dev = kobj_to_cpuidledev(kobj); - struct cpuidle_attr * cattr = attr_to_cpuidleattr(attr); + struct cpuidle_attr *cattr = attr_to_cpuidleattr(attr); if (cattr->store) { mutex_lock(&cpuidle_lock); @@ -237,8 +240,8 @@ static ssize_t show_state_##_name(struct cpuidle_state *state, \ #define define_store_state_ull_function(_name) \ static ssize_t store_state_##_name(struct cpuidle_state *state, \ - struct cpuidle_state_usage *state_usage, \ - const char *buf, size_t size) \ + struct cpuidle_state_usage *state_usage, \ + const char *buf, size_t size) \ { \ unsigned long long value; \ int err; \ @@ -256,14 +259,16 @@ static ssize_t store_state_##_name(struct cpuidle_state *state, \ #define define_show_state_ull_function(_name) \ static ssize_t show_state_##_name(struct cpuidle_state *state, \ - struct cpuidle_state_usage *state_usage, char *buf) \ + struct cpuidle_state_usage *state_usage, \ + char *buf) \ { \ return sprintf(buf, "%llu\n", state_usage->_name);\ } #define define_show_state_str_function(_name) \ static ssize_t show_state_##_name(struct cpuidle_state *state, \ - struct cpuidle_state_usage *state_usage, char *buf) \ + struct cpuidle_state_usage *state_usage, \ + char *buf) \ { \ if (state->_name[0] == '\0')\ return sprintf(buf, "\n");\ @@ -309,8 +314,9 @@ struct cpuidle_state_kobj { #define kobj_to_state(k) (kobj_to_state_obj(k)->state) #define kobj_to_state_usage(k) (kobj_to_state_obj(k)->state_usage) #define attr_to_stateattr(a) container_of(a, struct cpuidle_state_attr, attr) -static ssize_t cpuidle_state_show(struct kobject * kobj, - struct attribute * attr ,char * buf) + +static ssize_t cpuidle_state_show(struct kobject *kobj, struct attribute *attr, + char * buf) { int ret = -EIO; struct cpuidle_state *state = kobj_to_state(kobj); @@ -323,8 +329,8 @@ static ssize_t cpuidle_state_show(struct kobject * kobj, return ret; } -static ssize_t cpuidle_state_store(struct kobject *kobj, - struct attribute *attr, const char *buf, size_t size) +static ssize_t cpuidle_state_store(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t size) { int ret = -EIO; struct cpuidle_state *state = kobj_to_state(kobj); @@ -449,8 +455,8 @@ static void cpuidle_driver_sysfs_release(struct kobject *kobj) complete(&driver_kobj->kobj_unregister); } -static ssize_t cpuidle_driver_show(struct kobject *kobj, struct attribute * attr, - char * buf) +static ssize_t cpuidle_driver_show(struct kobject *kobj, struct attribute *attr, + char *buf) { int ret = -EIO; struct cpuidle_driver_kobj *driver_kobj = kobj_to_driver_kobj(kobj); From 728ce22b696f9f1404a74d7b2279a65933553a1b Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Wed, 12 Jun 2013 15:08:51 +0200 Subject: [PATCH 0104/3400] cpuidle: Make cpuidle's sysfs directory dynamically allocated The cpuidle sysfs code is designed to have a single instance of per CPU cpuidle directory. It is not possible to remove the sysfs entry and create it again. This is not a problem with the current code but future changes will add CPU hotplug support to enable/disable the device, so it will need to remove the sysfs entry like other subsystems do. That won't be possible without this change, because the kobj is a static object which can't be reused for kobj_init_and_add(). Add cpuidle_device_kobj to be allocated dynamically when adding/removing a sysfs entry which is consistent with the other cpuidle's sysfs entries. An added benefit is that the sysfs code is now more self-contained and the includes needed for sysfs can be moved from cpuidle.h directly into sysfs.c so as to reduce the total number of headers dragged along with cpuidle.h. [rjw: Changelog] Signed-off-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/sysfs.c | 63 +++++++++++++++++++++++++++++++---------- include/linux/cpuidle.h | 7 ++--- 2 files changed, 51 insertions(+), 19 deletions(-) diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c index 7d4448a9fbbd..8739cc05228c 100644 --- a/drivers/cpuidle/sysfs.c +++ b/drivers/cpuidle/sysfs.c @@ -11,8 +11,10 @@ #include #include #include +#include #include #include +#include #include "cpuidle.h" @@ -167,14 +169,27 @@ struct cpuidle_attr { #define define_one_rw(_name, show, store) \ static struct cpuidle_attr attr_##_name = __ATTR(_name, 0644, show, store) -#define kobj_to_cpuidledev(k) container_of(k, struct cpuidle_device, kobj) #define attr_to_cpuidleattr(a) container_of(a, struct cpuidle_attr, attr) +struct cpuidle_device_kobj { + struct cpuidle_device *dev; + struct completion kobj_unregister; + struct kobject kobj; +}; + +static inline struct cpuidle_device *to_cpuidle_device(struct kobject *kobj) +{ + struct cpuidle_device_kobj *kdev = + container_of(kobj, struct cpuidle_device_kobj, kobj); + + return kdev->dev; +} + static ssize_t cpuidle_show(struct kobject *kobj, struct attribute *attr, char *buf) { int ret = -EIO; - struct cpuidle_device *dev = kobj_to_cpuidledev(kobj); + struct cpuidle_device *dev = to_cpuidle_device(kobj); struct cpuidle_attr *cattr = attr_to_cpuidleattr(attr); if (cattr->show) { @@ -189,7 +204,7 @@ static ssize_t cpuidle_store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t count) { int ret = -EIO; - struct cpuidle_device *dev = kobj_to_cpuidledev(kobj); + struct cpuidle_device *dev = to_cpuidle_device(kobj); struct cpuidle_attr *cattr = attr_to_cpuidleattr(attr); if (cattr->store) { @@ -207,9 +222,10 @@ static const struct sysfs_ops cpuidle_sysfs_ops = { static void cpuidle_sysfs_release(struct kobject *kobj) { - struct cpuidle_device *dev = kobj_to_cpuidledev(kobj); + struct cpuidle_device_kobj *kdev = + container_of(kobj, struct cpuidle_device_kobj, kobj); - complete(&dev->kobj_unregister); + complete(&kdev->kobj_unregister); } static struct kobj_type ktype_cpuidle = { @@ -377,6 +393,7 @@ static int cpuidle_add_state_sysfs(struct cpuidle_device *device) { int i, ret = -ENOMEM; struct cpuidle_state_kobj *kobj; + struct cpuidle_device_kobj *kdev = device->kobj_dev; struct cpuidle_driver *drv = cpuidle_get_cpu_driver(device); /* state statistics */ @@ -389,7 +406,7 @@ static int cpuidle_add_state_sysfs(struct cpuidle_device *device) init_completion(&kobj->kobj_unregister); ret = kobject_init_and_add(&kobj->kobj, &ktype_state_cpuidle, - &device->kobj, "state%d", i); + &kdev->kobj, "state%d", i); if (ret) { kfree(kobj); goto error_state; @@ -506,6 +523,7 @@ static struct kobj_type ktype_driver_cpuidle = { static int cpuidle_add_driver_sysfs(struct cpuidle_device *dev) { struct cpuidle_driver_kobj *kdrv; + struct cpuidle_device_kobj *kdev = dev->kobj_dev; struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev); int ret; @@ -517,7 +535,7 @@ static int cpuidle_add_driver_sysfs(struct cpuidle_device *dev) init_completion(&kdrv->kobj_unregister); ret = kobject_init_and_add(&kdrv->kobj, &ktype_driver_cpuidle, - &dev->kobj, "driver"); + &kdev->kobj, "driver"); if (ret) { kfree(kdrv); return ret; @@ -586,16 +604,28 @@ void cpuidle_remove_device_sysfs(struct cpuidle_device *device) */ int cpuidle_add_sysfs(struct cpuidle_device *dev) { + struct cpuidle_device_kobj *kdev; struct device *cpu_dev = get_cpu_device((unsigned long)dev->cpu); int error; - init_completion(&dev->kobj_unregister); + kdev = kzalloc(sizeof(*kdev), GFP_KERNEL); + if (!kdev) + return -ENOMEM; + kdev->dev = dev; + dev->kobj_dev = kdev; - error = kobject_init_and_add(&dev->kobj, &ktype_cpuidle, &cpu_dev->kobj, - "cpuidle"); - if (!error) - kobject_uevent(&dev->kobj, KOBJ_ADD); - return error; + init_completion(&kdev->kobj_unregister); + + error = kobject_init_and_add(&kdev->kobj, &ktype_cpuidle, &cpu_dev->kobj, + "cpuidle"); + if (error) { + kfree(kdev); + return error; + } + + kobject_uevent(&kdev->kobj, KOBJ_ADD); + + return 0; } /** @@ -604,6 +634,9 @@ int cpuidle_add_sysfs(struct cpuidle_device *dev) */ void cpuidle_remove_sysfs(struct cpuidle_device *dev) { - kobject_put(&dev->kobj); - wait_for_completion(&dev->kobj_unregister); + struct cpuidle_device_kobj *kdev = dev->kobj_dev; + + kobject_put(&kdev->kobj); + wait_for_completion(&kdev->kobj_unregister); + kfree(kdev); } diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 0bc4b74668e9..b922db53b7ab 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -13,8 +13,6 @@ #include #include -#include -#include #include #define CPUIDLE_STATE_MAX 10 @@ -61,6 +59,8 @@ struct cpuidle_state { #define CPUIDLE_DRIVER_FLAGS_MASK (0xFFFF0000) +struct cpuidle_device_kobj; + struct cpuidle_device { unsigned int registered:1; unsigned int enabled:1; @@ -71,9 +71,8 @@ struct cpuidle_device { struct cpuidle_state_usage states_usage[CPUIDLE_STATE_MAX]; struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX]; struct cpuidle_driver_kobj *kobj_driver; + struct cpuidle_device_kobj *kobj_dev; struct list_head device_list; - struct kobject kobj; - struct completion kobj_unregister; #ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED int safe_state_index; From 1a7064380e6639e1cc5ed609ceb1ed46f3f188e3 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Wed, 12 Jun 2013 15:08:52 +0200 Subject: [PATCH 0105/3400] cpuidle: Add missing forward declarations of structures Add missing forward declarations of struct cpuidle_state_kobj and struct cpuidle_driver_kobj in cpuidle.h. [rjw: Changelog] Signed-off-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- include/linux/cpuidle.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index b922db53b7ab..781addc66f03 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -60,6 +60,8 @@ struct cpuidle_state { #define CPUIDLE_DRIVER_FLAGS_MASK (0xFFFF0000) struct cpuidle_device_kobj; +struct cpuidle_state_kobj; +struct cpuidle_driver_kobj; struct cpuidle_device { unsigned int registered:1; From f6bb51a53a7535c79d6c65862d6b48e83340b337 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Wed, 12 Jun 2013 15:08:53 +0200 Subject: [PATCH 0106/3400] cpuidle: Introduce __cpuidle_unregister_device() To reduce code duplication related to the unregistration of cpuidle devices, introduce __cpuidle_unregister_device() and move all of the unregistration code to that function. [rjw: Changelog] Signed-off-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/cpuidle.c | 62 ++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 4deed977f209..d78c6d89272f 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -42,8 +42,6 @@ void disable_cpuidle(void) off = 1; } -static int __cpuidle_register_device(struct cpuidle_device *dev); - /** * cpuidle_play_dead - cpu off-lining * @@ -357,6 +355,15 @@ void cpuidle_disable_device(struct cpuidle_device *dev) EXPORT_SYMBOL_GPL(cpuidle_disable_device); +static void __cpuidle_unregister_device(struct cpuidle_device *dev) +{ + struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev); + + list_del(&dev->device_list); + per_cpu(cpuidle_devices, dev->cpu) = NULL; + module_put(drv->owner); +} + /** * __cpuidle_register_device - internal register function called before register * and enable routines @@ -374,24 +381,15 @@ static int __cpuidle_register_device(struct cpuidle_device *dev) per_cpu(cpuidle_devices, dev->cpu) = dev; list_add(&dev->device_list, &cpuidle_detected_devices); - ret = cpuidle_add_sysfs(dev); - if (ret) - goto err_sysfs; ret = cpuidle_coupled_register_device(dev); - if (ret) - goto err_coupled; + if (ret) { + __cpuidle_unregister_device(dev); + return ret; + } dev->registered = 1; return 0; - -err_coupled: - cpuidle_remove_sysfs(dev); -err_sysfs: - list_del(&dev->device_list); - per_cpu(cpuidle_devices, dev->cpu) = NULL; - module_put(drv->owner); - return ret; } /** @@ -407,22 +405,30 @@ int cpuidle_register_device(struct cpuidle_device *dev) mutex_lock(&cpuidle_lock); - if ((ret = __cpuidle_register_device(dev))) { - mutex_unlock(&cpuidle_lock); - return ret; - } + ret = __cpuidle_register_device(dev); + if (ret) + goto out_unlock; + + ret = cpuidle_add_sysfs(dev); + if (ret) + goto out_unregister; ret = cpuidle_enable_device(dev); - if (ret) { - mutex_unlock(&cpuidle_lock); - return ret; - } + if (ret) + goto out_sysfs; cpuidle_install_idle_handler(); +out_unlock: mutex_unlock(&cpuidle_lock); - return 0; + return ret; + +out_sysfs: + cpuidle_remove_sysfs(dev); +out_unregister: + __cpuidle_unregister_device(dev); + goto out_unlock; } EXPORT_SYMBOL_GPL(cpuidle_register_device); @@ -433,8 +439,6 @@ EXPORT_SYMBOL_GPL(cpuidle_register_device); */ void cpuidle_unregister_device(struct cpuidle_device *dev) { - struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev); - if (dev->registered == 0) return; @@ -443,14 +447,12 @@ void cpuidle_unregister_device(struct cpuidle_device *dev) cpuidle_disable_device(dev); cpuidle_remove_sysfs(dev); - list_del(&dev->device_list); - per_cpu(cpuidle_devices, dev->cpu) = NULL; + + __cpuidle_unregister_device(dev); cpuidle_coupled_unregister_device(dev); cpuidle_resume_and_unlock(); - - module_put(drv->owner); } EXPORT_SYMBOL_GPL(cpuidle_unregister_device); From 5df0aa7341bd94ca2023a60c64c63faeb6ec209d Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Wed, 12 Jun 2013 15:08:54 +0200 Subject: [PATCH 0107/3400] cpuidle: Introduce __cpuidle_device_init() Add __cpuidle_device_init() for initializing the cpuidle_device structure. [rjw: Changelog] Signed-off-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/cpuidle.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index d78c6d89272f..5b63185da59b 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -276,7 +276,7 @@ static void poll_idle_init(struct cpuidle_driver *drv) {} */ int cpuidle_enable_device(struct cpuidle_device *dev) { - int ret, i; + int ret; struct cpuidle_driver *drv; if (!dev) @@ -306,12 +306,6 @@ int cpuidle_enable_device(struct cpuidle_device *dev) (ret = cpuidle_curr_governor->enable(drv, dev))) goto fail_sysfs; - for (i = 0; i < dev->state_count; i++) { - dev->states_usage[i].usage = 0; - dev->states_usage[i].time = 0; - } - dev->last_residency = 0; - smp_wmb(); dev->enabled = 1; @@ -364,6 +358,14 @@ static void __cpuidle_unregister_device(struct cpuidle_device *dev) module_put(drv->owner); } +static int __cpuidle_device_init(struct cpuidle_device *dev) +{ + memset(dev->states_usage, 0, sizeof(dev->states_usage)); + dev->last_residency = 0; + + return 0; +} + /** * __cpuidle_register_device - internal register function called before register * and enable routines @@ -405,6 +407,10 @@ int cpuidle_register_device(struct cpuidle_device *dev) mutex_lock(&cpuidle_lock); + ret = __cpuidle_device_init(dev); + if (ret) + goto out_unlock; + ret = __cpuidle_register_device(dev); if (ret) goto out_unlock; From c878a52d3c7cabab5b24460825c24eafd8be7058 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Wed, 12 Jun 2013 15:08:55 +0200 Subject: [PATCH 0108/3400] cpuidle: Check if device is already registered Make __cpuidle_register_device() check whether or not the device has been registered already and return -EBUSY immediately if that's the case. [rjw: Changelog] Signed-off-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki --- drivers/cpuidle/cpuidle.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 5b63185da59b..d75040ddd2b3 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -400,13 +400,16 @@ static int __cpuidle_register_device(struct cpuidle_device *dev) */ int cpuidle_register_device(struct cpuidle_device *dev) { - int ret; + int ret = -EBUSY; if (!dev) return -EINVAL; mutex_lock(&cpuidle_lock); + if (dev->registered) + goto out_unlock; + ret = __cpuidle_device_init(dev); if (ret) goto out_unlock; From dc9ceed6a12aff627c81e01ada191e8a23fcbe3e Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 4 Jul 2013 17:27:14 +0100 Subject: [PATCH 0109/3400] regulator: core: Make set_voltage_tol() try for mid-range first The expected semantic for something expressed as a tolerance is that it should deliver the specified value with some deviation allowed but this is not what set_voltage_tol() currently does. Instead it just passes the maximum possible range to set_voltage() which will typically result in a voltage aimed at lower than the target voltage. Instead first try to set a voltage between the target voltage and the upper limit, then fall back on the full range. This will be much more robust against physical variation in systems and makes the API behave more like users would expect. Signed-off-by: Mark Brown --- include/linux/regulator/consumer.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index 3a76389c6aaa..3610df8dd229 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h @@ -369,8 +369,11 @@ static inline int regulator_count_voltages(struct regulator *regulator) static inline int regulator_set_voltage_tol(struct regulator *regulator, int new_uV, int tol_uV) { - return regulator_set_voltage(regulator, - new_uV - tol_uV, new_uV + tol_uV); + if (regulator_set_voltage(regulator, new_uV, new_uV + tol_uV) == 0) + return 0; + else + return regulator_set_voltage(regulator, + new_uV - tol_uV, new_uV + tol_uV); } static inline int regulator_is_supported_voltage_tol(struct regulator *regulator, From 891636ea27ef42d92a420185d2ccbe190ba00a23 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 8 Jul 2013 09:14:45 +0100 Subject: [PATCH 0110/3400] regulator: core: Drop references on supply regulator when unregistering Signed-off-by: Mark Brown --- drivers/regulator/core.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 288c75abc190..1510333bcf0d 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -3740,8 +3740,11 @@ void regulator_unregister(struct regulator_dev *rdev) if (rdev == NULL) return; - if (rdev->supply) + if (rdev->supply) { + while (rdev->use_count--) + regulator_disable(rdev->supply); regulator_put(rdev->supply); + } mutex_lock(®ulator_list_mutex); debugfs_remove_recursive(rdev->debugfs); flush_work(&rdev->disable_work.work); From 94d33c02c7186b69849c292e1216a08ad1c0d99d Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 2 Jul 2013 22:52:41 +0100 Subject: [PATCH 0111/3400] regulator: core: Add helpers for multiple linear ranges Many regulators have several linear ranges of selector with different step sizes, for example offering better resolution at lower voltages. Provide regulator_{map,list}_voltage_linear_range() allowing these regulators to use generic code. To do so a table of regulator_linear_range structs needs to be pointed to from the descriptor. This was inspired by similar code included in a driver submission from Chao Xie and Yi Zhang at Marvell. Signed-off-by: Mark Brown --- drivers/regulator/core.c | 87 ++++++++++++++++++++++++++++++++ include/linux/regulator/driver.h | 25 +++++++++ 2 files changed, 112 insertions(+) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 288c75abc190..e8604be4c66d 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2078,6 +2078,43 @@ int regulator_list_voltage_linear(struct regulator_dev *rdev, } EXPORT_SYMBOL_GPL(regulator_list_voltage_linear); +/** + * regulator_list_voltage_linear_range - List voltages for linear ranges + * + * @rdev: Regulator device + * @selector: Selector to convert into a voltage + * + * Regulators with a series of simple linear mappings between voltages + * and selectors can set linear_ranges in the regulator descriptor and + * then use this function as their list_voltage() operation, + */ +int regulator_list_voltage_linear_range(struct regulator_dev *rdev, + unsigned int selector) +{ + const struct regulator_linear_range *range; + int i; + + if (!rdev->desc->n_linear_ranges) { + BUG_ON(!rdev->desc->n_linear_ranges); + return -EINVAL; + } + + for (i = 0; i < rdev->desc->n_linear_ranges; i++) { + range = &rdev->desc->linear_ranges[i]; + + if (!(selector >= range->min_sel && + selector <= range->max_sel)) + continue; + + selector -= range->min_sel; + + return range->min_uV + (range->uV_step * selector); + } + + return -EINVAL; +} +EXPORT_SYMBOL_GPL(regulator_list_voltage_linear_range); + /** * regulator_list_voltage_table - List voltages with table based mapping * @@ -2368,6 +2405,56 @@ int regulator_map_voltage_linear(struct regulator_dev *rdev, } EXPORT_SYMBOL_GPL(regulator_map_voltage_linear); +/** + * regulator_map_voltage_linear - map_voltage() for multiple linear ranges + * + * @rdev: Regulator to operate on + * @min_uV: Lower bound for voltage + * @max_uV: Upper bound for voltage + * + * Drivers providing linear_ranges in their descriptor can use this as + * their map_voltage() callback. + */ +int regulator_map_voltage_linear_range(struct regulator_dev *rdev, + int min_uV, int max_uV) +{ + const struct regulator_linear_range *range; + int ret = -EINVAL; + int voltage, i; + + if (!rdev->desc->n_linear_ranges) { + BUG_ON(!rdev->desc->n_linear_ranges); + return -EINVAL; + } + + for (i = 0; i < rdev->desc->n_linear_ranges; i++) { + range = &rdev->desc->linear_ranges[i]; + + if (!(min_uV <= range->max_uV && max_uV >= range->min_uV)) + continue; + + if (min_uV <= range->min_uV) + min_uV = range->min_uV; + + ret = DIV_ROUND_UP(min_uV - range->min_uV, range->uV_step); + if (ret < 0) + return ret; + + break; + } + + if (i == rdev->desc->n_linear_ranges) + return -EINVAL; + + /* Map back into a voltage to verify we're still in bounds */ + voltage = rdev->desc->ops->list_voltage(rdev, ret); + if (voltage < min_uV || voltage > max_uV) + return -EINVAL; + + return ret; +} +EXPORT_SYMBOL_GPL(regulator_map_voltage_linear_range); + static int _regulator_do_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) { diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index 6700cc94bdd1..67e13aa5a478 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -39,6 +39,24 @@ enum regulator_status { REGULATOR_STATUS_UNDEFINED, }; +/** + * Specify a range of voltages for regulator_map_linar_range() and + * regulator_list_linear_range(). + * + * @min_uV: Lowest voltage in range + * @max_uV: Highest voltage in range + * @min_sel: Lowest selector for range + * @max_sel: Highest selector for range + * @uV_step: Step size + */ +struct regulator_linear_range { + unsigned int min_uV; + unsigned int max_uV; + unsigned int min_sel; + unsigned int max_sel; + unsigned int uV_step; +}; + /** * struct regulator_ops - regulator operations. * @@ -223,6 +241,9 @@ struct regulator_desc { unsigned int linear_min_sel; unsigned int ramp_delay; + const struct regulator_linear_range *linear_ranges; + int n_linear_ranges; + const unsigned int *volt_table; unsigned int vsel_reg; @@ -326,10 +347,14 @@ int regulator_mode_to_status(unsigned int); int regulator_list_voltage_linear(struct regulator_dev *rdev, unsigned int selector); +int regulator_list_voltage_linear_range(struct regulator_dev *rdev, + unsigned int selector); int regulator_list_voltage_table(struct regulator_dev *rdev, unsigned int selector); int regulator_map_voltage_linear(struct regulator_dev *rdev, int min_uV, int max_uV); +int regulator_map_voltage_linear_range(struct regulator_dev *rdev, + int min_uV, int max_uV); int regulator_map_voltage_iterate(struct regulator_dev *rdev, int min_uV, int max_uV); int regulator_map_voltage_ascend(struct regulator_dev *rdev, From 6692e432a9d59b55edbfdb4ed388e03c7f17e43c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 2 Jul 2013 23:26:36 +0100 Subject: [PATCH 0112/3400] regulator: wm8400: Use linear ranges Signed-off-by: Mark Brown --- drivers/regulator/wm8400-regulator.c | 50 +++++++++------------------- 1 file changed, 16 insertions(+), 34 deletions(-) diff --git a/drivers/regulator/wm8400-regulator.c b/drivers/regulator/wm8400-regulator.c index a09f03ee5506..2ac7e1aceb05 100644 --- a/drivers/regulator/wm8400-regulator.c +++ b/drivers/regulator/wm8400-regulator.c @@ -19,47 +19,21 @@ #include #include -static int wm8400_ldo_list_voltage(struct regulator_dev *dev, - unsigned selector) -{ - if (selector > WM8400_LDO1_VSEL_MASK) - return -EINVAL; - - if (selector < 15) - return 900000 + (selector * 50000); - else - return 1700000 + ((selector - 15) * 100000); -} - -static int wm8400_ldo_map_voltage(struct regulator_dev *dev, - int min_uV, int max_uV) -{ - u16 val; - int volt; - - if (min_uV < 900000 || min_uV > 3300000) - return -EINVAL; - - if (min_uV < 1700000) /* Steps of 50mV from 900mV; */ - val = DIV_ROUND_UP(min_uV - 900000, 50000); - else /* Steps of 100mV from 1700mV */ - val = DIV_ROUND_UP(min_uV - 1700000, 100000) + 15; - - volt = wm8400_ldo_list_voltage(dev, val); - if (volt < min_uV || volt > max_uV) - return -EINVAL; - - return val; -} +static const struct regulator_linear_range wm8400_ldo_ranges[] = { + { .min_uV = 900000, .max_uV = 1600000, .min_sel = 0, .max_sel = 14, + .uV_step = 50000 }, + { .min_uV = 1700000, .max_uV = 3300000, .min_sel = 15, .max_sel = 31, + .uV_step = 100000 }, +}; static struct regulator_ops wm8400_ldo_ops = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, - .list_voltage = wm8400_ldo_list_voltage, + .list_voltage = regulator_list_voltage_linear_range, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, - .map_voltage = wm8400_ldo_map_voltage, + .map_voltage = regulator_map_voltage_linear_range, }; static unsigned int wm8400_dcdc_get_mode(struct regulator_dev *dev) @@ -155,6 +129,8 @@ static struct regulator_desc regulators[] = { .enable_reg = WM8400_LDO1_CONTROL, .enable_mask = WM8400_LDO1_ENA, .n_voltages = WM8400_LDO1_VSEL_MASK + 1, + .linear_ranges = wm8400_ldo_ranges, + .n_linear_ranges = ARRAY_SIZE(wm8400_ldo_ranges), .vsel_reg = WM8400_LDO1_CONTROL, .vsel_mask = WM8400_LDO1_VSEL_MASK, .type = REGULATOR_VOLTAGE, @@ -167,6 +143,8 @@ static struct regulator_desc regulators[] = { .enable_reg = WM8400_LDO2_CONTROL, .enable_mask = WM8400_LDO2_ENA, .n_voltages = WM8400_LDO2_VSEL_MASK + 1, + .linear_ranges = wm8400_ldo_ranges, + .n_linear_ranges = ARRAY_SIZE(wm8400_ldo_ranges), .type = REGULATOR_VOLTAGE, .vsel_reg = WM8400_LDO2_CONTROL, .vsel_mask = WM8400_LDO2_VSEL_MASK, @@ -179,6 +157,8 @@ static struct regulator_desc regulators[] = { .enable_reg = WM8400_LDO3_CONTROL, .enable_mask = WM8400_LDO3_ENA, .n_voltages = WM8400_LDO3_VSEL_MASK + 1, + .linear_ranges = wm8400_ldo_ranges, + .n_linear_ranges = ARRAY_SIZE(wm8400_ldo_ranges), .vsel_reg = WM8400_LDO3_CONTROL, .vsel_mask = WM8400_LDO3_VSEL_MASK, .type = REGULATOR_VOLTAGE, @@ -191,6 +171,8 @@ static struct regulator_desc regulators[] = { .enable_reg = WM8400_LDO4_CONTROL, .enable_mask = WM8400_LDO4_ENA, .n_voltages = WM8400_LDO4_VSEL_MASK + 1, + .linear_ranges = wm8400_ldo_ranges, + .n_linear_ranges = ARRAY_SIZE(wm8400_ldo_ranges), .vsel_reg = WM8400_LDO4_CONTROL, .vsel_mask = WM8400_LDO4_VSEL_MASK, .type = REGULATOR_VOLTAGE, From 5ff26a14c333113967f3abe5fcb81c8e49d282c0 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 2 Jul 2013 23:35:22 +0100 Subject: [PATCH 0113/3400] regulator: wm831x-ldo: Convert to use linear ranges Signed-off-by: Mark Brown --- drivers/regulator/wm831x-ldo.c | 104 ++++++++------------------------- 1 file changed, 24 insertions(+), 80 deletions(-) diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c index 9ff883f80878..76792c7d86f3 100644 --- a/drivers/regulator/wm831x-ldo.c +++ b/drivers/regulator/wm831x-ldo.c @@ -62,41 +62,12 @@ static irqreturn_t wm831x_ldo_uv_irq(int irq, void *data) * General purpose LDOs */ -#define WM831X_GP_LDO_SELECTOR_LOW 0xe -#define WM831X_GP_LDO_MAX_SELECTOR 0x1f - -static int wm831x_gp_ldo_list_voltage(struct regulator_dev *rdev, - unsigned int selector) -{ - /* 0.9-1.6V in 50mV steps */ - if (selector <= WM831X_GP_LDO_SELECTOR_LOW) - return 900000 + (selector * 50000); - /* 1.7-3.3V in 100mV steps */ - if (selector <= WM831X_GP_LDO_MAX_SELECTOR) - return 1600000 + ((selector - WM831X_GP_LDO_SELECTOR_LOW) - * 100000); - return -EINVAL; -} - -static int wm831x_gp_ldo_map_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV) -{ - int volt, vsel; - - if (min_uV < 900000) - vsel = 0; - else if (min_uV < 1700000) - vsel = ((min_uV - 900000) / 50000); - else - vsel = ((min_uV - 1700000) / 100000) - + WM831X_GP_LDO_SELECTOR_LOW + 1; - - volt = wm831x_gp_ldo_list_voltage(rdev, vsel); - if (volt < min_uV || volt > max_uV) - return -EINVAL; - - return vsel; -} +static const struct regulator_linear_range wm831x_gp_ldo_ranges[] = { + { .min_uV = 900000, .max_uV = 1650000, .min_sel = 0, .max_sel = 14, + .uV_step = 50000 }, + { .min_uV = 1700000, .max_uV = 3300000, .min_sel = 15, .max_sel = 31, + .uV_step = 100000 }, +}; static int wm831x_gp_ldo_set_suspend_voltage(struct regulator_dev *rdev, int uV) @@ -105,7 +76,7 @@ static int wm831x_gp_ldo_set_suspend_voltage(struct regulator_dev *rdev, struct wm831x *wm831x = ldo->wm831x; int sel, reg = ldo->base + WM831X_LDO_SLEEP_CONTROL; - sel = wm831x_gp_ldo_map_voltage(rdev, uV, uV); + sel = regulator_map_voltage_linear_range(rdev, uV, uV); if (sel < 0) return sel; @@ -230,8 +201,8 @@ static unsigned int wm831x_gp_ldo_get_optimum_mode(struct regulator_dev *rdev, static struct regulator_ops wm831x_gp_ldo_ops = { - .list_voltage = wm831x_gp_ldo_list_voltage, - .map_voltage = wm831x_gp_ldo_map_voltage, + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, .set_suspend_voltage = wm831x_gp_ldo_set_suspend_voltage, @@ -290,7 +261,7 @@ static int wm831x_gp_ldo_probe(struct platform_device *pdev) ldo->desc.id = id; ldo->desc.type = REGULATOR_VOLTAGE; - ldo->desc.n_voltages = WM831X_GP_LDO_MAX_SELECTOR + 1; + ldo->desc.n_voltages = 32; ldo->desc.ops = &wm831x_gp_ldo_ops; ldo->desc.owner = THIS_MODULE; ldo->desc.vsel_reg = ldo->base + WM831X_LDO_ON_CONTROL; @@ -299,6 +270,8 @@ static int wm831x_gp_ldo_probe(struct platform_device *pdev) ldo->desc.enable_mask = 1 << id; ldo->desc.bypass_reg = ldo->base; ldo->desc.bypass_mask = WM831X_LDO1_SWI; + ldo->desc.linear_ranges = wm831x_gp_ldo_ranges; + ldo->desc.n_linear_ranges = ARRAY_SIZE(wm831x_gp_ldo_ranges); config.dev = pdev->dev.parent; if (pdata) @@ -358,43 +331,12 @@ static struct platform_driver wm831x_gp_ldo_driver = { * Analogue LDOs */ - -#define WM831X_ALDO_SELECTOR_LOW 0xc -#define WM831X_ALDO_MAX_SELECTOR 0x1f - -static int wm831x_aldo_list_voltage(struct regulator_dev *rdev, - unsigned int selector) -{ - /* 1-1.6V in 50mV steps */ - if (selector <= WM831X_ALDO_SELECTOR_LOW) - return 1000000 + (selector * 50000); - /* 1.7-3.5V in 100mV steps */ - if (selector <= WM831X_ALDO_MAX_SELECTOR) - return 1600000 + ((selector - WM831X_ALDO_SELECTOR_LOW) - * 100000); - return -EINVAL; -} - -static int wm831x_aldo_map_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV) -{ - int volt, vsel; - - if (min_uV < 1000000) - vsel = 0; - else if (min_uV < 1700000) - vsel = ((min_uV - 1000000) / 50000); - else - vsel = ((min_uV - 1700000) / 100000) - + WM831X_ALDO_SELECTOR_LOW + 1; - - volt = wm831x_aldo_list_voltage(rdev, vsel); - if (volt < min_uV || volt > max_uV) - return -EINVAL; - - return vsel; - -} +static const struct regulator_linear_range wm831x_aldo_ranges[] = { + { .min_uV = 1000000, .max_uV = 1650000, .min_sel = 0, .max_sel = 12, + .uV_step = 50000 }, + { .min_uV = 1700000, .max_uV = 3500000, .min_sel = 13, .max_sel = 31, + .uV_step = 100000 }, +}; static int wm831x_aldo_set_suspend_voltage(struct regulator_dev *rdev, int uV) @@ -403,7 +345,7 @@ static int wm831x_aldo_set_suspend_voltage(struct regulator_dev *rdev, struct wm831x *wm831x = ldo->wm831x; int sel, reg = ldo->base + WM831X_LDO_SLEEP_CONTROL; - sel = wm831x_aldo_map_voltage(rdev, uV, uV); + sel = regulator_map_voltage_linear_range(rdev, uV, uV); if (sel < 0) return sel; @@ -486,8 +428,8 @@ static int wm831x_aldo_get_status(struct regulator_dev *rdev) } static struct regulator_ops wm831x_aldo_ops = { - .list_voltage = wm831x_aldo_list_voltage, - .map_voltage = wm831x_aldo_map_voltage, + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, .set_suspend_voltage = wm831x_aldo_set_suspend_voltage, @@ -545,7 +487,9 @@ static int wm831x_aldo_probe(struct platform_device *pdev) ldo->desc.id = id; ldo->desc.type = REGULATOR_VOLTAGE; - ldo->desc.n_voltages = WM831X_ALDO_MAX_SELECTOR + 1; + ldo->desc.n_voltages = 32; + ldo->desc.linear_ranges = wm831x_aldo_ranges; + ldo->desc.n_linear_ranges = ARRAY_SIZE(wm831x_aldo_ranges); ldo->desc.ops = &wm831x_aldo_ops; ldo->desc.owner = THIS_MODULE; ldo->desc.vsel_reg = ldo->base + WM831X_LDO_ON_CONTROL; From c36a1cdf96dd3a4e6b612d6847bff6c7086e358b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 2 Jul 2013 23:35:42 +0100 Subject: [PATCH 0114/3400] regulator: wm8350: Convert to use linear ranges Signed-off-by: Mark Brown --- drivers/regulator/wm8350-regulator.c | 55 +++++++++------------------- 1 file changed, 17 insertions(+), 38 deletions(-) diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c index 7f0fa22ef2aa..5453dd0105ed 100644 --- a/drivers/regulator/wm8350-regulator.c +++ b/drivers/regulator/wm8350-regulator.c @@ -542,41 +542,12 @@ static int wm8350_dcdc_set_suspend_mode(struct regulator_dev *rdev, return 0; } -static int wm8350_ldo_list_voltage(struct regulator_dev *rdev, - unsigned selector) -{ - if (selector > WM8350_LDO1_VSEL_MASK) - return -EINVAL; - - if (selector < 16) - return (selector * 50000) + 900000; - else - return ((selector - 16) * 100000) + 1800000; -} - -static int wm8350_ldo_map_voltage(struct regulator_dev *rdev, int min_uV, - int max_uV) -{ - int volt, sel; - int min_mV = min_uV / 1000; - int max_mV = max_uV / 1000; - - if (min_mV < 900 || min_mV > 3300) - return -EINVAL; - if (max_mV < 900 || max_mV > 3300) - return -EINVAL; - - if (min_mV < 1800) /* step size is 50mV < 1800mV */ - sel = DIV_ROUND_UP(min_uV - 900, 50); - else /* step size is 100mV > 1800mV */ - sel = DIV_ROUND_UP(min_uV - 1800, 100) + 16; - - volt = wm8350_ldo_list_voltage(rdev, sel); - if (volt < min_uV || volt > max_uV) - return -EINVAL; - - return sel; -} +static const struct regulator_linear_range wm8350_ldo_ranges[] = { + { .min_uV = 900000, .max_uV = 1750000, .min_sel = 0, .max_sel = 15, + .uV_step = 50000 }, + { .min_uV = 1800000, .max_uV = 3300000, .min_sel = 16, .max_sel = 31, + .uV_step = 100000 }, +}; static int wm8350_ldo_set_suspend_voltage(struct regulator_dev *rdev, int uV) { @@ -603,7 +574,7 @@ static int wm8350_ldo_set_suspend_voltage(struct regulator_dev *rdev, int uV) return -EINVAL; } - sel = wm8350_ldo_map_voltage(rdev, uV, uV); + sel = regulator_map_voltage_linear_range(rdev, uV, uV); if (sel < 0) return -EINVAL; @@ -998,10 +969,10 @@ static struct regulator_ops wm8350_dcdc2_5_ops = { }; static struct regulator_ops wm8350_ldo_ops = { - .map_voltage = wm8350_ldo_map_voltage, + .map_voltage = regulator_map_voltage_linear_range, .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, - .list_voltage = wm8350_ldo_list_voltage, + .list_voltage = regulator_list_voltage_linear_range, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, @@ -1108,6 +1079,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = { .irq = WM8350_IRQ_UV_LDO1, .type = REGULATOR_VOLTAGE, .n_voltages = WM8350_LDO1_VSEL_MASK + 1, + .linear_ranges = wm8350_ldo_ranges, + .n_linear_ranges = ARRAY_SIZE(wm8350_ldo_ranges), .vsel_reg = WM8350_LDO1_CONTROL, .vsel_mask = WM8350_LDO1_VSEL_MASK, .enable_reg = WM8350_DCDC_LDO_REQUESTED, @@ -1121,6 +1094,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = { .irq = WM8350_IRQ_UV_LDO2, .type = REGULATOR_VOLTAGE, .n_voltages = WM8350_LDO2_VSEL_MASK + 1, + .linear_ranges = wm8350_ldo_ranges, + .n_linear_ranges = ARRAY_SIZE(wm8350_ldo_ranges), .vsel_reg = WM8350_LDO2_CONTROL, .vsel_mask = WM8350_LDO2_VSEL_MASK, .enable_reg = WM8350_DCDC_LDO_REQUESTED, @@ -1134,6 +1109,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = { .irq = WM8350_IRQ_UV_LDO3, .type = REGULATOR_VOLTAGE, .n_voltages = WM8350_LDO3_VSEL_MASK + 1, + .linear_ranges = wm8350_ldo_ranges, + .n_linear_ranges = ARRAY_SIZE(wm8350_ldo_ranges), .vsel_reg = WM8350_LDO3_CONTROL, .vsel_mask = WM8350_LDO3_VSEL_MASK, .enable_reg = WM8350_DCDC_LDO_REQUESTED, @@ -1147,6 +1124,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = { .irq = WM8350_IRQ_UV_LDO4, .type = REGULATOR_VOLTAGE, .n_voltages = WM8350_LDO4_VSEL_MASK + 1, + .linear_ranges = wm8350_ldo_ranges, + .n_linear_ranges = ARRAY_SIZE(wm8350_ldo_ranges), .vsel_reg = WM8350_LDO4_CONTROL, .vsel_mask = WM8350_LDO4_VSEL_MASK, .enable_reg = WM8350_DCDC_LDO_REQUESTED, From 37a6f43dd1924013cbf2eb91b74b3cc9818b3af8 Mon Sep 17 00:00:00 2001 From: Milo Kim Date: Wed, 3 Jul 2013 10:30:57 +0900 Subject: [PATCH 0115/3400] regulator: lp872x: fix a build waring and coding styles Fix a warning below. drivers/regulator/lp872x.c:910:33: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] And checkpatch warnings are fixed. WARNING: space prohibited before semicolon Signed-off-by: Milo Kim Signed-off-by: Mark Brown --- drivers/regulator/lp872x.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c index b16336bcd4d4..1018fb2020a9 100644 --- a/drivers/regulator/lp872x.c +++ b/drivers/regulator/lp872x.c @@ -373,7 +373,7 @@ static int lp8725_buck_set_current_limit(struct regulator_dev *rdev, return -EINVAL; } - for (i = ARRAY_SIZE(lp8725_buck_uA) - 1 ; i >= 0; i--) { + for (i = ARRAY_SIZE(lp8725_buck_uA) - 1; i >= 0; i--) { if (lp8725_buck_uA[i] >= min_uA && lp8725_buck_uA[i] <= max_uA) return lp872x_update_bits(lp, addr, @@ -787,7 +787,7 @@ static int lp872x_regulator_register(struct lp872x *lp) struct regulator_dev *rdev; int i, ret; - for (i = 0 ; i < lp->num_regulators ; i++) { + for (i = 0; i < lp->num_regulators; i++) { desc = (lp->chipid == LP8720) ? &lp8720_regulator_desc[i] : &lp8725_regulator_desc[i]; @@ -820,7 +820,7 @@ static void lp872x_regulator_unregister(struct lp872x *lp) struct regulator_dev *rdev; int i; - for (i = 0 ; i < lp->num_regulators ; i++) { + for (i = 0; i < lp->num_regulators; i++) { rdev = *(lp->regulators + i); regulator_unregister(rdev); } @@ -907,7 +907,8 @@ static struct lp872x_platform_data goto out; for (i = 0; i < num_matches; i++) { - pdata->regulator_data[i].id = (int)match[i].driver_data; + pdata->regulator_data[i].id = + (enum lp872x_regulator_id)match[i].driver_data; pdata->regulator_data[i].init_data = match[i].init_data; /* Operation mode configuration for buck/buck1/buck2 */ From 1653ccf4c52df6a4abe8ec2f33f2cb2896d129ea Mon Sep 17 00:00:00 2001 From: Yadwinder Singh Brar Date: Sat, 29 Jun 2013 18:21:15 +0530 Subject: [PATCH 0116/3400] regulator: core: Add support for disabling ramp delay Some hardwares support disabling ramp delay, so adding ramp_disable flag to constraints. It will be used to figure out whether ramp_delay in constraints is explicitly set to zero or its unintialized (zero by default). And we don't need to call set_voltage_time_sel() for regulators for whom ramp delay is disabled in constraints. Signed-off-by: Yadwinder Singh Brar Signed-off-by: Mark Brown --- .../devicetree/bindings/regulator/regulator.txt | 2 ++ drivers/regulator/core.c | 6 ++++-- drivers/regulator/of_regulator.c | 12 +++++++++--- include/linux/regulator/machine.h | 1 + 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/regulator/regulator.txt b/Documentation/devicetree/bindings/regulator/regulator.txt index 48a3b8e5d6bd..2bd8f0978765 100644 --- a/Documentation/devicetree/bindings/regulator/regulator.txt +++ b/Documentation/devicetree/bindings/regulator/regulator.txt @@ -12,6 +12,8 @@ Optional properties: - regulator-allow-bypass: allow the regulator to go into bypass mode - -supply: phandle to the parent supply/regulator node - regulator-ramp-delay: ramp delay for regulator(in uV/uS) + For hardwares which support disabling ramp rate, it should be explicitly + intialised to zero (regulator-ramp-delay = <0>) for disabling ramp delay. Deprecated properties: - regulator-compatible: If a regulator chip contains multiple diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 288c75abc190..6e6371c2346c 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -984,7 +984,8 @@ static int set_machine_constraints(struct regulator_dev *rdev, } } - if (rdev->constraints->ramp_delay && ops->set_ramp_delay) { + if ((rdev->constraints->ramp_delay || rdev->constraints->ramp_disable) + && ops->set_ramp_delay) { ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay); if (ret < 0) { rdev_err(rdev, "failed to set ramp_delay\n"); @@ -2438,7 +2439,8 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, } /* Call set_voltage_time_sel if successfully obtained old_selector */ - if (ret == 0 && _regulator_is_enabled(rdev) && old_selector >= 0 && + if (ret == 0 && !rdev->constraints->ramp_disable && + _regulator_is_enabled(rdev) && old_selector >= 0 && old_selector != selector && rdev->desc->ops->set_voltage_time_sel) { delay = rdev->desc->ops->set_voltage_time_sel(rdev, diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index f3c8f8f9dc39..7827384680d6 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -21,6 +21,7 @@ static void of_get_regulation_constraints(struct device_node *np, { const __be32 *min_uV, *max_uV, *uV_offset; const __be32 *min_uA, *max_uA, *ramp_delay; + struct property *prop; struct regulation_constraints *constraints = &(*init_data)->constraints; constraints->name = of_get_property(np, "regulator-name", NULL); @@ -64,9 +65,14 @@ static void of_get_regulation_constraints(struct device_node *np, if (of_property_read_bool(np, "regulator-allow-bypass")) constraints->valid_ops_mask |= REGULATOR_CHANGE_BYPASS; - ramp_delay = of_get_property(np, "regulator-ramp-delay", NULL); - if (ramp_delay) - constraints->ramp_delay = be32_to_cpu(*ramp_delay); + prop = of_find_property(np, "regulator-ramp-delay", NULL); + if (prop && prop->value) { + ramp_delay = prop->value; + if (*ramp_delay) + constraints->ramp_delay = be32_to_cpu(*ramp_delay); + else + constraints->ramp_disable = true; + } } /** diff --git a/include/linux/regulator/machine.h b/include/linux/regulator/machine.h index 36adbc82de6a..999b20ce06cf 100644 --- a/include/linux/regulator/machine.h +++ b/include/linux/regulator/machine.h @@ -134,6 +134,7 @@ struct regulation_constraints { unsigned always_on:1; /* regulator never off when system is on */ unsigned boot_on:1; /* bootloader/firmware enabled regulator */ unsigned apply_uV:1; /* apply uV constraint if min == max */ + unsigned ramp_disable:1; /* disable ramp delay */ }; /** From 5b175952011adae30b531ab89cc24acb173b2ce4 Mon Sep 17 00:00:00 2001 From: Yadwinder Singh Brar Date: Sat, 29 Jun 2013 18:21:19 +0530 Subject: [PATCH 0117/3400] regulator: core: Remove redundant checks In function _regulator_do_set_voltage(), old_selector gets intialised only if (_regulator_is_enabled(rdev) && rdev->desc->ops->set_voltage_time_sel && rdev->desc->ops->get_voltage_sel)) is true. Before calling set_voltage_time_sel() we checks if (old_selector >= 0) and it will true if it got intialised properly. so we don't need to check again _regulator_is_enabled(rdev) && rdev->desc->ops->set_voltage_time_sel before calling set_voltage_time_sel(). Signed-off-by: Yadwinder Singh Brar Signed-off-by: Mark Brown --- drivers/regulator/core.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 6e6371c2346c..15368f35bbdf 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2439,9 +2439,8 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, } /* Call set_voltage_time_sel if successfully obtained old_selector */ - if (ret == 0 && !rdev->constraints->ramp_disable && - _regulator_is_enabled(rdev) && old_selector >= 0 && - old_selector != selector && rdev->desc->ops->set_voltage_time_sel) { + if (ret == 0 && !rdev->constraints->ramp_disable && old_selector >= 0 + && old_selector != selector) { delay = rdev->desc->ops->set_voltage_time_sel(rdev, old_selector, selector); From 1e1598ed04d831f5bb42a197b4045e6780365217 Mon Sep 17 00:00:00 2001 From: Yadwinder Singh Brar Date: Mon, 24 Jun 2013 16:50:56 +0530 Subject: [PATCH 0118/3400] regulator: s2mps11: Implement set_voltage_time_sel() ops for bucks Currently driver uses local struct s2mps11_info to store ramp rate for bucks whic its getting through platform data, so instead of using regulator constraints it should use s2mps11_info to calculate ramp delay. Signed-off-by: Yadwinder Singh Brar Signed-off-by: Mark Brown --- drivers/regulator/s2mps11.c | 53 ++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index 2f62564ca936..a671eb63a4e5 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -53,6 +53,57 @@ static int get_ramp_delay(int ramp_delay) return cnt; } +static int s2mps11_regulator_set_voltage_time_sel(struct regulator_dev *rdev, + unsigned int old_selector, + unsigned int new_selector) +{ + struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev); + unsigned int ramp_delay = 0; + int old_volt, new_volt; + + switch (rdev->desc->id) { + case S2MPS11_BUCK2: + if (!s2mps11->buck2_ramp) + return 0; + ramp_delay = s2mps11->ramp_delay2; + break; + case S2MPS11_BUCK3: + if (!s2mps11->buck3_ramp) + return 0; + ramp_delay = s2mps11->ramp_delay34; + break; + case S2MPS11_BUCK4: + if (!s2mps11->buck4_ramp) + return 0; + ramp_delay = s2mps11->ramp_delay34; + break; + case S2MPS11_BUCK5: + ramp_delay = s2mps11->ramp_delay5; + break; + case S2MPS11_BUCK6: + if (!s2mps11->buck6_ramp) + return 0; + case S2MPS11_BUCK1: + ramp_delay = s2mps11->ramp_delay16; + break; + case S2MPS11_BUCK7: + case S2MPS11_BUCK8: + case S2MPS11_BUCK10: + ramp_delay = s2mps11->ramp_delay7810; + break; + case S2MPS11_BUCK9: + ramp_delay = s2mps11->ramp_delay9; + } + + if (ramp_delay == 0) + ramp_delay = rdev->desc->ramp_delay; + + old_volt = rdev->desc->min_uV + (rdev->desc->uV_step * old_selector); + new_volt = rdev->desc->min_uV + (rdev->desc->uV_step * new_selector); + + return DIV_ROUND_UP(abs(new_volt - old_volt), ramp_delay); +} + static struct regulator_ops s2mps11_ldo_ops = { .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, @@ -72,7 +123,7 @@ static struct regulator_ops s2mps11_buck_ops = { .disable = regulator_disable_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, - .set_voltage_time_sel = regulator_set_voltage_time_sel, + .set_voltage_time_sel = s2mps11_regulator_set_voltage_time_sel, }; #define regulator_desc_ldo1(num) { \ From 874b31585650afa6745de5133849365e7e6af418 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 5 Jul 2013 11:44:49 +0100 Subject: [PATCH 0119/3400] spi/bitbang: Unexport spi_bitbang_transfer() Currently no drivers use the ability to override spi_bitbang_transfer() and if any started this would make it harder to convert the bitbang code to use transfer_one_message() so remove the export in order to prevent anyone starting. Signed-off-by: Mark Brown --- drivers/spi/spi-bitbang.c | 3 +-- include/linux/spi/spi_bitbang.h | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c index a63d7da3bfe2..495ce0a51d2f 100644 --- a/drivers/spi/spi-bitbang.c +++ b/drivers/spi/spi-bitbang.c @@ -376,7 +376,7 @@ static void bitbang_work(struct work_struct *work) /** * spi_bitbang_transfer - default submit to transfer queue */ -int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m) +static int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m) { struct spi_bitbang *bitbang; unsigned long flags; @@ -398,7 +398,6 @@ int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m) return status; } -EXPORT_SYMBOL_GPL(spi_bitbang_transfer); /*----------------------------------------------------------------------*/ diff --git a/include/linux/spi/spi_bitbang.h b/include/linux/spi/spi_bitbang.h index f987a2bee16a..b5aa215493f6 100644 --- a/include/linux/spi/spi_bitbang.h +++ b/include/linux/spi/spi_bitbang.h @@ -41,7 +41,6 @@ struct spi_bitbang { */ extern int spi_bitbang_setup(struct spi_device *spi); extern void spi_bitbang_cleanup(struct spi_device *spi); -extern int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m); extern int spi_bitbang_setup_transfer(struct spi_device *spi, struct spi_transfer *t); From 91b308586793b48c590c9ac3528bbacb8ef53e15 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 5 Jul 2013 12:06:44 +0100 Subject: [PATCH 0120/3400] spi/bitbang: Factor out message transfer from message pump loop In order to make it easier to convert to transfer_one_message() lift the code that does the actual message transfer out of the work function that implements the message pump. This should have no functional impact, it's just a simple code motion patch. Signed-off-by: Mark Brown --- drivers/spi/spi-bitbang.c | 205 ++++++++++++++++++++------------------ 1 file changed, 107 insertions(+), 98 deletions(-) diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c index 495ce0a51d2f..8b8487c9694e 100644 --- a/drivers/spi/spi-bitbang.c +++ b/drivers/spi/spi-bitbang.c @@ -255,6 +255,112 @@ static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t) * Drivers can provide word-at-a-time i/o primitives, or provide * transfer-at-a-time ones to leverage dma or fifo hardware. */ +static int spi_bitbang_transfer_one(struct spi_device *spi, + struct spi_message *m) +{ + struct spi_bitbang *bitbang; + unsigned nsecs; + struct spi_transfer *t = NULL; + unsigned tmp; + unsigned cs_change; + int status; + int do_setup = -1; + + bitbang = spi_master_get_devdata(spi->master); + + /* FIXME this is made-up ... the correct value is known to + * word-at-a-time bitbang code, and presumably chipselect() + * should enforce these requirements too? + */ + nsecs = 100; + + tmp = 0; + cs_change = 1; + status = 0; + + list_for_each_entry (t, &m->transfers, transfer_list) { + + /* override speed or wordsize? */ + if (t->speed_hz || t->bits_per_word) + do_setup = 1; + + /* init (-1) or override (1) transfer params */ + if (do_setup != 0) { + status = bitbang->setup_transfer(spi, t); + if (status < 0) + break; + if (do_setup == -1) + do_setup = 0; + } + + /* set up default clock polarity, and activate chip; + * this implicitly updates clock and spi modes as + * previously recorded for this device via setup(). + * (and also deselects any other chip that might be + * selected ...) + */ + if (cs_change) { + bitbang->chipselect(spi, BITBANG_CS_ACTIVE); + ndelay(nsecs); + } + cs_change = t->cs_change; + if (!t->tx_buf && !t->rx_buf && t->len) { + status = -EINVAL; + break; + } + + /* transfer data. the lower level code handles any + * new dma mappings it needs. our caller always gave + * us dma-safe buffers. + */ + if (t->len) { + /* REVISIT dma API still needs a designated + * DMA_ADDR_INVALID; ~0 might be better. + */ + if (!m->is_dma_mapped) + t->rx_dma = t->tx_dma = 0; + status = bitbang->txrx_bufs(spi, t); + } + if (status > 0) + m->actual_length += status; + if (status != t->len) { + /* always report some kind of error */ + if (status >= 0) + status = -EREMOTEIO; + break; + } + status = 0; + + /* protocol tweaks before next transfer */ + if (t->delay_usecs) + udelay(t->delay_usecs); + + if (cs_change && !list_is_last(&t->transfer_list, &m->transfers)) { + /* sometimes a short mid-message deselect of the chip + * may be needed to terminate a mode or command + */ + ndelay(nsecs); + bitbang->chipselect(spi, BITBANG_CS_INACTIVE); + ndelay(nsecs); + } + } + + m->status = status; + m->complete(m->context); + + /* normally deactivate chipselect ... unless no error and + * cs_change has hinted that the next message will probably + * be for this chip too. + */ + if (!(status == 0 && cs_change)) { + ndelay(nsecs); + bitbang->chipselect(spi, BITBANG_CS_INACTIVE); + ndelay(nsecs); + } + + return status; +} + static void bitbang_work(struct work_struct *work) { struct spi_bitbang *bitbang = @@ -265,107 +371,10 @@ static void bitbang_work(struct work_struct *work) spin_lock_irqsave(&bitbang->lock, flags); bitbang->busy = 1; list_for_each_entry_safe(m, _m, &bitbang->queue, queue) { - struct spi_device *spi; - unsigned nsecs; - struct spi_transfer *t = NULL; - unsigned tmp; - unsigned cs_change; - int status; - int do_setup = -1; - list_del(&m->queue); spin_unlock_irqrestore(&bitbang->lock, flags); - /* FIXME this is made-up ... the correct value is known to - * word-at-a-time bitbang code, and presumably chipselect() - * should enforce these requirements too? - */ - nsecs = 100; - - spi = m->spi; - tmp = 0; - cs_change = 1; - status = 0; - - list_for_each_entry (t, &m->transfers, transfer_list) { - - /* override speed or wordsize? */ - if (t->speed_hz || t->bits_per_word) - do_setup = 1; - - /* init (-1) or override (1) transfer params */ - if (do_setup != 0) { - status = bitbang->setup_transfer(spi, t); - if (status < 0) - break; - if (do_setup == -1) - do_setup = 0; - } - - /* set up default clock polarity, and activate chip; - * this implicitly updates clock and spi modes as - * previously recorded for this device via setup(). - * (and also deselects any other chip that might be - * selected ...) - */ - if (cs_change) { - bitbang->chipselect(spi, BITBANG_CS_ACTIVE); - ndelay(nsecs); - } - cs_change = t->cs_change; - if (!t->tx_buf && !t->rx_buf && t->len) { - status = -EINVAL; - break; - } - - /* transfer data. the lower level code handles any - * new dma mappings it needs. our caller always gave - * us dma-safe buffers. - */ - if (t->len) { - /* REVISIT dma API still needs a designated - * DMA_ADDR_INVALID; ~0 might be better. - */ - if (!m->is_dma_mapped) - t->rx_dma = t->tx_dma = 0; - status = bitbang->txrx_bufs(spi, t); - } - if (status > 0) - m->actual_length += status; - if (status != t->len) { - /* always report some kind of error */ - if (status >= 0) - status = -EREMOTEIO; - break; - } - status = 0; - - /* protocol tweaks before next transfer */ - if (t->delay_usecs) - udelay(t->delay_usecs); - - if (cs_change && !list_is_last(&t->transfer_list, &m->transfers)) { - /* sometimes a short mid-message deselect of the chip - * may be needed to terminate a mode or command - */ - ndelay(nsecs); - bitbang->chipselect(spi, BITBANG_CS_INACTIVE); - ndelay(nsecs); - } - } - - m->status = status; - m->complete(m->context); - - /* normally deactivate chipselect ... unless no error and - * cs_change has hinted that the next message will probably - * be for this chip too. - */ - if (!(status == 0 && cs_change)) { - ndelay(nsecs); - bitbang->chipselect(spi, BITBANG_CS_INACTIVE); - ndelay(nsecs); - } + spi_bitbang_transfer_one(m->spi, m); spin_lock_irqsave(&bitbang->lock, flags); } From fa4bd4f1ade784d9cbed67ab228d0ad5edb3830d Mon Sep 17 00:00:00 2001 From: Scott Jiang Date: Wed, 26 Jun 2013 18:07:40 -0400 Subject: [PATCH 0121/3400] spi: add spi controller v3 master driver for Blackfin New spi controller(version 3) is integrated into Blackfin 60x processor. Comparing to bf5xx spi controller, we support 32 bits word size and independent receive and transmit DMA channels now. Also mode 0 and 2 (CPHA = 0) can get fully supported becasue cs line may be controlled by the software. Signed-off-by: Scott Jiang Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 9 +- drivers/spi/Makefile | 1 + drivers/spi/spi-bfin-v3.c | 973 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 982 insertions(+), 1 deletion(-) create mode 100644 drivers/spi/spi-bfin-v3.c diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 89cbbabaff44..e31bf77ab259 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -88,10 +88,17 @@ config SPI_BCM2835 config SPI_BFIN5XX tristate "SPI controller driver for ADI Blackfin5xx" - depends on BLACKFIN + depends on BLACKFIN && !BF60x help This is the SPI controller master driver for Blackfin 5xx processor. +config SPI_BFIN_V3 + tristate "SPI controller v3 for Blackfin" + depends on BF60x + help + This is the SPI controller v3 master driver + found on Blackfin 60x processor. + config SPI_BFIN_SPORT tristate "SPI bus via Blackfin SPORT" depends on BLACKFIN diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 33f9c09561e7..7c4170263cd8 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_SPI_AU1550) += spi-au1550.o obj-$(CONFIG_SPI_BCM2835) += spi-bcm2835.o obj-$(CONFIG_SPI_BCM63XX) += spi-bcm63xx.o obj-$(CONFIG_SPI_BFIN5XX) += spi-bfin5xx.o +obj-$(CONFIG_SPI_BFIN_V3) += spi-bfin-v3.o obj-$(CONFIG_SPI_BFIN_SPORT) += spi-bfin-sport.o obj-$(CONFIG_SPI_BITBANG) += spi-bitbang.o obj-$(CONFIG_SPI_BUTTERFLY) += spi-butterfly.o diff --git a/drivers/spi/spi-bfin-v3.c b/drivers/spi/spi-bfin-v3.c new file mode 100644 index 000000000000..603d7e91085b --- /dev/null +++ b/drivers/spi/spi-bfin-v3.c @@ -0,0 +1,973 @@ +/* + * Analog Devices SPI3 controller driver + * + * Copyright (c) 2013 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 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +enum bfin_spi_state { + START_STATE, + RUNNING_STATE, + DONE_STATE, + ERROR_STATE +}; + +struct bfin_spi_master; + +struct bfin_spi_transfer_ops { + void (*write) (struct bfin_spi_master *); + void (*read) (struct bfin_spi_master *); + void (*duplex) (struct bfin_spi_master *); +}; + +/* runtime info for spi master */ +struct bfin_spi_master { + /* SPI framework hookup */ + struct spi_master *master; + + /* Regs base of SPI controller */ + struct bfin_spi_regs __iomem *regs; + + /* Pin request list */ + u16 *pin_req; + + /* Message Transfer pump */ + struct tasklet_struct pump_transfers; + + /* Current message transfer state info */ + struct spi_message *cur_msg; + struct spi_transfer *cur_transfer; + struct bfin_spi_device *cur_chip; + unsigned transfer_len; + + /* transfer buffer */ + void *tx; + void *tx_end; + void *rx; + void *rx_end; + + /* dma info */ + unsigned int tx_dma; + unsigned int rx_dma; + dma_addr_t tx_dma_addr; + dma_addr_t rx_dma_addr; + unsigned long dummy_buffer; /* used in unidirectional transfer */ + unsigned long tx_dma_size; + unsigned long rx_dma_size; + int tx_num; + int rx_num; + + /* store register value for suspend/resume */ + u32 control; + u32 ssel; + + unsigned long sclk; + enum bfin_spi_state state; + + const struct bfin_spi_transfer_ops *ops; +}; + +struct bfin_spi_device { + u32 control; + u32 clock; + u32 ssel; + + u8 cs; + u16 cs_chg_udelay; /* Some devices require > 255usec delay */ + u32 cs_gpio; + u32 tx_dummy_val; /* tx value for rx only transfer */ + bool enable_dma; + const struct bfin_spi_transfer_ops *ops; +}; + +static void bfin_spi_enable(struct bfin_spi_master *drv_data) +{ + bfin_write_or(&drv_data->regs->control, SPI_CTL_EN); +} + +static void bfin_spi_disable(struct bfin_spi_master *drv_data) +{ + bfin_write_and(&drv_data->regs->control, ~SPI_CTL_EN); +} + +/* Caculate the SPI_CLOCK register value based on input HZ */ +static u32 hz_to_spi_clock(u32 sclk, u32 speed_hz) +{ + u32 spi_clock = sclk / speed_hz; + + if (spi_clock) + spi_clock--; + return spi_clock; +} + +static int bfin_spi_flush(struct bfin_spi_master *drv_data) +{ + unsigned long limit = loops_per_jiffy << 1; + + /* wait for stop and clear stat */ + while (!(bfin_read(&drv_data->regs->status) & SPI_STAT_SPIF) && --limit) + cpu_relax(); + + bfin_write(&drv_data->regs->status, 0xFFFFFFFF); + + return limit; +} + +/* Chip select operation functions for cs_change flag */ +static void bfin_spi_cs_active(struct bfin_spi_master *drv_data, struct bfin_spi_device *chip) +{ + if (likely(chip->cs < MAX_CTRL_CS)) + bfin_write_and(&drv_data->regs->ssel, ~chip->ssel); + else + gpio_set_value(chip->cs_gpio, 0); +} + +static void bfin_spi_cs_deactive(struct bfin_spi_master *drv_data, + struct bfin_spi_device *chip) +{ + if (likely(chip->cs < MAX_CTRL_CS)) + bfin_write_or(&drv_data->regs->ssel, chip->ssel); + else + gpio_set_value(chip->cs_gpio, 1); + + /* Move delay here for consistency */ + if (chip->cs_chg_udelay) + udelay(chip->cs_chg_udelay); +} + +/* enable or disable the pin muxed by GPIO and SPI CS to work as SPI CS */ +static inline void bfin_spi_cs_enable(struct bfin_spi_master *drv_data, + struct bfin_spi_device *chip) +{ + if (chip->cs < MAX_CTRL_CS) + bfin_write_or(&drv_data->regs->ssel, chip->ssel >> 8); +} + +static inline void bfin_spi_cs_disable(struct bfin_spi_master *drv_data, + struct bfin_spi_device *chip) +{ + if (chip->cs < MAX_CTRL_CS) + bfin_write_and(&drv_data->regs->ssel, ~(chip->ssel >> 8)); +} + +/* stop controller and re-config current chip*/ +static void bfin_spi_restore_state(struct bfin_spi_master *drv_data) +{ + struct bfin_spi_device *chip = drv_data->cur_chip; + + /* Clear status and disable clock */ + bfin_write(&drv_data->regs->status, 0xFFFFFFFF); + bfin_write(&drv_data->regs->rx_control, 0x0); + bfin_write(&drv_data->regs->tx_control, 0x0); + bfin_spi_disable(drv_data); + + SSYNC(); + + /* Load the registers */ + bfin_write(&drv_data->regs->control, chip->control); + bfin_write(&drv_data->regs->clock, chip->clock); + + bfin_spi_enable(drv_data); + drv_data->tx_num = drv_data->rx_num = 0; + /* we always choose tx transfer initiate */ + bfin_write(&drv_data->regs->rx_control, SPI_RXCTL_REN); + bfin_write(&drv_data->regs->tx_control, + SPI_TXCTL_TEN | SPI_TXCTL_TTI); + bfin_spi_cs_active(drv_data, chip); +} + +/* discard invalid rx data and empty rfifo */ +static inline void dummy_read(struct bfin_spi_master *drv_data) +{ + while (!(bfin_read(&drv_data->regs->status) & SPI_STAT_RFE)) + bfin_read(&drv_data->regs->rfifo); +} + +static void bfin_spi_u8_write(struct bfin_spi_master *drv_data) +{ + dummy_read(drv_data); + while (drv_data->tx < drv_data->tx_end) { + bfin_write(&drv_data->regs->tfifo, (*(u8 *)(drv_data->tx++))); + while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE) + cpu_relax(); + bfin_read(&drv_data->regs->rfifo); + } +} + +static void bfin_spi_u8_read(struct bfin_spi_master *drv_data) +{ + u32 tx_val = drv_data->cur_chip->tx_dummy_val; + + dummy_read(drv_data); + while (drv_data->rx < drv_data->rx_end) { + bfin_write(&drv_data->regs->tfifo, tx_val); + while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE) + cpu_relax(); + *(u8 *)(drv_data->rx++) = bfin_read(&drv_data->regs->rfifo); + } +} + +static void bfin_spi_u8_duplex(struct bfin_spi_master *drv_data) +{ + dummy_read(drv_data); + while (drv_data->rx < drv_data->rx_end) { + bfin_write(&drv_data->regs->tfifo, (*(u8 *)(drv_data->tx++))); + while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE) + cpu_relax(); + *(u8 *)(drv_data->rx++) = bfin_read(&drv_data->regs->rfifo); + } +} + +static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u8 = { + .write = bfin_spi_u8_write, + .read = bfin_spi_u8_read, + .duplex = bfin_spi_u8_duplex, +}; + +static void bfin_spi_u16_write(struct bfin_spi_master *drv_data) +{ + dummy_read(drv_data); + while (drv_data->tx < drv_data->tx_end) { + bfin_write(&drv_data->regs->tfifo, (*(u16 *)drv_data->tx)); + drv_data->tx += 2; + while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE) + cpu_relax(); + bfin_read(&drv_data->regs->rfifo); + } +} + +static void bfin_spi_u16_read(struct bfin_spi_master *drv_data) +{ + u32 tx_val = drv_data->cur_chip->tx_dummy_val; + + dummy_read(drv_data); + while (drv_data->rx < drv_data->rx_end) { + bfin_write(&drv_data->regs->tfifo, tx_val); + while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE) + cpu_relax(); + *(u16 *)drv_data->rx = bfin_read(&drv_data->regs->rfifo); + drv_data->rx += 2; + } +} + +static void bfin_spi_u16_duplex(struct bfin_spi_master *drv_data) +{ + dummy_read(drv_data); + while (drv_data->rx < drv_data->rx_end) { + bfin_write(&drv_data->regs->tfifo, (*(u16 *)drv_data->tx)); + drv_data->tx += 2; + while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE) + cpu_relax(); + *(u16 *)drv_data->rx = bfin_read(&drv_data->regs->rfifo); + drv_data->rx += 2; + } +} + +static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u16 = { + .write = bfin_spi_u16_write, + .read = bfin_spi_u16_read, + .duplex = bfin_spi_u16_duplex, +}; + +static void bfin_spi_u32_write(struct bfin_spi_master *drv_data) +{ + dummy_read(drv_data); + while (drv_data->tx < drv_data->tx_end) { + bfin_write(&drv_data->regs->tfifo, (*(u32 *)drv_data->tx)); + drv_data->tx += 4; + while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE) + cpu_relax(); + bfin_read(&drv_data->regs->rfifo); + } +} + +static void bfin_spi_u32_read(struct bfin_spi_master *drv_data) +{ + u32 tx_val = drv_data->cur_chip->tx_dummy_val; + + dummy_read(drv_data); + while (drv_data->rx < drv_data->rx_end) { + bfin_write(&drv_data->regs->tfifo, tx_val); + while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE) + cpu_relax(); + *(u32 *)drv_data->rx = bfin_read(&drv_data->regs->rfifo); + drv_data->rx += 4; + } +} + +static void bfin_spi_u32_duplex(struct bfin_spi_master *drv_data) +{ + dummy_read(drv_data); + while (drv_data->rx < drv_data->rx_end) { + bfin_write(&drv_data->regs->tfifo, (*(u32 *)drv_data->tx)); + drv_data->tx += 4; + while (bfin_read(&drv_data->regs->status) & SPI_STAT_RFE) + cpu_relax(); + *(u32 *)drv_data->rx = bfin_read(&drv_data->regs->rfifo); + drv_data->rx += 4; + } +} + +static const struct bfin_spi_transfer_ops bfin_bfin_spi_transfer_ops_u32 = { + .write = bfin_spi_u32_write, + .read = bfin_spi_u32_read, + .duplex = bfin_spi_u32_duplex, +}; + + +/* test if there is more transfer to be done */ +static void bfin_spi_next_transfer(struct bfin_spi_master *drv) +{ + struct spi_message *msg = drv->cur_msg; + struct spi_transfer *t = drv->cur_transfer; + + /* Move to next transfer */ + if (t->transfer_list.next != &msg->transfers) { + drv->cur_transfer = list_entry(t->transfer_list.next, + struct spi_transfer, transfer_list); + drv->state = RUNNING_STATE; + } else { + drv->state = DONE_STATE; + drv->cur_transfer = NULL; + } +} + +static void bfin_spi_giveback(struct bfin_spi_master *drv_data) +{ + struct bfin_spi_device *chip = drv_data->cur_chip; + + bfin_spi_cs_deactive(drv_data, chip); + spi_finalize_current_message(drv_data->master); +} + +static int bfin_spi_setup_transfer(struct bfin_spi_master *drv) +{ + struct spi_transfer *t = drv->cur_transfer; + u32 cr, cr_width; + + if (t->tx_buf) { + drv->tx = (void *)t->tx_buf; + drv->tx_end = drv->tx + t->len; + } else { + drv->tx = NULL; + } + + if (t->rx_buf) { + drv->rx = t->rx_buf; + drv->rx_end = drv->rx + t->len; + } else { + drv->rx = NULL; + } + + drv->transfer_len = t->len; + + /* bits per word setup */ + switch (t->bits_per_word) { + case 8: + cr_width = SPI_CTL_SIZE08; + drv->ops = &bfin_bfin_spi_transfer_ops_u8; + break; + case 16: + cr_width = SPI_CTL_SIZE16; + drv->ops = &bfin_bfin_spi_transfer_ops_u16; + break; + case 32: + cr_width = SPI_CTL_SIZE32; + drv->ops = &bfin_bfin_spi_transfer_ops_u32; + break; + default: + return -EINVAL; + } + cr = bfin_read(&drv->regs->control) & ~SPI_CTL_SIZE; + cr |= cr_width; + bfin_write(&drv->regs->control, cr); + + /* speed setup */ + bfin_write(&drv->regs->clock, + hz_to_spi_clock(drv->sclk, t->speed_hz)); + return 0; +} + +static int bfin_spi_dma_xfer(struct bfin_spi_master *drv_data) +{ + struct spi_transfer *t = drv_data->cur_transfer; + struct spi_message *msg = drv_data->cur_msg; + struct bfin_spi_device *chip = drv_data->cur_chip; + u32 dma_config; + unsigned long word_count, word_size; + void *tx_buf, *rx_buf; + + switch (t->bits_per_word) { + case 8: + dma_config = WDSIZE_8 | PSIZE_8; + word_count = drv_data->transfer_len; + word_size = 1; + break; + case 16: + dma_config = WDSIZE_16 | PSIZE_16; + word_count = drv_data->transfer_len / 2; + word_size = 2; + break; + default: + dma_config = WDSIZE_32 | PSIZE_32; + word_count = drv_data->transfer_len / 4; + word_size = 4; + break; + } + + if (!drv_data->rx) { + tx_buf = drv_data->tx; + rx_buf = &drv_data->dummy_buffer; + drv_data->tx_dma_size = drv_data->transfer_len; + drv_data->rx_dma_size = sizeof(drv_data->dummy_buffer); + set_dma_x_modify(drv_data->tx_dma, word_size); + set_dma_x_modify(drv_data->rx_dma, 0); + } else if (!drv_data->tx) { + drv_data->dummy_buffer = chip->tx_dummy_val; + tx_buf = &drv_data->dummy_buffer; + rx_buf = drv_data->rx; + drv_data->tx_dma_size = sizeof(drv_data->dummy_buffer); + drv_data->rx_dma_size = drv_data->transfer_len; + set_dma_x_modify(drv_data->tx_dma, 0); + set_dma_x_modify(drv_data->rx_dma, word_size); + } else { + tx_buf = drv_data->tx; + rx_buf = drv_data->rx; + drv_data->tx_dma_size = drv_data->rx_dma_size + = drv_data->transfer_len; + set_dma_x_modify(drv_data->tx_dma, word_size); + set_dma_x_modify(drv_data->rx_dma, word_size); + } + + drv_data->tx_dma_addr = dma_map_single(&msg->spi->dev, + (void *)tx_buf, + drv_data->tx_dma_size, + DMA_TO_DEVICE); + if (dma_mapping_error(&msg->spi->dev, + drv_data->tx_dma_addr)) + return -ENOMEM; + + drv_data->rx_dma_addr = dma_map_single(&msg->spi->dev, + (void *)rx_buf, + drv_data->rx_dma_size, + DMA_FROM_DEVICE); + if (dma_mapping_error(&msg->spi->dev, + drv_data->rx_dma_addr)) { + dma_unmap_single(&msg->spi->dev, + drv_data->tx_dma_addr, + drv_data->tx_dma_size, + DMA_TO_DEVICE); + return -ENOMEM; + } + + dummy_read(drv_data); + set_dma_x_count(drv_data->tx_dma, word_count); + set_dma_x_count(drv_data->rx_dma, word_count); + set_dma_start_addr(drv_data->tx_dma, drv_data->tx_dma_addr); + set_dma_start_addr(drv_data->rx_dma, drv_data->rx_dma_addr); + dma_config |= DMAFLOW_STOP | RESTART | DI_EN; + set_dma_config(drv_data->tx_dma, dma_config); + set_dma_config(drv_data->rx_dma, dma_config | WNR); + enable_dma(drv_data->tx_dma); + enable_dma(drv_data->rx_dma); + SSYNC(); + + bfin_write(&drv_data->regs->rx_control, SPI_RXCTL_REN | SPI_RXCTL_RDR_NE); + SSYNC(); + bfin_write(&drv_data->regs->tx_control, + SPI_TXCTL_TEN | SPI_TXCTL_TTI | SPI_TXCTL_TDR_NF); + + return 0; +} + +static int bfin_spi_pio_xfer(struct bfin_spi_master *drv_data) +{ + struct spi_message *msg = drv_data->cur_msg; + + if (!drv_data->rx) { + /* write only half duplex */ + drv_data->ops->write(drv_data); + if (drv_data->tx != drv_data->tx_end) + return -EIO; + } else if (!drv_data->tx) { + /* read only half duplex */ + drv_data->ops->read(drv_data); + if (drv_data->rx != drv_data->rx_end) + return -EIO; + } else { + /* full duplex mode */ + drv_data->ops->duplex(drv_data); + if (drv_data->tx != drv_data->tx_end) + return -EIO; + } + + if (!bfin_spi_flush(drv_data)) + return -EIO; + msg->actual_length += drv_data->transfer_len; + tasklet_schedule(&drv_data->pump_transfers); + return 0; +} + +static void bfin_spi_pump_transfers(unsigned long data) +{ + struct bfin_spi_master *drv_data = (struct bfin_spi_master *)data; + struct spi_message *msg = NULL; + struct spi_transfer *t = NULL; + struct bfin_spi_device *chip = NULL; + int ret; + + /* Get current state information */ + msg = drv_data->cur_msg; + t = drv_data->cur_transfer; + chip = drv_data->cur_chip; + + /* Handle for abort */ + if (drv_data->state == ERROR_STATE) { + msg->status = -EIO; + bfin_spi_giveback(drv_data); + return; + } + + if (drv_data->state == RUNNING_STATE) { + if (t->delay_usecs) + udelay(t->delay_usecs); + if (t->cs_change) + bfin_spi_cs_deactive(drv_data, chip); + bfin_spi_next_transfer(drv_data); + t = drv_data->cur_transfer; + } + /* Handle end of message */ + if (drv_data->state == DONE_STATE) { + msg->status = 0; + bfin_spi_giveback(drv_data); + return; + } + + if ((t->len == 0) || (t->tx_buf == NULL && t->rx_buf == NULL)) { + /* Schedule next transfer tasklet */ + tasklet_schedule(&drv_data->pump_transfers); + return; + } + + ret = bfin_spi_setup_transfer(drv_data); + if (ret) { + msg->status = ret; + bfin_spi_giveback(drv_data); + } + + bfin_write(&drv_data->regs->status, 0xFFFFFFFF); + bfin_spi_cs_active(drv_data, chip); + drv_data->state = RUNNING_STATE; + + if (chip->enable_dma) + ret = bfin_spi_dma_xfer(drv_data); + else + ret = bfin_spi_pio_xfer(drv_data); + if (ret) { + msg->status = ret; + bfin_spi_giveback(drv_data); + } +} + +static int bfin_spi_transfer_one_message(struct spi_master *master, + struct spi_message *m) +{ + struct bfin_spi_master *drv_data = spi_master_get_devdata(master); + + drv_data->cur_msg = m; + drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi); + bfin_spi_restore_state(drv_data); + + drv_data->state = START_STATE; + drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next, + struct spi_transfer, transfer_list); + + tasklet_schedule(&drv_data->pump_transfers); + return 0; +} + +#define MAX_SPI_SSEL 7 + +static const u16 ssel[][MAX_SPI_SSEL] = { + {P_SPI0_SSEL1, P_SPI0_SSEL2, P_SPI0_SSEL3, + P_SPI0_SSEL4, P_SPI0_SSEL5, + P_SPI0_SSEL6, P_SPI0_SSEL7}, + + {P_SPI1_SSEL1, P_SPI1_SSEL2, P_SPI1_SSEL3, + P_SPI1_SSEL4, P_SPI1_SSEL5, + P_SPI1_SSEL6, P_SPI1_SSEL7}, + + {P_SPI2_SSEL1, P_SPI2_SSEL2, P_SPI2_SSEL3, + P_SPI2_SSEL4, P_SPI2_SSEL5, + P_SPI2_SSEL6, P_SPI2_SSEL7}, +}; + +static int bfin_spi_setup(struct spi_device *spi) +{ + struct bfin_spi_master *drv_data = spi_master_get_devdata(spi->master); + struct bfin_spi_device *chip = spi_get_ctldata(spi); + u32 bfin_ctl_reg = SPI_CTL_ODM | SPI_CTL_PSSE; + int ret = -EINVAL; + + if (!chip) { + struct bfin_spi3_chip *chip_info = spi->controller_data; + + chip = kzalloc(sizeof(*chip), GFP_KERNEL); + if (!chip) { + dev_err(&spi->dev, "can not allocate chip data\n"); + return -ENOMEM; + } + if (chip_info) { + if (chip_info->control & ~bfin_ctl_reg) { + dev_err(&spi->dev, + "do not set bits that the SPI framework manages\n"); + goto error; + } + chip->control = chip_info->control; + chip->cs_chg_udelay = chip_info->cs_chg_udelay; + chip->tx_dummy_val = chip_info->tx_dummy_val; + chip->enable_dma = chip_info->enable_dma; + } + chip->cs = spi->chip_select; + if (chip->cs < MAX_CTRL_CS) { + chip->ssel = (1 << chip->cs) << 8; + ret = peripheral_request(ssel[spi->master->bus_num] + [chip->cs-1], dev_name(&spi->dev)); + if (ret) { + dev_err(&spi->dev, "peripheral_request() error\n"); + goto error; + } + } else { + chip->cs_gpio = chip->cs - MAX_CTRL_CS; + ret = gpio_request_one(chip->cs_gpio, GPIOF_OUT_INIT_HIGH, + dev_name(&spi->dev)); + if (ret) { + dev_err(&spi->dev, "gpio_request_one() error\n"); + goto error; + } + } + spi_set_ctldata(spi, chip); + } + + /* force a default base state */ + chip->control &= bfin_ctl_reg; + + if (spi->mode & SPI_CPOL) + chip->control |= SPI_CTL_CPOL; + if (spi->mode & SPI_CPHA) + chip->control |= SPI_CTL_CPHA; + if (spi->mode & SPI_LSB_FIRST) + chip->control |= SPI_CTL_LSBF; + chip->control |= SPI_CTL_MSTR; + /* we choose software to controll cs */ + chip->control &= ~SPI_CTL_ASSEL; + + chip->clock = hz_to_spi_clock(drv_data->sclk, spi->max_speed_hz); + + bfin_spi_cs_enable(drv_data, chip); + bfin_spi_cs_deactive(drv_data, chip); + + return 0; +error: + if (chip) { + kfree(chip); + spi_set_ctldata(spi, NULL); + } + + return ret; +} + +static void bfin_spi_cleanup(struct spi_device *spi) +{ + struct bfin_spi_device *chip = spi_get_ctldata(spi); + struct bfin_spi_master *drv_data = spi_master_get_devdata(spi->master); + + if (!chip) + return; + + if (chip->cs < MAX_CTRL_CS) { + peripheral_free(ssel[spi->master->bus_num] + [chip->cs-1]); + bfin_spi_cs_disable(drv_data, chip); + } else { + gpio_free(chip->cs_gpio); + } + + kfree(chip); + spi_set_ctldata(spi, NULL); +} + +static irqreturn_t bfin_spi_tx_dma_isr(int irq, void *dev_id) +{ + struct bfin_spi_master *drv_data = dev_id; + u32 dma_stat = get_dma_curr_irqstat(drv_data->tx_dma); + + clear_dma_irqstat(drv_data->tx_dma); + if (dma_stat & DMA_DONE) { + drv_data->tx_num++; + } else { + dev_err(&drv_data->master->dev, + "spi tx dma error: %d\n", dma_stat); + if (drv_data->tx) + drv_data->state = ERROR_STATE; + } + bfin_write_and(&drv_data->regs->tx_control, ~SPI_TXCTL_TDR_NF); + return IRQ_HANDLED; +} + +static irqreturn_t bfin_spi_rx_dma_isr(int irq, void *dev_id) +{ + struct bfin_spi_master *drv_data = dev_id; + struct spi_message *msg = drv_data->cur_msg; + u32 dma_stat = get_dma_curr_irqstat(drv_data->rx_dma); + + clear_dma_irqstat(drv_data->rx_dma); + if (dma_stat & DMA_DONE) { + drv_data->rx_num++; + /* we may fail on tx dma */ + if (drv_data->state != ERROR_STATE) + msg->actual_length += drv_data->transfer_len; + } else { + drv_data->state = ERROR_STATE; + dev_err(&drv_data->master->dev, + "spi rx dma error: %d\n", dma_stat); + } + bfin_write(&drv_data->regs->tx_control, 0); + bfin_write(&drv_data->regs->rx_control, 0); + if (drv_data->rx_num != drv_data->tx_num) + dev_dbg(&drv_data->master->dev, + "dma interrupt missing: tx=%d,rx=%d\n", + drv_data->tx_num, drv_data->rx_num); + tasklet_schedule(&drv_data->pump_transfers); + return IRQ_HANDLED; +} + +static int bfin_spi_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct bfin_spi3_master *info = dev->platform_data; + struct spi_master *master; + struct bfin_spi_master *drv_data; + struct resource *mem, *res; + unsigned int tx_dma, rx_dma; + unsigned long sclk; + int ret; + + if (!info) { + dev_err(dev, "platform data missing!\n"); + return -ENODEV; + } + + sclk = get_sclk1(); + if (!sclk) { + dev_err(dev, "can not get sclk1\n"); + return -ENXIO; + } + + /* get register base and tx/rx dma */ + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!mem) { + dev_err(dev, "can not get register base\n"); + return -ENXIO; + } + + res = platform_get_resource(pdev, IORESOURCE_DMA, 0); + if (!res) { + dev_err(dev, "can not get tx dma resource\n"); + return -ENXIO; + } + tx_dma = res->start; + + res = platform_get_resource(pdev, IORESOURCE_DMA, 1); + if (!res) { + dev_err(dev, "can not get rx dma resource\n"); + return -ENXIO; + } + rx_dma = res->start; + + /* allocate master with space for drv_data */ + master = spi_alloc_master(dev, sizeof(*drv_data)); + if (!master) { + dev_err(dev, "can not alloc spi_master\n"); + return -ENOMEM; + } + platform_set_drvdata(pdev, master); + + /* the mode bits supported by this driver */ + master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST; + + master->bus_num = pdev->id; + master->num_chipselect = info->num_chipselect; + master->cleanup = bfin_spi_cleanup; + master->setup = bfin_spi_setup; + master->transfer_one_message = bfin_spi_transfer_one_message; + master->bits_per_word_mask = BIT(32 - 1) | BIT(16 - 1) | BIT(8 - 1); + + drv_data = spi_master_get_devdata(master); + drv_data->master = master; + drv_data->tx_dma = tx_dma; + drv_data->rx_dma = rx_dma; + drv_data->pin_req = info->pin_req; + drv_data->sclk = sclk; + + drv_data->regs = devm_ioremap_resource(dev, mem); + if (IS_ERR(drv_data->regs)) { + ret = PTR_ERR(drv_data->regs); + goto err_put_master; + } + + /* request tx and rx dma */ + ret = request_dma(tx_dma, "SPI_TX_DMA"); + if (ret) { + dev_err(dev, "can not request SPI TX DMA channel\n"); + goto err_put_master; + } + set_dma_callback(tx_dma, bfin_spi_tx_dma_isr, drv_data); + + ret = request_dma(rx_dma, "SPI_RX_DMA"); + if (ret) { + dev_err(dev, "can not request SPI RX DMA channel\n"); + goto err_free_tx_dma; + } + set_dma_callback(drv_data->rx_dma, bfin_spi_rx_dma_isr, drv_data); + + /* request CLK, MOSI and MISO */ + ret = peripheral_request_list(drv_data->pin_req, "bfin-spi3"); + if (ret < 0) { + dev_err(dev, "can not request spi pins\n"); + goto err_free_rx_dma; + } + + bfin_write(&drv_data->regs->control, SPI_CTL_MSTR | SPI_CTL_CPHA); + bfin_write(&drv_data->regs->ssel, 0x0000FE00); + bfin_write(&drv_data->regs->delay, 0x0); + + tasklet_init(&drv_data->pump_transfers, + bfin_spi_pump_transfers, (unsigned long)drv_data); + /* register with the SPI framework */ + ret = spi_register_master(master); + if (ret) { + dev_err(dev, "can not register spi master\n"); + goto err_free_peripheral; + } + + return ret; + +err_free_peripheral: + peripheral_free_list(drv_data->pin_req); +err_free_rx_dma: + free_dma(rx_dma); +err_free_tx_dma: + free_dma(tx_dma); +err_put_master: + platform_set_drvdata(pdev, NULL); + spi_master_put(master); + + return ret; +} + +static int bfin_spi_remove(struct platform_device *pdev) +{ + struct spi_master *master = platform_get_drvdata(pdev); + struct bfin_spi_master *drv_data = spi_master_get_devdata(master); + + bfin_spi_disable(drv_data); + + peripheral_free_list(drv_data->pin_req); + free_dma(drv_data->rx_dma); + free_dma(drv_data->tx_dma); + + platform_set_drvdata(pdev, NULL); + spi_unregister_master(drv_data->master); + return 0; +} + +#ifdef CONFIG_PM +static int bfin_spi_suspend(struct device *dev) +{ + struct spi_master *master = dev_get_drvdata(dev); + struct bfin_spi_master *drv_data = spi_master_get_devdata(master); + + spi_master_suspend(master); + + drv_data->control = bfin_read(&drv_data->regs->control); + drv_data->ssel = bfin_read(&drv_data->regs->ssel); + + bfin_write(&drv_data->regs->control, SPI_CTL_MSTR | SPI_CTL_CPHA); + bfin_write(&drv_data->regs->ssel, 0x0000FE00); + dma_disable_irq(drv_data->rx_dma); + dma_disable_irq(drv_data->tx_dma); + + return 0; +} + +static int bfin_spi_resume(struct device *dev) +{ + struct spi_master *master = dev_get_drvdata(dev); + struct bfin_spi_master *drv_data = spi_master_get_devdata(master); + int ret = 0; + + /* bootrom may modify spi and dma status when resume in spi boot mode */ + disable_dma(drv_data->rx_dma); + + dma_enable_irq(drv_data->rx_dma); + dma_enable_irq(drv_data->tx_dma); + bfin_write(&drv_data->regs->control, drv_data->control); + bfin_write(&drv_data->regs->ssel, drv_data->ssel); + + ret = spi_master_resume(master); + if (ret) { + free_dma(drv_data->rx_dma); + free_dma(drv_data->tx_dma); + } + + return ret; +} +#endif +static const struct dev_pm_ops bfin_spi_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(bfin_spi_suspend, bfin_spi_resume) +}; + +MODULE_ALIAS("platform:bfin-spi3"); +static struct platform_driver bfin_spi_driver = { + .driver = { + .name = "bfin-spi3", + .owner = THIS_MODULE, + .pm = &bfin_spi_pm_ops, + }, + .remove = bfin_spi_remove, +}; + +module_platform_driver_probe(bfin_spi_driver, bfin_spi_probe); + +MODULE_DESCRIPTION("Analog Devices SPI3 controller driver"); +MODULE_AUTHOR("Scott Jiang "); +MODULE_LICENSE("GPL v2"); From 838af505843ca6277b47816e284001dbe7875386 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 5 Jul 2013 19:37:51 +0100 Subject: [PATCH 0122/3400] spi/rspi: Add missing dependency on DMAE The filter function used by the rspi driver is part of the DMAE controller driver so if the DMA controller driver is somehow disabled then the rspi driver will fail to build. Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 89cbbabaff44..175491f2bb39 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -341,7 +341,7 @@ config SPI_PXA2XX_PCI config SPI_RSPI tristate "Renesas RSPI controller" - depends on SUPERH + depends on SUPERH && SH_DMAE_BASE help SPI driver for Renesas RSPI blocks. From a2fd4f9fa3b9f051550b36c4dfa74bc32bda24ee Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 10 Jul 2013 14:57:26 +0100 Subject: [PATCH 0123/3400] spi: Support transfer speed checking in the core Allow drivers to avoid implementing their own checks for simple rates by specifying the limits in the master structure. Signed-off-by: Mark Brown --- drivers/spi/spi.c | 7 +++++++ include/linux/spi/spi.h | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 978dda2c5239..a52f16685d6a 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1387,6 +1387,13 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message) BIT(xfer->bits_per_word - 1))) return -EINVAL; } + + if (xfer->speed_hz && master->min_speed_hz && + xfer->speed_hz < master->min_speed_hz) + return -EINVAL; + if (xfer->speed_hz && master->max_speed_hz && + xfer->speed_hz > master->max_speed_hz) + return -EINVAL; } message->spi = spi; diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 28e440be1c07..cdf668156154 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -233,6 +233,8 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) * suported. If set, the SPI core will reject any transfer with an * unsupported bits_per_word. If not set, this value is simply ignored, * and it's up to the individual driver to perform any validation. + * @min_speed_hz: Lowest supported transfer speed + * @max_speed_hz: Highest supported transfer speed * @flags: other constraints relevant to this driver * @bus_lock_spinlock: spinlock for SPI bus locking * @bus_lock_mutex: mutex for SPI bus locking @@ -312,6 +314,10 @@ struct spi_master { #define SPI_BIT_MASK(bits) (((bits) == 32) ? ~0UL : (BIT(bits) - 1)) #define SPI_BPW_RANGE_MASK(min, max) (SPI_BIT_MASK(max) - SPI_BIT_MASK(min - 1)) + /* limits on transfer speed */ + u32 min_speed_hz; + u32 max_speed_hz; + /* other constraints relevant to this driver */ u16 flags; #define SPI_MASTER_HALF_DUPLEX BIT(0) /* can't do full duplex */ From 24a0013a04e81e95198daab98edf4df02e191568 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 10 Jul 2013 15:05:40 +0100 Subject: [PATCH 0124/3400] spi: More sanity checks for transfers Check that transfers are non-empty and that there is a completion for them. Signed-off-by: Mark Brown --- drivers/spi/spi.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index a52f16685d6a..c2899161ccac 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1351,6 +1351,11 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message) struct spi_master *master = spi->master; struct spi_transfer *xfer; + if (list_empty(&message->transfers)) + return -EINVAL; + if (!message->complete) + return -EINVAL; + /* Half-duplex links include original MicroWire, and ones with * only one data pin like SPI_3WIRE (switches direction) or where * either MOSI or MISO is missing. They can also be caused by From c8b94d8492e6e3f938519517ae859f94820f9422 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 5 Jul 2013 19:26:52 +0100 Subject: [PATCH 0125/3400] spi/clps711x: Remove unneeded devm_ deallocations The whole point of devm is that it'll do these automatically. Signed-off-by: Mark Brown --- drivers/spi/spi-clps711x.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/spi/spi-clps711x.c b/drivers/spi/spi-clps711x.c index 17965fe225cc..5655acf55bfe 100644 --- a/drivers/spi/spi-clps711x.c +++ b/drivers/spi/spi-clps711x.c @@ -239,11 +239,8 @@ static int spi_clps711x_probe(struct platform_device *pdev) } dev_err(&pdev->dev, "Failed to register master\n"); - devm_free_irq(&pdev->dev, IRQ_SSEOTI, hw); clk_out: - devm_clk_put(&pdev->dev, hw->spi_clk); - err_out: while (--i >= 0) if (gpio_is_valid(hw->chipselect[i])) @@ -261,13 +258,10 @@ static int spi_clps711x_remove(struct platform_device *pdev) struct spi_master *master = platform_get_drvdata(pdev); struct spi_clps711x_data *hw = spi_master_get_devdata(master); - devm_free_irq(&pdev->dev, IRQ_SSEOTI, hw); - for (i = 0; i < master->num_chipselect; i++) if (gpio_is_valid(hw->chipselect[i])) gpio_free(hw->chipselect[i]); - devm_clk_put(&pdev->dev, hw->spi_clk); spi_unregister_master(master); kfree(master); From 4870c2170d91f33a1a90bd5b1d7c5534332f30f2 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 28 Jun 2013 11:43:34 -0700 Subject: [PATCH 0126/3400] spi: spi-ep93xx: always handle transfer specific settings __spi_async(), which starts every SPI message transfer, initializes the bits_per_word and max speed for every transfer in the message. Since the conditional test in ep93xx_spi_process_transfer() will always succeed just remove it and always call ep93xx_spi_chip_setup() to configure the hardware for each transfer in the message. Remove the redundant ep93xx_spi_chp_setup() in ep93xx_spi_process_transfer() which just initializes the hardware to the "default" based on the SPI device. Signed-off-by: H Hartley Sweeten Acked-by: Mika Westerberg Signed-off-by: Mark Brown --- drivers/spi/spi-ep93xx.c | 45 ++++++++++------------------------------ 1 file changed, 11 insertions(+), 34 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index cad30b8a1d71..11e2b999cce2 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -708,39 +708,21 @@ static void ep93xx_spi_process_transfer(struct ep93xx_spi *espi, struct spi_transfer *t) { struct ep93xx_spi_chip *chip = spi_get_ctldata(msg->spi); + int err; msg->state = t; - /* - * Handle any transfer specific settings if needed. We use - * temporary chip settings here and restore original later when - * the transfer is finished. - */ - if (t->speed_hz || t->bits_per_word) { - struct ep93xx_spi_chip tmp_chip = *chip; - - if (t->speed_hz) { - int err; - - err = ep93xx_spi_calc_divisors(espi, &tmp_chip, - t->speed_hz); - if (err) { - dev_err(&espi->pdev->dev, - "failed to adjust speed\n"); - msg->status = err; - return; - } - } - - if (t->bits_per_word) - tmp_chip.dss = bits_per_word_to_dss(t->bits_per_word); - - /* - * Set up temporary new hw settings for this transfer. - */ - ep93xx_spi_chip_setup(espi, &tmp_chip); + err = ep93xx_spi_calc_divisors(espi, chip, t->speed_hz); + if (err) { + dev_err(&espi->pdev->dev, "failed to adjust speed\n"); + msg->status = err; + return; } + chip->dss = bits_per_word_to_dss(t->bits_per_word); + + ep93xx_spi_chip_setup(espi, chip); + espi->rx = 0; espi->tx = 0; @@ -783,9 +765,6 @@ static void ep93xx_spi_process_transfer(struct ep93xx_spi *espi, ep93xx_spi_cs_control(msg->spi, true); } } - - if (t->speed_hz || t->bits_per_word) - ep93xx_spi_chip_setup(espi, chip); } /* @@ -838,10 +817,8 @@ static void ep93xx_spi_process_message(struct ep93xx_spi *espi, espi->fifo_level = 0; /* - * Update SPI controller registers according to spi device and assert - * the chipselect. + * Assert the chipselect. */ - ep93xx_spi_chip_setup(espi, spi_get_ctldata(msg->spi)); ep93xx_spi_cs_control(msg->spi, true); list_for_each_entry(t, &msg->transfers, transfer_list) { From 8d7586bda032748ceec44416fa32a711a62e4954 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 2 Jul 2013 10:06:26 -0700 Subject: [PATCH 0127/3400] spi: spi-ep93xx: use read,write instead of __raw_* variants The memory resource used by this driver is ioremap()'d and the normal read,write calls can be used instead of the __raw_* variants. Also, remove the inline tag on the helper functions and let the compiler decide if they are inlined. Signed-off-by: H Hartley Sweeten Acked-by: Mika Westerberg Signed-off-by: Mark Brown --- drivers/spi/spi-ep93xx.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index 11e2b999cce2..d7eccfc40ac9 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -158,28 +158,26 @@ struct ep93xx_spi_chip { /* converts bits per word to CR0.DSS value */ #define bits_per_word_to_dss(bpw) ((bpw) - 1) -static inline void -ep93xx_spi_write_u8(const struct ep93xx_spi *espi, u16 reg, u8 value) +static void ep93xx_spi_write_u8(const struct ep93xx_spi *espi, + u16 reg, u8 value) { - __raw_writeb(value, espi->regs_base + reg); + writeb(value, espi->regs_base + reg); } -static inline u8 -ep93xx_spi_read_u8(const struct ep93xx_spi *spi, u16 reg) +static u8 ep93xx_spi_read_u8(const struct ep93xx_spi *spi, u16 reg) { - return __raw_readb(spi->regs_base + reg); + return readb(spi->regs_base + reg); } -static inline void -ep93xx_spi_write_u16(const struct ep93xx_spi *espi, u16 reg, u16 value) +static void ep93xx_spi_write_u16(const struct ep93xx_spi *espi, + u16 reg, u16 value) { - __raw_writew(value, espi->regs_base + reg); + writew(value, espi->regs_base + reg); } -static inline u16 -ep93xx_spi_read_u16(const struct ep93xx_spi *spi, u16 reg) +static u16 ep93xx_spi_read_u16(const struct ep93xx_spi *spi, u16 reg) { - return __raw_readw(spi->regs_base + reg); + return readw(spi->regs_base + reg); } static int ep93xx_spi_enable(const struct ep93xx_spi *espi) From 701c3587ee38ed53719187b0f1b059e113ac534f Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 2 Jul 2013 10:07:01 -0700 Subject: [PATCH 0128/3400] spi: spi-ep93xx: remove bits_per_word() helper Check t->bits_per_word directly and remove the inline helper function. Signed-off-by: H Hartley Sweeten Acked-by: Mika Westerberg Signed-off-by: Mark Brown --- drivers/spi/spi-ep93xx.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index d7eccfc40ac9..d5e64201cdd3 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -429,17 +429,9 @@ static void ep93xx_spi_chip_setup(const struct ep93xx_spi *espi, ep93xx_spi_write_u16(espi, SSPCR0, cr0); } -static inline int bits_per_word(const struct ep93xx_spi *espi) -{ - struct spi_message *msg = espi->current_msg; - struct spi_transfer *t = msg->state; - - return t->bits_per_word; -} - static void ep93xx_do_write(struct ep93xx_spi *espi, struct spi_transfer *t) { - if (bits_per_word(espi) > 8) { + if (t->bits_per_word > 8) { u16 tx_val = 0; if (t->tx_buf) @@ -458,7 +450,7 @@ static void ep93xx_do_write(struct ep93xx_spi *espi, struct spi_transfer *t) static void ep93xx_do_read(struct ep93xx_spi *espi, struct spi_transfer *t) { - if (bits_per_word(espi) > 8) { + if (t->bits_per_word > 8) { u16 rx_val; rx_val = ep93xx_spi_read_u16(espi, SSPDR); @@ -544,7 +536,7 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_transfer_direction dir) size_t len = t->len; int i, ret, nents; - if (bits_per_word(espi) > 8) + if (t->bits_per_word > 8) buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; else buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE; From 48a7776e981fdf780728e45de4ae4f2b522c9c4d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 2 Jul 2013 10:07:53 -0700 Subject: [PATCH 0129/3400] spi: spi-ep93xx: get platform resources early in (*probe) Get the platform resources early in the (*probe) to minimize the number of goto's in the error path. Signed-off-by: H Hartley Sweeten Acked-by: Mika Westerberg Signed-off-by: Mark Brown --- drivers/spi/spi-ep93xx.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index d5e64201cdd3..c2660c24c0ab 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -991,6 +991,18 @@ static int ep93xx_spi_probe(struct platform_device *pdev) info = pdev->dev.platform_data; + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "failed to get irq resources\n"); + return -EBUSY; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "unable to get iomem resource\n"); + return -ENODEV; + } + master = spi_alloc_master(&pdev->dev, sizeof(*espi)); if (!master) { dev_err(&pdev->dev, "failed to allocate spi master\n"); @@ -1027,20 +1039,6 @@ static int ep93xx_spi_probe(struct platform_device *pdev) espi->min_rate = clk_get_rate(espi->clk) / (254 * 256); espi->pdev = pdev; - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - error = -EBUSY; - dev_err(&pdev->dev, "failed to get irq resources\n"); - goto fail_put_clock; - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "unable to get iomem resource\n"); - error = -ENODEV; - goto fail_put_clock; - } - espi->sspdr_phys = res->start + SSPDR; espi->regs_base = devm_ioremap_resource(&pdev->dev, res); From b2d185edbac9c40adb1d390ad966e6900992e69d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 2 Jul 2013 10:08:59 -0700 Subject: [PATCH 0130/3400] spi: spi-ep93xx: remove dev_err() for kzalloc() failure The kzalloc() failure will have already output a message. Signed-off-by: H Hartley Sweeten Acked-by: Mika Westerberg Signed-off-by: Mark Brown --- drivers/spi/spi-ep93xx.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index c2660c24c0ab..7a44163ace50 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -1004,10 +1004,8 @@ static int ep93xx_spi_probe(struct platform_device *pdev) } master = spi_alloc_master(&pdev->dev, sizeof(*espi)); - if (!master) { - dev_err(&pdev->dev, "failed to allocate spi master\n"); + if (!master) return -ENOMEM; - } master->setup = ep93xx_spi_setup; master->transfer = ep93xx_spi_transfer; From d9b65dfd44fdade5c0fde5f7b8a0f267e99f990d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 2 Jul 2013 10:09:29 -0700 Subject: [PATCH 0131/3400] spi: spi-ep93xx: remove 'dss' from per chip private data This value is only needed to set the bits per word for each transfer of a message. There is no reason to set the value in ep93xx_spi_enable() because ep93xx_spi_process_transfer() sets it again for each transfer. Just pass the t->bits_per_word directly to ep93xx_spi_chip_setup() in ep93xx_spi_process_transfer() and remove 'dss' from the per chip private data. Signed-off-by: H Hartley Sweeten Acked-by: Mika Westerberg Signed-off-by: Mark Brown --- drivers/spi/spi-ep93xx.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index 7a44163ace50..8d562526abe5 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -139,7 +139,6 @@ struct ep93xx_spi { * @rate: max rate in hz this chip supports * @div_cpsr: cpsr (pre-scaler) divider * @div_scr: scr divider - * @dss: bits per word (4 - 16 bits) * @ops: private chip operations * * This structure is used to store hardware register specific settings for each @@ -151,7 +150,6 @@ struct ep93xx_spi_chip { unsigned long rate; u8 div_cpsr; u8 div_scr; - u8 dss; struct ep93xx_spi_chip_ops *ops; }; @@ -329,8 +327,6 @@ static int ep93xx_spi_setup(struct spi_device *spi) chip->rate = spi->max_speed_hz; } - chip->dss = bits_per_word_to_dss(spi->bits_per_word); - ep93xx_spi_cs_control(spi, false); return 0; } @@ -407,22 +403,25 @@ static void ep93xx_spi_cleanup(struct spi_device *spi) * ep93xx_spi_chip_setup() - configures hardware according to given @chip * @espi: ep93xx SPI controller struct * @chip: chip specific settings + * @bits_per_word: transfer bits_per_word * * This function sets up the actual hardware registers with settings given in * @chip. Note that no validation is done so make sure that callers validate * settings before calling this. */ static void ep93xx_spi_chip_setup(const struct ep93xx_spi *espi, - const struct ep93xx_spi_chip *chip) + const struct ep93xx_spi_chip *chip, + u8 bits_per_word) { + u8 dss = bits_per_word_to_dss(bits_per_word); u16 cr0; cr0 = chip->div_scr << SSPCR0_SCR_SHIFT; cr0 |= (chip->spi->mode & (SPI_CPHA|SPI_CPOL)) << SSPCR0_MODE_SHIFT; - cr0 |= chip->dss; + cr0 |= dss; dev_dbg(&espi->pdev->dev, "setup: mode %d, cpsr %d, scr %d, dss %d\n", - chip->spi->mode, chip->div_cpsr, chip->div_scr, chip->dss); + chip->spi->mode, chip->div_cpsr, chip->div_scr, dss); dev_dbg(&espi->pdev->dev, "setup: cr0 %#x", cr0); ep93xx_spi_write_u8(espi, SSPCPSR, chip->div_cpsr); @@ -709,9 +708,7 @@ static void ep93xx_spi_process_transfer(struct ep93xx_spi *espi, return; } - chip->dss = bits_per_word_to_dss(t->bits_per_word); - - ep93xx_spi_chip_setup(espi, chip); + ep93xx_spi_chip_setup(espi, chip, t->bits_per_word); espi->rx = 0; espi->tx = 0; From e6eb8d9bb7b9c144ae63a5e97a686dd8a3377443 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 2 Jul 2013 10:08:21 -0700 Subject: [PATCH 0132/3400] spi: spi-ep93xx: use devm_clk_get() Use devm_clk_get() so that the clk_put() happens automatically when the last reference to this driver is dropped. Signed-off-by: H Hartley Sweeten Acked-by: Mika Westerberg Signed-off-by: Mark Brown --- drivers/spi/spi-ep93xx.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index 8d562526abe5..cc2a2405bd1d 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -1016,7 +1016,7 @@ static int ep93xx_spi_probe(struct platform_device *pdev) espi = spi_master_get_devdata(master); - espi->clk = clk_get(&pdev->dev, NULL); + espi->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(espi->clk)) { dev_err(&pdev->dev, "unable to get spi clock\n"); error = PTR_ERR(espi->clk); @@ -1039,14 +1039,14 @@ static int ep93xx_spi_probe(struct platform_device *pdev) espi->regs_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(espi->regs_base)) { error = PTR_ERR(espi->regs_base); - goto fail_put_clock; + goto fail_release_master; } error = devm_request_irq(&pdev->dev, irq, ep93xx_spi_interrupt, 0, "ep93xx-spi", espi); if (error) { dev_err(&pdev->dev, "failed to request irq\n"); - goto fail_put_clock; + goto fail_release_master; } if (info->use_dma && ep93xx_spi_setup_dma(espi)) @@ -1080,8 +1080,6 @@ fail_free_queue: destroy_workqueue(espi->wq); fail_free_dma: ep93xx_spi_release_dma(espi); -fail_put_clock: - clk_put(espi->clk); fail_release_master: spi_master_put(master); @@ -1117,7 +1115,6 @@ static int ep93xx_spi_remove(struct platform_device *pdev) spin_unlock_irq(&espi->lock); ep93xx_spi_release_dma(espi); - clk_put(espi->clk); spi_unregister_master(master); return 0; From 22c1b69ea833de84a9505135303ff443e62b3b15 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 2 Jul 2013 10:10:00 -0700 Subject: [PATCH 0133/3400] spi: spi-ep93xx: don't bother calculating the divisors in ep93xx_spi_setup() The divisors needed to generate the SPI clock are calculated per transfer based on the t->speed_hz. There is no reason to calculate them in ep93xx_spi_setup(). Signed-off-by: H Hartley Sweeten Acked-by: Mika Westerberg Signed-off-by: Mark Brown --- drivers/spi/spi-ep93xx.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index cc2a2405bd1d..6cdfc4036b75 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -136,7 +136,6 @@ struct ep93xx_spi { /** * struct ep93xx_spi_chip - SPI device hardware settings * @spi: back pointer to the SPI device - * @rate: max rate in hz this chip supports * @div_cpsr: cpsr (pre-scaler) divider * @div_scr: scr divider * @ops: private chip operations @@ -147,7 +146,6 @@ struct ep93xx_spi { */ struct ep93xx_spi_chip { const struct spi_device *spi; - unsigned long rate; u8 div_cpsr; u8 div_scr; struct ep93xx_spi_chip_ops *ops; @@ -315,18 +313,6 @@ static int ep93xx_spi_setup(struct spi_device *spi) spi_set_ctldata(spi, chip); } - if (spi->max_speed_hz != chip->rate) { - int err; - - err = ep93xx_spi_calc_divisors(espi, chip, spi->max_speed_hz); - if (err != 0) { - spi_set_ctldata(spi, NULL); - kfree(chip); - return err; - } - chip->rate = spi->max_speed_hz; - } - ep93xx_spi_cs_control(spi, false); return 0; } From f7ef1da9e22ce390333645fc0ea70ff279eecd55 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 2 Jul 2013 10:10:29 -0700 Subject: [PATCH 0134/3400] spi: spi-ep93xx: move the clock divider calcs into ep93xx_spi_chip_setup() The divider values stored in the per chip data are only used to set the registers in the hardware to generate the desired SPI clock. Since these are calculated per transfer based on the t->speed_hz there is no reason keep them in the per chip data. Move the ep93xx_spi_calc_divisors() call into ep93xx_spi_chip_setup() and return the dividers thru pointers. Remove the divider values from the per chip data structure. Signed-off-by: H Hartley Sweeten Acked-by: Mika Westerberg Signed-off-by: Mark Brown --- drivers/spi/spi-ep93xx.c | 57 ++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 32 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index 6cdfc4036b75..2e64806b40af 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -136,18 +136,10 @@ struct ep93xx_spi { /** * struct ep93xx_spi_chip - SPI device hardware settings * @spi: back pointer to the SPI device - * @div_cpsr: cpsr (pre-scaler) divider - * @div_scr: scr divider * @ops: private chip operations - * - * This structure is used to store hardware register specific settings for each - * SPI device. Settings are written to hardware by function - * ep93xx_spi_chip_setup(). */ struct ep93xx_spi_chip { const struct spi_device *spi; - u8 div_cpsr; - u8 div_scr; struct ep93xx_spi_chip_ops *ops; }; @@ -224,17 +216,13 @@ static void ep93xx_spi_disable_interrupts(const struct ep93xx_spi *espi) /** * ep93xx_spi_calc_divisors() - calculates SPI clock divisors * @espi: ep93xx SPI controller struct - * @chip: divisors are calculated for this chip * @rate: desired SPI output clock rate - * - * Function calculates cpsr (clock pre-scaler) and scr divisors based on - * given @rate and places them to @chip->div_cpsr and @chip->div_scr. If, - * for some reason, divisors cannot be calculated nothing is stored and - * %-EINVAL is returned. + * @div_cpsr: pointer to return the cpsr (pre-scaler) divider + * @div_scr: pointer to return the scr divider */ static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi, - struct ep93xx_spi_chip *chip, - unsigned long rate) + unsigned long rate, + u8 *div_cpsr, u8 *div_scr) { unsigned long spi_clk_rate = clk_get_rate(espi->clk); int cpsr, scr; @@ -257,8 +245,8 @@ static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi, for (cpsr = 2; cpsr <= 254; cpsr += 2) { for (scr = 0; scr <= 255; scr++) { if ((spi_clk_rate / (cpsr * (scr + 1))) <= rate) { - chip->div_scr = (u8)scr; - chip->div_cpsr = (u8)cpsr; + *div_scr = (u8)scr; + *div_cpsr = (u8)cpsr; return 0; } } @@ -389,29 +377,35 @@ static void ep93xx_spi_cleanup(struct spi_device *spi) * ep93xx_spi_chip_setup() - configures hardware according to given @chip * @espi: ep93xx SPI controller struct * @chip: chip specific settings + * @speed_hz: transfer speed * @bits_per_word: transfer bits_per_word - * - * This function sets up the actual hardware registers with settings given in - * @chip. Note that no validation is done so make sure that callers validate - * settings before calling this. */ -static void ep93xx_spi_chip_setup(const struct ep93xx_spi *espi, - const struct ep93xx_spi_chip *chip, - u8 bits_per_word) +static int ep93xx_spi_chip_setup(const struct ep93xx_spi *espi, + const struct ep93xx_spi_chip *chip, + u32 speed_hz, u8 bits_per_word) { u8 dss = bits_per_word_to_dss(bits_per_word); + u8 div_cpsr = 0; + u8 div_scr = 0; u16 cr0; + int err; - cr0 = chip->div_scr << SSPCR0_SCR_SHIFT; + err = ep93xx_spi_calc_divisors(espi, speed_hz, &div_cpsr, &div_scr); + if (err) + return err; + + cr0 = div_scr << SSPCR0_SCR_SHIFT; cr0 |= (chip->spi->mode & (SPI_CPHA|SPI_CPOL)) << SSPCR0_MODE_SHIFT; cr0 |= dss; dev_dbg(&espi->pdev->dev, "setup: mode %d, cpsr %d, scr %d, dss %d\n", - chip->spi->mode, chip->div_cpsr, chip->div_scr, dss); + chip->spi->mode, div_cpsr, div_scr, dss); dev_dbg(&espi->pdev->dev, "setup: cr0 %#x", cr0); - ep93xx_spi_write_u8(espi, SSPCPSR, chip->div_cpsr); + ep93xx_spi_write_u8(espi, SSPCPSR, div_cpsr); ep93xx_spi_write_u16(espi, SSPCR0, cr0); + + return 0; } static void ep93xx_do_write(struct ep93xx_spi *espi, struct spi_transfer *t) @@ -687,15 +681,14 @@ static void ep93xx_spi_process_transfer(struct ep93xx_spi *espi, msg->state = t; - err = ep93xx_spi_calc_divisors(espi, chip, t->speed_hz); + err = ep93xx_spi_chip_setup(espi, chip, t->speed_hz, t->bits_per_word); if (err) { - dev_err(&espi->pdev->dev, "failed to adjust speed\n"); + dev_err(&espi->pdev->dev, + "failed to setup chip for transfer\n"); msg->status = err; return; } - ep93xx_spi_chip_setup(espi, chip, t->bits_per_word); - espi->rx = 0; espi->tx = 0; From 130b82c047675cf398ac49b7d230288f1b9ac9ad Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 11 Jul 2013 01:26:48 -0300 Subject: [PATCH 0135/3400] spi: spi-imx: Use devm functions Using devm functions can make the code smaller and cleaner. Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown --- drivers/spi/spi-imx.c | 61 +++++++++++-------------------------------- 1 file changed, 15 insertions(+), 46 deletions(-) diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 7db4f43ee4d8..756cd466cfaf 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -796,10 +796,11 @@ static int spi_imx_probe(struct platform_device *pdev) if (!gpio_is_valid(cs_gpio)) continue; - ret = gpio_request(spi_imx->chipselect[i], DRIVER_NAME); + ret = devm_gpio_request(&pdev->dev, spi_imx->chipselect[i], + DRIVER_NAME); if (ret) { dev_err(&pdev->dev, "can't get cs gpios\n"); - goto out_gpio_free; + goto out_master_put; } } @@ -816,46 +817,35 @@ static int spi_imx_probe(struct platform_device *pdev) (struct spi_imx_devtype_data *) pdev->id_entry->driver_data; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "can't get platform resource\n"); - ret = -ENOMEM; - goto out_gpio_free; - } - - if (!request_mem_region(res->start, resource_size(res), pdev->name)) { - dev_err(&pdev->dev, "request_mem_region failed\n"); - ret = -EBUSY; - goto out_gpio_free; - } - - spi_imx->base = ioremap(res->start, resource_size(res)); - if (!spi_imx->base) { - ret = -EINVAL; - goto out_release_mem; + spi_imx->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(spi_imx->base)) { + ret = PTR_ERR(spi_imx->base); + goto out_master_put; } spi_imx->irq = platform_get_irq(pdev, 0); if (spi_imx->irq < 0) { ret = -EINVAL; - goto out_iounmap; + goto out_master_put; } - ret = request_irq(spi_imx->irq, spi_imx_isr, 0, DRIVER_NAME, spi_imx); + ret = devm_request_irq(&pdev->dev, spi_imx->irq, spi_imx_isr, 0, + DRIVER_NAME, spi_imx); if (ret) { dev_err(&pdev->dev, "can't get irq%d: %d\n", spi_imx->irq, ret); - goto out_iounmap; + goto out_master_put; } spi_imx->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); if (IS_ERR(spi_imx->clk_ipg)) { ret = PTR_ERR(spi_imx->clk_ipg); - goto out_free_irq; + goto out_master_put; } spi_imx->clk_per = devm_clk_get(&pdev->dev, "per"); if (IS_ERR(spi_imx->clk_per)) { ret = PTR_ERR(spi_imx->clk_per); - goto out_free_irq; + goto out_master_put; } clk_prepare_enable(spi_imx->clk_per); @@ -881,45 +871,24 @@ static int spi_imx_probe(struct platform_device *pdev) out_clk_put: clk_disable_unprepare(spi_imx->clk_per); clk_disable_unprepare(spi_imx->clk_ipg); -out_free_irq: - free_irq(spi_imx->irq, spi_imx); -out_iounmap: - iounmap(spi_imx->base); -out_release_mem: - release_mem_region(res->start, resource_size(res)); -out_gpio_free: - while (--i >= 0) { - if (gpio_is_valid(spi_imx->chipselect[i])) - gpio_free(spi_imx->chipselect[i]); - } +out_master_put: spi_master_put(master); - kfree(master); + return ret; } static int spi_imx_remove(struct platform_device *pdev) { struct spi_master *master = platform_get_drvdata(pdev); - struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); struct spi_imx_data *spi_imx = spi_master_get_devdata(master); - int i; spi_bitbang_stop(&spi_imx->bitbang); writel(0, spi_imx->base + MXC_CSPICTRL); clk_disable_unprepare(spi_imx->clk_per); clk_disable_unprepare(spi_imx->clk_ipg); - free_irq(spi_imx->irq, spi_imx); - iounmap(spi_imx->base); - - for (i = 0; i < master->num_chipselect; i++) - if (gpio_is_valid(spi_imx->chipselect[i])) - gpio_free(spi_imx->chipselect[i]); - spi_master_put(master); - release_mem_region(res->start, resource_size(res)); - return 0; } From 83174626ccf897827d2c49f26d9b0b7f74af85cc Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 11 Jul 2013 01:26:49 -0300 Subject: [PATCH 0136/3400] spi: spi-imx: Check the return value from clk_prepare_enable() clk_prepare_enable() may fail, so let's check its return value and propagate it in the case of error. While at it, fix the order of clk_disable_unprepare calls: clk_ipg should be disabled first, followed by clk_per. Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown --- drivers/spi/spi-imx.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 756cd466cfaf..81c7dd2228f9 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -848,8 +848,13 @@ static int spi_imx_probe(struct platform_device *pdev) goto out_master_put; } - clk_prepare_enable(spi_imx->clk_per); - clk_prepare_enable(spi_imx->clk_ipg); + ret = clk_prepare_enable(spi_imx->clk_per); + if (ret) + goto out_master_put; + + ret = clk_prepare_enable(spi_imx->clk_ipg); + if (ret) + goto out_put_per; spi_imx->spi_clk = clk_get_rate(spi_imx->clk_per); @@ -869,8 +874,9 @@ static int spi_imx_probe(struct platform_device *pdev) return ret; out_clk_put: - clk_disable_unprepare(spi_imx->clk_per); clk_disable_unprepare(spi_imx->clk_ipg); +out_put_per: + clk_disable_unprepare(spi_imx->clk_per); out_master_put: spi_master_put(master); @@ -885,8 +891,8 @@ static int spi_imx_remove(struct platform_device *pdev) spi_bitbang_stop(&spi_imx->bitbang); writel(0, spi_imx->base + MXC_CSPICTRL); - clk_disable_unprepare(spi_imx->clk_per); clk_disable_unprepare(spi_imx->clk_ipg); + clk_disable_unprepare(spi_imx->clk_per); spi_master_put(master); return 0; From e11933f626c0a1333ec118d35a0c6c90d576b707 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Wed, 10 Jul 2013 00:16:27 -0300 Subject: [PATCH 0137/3400] spi: spi-mxs: Fix the error path sequence On mxs_spi_probe() the dma channels are requested prior to enabling the SSP clock, so in the error path we should disable the SSP clock first and release the DMA channels later. Same logic applies in mxs_spi_remove(). Signed-off-by: Fabio Estevam Acked-by: Marek Vasut Signed-off-by: Mark Brown --- drivers/spi/spi-mxs.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c index 424d38e59421..92254a1672e7 100644 --- a/drivers/spi/spi-mxs.c +++ b/drivers/spi/spi-mxs.c @@ -580,8 +580,8 @@ static int mxs_spi_probe(struct platform_device *pdev) return 0; out_free_dma: - dma_release_channel(ssp->dmach); clk_disable_unprepare(ssp->clk); + dma_release_channel(ssp->dmach); out_master_free: spi_master_put(master); return ret; @@ -598,11 +598,8 @@ static int mxs_spi_remove(struct platform_device *pdev) ssp = &spi->ssp; spi_unregister_master(master); - - dma_release_channel(ssp->dmach); - clk_disable_unprepare(ssp->clk); - + dma_release_channel(ssp->dmach); spi_master_put(master); return 0; From 9c4a39afaa2ef8f96b7bda1ffb5deef0e98ad189 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Wed, 10 Jul 2013 00:16:28 -0300 Subject: [PATCH 0138/3400] spi: spi-mxs: Check the return value from clk_prepare_enable() clk_prepare_enable() may fail, so let's check its return value and propagate it in the case of error. While at it, rename 'out_free_dma' to 'out_disable_clk' so that it can properly describe its purpose. Signed-off-by: Fabio Estevam Acked-by: Marek Vasut Signed-off-by: Mark Brown --- drivers/spi/spi-mxs.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c index 92254a1672e7..ecc59444875c 100644 --- a/drivers/spi/spi-mxs.c +++ b/drivers/spi/spi-mxs.c @@ -563,7 +563,10 @@ static int mxs_spi_probe(struct platform_device *pdev) goto out_master_free; } - clk_prepare_enable(ssp->clk); + ret = clk_prepare_enable(ssp->clk); + if (ret) + goto out_dma_release; + clk_set_rate(ssp->clk, clk_freq); ssp->clk_rate = clk_get_rate(ssp->clk) / 1000; @@ -574,13 +577,14 @@ static int mxs_spi_probe(struct platform_device *pdev) ret = spi_register_master(master); if (ret) { dev_err(&pdev->dev, "Cannot register SPI master, %d\n", ret); - goto out_free_dma; + goto out_disable_clk; } return 0; -out_free_dma: +out_disable_clk: clk_disable_unprepare(ssp->clk); +out_dma_release: dma_release_channel(ssp->dmach); out_master_free: spi_master_put(master); From 8498bce934b864d609dab15a342bc47bb637c7f6 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Wed, 10 Jul 2013 00:16:29 -0300 Subject: [PATCH 0139/3400] spi: spi-mxs: Check the return value from stmp_reset_block() stmp_reset_block() may fail, so let's check its return value and propagate it in the case of error. Signed-off-by: Fabio Estevam Acked-by: Marek Vasut Signed-off-by: Mark Brown --- drivers/spi/spi-mxs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c index ecc59444875c..5b0a8e309197 100644 --- a/drivers/spi/spi-mxs.c +++ b/drivers/spi/spi-mxs.c @@ -570,7 +570,9 @@ static int mxs_spi_probe(struct platform_device *pdev) clk_set_rate(ssp->clk, clk_freq); ssp->clk_rate = clk_get_rate(ssp->clk) / 1000; - stmp_reset_block(ssp->base); + ret = stmp_reset_block(ssp->base); + if (ret) + goto out_disable_clk; platform_set_drvdata(pdev, master); From 407d600f1fb99978bde36b79403f6177865697b6 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 10 Jul 2013 14:34:55 +0100 Subject: [PATCH 0140/3400] spi/omap-100k: Remove empty reset function Signed-off-by: Mark Brown --- drivers/spi/spi-omap-100k.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/spi/spi-omap-100k.c b/drivers/spi/spi-omap-100k.c index ee25670f8cfd..18bcaf3bcf17 100644 --- a/drivers/spi/spi-omap-100k.c +++ b/drivers/spi/spi-omap-100k.c @@ -472,11 +472,6 @@ static int omap1_spi100k_transfer(struct spi_device *spi, struct spi_message *m) return 0; } -static int omap1_spi100k_reset(struct omap1_spi100k *spi100k) -{ - return 0; -} - static int omap1_spi100k_probe(struct platform_device *pdev) { struct spi_master *master; @@ -532,9 +527,6 @@ static int omap1_spi100k_probe(struct platform_device *pdev) goto err2; } - if (omap1_spi100k_reset(spi100k) < 0) - goto err3; - status = spi_register_master(master); if (status < 0) goto err3; From 69ea672a13a9b702ea3dc84de0cd9e1f4a088217 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 10 Jul 2013 15:06:46 +0100 Subject: [PATCH 0141/3400] spi/omap-100k: Use core functionality to check validity of transfers Signed-off-by: Mark Brown --- drivers/spi/spi-omap-100k.c | 32 ++------------------------------ 1 file changed, 2 insertions(+), 30 deletions(-) diff --git a/drivers/spi/spi-omap-100k.c b/drivers/spi/spi-omap-100k.c index 18bcaf3bcf17..3b42a4ba8fa2 100644 --- a/drivers/spi/spi-omap-100k.c +++ b/drivers/spi/spi-omap-100k.c @@ -424,7 +424,6 @@ static int omap1_spi100k_transfer(struct spi_device *spi, struct spi_message *m) { struct omap1_spi100k *spi100k; unsigned long flags; - struct spi_transfer *t; m->actual_length = 0; m->status = -EINPROGRESS; @@ -435,35 +434,6 @@ static int omap1_spi100k_transfer(struct spi_device *spi, struct spi_message *m) if (spi100k->state == SPI_SHUTDOWN) return -ESHUTDOWN; - /* reject invalid messages and transfers */ - if (list_empty(&m->transfers) || !m->complete) - return -EINVAL; - - list_for_each_entry(t, &m->transfers, transfer_list) { - const void *tx_buf = t->tx_buf; - void *rx_buf = t->rx_buf; - unsigned len = t->len; - - if (t->speed_hz > OMAP1_SPI100K_MAX_FREQ - || (len && !(rx_buf || tx_buf))) { - dev_dbg(&spi->dev, "transfer: %d Hz, %d %s%s, %d bpw\n", - t->speed_hz, - len, - tx_buf ? "tx" : "", - rx_buf ? "rx" : "", - t->bits_per_word); - return -EINVAL; - } - - if (t->speed_hz && t->speed_hz < OMAP1_SPI100K_MAX_FREQ/(1<<16)) { - dev_dbg(&spi->dev, "%d Hz max exceeds %d\n", - t->speed_hz, - OMAP1_SPI100K_MAX_FREQ/(1<<16)); - return -EINVAL; - } - - } - spin_lock_irqsave(&spi100k->lock, flags); list_add_tail(&m->queue, &spi100k->msg_queue); queue_work(omap1_spi100k_wq, &spi100k->work); @@ -496,6 +466,8 @@ static int omap1_spi100k_probe(struct platform_device *pdev) master->num_chipselect = 2; master->mode_bits = MODEBITS; master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); + master->min_speed_hz = OMAP1_SPI100K_MAX_FREQ/(1<<16); + master->max_speed_hz = OMAP1_SPI100K_MAX_FREQ; platform_set_drvdata(pdev, master); From e8153ab3d7ab33aad872fd36f91a22a1071ceabf Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 10 Jul 2013 15:40:19 +0100 Subject: [PATCH 0142/3400] spi/omap-100k: Factor message transfer function out of work queue In preparation for removing the custom workqueue. Signed-off-by: Mark Brown --- drivers/spi/spi-omap-100k.c | 133 ++++++++++++++++++------------------ 1 file changed, 68 insertions(+), 65 deletions(-) diff --git a/drivers/spi/spi-omap-100k.c b/drivers/spi/spi-omap-100k.c index 3b42a4ba8fa2..5999285f4cbd 100644 --- a/drivers/spi/spi-omap-100k.c +++ b/drivers/spi/spi-omap-100k.c @@ -321,10 +321,76 @@ static int omap1_spi100k_setup(struct spi_device *spi) return ret; } +static int omap1_spi100k_transfer_one_message(struct spi_master *master, + struct spi_message *m) +{ + struct omap1_spi100k *spi100k = spi_master_get_devdata(master); + struct spi_device *spi = m->spi; + struct spi_transfer *t = NULL; + int cs_active = 0; + int par_override = 0; + int status = 0; + + list_for_each_entry(t, &m->transfers, transfer_list) { + if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) { + status = -EINVAL; + break; + } + if (par_override || t->speed_hz || t->bits_per_word) { + par_override = 1; + status = omap1_spi100k_setup_transfer(spi, t); + if (status < 0) + break; + if (!t->speed_hz && !t->bits_per_word) + par_override = 0; + } + + if (!cs_active) { + omap1_spi100k_force_cs(spi100k, 1); + cs_active = 1; + } + + if (t->len) { + unsigned count; + + count = omap1_spi100k_txrx_pio(spi, t); + m->actual_length += count; + + if (count != t->len) { + status = -EIO; + break; + } + } + + if (t->delay_usecs) + udelay(t->delay_usecs); + + /* ignore the "leave it on after last xfer" hint */ + + if (t->cs_change) { + omap1_spi100k_force_cs(spi100k, 0); + cs_active = 0; + } + } + + /* Restore defaults if they were overriden */ + if (par_override) { + par_override = 0; + status = omap1_spi100k_setup_transfer(spi, NULL); + } + + if (cs_active) + omap1_spi100k_force_cs(spi100k, 0); + + m->status = status; + m->complete(m->context); + + return status; +} + static void omap1_spi100k_work(struct work_struct *work) { struct omap1_spi100k *spi100k; - int status = 0; spi100k = container_of(work, struct omap1_spi100k, work); spin_lock_irq(&spi100k->lock); @@ -340,11 +406,6 @@ static void omap1_spi100k_work(struct work_struct *work) */ while (!list_empty(&spi100k->msg_queue)) { struct spi_message *m; - struct spi_device *spi; - struct spi_transfer *t = NULL; - int cs_active = 0; - struct omap1_spi100k_cs *cs; - int par_override = 0; m = container_of(spi100k->msg_queue.next, struct spi_message, queue); @@ -352,62 +413,7 @@ static void omap1_spi100k_work(struct work_struct *work) list_del_init(&m->queue); spin_unlock_irq(&spi100k->lock); - spi = m->spi; - cs = spi->controller_state; - - list_for_each_entry(t, &m->transfers, transfer_list) { - if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) { - status = -EINVAL; - break; - } - if (par_override || t->speed_hz || t->bits_per_word) { - par_override = 1; - status = omap1_spi100k_setup_transfer(spi, t); - if (status < 0) - break; - if (!t->speed_hz && !t->bits_per_word) - par_override = 0; - } - - if (!cs_active) { - omap1_spi100k_force_cs(spi100k, 1); - cs_active = 1; - } - - if (t->len) { - unsigned count; - - count = omap1_spi100k_txrx_pio(spi, t); - m->actual_length += count; - - if (count != t->len) { - status = -EIO; - break; - } - } - - if (t->delay_usecs) - udelay(t->delay_usecs); - - /* ignore the "leave it on after last xfer" hint */ - - if (t->cs_change) { - omap1_spi100k_force_cs(spi100k, 0); - cs_active = 0; - } - } - - /* Restore defaults if they were overriden */ - if (par_override) { - par_override = 0; - status = omap1_spi100k_setup_transfer(spi, NULL); - } - - if (cs_active) - omap1_spi100k_force_cs(spi100k, 0); - - m->status = status; - m->complete(m->context); + omap1_spi100k_transfer_one_message(m->spi->master, m); spin_lock_irq(&spi100k->lock); } @@ -415,9 +421,6 @@ static void omap1_spi100k_work(struct work_struct *work) clk_disable(spi100k->ick); clk_disable(spi100k->fck); spin_unlock_irq(&spi100k->lock); - - if (status < 0) - printk(KERN_WARNING "spi transfer failed with %d\n", status); } static int omap1_spi100k_transfer(struct spi_device *spi, struct spi_message *m) From da60b85506861b71db345f93bae72cbd8b51dcdd Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 10 Jul 2013 15:52:11 +0100 Subject: [PATCH 0143/3400] spi/omap-100k: Convert to use core message queue implementation Saves some code duplication and gets us the benefits of any improvements in the core code. Signed-off-by: Mark Brown --- drivers/spi/spi-omap-100k.c | 103 ++++++------------------------------ 1 file changed, 17 insertions(+), 86 deletions(-) diff --git a/drivers/spi/spi-omap-100k.c b/drivers/spi/spi-omap-100k.c index 5999285f4cbd..d4fcca9dc8e5 100644 --- a/drivers/spi/spi-omap-100k.c +++ b/drivers/spi/spi-omap-100k.c @@ -83,11 +83,6 @@ #define SPI_SHUTDOWN 1 struct omap1_spi100k { - struct work_struct work; - - /* lock protects queue and registers */ - spinlock_t lock; - struct list_head msg_queue; struct spi_master *master; struct clk *ick; struct clk *fck; @@ -104,8 +99,6 @@ struct omap1_spi100k_cs { int word_len; }; -static struct workqueue_struct *omap1_spi100k_wq; - #define MOD_REG_BIT(val, mask, set) do { \ if (set) \ val |= mask; \ @@ -321,6 +314,16 @@ static int omap1_spi100k_setup(struct spi_device *spi) return ret; } +static int omap1_spi100k_prepare_hardware(struct spi_master *master) +{ + struct omap1_spi100k *spi100k = spi_master_get_devdata(master); + + clk_enable(spi100k->ick); + clk_enable(spi100k->fck); + + return 0; +} + static int omap1_spi100k_transfer_one_message(struct spi_master *master, struct spi_message *m) { @@ -383,64 +386,18 @@ static int omap1_spi100k_transfer_one_message(struct spi_master *master, omap1_spi100k_force_cs(spi100k, 0); m->status = status; - m->complete(m->context); + + spi_finalize_current_message(master); return status; } -static void omap1_spi100k_work(struct work_struct *work) +static int omap1_spi100k_unprepare_hardware(struct spi_master *master) { - struct omap1_spi100k *spi100k; - - spi100k = container_of(work, struct omap1_spi100k, work); - spin_lock_irq(&spi100k->lock); - - clk_enable(spi100k->ick); - clk_enable(spi100k->fck); - - /* We only enable one channel at a time -- the one whose message is - * at the head of the queue -- although this controller would gladly - * arbitrate among multiple channels. This corresponds to "single - * channel" master mode. As a side effect, we need to manage the - * chipselect with the FORCE bit ... CS != channel enable. - */ - while (!list_empty(&spi100k->msg_queue)) { - struct spi_message *m; - - m = container_of(spi100k->msg_queue.next, struct spi_message, - queue); - - list_del_init(&m->queue); - spin_unlock_irq(&spi100k->lock); - - omap1_spi100k_transfer_one_message(m->spi->master, m); - - spin_lock_irq(&spi100k->lock); - } + struct omap1_spi100k *spi100k = spi_master_get_devdata(master); clk_disable(spi100k->ick); clk_disable(spi100k->fck); - spin_unlock_irq(&spi100k->lock); -} - -static int omap1_spi100k_transfer(struct spi_device *spi, struct spi_message *m) -{ - struct omap1_spi100k *spi100k; - unsigned long flags; - - m->actual_length = 0; - m->status = -EINPROGRESS; - - spi100k = spi_master_get_devdata(spi->master); - - /* Don't accept new work if we're shutting down */ - if (spi100k->state == SPI_SHUTDOWN) - return -ESHUTDOWN; - - spin_lock_irqsave(&spi100k->lock, flags); - list_add_tail(&m->queue, &spi100k->msg_queue); - queue_work(omap1_spi100k_wq, &spi100k->work); - spin_unlock_irqrestore(&spi100k->lock, flags); return 0; } @@ -464,7 +421,9 @@ static int omap1_spi100k_probe(struct platform_device *pdev) master->bus_num = pdev->id; master->setup = omap1_spi100k_setup; - master->transfer = omap1_spi100k_transfer; + master->transfer_one_message = omap1_spi100k_transfer_one_message; + master->prepare_transfer_hardware = omap1_spi100k_prepare_hardware; + master->unprepare_transfer_hardware = omap1_spi100k_unprepare_hardware; master->cleanup = NULL; master->num_chipselect = 2; master->mode_bits = MODEBITS; @@ -484,10 +443,6 @@ static int omap1_spi100k_probe(struct platform_device *pdev) */ spi100k->base = (void __iomem *) pdev->dev.platform_data; - INIT_WORK(&spi100k->work, omap1_spi100k_work); - - spin_lock_init(&spi100k->lock); - INIT_LIST_HEAD(&spi100k->msg_queue); spi100k->ick = clk_get(&pdev->dev, "ick"); if (IS_ERR(spi100k->ick)) { dev_dbg(&pdev->dev, "can't get spi100k_ick\n"); @@ -524,27 +479,11 @@ static int omap1_spi100k_remove(struct platform_device *pdev) struct spi_master *master; struct omap1_spi100k *spi100k; struct resource *r; - unsigned limit = 500; - unsigned long flags; int status = 0; master = platform_get_drvdata(pdev); spi100k = spi_master_get_devdata(master); - spin_lock_irqsave(&spi100k->lock, flags); - - spi100k->state = SPI_SHUTDOWN; - while (!list_empty(&spi100k->msg_queue) && limit--) { - spin_unlock_irqrestore(&spi100k->lock, flags); - msleep(10); - spin_lock_irqsave(&spi100k->lock, flags); - } - - if (!list_empty(&spi100k->msg_queue)) - status = -EBUSY; - - spin_unlock_irqrestore(&spi100k->lock, flags); - if (status != 0) return status; @@ -569,20 +508,12 @@ static struct platform_driver omap1_spi100k_driver = { static int __init omap1_spi100k_init(void) { - omap1_spi100k_wq = create_singlethread_workqueue( - omap1_spi100k_driver.driver.name); - - if (omap1_spi100k_wq == NULL) - return -1; - return platform_driver_probe(&omap1_spi100k_driver, omap1_spi100k_probe); } static void __exit omap1_spi100k_exit(void) { platform_driver_unregister(&omap1_spi100k_driver); - - destroy_workqueue(omap1_spi100k_wq); } module_init(omap1_spi100k_init); From 022a9412ec056026739c15df90e947b67d1b8222 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 10 Jul 2013 16:07:51 +0100 Subject: [PATCH 0144/3400] spi/omap-100k: Convert to devm_clk_get() Signed-off-by: Mark Brown --- drivers/spi/spi-omap-100k.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/drivers/spi/spi-omap-100k.c b/drivers/spi/spi-omap-100k.c index d4fcca9dc8e5..691ef3f199ff 100644 --- a/drivers/spi/spi-omap-100k.c +++ b/drivers/spi/spi-omap-100k.c @@ -443,33 +443,29 @@ static int omap1_spi100k_probe(struct platform_device *pdev) */ spi100k->base = (void __iomem *) pdev->dev.platform_data; - spi100k->ick = clk_get(&pdev->dev, "ick"); + spi100k->ick = devm_clk_get(&pdev->dev, "ick"); if (IS_ERR(spi100k->ick)) { dev_dbg(&pdev->dev, "can't get spi100k_ick\n"); status = PTR_ERR(spi100k->ick); - goto err1; + goto err; } - spi100k->fck = clk_get(&pdev->dev, "fck"); + spi100k->fck = devm_clk_get(&pdev->dev, "fck"); if (IS_ERR(spi100k->fck)) { dev_dbg(&pdev->dev, "can't get spi100k_fck\n"); status = PTR_ERR(spi100k->fck); - goto err2; + goto err; } status = spi_register_master(master); if (status < 0) - goto err3; + goto err; spi100k->state = SPI_RUNNING; return status; -err3: - clk_put(spi100k->fck); -err2: - clk_put(spi100k->ick); -err1: +err: spi_master_put(master); return status; } @@ -487,9 +483,6 @@ static int omap1_spi100k_remove(struct platform_device *pdev) if (status != 0) return status; - clk_put(spi100k->fck); - clk_put(spi100k->ick); - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); spi_unregister_master(master); From 13cd19e855437254fe38b8522584f3a0738b0884 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 10 Jul 2013 16:09:22 +0100 Subject: [PATCH 0145/3400] spi/omap-100k: Prepare and unprepare clocks Signed-off-by: Mark Brown --- drivers/spi/spi-omap-100k.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/spi/spi-omap-100k.c b/drivers/spi/spi-omap-100k.c index 691ef3f199ff..3590dd43837b 100644 --- a/drivers/spi/spi-omap-100k.c +++ b/drivers/spi/spi-omap-100k.c @@ -303,13 +303,13 @@ static int omap1_spi100k_setup(struct spi_device *spi) spi100k_open(spi->master); - clk_enable(spi100k->ick); - clk_enable(spi100k->fck); + clk_prepare_enable(spi100k->ick); + clk_prepare_enable(spi100k->fck); ret = omap1_spi100k_setup_transfer(spi, NULL); - clk_disable(spi100k->ick); - clk_disable(spi100k->fck); + clk_disable_unprepare(spi100k->ick); + clk_disable_unprepare(spi100k->fck); return ret; } @@ -318,8 +318,8 @@ static int omap1_spi100k_prepare_hardware(struct spi_master *master) { struct omap1_spi100k *spi100k = spi_master_get_devdata(master); - clk_enable(spi100k->ick); - clk_enable(spi100k->fck); + clk_prepare_enable(spi100k->ick); + clk_prepare_enable(spi100k->fck); return 0; } @@ -396,8 +396,8 @@ static int omap1_spi100k_unprepare_hardware(struct spi_master *master) { struct omap1_spi100k *spi100k = spi_master_get_devdata(master); - clk_disable(spi100k->ick); - clk_disable(spi100k->fck); + clk_disable_unprepare(spi100k->ick); + clk_disable_unprepare(spi100k->fck); return 0; } From 2d0c6148e381b81f8e6783d24b724963a86364cc Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 10 Jul 2013 16:10:33 +0100 Subject: [PATCH 0146/3400] spi/omap-100k: Convert to module_platform_driver() Signed-off-by: Mark Brown --- drivers/spi/spi-omap-100k.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/drivers/spi/spi-omap-100k.c b/drivers/spi/spi-omap-100k.c index 3590dd43837b..cdcc72c5d380 100644 --- a/drivers/spi/spi-omap-100k.c +++ b/drivers/spi/spi-omap-100k.c @@ -495,22 +495,11 @@ static struct platform_driver omap1_spi100k_driver = { .name = "omap1_spi100k", .owner = THIS_MODULE, }, + .probe = omap1_spi100k_probe, .remove = omap1_spi100k_remove, }; - -static int __init omap1_spi100k_init(void) -{ - return platform_driver_probe(&omap1_spi100k_driver, omap1_spi100k_probe); -} - -static void __exit omap1_spi100k_exit(void) -{ - platform_driver_unregister(&omap1_spi100k_driver); -} - -module_init(omap1_spi100k_init); -module_exit(omap1_spi100k_exit); +module_platform_driver(omap1_spi100k_driver); MODULE_DESCRIPTION("OMAP7xx SPI 100k controller driver"); MODULE_AUTHOR("Fabrice Crohas "); From 1de7061253a2742c743f3883f0e73480c9bceee0 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Wed, 3 Jul 2013 13:25:06 +0300 Subject: [PATCH 0147/3400] spi/pxa2xx: enable DMA on newer Intel LPSS silicon There is an additional bit in the Intel LPSS SPI private registers that needs to be set in order to be able to use DMA with the SPI controller. Enable this as well. Signed-off-by: Mika Westerberg Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index f440dcee852b..e0fd6f63c93e 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -69,6 +69,8 @@ MODULE_ALIAS("platform:pxa2xx-spi"); #define LPSS_TX_HITHRESH_DFLT 224 /* Offset from drv_data->lpss_base */ +#define GENERAL_REG 0x08 +#define GENERAL_REG_RXTO_HOLDOFF_DISABLE BIT(24) #define SSP_REG 0x0c #define SPI_CS_CONTROL 0x18 #define SPI_CS_CONTROL_SW_MODE BIT(0) @@ -142,8 +144,13 @@ detection_done: __lpss_ssp_write_priv(drv_data, SPI_CS_CONTROL, value); /* Enable multiblock DMA transfers */ - if (drv_data->master_info->enable_dma) + if (drv_data->master_info->enable_dma) { __lpss_ssp_write_priv(drv_data, SSP_REG, 1); + + value = __lpss_ssp_read_priv(drv_data, GENERAL_REG); + value |= GENERAL_REG_RXTO_HOLDOFF_DISABLE; + __lpss_ssp_write_priv(drv_data, GENERAL_REG, value); + } } static void lpss_ssp_cs_control(struct driver_data *drv_data, bool enable) From 9f4b323803ff18d87dcc042723b527ee646dddfc Mon Sep 17 00:00:00 2001 From: Girish K S Date: Thu, 27 Jun 2013 12:26:53 +0530 Subject: [PATCH 0148/3400] spi: s3c64xx: add missing check for polling mode Due to changes in mainline prior to submission the spi device detection in polling mode breaks. This revealed the missing check for polling during dma prepare. This patch adds the missing check. Signed-off-by: Girish K S Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index eb53df27e7ea..63e2070c6c14 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -434,6 +434,9 @@ static int s3c64xx_spi_prepare_transfer(struct spi_master *spi) dma_cap_mask_t mask; int ret; + if (is_polling(sdd)) + return 0; + dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); From 94b1f0dfa6dd8a3ed303cc7b0034b17e9cc34824 Mon Sep 17 00:00:00 2001 From: Qipan Li Date: Tue, 25 Jun 2013 19:45:29 +0800 Subject: [PATCH 0149/3400] spi: sirf: add missed spi mode_bits that SiRFSoC hardware supports Missing this will cause some user cases fail when they want to change spi transfer mode. Signed-off-by: Qipan Li Signed-off-by: Barry Song Signed-off-by: Mark Brown --- drivers/spi/spi-sirf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/spi/spi-sirf.c b/drivers/spi/spi-sirf.c index fc20bcfd90c3..96087169296e 100644 --- a/drivers/spi/spi-sirf.c +++ b/drivers/spi/spi-sirf.c @@ -538,6 +538,7 @@ static int spi_sirfsoc_probe(struct platform_device *pdev) sspi->bitbang.txrx_bufs = spi_sirfsoc_transfer; sspi->bitbang.master->setup = spi_sirfsoc_setup; master->bus_num = pdev->id; + master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_CS_HIGH; master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(12) | SPI_BPW_MASK(16) | SPI_BPW_MASK(32); sspi->bitbang.master->dev.of_node = pdev->dev.of_node; From 86562d04fc8212e2453d9714064a741a7d400da0 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 2 Jul 2013 08:37:44 +0800 Subject: [PATCH 0150/3400] spi: tegra114: remove redundant dev_err call in tegra_spi_probe() There is a error message within devm_ioremap_resource already, so remove the dev_err call to avoid redundant error message. Signed-off-by: Wei Yongjun Signed-off-by: Mark Brown --- drivers/spi/spi-tegra114.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index e8f542ab8935..8c99c00515c4 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -1068,7 +1068,6 @@ static int tegra_spi_probe(struct platform_device *pdev) tspi->base = devm_ioremap_resource(&pdev->dev, r); if (IS_ERR(tspi->base)) { ret = PTR_ERR(tspi->base); - dev_err(&pdev->dev, "ioremap failed: err = %d\n", ret); goto exit_free_master; } From cd4c424463b6051b0d3cac49a96389788c39bb35 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 10 Jul 2013 17:34:43 +0300 Subject: [PATCH 0151/3400] spi: tle62x0: dump small buffers using %*ph We have nice specifier in kernel for that. It changes separator from ',' (comma) to space, though it's not a big deal since it's just a debug message. Signed-off-by: Andy Shevchenko Signed-off-by: Mark Brown --- drivers/spi/spi-tle62x0.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/spi/spi-tle62x0.c b/drivers/spi/spi-tle62x0.c index 6b0874d782ed..3e528c0396e7 100644 --- a/drivers/spi/spi-tle62x0.c +++ b/drivers/spi/spi-tle62x0.c @@ -52,8 +52,7 @@ static inline int tle62x0_write(struct tle62x0_state *st) buff[1] = gpio_state; } - dev_dbg(&st->us->dev, "buff %02x,%02x,%02x\n", - buff[0], buff[1], buff[2]); + dev_dbg(&st->us->dev, "buff %3ph\n", buff); return spi_write(st->us, buff, (st->nr_gpio == 16) ? 3 : 2); } From c40537d008ab1b4fe2f12641cca1462de10a95f7 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 1 Jul 2013 20:33:01 +0100 Subject: [PATCH 0152/3400] spi/xilinx: Convert to devm_ioremap_resource() Saves code and reduces the possibility of error. Signed-off-by: Mark Brown --- drivers/spi/spi-xilinx.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c index fb56fcfdf65e..ad48710b2859 100644 --- a/drivers/spi/spi-xilinx.c +++ b/drivers/spi/spi-xilinx.c @@ -362,14 +362,10 @@ struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem, xspi->bitbang.txrx_bufs = xilinx_spi_txrx_bufs; init_completion(&xspi->done); - if (!request_mem_region(mem->start, resource_size(mem), - XILINX_SPI_NAME)) + xspi->regs = devm_ioremap_resource(dev, mem); + if (IS_ERR(xspi->regs)) { + ret = PTR_ERR(xspi->regs); goto put_master; - - xspi->regs = ioremap(mem->start, resource_size(mem)); - if (xspi->regs == NULL) { - dev_warn(dev, "ioremap failure\n"); - goto map_failed; } master->bus_num = bus_num; @@ -408,7 +404,7 @@ struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem, xspi->tx_fn = xspi_tx32; xspi->rx_fn = xspi_rx32; } else - goto unmap_io; + goto put_master; /* SPI controller initializations */ @@ -417,7 +413,7 @@ struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem, /* Register for SPI Interrupt */ ret = request_irq(xspi->irq, xilinx_spi_irq, 0, XILINX_SPI_NAME, xspi); if (ret) - goto unmap_io; + goto put_master; ret = spi_bitbang_start(&xspi->bitbang); if (ret) { @@ -431,10 +427,6 @@ struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem, free_irq: free_irq(xspi->irq, xspi); -unmap_io: - iounmap(xspi->regs); -map_failed: - release_mem_region(mem->start, resource_size(mem)); put_master: spi_master_put(master); return NULL; @@ -449,9 +441,7 @@ void xilinx_spi_deinit(struct spi_master *master) spi_bitbang_stop(&xspi->bitbang); free_irq(xspi->irq, xspi); - iounmap(xspi->regs); - release_mem_region(xspi->mem.start, resource_size(&xspi->mem)); spi_master_put(xspi->bitbang.master); } EXPORT_SYMBOL(xilinx_spi_deinit); From d81c0bbbf84086568b559bee59e4a93aba4a6e0f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 3 Jul 2013 12:05:42 +0100 Subject: [PATCH 0153/3400] spi/xilinx: Remove remains of of_platform device registration In the past there used to be a separate platform device type for device tree systems so the probe and removal functions were split into generic and bus sections. Since this is no longer the case simplify the code (and remove some unprototyped exports) by factoring everything into the bus probe() and remove(). Signed-off-by: Mark Brown --- drivers/spi/spi-xilinx.c | 147 +++++++++++++++++---------------------- 1 file changed, 64 insertions(+), 83 deletions(-) diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c index ad48710b2859..038e59a8bf0a 100644 --- a/drivers/spi/spi-xilinx.c +++ b/drivers/spi/spi-xilinx.c @@ -340,17 +340,51 @@ static const struct of_device_id xilinx_spi_of_match[] = { }; MODULE_DEVICE_TABLE(of, xilinx_spi_of_match); -struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem, - u32 irq, s16 bus_num, int num_cs, int bits_per_word) +static int xilinx_spi_probe(struct platform_device *dev) { - struct spi_master *master; struct xilinx_spi *xspi; - int ret; + struct xspi_platform_data *pdata; + struct resource *r; + int ret, irq, num_cs = 0, bits_per_word = 8; + struct spi_master *master; u32 tmp; + u8 i; - master = spi_alloc_master(dev, sizeof(struct xilinx_spi)); + pdata = dev->dev.platform_data; + if (pdata) { + num_cs = pdata->num_chipselect; + bits_per_word = pdata->bits_per_word; + } + +#ifdef CONFIG_OF + if (dev->dev.of_node) { + const __be32 *prop; + int len; + + /* number of slave select bits is required */ + prop = of_get_property(dev->dev.of_node, "xlnx,num-ss-bits", + &len); + if (prop && len >= sizeof(*prop)) + num_cs = __be32_to_cpup(prop); + } +#endif + + if (!num_cs) { + dev_err(&dev->dev, "Missing slave select configuration data\n"); + return -EINVAL; + } + + r = platform_get_resource(dev, IORESOURCE_MEM, 0); + if (!r) + return -ENODEV; + + irq = platform_get_irq(dev, 0); + if (irq < 0) + return -ENXIO; + + master = spi_alloc_master(&dev->dev, sizeof(struct xilinx_spi)); if (!master) - return NULL; + return -ENODEV; /* the spi->mode bits understood by this driver: */ master->mode_bits = SPI_CPOL | SPI_CPHA; @@ -362,17 +396,17 @@ struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem, xspi->bitbang.txrx_bufs = xilinx_spi_txrx_bufs; init_completion(&xspi->done); - xspi->regs = devm_ioremap_resource(dev, mem); + xspi->regs = devm_ioremap_resource(&dev->dev, r); if (IS_ERR(xspi->regs)) { ret = PTR_ERR(xspi->regs); goto put_master; } - master->bus_num = bus_num; + master->bus_num = dev->dev.id; master->num_chipselect = num_cs; - master->dev.of_node = dev->of_node; + master->dev.of_node = dev->dev.of_node; - xspi->mem = *mem; + xspi->mem = *r; xspi->irq = irq; /* @@ -403,8 +437,10 @@ struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem, } else if (xspi->bits_per_word == 32) { xspi->tx_fn = xspi_tx32; xspi->rx_fn = xspi_rx32; - } else + } else { + ret = -EINVAL; goto put_master; + } /* SPI controller initializations */ @@ -417,80 +453,12 @@ struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem, ret = spi_bitbang_start(&xspi->bitbang); if (ret) { - dev_err(dev, "spi_bitbang_start FAILED\n"); + dev_err(&dev->dev, "spi_bitbang_start FAILED\n"); goto free_irq; } - dev_info(dev, "at 0x%08llX mapped to 0x%p, irq=%d\n", - (unsigned long long)mem->start, xspi->regs, xspi->irq); - return master; - -free_irq: - free_irq(xspi->irq, xspi); -put_master: - spi_master_put(master); - return NULL; -} -EXPORT_SYMBOL(xilinx_spi_init); - -void xilinx_spi_deinit(struct spi_master *master) -{ - struct xilinx_spi *xspi; - - xspi = spi_master_get_devdata(master); - - spi_bitbang_stop(&xspi->bitbang); - free_irq(xspi->irq, xspi); - - spi_master_put(xspi->bitbang.master); -} -EXPORT_SYMBOL(xilinx_spi_deinit); - -static int xilinx_spi_probe(struct platform_device *dev) -{ - struct xspi_platform_data *pdata; - struct resource *r; - int irq, num_cs = 0, bits_per_word = 8; - struct spi_master *master; - u8 i; - - pdata = dev->dev.platform_data; - if (pdata) { - num_cs = pdata->num_chipselect; - bits_per_word = pdata->bits_per_word; - } - -#ifdef CONFIG_OF - if (dev->dev.of_node) { - const __be32 *prop; - int len; - - /* number of slave select bits is required */ - prop = of_get_property(dev->dev.of_node, "xlnx,num-ss-bits", - &len); - if (prop && len >= sizeof(*prop)) - num_cs = __be32_to_cpup(prop); - } -#endif - - if (!num_cs) { - dev_err(&dev->dev, "Missing slave select configuration data\n"); - return -EINVAL; - } - - - r = platform_get_resource(dev, IORESOURCE_MEM, 0); - if (!r) - return -ENODEV; - - irq = platform_get_irq(dev, 0); - if (irq < 0) - return -ENXIO; - - master = xilinx_spi_init(&dev->dev, r, irq, dev->id, num_cs, - bits_per_word); - if (!master) - return -ENODEV; + dev_info(&dev->dev, "at 0x%08llX mapped to 0x%p, irq=%d\n", + (unsigned long long)r->start, xspi->regs, xspi->irq); if (pdata) { for (i = 0; i < pdata->num_devices; i++) @@ -499,11 +467,24 @@ static int xilinx_spi_probe(struct platform_device *dev) platform_set_drvdata(dev, master); return 0; + +free_irq: + free_irq(xspi->irq, xspi); +put_master: + spi_master_put(master); + + return ret; } static int xilinx_spi_remove(struct platform_device *dev) { - xilinx_spi_deinit(platform_get_drvdata(dev)); + struct spi_master *master = platform_get_drvdata(dev); + struct xilinx_spi *xspi = spi_master_get_devdata(master); + + spi_bitbang_stop(&xspi->bitbang); + free_irq(xspi->irq, xspi); + + spi_master_put(xspi->bitbang.master); return 0; } From 7cb2abd05fe1f9aea70b8ee38004b60bc882ffb5 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 5 Jul 2013 11:24:26 +0100 Subject: [PATCH 0154/3400] spi/xilinx: Refer to platform device as pdev in probe() and remove() This is a more traditional name and makes things a bit clearer when referring to actual struct devices as we do frequently during probe(). Signed-off-by: Mark Brown Acked-by: Michal Simek --- drivers/spi/spi-xilinx.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c index 038e59a8bf0a..3026efa5a59f 100644 --- a/drivers/spi/spi-xilinx.c +++ b/drivers/spi/spi-xilinx.c @@ -340,7 +340,7 @@ static const struct of_device_id xilinx_spi_of_match[] = { }; MODULE_DEVICE_TABLE(of, xilinx_spi_of_match); -static int xilinx_spi_probe(struct platform_device *dev) +static int xilinx_spi_probe(struct platform_device *pdev) { struct xilinx_spi *xspi; struct xspi_platform_data *pdata; @@ -350,19 +350,19 @@ static int xilinx_spi_probe(struct platform_device *dev) u32 tmp; u8 i; - pdata = dev->dev.platform_data; + pdata = pdev->dev.platform_data; if (pdata) { num_cs = pdata->num_chipselect; bits_per_word = pdata->bits_per_word; } #ifdef CONFIG_OF - if (dev->dev.of_node) { + if (pdev->dev.of_node) { const __be32 *prop; int len; /* number of slave select bits is required */ - prop = of_get_property(dev->dev.of_node, "xlnx,num-ss-bits", + prop = of_get_property(pdev->dev.of_node, "xlnx,num-ss-bits", &len); if (prop && len >= sizeof(*prop)) num_cs = __be32_to_cpup(prop); @@ -370,19 +370,20 @@ static int xilinx_spi_probe(struct platform_device *dev) #endif if (!num_cs) { - dev_err(&dev->dev, "Missing slave select configuration data\n"); + dev_err(&pdev->dev, + "Missing slave select configuration data\n"); return -EINVAL; } - r = platform_get_resource(dev, IORESOURCE_MEM, 0); + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!r) return -ENODEV; - irq = platform_get_irq(dev, 0); + irq = platform_get_irq(pdev, 0); if (irq < 0) return -ENXIO; - master = spi_alloc_master(&dev->dev, sizeof(struct xilinx_spi)); + master = spi_alloc_master(&pdev->dev, sizeof(struct xilinx_spi)); if (!master) return -ENODEV; @@ -396,15 +397,15 @@ static int xilinx_spi_probe(struct platform_device *dev) xspi->bitbang.txrx_bufs = xilinx_spi_txrx_bufs; init_completion(&xspi->done); - xspi->regs = devm_ioremap_resource(&dev->dev, r); + xspi->regs = devm_ioremap_resource(&pdev->dev, r); if (IS_ERR(xspi->regs)) { ret = PTR_ERR(xspi->regs); goto put_master; } - master->bus_num = dev->dev.id; + master->bus_num = pdev->dev.id; master->num_chipselect = num_cs; - master->dev.of_node = dev->dev.of_node; + master->dev.of_node = pdev->dev.of_node; xspi->mem = *r; xspi->irq = irq; @@ -453,11 +454,11 @@ static int xilinx_spi_probe(struct platform_device *dev) ret = spi_bitbang_start(&xspi->bitbang); if (ret) { - dev_err(&dev->dev, "spi_bitbang_start FAILED\n"); + dev_err(&pdev->dev, "spi_bitbang_start FAILED\n"); goto free_irq; } - dev_info(&dev->dev, "at 0x%08llX mapped to 0x%p, irq=%d\n", + dev_info(&pdev->dev, "at 0x%08llX mapped to 0x%p, irq=%d\n", (unsigned long long)r->start, xspi->regs, xspi->irq); if (pdata) { @@ -465,7 +466,7 @@ static int xilinx_spi_probe(struct platform_device *dev) spi_new_device(master, pdata->devices + i); } - platform_set_drvdata(dev, master); + platform_set_drvdata(pdev, master); return 0; free_irq: @@ -476,9 +477,9 @@ put_master: return ret; } -static int xilinx_spi_remove(struct platform_device *dev) +static int xilinx_spi_remove(struct platform_device *pdev) { - struct spi_master *master = platform_get_drvdata(dev); + struct spi_master *master = platform_get_drvdata(pdev); struct xilinx_spi *xspi = spi_master_get_devdata(master); spi_bitbang_stop(&xspi->bitbang); From 5586c09e19b0dea5c1b4fd9838ca73575def223f Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 8 Jul 2013 15:29:14 +0200 Subject: [PATCH 0155/3400] spi/xilinx: Remove CONFIG_OF from the driver dev.of_node is in struct device all the time. Signed-off-by: Michal Simek Signed-off-by: Mark Brown --- drivers/spi/spi-xilinx.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c index 3026efa5a59f..2e1d8a4ac375 100644 --- a/drivers/spi/spi-xilinx.c +++ b/drivers/spi/spi-xilinx.c @@ -356,7 +356,6 @@ static int xilinx_spi_probe(struct platform_device *pdev) bits_per_word = pdata->bits_per_word; } -#ifdef CONFIG_OF if (pdev->dev.of_node) { const __be32 *prop; int len; @@ -367,7 +366,6 @@ static int xilinx_spi_probe(struct platform_device *pdev) if (prop && len >= sizeof(*prop)) num_cs = __be32_to_cpup(prop); } -#endif if (!num_cs) { dev_err(&pdev->dev, From ad3fdbcaf98dc1258f7ee1503703e7fcbc0d8d8e Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 8 Jul 2013 15:29:15 +0200 Subject: [PATCH 0156/3400] spi/xilinx: Clean ioremap calling devm_ioremap_resource() automatically checks that struct resource is initialized. Also group platform_get_resource() and devm_ioremap_resource() together. And remove mem resource from struct xilinx_spi. Signed-off-by: Michal Simek Signed-off-by: Mark Brown --- drivers/spi/spi-xilinx.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c index 2e1d8a4ac375..a9b99a997f91 100644 --- a/drivers/spi/spi-xilinx.c +++ b/drivers/spi/spi-xilinx.c @@ -80,7 +80,6 @@ struct xilinx_spi { /* bitbang has to be first */ struct spi_bitbang bitbang; struct completion done; - struct resource mem; /* phys mem */ void __iomem *regs; /* virt. address of the control registers */ u32 irq; @@ -344,7 +343,7 @@ static int xilinx_spi_probe(struct platform_device *pdev) { struct xilinx_spi *xspi; struct xspi_platform_data *pdata; - struct resource *r; + struct resource *res; int ret, irq, num_cs = 0, bits_per_word = 8; struct spi_master *master; u32 tmp; @@ -373,10 +372,6 @@ static int xilinx_spi_probe(struct platform_device *pdev) return -EINVAL; } - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!r) - return -ENODEV; - irq = platform_get_irq(pdev, 0); if (irq < 0) return -ENXIO; @@ -395,7 +390,8 @@ static int xilinx_spi_probe(struct platform_device *pdev) xspi->bitbang.txrx_bufs = xilinx_spi_txrx_bufs; init_completion(&xspi->done); - xspi->regs = devm_ioremap_resource(&pdev->dev, r); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + xspi->regs = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(xspi->regs)) { ret = PTR_ERR(xspi->regs); goto put_master; @@ -405,7 +401,6 @@ static int xilinx_spi_probe(struct platform_device *pdev) master->num_chipselect = num_cs; master->dev.of_node = pdev->dev.of_node; - xspi->mem = *r; xspi->irq = irq; /* @@ -457,7 +452,7 @@ static int xilinx_spi_probe(struct platform_device *pdev) } dev_info(&pdev->dev, "at 0x%08llX mapped to 0x%p, irq=%d\n", - (unsigned long long)r->start, xspi->regs, xspi->irq); + (unsigned long long)res->start, xspi->regs, xspi->irq); if (pdata) { for (i = 0; i < pdata->num_devices; i++) From be3acdff943f46c32e9b2f453f0033bbae01a804 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 8 Jul 2013 15:29:17 +0200 Subject: [PATCH 0157/3400] spi/xilinx: Use of_property_read_u32 for reading value from node It simplifies driver probing. Signed-off-by: Michal Simek Signed-off-by: Mark Brown --- drivers/spi/spi-xilinx.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c index a9b99a997f91..0b23408d357c 100644 --- a/drivers/spi/spi-xilinx.c +++ b/drivers/spi/spi-xilinx.c @@ -353,17 +353,9 @@ static int xilinx_spi_probe(struct platform_device *pdev) if (pdata) { num_cs = pdata->num_chipselect; bits_per_word = pdata->bits_per_word; - } - - if (pdev->dev.of_node) { - const __be32 *prop; - int len; - - /* number of slave select bits is required */ - prop = of_get_property(pdev->dev.of_node, "xlnx,num-ss-bits", - &len); - if (prop && len >= sizeof(*prop)) - num_cs = __be32_to_cpup(prop); + } else { + of_property_read_u32(pdev->dev.of_node, "xlnx,num-ss-bits", + &num_cs); } if (!num_cs) { From 7b3b7432ae7848a269671921393148ff1aae3881 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 9 Jul 2013 18:05:16 +0200 Subject: [PATCH 0158/3400] spi/xilinx: Simplify irq allocation Use devm_request_irq() for irq allocation which simplify driver code. Signed-off-by: Michal Simek Signed-off-by: Mark Brown --- drivers/spi/spi-xilinx.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c index 0b23408d357c..e5d3716da21a 100644 --- a/drivers/spi/spi-xilinx.c +++ b/drivers/spi/spi-xilinx.c @@ -344,7 +344,7 @@ static int xilinx_spi_probe(struct platform_device *pdev) struct xilinx_spi *xspi; struct xspi_platform_data *pdata; struct resource *res; - int ret, irq, num_cs = 0, bits_per_word = 8; + int ret, num_cs = 0, bits_per_word = 8; struct spi_master *master; u32 tmp; u8 i; @@ -364,10 +364,6 @@ static int xilinx_spi_probe(struct platform_device *pdev) return -EINVAL; } - irq = platform_get_irq(pdev, 0); - if (irq < 0) - return -ENXIO; - master = spi_alloc_master(&pdev->dev, sizeof(struct xilinx_spi)); if (!master) return -ENODEV; @@ -393,8 +389,6 @@ static int xilinx_spi_probe(struct platform_device *pdev) master->num_chipselect = num_cs; master->dev.of_node = pdev->dev.of_node; - xspi->irq = irq; - /* * Detect endianess on the IP via loop bit in CR. Detection * must be done before reset is sent because incorrect reset @@ -428,19 +422,25 @@ static int xilinx_spi_probe(struct platform_device *pdev) goto put_master; } - /* SPI controller initializations */ xspi_init_hw(xspi); + xspi->irq = platform_get_irq(pdev, 0); + if (xspi->irq < 0) { + ret = xspi->irq; + goto put_master; + } + /* Register for SPI Interrupt */ - ret = request_irq(xspi->irq, xilinx_spi_irq, 0, XILINX_SPI_NAME, xspi); + ret = devm_request_irq(&pdev->dev, xspi->irq, xilinx_spi_irq, 0, + dev_name(&pdev->dev), xspi); if (ret) goto put_master; ret = spi_bitbang_start(&xspi->bitbang); if (ret) { dev_err(&pdev->dev, "spi_bitbang_start FAILED\n"); - goto free_irq; + goto put_master; } dev_info(&pdev->dev, "at 0x%08llX mapped to 0x%p, irq=%d\n", @@ -454,8 +454,6 @@ static int xilinx_spi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, master); return 0; -free_irq: - free_irq(xspi->irq, xspi); put_master: spi_master_put(master); @@ -466,9 +464,14 @@ static int xilinx_spi_remove(struct platform_device *pdev) { struct spi_master *master = platform_get_drvdata(pdev); struct xilinx_spi *xspi = spi_master_get_devdata(master); + void __iomem *regs_base = xspi->regs; spi_bitbang_stop(&xspi->bitbang); - free_irq(xspi->irq, xspi); + + /* Disable all the interrupts just in case */ + xspi->write_fn(0, regs_base + XIPIF_V123B_IIER_OFFSET); + /* Disable the global IPIF interrupt */ + xspi->write_fn(0, regs_base + XIPIF_V123B_DGIER_OFFSET); spi_master_put(xspi->bitbang.master); From 1696d9dc57e062ce5200f6a42a6aaada15b434bb Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Mon, 15 Jul 2013 10:15:09 +0200 Subject: [PATCH 0159/3400] ACPI: Remove the old /proc/acpi/event interface It is quite some time that this one has been deprecated. Get rid of it. Should some really important user be overseen, it may be reverted and the userspace program worked on first, but it is time to do something to get rid of this old stuff... Signed-off-by: Thomas Renninger Acked-by: Matthew Garrett Acked-by: Henrique de Moraes Holschuh Signed-off-by: Rafael J. Wysocki --- Documentation/laptops/asus-laptop.txt | 8 +- Documentation/laptops/sony-laptop.txt | 8 +- drivers/acpi/Kconfig | 18 ---- drivers/acpi/ac.c | 1 - drivers/acpi/acpi_pad.c | 1 - drivers/acpi/battery.c | 2 - drivers/acpi/bus.c | 98 ---------------------- drivers/acpi/button.c | 2 - drivers/acpi/event.c | 106 ------------------------ drivers/acpi/processor_driver.c | 4 - drivers/acpi/sbs.c | 15 +--- drivers/acpi/thermal.c | 3 - drivers/acpi/video.c | 10 --- drivers/char/sonypi.c | 5 -- drivers/pci/hotplug/acpiphp_ibm.c | 1 - drivers/platform/x86/asus-laptop.c | 1 - drivers/platform/x86/eeepc-laptop.c | 1 - drivers/platform/x86/fujitsu-laptop.c | 4 - drivers/platform/x86/panasonic-laptop.c | 3 - drivers/platform/x86/sony-laptop.c | 4 - drivers/platform/x86/thinkpad_acpi.c | 11 --- include/acpi/acpi_bus.h | 9 -- 22 files changed, 10 insertions(+), 305 deletions(-) diff --git a/Documentation/laptops/asus-laptop.txt b/Documentation/laptops/asus-laptop.txt index 69f9fb3701e0..79a1bc675a8d 100644 --- a/Documentation/laptops/asus-laptop.txt +++ b/Documentation/laptops/asus-laptop.txt @@ -8,8 +8,8 @@ http://acpi4asus.sf.net/ This driver provides support for extra features of ACPI-compatible ASUS laptops. It may also support some MEDION, JVC or VICTOR laptops (such as MEDION 9675 or - VICTOR XP7210 for example). It makes all the extra buttons generate standard - ACPI events that go through /proc/acpi/events and input events (like keyboards). + VICTOR XP7210 for example). It makes all the extra buttons generate input + events (like keyboards). On some models adds support for changing the display brightness and output, switching the LCD backlight on and off, and most importantly, allows you to blink those fancy LEDs intended for reporting mail and wireless status. @@ -55,8 +55,8 @@ Usage DSDT) to me. That's all, now, all the events generated by the hotkeys of your laptop - should be reported in your /proc/acpi/event entry. You can check with - "acpi_listen". + should be reported via netlink events. You can check with + "acpi_genl monitor" (part of the acpica project). Hotkeys are also reported as input keys (like keyboards) you can check which key are supported using "xev" under X11. diff --git a/Documentation/laptops/sony-laptop.txt b/Documentation/laptops/sony-laptop.txt index 0d5ac7f5287e..978b1e615155 100644 --- a/Documentation/laptops/sony-laptop.txt +++ b/Documentation/laptops/sony-laptop.txt @@ -12,10 +12,10 @@ Fn keys (hotkeys): ------------------ Some models report hotkeys through the SNC or SPIC devices, such events are reported both through the ACPI subsystem as acpi events and through the INPUT -subsystem. See the logs of acpid or /proc/acpi/event and -/proc/bus/input/devices to find out what those events are and which input -devices are created by the driver. Additionally, loading the driver with the -debug option will report all events in the kernel log. +subsystem. See the logs of /proc/bus/input/devices to find out what those +events are and which input devices are created by the driver. +Additionally, loading the driver with the debug option will report all events +in the kernel log. The "scancodes" passed to the input system (that can be remapped with udev) are indexes to the table "sony_laptop_input_keycode_map" in the sony-laptop.c diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 100bd724f648..3278a210c435 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -91,24 +91,6 @@ config ACPI_EC_DEBUGFS Thus this option is a debug option that helps to write ACPI drivers and can be used to identify ACPI code or EC firmware bugs. -config ACPI_PROC_EVENT - bool "Deprecated /proc/acpi/event support" - depends on PROC_FS - default y - help - A user-space daemon, acpid, typically reads /proc/acpi/event - and handles all ACPI-generated events. - - These events are now delivered to user-space either - via the input layer or as netlink events. - - This build option enables the old code for legacy - user-space implementation. After some time, this will - be moved under CONFIG_ACPI_PROCFS, and then deleted. - - Say Y here to retain the old behaviour. Say N if your - user-space is newer than kernel 2.6.23 (September 2007). - config ACPI_AC tristate "AC Adapter" depends on X86 diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index 4f4e741d34b2..f37beaa32750 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -267,7 +267,6 @@ static void acpi_ac_notify(struct acpi_device *device, u32 event) msleep(ac_sleep_before_get_state_ms); acpi_ac_get_state(ac); - acpi_bus_generate_proc_event(device, event, (u32) ac->state); acpi_bus_generate_netlink_event(device->pnp.device_class, dev_name(&device->dev), event, (u32) ac->state); diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c index 27bb6a91de5f..6230637054c6 100644 --- a/drivers/acpi/acpi_pad.c +++ b/drivers/acpi/acpi_pad.c @@ -452,7 +452,6 @@ static void acpi_pad_notify(acpi_handle handle, u32 event, switch (event) { case ACPI_PROCESSOR_AGGREGATOR_NOTIFY: acpi_pad_handle_notify(handle); - acpi_bus_generate_proc_event(device, event, 0); acpi_bus_generate_netlink_event(device->pnp.device_class, dev_name(&device->dev), event, 0); break; diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 082b4dd252a8..33dfa851899d 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -1034,8 +1034,6 @@ static void acpi_battery_notify(struct acpi_device *device, u32 event) if (event == ACPI_BATTERY_NOTIFY_INFO) acpi_battery_refresh(battery); acpi_battery_update(battery); - acpi_bus_generate_proc_event(device, event, - acpi_battery_present(battery)); acpi_bus_generate_netlink_event(device->pnp.device_class, dev_name(&device->dev), event, acpi_battery_present(battery)); diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index a5bb33bab448..b6e9a3786e2d 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -345,104 +345,6 @@ static void acpi_bus_osc_support(void) /* do we need to check other returned cap? Sounds no */ } -/* -------------------------------------------------------------------------- - Event Management - -------------------------------------------------------------------------- */ - -#ifdef CONFIG_ACPI_PROC_EVENT -static DEFINE_SPINLOCK(acpi_bus_event_lock); - -LIST_HEAD(acpi_bus_event_list); -DECLARE_WAIT_QUEUE_HEAD(acpi_bus_event_queue); - -extern int event_is_open; - -int acpi_bus_generate_proc_event4(const char *device_class, const char *bus_id, u8 type, int data) -{ - struct acpi_bus_event *event; - unsigned long flags; - - /* drop event on the floor if no one's listening */ - if (!event_is_open) - return 0; - - event = kzalloc(sizeof(struct acpi_bus_event), GFP_ATOMIC); - if (!event) - return -ENOMEM; - - strcpy(event->device_class, device_class); - strcpy(event->bus_id, bus_id); - event->type = type; - event->data = data; - - spin_lock_irqsave(&acpi_bus_event_lock, flags); - list_add_tail(&event->node, &acpi_bus_event_list); - spin_unlock_irqrestore(&acpi_bus_event_lock, flags); - - wake_up_interruptible(&acpi_bus_event_queue); - - return 0; - -} - -EXPORT_SYMBOL_GPL(acpi_bus_generate_proc_event4); - -int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data) -{ - if (!device) - return -EINVAL; - return acpi_bus_generate_proc_event4(device->pnp.device_class, - device->pnp.bus_id, type, data); -} - -EXPORT_SYMBOL(acpi_bus_generate_proc_event); - -int acpi_bus_receive_event(struct acpi_bus_event *event) -{ - unsigned long flags; - struct acpi_bus_event *entry = NULL; - - DECLARE_WAITQUEUE(wait, current); - - - if (!event) - return -EINVAL; - - if (list_empty(&acpi_bus_event_list)) { - - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&acpi_bus_event_queue, &wait); - - if (list_empty(&acpi_bus_event_list)) - schedule(); - - remove_wait_queue(&acpi_bus_event_queue, &wait); - set_current_state(TASK_RUNNING); - - if (signal_pending(current)) - return -ERESTARTSYS; - } - - spin_lock_irqsave(&acpi_bus_event_lock, flags); - if (!list_empty(&acpi_bus_event_list)) { - entry = list_entry(acpi_bus_event_list.next, - struct acpi_bus_event, node); - list_del(&entry->node); - } - spin_unlock_irqrestore(&acpi_bus_event_lock, flags); - - if (!entry) - return -ENODEV; - - memcpy(event, entry, sizeof(struct acpi_bus_event)); - - kfree(entry); - - return 0; -} - -#endif /* CONFIG_ACPI_PROC_EVENT */ - /* -------------------------------------------------------------------------- Notification Handling -------------------------------------------------------------------------- */ diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index d2e617b5b3f6..a55773801c5f 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -303,8 +303,6 @@ static void acpi_button_notify(struct acpi_device *device, u32 event) pm_wakeup_event(&device->dev, 0); } - - acpi_bus_generate_proc_event(device, event, ++button->pushed); break; default: ACPI_DEBUG_PRINT((ACPI_DB_INFO, diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c index 1442737cedec..8247fcdde079 100644 --- a/drivers/acpi/event.c +++ b/drivers/acpi/event.c @@ -21,100 +21,6 @@ #define _COMPONENT ACPI_SYSTEM_COMPONENT ACPI_MODULE_NAME("event"); -#ifdef CONFIG_ACPI_PROC_EVENT -/* Global vars for handling event proc entry */ -static DEFINE_SPINLOCK(acpi_system_event_lock); -int event_is_open = 0; -extern struct list_head acpi_bus_event_list; -extern wait_queue_head_t acpi_bus_event_queue; - -static int acpi_system_open_event(struct inode *inode, struct file *file) -{ - spin_lock_irq(&acpi_system_event_lock); - - if (event_is_open) - goto out_busy; - - event_is_open = 1; - - spin_unlock_irq(&acpi_system_event_lock); - return 0; - - out_busy: - spin_unlock_irq(&acpi_system_event_lock); - return -EBUSY; -} - -static ssize_t -acpi_system_read_event(struct file *file, char __user * buffer, size_t count, - loff_t * ppos) -{ - int result = 0; - struct acpi_bus_event event; - static char str[ACPI_MAX_STRING]; - static int chars_remaining = 0; - static char *ptr; - - if (!chars_remaining) { - memset(&event, 0, sizeof(struct acpi_bus_event)); - - if ((file->f_flags & O_NONBLOCK) - && (list_empty(&acpi_bus_event_list))) - return -EAGAIN; - - result = acpi_bus_receive_event(&event); - if (result) - return result; - - chars_remaining = sprintf(str, "%s %s %08x %08x\n", - event.device_class ? event. - device_class : "", - event.bus_id ? event. - bus_id : "", event.type, - event.data); - ptr = str; - } - - if (chars_remaining < count) { - count = chars_remaining; - } - - if (copy_to_user(buffer, ptr, count)) - return -EFAULT; - - *ppos += count; - chars_remaining -= count; - ptr += count; - - return count; -} - -static int acpi_system_close_event(struct inode *inode, struct file *file) -{ - spin_lock_irq(&acpi_system_event_lock); - event_is_open = 0; - spin_unlock_irq(&acpi_system_event_lock); - return 0; -} - -static unsigned int acpi_system_poll_event(struct file *file, poll_table * wait) -{ - poll_wait(file, &acpi_bus_event_queue, wait); - if (!list_empty(&acpi_bus_event_list)) - return POLLIN | POLLRDNORM; - return 0; -} - -static const struct file_operations acpi_system_event_ops = { - .owner = THIS_MODULE, - .open = acpi_system_open_event, - .read = acpi_system_read_event, - .release = acpi_system_close_event, - .poll = acpi_system_poll_event, - .llseek = default_llseek, -}; -#endif /* CONFIG_ACPI_PROC_EVENT */ - /* ACPI notifier chain */ static BLOCKING_NOTIFIER_HEAD(acpi_chain_head); @@ -280,9 +186,6 @@ static int acpi_event_genetlink_init(void) static int __init acpi_event_init(void) { -#ifdef CONFIG_ACPI_PROC_EVENT - struct proc_dir_entry *entry; -#endif int error = 0; if (acpi_disabled) @@ -293,15 +196,6 @@ static int __init acpi_event_init(void) if (error) printk(KERN_WARNING PREFIX "Failed to create genetlink family for ACPI event\n"); - -#ifdef CONFIG_ACPI_PROC_EVENT - /* 'event' [R] */ - entry = proc_create("event", S_IRUSR, acpi_root_dir, - &acpi_system_event_ops); - if (!entry) - return -ENODEV; -#endif - return 0; } diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index 823be116619e..94b7b3b5559e 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -91,21 +91,17 @@ static void acpi_processor_notify(acpi_handle handle, u32 event, void *data) acpi_processor_ppc_has_changed(pr, 1); if (saved == pr->performance_platform_limit) break; - acpi_bus_generate_proc_event(device, event, - pr->performance_platform_limit); acpi_bus_generate_netlink_event(device->pnp.device_class, dev_name(&device->dev), event, pr->performance_platform_limit); break; case ACPI_PROCESSOR_NOTIFY_POWER: acpi_processor_cst_has_changed(pr); - acpi_bus_generate_proc_event(device, event, 0); acpi_bus_generate_netlink_event(device->pnp.device_class, dev_name(&device->dev), event, 0); break; case ACPI_PROCESSOR_NOTIFY_THROTTLING: acpi_processor_tstate_has_changed(pr); - acpi_bus_generate_proc_event(device, event, 0); acpi_bus_generate_netlink_event(device->pnp.device_class, dev_name(&device->dev), event, 0); break; diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index b6241eeb1132..aef7e1cd1e5d 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -873,14 +873,9 @@ static void acpi_sbs_callback(void *context) u8 saved_charger_state = sbs->charger_present; u8 saved_battery_state; acpi_ac_get_present(sbs); - if (sbs->charger_present != saved_charger_state) { -#ifdef CONFIG_ACPI_PROC_EVENT - acpi_bus_generate_proc_event4(ACPI_AC_CLASS, ACPI_AC_DIR_NAME, - ACPI_SBS_NOTIFY_STATUS, - sbs->charger_present); -#endif + if (sbs->charger_present != saved_charger_state) kobject_uevent(&sbs->charger.dev->kobj, KOBJ_CHANGE); - } + if (sbs->manager_present) { for (id = 0; id < MAX_SBS_BAT; ++id) { if (!(sbs->batteries_supported & (1 << id))) @@ -890,12 +885,6 @@ static void acpi_sbs_callback(void *context) acpi_battery_read(bat); if (saved_battery_state == bat->present) continue; -#ifdef CONFIG_ACPI_PROC_EVENT - acpi_bus_generate_proc_event4(ACPI_BATTERY_CLASS, - bat->name, - ACPI_SBS_NOTIFY_STATUS, - bat->present); -#endif kobject_uevent(&bat->bat.dev->kobj, KOBJ_CHANGE); } } diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index a33821ca3895..547a906a7662 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -769,7 +769,6 @@ static int thermal_notify(struct thermal_zone_device *thermal, int trip, else return 0; - acpi_bus_generate_proc_event(tz->device, type, 1); acpi_bus_generate_netlink_event(tz->device->pnp.device_class, dev_name(&tz->device->dev), type, 1); @@ -980,14 +979,12 @@ static void acpi_thermal_notify(struct acpi_device *device, u32 event) case ACPI_THERMAL_NOTIFY_THRESHOLDS: acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_THRESHOLDS); acpi_thermal_check(tz); - acpi_bus_generate_proc_event(device, event, 0); acpi_bus_generate_netlink_event(device->pnp.device_class, dev_name(&device->dev), event, 0); break; case ACPI_THERMAL_NOTIFY_DEVICES: acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_DEVICES); acpi_thermal_check(tz); - acpi_bus_generate_proc_event(device, event, 0); acpi_bus_generate_netlink_event(device->pnp.device_class, dev_name(&device->dev), event, 0); break; diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 5d7075d25700..8f91a3783191 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -1556,7 +1556,6 @@ static void acpi_video_bus_notify(struct acpi_device *device, u32 event) switch (event) { case ACPI_VIDEO_NOTIFY_SWITCH: /* User requested a switch, * most likely via hotkey. */ - acpi_bus_generate_proc_event(device, event, 0); keycode = KEY_SWITCHVIDEOMODE; break; @@ -1564,20 +1563,16 @@ static void acpi_video_bus_notify(struct acpi_device *device, u32 event) * connector. */ acpi_video_device_enumerate(video); acpi_video_device_rebind(video); - acpi_bus_generate_proc_event(device, event, 0); keycode = KEY_SWITCHVIDEOMODE; break; case ACPI_VIDEO_NOTIFY_CYCLE: /* Cycle Display output hotkey pressed. */ - acpi_bus_generate_proc_event(device, event, 0); keycode = KEY_SWITCHVIDEOMODE; break; case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT: /* Next Display output hotkey pressed. */ - acpi_bus_generate_proc_event(device, event, 0); keycode = KEY_VIDEO_NEXT; break; case ACPI_VIDEO_NOTIFY_PREV_OUTPUT: /* previous Display output hotkey pressed. */ - acpi_bus_generate_proc_event(device, event, 0); keycode = KEY_VIDEO_PREV; break; @@ -1620,31 +1615,26 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data) case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS: /* Cycle brightness */ if (brightness_switch_enabled) acpi_video_switch_brightness(video_device, event); - acpi_bus_generate_proc_event(device, event, 0); keycode = KEY_BRIGHTNESS_CYCLE; break; case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS: /* Increase brightness */ if (brightness_switch_enabled) acpi_video_switch_brightness(video_device, event); - acpi_bus_generate_proc_event(device, event, 0); keycode = KEY_BRIGHTNESSUP; break; case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS: /* Decrease brightness */ if (brightness_switch_enabled) acpi_video_switch_brightness(video_device, event); - acpi_bus_generate_proc_event(device, event, 0); keycode = KEY_BRIGHTNESSDOWN; break; case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightness */ if (brightness_switch_enabled) acpi_video_switch_brightness(video_device, event); - acpi_bus_generate_proc_event(device, event, 0); keycode = KEY_BRIGHTNESS_ZERO; break; case ACPI_VIDEO_NOTIFY_DISPLAY_OFF: /* display device off */ if (brightness_switch_enabled) acpi_video_switch_brightness(video_device, event); - acpi_bus_generate_proc_event(device, event, 0); keycode = KEY_DISPLAY_OFF; break; default: diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index bf2349dbbf7f..7cc1fe2241fd 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c @@ -876,11 +876,6 @@ found: if (useinput) sonypi_report_input_event(event); -#ifdef CONFIG_ACPI - if (sonypi_acpi_device) - acpi_bus_generate_proc_event(sonypi_acpi_device, 1, event); -#endif - kfifo_in_locked(&sonypi_device.fifo, (unsigned char *)&event, sizeof(event), &sonypi_device.fifo_lock); kill_fasync(&sonypi_device.fifo_async, SIGIO, POLL_IN); diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c index c35e8ad6db01..5394fffdf167 100644 --- a/drivers/pci/hotplug/acpiphp_ibm.c +++ b/drivers/pci/hotplug/acpiphp_ibm.c @@ -270,7 +270,6 @@ static void ibm_handle_events(acpi_handle handle, u32 event, void *context) if (subevent == 0x80) { dbg("%s: generationg bus event\n", __func__); - acpi_bus_generate_proc_event(note->device, note->event, detail); acpi_bus_generate_netlink_event(note->device->pnp.device_class, dev_name(¬e->device->dev), note->event, detail); diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 8e268da6fdbd..0e9c169b42f8 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -1543,7 +1543,6 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event) /* TODO Find a better way to handle events count. */ count = asus->event_count[event % 128]++; - acpi_bus_generate_proc_event(asus->device, event, count); acpi_bus_generate_netlink_event(asus->device->pnp.device_class, dev_name(&asus->device->dev), event, count); diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 5d26e70bed6c..a6afd4108beb 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -1269,7 +1269,6 @@ static void eeepc_acpi_notify(struct acpi_device *device, u32 event) if (event > ACPI_MAX_SYS_NOTIFY) return; count = eeepc->event_count[event % 128]++; - acpi_bus_generate_proc_event(device, event, count); acpi_bus_generate_netlink_event(device->pnp.device_class, dev_name(&device->dev), event, count); diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c index 1c9386e7c58c..52b8a97efde1 100644 --- a/drivers/platform/x86/fujitsu-laptop.c +++ b/drivers/platform/x86/fujitsu-laptop.c @@ -773,8 +773,6 @@ static void acpi_fujitsu_notify(struct acpi_device *device, u32 event) else set_lcd_level(newb); } - acpi_bus_generate_proc_event(fujitsu->dev, - ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS, 0); keycode = KEY_BRIGHTNESSUP; } else if (oldb > newb) { if (disable_brightness_adjust != 1) { @@ -783,8 +781,6 @@ static void acpi_fujitsu_notify(struct acpi_device *device, u32 event) else set_lcd_level(newb); } - acpi_bus_generate_proc_event(fujitsu->dev, - ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS, 0); keycode = KEY_BRIGHTNESSDOWN; } break; diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c index 4add9a31bf60..984253da365d 100644 --- a/drivers/platform/x86/panasonic-laptop.c +++ b/drivers/platform/x86/panasonic-laptop.c @@ -464,9 +464,6 @@ static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc) "error getting hotkey status\n")); return; } - - acpi_bus_generate_proc_event(pcc->device, HKEY_NOTIFY, result); - if (!sparse_keymap_report_event(hotk_input_dev, result & 0xf, result & 0x80, false)) ACPI_DEBUG_PRINT((ACPI_DB_ERROR, diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 2ac045f27f10..069821b1fc22 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -1275,9 +1275,6 @@ static void sony_nc_notify(struct acpi_device *device, u32 event) ev_type = HOTKEY; sony_laptop_report_input_event(real_ev); } - - acpi_bus_generate_proc_event(sony_nc_acpi_device, ev_type, real_ev); - acpi_bus_generate_netlink_event(sony_nc_acpi_device->pnp.device_class, dev_name(&sony_nc_acpi_device->dev), ev_type, real_ev); } @@ -4243,7 +4240,6 @@ static irqreturn_t sony_pic_irq(int irq, void *dev_id) found: sony_laptop_report_input_event(device_event); - acpi_bus_generate_proc_event(dev->acpi_dev, 1, device_event); sonypi_compat_report_event(device_event); return IRQ_HANDLED; } diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 54d31c0a9840..e946c0d58a97 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -2282,10 +2282,6 @@ static struct tp_acpi_drv_struct ibm_hotkey_acpidriver; static void tpacpi_hotkey_send_key(unsigned int scancode) { tpacpi_input_send_key_masked(scancode); - if (hotkey_report_mode < 2) { - acpi_bus_generate_proc_event(ibm_hotkey_acpidriver.device, - 0x80, TP_HKEY_EV_HOTKEY_BASE + scancode); - } } static void hotkey_read_nvram(struct tp_nvram_state *n, const u32 m) @@ -3737,13 +3733,6 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event) "event happened to %s\n", TPACPI_MAIL); } - /* Legacy events */ - if (!ignore_acpi_ev && - (send_acpi_ev || hotkey_report_mode < 2)) { - acpi_bus_generate_proc_event(ibm->acpi->device, - event, hkey); - } - /* netlink events */ if (!ignore_acpi_ev && send_acpi_ev) { acpi_bus_generate_netlink_event( diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 56e6b68c8d2f..2650d1f19e43 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -383,15 +383,6 @@ bool acpi_bus_can_wakeup(acpi_handle handle); static inline bool acpi_bus_can_wakeup(acpi_handle handle) { return false; } #endif -#ifdef CONFIG_ACPI_PROC_EVENT -int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data); -int acpi_bus_generate_proc_event4(const char *class, const char *bid, u8 type, int data); -int acpi_bus_receive_event(struct acpi_bus_event *event); -#else -static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data) - { return 0; } -#endif - void acpi_scan_lock_acquire(void); void acpi_scan_lock_release(void); int acpi_scan_add_handler(struct acpi_scan_handler *handler); From 8b5301c5ff2568236c6e3b3d0c93a3e4194ec3f5 Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Wed, 3 Jul 2013 14:48:39 +0200 Subject: [PATCH 0160/3400] platform / thinkpad: Remove deprecated hotkey_report_mode parameter It is somewhat strange that the default value to support the depracated interface is set (1). Anyway this has existed for years. The previous patch already removed the functionality to still export events through /proc. Now this param is useless and should vanish too. Signed-off-by: Thomas Renninger Acked-by: Matthew Garrett Acked-by: Henrique de Moraes Holschuh Signed-off-by: Rafael J. Wysocki --- Documentation/laptops/thinkpad-acpi.txt | 73 ++----------------------- drivers/platform/x86/thinkpad_acpi.c | 29 ---------- 2 files changed, 6 insertions(+), 96 deletions(-) diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt index cf7bc6cb9719..86c52360ffe7 100644 --- a/Documentation/laptops/thinkpad-acpi.txt +++ b/Documentation/laptops/thinkpad-acpi.txt @@ -329,20 +329,6 @@ sysfs notes: This attribute has poll()/select() support. - hotkey_report_mode: - Returns the state of the procfs ACPI event report mode - filter for hot keys. If it is set to 1 (the default), - all hot key presses are reported both through the input - layer and also as ACPI events through procfs (but not - through netlink). If it is set to 2, hot key presses - are reported only through the input layer. - - This attribute is read-only in kernels 2.6.23 or later, - and read-write on earlier kernels. - - May return -EPERM (write access locked out by module - parameter) or -EACCES (read-only). - wakeup_reason: Set to 1 if the system is waking up because the user requested a bay ejection. Set to 2 if the system is @@ -518,24 +504,21 @@ SW_TABLET_MODE Tablet ThinkPads HKEY events 0x5009 and 0x500A Non hotkey ACPI HKEY event map: ------------------------------- -Events that are not propagated by the driver, except for legacy -compatibility purposes when hotkey_report_mode is set to 1: - -0x5001 Lid closed -0x5002 Lid opened -0x5009 Tablet swivel: switched to tablet mode -0x500A Tablet swivel: switched to normal mode -0x7000 Radio Switch may have changed state - Events that are never propagated by the driver: 0x2304 System is waking up from suspend to undock 0x2305 System is waking up from suspend to eject bay 0x2404 System is waking up from hibernation to undock 0x2405 System is waking up from hibernation to eject bay +0x5001 Lid closed +0x5002 Lid opened +0x5009 Tablet swivel: switched to tablet mode +0x500A Tablet swivel: switched to normal mode 0x5010 Brightness level changed/control event 0x6000 KEYBOARD: Numlock key pressed 0x6005 KEYBOARD: Fn key pressed (TO BE VERIFIED) +0x7000 Radio Switch may have changed state + Events that are propagated by the driver to userspace: @@ -574,50 +557,6 @@ operating system is to force either an immediate suspend or hibernate cycle, or a system shutdown. Obviously, something is very wrong if this happens. -Compatibility notes: - -ibm-acpi and thinkpad-acpi 0.15 (mainline kernels before 2.6.23) never -supported the input layer, and sent events over the procfs ACPI event -interface. - -To avoid sending duplicate events over the input layer and the ACPI -event interface, thinkpad-acpi 0.16 implements a module parameter -(hotkey_report_mode), and also a sysfs device attribute with the same -name. - -Make no mistake here: userspace is expected to switch to using the input -layer interface of thinkpad-acpi, together with the ACPI netlink event -interface in kernels 2.6.23 and later, or with the ACPI procfs event -interface in kernels 2.6.22 and earlier. - -If no hotkey_report_mode module parameter is specified (or it is set to -zero), the driver defaults to mode 1 (see below), and on kernels 2.6.22 -and earlier, also allows one to change the hotkey_report_mode through -sysfs. In kernels 2.6.23 and later, where the netlink ACPI event -interface is available, hotkey_report_mode cannot be changed through -sysfs (it is read-only). - -If the hotkey_report_mode module parameter is set to 1 or 2, it cannot -be changed later through sysfs (any writes will return -EPERM to signal -that hotkey_report_mode was locked. On 2.6.23 and later, where -hotkey_report_mode cannot be changed at all, writes will return -EACCES). - -hotkey_report_mode set to 1 makes the driver export through the procfs -ACPI event interface all hot key presses (which are *also* sent to the -input layer). This is a legacy compatibility behaviour, and it is also -the default mode of operation for the driver. - -hotkey_report_mode set to 2 makes the driver filter out the hot key -presses from the procfs ACPI event interface, so these events will only -be sent through the input layer. Userspace that has been updated to use -the thinkpad-acpi input layer interface should set hotkey_report_mode to -2. - -Hot key press events are never sent to the ACPI netlink event interface. -Really up-to-date userspace under kernel 2.6.23 and later is to use the -netlink interface and the input layer interface, and don't bother at all -with hotkey_report_mode. - Brightness hotkey notes: diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index e946c0d58a97..be67e5e28d18 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -2022,8 +2022,6 @@ static u32 hotkey_driver_mask; /* events needed by the driver */ static u32 hotkey_user_mask; /* events visible to userspace */ static u32 hotkey_acpi_mask; /* events enabled in firmware */ -static unsigned int hotkey_report_mode; - static u16 *hotkey_keycode_map; static struct attribute_set *hotkey_dev_attributes; @@ -2878,18 +2876,6 @@ static void hotkey_tablet_mode_notify_change(void) "hotkey_tablet_mode"); } -/* sysfs hotkey report_mode -------------------------------------------- */ -static ssize_t hotkey_report_mode_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", - (hotkey_report_mode != 0) ? hotkey_report_mode : 1); -} - -static struct device_attribute dev_attr_hotkey_report_mode = - __ATTR(hotkey_report_mode, S_IRUGO, hotkey_report_mode_show, NULL); - /* sysfs wakeup reason (pollable) -------------------------------------- */ static ssize_t hotkey_wakeup_reason_show(struct device *dev, struct device_attribute *attr, @@ -2931,7 +2917,6 @@ static struct attribute *hotkey_attributes[] __initdata = { &dev_attr_hotkey_enable.attr, &dev_attr_hotkey_bios_enabled.attr, &dev_attr_hotkey_bios_mask.attr, - &dev_attr_hotkey_report_mode.attr, &dev_attr_hotkey_wakeup_reason.attr, &dev_attr_hotkey_wakeup_hotunplug_complete.attr, &dev_attr_hotkey_mask.attr, @@ -3435,11 +3420,6 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) "initial masks: user=0x%08x, fw=0x%08x, poll=0x%08x\n", hotkey_user_mask, hotkey_acpi_mask, hotkey_source_mask); - dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, - "legacy ibm/hotkey event reporting over procfs %s\n", - (hotkey_report_mode < 2) ? - "enabled" : "disabled"); - tpacpi_inputdev->open = &hotkey_inputdev_open; tpacpi_inputdev->close = &hotkey_inputdev_close; @@ -8829,11 +8809,6 @@ module_param(brightness_enable, uint, 0444); MODULE_PARM_DESC(brightness_enable, "Enables backlight control when 1, disables when 0"); -module_param(hotkey_report_mode, uint, 0444); -MODULE_PARM_DESC(hotkey_report_mode, - "used for backwards compatibility with userspace, " - "see documentation"); - #ifdef CONFIG_THINKPAD_ACPI_ALSA_SUPPORT module_param_named(volume_mode, volume_mode, uint, 0444); MODULE_PARM_DESC(volume_mode, @@ -8964,10 +8939,6 @@ static int __init thinkpad_acpi_module_init(void) tpacpi_lifecycle = TPACPI_LIFE_INIT; - /* Parameter checking */ - if (hotkey_report_mode > 2) - return -EINVAL; - /* Driver-level probe */ ret = get_thinkpad_model_data(&thinkpad_id); From 939c02777a27ea7915764ecca5263dbb60c664f3 Mon Sep 17 00:00:00 2001 From: Yadwinder Singh Brar Date: Sat, 29 Jun 2013 18:21:16 +0530 Subject: [PATCH 0161/3400] regulator: s2mps11: Implement set_ramp_rate callback for bucks Implementing set_ramp_rate() and using standard constraints for getting ramp_delay and ramp_disable, instead of getting it as s2mps11 specific data through platform data, makes driver more compliant with framework and reduces the complexity for adding DT support. Signed-off-by: Yadwinder Singh Brar Signed-off-by: Mark Brown --- drivers/regulator/s2mps11.c | 117 ++++++++++++++++++++++++++++ include/linux/mfd/samsung/s2mps11.h | 11 +++ 2 files changed, 128 insertions(+) diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index a671eb63a4e5..4b84e7660637 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -104,6 +105,121 @@ static int s2mps11_regulator_set_voltage_time_sel(struct regulator_dev *rdev, return DIV_ROUND_UP(abs(new_volt - old_volt), ramp_delay); } +static int s2mps11_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) +{ + struct s2mps11_info *s2mps11 = rdev_get_drvdata(rdev); + unsigned int ramp_val, ramp_shift, ramp_reg = S2MPS11_REG_RAMP_BUCK; + unsigned int ramp_enable = 1, enable_shift = 0; + int ret; + + switch (rdev->desc->id) { + case S2MPS11_BUCK1: + if (ramp_delay > s2mps11->ramp_delay16) + s2mps11->ramp_delay16 = ramp_delay; + else + ramp_delay = s2mps11->ramp_delay16; + + ramp_shift = S2MPS11_BUCK16_RAMP_SHIFT; + break; + case S2MPS11_BUCK2: + enable_shift = S2MPS11_BUCK2_RAMP_EN_SHIFT; + if (!ramp_delay) { + ramp_enable = 0; + break; + } + + s2mps11->ramp_delay2 = ramp_delay; + ramp_shift = S2MPS11_BUCK2_RAMP_SHIFT; + ramp_reg = S2MPS11_REG_RAMP; + break; + case S2MPS11_BUCK3: + enable_shift = S2MPS11_BUCK3_RAMP_EN_SHIFT; + if (!ramp_delay) { + ramp_enable = 0; + break; + } + + if (ramp_delay > s2mps11->ramp_delay34) + s2mps11->ramp_delay34 = ramp_delay; + else + ramp_delay = s2mps11->ramp_delay34; + + ramp_shift = S2MPS11_BUCK34_RAMP_SHIFT; + ramp_reg = S2MPS11_REG_RAMP; + break; + case S2MPS11_BUCK4: + enable_shift = S2MPS11_BUCK4_RAMP_EN_SHIFT; + if (!ramp_delay) { + ramp_enable = 0; + break; + } + + if (ramp_delay > s2mps11->ramp_delay34) + s2mps11->ramp_delay34 = ramp_delay; + else + ramp_delay = s2mps11->ramp_delay34; + + ramp_shift = S2MPS11_BUCK34_RAMP_SHIFT; + ramp_reg = S2MPS11_REG_RAMP; + break; + case S2MPS11_BUCK5: + s2mps11->ramp_delay5 = ramp_delay; + ramp_shift = S2MPS11_BUCK5_RAMP_SHIFT; + break; + case S2MPS11_BUCK6: + enable_shift = S2MPS11_BUCK6_RAMP_EN_SHIFT; + if (!ramp_delay) { + ramp_enable = 0; + break; + } + + if (ramp_delay > s2mps11->ramp_delay16) + s2mps11->ramp_delay16 = ramp_delay; + else + ramp_delay = s2mps11->ramp_delay16; + + ramp_shift = S2MPS11_BUCK16_RAMP_SHIFT; + break; + case S2MPS11_BUCK7: + case S2MPS11_BUCK8: + case S2MPS11_BUCK10: + if (ramp_delay > s2mps11->ramp_delay7810) + s2mps11->ramp_delay7810 = ramp_delay; + else + ramp_delay = s2mps11->ramp_delay7810; + + ramp_shift = S2MPS11_BUCK7810_RAMP_SHIFT; + break; + case S2MPS11_BUCK9: + s2mps11->ramp_delay9 = ramp_delay; + ramp_shift = S2MPS11_BUCK9_RAMP_SHIFT; + break; + default: + return 0; + } + + if (!ramp_enable) + goto ramp_disable; + + if (enable_shift) { + ret = regmap_update_bits(rdev->regmap, S2MPS11_REG_RAMP, + 1 << enable_shift, 1 << enable_shift); + if (ret) { + dev_err(&rdev->dev, "failed to enable ramp rate\n"); + return ret; + } + } + + ramp_val = get_ramp_delay(ramp_delay); + + return regmap_update_bits(rdev->regmap, ramp_reg, + ramp_val << ramp_shift, 1 << ramp_shift); + +ramp_disable: + return regmap_update_bits(rdev->regmap, S2MPS11_REG_RAMP, 0, + 1 << enable_shift); +} + static struct regulator_ops s2mps11_ldo_ops = { .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, @@ -124,6 +240,7 @@ static struct regulator_ops s2mps11_buck_ops = { .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, .set_voltage_time_sel = s2mps11_regulator_set_voltage_time_sel, + .set_ramp_delay = s2mps11_set_ramp_delay, }; #define regulator_desc_ldo1(num) { \ diff --git a/include/linux/mfd/samsung/s2mps11.h b/include/linux/mfd/samsung/s2mps11.h index 4e94dc65f987..d0d52ea60074 100644 --- a/include/linux/mfd/samsung/s2mps11.h +++ b/include/linux/mfd/samsung/s2mps11.h @@ -191,6 +191,17 @@ enum s2mps11_regulators { #define S2MPS11_BUCK_N_VOLTAGES (S2MPS11_BUCK_VSEL_MASK + 1) #define S2MPS11_RAMP_DELAY 25000 /* uV/us */ + +#define S2MPS11_BUCK2_RAMP_SHIFT 6 +#define S2MPS11_BUCK34_RAMP_SHIFT 4 +#define S2MPS11_BUCK5_RAMP_SHIFT 6 +#define S2MPS11_BUCK16_RAMP_SHIFT 4 +#define S2MPS11_BUCK7810_RAMP_SHIFT 2 +#define S2MPS11_BUCK9_RAMP_SHIFT 0 +#define S2MPS11_BUCK2_RAMP_EN_SHIFT 3 +#define S2MPS11_BUCK3_RAMP_EN_SHIFT 2 +#define S2MPS11_BUCK4_RAMP_EN_SHIFT 1 +#define S2MPS11_BUCK6_RAMP_EN_SHIFT 0 #define S2MPS11_PMIC_EN_SHIFT 6 #define S2MPS11_REGULATOR_MAX (S2MPS11_REG_MAX - 3) From a50c6b3255b819c9e18c1cc350ed46698b346c1a Mon Sep 17 00:00:00 2001 From: Yadwinder Singh Brar Date: Sat, 29 Jun 2013 18:21:17 +0530 Subject: [PATCH 0162/3400] regulator: s2mps11: Add DT support This patch adds DT support for parsing regulators constraints for parent(mfd) node and moves some common intialising code out of loop while registering. Signed-off-by: Yadwinder Singh Brar Signed-off-by: Mark Brown --- drivers/regulator/s2mps11.c | 49 ++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index 4b84e7660637..b316d40c8e14 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -16,13 +16,17 @@ #include #include #include +#include #include #include #include #include +#include #include #include +#define S2MPS11_REGULATOR_CNT ARRAY_SIZE(regulators) + struct s2mps11_info { struct regulator_dev *rdev[S2MPS11_REGULATOR_MAX]; @@ -407,22 +411,38 @@ static int s2mps11_pmic_probe(struct platform_device *pdev) { struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); struct sec_platform_data *pdata = dev_get_platdata(iodev->dev); + struct of_regulator_match rdata[S2MPS11_REGULATOR_MAX]; + struct device_node *reg_np = NULL; struct regulator_config config = { }; struct s2mps11_info *s2mps11; int i, ret; unsigned char ramp_enable, ramp_reg = 0; - if (!pdata) { - dev_err(pdev->dev.parent, "Platform data not supplied\n"); - return -ENODEV; - } - s2mps11 = devm_kzalloc(&pdev->dev, sizeof(struct s2mps11_info), GFP_KERNEL); if (!s2mps11) return -ENOMEM; - platform_set_drvdata(pdev, s2mps11); + if (!iodev->dev->of_node) + goto p_data; + + for (i = 0; i < S2MPS11_REGULATOR_CNT; i++) + rdata[i].name = regulators[i].name; + + reg_np = of_find_node_by_name(iodev->dev->of_node, "regulators"); + if (!reg_np) { + dev_err(&pdev->dev, "could not find regulators sub-node\n"); + return -EINVAL; + } + + of_regulator_match(&pdev->dev, reg_np, rdata, S2MPS11_REGULATOR_MAX); + + goto common_reg; +p_data: + if (!pdata) { + dev_err(pdev->dev.parent, "Platform data not supplied\n"); + return -ENODEV; + } s2mps11->ramp_delay2 = pdata->buck2_ramp_delay; s2mps11->ramp_delay34 = pdata->buck34_ramp_delay; @@ -454,12 +474,19 @@ static int s2mps11_pmic_probe(struct platform_device *pdev) ramp_reg |= get_ramp_delay(s2mps11->ramp_delay9); sec_reg_write(iodev, S2MPS11_REG_RAMP_BUCK, ramp_reg); - for (i = 0; i < S2MPS11_REGULATOR_MAX; i++) { +common_reg: + platform_set_drvdata(pdev, s2mps11); - config.dev = &pdev->dev; - config.regmap = iodev->regmap; - config.init_data = pdata->regulators[i].initdata; - config.driver_data = s2mps11; + config.dev = &pdev->dev; + config.regmap = iodev->regmap; + config.driver_data = s2mps11; + for (i = 0; i < S2MPS11_REGULATOR_MAX; i++) { + if (!reg_np) { + config.init_data = pdata->regulators[i].initdata; + } else { + config.init_data = rdata[i].init_data; + config.of_node = rdata[i].of_node; + } s2mps11->rdev[i] = regulator_register(®ulators[i], &config); if (IS_ERR(s2mps11->rdev[i])) { From 6c683c929977b90795939e1e862271c112e7d10f Mon Sep 17 00:00:00 2001 From: Yadwinder Singh Brar Date: Sat, 29 Jun 2013 18:21:18 +0530 Subject: [PATCH 0163/3400] regulator: s2mps11: Convert driver completely to use set_ramp_delay callback Since now we have ramp_delay and ramp_disable as standard regulator constraints and DT part using it so this patch removes legacy part i.e. getting ramp_delayxx and ramp_enable from pdata since it can be passed as standard regulator constraints. Signed-off-by: Yadwinder Singh Brar Signed-off-by: Mark Brown --- drivers/regulator/s2mps11.c | 62 ++++++------------------------------- 1 file changed, 9 insertions(+), 53 deletions(-) diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index b316d40c8e14..f047d36f6027 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c @@ -36,11 +36,6 @@ struct s2mps11_info { int ramp_delay16; int ramp_delay7810; int ramp_delay9; - - bool buck6_ramp; - bool buck2_ramp; - bool buck3_ramp; - bool buck4_ramp; }; static int get_ramp_delay(int ramp_delay) @@ -68,26 +63,18 @@ static int s2mps11_regulator_set_voltage_time_sel(struct regulator_dev *rdev, switch (rdev->desc->id) { case S2MPS11_BUCK2: - if (!s2mps11->buck2_ramp) - return 0; ramp_delay = s2mps11->ramp_delay2; break; case S2MPS11_BUCK3: - if (!s2mps11->buck3_ramp) - return 0; ramp_delay = s2mps11->ramp_delay34; break; case S2MPS11_BUCK4: - if (!s2mps11->buck4_ramp) - return 0; ramp_delay = s2mps11->ramp_delay34; break; case S2MPS11_BUCK5: ramp_delay = s2mps11->ramp_delay5; break; case S2MPS11_BUCK6: - if (!s2mps11->buck6_ramp) - return 0; case S2MPS11_BUCK1: ramp_delay = s2mps11->ramp_delay16; break; @@ -416,15 +403,21 @@ static int s2mps11_pmic_probe(struct platform_device *pdev) struct regulator_config config = { }; struct s2mps11_info *s2mps11; int i, ret; - unsigned char ramp_enable, ramp_reg = 0; s2mps11 = devm_kzalloc(&pdev->dev, sizeof(struct s2mps11_info), GFP_KERNEL); if (!s2mps11) return -ENOMEM; - if (!iodev->dev->of_node) - goto p_data; + if (!iodev->dev->of_node) { + if (pdata) { + goto common_reg; + } else { + dev_err(pdev->dev.parent, + "Platform data or DT node not supplied\n"); + return -ENODEV; + } + } for (i = 0; i < S2MPS11_REGULATOR_CNT; i++) rdata[i].name = regulators[i].name; @@ -437,43 +430,6 @@ static int s2mps11_pmic_probe(struct platform_device *pdev) of_regulator_match(&pdev->dev, reg_np, rdata, S2MPS11_REGULATOR_MAX); - goto common_reg; -p_data: - if (!pdata) { - dev_err(pdev->dev.parent, "Platform data not supplied\n"); - return -ENODEV; - } - - s2mps11->ramp_delay2 = pdata->buck2_ramp_delay; - s2mps11->ramp_delay34 = pdata->buck34_ramp_delay; - s2mps11->ramp_delay5 = pdata->buck5_ramp_delay; - s2mps11->ramp_delay16 = pdata->buck16_ramp_delay; - s2mps11->ramp_delay7810 = pdata->buck7810_ramp_delay; - s2mps11->ramp_delay9 = pdata->buck9_ramp_delay; - - s2mps11->buck6_ramp = pdata->buck6_ramp_enable; - s2mps11->buck2_ramp = pdata->buck2_ramp_enable; - s2mps11->buck3_ramp = pdata->buck3_ramp_enable; - s2mps11->buck4_ramp = pdata->buck4_ramp_enable; - - ramp_enable = (s2mps11->buck2_ramp << 3) | (s2mps11->buck3_ramp << 2) | - (s2mps11->buck4_ramp << 1) | s2mps11->buck6_ramp ; - - if (ramp_enable) { - if (s2mps11->buck2_ramp) - ramp_reg |= get_ramp_delay(s2mps11->ramp_delay2) << 6; - if (s2mps11->buck3_ramp || s2mps11->buck4_ramp) - ramp_reg |= get_ramp_delay(s2mps11->ramp_delay34) << 4; - sec_reg_write(iodev, S2MPS11_REG_RAMP, ramp_reg | ramp_enable); - } - - ramp_reg &= 0x00; - ramp_reg |= get_ramp_delay(s2mps11->ramp_delay5) << 6; - ramp_reg |= get_ramp_delay(s2mps11->ramp_delay16) << 4; - ramp_reg |= get_ramp_delay(s2mps11->ramp_delay7810) << 2; - ramp_reg |= get_ramp_delay(s2mps11->ramp_delay9); - sec_reg_write(iodev, S2MPS11_REG_RAMP_BUCK, ramp_reg); - common_reg: platform_set_drvdata(pdev, s2mps11); From c85cffa5894fad8ad7c8051ccf7dd73a3a3f92b6 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 11 Jul 2013 17:28:29 +0200 Subject: [PATCH 0164/3400] perf timechart: Use traceevent lib event-parse.h include Adding traceevent lib event-parse.h include to timechart command and removing duplicated local 'enum trace_flag_type' definition. Signed-off-by: Jiri Olsa Acked-by: Namhyung Kim Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Thomas Renninger Link: http://lkml.kernel.org/r/1373556513-3000-2-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-timechart.c | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index 4536a92b18f3..a5120095978e 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c @@ -12,6 +12,8 @@ * of the License. */ +#include + #include "builtin.h" #include "util/util.h" @@ -328,25 +330,6 @@ struct wakeup_entry { int success; }; -/* - * trace_flag_type is an enumeration that holds different - * states when a trace occurs. These are: - * IRQS_OFF - interrupts were disabled - * IRQS_NOSUPPORT - arch does not support irqs_disabled_flags - * NEED_RESCED - reschedule is requested - * HARDIRQ - inside an interrupt handler - * SOFTIRQ - inside a softirq handler - */ -enum trace_flag_type { - TRACE_FLAG_IRQS_OFF = 0x01, - TRACE_FLAG_IRQS_NOSUPPORT = 0x02, - TRACE_FLAG_NEED_RESCHED = 0x04, - TRACE_FLAG_HARDIRQ = 0x08, - TRACE_FLAG_SOFTIRQ = 0x10, -}; - - - struct sched_switch { struct trace_entry te; char prev_comm[TASK_COMM_LEN]; From 5936678e7da5f8d2944a2ad45d66c88b4a7ccb67 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 11 Jul 2013 17:28:30 +0200 Subject: [PATCH 0165/3400] perf timechart: Remove event types framework only user The only user of the event types data is 'perf timechart' command and uses this info to identify proper tracepoints based on its name. Switching this code to use tracepoint callbacks handlers same as another commands like builtin-{kmem,lock,sched}.c using the perf_session__set_tracepoints_handlers function. This way we get rid of the only event types user and can remove them completely in next patches. Signed-off-by: Jiri Olsa Acked-by: Namhyung Kim Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Thomas Renninger Link: http://lkml.kernel.org/r/1373556513-3000-3-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-timechart.c | 159 ++++++++++++++++++++------------- 1 file changed, 99 insertions(+), 60 deletions(-) diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index a5120095978e..c2e02319347a 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c @@ -21,6 +21,7 @@ #include "util/color.h" #include #include "util/cache.h" +#include "util/evlist.h" #include "util/evsel.h" #include #include "util/symbol.h" @@ -462,6 +463,8 @@ static void sched_switch(int cpu, u64 timestamp, struct trace_entry *te) } } +typedef int (*tracepoint_handler)(struct perf_evsel *evsel, + struct perf_sample *sample); static int process_sample_event(struct perf_tool *tool __maybe_unused, union perf_event *event __maybe_unused, @@ -469,8 +472,6 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused, struct perf_evsel *evsel, struct machine *machine __maybe_unused) { - struct trace_entry *te; - if (evsel->attr.sample_type & PERF_SAMPLE_TIME) { if (!first_time || first_time > sample->time) first_time = sample->time; @@ -478,69 +479,90 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused, last_time = sample->time; } - te = (void *)sample->raw_data; - if ((evsel->attr.sample_type & PERF_SAMPLE_RAW) && sample->raw_size > 0) { - char *event_str; -#ifdef SUPPORT_OLD_POWER_EVENTS - struct power_entry_old *peo; - peo = (void *)te; -#endif - /* - * FIXME: use evsel, its already mapped from id to perf_evsel, - * remove perf_header__find_event infrastructure bits. - * Mapping all these "power:cpu_idle" strings to the tracepoint - * ID and then just comparing against evsel->attr.config. - * - * e.g.: - * - * if (evsel->attr.config == power_cpu_idle_id) - */ - event_str = perf_header__find_event(te->type); + if (sample->cpu > numcpus) + numcpus = sample->cpu; - if (!event_str) - return 0; - - if (sample->cpu > numcpus) - numcpus = sample->cpu; - - if (strcmp(event_str, "power:cpu_idle") == 0) { - struct power_processor_entry *ppe = (void *)te; - if (ppe->state == (u32)PWR_EVENT_EXIT) - c_state_end(ppe->cpu_id, sample->time); - else - c_state_start(ppe->cpu_id, sample->time, - ppe->state); - } - else if (strcmp(event_str, "power:cpu_frequency") == 0) { - struct power_processor_entry *ppe = (void *)te; - p_state_change(ppe->cpu_id, sample->time, ppe->state); - } - - else if (strcmp(event_str, "sched:sched_wakeup") == 0) - sched_wakeup(sample->cpu, sample->time, sample->pid, te); - - else if (strcmp(event_str, "sched:sched_switch") == 0) - sched_switch(sample->cpu, sample->time, te); - -#ifdef SUPPORT_OLD_POWER_EVENTS - if (use_old_power_events) { - if (strcmp(event_str, "power:power_start") == 0) - c_state_start(peo->cpu_id, sample->time, - peo->value); - - else if (strcmp(event_str, "power:power_end") == 0) - c_state_end(sample->cpu, sample->time); - - else if (strcmp(event_str, - "power:power_frequency") == 0) - p_state_change(peo->cpu_id, sample->time, - peo->value); - } -#endif + if (evsel->handler.func != NULL) { + tracepoint_handler f = evsel->handler.func; + return f(evsel, sample); } + return 0; } +static int +process_sample_cpu_idle(struct perf_evsel *evsel __maybe_unused, + struct perf_sample *sample) +{ + struct power_processor_entry *ppe = sample->raw_data; + + if (ppe->state == (u32) PWR_EVENT_EXIT) + c_state_end(ppe->cpu_id, sample->time); + else + c_state_start(ppe->cpu_id, sample->time, ppe->state); + return 0; +} + +static int +process_sample_cpu_frequency(struct perf_evsel *evsel __maybe_unused, + struct perf_sample *sample) +{ + struct power_processor_entry *ppe = sample->raw_data; + + p_state_change(ppe->cpu_id, sample->time, ppe->state); + return 0; +} + +static int +process_sample_sched_wakeup(struct perf_evsel *evsel __maybe_unused, + struct perf_sample *sample) +{ + struct trace_entry *te = sample->raw_data; + + sched_wakeup(sample->cpu, sample->time, sample->pid, te); + return 0; +} + +static int +process_sample_sched_switch(struct perf_evsel *evsel __maybe_unused, + struct perf_sample *sample) +{ + struct trace_entry *te = sample->raw_data; + + sched_switch(sample->cpu, sample->time, te); + return 0; +} + +#ifdef SUPPORT_OLD_POWER_EVENTS +static int +process_sample_power_start(struct perf_evsel *evsel __maybe_unused, + struct perf_sample *sample) +{ + struct power_entry_old *peo = sample->raw_data; + + c_state_start(peo->cpu_id, sample->time, peo->value); + return 0; +} + +static int +process_sample_power_end(struct perf_evsel *evsel __maybe_unused, + struct perf_sample *sample) +{ + c_state_end(sample->cpu, sample->time); + return 0; +} + +static int +process_sample_power_frequency(struct perf_evsel *evsel __maybe_unused, + struct perf_sample *sample) +{ + struct power_entry_old *peo = sample->raw_data; + + p_state_change(peo->cpu_id, sample->time, peo->value); + return 0; +} +#endif /* SUPPORT_OLD_POWER_EVENTS */ + /* * After the last sample we need to wrap up the current C/P state * and close out each CPU for these. @@ -957,6 +979,17 @@ static int __cmd_timechart(const char *output_name) .sample = process_sample_event, .ordered_samples = true, }; + const struct perf_evsel_str_handler power_tracepoints[] = { + { "power:cpu_idle", process_sample_cpu_idle }, + { "power:cpu_frequency", process_sample_cpu_frequency }, + { "sched:sched_wakeup", process_sample_sched_wakeup }, + { "sched:sched_switch", process_sample_sched_switch }, +#ifdef SUPPORT_OLD_POWER_EVENTS + { "power:power_start", process_sample_power_start }, + { "power:power_end", process_sample_power_end }, + { "power:power_frequency", process_sample_power_frequency }, +#endif + }; struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0, false, &perf_timechart); int ret = -EINVAL; @@ -967,6 +1000,12 @@ static int __cmd_timechart(const char *output_name) if (!perf_session__has_traces(session, "timechart record")) goto out_delete; + if (perf_session__set_tracepoints_handlers(session, + power_tracepoints)) { + pr_err("Initializing session tracepoint handlers failed\n"); + goto out_delete; + } + ret = perf_session__process_events(session, &perf_timechart); if (ret) goto out_delete; From 44b3c57802b7557d0e2d8c3bd39bce942e9324cc Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 11 Jul 2013 17:28:31 +0200 Subject: [PATCH 0166/3400] perf tools: Remove event types from perf data file Removing event types data storing/reading to/from perf data file as it's no longer needed. The only user of this data 'perf timechart' was switched to use tracepoints handler callbacks. The event_types offset and size stay in the perf data file header but are ignored from now on. Signed-off-by: Jiri Olsa Acked-by: Namhyung Kim Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1373556513-3000-4-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/header.c | 28 +--------------------------- tools/perf/util/header.h | 3 +-- 2 files changed, 2 insertions(+), 29 deletions(-) diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index d12d79cf8d32..88626678bfc4 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -2334,16 +2334,6 @@ int perf_session__write_header(struct perf_session *session, } } - header->event_offset = lseek(fd, 0, SEEK_CUR); - header->event_size = trace_event_count * sizeof(struct perf_trace_event_type); - if (trace_events) { - err = do_write(fd, trace_events, header->event_size); - if (err < 0) { - pr_debug("failed to write perf header events\n"); - return err; - } - } - header->data_offset = lseek(fd, 0, SEEK_CUR); if (at_exit) { @@ -2364,10 +2354,7 @@ int perf_session__write_header(struct perf_session *session, .offset = header->data_offset, .size = header->data_size, }, - .event_types = { - .offset = header->event_offset, - .size = header->event_size, - }, + /* event_types is ignored, store zeros */ }; memcpy(&f_header.adds_features, &header->adds_features, sizeof(header->adds_features)); @@ -2614,8 +2601,6 @@ int perf_file_header__read(struct perf_file_header *header, memcpy(&ph->adds_features, &header->adds_features, sizeof(ph->adds_features)); - ph->event_offset = header->event_types.offset; - ph->event_size = header->event_types.size; ph->data_offset = header->data.offset; ph->data_size = header->data.size; return 0; @@ -2839,17 +2824,6 @@ int perf_session__read_header(struct perf_session *session, int fd) symbol_conf.nr_events = nr_attrs; - if (f_header.event_types.size) { - lseek(fd, f_header.event_types.offset, SEEK_SET); - trace_events = malloc(f_header.event_types.size); - if (trace_events == NULL) - return -ENOMEM; - if (perf_header__getbuffer64(header, fd, trace_events, - f_header.event_types.size)) - goto out_errno; - trace_event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type); - } - perf_header__process_sections(header, fd, &session->pevent, perf_file_section__process); diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index 2d1ca7d3ca9c..298982fb195b 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h @@ -45,6 +45,7 @@ struct perf_file_header { u64 attr_size; struct perf_file_section attrs; struct perf_file_section data; + /* event_types is ignored */ struct perf_file_section event_types; DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS); }; @@ -88,8 +89,6 @@ struct perf_header { s64 attr_offset; u64 data_offset; u64 data_size; - u64 event_offset; - u64 event_size; DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS); struct perf_session_env env; }; From 30d350795e8e57c17eabaab454932889f1ae8159 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 11 Jul 2013 17:28:32 +0200 Subject: [PATCH 0167/3400] perf record: Remove event types pushing Removing event types data pushing from record command. It's no longer needed, because this data is ignored. Signed-off-by: Jiri Olsa Acked-by: Namhyung Kim Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1373556513-3000-5-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index ecca62e27b28..1f5243c1c477 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -904,7 +904,6 @@ const struct option record_options[] = { int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) { int err = -ENOMEM; - struct perf_evsel *pos; struct perf_evlist *evsel_list; struct perf_record *rec = &record; char errbuf[BUFSIZ]; @@ -968,11 +967,6 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0) usage_with_options(record_usage, record_options); - list_for_each_entry(pos, &evsel_list->entries, node) { - if (perf_header__push_event(pos->attr.config, perf_evsel__name(pos))) - goto out_free_fd; - } - if (rec->opts.user_interval != ULLONG_MAX) rec->opts.default_interval = rec->opts.user_interval; if (rec->opts.user_freq != UINT_MAX) From 6065210db932fd183cbc8bc77558fee275360e71 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 11 Jul 2013 17:28:33 +0200 Subject: [PATCH 0168/3400] perf tools: Remove event types framework completely Removing event types framework completely. The only remainder (apart from few comments) is following enum: enum perf_user_event_type { ... PERF_RECORD_HEADER_EVENT_TYPE = 65, /* deprecated */ ... } It's kept as deprecated, resulting in error when processed in perf_session__process_user_event function. Signed-off-by: Jiri Olsa Acked-by: Namhyung Kim Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1373556513-3000-6-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-inject.c | 7 --- tools/perf/builtin-record.c | 7 --- tools/perf/builtin-report.c | 1 - tools/perf/builtin-script.c | 1 - tools/perf/util/event.h | 2 +- tools/perf/util/header.c | 90 ------------------------------------- tools/perf/util/header.h | 13 ------ tools/perf/util/session.c | 11 ----- tools/perf/util/tool.h | 3 -- 9 files changed, 1 insertion(+), 134 deletions(-) diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index ad1296c6f88c..1d8de2e4a407 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -67,12 +67,6 @@ static int perf_event__repipe_op2_synth(struct perf_tool *tool, return perf_event__repipe_synth(tool, event); } -static int perf_event__repipe_event_type_synth(struct perf_tool *tool, - union perf_event *event) -{ - return perf_event__repipe_synth(tool, event); -} - static int perf_event__repipe_attr(struct perf_tool *tool, union perf_event *event, struct perf_evlist **pevlist) @@ -402,7 +396,6 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) .throttle = perf_event__repipe, .unthrottle = perf_event__repipe, .attr = perf_event__repipe_attr, - .event_type = perf_event__repipe_event_type_synth, .tracing_data = perf_event__repipe_op2_synth, .finished_round = perf_event__repipe_op2_synth, .build_id = perf_event__repipe_op2_synth, diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 1f5243c1c477..a41ac41546c9 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -474,13 +474,6 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) goto out_delete_session; } - err = perf_event__synthesize_event_types(tool, process_synthesized_event, - machine); - if (err < 0) { - pr_err("Couldn't synthesize event_types.\n"); - goto out_delete_session; - } - if (have_tracepoints(&evsel_list->entries)) { /* * FIXME err <= 0 here actually means that diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 188c265751c8..a34c587900c7 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -741,7 +741,6 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) .lost = perf_event__process_lost, .read = process_read_event, .attr = perf_event__process_attr, - .event_type = perf_event__process_event_type, .tracing_data = perf_event__process_tracing_data, .build_id = perf_event__process_build_id, .ordered_samples = true, diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 3de8979fe87d..ecb697998d3b 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -524,7 +524,6 @@ static struct perf_tool perf_script = { .exit = perf_event__process_exit, .fork = perf_event__process_fork, .attr = perf_event__process_attr, - .event_type = perf_event__process_event_type, .tracing_data = perf_event__process_tracing_data, .build_id = perf_event__process_build_id, .ordered_samples = true, diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 181389535c0c..1ebb8fb0178c 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -116,7 +116,7 @@ struct build_id_event { enum perf_user_event_type { /* above any possible kernel type */ PERF_RECORD_USER_TYPE_START = 64, PERF_RECORD_HEADER_ATTR = 64, - PERF_RECORD_HEADER_EVENT_TYPE = 65, + PERF_RECORD_HEADER_EVENT_TYPE = 65, /* depreceated */ PERF_RECORD_HEADER_TRACING_DATA = 66, PERF_RECORD_HEADER_BUILD_ID = 67, PERF_RECORD_FINISHED_ROUND = 68, diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 88626678bfc4..b28a65ecd61b 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -25,41 +25,9 @@ static bool no_buildid_cache = false; -static int trace_event_count; -static struct perf_trace_event_type *trace_events; - static u32 header_argc; static const char **header_argv; -int perf_header__push_event(u64 id, const char *name) -{ - struct perf_trace_event_type *nevents; - - if (strlen(name) > MAX_EVENT_NAME) - pr_warning("Event %s will be truncated\n", name); - - nevents = realloc(trace_events, (trace_event_count + 1) * sizeof(*trace_events)); - if (nevents == NULL) - return -ENOMEM; - trace_events = nevents; - - memset(&trace_events[trace_event_count], 0, sizeof(struct perf_trace_event_type)); - trace_events[trace_event_count].event_id = id; - strncpy(trace_events[trace_event_count].name, name, MAX_EVENT_NAME - 1); - trace_event_count++; - return 0; -} - -char *perf_header__find_event(u64 id) -{ - int i; - for (i = 0 ; i < trace_event_count; i++) { - if (trace_events[i].event_id == id) - return trace_events[i].name; - } - return NULL; -} - /* * magic2 = "PERFILE2" * must be a numerical value to let the endianness @@ -2936,64 +2904,6 @@ int perf_event__process_attr(struct perf_tool *tool __maybe_unused, return 0; } -int perf_event__synthesize_event_type(struct perf_tool *tool, - u64 event_id, char *name, - perf_event__handler_t process, - struct machine *machine) -{ - union perf_event ev; - size_t size = 0; - int err = 0; - - memset(&ev, 0, sizeof(ev)); - - ev.event_type.event_type.event_id = event_id; - memset(ev.event_type.event_type.name, 0, MAX_EVENT_NAME); - strncpy(ev.event_type.event_type.name, name, MAX_EVENT_NAME - 1); - - ev.event_type.header.type = PERF_RECORD_HEADER_EVENT_TYPE; - size = strlen(ev.event_type.event_type.name); - size = PERF_ALIGN(size, sizeof(u64)); - ev.event_type.header.size = sizeof(ev.event_type) - - (sizeof(ev.event_type.event_type.name) - size); - - err = process(tool, &ev, NULL, machine); - - return err; -} - -int perf_event__synthesize_event_types(struct perf_tool *tool, - perf_event__handler_t process, - struct machine *machine) -{ - struct perf_trace_event_type *type; - int i, err = 0; - - for (i = 0; i < trace_event_count; i++) { - type = &trace_events[i]; - - err = perf_event__synthesize_event_type(tool, type->event_id, - type->name, process, - machine); - if (err) { - pr_debug("failed to create perf header event type\n"); - return err; - } - } - - return err; -} - -int perf_event__process_event_type(struct perf_tool *tool __maybe_unused, - union perf_event *event) -{ - if (perf_header__push_event(event->event_type.event_type.event_id, - event->event_type.event_type.name) < 0) - return -ENOMEM; - - return 0; -} - int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd, struct perf_evlist *evlist, perf_event__handler_t process) diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index 298982fb195b..669fda531da6 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h @@ -102,9 +102,6 @@ int perf_session__write_header(struct perf_session *session, int fd, bool at_exit); int perf_header__write_pipe(int fd); -int perf_header__push_event(u64 id, const char *name); -char *perf_header__find_event(u64 id); - void perf_header__set_feat(struct perf_header *header, int feat); void perf_header__clear_feat(struct perf_header *header, int feat); bool perf_header__has_feat(const struct perf_header *header, int feat); @@ -132,16 +129,6 @@ int perf_event__synthesize_attrs(struct perf_tool *tool, int perf_event__process_attr(struct perf_tool *tool, union perf_event *event, struct perf_evlist **pevlist); -int perf_event__synthesize_event_type(struct perf_tool *tool, - u64 event_id, char *name, - perf_event__handler_t process, - struct machine *machine); -int perf_event__synthesize_event_types(struct perf_tool *tool, - perf_event__handler_t process, - struct machine *machine); -int perf_event__process_event_type(struct perf_tool *tool, - union perf_event *event); - int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd, struct perf_evlist *evlist, perf_event__handler_t process); diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 1eb58eedcac1..d0d9f946a1b1 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -241,13 +241,6 @@ static int process_finished_round_stub(struct perf_tool *tool __maybe_unused, return 0; } -static int process_event_type_stub(struct perf_tool *tool __maybe_unused, - union perf_event *event __maybe_unused) -{ - dump_printf(": unhandled!\n"); - return 0; -} - static int process_finished_round(struct perf_tool *tool, union perf_event *event, struct perf_session *session); @@ -274,8 +267,6 @@ static void perf_tool__fill_defaults(struct perf_tool *tool) tool->unthrottle = process_event_stub; if (tool->attr == NULL) tool->attr = process_event_synth_attr_stub; - if (tool->event_type == NULL) - tool->event_type = process_event_type_stub; if (tool->tracing_data == NULL) tool->tracing_data = process_event_synth_tracing_data_stub; if (tool->build_id == NULL) @@ -928,8 +919,6 @@ static int perf_session__process_user_event(struct perf_session *session, union if (err == 0) perf_session__set_id_hdr_size(session); return err; - case PERF_RECORD_HEADER_EVENT_TYPE: - return tool->event_type(tool, event); case PERF_RECORD_HEADER_TRACING_DATA: /* setup for reading amidst mmap */ lseek(session->fd, file_offset, SEEK_SET); diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h index 88f8cbdb8a34..62b16b6165ba 100644 --- a/tools/perf/util/tool.h +++ b/tools/perf/util/tool.h @@ -22,8 +22,6 @@ typedef int (*event_attr_op)(struct perf_tool *tool, union perf_event *event, struct perf_evlist **pevlist); -typedef int (*event_simple_op)(struct perf_tool *tool, union perf_event *event); - typedef int (*event_op2)(struct perf_tool *tool, union perf_event *event, struct perf_session *session); @@ -39,7 +37,6 @@ struct perf_tool { unthrottle; event_attr_op attr; event_op2 tracing_data; - event_simple_op event_type; event_op2 finished_round, build_id; bool ordered_samples; From b4519c71c45b31f5acd6db984c8830e52120323a Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 16 Jul 2013 02:10:11 -0300 Subject: [PATCH 0169/3400] regmap: Provide __acquires/__releases annotations Fix the following sparse warnings: drivers/base/regmap/regmap.c:305:13: warning: context imbalance in 'regmap_lock_spinlock' - wrong count at exit drivers/base/regmap/regmap.c:314:13: warning: context imbalance in 'regmap_unlock_spinlock' - unexpected unlock Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown --- drivers/base/regmap/regmap.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 95920583e31e..bf8a81c930ac 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -303,6 +303,7 @@ static void regmap_unlock_mutex(void *__map) } static void regmap_lock_spinlock(void *__map) +__acquires(&map->spinlock) { struct regmap *map = __map; unsigned long flags; @@ -312,6 +313,7 @@ static void regmap_lock_spinlock(void *__map) } static void regmap_unlock_spinlock(void *__map) +__releases(&map->spinlock) { struct regmap *map = __map; spin_unlock_irqrestore(&map->spinlock, map->spinlock_flags); From 1d5be6b287c8efc879fbe578e2b7bc8f7a38f313 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 12 Jul 2013 13:38:17 -0700 Subject: [PATCH 0170/3400] cgroup: move module ref handling into rebind_subsystems() Module ref handling in cgroup is rather weird. parse_cgroupfs_options() grabs all the modules for the specified subsystems. A module ref is kept if the specified subsystem is newly bound to the hierarchy. If not, or the operation fails, the refs are dropped. This scatters module ref handling across multiple functions making it difficult to track. It also make the function nasty to use for dynamic subsystem binding which is necessary for the planned unified hierarchy. There's nothing which requires the subsystem modules to be pinned between parse_cgroupfs_options() and rebind_subsystems() in both mount and remount paths. parse_cgroupfs_options() can just parse and rebind_subsystems() can handle pinning the subsystems that it wants to bind, which is a natural part of its task - binding - anyway. Move module ref handling into rebind_subsystems() which makes the code a lot simpler - modules are gotten iff it's gonna be bound and put iff unbound or binding fails. v2: Li pointed out that if a controller module is unloaded between parsing and binding, rebind_subsystems() won't notice the missing controller as it only iterates through existing controllers. Fix it by updating rebind_subsystems() to compare @added_mask to @pinned and fail with -ENOENT if they don't match. Signed-off-by: Tejun Heo Acked-by: Li Zefan --- kernel/cgroup.c | 93 +++++++++++++++---------------------------------- 1 file changed, 28 insertions(+), 65 deletions(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index c108d3d1ea30..2a8cf1a7d2f4 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -1003,6 +1003,7 @@ static int rebind_subsystems(struct cgroupfs_root *root, { struct cgroup *cgrp = &root->top_cgroup; struct cgroup_subsys *ss; + unsigned long pinned = 0; int i, ret; BUG_ON(!mutex_is_locked(&cgroup_mutex)); @@ -1010,20 +1011,32 @@ static int rebind_subsystems(struct cgroupfs_root *root, /* Check that any added subsystems are currently free */ for_each_subsys(ss, i) { - unsigned long bit = 1UL << i; - - if (!(bit & added_mask)) + if (!(added_mask & (1 << i))) continue; + /* is the subsystem mounted elsewhere? */ if (ss->root != &cgroup_dummy_root) { - /* Subsystem isn't free */ - return -EBUSY; + ret = -EBUSY; + goto out_put; } + + /* pin the module */ + if (!try_module_get(ss->module)) { + ret = -ENOENT; + goto out_put; + } + pinned |= 1 << i; + } + + /* subsys could be missing if unloaded between parsing and here */ + if (added_mask != pinned) { + ret = -ENOENT; + goto out_put; } ret = cgroup_populate_dir(cgrp, added_mask); if (ret) - return ret; + goto out_put; /* * Nothing can fail from this point on. Remove files for the @@ -1067,11 +1080,6 @@ static int rebind_subsystems(struct cgroupfs_root *root, } else if (bit & root->subsys_mask) { /* Subsystem state should already exist */ BUG_ON(!cgrp->subsys[i]); - /* - * a refcount was taken, but we already had one, so - * drop the extra reference. - */ - module_put(ss->module); #ifdef CONFIG_MODULE_UNLOAD BUG_ON(ss->module && !module_refcount(ss->module)); #endif @@ -1088,6 +1096,12 @@ static int rebind_subsystems(struct cgroupfs_root *root, root->flags |= CGRP_ROOT_SUBSYS_BOUND; return 0; + +out_put: + for_each_subsys(ss, i) + if (pinned & (1 << i)) + module_put(ss->module); + return ret; } static int cgroup_show_options(struct seq_file *seq, struct dentry *dentry) @@ -1138,7 +1152,6 @@ static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts) char *token, *o = data; bool all_ss = false, one_ss = false; unsigned long mask = (unsigned long)-1; - bool module_pin_failed = false; struct cgroup_subsys *ss; int i; @@ -1281,52 +1294,9 @@ static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts) if (!opts->subsys_mask && !opts->name) return -EINVAL; - /* - * Grab references on all the modules we'll need, so the subsystems - * don't dance around before rebind_subsystems attaches them. This may - * take duplicate reference counts on a subsystem that's already used, - * but rebind_subsystems handles this case. - */ - for_each_subsys(ss, i) { - if (!(opts->subsys_mask & (1UL << i))) - continue; - if (!try_module_get(cgroup_subsys[i]->module)) { - module_pin_failed = true; - break; - } - } - if (module_pin_failed) { - /* - * oops, one of the modules was going away. this means that we - * raced with a module_delete call, and to the user this is - * essentially a "subsystem doesn't exist" case. - */ - for (i--; i >= 0; i--) { - /* drop refcounts only on the ones we took */ - unsigned long bit = 1UL << i; - - if (!(bit & opts->subsys_mask)) - continue; - module_put(cgroup_subsys[i]->module); - } - return -ENOENT; - } - return 0; } -static void drop_parsed_module_refcounts(unsigned long subsys_mask) -{ - struct cgroup_subsys *ss; - int i; - - mutex_lock(&cgroup_mutex); - for_each_subsys(ss, i) - if (subsys_mask & (1UL << i)) - module_put(cgroup_subsys[i]->module); - mutex_unlock(&cgroup_mutex); -} - static int cgroup_remount(struct super_block *sb, int *flags, char *data) { int ret = 0; @@ -1384,8 +1354,6 @@ static int cgroup_remount(struct super_block *sb, int *flags, char *data) mutex_unlock(&cgroup_root_mutex); mutex_unlock(&cgroup_mutex); mutex_unlock(&cgrp->dentry->d_inode->i_mutex); - if (ret) - drop_parsed_module_refcounts(opts.subsys_mask); return ret; } @@ -1591,7 +1559,7 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type, new_root = cgroup_root_from_opts(&opts); if (IS_ERR(new_root)) { ret = PTR_ERR(new_root); - goto drop_modules; + goto out_err; } opts.new_root = new_root; @@ -1600,7 +1568,7 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type, if (IS_ERR(sb)) { ret = PTR_ERR(sb); cgroup_free_root(opts.new_root); - goto drop_modules; + goto out_err; } root = sb->s_fs_info; @@ -1708,9 +1676,6 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type, pr_warning("cgroup: new mount options do not match the existing superblock, will be ignored\n"); } } - - /* no subsys rebinding, so refcounts don't change */ - drop_parsed_module_refcounts(opts.subsys_mask); } kfree(opts.release_agent); @@ -1728,8 +1693,6 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type, mutex_unlock(&inode->i_mutex); drop_new_super: deactivate_locked_super(sb); - drop_modules: - drop_parsed_module_refcounts(opts.subsys_mask); out_err: kfree(opts.release_agent); kfree(opts.name); @@ -4837,7 +4800,7 @@ void cgroup_unload_subsys(struct cgroup_subsys *ss) /* * we shouldn't be called if the subsystem is in use, and the use of - * try_module_get in parse_cgroupfs_options should ensure that it + * try_module_get() in rebind_subsystems() should ensure that it * doesn't start being used while we're killing it off. */ BUG_ON(ss->root != &cgroup_dummy_root); From a698b4488ab98deef6c3beeba3e27fea17650132 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 28 Jun 2013 21:08:27 -0700 Subject: [PATCH 0171/3400] cgroup: remove gratuituous BUG_ON()s from rebind_subsystems() rebind_subsystems() performs santiy checks even on subsystems which aren't specified to be added or removed and the checks aren't all that useful given that these are in a very cold path while the violations they check would trip up in much hotter paths. Let's remove these from rebind_subsystems(). Signed-off-by: Tejun Heo Acked-by: Li Zefan --- kernel/cgroup.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 2a8cf1a7d2f4..345fac8e4fba 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -1077,15 +1077,6 @@ static int rebind_subsystems(struct cgroupfs_root *root, /* subsystem is now free - drop reference on module */ module_put(ss->module); root->subsys_mask &= ~bit; - } else if (bit & root->subsys_mask) { - /* Subsystem state should already exist */ - BUG_ON(!cgrp->subsys[i]); -#ifdef CONFIG_MODULE_UNLOAD - BUG_ON(ss->module && !module_refcount(ss->module)); -#endif - } else { - /* Subsystem state shouldn't exist */ - BUG_ON(cgrp->subsys[i]); } } From dc34e7e1a701134c2639dc7af78dc91055616477 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Mon, 1 Jul 2013 00:01:32 +0400 Subject: [PATCH 0172/3400] libata: move 'struct ata_taskfile' and friends from ata.h to libata.h Move 'struct ata_taskfile', ata_prot_flags() and their friends from to . They were misplaced from the beginning, as should cover ATA/ATAPI and related standards only -- to which the aforementioned structure and function have only remote relation. I would have moved 'enum ata_tf_protocols' closely related to 'struct ata_taskfile' but it unfortunately gets used by 'drivers/ide/ide-ioctls.c'... Signed-off-by: Sergei Shtylyov Signed-off-by: Tejun Heo --- include/linux/ata.h | 102 ----------------------------------------- include/linux/libata.h | 102 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+), 102 deletions(-) diff --git a/include/linux/ata.h b/include/linux/ata.h index ee0bd9524055..f63fb1afc5cc 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -446,22 +446,6 @@ enum { SERR_TRANS_ST_ERROR = (1 << 24), /* Transport state trans. error */ SERR_UNRECOG_FIS = (1 << 25), /* Unrecognized FIS */ SERR_DEV_XCHG = (1 << 26), /* device exchanged */ - - /* struct ata_taskfile flags */ - ATA_TFLAG_LBA48 = (1 << 0), /* enable 48-bit LBA and "HOB" */ - ATA_TFLAG_ISADDR = (1 << 1), /* enable r/w to nsect/lba regs */ - ATA_TFLAG_DEVICE = (1 << 2), /* enable r/w to device reg */ - ATA_TFLAG_WRITE = (1 << 3), /* data dir: host->dev==1 (write) */ - ATA_TFLAG_LBA = (1 << 4), /* enable LBA */ - ATA_TFLAG_FUA = (1 << 5), /* enable FUA */ - ATA_TFLAG_POLLING = (1 << 6), /* set nIEN to 1 and use polling */ - - /* protocol flags */ - ATA_PROT_FLAG_PIO = (1 << 0), /* is PIO */ - ATA_PROT_FLAG_DMA = (1 << 1), /* is DMA */ - ATA_PROT_FLAG_DATA = ATA_PROT_FLAG_PIO | ATA_PROT_FLAG_DMA, - ATA_PROT_FLAG_NCQ = (1 << 2), /* is NCQ */ - ATA_PROT_FLAG_ATAPI = (1 << 3), /* is ATAPI */ }; enum ata_tf_protocols { @@ -488,83 +472,6 @@ struct ata_bmdma_prd { __le32 flags_len; }; -struct ata_taskfile { - unsigned long flags; /* ATA_TFLAG_xxx */ - u8 protocol; /* ATA_PROT_xxx */ - - u8 ctl; /* control reg */ - - u8 hob_feature; /* additional data */ - u8 hob_nsect; /* to support LBA48 */ - u8 hob_lbal; - u8 hob_lbam; - u8 hob_lbah; - - u8 feature; - u8 nsect; - u8 lbal; - u8 lbam; - u8 lbah; - - u8 device; - - u8 command; /* IO operation */ -}; - -/* - * protocol tests - */ -static inline unsigned int ata_prot_flags(u8 prot) -{ - switch (prot) { - case ATA_PROT_NODATA: - return 0; - case ATA_PROT_PIO: - return ATA_PROT_FLAG_PIO; - case ATA_PROT_DMA: - return ATA_PROT_FLAG_DMA; - case ATA_PROT_NCQ: - return ATA_PROT_FLAG_DMA | ATA_PROT_FLAG_NCQ; - case ATAPI_PROT_NODATA: - return ATA_PROT_FLAG_ATAPI; - case ATAPI_PROT_PIO: - return ATA_PROT_FLAG_ATAPI | ATA_PROT_FLAG_PIO; - case ATAPI_PROT_DMA: - return ATA_PROT_FLAG_ATAPI | ATA_PROT_FLAG_DMA; - } - return 0; -} - -static inline int ata_is_atapi(u8 prot) -{ - return ata_prot_flags(prot) & ATA_PROT_FLAG_ATAPI; -} - -static inline int ata_is_nodata(u8 prot) -{ - return !(ata_prot_flags(prot) & ATA_PROT_FLAG_DATA); -} - -static inline int ata_is_pio(u8 prot) -{ - return ata_prot_flags(prot) & ATA_PROT_FLAG_PIO; -} - -static inline int ata_is_dma(u8 prot) -{ - return ata_prot_flags(prot) & ATA_PROT_FLAG_DMA; -} - -static inline int ata_is_ncq(u8 prot) -{ - return ata_prot_flags(prot) & ATA_PROT_FLAG_NCQ; -} - -static inline int ata_is_data(u8 prot) -{ - return ata_prot_flags(prot) & ATA_PROT_FLAG_DATA; -} - /* * id tests */ @@ -1060,15 +967,6 @@ static inline unsigned ata_set_lba_range_entries(void *_buffer, return used_bytes; } -static inline int is_multi_taskfile(struct ata_taskfile *tf) -{ - return (tf->command == ATA_CMD_READ_MULTI) || - (tf->command == ATA_CMD_WRITE_MULTI) || - (tf->command == ATA_CMD_READ_MULTI_EXT) || - (tf->command == ATA_CMD_WRITE_MULTI_EXT) || - (tf->command == ATA_CMD_WRITE_MULTI_FUA_EXT); -} - static inline bool ata_ok(u8 status) { return ((status & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ | ATA_ERR)) diff --git a/include/linux/libata.h b/include/linux/libata.h index 4ea55bb45deb..283d66bc603c 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -138,6 +138,22 @@ enum { ATA_SHT_THIS_ID = -1, ATA_SHT_USE_CLUSTERING = 1, + /* struct ata_taskfile flags */ + ATA_TFLAG_LBA48 = (1 << 0), /* enable 48-bit LBA and "HOB" */ + ATA_TFLAG_ISADDR = (1 << 1), /* enable r/w to nsect/lba regs */ + ATA_TFLAG_DEVICE = (1 << 2), /* enable r/w to device reg */ + ATA_TFLAG_WRITE = (1 << 3), /* data dir: host->dev==1 (write) */ + ATA_TFLAG_LBA = (1 << 4), /* enable LBA */ + ATA_TFLAG_FUA = (1 << 5), /* enable FUA */ + ATA_TFLAG_POLLING = (1 << 6), /* set nIEN to 1 and use polling */ + + /* protocol flags */ + ATA_PROT_FLAG_PIO = (1 << 0), /* is PIO */ + ATA_PROT_FLAG_DMA = (1 << 1), /* is DMA */ + ATA_PROT_FLAG_DATA = ATA_PROT_FLAG_PIO | ATA_PROT_FLAG_DMA, + ATA_PROT_FLAG_NCQ = (1 << 2), /* is NCQ */ + ATA_PROT_FLAG_ATAPI = (1 << 3), /* is ATAPI */ + /* struct ata_device stuff */ ATA_DFLAG_LBA = (1 << 0), /* device supports LBA */ ATA_DFLAG_LBA48 = (1 << 1), /* device supports LBA48 */ @@ -518,6 +534,29 @@ enum sw_activity { BLINK_OFF, }; +struct ata_taskfile { + unsigned long flags; /* ATA_TFLAG_xxx */ + u8 protocol; /* ATA_PROT_xxx */ + + u8 ctl; /* control reg */ + + u8 hob_feature; /* additional data */ + u8 hob_nsect; /* to support LBA48 */ + u8 hob_lbal; + u8 hob_lbam; + u8 hob_lbah; + + u8 feature; + u8 nsect; + u8 lbal; + u8 lbam; + u8 lbah; + + u8 device; + + u8 command; /* IO operation */ +}; + #ifdef CONFIG_ATA_SFF struct ata_ioports { void __iomem *cmd_addr; @@ -959,6 +998,69 @@ extern const unsigned long sata_deb_timing_long[]; extern struct ata_port_operations ata_dummy_port_ops; extern const struct ata_port_info ata_dummy_port_info; +/* + * protocol tests + */ +static inline unsigned int ata_prot_flags(u8 prot) +{ + switch (prot) { + case ATA_PROT_NODATA: + return 0; + case ATA_PROT_PIO: + return ATA_PROT_FLAG_PIO; + case ATA_PROT_DMA: + return ATA_PROT_FLAG_DMA; + case ATA_PROT_NCQ: + return ATA_PROT_FLAG_DMA | ATA_PROT_FLAG_NCQ; + case ATAPI_PROT_NODATA: + return ATA_PROT_FLAG_ATAPI; + case ATAPI_PROT_PIO: + return ATA_PROT_FLAG_ATAPI | ATA_PROT_FLAG_PIO; + case ATAPI_PROT_DMA: + return ATA_PROT_FLAG_ATAPI | ATA_PROT_FLAG_DMA; + } + return 0; +} + +static inline int ata_is_atapi(u8 prot) +{ + return ata_prot_flags(prot) & ATA_PROT_FLAG_ATAPI; +} + +static inline int ata_is_nodata(u8 prot) +{ + return !(ata_prot_flags(prot) & ATA_PROT_FLAG_DATA); +} + +static inline int ata_is_pio(u8 prot) +{ + return ata_prot_flags(prot) & ATA_PROT_FLAG_PIO; +} + +static inline int ata_is_dma(u8 prot) +{ + return ata_prot_flags(prot) & ATA_PROT_FLAG_DMA; +} + +static inline int ata_is_ncq(u8 prot) +{ + return ata_prot_flags(prot) & ATA_PROT_FLAG_NCQ; +} + +static inline int ata_is_data(u8 prot) +{ + return ata_prot_flags(prot) & ATA_PROT_FLAG_DATA; +} + +static inline int is_multi_taskfile(struct ata_taskfile *tf) +{ + return (tf->command == ATA_CMD_READ_MULTI) || + (tf->command == ATA_CMD_WRITE_MULTI) || + (tf->command == ATA_CMD_READ_MULTI_EXT) || + (tf->command == ATA_CMD_WRITE_MULTI_EXT) || + (tf->command == ATA_CMD_WRITE_MULTI_FUA_EXT); +} + static inline const unsigned long * sata_ehc_deb_timing(struct ata_eh_context *ehc) { From 9b710506a03b01a9fdd83962912bc9d8237b82e8 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 16 Jul 2013 15:20:14 -0700 Subject: [PATCH 0173/3400] x86, bitops: Change bitops to be native operand size Change the bitops operation to be naturally "long", i.e. 63 bits on the 64-bit kernel. Additional bugs are likely to crop up in the future. We already have bugs which machines with > 16 TiB of memory in a single node, as can happen if memory is interleaved. The x86 bitop operations take a signed index, so using an unsigned type is not an option. Jim Kukunas measured the effect of this patch on kernel size: it adds 2779 bytes to the allyesconfig kernel. Some of that probably could be elided by replacing the inline functions with macros which select the 32-bit type if the index is a 32-bit value, something like: In that case we could also use "Jr" constraints for the 64-bit version. However, this would more than double the amount of code for a relatively small gain. Note that we can't use ilog2() for _BITOPS_LONG_SHIFT, as that causes a recursive header inclusion problem. The change to constant_test_bit() should both generate better code and give correct result for negative bit indicies. As previously written the compiler had to generate extra code to create the proper wrong result for negative values. Signed-off-by: H. Peter Anvin Cc: Jim Kukunas Link: http://lkml.kernel.org/n/tip-z61ofiwe90xeyb461o72h8ya@git.kernel.org --- arch/x86/include/asm/bitops.h | 46 ++++++++++++++++++------------ arch/x86/include/asm/sync_bitops.h | 24 ++++++++-------- 2 files changed, 39 insertions(+), 31 deletions(-) diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h index 6dfd0195bb55..41639ce8fd63 100644 --- a/arch/x86/include/asm/bitops.h +++ b/arch/x86/include/asm/bitops.h @@ -15,6 +15,14 @@ #include #include +#if BITS_PER_LONG == 32 +# define _BITOPS_LONG_SHIFT 5 +#elif BITS_PER_LONG == 64 +# define _BITOPS_LONG_SHIFT 6 +#else +# error "Unexpected BITS_PER_LONG" +#endif + #define BIT_64(n) (U64_C(1) << (n)) /* @@ -59,7 +67,7 @@ * restricted to acting on a single-word quantity. */ static __always_inline void -set_bit(unsigned int nr, volatile unsigned long *addr) +set_bit(long nr, volatile unsigned long *addr) { if (IS_IMMEDIATE(nr)) { asm volatile(LOCK_PREFIX "orb %1,%0" @@ -81,7 +89,7 @@ set_bit(unsigned int nr, volatile unsigned long *addr) * If it's called on the same region of memory simultaneously, the effect * may be that only one operation succeeds. */ -static inline void __set_bit(int nr, volatile unsigned long *addr) +static inline void __set_bit(long nr, volatile unsigned long *addr) { asm volatile("bts %1,%0" : ADDR : "Ir" (nr) : "memory"); } @@ -97,7 +105,7 @@ static inline void __set_bit(int nr, volatile unsigned long *addr) * in order to ensure changes are visible on other processors. */ static __always_inline void -clear_bit(int nr, volatile unsigned long *addr) +clear_bit(long nr, volatile unsigned long *addr) { if (IS_IMMEDIATE(nr)) { asm volatile(LOCK_PREFIX "andb %1,%0" @@ -118,13 +126,13 @@ clear_bit(int nr, volatile unsigned long *addr) * clear_bit() is atomic and implies release semantics before the memory * operation. It can be used for an unlock. */ -static inline void clear_bit_unlock(unsigned nr, volatile unsigned long *addr) +static inline void clear_bit_unlock(long nr, volatile unsigned long *addr) { barrier(); clear_bit(nr, addr); } -static inline void __clear_bit(int nr, volatile unsigned long *addr) +static inline void __clear_bit(long nr, volatile unsigned long *addr) { asm volatile("btr %1,%0" : ADDR : "Ir" (nr)); } @@ -141,7 +149,7 @@ static inline void __clear_bit(int nr, volatile unsigned long *addr) * No memory barrier is required here, because x86 cannot reorder stores past * older loads. Same principle as spin_unlock. */ -static inline void __clear_bit_unlock(unsigned nr, volatile unsigned long *addr) +static inline void __clear_bit_unlock(long nr, volatile unsigned long *addr) { barrier(); __clear_bit(nr, addr); @@ -159,7 +167,7 @@ static inline void __clear_bit_unlock(unsigned nr, volatile unsigned long *addr) * If it's called on the same region of memory simultaneously, the effect * may be that only one operation succeeds. */ -static inline void __change_bit(int nr, volatile unsigned long *addr) +static inline void __change_bit(long nr, volatile unsigned long *addr) { asm volatile("btc %1,%0" : ADDR : "Ir" (nr)); } @@ -173,7 +181,7 @@ static inline void __change_bit(int nr, volatile unsigned long *addr) * Note that @nr may be almost arbitrarily large; this function is not * restricted to acting on a single-word quantity. */ -static inline void change_bit(int nr, volatile unsigned long *addr) +static inline void change_bit(long nr, volatile unsigned long *addr) { if (IS_IMMEDIATE(nr)) { asm volatile(LOCK_PREFIX "xorb %1,%0" @@ -194,7 +202,7 @@ static inline void change_bit(int nr, volatile unsigned long *addr) * This operation is atomic and cannot be reordered. * It also implies a memory barrier. */ -static inline int test_and_set_bit(int nr, volatile unsigned long *addr) +static inline int test_and_set_bit(long nr, volatile unsigned long *addr) { int oldbit; @@ -212,7 +220,7 @@ static inline int test_and_set_bit(int nr, volatile unsigned long *addr) * This is the same as test_and_set_bit on x86. */ static __always_inline int -test_and_set_bit_lock(int nr, volatile unsigned long *addr) +test_and_set_bit_lock(long nr, volatile unsigned long *addr) { return test_and_set_bit(nr, addr); } @@ -226,7 +234,7 @@ test_and_set_bit_lock(int nr, volatile unsigned long *addr) * If two examples of this operation race, one can appear to succeed * but actually fail. You must protect multiple accesses with a lock. */ -static inline int __test_and_set_bit(int nr, volatile unsigned long *addr) +static inline int __test_and_set_bit(long nr, volatile unsigned long *addr) { int oldbit; @@ -245,7 +253,7 @@ static inline int __test_and_set_bit(int nr, volatile unsigned long *addr) * This operation is atomic and cannot be reordered. * It also implies a memory barrier. */ -static inline int test_and_clear_bit(int nr, volatile unsigned long *addr) +static inline int test_and_clear_bit(long nr, volatile unsigned long *addr) { int oldbit; @@ -272,7 +280,7 @@ static inline int test_and_clear_bit(int nr, volatile unsigned long *addr) * accessed from a hypervisor on the same CPU if running in a VM: don't change * this without also updating arch/x86/kernel/kvm.c */ -static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr) +static inline int __test_and_clear_bit(long nr, volatile unsigned long *addr) { int oldbit; @@ -284,7 +292,7 @@ static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr) } /* WARNING: non atomic and it can be reordered! */ -static inline int __test_and_change_bit(int nr, volatile unsigned long *addr) +static inline int __test_and_change_bit(long nr, volatile unsigned long *addr) { int oldbit; @@ -304,7 +312,7 @@ static inline int __test_and_change_bit(int nr, volatile unsigned long *addr) * This operation is atomic and cannot be reordered. * It also implies a memory barrier. */ -static inline int test_and_change_bit(int nr, volatile unsigned long *addr) +static inline int test_and_change_bit(long nr, volatile unsigned long *addr) { int oldbit; @@ -315,13 +323,13 @@ static inline int test_and_change_bit(int nr, volatile unsigned long *addr) return oldbit; } -static __always_inline int constant_test_bit(unsigned int nr, const volatile unsigned long *addr) +static __always_inline int constant_test_bit(long nr, const volatile unsigned long *addr) { - return ((1UL << (nr % BITS_PER_LONG)) & - (addr[nr / BITS_PER_LONG])) != 0; + return ((1UL << (nr & (BITS_PER_LONG-1))) & + (addr[nr >> _BITOPS_LONG_SHIFT])) != 0; } -static inline int variable_test_bit(int nr, volatile const unsigned long *addr) +static inline int variable_test_bit(long nr, volatile const unsigned long *addr) { int oldbit; diff --git a/arch/x86/include/asm/sync_bitops.h b/arch/x86/include/asm/sync_bitops.h index 9d09b4073b60..05af3b31d522 100644 --- a/arch/x86/include/asm/sync_bitops.h +++ b/arch/x86/include/asm/sync_bitops.h @@ -26,9 +26,9 @@ * Note that @nr may be almost arbitrarily large; this function is not * restricted to acting on a single-word quantity. */ -static inline void sync_set_bit(int nr, volatile unsigned long *addr) +static inline void sync_set_bit(long nr, volatile unsigned long *addr) { - asm volatile("lock; btsl %1,%0" + asm volatile("lock; bts %1,%0" : "+m" (ADDR) : "Ir" (nr) : "memory"); @@ -44,9 +44,9 @@ static inline void sync_set_bit(int nr, volatile unsigned long *addr) * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit() * in order to ensure changes are visible on other processors. */ -static inline void sync_clear_bit(int nr, volatile unsigned long *addr) +static inline void sync_clear_bit(long nr, volatile unsigned long *addr) { - asm volatile("lock; btrl %1,%0" + asm volatile("lock; btr %1,%0" : "+m" (ADDR) : "Ir" (nr) : "memory"); @@ -61,9 +61,9 @@ static inline void sync_clear_bit(int nr, volatile unsigned long *addr) * Note that @nr may be almost arbitrarily large; this function is not * restricted to acting on a single-word quantity. */ -static inline void sync_change_bit(int nr, volatile unsigned long *addr) +static inline void sync_change_bit(long nr, volatile unsigned long *addr) { - asm volatile("lock; btcl %1,%0" + asm volatile("lock; btc %1,%0" : "+m" (ADDR) : "Ir" (nr) : "memory"); @@ -77,11 +77,11 @@ static inline void sync_change_bit(int nr, volatile unsigned long *addr) * This operation is atomic and cannot be reordered. * It also implies a memory barrier. */ -static inline int sync_test_and_set_bit(int nr, volatile unsigned long *addr) +static inline int sync_test_and_set_bit(long nr, volatile unsigned long *addr) { int oldbit; - asm volatile("lock; btsl %2,%1\n\tsbbl %0,%0" + asm volatile("lock; bts %2,%1\n\tsbbl %0,%0" : "=r" (oldbit), "+m" (ADDR) : "Ir" (nr) : "memory"); return oldbit; @@ -95,11 +95,11 @@ static inline int sync_test_and_set_bit(int nr, volatile unsigned long *addr) * This operation is atomic and cannot be reordered. * It also implies a memory barrier. */ -static inline int sync_test_and_clear_bit(int nr, volatile unsigned long *addr) +static inline int sync_test_and_clear_bit(long nr, volatile unsigned long *addr) { int oldbit; - asm volatile("lock; btrl %2,%1\n\tsbbl %0,%0" + asm volatile("lock; btr %2,%1\n\tsbbl %0,%0" : "=r" (oldbit), "+m" (ADDR) : "Ir" (nr) : "memory"); return oldbit; @@ -113,11 +113,11 @@ static inline int sync_test_and_clear_bit(int nr, volatile unsigned long *addr) * This operation is atomic and cannot be reordered. * It also implies a memory barrier. */ -static inline int sync_test_and_change_bit(int nr, volatile unsigned long *addr) +static inline int sync_test_and_change_bit(long nr, volatile unsigned long *addr) { int oldbit; - asm volatile("lock; btcl %2,%1\n\tsbbl %0,%0" + asm volatile("lock; btc %2,%1\n\tsbbl %0,%0" : "=r" (oldbit), "+m" (ADDR) : "Ir" (nr) : "memory"); return oldbit; From fd4363fff3d96795d3feb1b3fb48ce590f186bdd Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Fri, 12 Jul 2013 11:21:48 +0200 Subject: [PATCH 0174/3400] x86: Introduce int3 (breakpoint)-based instruction patching Introduce a method for run-time instruction patching on a live SMP kernel based on int3 breakpoint, completely avoiding the need for stop_machine(). The way this is achieved: - add a int3 trap to the address that will be patched - sync cores - update all but the first byte of the patched range - sync cores - replace the first byte (int3) by the first byte of replacing opcode - sync cores According to http://lkml.indiana.edu/hypermail/linux/kernel/1001.1/01530.html synchronization after replacing "all but first" instructions should not be necessary (on Intel hardware), as the syncing after the subsequent patching of the first byte provides enough safety. But there's not only Intel HW out there, and we'd rather be on a safe side. If any CPU instruction execution would collide with the patching, it'd be trapped by the int3 breakpoint and redirected to the provided "handler" (which would typically mean just skipping over the patched region, acting as "nop" has been there, in case we are doing nop -> jump and jump -> nop transitions). Ftrace has been using this very technique since 08d636b ("ftrace/x86: Have arch x86_64 use breakpoints instead of stop machine") for ages already, and jump labels are another obvious potential user of this. Based on activities of Masami Hiramatsu a few years ago. Reviewed-by: Steven Rostedt Reviewed-by: Masami Hiramatsu Signed-off-by: Jiri Kosina Link: http://lkml.kernel.org/r/alpine.LNX.2.00.1307121102440.29788@pobox.suse.cz Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/alternative.h | 1 + arch/x86/kernel/alternative.c | 106 +++++++++++++++++++++++++++++ kernel/kprobes.c | 2 +- 3 files changed, 108 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h index 58ed6d96a6ac..3abf8dd6f44f 100644 --- a/arch/x86/include/asm/alternative.h +++ b/arch/x86/include/asm/alternative.h @@ -233,6 +233,7 @@ struct text_poke_param { }; extern void *text_poke(void *addr, const void *opcode, size_t len); +extern void *text_poke_bp(void *addr, const void *opcode, size_t len, void *handler); extern void *text_poke_smp(void *addr, const void *opcode, size_t len); extern void text_poke_smp_batch(struct text_poke_param *params, int n); diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index c15cf9a25e27..0ab49366a7a6 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -596,6 +597,111 @@ void *__kprobes text_poke(void *addr, const void *opcode, size_t len) return addr; } +static void do_sync_core(void *info) +{ + sync_core(); +} + +static bool bp_patching_in_progress; +static void *bp_int3_handler, *bp_int3_addr; + +static int int3_notify(struct notifier_block *self, unsigned long val, void *data) +{ + struct die_args *args = data; + + /* bp_patching_in_progress */ + smp_rmb(); + + if (likely(!bp_patching_in_progress)) + return NOTIFY_DONE; + + /* we are not interested in non-int3 faults and ring > 0 faults */ + if (val != DIE_INT3 || !args->regs || user_mode_vm(args->regs) + || args->regs->ip != (unsigned long)bp_int3_addr) + return NOTIFY_DONE; + + /* set up the specified breakpoint handler */ + args->regs->ip = (unsigned long) bp_int3_handler; + + return NOTIFY_STOP; +} +/** + * text_poke_bp() -- update instructions on live kernel on SMP + * @addr: address to patch + * @opcode: opcode of new instruction + * @len: length to copy + * @handler: address to jump to when the temporary breakpoint is hit + * + * Modify multi-byte instruction by using int3 breakpoint on SMP. + * In contrary to text_poke_smp(), we completely avoid stop_machine() here, + * and achieve the synchronization using int3 breakpoint. + * + * The way it is done: + * - add a int3 trap to the address that will be patched + * - sync cores + * - update all but the first byte of the patched range + * - sync cores + * - replace the first byte (int3) by the first byte of + * replacing opcode + * - sync cores + * + * Note: must be called under text_mutex. + */ +void *text_poke_bp(void *addr, const void *opcode, size_t len, void *handler) +{ + unsigned char int3 = 0xcc; + + bp_int3_handler = handler; + bp_int3_addr = (u8 *)addr + sizeof(int3); + bp_patching_in_progress = true; + /* + * Corresponding read barrier in int3 notifier for + * making sure the in_progress flags is correctly ordered wrt. + * patching + */ + smp_wmb(); + + text_poke(addr, &int3, sizeof(int3)); + + on_each_cpu(do_sync_core, NULL, 1); + + if (len - sizeof(int3) > 0) { + /* patch all but the first byte */ + text_poke((char *)addr + sizeof(int3), + (const char *) opcode + sizeof(int3), + len - sizeof(int3)); + /* + * According to Intel, this core syncing is very likely + * not necessary and we'd be safe even without it. But + * better safe than sorry (plus there's not only Intel). + */ + on_each_cpu(do_sync_core, NULL, 1); + } + + /* patch the first byte */ + text_poke(addr, opcode, sizeof(int3)); + + on_each_cpu(do_sync_core, NULL, 1); + + bp_patching_in_progress = false; + smp_wmb(); + + return addr; +} + +/* this one needs to run before anything else handles it as a + * regular exception */ +static struct notifier_block int3_nb = { + .priority = 0x7fffffff, + .notifier_call = int3_notify +}; + +static int __init int3_init(void) +{ + return register_die_notifier(&int3_nb); +} + +arch_initcall(int3_init); /* * Cross-modifying kernel text with stop_machine(). * This code originally comes from immediate value. diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 6e33498d665c..b58b490fa439 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -1709,7 +1709,7 @@ EXPORT_SYMBOL_GPL(unregister_kprobes); static struct notifier_block kprobe_exceptions_nb = { .notifier_call = kprobe_exceptions_notify, - .priority = 0x7fffffff /* we need to be notified first */ + .priority = 0x7ffffff0 /* High priority, but not first. */ }; unsigned long __weak arch_deref_entry_point(void *entry) From 51b2c07b22261f19188d9a9071943d60a067481c Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Fri, 12 Jul 2013 11:22:09 +0200 Subject: [PATCH 0175/3400] x86: Make jump_label use int3-based patching Make jump labels use text_poke_bp() for text patching instead of text_poke_smp(), avoiding the need for stop_machine(). Reviewed-by: Steven Rostedt Reviewed-by: Masami Hiramatsu Signed-off-by: Jiri Kosina Link: http://lkml.kernel.org/r/alpine.LNX.2.00.1307121120250.29788@pobox.suse.cz Signed-off-by: H. Peter Anvin --- arch/x86/kernel/jump_label.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/jump_label.c b/arch/x86/kernel/jump_label.c index 2889b3d43882..460f5d9ceebb 100644 --- a/arch/x86/kernel/jump_label.c +++ b/arch/x86/kernel/jump_label.c @@ -37,7 +37,19 @@ static void __jump_label_transform(struct jump_entry *entry, } else memcpy(&code, ideal_nops[NOP_ATOMIC5], JUMP_LABEL_NOP_SIZE); - (*poker)((void *)entry->code, &code, JUMP_LABEL_NOP_SIZE); + /* + * Make text_poke_bp() a default fallback poker. + * + * At the time the change is being done, just ignore whether we + * are doing nop -> jump or jump -> nop transition, and assume + * always nop being the 'currently valid' instruction + * + */ + if (poker) + (*poker)((void *)entry->code, &code, JUMP_LABEL_NOP_SIZE); + else + text_poke_bp((void *)entry->code, &code, JUMP_LABEL_NOP_SIZE, + (void *)entry->code + JUMP_LABEL_NOP_SIZE); } void arch_jump_label_transform(struct jump_entry *entry, @@ -45,7 +57,7 @@ void arch_jump_label_transform(struct jump_entry *entry, { get_online_cpus(); mutex_lock(&text_mutex); - __jump_label_transform(entry, type, text_poke_smp); + __jump_label_transform(entry, type, NULL); mutex_unlock(&text_mutex); put_online_cpus(); } From dfec4a6e42286dacc733c7e6be43606a5622ca58 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Tue, 16 Jul 2013 17:16:22 +0200 Subject: [PATCH 0176/3400] spi: atmel: prepare clk before calling enable Replace clk_enable/disable with clk_prepare_enable/disable_unprepare to avoid common clk framework warnings. Signed-off-by: Boris BREZILLON Signed-off-by: Mark Brown --- drivers/spi/spi-atmel.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index ea1ec009f44d..4c6c455685c2 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -1579,7 +1579,9 @@ static int atmel_spi_probe(struct platform_device *pdev) goto out_unmap_regs; /* Initialize the hardware */ - clk_enable(clk); + ret = clk_prepare_enable(clk); + if (ret) + goto out_unmap_regs; spi_writel(as, CR, SPI_BIT(SWRST)); spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */ if (as->caps.has_wdrbt) { @@ -1609,7 +1611,7 @@ out_free_dma: spi_writel(as, CR, SPI_BIT(SWRST)); spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */ - clk_disable(clk); + clk_disable_unprepare(clk); free_irq(irq, master); out_unmap_regs: iounmap(as->regs); @@ -1661,7 +1663,7 @@ static int atmel_spi_remove(struct platform_device *pdev) dma_free_coherent(&pdev->dev, BUFFER_SIZE, as->buffer, as->buffer_dma); - clk_disable(as->clk); + clk_disable_unprepare(as->clk); clk_put(as->clk); free_irq(as->irq, master); iounmap(as->regs); @@ -1678,7 +1680,7 @@ static int atmel_spi_suspend(struct platform_device *pdev, pm_message_t mesg) struct spi_master *master = platform_get_drvdata(pdev); struct atmel_spi *as = spi_master_get_devdata(master); - clk_disable(as->clk); + clk_disable_unprepare(as->clk); return 0; } @@ -1687,7 +1689,7 @@ static int atmel_spi_resume(struct platform_device *pdev) struct spi_master *master = platform_get_drvdata(pdev); struct atmel_spi *as = spi_master_get_devdata(master); - clk_enable(as->clk); + return clk_prepare_enable(as->clk); return 0; } From 393536f8b9bbcafce2d334153783c0b7382ca457 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Tue, 16 Jul 2013 11:41:09 -0500 Subject: [PATCH 0177/3400] regulator: palmas-pmic: doc: fix typo for sleep-mode commit 3c870e3f9d9d98f1ab98614b3b1fd5c79287d361 (regulator: palmas: Change the DT node property names to follow the convention) Missed updating mode-sleep from sleep-mode. Fix the same. Documentation example seems proper for this property. Signed-off-by: Nishanth Menon Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/regulator/palmas-pmic.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/regulator/palmas-pmic.txt b/Documentation/devicetree/bindings/regulator/palmas-pmic.txt index d5a308629c57..04d67f092383 100644 --- a/Documentation/devicetree/bindings/regulator/palmas-pmic.txt +++ b/Documentation/devicetree/bindings/regulator/palmas-pmic.txt @@ -31,7 +31,7 @@ Optional nodes: Optional sub-node properties: ti,warm-reset - maintain voltage during warm reset(boolean) ti,roof-floor - control voltage selection by pin(boolean) - ti,sleep-mode - mode to adopt in pmic sleep 0 - off, 1 - auto, + ti,mode-sleep - mode to adopt in pmic sleep 0 - off, 1 - auto, 2 - eco, 3 - forced pwm ti,tstep - slope control 0 - Jump, 1 10mV/us, 2 5mV/us, 3 2.5mV/us ti,smps-range - OTP has the wrong range set for the hardware so override From 386c90ac747913f1a31a0cdacb14f2347114474d Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Tue, 16 Jul 2013 11:41:10 -0500 Subject: [PATCH 0178/3400] regulator: palmas-pmic: doc: remove ti,tstep commit 28d1e8cd671a53d6b4f967abbbc2a55f7bd333f6 (regulator: palma: add ramp delay support through regulator constraints) Removed the regulator's ti,step option from driver without updating the documentation. So, remove from documentation and example as well. Signed-off-by: Nishanth Menon Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/regulator/palmas-pmic.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/Documentation/devicetree/bindings/regulator/palmas-pmic.txt b/Documentation/devicetree/bindings/regulator/palmas-pmic.txt index 04d67f092383..30b0581bb1ce 100644 --- a/Documentation/devicetree/bindings/regulator/palmas-pmic.txt +++ b/Documentation/devicetree/bindings/regulator/palmas-pmic.txt @@ -33,7 +33,6 @@ Optional nodes: ti,roof-floor - control voltage selection by pin(boolean) ti,mode-sleep - mode to adopt in pmic sleep 0 - off, 1 - auto, 2 - eco, 3 - forced pwm - ti,tstep - slope control 0 - Jump, 1 10mV/us, 2 5mV/us, 3 2.5mV/us ti,smps-range - OTP has the wrong range set for the hardware so override 0 - low range, 1 - high range. @@ -59,7 +58,6 @@ pmic { ti,warm-reset; ti,roof-floor; ti,mode-sleep = <0>; - ti,tstep = <0>; ti,smps-range = <1>; }; From 84ddb3c1df021c69a40af30e3e30cc7429a5d659 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 8 Jul 2013 09:12:37 -0700 Subject: [PATCH 0179/3400] spi: spi-ep93xx: convert to the queued driver infrastructure The SPI core provides infrastructure for standard message queueing. Use that instead of handling it in the driver. Signed-off-by: H Hartley Sweeten Acked-by: Mika Westerberg Signed-off-by: Mark Brown --- drivers/spi/spi-ep93xx.c | 165 +++++---------------------------------- 1 file changed, 19 insertions(+), 146 deletions(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index 2e64806b40af..4c9a50ce4f6c 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -70,19 +69,13 @@ /** * struct ep93xx_spi - EP93xx SPI controller structure - * @lock: spinlock that protects concurrent accesses to fields @running, - * @current_msg and @msg_queue * @pdev: pointer to platform device * @clk: clock for the controller * @regs_base: pointer to ioremap()'d registers * @sspdr_phys: physical address of the SSPDR register * @min_rate: minimum clock rate (in Hz) supported by the controller * @max_rate: maximum clock rate (in Hz) supported by the controller - * @running: is the queue running - * @wq: workqueue used by the driver - * @msg_work: work that is queued for the driver * @wait: wait here until given transfer is completed - * @msg_queue: queue for the messages * @current_msg: message that is currently processed (or %NULL if none) * @tx: current byte in transfer to transmit * @rx: current byte in transfer to receive @@ -96,30 +89,15 @@ * @tx_sgt: sg table for TX transfers * @zeropage: dummy page used as RX buffer when only TX buffer is passed in by * the client - * - * This structure holds EP93xx SPI controller specific information. When - * @running is %true, driver accepts transfer requests from protocol drivers. - * @current_msg is used to hold pointer to the message that is currently - * processed. If @current_msg is %NULL, it means that no processing is going - * on. - * - * Most of the fields are only written once and they can be accessed without - * taking the @lock. Fields that are accessed concurrently are: @current_msg, - * @running, and @msg_queue. */ struct ep93xx_spi { - spinlock_t lock; const struct platform_device *pdev; struct clk *clk; void __iomem *regs_base; unsigned long sspdr_phys; unsigned long min_rate; unsigned long max_rate; - bool running; - struct workqueue_struct *wq; - struct work_struct msg_work; struct completion wait; - struct list_head msg_queue; struct spi_message *current_msg; size_t tx; size_t rx; @@ -230,7 +208,7 @@ static int ep93xx_spi_calc_divisors(const struct ep93xx_spi *espi, /* * Make sure that max value is between values supported by the * controller. Note that minimum value is already checked in - * ep93xx_spi_transfer(). + * ep93xx_spi_transfer_one_message(). */ rate = clamp(rate, espi->min_rate, espi->max_rate); @@ -305,54 +283,6 @@ static int ep93xx_spi_setup(struct spi_device *spi) return 0; } -/** - * ep93xx_spi_transfer() - queue message to be transferred - * @spi: target SPI device - * @msg: message to be transferred - * - * This function is called by SPI device drivers when they are going to transfer - * a new message. It simply puts the message in the queue and schedules - * workqueue to perform the actual transfer later on. - * - * Returns %0 on success and negative error in case of failure. - */ -static int ep93xx_spi_transfer(struct spi_device *spi, struct spi_message *msg) -{ - struct ep93xx_spi *espi = spi_master_get_devdata(spi->master); - struct spi_transfer *t; - unsigned long flags; - - if (!msg || !msg->complete) - return -EINVAL; - - /* first validate each transfer */ - list_for_each_entry(t, &msg->transfers, transfer_list) { - if (t->speed_hz && t->speed_hz < espi->min_rate) - return -EINVAL; - } - - /* - * Now that we own the message, let's initialize it so that it is - * suitable for us. We use @msg->status to signal whether there was - * error in transfer and @msg->state is used to hold pointer to the - * current transfer (or %NULL if no active current transfer). - */ - msg->state = NULL; - msg->status = 0; - msg->actual_length = 0; - - spin_lock_irqsave(&espi->lock, flags); - if (!espi->running) { - spin_unlock_irqrestore(&espi->lock, flags); - return -ESHUTDOWN; - } - list_add_tail(&msg->queue, &espi->msg_queue); - queue_work(espi->wq, &espi->msg_work); - spin_unlock_irqrestore(&espi->lock, flags); - - return 0; -} - /** * ep93xx_spi_cleanup() - cleans up master controller specific state * @spi: SPI device to cleanup @@ -801,50 +731,29 @@ static void ep93xx_spi_process_message(struct ep93xx_spi *espi, ep93xx_spi_disable(espi); } -#define work_to_espi(work) (container_of((work), struct ep93xx_spi, msg_work)) - -/** - * ep93xx_spi_work() - EP93xx SPI workqueue worker function - * @work: work struct - * - * Workqueue worker function. This function is called when there are new - * SPI messages to be processed. Message is taken out from the queue and then - * passed to ep93xx_spi_process_message(). - * - * After message is transferred, protocol driver is notified by calling - * @msg->complete(). In case of error, @msg->status is set to negative error - * number, otherwise it contains zero (and @msg->actual_length is updated). - */ -static void ep93xx_spi_work(struct work_struct *work) +static int ep93xx_spi_transfer_one_message(struct spi_master *master, + struct spi_message *msg) { - struct ep93xx_spi *espi = work_to_espi(work); - struct spi_message *msg; + struct ep93xx_spi *espi = spi_master_get_devdata(master); + struct spi_transfer *t; - spin_lock_irq(&espi->lock); - if (!espi->running || espi->current_msg || - list_empty(&espi->msg_queue)) { - spin_unlock_irq(&espi->lock); - return; + /* first validate each transfer */ + list_for_each_entry(t, &msg->transfers, transfer_list) { + if (t->speed_hz < espi->min_rate) + return -EINVAL; } - msg = list_first_entry(&espi->msg_queue, struct spi_message, queue); - list_del_init(&msg->queue); + + msg->state = NULL; + msg->status = 0; + msg->actual_length = 0; + espi->current_msg = msg; - spin_unlock_irq(&espi->lock); - ep93xx_spi_process_message(espi, msg); - - /* - * Update the current message and re-schedule ourselves if there are - * more messages in the queue. - */ - spin_lock_irq(&espi->lock); espi->current_msg = NULL; - if (espi->running && !list_empty(&espi->msg_queue)) - queue_work(espi->wq, &espi->msg_work); - spin_unlock_irq(&espi->lock); - /* notify the protocol driver that we are done with this message */ - msg->complete(msg->context); + spi_finalize_current_message(master); + + return 0; } static irqreturn_t ep93xx_spi_interrupt(int irq, void *dev_id) @@ -984,7 +893,7 @@ static int ep93xx_spi_probe(struct platform_device *pdev) return -ENOMEM; master->setup = ep93xx_spi_setup; - master->transfer = ep93xx_spi_transfer; + master->transfer_one_message = ep93xx_spi_transfer_one_message; master->cleanup = ep93xx_spi_cleanup; master->bus_num = pdev->id; master->num_chipselect = info->num_chipselect; @@ -1002,7 +911,6 @@ static int ep93xx_spi_probe(struct platform_device *pdev) goto fail_release_master; } - spin_lock_init(&espi->lock); init_completion(&espi->wait); /* @@ -1031,23 +939,13 @@ static int ep93xx_spi_probe(struct platform_device *pdev) if (info->use_dma && ep93xx_spi_setup_dma(espi)) dev_warn(&pdev->dev, "DMA setup failed. Falling back to PIO\n"); - espi->wq = create_singlethread_workqueue("ep93xx_spid"); - if (!espi->wq) { - dev_err(&pdev->dev, "unable to create workqueue\n"); - error = -ENOMEM; - goto fail_free_dma; - } - INIT_WORK(&espi->msg_work, ep93xx_spi_work); - INIT_LIST_HEAD(&espi->msg_queue); - espi->running = true; - /* make sure that the hardware is disabled */ ep93xx_spi_write_u8(espi, SSPCR1, 0); error = spi_register_master(master); if (error) { dev_err(&pdev->dev, "failed to register SPI master\n"); - goto fail_free_queue; + goto fail_free_dma; } dev_info(&pdev->dev, "EP93xx SPI Controller at 0x%08lx irq %d\n", @@ -1055,8 +953,6 @@ static int ep93xx_spi_probe(struct platform_device *pdev) return 0; -fail_free_queue: - destroy_workqueue(espi->wq); fail_free_dma: ep93xx_spi_release_dma(espi); fail_release_master: @@ -1070,29 +966,6 @@ static int ep93xx_spi_remove(struct platform_device *pdev) struct spi_master *master = platform_get_drvdata(pdev); struct ep93xx_spi *espi = spi_master_get_devdata(master); - spin_lock_irq(&espi->lock); - espi->running = false; - spin_unlock_irq(&espi->lock); - - destroy_workqueue(espi->wq); - - /* - * Complete remaining messages with %-ESHUTDOWN status. - */ - spin_lock_irq(&espi->lock); - while (!list_empty(&espi->msg_queue)) { - struct spi_message *msg; - - msg = list_first_entry(&espi->msg_queue, - struct spi_message, queue); - list_del_init(&msg->queue); - msg->status = -ESHUTDOWN; - spin_unlock_irq(&espi->lock); - msg->complete(msg->context); - spin_lock_irq(&espi->lock); - } - spin_unlock_irq(&espi->lock); - ep93xx_spi_release_dma(espi); spi_unregister_master(master); From ab4ecda5205b56cb3b8b44f2c18ffdefb24313a2 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 16 Jul 2013 16:50:36 +0200 Subject: [PATCH 0180/3400] perf tools: Fix 'make tools/perf' Boris just raised another variant of building perf tools which is broken: $ make tools/perf ... LINK /home/robert/cx/linux/tools/perf/perf gcc: error: ../linux/tools/lib/lk/liblk.a: No such file or directory The variant wasn't considered by: 107de37 perf tools: Fix build errors with O and DESTDIR make vars set There are other variant of building perf too: $ make -C tools perf $ make -C tools/perf Plus variants with O= and DESTDIR set. This patch fixes the above and was tested with the following: $ make O=... DESTDIR=... tools/perf $ make O=... DESTDIR=... -C tools/ perf $ make O=... DESTDIR=... -C tools/perf $ make tools/perf $ make -C tools/ perf $ make -C tools/perf Reported-by: Borislav Petkov Signed-off-by: Robert Richter Signed-off-by: Robert Richter Cc: Borislav Petkov Cc: H. Peter Anvin Cc: Ingo Molnar Cc: Jiri Olsa Cc: Thomas Gleixner Cc: linux-tip-commits@vger.kernel.org Link: http://lkml.kernel.org/r/20130716145036.GH8731@rric.localhost Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 5b7c6db87fde..2a6902677141 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -124,7 +124,7 @@ strip-libs = $(filter-out -l%,$(1)) ifneq ($(OUTPUT),) TE_PATH=$(OUTPUT) ifneq ($(subdir),) - LK_PATH=$(objtree)/lib/lk/ + LK_PATH=$(OUTPUT)/../lib/lk/ else LK_PATH=$(OUTPUT) endif From 5698d2c99ec11006b4c241ebad5252289902b358 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 17 Jul 2013 17:08:15 +0900 Subject: [PATCH 0181/3400] perf symbols: Do not apply symfs for an absolute vmlinux path If an user gives both of --symfs and --vmlinux option, the vmlinux will be searched under the symfs directory. This is somewhat confusing since vmlinux often lives in kernel build directory or somewhere other than user space binaries. So it'd be better not adding symfs prefix for a vmlinux if it has an absolute pathname. Reported-by: Kwanghyun Yoo Signed-off-by: Namhyung Kim Acked-by: David Ahern Cc: David Ahern Cc: Ingo Molnar Cc: Jiri Olsa Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1374048495-3643-1-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/symbol.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index d5528e1cc03a..02718e728d59 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -888,8 +888,11 @@ int dso__load_vmlinux(struct dso *dso, struct map *map, char symfs_vmlinux[PATH_MAX]; enum dso_binary_type symtab_type; - snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s%s", - symbol_conf.symfs, vmlinux); + if (vmlinux[0] == '/') + snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s", vmlinux); + else + snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s%s", + symbol_conf.symfs, vmlinux); if (dso->kernel == DSO_TYPE_GUEST_KERNEL) symtab_type = DSO_BINARY_TYPE__GUEST_VMLINUX; From 8d76e1852794fac6ff0b538120d9856b0b07ef8a Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 12 Jul 2013 16:29:06 +0200 Subject: [PATCH 0182/3400] perf tests: Check proper prev_state size for sched_switch tp The prev_state is defined as long which is 4 bytes long on 32-bit x86. Changing the check against sizeof(long). Signed-off-by: Jiri Olsa Cc: Corey Ashford Cc: Frederic Weisbecker Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1373639346-4547-1-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/evsel-tp-sched.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/tests/evsel-tp-sched.c b/tools/perf/tests/evsel-tp-sched.c index f79e7d059820..9b98c1554833 100644 --- a/tools/perf/tests/evsel-tp-sched.c +++ b/tools/perf/tests/evsel-tp-sched.c @@ -49,7 +49,7 @@ int test__perf_evsel__tp_sched_test(void) if (perf_evsel__test_field(evsel, "prev_prio", 4, true)) ret = -1; - if (perf_evsel__test_field(evsel, "prev_state", 8, true)) + if (perf_evsel__test_field(evsel, "prev_state", sizeof(long), true)) ret = -1; if (perf_evsel__test_field(evsel, "next_comm", 16, true)) From 2025172e32808a327b00f968c72baa79adc594c2 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 5 Jul 2013 20:07:27 +0100 Subject: [PATCH 0183/3400] spi/bitbang: Use core message pump Convert drivers using bitbang to use the core mesasge pump infrastructure, saving some code and meaning that these drivers get to take advantage of work done on improving the core implementation. Signed-off-by: Mark Brown --- drivers/spi/spi-bitbang.c | 100 ++++++++++---------------------- include/linux/spi/spi_bitbang.h | 4 -- 2 files changed, 30 insertions(+), 74 deletions(-) diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c index 8b8487c9694e..c100875cfd42 100644 --- a/drivers/spi/spi-bitbang.c +++ b/drivers/spi/spi-bitbang.c @@ -255,6 +255,21 @@ static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t) * Drivers can provide word-at-a-time i/o primitives, or provide * transfer-at-a-time ones to leverage dma or fifo hardware. */ + +static int spi_bitbang_prepare_hardware(struct spi_master *spi) +{ + struct spi_bitbang *bitbang; + unsigned long flags; + + bitbang = spi_master_get_devdata(spi); + + spin_lock_irqsave(&bitbang->lock, flags); + bitbang->busy = 1; + spin_unlock_irqrestore(&bitbang->lock, flags); + + return 0; +} + static int spi_bitbang_transfer_one(struct spi_device *spi, struct spi_message *m) { @@ -346,7 +361,6 @@ static int spi_bitbang_transfer_one(struct spi_device *spi, } m->status = status; - m->complete(m->context); /* normally deactivate chipselect ... unless no error and * cs_change has hinted that the next message will probably @@ -358,54 +372,23 @@ static int spi_bitbang_transfer_one(struct spi_device *spi, ndelay(nsecs); } + spi_finalize_current_message(spi->master); + return status; } -static void bitbang_work(struct work_struct *work) +static int spi_bitbang_unprepare_hardware(struct spi_master *spi) { - struct spi_bitbang *bitbang = - container_of(work, struct spi_bitbang, work); + struct spi_bitbang *bitbang; unsigned long flags; - struct spi_message *m, *_m; + + bitbang = spi_master_get_devdata(spi); spin_lock_irqsave(&bitbang->lock, flags); - bitbang->busy = 1; - list_for_each_entry_safe(m, _m, &bitbang->queue, queue) { - list_del(&m->queue); - spin_unlock_irqrestore(&bitbang->lock, flags); - - spi_bitbang_transfer_one(m->spi, m); - - spin_lock_irqsave(&bitbang->lock, flags); - } bitbang->busy = 0; spin_unlock_irqrestore(&bitbang->lock, flags); -} -/** - * spi_bitbang_transfer - default submit to transfer queue - */ -static int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m) -{ - struct spi_bitbang *bitbang; - unsigned long flags; - int status = 0; - - m->actual_length = 0; - m->status = -EINPROGRESS; - - bitbang = spi_master_get_devdata(spi->master); - - spin_lock_irqsave(&bitbang->lock, flags); - if (!spi->max_speed_hz) - status = -ENETDOWN; - else { - list_add_tail(&m->queue, &bitbang->queue); - queue_work(bitbang->workqueue, &bitbang->work); - } - spin_unlock_irqrestore(&bitbang->lock, flags); - - return status; + return 0; } /*----------------------------------------------------------------------*/ @@ -436,20 +419,22 @@ static int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m) int spi_bitbang_start(struct spi_bitbang *bitbang) { struct spi_master *master = bitbang->master; - int status; if (!master || !bitbang->chipselect) return -EINVAL; - INIT_WORK(&bitbang->work, bitbang_work); spin_lock_init(&bitbang->lock); - INIT_LIST_HEAD(&bitbang->queue); if (!master->mode_bits) master->mode_bits = SPI_CPOL | SPI_CPHA | bitbang->flags; - if (!master->transfer) - master->transfer = spi_bitbang_transfer; + if (master->transfer || master->transfer_one_message) + return -EINVAL; + + master->prepare_transfer_hardware = spi_bitbang_prepare_hardware; + master->unprepare_transfer_hardware = spi_bitbang_unprepare_hardware; + master->transfer_one_message = spi_bitbang_transfer_one; + if (!bitbang->txrx_bufs) { bitbang->use_dma = 0; bitbang->txrx_bufs = spi_bitbang_bufs; @@ -462,32 +447,11 @@ int spi_bitbang_start(struct spi_bitbang *bitbang) } } else if (!master->setup) return -EINVAL; - if (master->transfer == spi_bitbang_transfer && - !bitbang->setup_transfer) - return -EINVAL; - - /* this task is the only thing to touch the SPI bits */ - bitbang->busy = 0; - bitbang->workqueue = create_singlethread_workqueue( - dev_name(master->dev.parent)); - if (bitbang->workqueue == NULL) { - status = -EBUSY; - goto err1; - } /* driver may get busy before register() returns, especially * if someone registered boardinfo for devices */ - status = spi_register_master(master); - if (status < 0) - goto err2; - - return status; - -err2: - destroy_workqueue(bitbang->workqueue); -err1: - return status; + return spi_register_master(master); } EXPORT_SYMBOL_GPL(spi_bitbang_start); @@ -498,10 +462,6 @@ int spi_bitbang_stop(struct spi_bitbang *bitbang) { spi_unregister_master(bitbang->master); - WARN_ON(!list_empty(&bitbang->queue)); - - destroy_workqueue(bitbang->workqueue); - return 0; } EXPORT_SYMBOL_GPL(spi_bitbang_stop); diff --git a/include/linux/spi/spi_bitbang.h b/include/linux/spi/spi_bitbang.h index b5aa215493f6..daebaba886aa 100644 --- a/include/linux/spi/spi_bitbang.h +++ b/include/linux/spi/spi_bitbang.h @@ -4,11 +4,7 @@ #include struct spi_bitbang { - struct workqueue_struct *workqueue; - struct work_struct work; - spinlock_t lock; - struct list_head queue; u8 busy; u8 use_dma; u8 flags; /* extra spi->mode support */ From 9ca1273bb9d35c81bfb73215556bf794a73a2d83 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 17 Jul 2013 18:34:48 +0300 Subject: [PATCH 0184/3400] spi/xilinx: signedness issue checking platform_get_irq() In xilinx_spi_probe() we use xspi->irq to store negative error codes so it has to be signed. We weren't going to use the upper bit any way so this is fine. Signed-off-by: Dan Carpenter Signed-off-by: Mark Brown --- drivers/spi/spi-xilinx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-xilinx.c b/drivers/spi/spi-xilinx.c index e5d3716da21a..dec7e71a833c 100644 --- a/drivers/spi/spi-xilinx.c +++ b/drivers/spi/spi-xilinx.c @@ -82,7 +82,7 @@ struct xilinx_spi { struct completion done; void __iomem *regs; /* virt. address of the control registers */ - u32 irq; + int irq; u8 *rx_ptr; /* pointer in the Tx buffer */ const u8 *tx_ptr; /* pointer in the Rx buffer */ From d4339569a6f8bb1e703337175dcd4fd4bcd5d891 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Wed, 17 Jul 2013 19:49:41 +0200 Subject: [PATCH 0185/3400] perf session: Use session->fd instead of passing fd as argument Using session->fd instead of passing fd as argument because it's always session->fd that's passed as fd argument. Signed-off-by: Jiri Olsa Cc: Andi Kleen Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1374083403-14591-2-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/header.c | 11 +++++------ tools/perf/util/header.h | 2 +- tools/perf/util/session.c | 4 ++-- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index b28a65ecd61b..b3f253f2841e 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -2619,19 +2619,17 @@ static int perf_file_header__read_pipe(struct perf_pipe_file_header *header, return 0; } -static int perf_header__read_pipe(struct perf_session *session, int fd) +static int perf_header__read_pipe(struct perf_session *session) { struct perf_header *header = &session->header; struct perf_pipe_file_header f_header; - if (perf_file_header__read_pipe(&f_header, header, fd, + if (perf_file_header__read_pipe(&f_header, header, session->fd, session->repipe) < 0) { pr_debug("incompatible file format\n"); return -EINVAL; } - session->fd = fd; - return 0; } @@ -2725,20 +2723,21 @@ static int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist, return 0; } -int perf_session__read_header(struct perf_session *session, int fd) +int perf_session__read_header(struct perf_session *session) { struct perf_header *header = &session->header; struct perf_file_header f_header; struct perf_file_attr f_attr; u64 f_id; int nr_attrs, nr_ids, i, j; + int fd = session->fd; session->evlist = perf_evlist__new(); if (session->evlist == NULL) return -ENOMEM; if (session->fd_pipe) - return perf_header__read_pipe(session, fd); + return perf_header__read_pipe(session); if (perf_file_header__read(&f_header, header, fd) < 0) return -EINVAL; diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index 669fda531da6..0bacb2d6eafa 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h @@ -96,7 +96,7 @@ struct perf_header { struct perf_evlist; struct perf_session; -int perf_session__read_header(struct perf_session *session, int fd); +int perf_session__read_header(struct perf_session *session); int perf_session__write_header(struct perf_session *session, struct perf_evlist *evlist, int fd, bool at_exit); diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index d0d9f946a1b1..272c9cf57122 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -24,7 +24,7 @@ static int perf_session__open(struct perf_session *self, bool force) self->fd_pipe = true; self->fd = STDIN_FILENO; - if (perf_session__read_header(self, self->fd) < 0) + if (perf_session__read_header(self) < 0) pr_err("incompatible file format (rerun with -v to learn more)"); return 0; @@ -56,7 +56,7 @@ static int perf_session__open(struct perf_session *self, bool force) goto out_close; } - if (perf_session__read_header(self, self->fd) < 0) { + if (perf_session__read_header(self) < 0) { pr_err("incompatible file format (rerun with -v to learn more)"); goto out_close; } From 75211dbfabf1de3a42703f4d3cd6f6e047289d40 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Wed, 17 Jul 2013 19:49:42 +0200 Subject: [PATCH 0186/3400] perf header: Remove data_offset seek as it's not needed Removing data_offset seek as it's not needed, because data are not read by syscall but mmaped instead. Signed-off-by: Jiri Olsa Cc: Andi Kleen Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1374083403-14591-3-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/header.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index b3f253f2841e..035efe764286 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -2794,8 +2794,6 @@ int perf_session__read_header(struct perf_session *session) perf_header__process_sections(header, fd, &session->pevent, perf_file_section__process); - lseek(fd, header->data_offset, SEEK_SET); - if (perf_evlist__prepare_tracepoint_events(session->evlist, session->pevent)) goto out_delete_evlist; From 944d62ba4c8e1c9bb2962a70e3d495106fae8cd9 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Wed, 17 Jul 2013 19:49:43 +0200 Subject: [PATCH 0187/3400] perf header: Remove attr_offset from perf_header Removing attr_offset from perf_header as it's possible to use it as a local variable. Signed-off-by: Jiri Olsa Cc: Andi Kleen Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1374083403-14591-4-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/header.c | 5 +++-- tools/perf/util/header.h | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 035efe764286..dcba56aac1b7 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -2272,6 +2272,7 @@ int perf_session__write_header(struct perf_session *session, struct perf_file_attr f_attr; struct perf_header *header = &session->header; struct perf_evsel *evsel; + u64 attr_offset; int err; lseek(fd, sizeof(f_header), SEEK_SET); @@ -2285,7 +2286,7 @@ int perf_session__write_header(struct perf_session *session, } } - header->attr_offset = lseek(fd, 0, SEEK_CUR); + attr_offset = lseek(fd, 0, SEEK_CUR); list_for_each_entry(evsel, &evlist->entries, node) { f_attr = (struct perf_file_attr){ @@ -2315,7 +2316,7 @@ int perf_session__write_header(struct perf_session *session, .size = sizeof(f_header), .attr_size = sizeof(f_attr), .attrs = { - .offset = header->attr_offset, + .offset = attr_offset, .size = evlist->nr_entries * sizeof(f_attr), }, .data = { diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index 0bacb2d6eafa..6fa80f947f71 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h @@ -86,7 +86,6 @@ struct perf_session_env { struct perf_header { bool needs_swap; - s64 attr_offset; u64 data_offset; u64 data_size; DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS); From 8d541e974f4b3ed5db7e278b4d64481af34910a9 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Wed, 17 Jul 2013 19:49:44 +0200 Subject: [PATCH 0188/3400] perf header: Introduce feat_offset into perf_header Introducing feat_offset into perf_header to make the location of the features section clear. Signed-off-by: Jiri Olsa Cc: Andi Kleen Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1374083403-14591-5-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/header.c | 6 ++++-- tools/perf/util/header.h | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index dcba56aac1b7..eefb052190f3 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -2225,7 +2225,7 @@ static int perf_header__adds_write(struct perf_header *header, sec_size = sizeof(*feat_sec) * nr_sections; - sec_start = header->data_offset + header->data_size; + sec_start = header->feat_offset; lseek(fd, sec_start + sec_size, SEEK_SET); for_each_set_bit(feat, header->adds_features, HEADER_FEAT_BITS) { @@ -2304,6 +2304,7 @@ int perf_session__write_header(struct perf_session *session, } header->data_offset = lseek(fd, 0, SEEK_CUR); + header->feat_offset = header->data_offset + header->data_size; if (at_exit) { err = perf_header__adds_write(header, evlist, fd); @@ -2373,7 +2374,7 @@ int perf_header__process_sections(struct perf_header *header, int fd, sec_size = sizeof(*feat_sec) * nr_sections; - lseek(fd, header->data_offset + header->data_size, SEEK_SET); + lseek(fd, header->feat_offset, SEEK_SET); err = perf_header__getbuffer64(header, fd, feat_sec, sec_size); if (err < 0) @@ -2572,6 +2573,7 @@ int perf_file_header__read(struct perf_file_header *header, ph->data_offset = header->data.offset; ph->data_size = header->data.size; + ph->feat_offset = header->data.offset + header->data.size; return 0; } diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index 6fa80f947f71..e6387dcb95c0 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h @@ -88,6 +88,7 @@ struct perf_header { bool needs_swap; u64 data_offset; u64 data_size; + u64 feat_offset; DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS); struct perf_session_env env; }; From 2a08c3ec4f7d6058a450d2d4bc6e366955872707 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Wed, 17 Jul 2013 19:49:47 +0200 Subject: [PATCH 0189/3400] perf header: Recognize version number for perf data file Keep the recognized data file version within 'struct perf_header'. Signed-off-by: Jiri Olsa Cc: Andi Kleen Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1374083403-14591-8-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/header.c | 2 ++ tools/perf/util/header.h | 16 +++++++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index eefb052190f3..f558f83769af 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -2480,6 +2480,7 @@ static int check_magic_endian(u64 magic, uint64_t hdr_sz, /* check for legacy format */ ret = memcmp(&magic, __perf_magic1, sizeof(magic)); if (ret == 0) { + ph->version = PERF_HEADER_VERSION_1; pr_debug("legacy perf.data format\n"); if (is_pipe) return try_all_pipe_abis(hdr_sz, ph); @@ -2501,6 +2502,7 @@ static int check_magic_endian(u64 magic, uint64_t hdr_sz, return -1; ph->needs_swap = true; + ph->version = PERF_HEADER_VERSION_2; return 0; } diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index e6387dcb95c0..307c9aed972e 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h @@ -34,6 +34,11 @@ enum { HEADER_FEAT_BITS = 256, }; +enum perf_header_version { + PERF_HEADER_VERSION_1, + PERF_HEADER_VERSION_2, +}; + struct perf_file_section { u64 offset; u64 size; @@ -85,12 +90,13 @@ struct perf_session_env { }; struct perf_header { - bool needs_swap; - u64 data_offset; - u64 data_size; - u64 feat_offset; + enum perf_header_version version; + bool needs_swap; + u64 data_offset; + u64 data_size; + u64 feat_offset; DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS); - struct perf_session_env env; + struct perf_session_env env; }; struct perf_evlist; From d60990d597bfa2816dfe28a5c5c6787610b423e6 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Wed, 17 Jul 2013 15:49:54 -0300 Subject: [PATCH 0190/3400] spi: spi-bitbang: Fix conversion of spi_bitbang_transfer_one() Since commit 2025172e3 (spi/bitbang: Use core message pump), the following kernel crash is seen: Unable to handle kernel NULL pointer dereference at virtual address 0000000d pgd = 80004000 [0000000d] *pgd=00000000 Internal error: Oops: 5 [#1] SMP ARM Modules linked in: CPU: 1 PID: 48 Comm: spi32766 Not tainted 3.11.0-rc1+ #4 task: bfa3e580 ti: bfb90000 task.ti: bfb90000 PC is at spi_bitbang_transfer_one+0x50/0x248 LR is at spi_bitbang_transfer_one+0x20/0x248 ... ,and also the following build warning: drivers/spi/spi-bitbang.c: In function 'spi_bitbang_start': drivers/spi/spi-bitbang.c:436:31: warning: assignment from incompatible pointer type [enabled by default] In order to fix it, we need to change the first parameter of spi_bitbang_transfer_one() to 'struct spi_master *master'. Tested on a mx6qsabrelite by succesfully probing a SPI NOR flash. Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown --- drivers/spi/spi-bitbang.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c index c100875cfd42..a89178dc8498 100644 --- a/drivers/spi/spi-bitbang.c +++ b/drivers/spi/spi-bitbang.c @@ -270,7 +270,7 @@ static int spi_bitbang_prepare_hardware(struct spi_master *spi) return 0; } -static int spi_bitbang_transfer_one(struct spi_device *spi, +static int spi_bitbang_transfer_one(struct spi_master *master, struct spi_message *m) { struct spi_bitbang *bitbang; @@ -280,8 +280,9 @@ static int spi_bitbang_transfer_one(struct spi_device *spi, unsigned cs_change; int status; int do_setup = -1; + struct spi_device *spi = m->spi; - bitbang = spi_master_get_devdata(spi->master); + bitbang = spi_master_get_devdata(master); /* FIXME this is made-up ... the correct value is known to * word-at-a-time bitbang code, and presumably chipselect() @@ -372,7 +373,7 @@ static int spi_bitbang_transfer_one(struct spi_device *spi, ndelay(nsecs); } - spi_finalize_current_message(spi->master); + spi_finalize_current_message(master); return status; } From 19b0a1e5ac5a7f1dafd5ee2479a5db72b330246b Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 17 Jul 2013 19:39:19 -0700 Subject: [PATCH 0191/3400] clocksource: orion: Use linux/sched_clock.h The sched_clock.h include is under include/linux now. Cc: Sebastian Hesselbarth Signed-off-by: Stephen Boyd Signed-off-by: John Stultz --- drivers/clocksource/time-orion.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clocksource/time-orion.c b/drivers/clocksource/time-orion.c index ecbeb6810215..9c7f018a67ca 100644 --- a/drivers/clocksource/time-orion.c +++ b/drivers/clocksource/time-orion.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #define TIMER_CTRL 0x00 #define TIMER0_EN BIT(0) From e69f61862ab833e9b8d3c15b6ce07fd69f3bfecc Mon Sep 17 00:00:00 2001 From: Yacine Belkadi Date: Fri, 12 Jul 2013 20:45:47 +0200 Subject: [PATCH 0192/3400] sched: Fix some kernel-doc warnings When building the htmldocs (in verbose mode), scripts/kernel-doc reports the follwing type of warnings: Warning(kernel/sched/core.c:936): No description found for return value of 'task_curr' ... Fix those by: - adding the missing descriptions - using "Return" sections for the descriptions Signed-off-by: Yacine Belkadi Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1373654747-2389-1-git-send-email-yacine.belkadi.1@gmail.com [ While at it, fix the cpupri_set() explanation. ] Signed-off-by: Ingo Molnar --- include/linux/sched.h | 6 ++++ kernel/sched/core.c | 82 ++++++++++++++++++++++++++++++++----------- kernel/sched/cpupri.c | 4 +-- kernel/sched/fair.c | 9 +++-- 4 files changed, 76 insertions(+), 25 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index 50d04b92ceda..82300247974c 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1532,6 +1532,8 @@ static inline pid_t task_pgrp_nr(struct task_struct *tsk) * Test if a process is not yet dead (at most zombie state) * If pid_alive fails, then pointers within the task structure * can be stale and must not be dereferenced. + * + * Return: 1 if the process is alive. 0 otherwise. */ static inline int pid_alive(struct task_struct *p) { @@ -1543,6 +1545,8 @@ static inline int pid_alive(struct task_struct *p) * @tsk: Task structure to be checked. * * Check if a task structure is the first user space task the kernel created. + * + * Return: 1 if the task structure is init. 0 otherwise. */ static inline int is_global_init(struct task_struct *tsk) { @@ -1893,6 +1897,8 @@ extern struct task_struct *idle_task(int cpu); /** * is_idle_task - is the specified task an idle task? * @p: the task in question. + * + * Return: 1 if @p is an idle task. 0 otherwise. */ static inline bool is_idle_task(const struct task_struct *p) { diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 0d8eb4525e76..4c3967f91e20 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -933,6 +933,8 @@ static int effective_prio(struct task_struct *p) /** * task_curr - is this task currently executing on a CPU? * @p: the task in question. + * + * Return: 1 if the task is currently executing. 0 otherwise. */ inline int task_curr(const struct task_struct *p) { @@ -1482,7 +1484,7 @@ static void ttwu_queue(struct task_struct *p, int cpu) * the simpler "current->state = TASK_RUNNING" to mark yourself * runnable without the overhead of this. * - * Returns %true if @p was woken up, %false if it was already running + * Return: %true if @p was woken up, %false if it was already running. * or @state didn't match @p's state. */ static int @@ -1577,8 +1579,9 @@ out: * @p: The process to be woken up. * * Attempt to wake up the nominated process and move it to the set of runnable - * processes. Returns 1 if the process was woken up, 0 if it was already - * running. + * processes. + * + * Return: 1 if the process was woken up, 0 if it was already running. * * It may be assumed that this function implies a write memory barrier before * changing the task state if and only if any tasks are woken up. @@ -2191,6 +2194,8 @@ void scheduler_tick(void) * This makes sure that uptime, CFS vruntime, load * balancing, etc... continue to move forward, even * with a very low granularity. + * + * Return: Maximum deferment in nanoseconds. */ u64 scheduler_tick_max_deferment(void) { @@ -2796,8 +2801,8 @@ EXPORT_SYMBOL(wait_for_completion); * specified timeout to expire. The timeout is in jiffies. It is not * interruptible. * - * The return value is 0 if timed out, and positive (at least 1, or number of - * jiffies left till timeout) if completed. + * Return: 0 if timed out, and positive (at least 1, or number of jiffies left + * till timeout) if completed. */ unsigned long __sched wait_for_completion_timeout(struct completion *x, unsigned long timeout) @@ -2829,8 +2834,8 @@ EXPORT_SYMBOL(wait_for_completion_io); * specified timeout to expire. The timeout is in jiffies. It is not * interruptible. The caller is accounted as waiting for IO. * - * The return value is 0 if timed out, and positive (at least 1, or number of - * jiffies left till timeout) if completed. + * Return: 0 if timed out, and positive (at least 1, or number of jiffies left + * till timeout) if completed. */ unsigned long __sched wait_for_completion_io_timeout(struct completion *x, unsigned long timeout) @@ -2846,7 +2851,7 @@ EXPORT_SYMBOL(wait_for_completion_io_timeout); * This waits for completion of a specific task to be signaled. It is * interruptible. * - * The return value is -ERESTARTSYS if interrupted, 0 if completed. + * Return: -ERESTARTSYS if interrupted, 0 if completed. */ int __sched wait_for_completion_interruptible(struct completion *x) { @@ -2865,8 +2870,8 @@ EXPORT_SYMBOL(wait_for_completion_interruptible); * This waits for either a completion of a specific task to be signaled or for a * specified timeout to expire. It is interruptible. The timeout is in jiffies. * - * The return value is -ERESTARTSYS if interrupted, 0 if timed out, - * positive (at least 1, or number of jiffies left till timeout) if completed. + * Return: -ERESTARTSYS if interrupted, 0 if timed out, positive (at least 1, + * or number of jiffies left till timeout) if completed. */ long __sched wait_for_completion_interruptible_timeout(struct completion *x, @@ -2883,7 +2888,7 @@ EXPORT_SYMBOL(wait_for_completion_interruptible_timeout); * This waits to be signaled for completion of a specific task. It can be * interrupted by a kill signal. * - * The return value is -ERESTARTSYS if interrupted, 0 if completed. + * Return: -ERESTARTSYS if interrupted, 0 if completed. */ int __sched wait_for_completion_killable(struct completion *x) { @@ -2903,8 +2908,8 @@ EXPORT_SYMBOL(wait_for_completion_killable); * signaled or for a specified timeout to expire. It can be * interrupted by a kill signal. The timeout is in jiffies. * - * The return value is -ERESTARTSYS if interrupted, 0 if timed out, - * positive (at least 1, or number of jiffies left till timeout) if completed. + * Return: -ERESTARTSYS if interrupted, 0 if timed out, positive (at least 1, + * or number of jiffies left till timeout) if completed. */ long __sched wait_for_completion_killable_timeout(struct completion *x, @@ -2918,7 +2923,7 @@ EXPORT_SYMBOL(wait_for_completion_killable_timeout); * try_wait_for_completion - try to decrement a completion without blocking * @x: completion structure * - * Returns: 0 if a decrement cannot be done without blocking + * Return: 0 if a decrement cannot be done without blocking * 1 if a decrement succeeded. * * If a completion is being used as a counting completion, @@ -2945,7 +2950,7 @@ EXPORT_SYMBOL(try_wait_for_completion); * completion_done - Test to see if a completion has any waiters * @x: completion structure * - * Returns: 0 if there are waiters (wait_for_completion() in progress) + * Return: 0 if there are waiters (wait_for_completion() in progress) * 1 if there are no waiters. * */ @@ -3182,7 +3187,7 @@ SYSCALL_DEFINE1(nice, int, increment) * task_prio - return the priority value of a given task. * @p: the task in question. * - * This is the priority value as seen by users in /proc. + * Return: The priority value as seen by users in /proc. * RT tasks are offset by -200. Normal tasks are centered * around 0, value goes from -16 to +15. */ @@ -3194,6 +3199,8 @@ int task_prio(const struct task_struct *p) /** * task_nice - return the nice value of a given task. * @p: the task in question. + * + * Return: The nice value [ -20 ... 0 ... 19 ]. */ int task_nice(const struct task_struct *p) { @@ -3204,6 +3211,8 @@ EXPORT_SYMBOL(task_nice); /** * idle_cpu - is a given cpu idle currently? * @cpu: the processor in question. + * + * Return: 1 if the CPU is currently idle. 0 otherwise. */ int idle_cpu(int cpu) { @@ -3226,6 +3235,8 @@ int idle_cpu(int cpu) /** * idle_task - return the idle task for a given cpu. * @cpu: the processor in question. + * + * Return: The idle task for the cpu @cpu. */ struct task_struct *idle_task(int cpu) { @@ -3235,6 +3246,8 @@ struct task_struct *idle_task(int cpu) /** * find_process_by_pid - find a process with a matching PID value. * @pid: the pid in question. + * + * The task of @pid, if found. %NULL otherwise. */ static struct task_struct *find_process_by_pid(pid_t pid) { @@ -3432,6 +3445,8 @@ recheck: * @policy: new policy. * @param: structure containing the new RT priority. * + * Return: 0 on success. An error code otherwise. + * * NOTE that the task may be already dead. */ int sched_setscheduler(struct task_struct *p, int policy, @@ -3451,6 +3466,8 @@ EXPORT_SYMBOL_GPL(sched_setscheduler); * current context has permission. For example, this is needed in * stop_machine(): we create temporary high priority worker threads, * but our caller might not have that capability. + * + * Return: 0 on success. An error code otherwise. */ int sched_setscheduler_nocheck(struct task_struct *p, int policy, const struct sched_param *param) @@ -3485,6 +3502,8 @@ do_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param) * @pid: the pid in question. * @policy: new policy. * @param: structure containing the new RT priority. + * + * Return: 0 on success. An error code otherwise. */ SYSCALL_DEFINE3(sched_setscheduler, pid_t, pid, int, policy, struct sched_param __user *, param) @@ -3500,6 +3519,8 @@ SYSCALL_DEFINE3(sched_setscheduler, pid_t, pid, int, policy, * sys_sched_setparam - set/change the RT priority of a thread * @pid: the pid in question. * @param: structure containing the new RT priority. + * + * Return: 0 on success. An error code otherwise. */ SYSCALL_DEFINE2(sched_setparam, pid_t, pid, struct sched_param __user *, param) { @@ -3509,6 +3530,9 @@ SYSCALL_DEFINE2(sched_setparam, pid_t, pid, struct sched_param __user *, param) /** * sys_sched_getscheduler - get the policy (scheduling class) of a thread * @pid: the pid in question. + * + * Return: On success, the policy of the thread. Otherwise, a negative error + * code. */ SYSCALL_DEFINE1(sched_getscheduler, pid_t, pid) { @@ -3535,6 +3559,9 @@ SYSCALL_DEFINE1(sched_getscheduler, pid_t, pid) * sys_sched_getparam - get the RT priority of a thread * @pid: the pid in question. * @param: structure containing the RT priority. + * + * Return: On success, 0 and the RT priority is in @param. Otherwise, an error + * code. */ SYSCALL_DEFINE2(sched_getparam, pid_t, pid, struct sched_param __user *, param) { @@ -3659,6 +3686,8 @@ static int get_user_cpu_mask(unsigned long __user *user_mask_ptr, unsigned len, * @pid: pid of the process * @len: length in bytes of the bitmask pointed to by user_mask_ptr * @user_mask_ptr: user-space pointer to the new cpu mask + * + * Return: 0 on success. An error code otherwise. */ SYSCALL_DEFINE3(sched_setaffinity, pid_t, pid, unsigned int, len, unsigned long __user *, user_mask_ptr) @@ -3710,6 +3739,8 @@ out_unlock: * @pid: pid of the process * @len: length in bytes of the bitmask pointed to by user_mask_ptr * @user_mask_ptr: user-space pointer to hold the current cpu mask + * + * Return: 0 on success. An error code otherwise. */ SYSCALL_DEFINE3(sched_getaffinity, pid_t, pid, unsigned int, len, unsigned long __user *, user_mask_ptr) @@ -3744,6 +3775,8 @@ SYSCALL_DEFINE3(sched_getaffinity, pid_t, pid, unsigned int, len, * * This function yields the current CPU to other tasks. If there are no * other threads running on this CPU then this function will return. + * + * Return: 0. */ SYSCALL_DEFINE0(sched_yield) { @@ -3869,7 +3902,7 @@ EXPORT_SYMBOL(yield); * It's the caller's job to ensure that the target task struct * can't go away on us before we can do any checks. * - * Returns: + * Return: * true (>0) if we indeed boosted the target task. * false (0) if we failed to boost the target. * -ESRCH if there's no task to yield to. @@ -3972,8 +4005,9 @@ long __sched io_schedule_timeout(long timeout) * sys_sched_get_priority_max - return maximum RT priority. * @policy: scheduling class. * - * this syscall returns the maximum rt_priority that can be used - * by a given scheduling class. + * Return: On success, this syscall returns the maximum + * rt_priority that can be used by a given scheduling class. + * On failure, a negative error code is returned. */ SYSCALL_DEFINE1(sched_get_priority_max, int, policy) { @@ -3997,8 +4031,9 @@ SYSCALL_DEFINE1(sched_get_priority_max, int, policy) * sys_sched_get_priority_min - return minimum RT priority. * @policy: scheduling class. * - * this syscall returns the minimum rt_priority that can be used - * by a given scheduling class. + * Return: On success, this syscall returns the minimum + * rt_priority that can be used by a given scheduling class. + * On failure, a negative error code is returned. */ SYSCALL_DEFINE1(sched_get_priority_min, int, policy) { @@ -4024,6 +4059,9 @@ SYSCALL_DEFINE1(sched_get_priority_min, int, policy) * * this syscall writes the default timeslice value of a given process * into the user-space timespec buffer. A value of '0' means infinity. + * + * Return: On success, 0 and the timeslice is in @interval. Otherwise, + * an error code. */ SYSCALL_DEFINE2(sched_rr_get_interval, pid_t, pid, struct timespec __user *, interval) @@ -6632,6 +6670,8 @@ void normalize_rt_tasks(void) * @cpu: the processor in question. * * ONLY VALID WHEN THE WHOLE SYSTEM IS STOPPED! + * + * Return: The current task for @cpu. */ struct task_struct *curr_task(int cpu) { diff --git a/kernel/sched/cpupri.c b/kernel/sched/cpupri.c index 1095e878a46f..8b836b376d91 100644 --- a/kernel/sched/cpupri.c +++ b/kernel/sched/cpupri.c @@ -62,7 +62,7 @@ static int convert_prio(int prio) * any discrepancies created by racing against the uncertainty of the current * priority configuration. * - * Returns: (int)bool - CPUs were found + * Return: (int)bool - CPUs were found */ int cpupri_find(struct cpupri *cp, struct task_struct *p, struct cpumask *lowest_mask) @@ -203,7 +203,7 @@ void cpupri_set(struct cpupri *cp, int cpu, int newpri) * cpupri_init - initialize the cpupri structure * @cp: The cpupri context * - * Returns: -ENOMEM if memory fails. + * Return: -ENOMEM on memory allocation failure. */ int cpupri_init(struct cpupri *cp) { diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index f77f9c527449..98d135584b4b 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -4280,6 +4280,8 @@ struct sg_lb_stats { * 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. + * + * Return: The load index. */ static inline int get_sd_load_idx(struct sched_domain *sd, enum cpu_idle_type idle) @@ -4574,6 +4576,9 @@ static inline void update_sg_lb_stats(struct lb_env *env, * * Determine if @sg is a busier group than the previously selected * busiest group. + * + * Return: %true if @sg is a busier group than the previously selected + * busiest group. %false otherwise. */ static bool update_sd_pick_busiest(struct lb_env *env, struct sd_lb_stats *sds, @@ -4691,7 +4696,7 @@ static inline void update_sd_lb_stats(struct lb_env *env, * assuming lower CPU number will be equivalent to lower a SMT thread * number. * - * Returns 1 when packing is required and a task should be moved to + * Return: 1 when packing is required and a task should be moved to * this CPU. The amount of the imbalance is returned in *imbalance. * * @env: The load balancing environment. @@ -4869,7 +4874,7 @@ static inline void calculate_imbalance(struct lb_env *env, struct sd_lb_stats *s * @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. + * Return: - 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. From 070260f07c7daec311f2466eb9d1df475d5a46f8 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 18 Jul 2013 11:52:04 +0100 Subject: [PATCH 0193/3400] regulator: core: Use the power efficient workqueue for delayed powerdown There is no need to use a normal per-CPU workqueue for delayed power downs as they're not timing or performance critical and waking up a core for them would defeat some of the point. Signed-off-by: Mark Brown Reviewed-by: Viresh Kumar Acked-by: Liam Girdwood --- drivers/regulator/core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 1510333bcf0d..f49c6615dc37 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1890,8 +1890,9 @@ int regulator_disable_deferred(struct regulator *regulator, int ms) rdev->deferred_disables++; mutex_unlock(&rdev->mutex); - ret = schedule_delayed_work(&rdev->disable_work, - msecs_to_jiffies(ms)); + ret = queue_delayed_work(system_power_efficient_wq, + &rdev->disable_work, + msecs_to_jiffies(ms)); if (ret < 0) return ret; else From 82b736df4da2c6fdf2c0018938685cf36d112ecd Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 5 Jul 2013 20:45:22 +0100 Subject: [PATCH 0194/3400] regulator: build: Sort Kconfig Reduces merge issues if nothing else. Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 254 ++++++++++++++++++------------------- drivers/regulator/Makefile | 2 +- 2 files changed, 128 insertions(+), 128 deletions(-) diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index f1e6ad98eeba..759b601b54ef 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -64,15 +64,11 @@ config REGULATOR_USERSPACE_CONSUMER If unsure, say no. -config REGULATOR_GPIO - tristate "GPIO regulator support" - depends on GPIOLIB +config REGULATOR_88PM8607 + bool "Marvell 88PM8607 Power regulators" + depends on MFD_88PM860X=y help - This driver provides support for regulators that can be - controlled via gpios. - It is capable of supporting current and voltage regulators - and the platform has to provide a mapping of GPIO-states - to target volts/amps. + This driver supports 88PM8607 voltage regulator chips. config REGULATOR_AD5398 tristate "Analog Devices AD5398/AD5821 regulators" @@ -81,6 +77,14 @@ config REGULATOR_AD5398 This driver supports AD5398 and AD5821 current regulator chips. If building into module, its name is ad5398.ko. +config REGULATOR_ANATOP + tristate "Freescale i.MX on-chip ANATOP LDO regulators" + depends on MFD_SYSCON + help + Say y here to support Freescale i.MX on-chip ANATOP LDOs + regulators. It is recommended that this option be + enabled on i.MX6 platform. + config REGULATOR_AAT2870 tristate "AnalogicTech AAT2870 Regulators" depends on MFD_AAT2870_CORE @@ -88,6 +92,22 @@ config REGULATOR_AAT2870 If you have a AnalogicTech AAT2870 say Y to enable the regulator driver. +config REGULATOR_AB3100 + tristate "ST-Ericsson AB3100 Regulator functions" + depends on AB3100_CORE + default y if AB3100_CORE + help + These regulators correspond to functionality in the + AB3100 analog baseband dealing with power regulators + for the system. + +config REGULATOR_AB8500 + bool "ST-Ericsson AB8500 Power Regulators" + depends on AB8500_CORE + help + This driver supports the regulators found on the ST-Ericsson mixed + signal AB8500 PMIC + config REGULATOR_ARIZONA tristate "Wolfson Arizona class devices" depends on MFD_ARIZONA @@ -96,6 +116,13 @@ config REGULATOR_ARIZONA Support for the regulators found on Wolfson Arizona class devices. +config REGULATOR_AS3711 + tristate "AS3711 PMIC" + depends on MFD_AS3711 + help + This driver provides support for the voltage regulators on the + AS3711 PMIC + config REGULATOR_DA903X tristate "Dialog Semiconductor DA9030/DA9034 regulators" depends on PMIC_DA903X @@ -120,6 +147,17 @@ config REGULATOR_DA9055 This driver can also be built as a module. If so, the module will be called da9055-regulator. +config REGULATOR_DBX500_PRCMU + bool + +config REGULATOR_DB8500_PRCMU + bool "ST-Ericsson DB8500 Voltage Domain Regulators" + depends on MFD_DB8500_PRCMU + select REGULATOR_DBX500_PRCMU + help + This driver supports the voltage domain regulators controlled by the + DB8500 PRCMU + config REGULATOR_FAN53555 tristate "Fairchild FAN53555 Regulator" depends on I2C @@ -131,32 +169,15 @@ config REGULATOR_FAN53555 input voltage supply of 2.5V to 5.5V. The output voltage is programmed through an I2C interface. -config REGULATOR_ANATOP - tristate "Freescale i.MX on-chip ANATOP LDO regulators" - depends on MFD_SYSCON +config REGULATOR_GPIO + tristate "GPIO regulator support" + depends on GPIOLIB help - Say y here to support Freescale i.MX on-chip ANATOP LDOs - regulators. It is recommended that this option be - enabled on i.MX6 platform. - -config REGULATOR_MC13XXX_CORE - tristate - -config REGULATOR_MC13783 - tristate "Freescale MC13783 regulator driver" - depends on MFD_MC13783 - select REGULATOR_MC13XXX_CORE - help - Say y here to support the regulators found on the Freescale MC13783 - PMIC. - -config REGULATOR_MC13892 - tristate "Freescale MC13892 regulator driver" - depends on MFD_MC13XXX - select REGULATOR_MC13XXX_CORE - help - Say y here to support the regulators found on the Freescale MC13892 - PMIC. + This driver provides support for regulators that can be + controlled via gpios. + It is capable of supporting current and voltage regulators + and the platform has to provide a mapping of GPIO-states + to target volts/amps. config REGULATOR_ISL6271A tristate "Intersil ISL6271A Power regulator" @@ -164,11 +185,41 @@ config REGULATOR_ISL6271A help This driver supports ISL6271A voltage regulator chip. -config REGULATOR_88PM8607 - bool "Marvell 88PM8607 Power regulators" - depends on MFD_88PM860X=y +config REGULATOR_LP3971 + tristate "National Semiconductors LP3971 PMIC regulator driver" + depends on I2C help - This driver supports 88PM8607 voltage regulator chips. + Say Y here to support the voltage regulators and convertors + on National Semiconductors LP3971 PMIC + +config REGULATOR_LP3972 + tristate "National Semiconductors LP3972 PMIC regulator driver" + depends on I2C + help + Say Y here to support the voltage regulators and convertors + on National Semiconductors LP3972 PMIC + +config REGULATOR_LP872X + bool "TI/National Semiconductor LP8720/LP8725 voltage regulators" + depends on I2C=y + select REGMAP_I2C + help + This driver supports LP8720/LP8725 PMIC + +config REGULATOR_LP8755 + tristate "TI LP8755 High Performance PMU driver" + depends on I2C + select REGMAP_I2C + help + This driver supports LP8755 High Performance PMU driver. This + chip contains six step-down DC/DC converters which can support + 9 mode multiphase configuration. + +config REGULATOR_LP8788 + bool "TI LP8788 Power Regulators" + depends on MFD_LP8788 + help + This driver supports LP8788 voltage regulator chip. config REGULATOR_MAX1586 tristate "Maxim 1586/1587 voltage regulator" @@ -259,6 +310,37 @@ config REGULATOR_MAX77693 and one current regulator 'CHARGER'. This is suitable for Exynos-4x12 chips. +config REGULATOR_MC13XXX_CORE + tristate + +config REGULATOR_MC13783 + tristate "Freescale MC13783 regulator driver" + depends on MFD_MC13783 + select REGULATOR_MC13XXX_CORE + help + Say y here to support the regulators found on the Freescale MC13783 + PMIC. + +config REGULATOR_MC13892 + tristate "Freescale MC13892 regulator driver" + depends on MFD_MC13XXX + select REGULATOR_MC13XXX_CORE + help + Say y here to support the regulators found on the Freescale MC13892 + PMIC. + +config REGULATOR_PALMAS + tristate "TI Palmas PMIC Regulators" + depends on MFD_PALMAS + help + If you wish to control the regulators on the Palmas series of + chips say Y here. This will enable support for all the software + controllable SMPS/LDO regulators. + + The regulators available on Palmas series chips vary depending + on the muxing. This is handled automatically in the driver by + reading the mux info from OTP. + config REGULATOR_PCAP tristate "Motorola PCAP2 regulator driver" depends on EZX_PCAP @@ -266,42 +348,6 @@ config REGULATOR_PCAP This driver provides support for the voltage regulators of the PCAP2 PMIC. -config REGULATOR_LP3971 - tristate "National Semiconductors LP3971 PMIC regulator driver" - depends on I2C - help - Say Y here to support the voltage regulators and convertors - on National Semiconductors LP3971 PMIC - -config REGULATOR_LP3972 - tristate "National Semiconductors LP3972 PMIC regulator driver" - depends on I2C - help - Say Y here to support the voltage regulators and convertors - on National Semiconductors LP3972 PMIC - -config REGULATOR_LP872X - bool "TI/National Semiconductor LP8720/LP8725 voltage regulators" - depends on I2C=y - select REGMAP_I2C - help - This driver supports LP8720/LP8725 PMIC - -config REGULATOR_LP8755 - tristate "TI LP8755 High Performance PMU driver" - depends on I2C - select REGMAP_I2C - help - This driver supports LP8755 High Performance PMU driver. This - chip contains six step-down DC/DC converters which can support - 9 mode multiphase configuration. - -config REGULATOR_LP8788 - bool "TI LP8788 Power Regulators" - depends on MFD_LP8788 - help - This driver supports LP8788 voltage regulator chip. - config REGULATOR_PCF50633 tristate "NXP PCF50633 regulator driver" depends on MFD_PCF50633 @@ -335,44 +381,15 @@ config REGULATOR_S5M8767 via I2C bus. S5M8767A have 9 Bucks and 28 LDOs output and supports DVS mode with 8bits of output voltage control. -config REGULATOR_AB3100 - tristate "ST-Ericsson AB3100 Regulator functions" - depends on AB3100_CORE - default y if AB3100_CORE +config REGULATOR_TI_ABB + bool "TI Adaptive Body Bias on-chip LDO" + depends on ARCH_OMAP help - These regulators correspond to functionality in the - AB3100 analog baseband dealing with power regulators - for the system. - -config REGULATOR_AB8500 - bool "ST-Ericsson AB8500 Power Regulators" - depends on AB8500_CORE - help - This driver supports the regulators found on the ST-Ericsson mixed - signal AB8500 PMIC - -config REGULATOR_DBX500_PRCMU - bool - -config REGULATOR_DB8500_PRCMU - bool "ST-Ericsson DB8500 Voltage Domain Regulators" - depends on MFD_DB8500_PRCMU - select REGULATOR_DBX500_PRCMU - help - This driver supports the voltage domain regulators controlled by the - DB8500 PRCMU - -config REGULATOR_PALMAS - tristate "TI Palmas PMIC Regulators" - depends on MFD_PALMAS - help - If you wish to control the regulators on the Palmas series of - chips say Y here. This will enable support for all the software - controllable SMPS/LDO regulators. - - The regulators available on Palmas series chips vary depending - on the muxing. This is handled automatically in the driver by - reading the mux info from OTP. + Select this option to support Texas Instruments' on-chip Adaptive Body + Bias (ABB) LDO regulators. It is recommended that this option be + enabled on required TI SoC. Certain Operating Performance Points + on TI SoCs may be unstable without enabling this as it provides + device specific optimized bias to allow/optimize functionality. config REGULATOR_TPS51632 tristate "TI TPS51632 Power Regulator" @@ -481,16 +498,6 @@ config REGULATOR_TWL4030 This driver supports the voltage regulators provided by this family of companion chips. -config REGULATOR_TI_ABB - bool "TI Adaptive Body Bias on-chip LDO" - depends on ARCH_OMAP - help - Select this option to support Texas Instruments' on-chip Adaptive Body - Bias (ABB) LDO regulators. It is recommended that this option be - enabled on required TI SoC. Certain Operating Performance Points - on TI SoCs may be unstable without enabling this as it provides - device specific optimized bias to allow/optimize functionality. - config REGULATOR_VEXPRESS tristate "Versatile Express regulators" depends on VEXPRESS_CONFIG @@ -526,12 +533,5 @@ config REGULATOR_WM8994 This driver provides support for the voltage regulators on the WM8994 CODEC. -config REGULATOR_AS3711 - tristate "AS3711 PMIC" - depends on MFD_AS3711 - help - This driver provides support for the voltage regulators on the - AS3711 PMIC - endif diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index ba4a3cf3afec..d240772d90ee 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -52,6 +52,7 @@ obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o +obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o obj-$(CONFIG_REGULATOR_TPS62360) += tps62360-regulator.o obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o @@ -64,7 +65,6 @@ obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o obj-$(CONFIG_REGULATOR_TPS65912) += tps65912-regulator.o obj-$(CONFIG_REGULATOR_TPS80031) += tps80031-regulator.o obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o -obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o obj-$(CONFIG_REGULATOR_VEXPRESS) += vexpress.o obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o From 9222d247bcbaacc40fe15549158f9d67523c1ace Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 16 Jul 2013 16:45:31 +0200 Subject: [PATCH 0195/3400] MAINTAINERS: Add Daniel as maintainer for CLOCKSOURCE and CLOCKEVENT Drivers I've been doing a bad job at managing the drivers/clocksource directory, so Daniel has been helping with review and patch queuing for the clocksource and clockevent drivers, so add him formally to the MAINTAINERS list. Cc: Daniel Lezcano Cc: Thomas Gleixner Cc: Joe Perches Cc: Arnd Bergmann Cc: Olof Johansson Signed-off-by: John Stultz Signed-off-by: Daniel Lezcano --- MAINTAINERS | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index bf61e04291ab..12a1ef44ca83 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2107,6 +2107,13 @@ M: Russell King S: Maintained F: include/linux/clk.h +CLOCKSOURCE, CLOCKEVENT DRIVERS +M: Daniel Lezcano +M: Thomas Gleixner +T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/core +S: Supported +F: drivers/clocksource + CISCO FCOE HBA DRIVER M: Hiral Patel M: Suma Ramars @@ -7123,7 +7130,7 @@ S: Maintained F: include/linux/mmc/dw_mmc.h F: drivers/mmc/host/dw_mmc* -TIMEKEEPING, NTP +TIMEKEEPING, CLOCKSOURCE CORE, NTP M: John Stultz M: Thomas Gleixner T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/core @@ -7136,7 +7143,6 @@ F: include/uapi/linux/timex.h F: kernel/time/clocksource.c F: kernel/time/time*.c F: kernel/time/ntp.c -F: drivers/clocksource TLG2300 VIDEO4LINUX-2 DRIVER M: Huang Shijie From 40777645eb7fe5b9184b339e1a8aa889993f6d75 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 16 Jul 2013 16:45:37 +0200 Subject: [PATCH 0196/3400] clocksource: sun4i: Use the BIT macros where possible Signed-off-by: Maxime Ripard Signed-off-by: Daniel Lezcano --- drivers/clocksource/sun4i_timer.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/clocksource/sun4i_timer.c b/drivers/clocksource/sun4i_timer.c index d4674e78ef35..bdf34d9910cb 100644 --- a/drivers/clocksource/sun4i_timer.c +++ b/drivers/clocksource/sun4i_timer.c @@ -24,12 +24,12 @@ #include #define TIMER_IRQ_EN_REG 0x00 -#define TIMER_IRQ_EN(val) (1 << val) +#define TIMER_IRQ_EN(val) BIT(val) #define TIMER_IRQ_ST_REG 0x04 #define TIMER_CTL_REG(val) (0x10 * val + 0x10) -#define TIMER_CTL_ENABLE (1 << 0) -#define TIMER_CTL_AUTORELOAD (1 << 1) -#define TIMER_CTL_ONESHOT (1 << 7) +#define TIMER_CTL_ENABLE BIT(0) +#define TIMER_CTL_AUTORELOAD BIT(1) +#define TIMER_CTL_ONESHOT BIT(7) #define TIMER_INTVAL_REG(val) (0x10 * val + 0x14) #define TIMER_CNTVAL_REG(val) (0x10 * val + 0x18) From bb008b9e873f5544120dcd401316b4c0e7743dde Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 16 Jul 2013 16:45:37 +0200 Subject: [PATCH 0197/3400] clocksource: sun4i: Wrap macros arguments in parenthesis The macros were not using parenthesis to escape the arguments passed to them. It is pretty unsafe, so add those parenthesis. Signed-off-by: Maxime Ripard Signed-off-by: Daniel Lezcano --- drivers/clocksource/sun4i_timer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clocksource/sun4i_timer.c b/drivers/clocksource/sun4i_timer.c index bdf34d9910cb..34ab6580ad1c 100644 --- a/drivers/clocksource/sun4i_timer.c +++ b/drivers/clocksource/sun4i_timer.c @@ -30,8 +30,8 @@ #define TIMER_CTL_ENABLE BIT(0) #define TIMER_CTL_AUTORELOAD BIT(1) #define TIMER_CTL_ONESHOT BIT(7) -#define TIMER_INTVAL_REG(val) (0x10 * val + 0x14) -#define TIMER_CNTVAL_REG(val) (0x10 * val + 0x18) +#define TIMER_INTVAL_REG(val) (0x10 * (val) + 0x14) +#define TIMER_CNTVAL_REG(val) (0x10 * (val) + 0x18) #define TIMER_SCAL 16 From 9eded23215e99338155c18f6d860859106568bb0 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 16 Jul 2013 16:45:37 +0200 Subject: [PATCH 0198/3400] clocksource: sun4i: rename AUTORELOAD define to RELOAD The name AUTORELOAD was actually pretty bad since it doesn't make the register reload the previous interval when it expires, but setting this value pushes the new programmed interval to the internal timer counter. Rename it to RELOAD instead. Signed-off-by: Maxime Ripard Signed-off-by: Daniel Lezcano --- drivers/clocksource/sun4i_timer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clocksource/sun4i_timer.c b/drivers/clocksource/sun4i_timer.c index 34ab6580ad1c..f5e227b06ad5 100644 --- a/drivers/clocksource/sun4i_timer.c +++ b/drivers/clocksource/sun4i_timer.c @@ -28,7 +28,7 @@ #define TIMER_IRQ_ST_REG 0x04 #define TIMER_CTL_REG(val) (0x10 * val + 0x10) #define TIMER_CTL_ENABLE BIT(0) -#define TIMER_CTL_AUTORELOAD BIT(1) +#define TIMER_CTL_RELOAD BIT(1) #define TIMER_CTL_ONESHOT BIT(7) #define TIMER_INTVAL_REG(val) (0x10 * (val) + 0x14) #define TIMER_CNTVAL_REG(val) (0x10 * (val) + 0x18) @@ -129,7 +129,7 @@ static void __init sun4i_timer_init(struct device_node *node) /* set mode to auto reload */ val = readl(timer_base + TIMER_CTL_REG(0)); - writel(val | TIMER_CTL_AUTORELOAD, timer_base + TIMER_CTL_REG(0)); + writel(val | TIMER_CTL_RELOAD, timer_base + TIMER_CTL_REG(0)); ret = setup_irq(irq, &sun4i_timer_irq); if (ret) From 137c6b3c7c63944a9cb51de0870b72f62d240f62 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 16 Jul 2013 16:45:37 +0200 Subject: [PATCH 0199/3400] clocksource: sun4i: Add clocksource and sched clock drivers Use the second timer found on the Allwinner SoCs as a clock source and sched clock, that were both not used yet on these platforms. Signed-off-by: Maxime Ripard Signed-off-by: Daniel Lezcano --- drivers/clocksource/sun4i_timer.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/clocksource/sun4i_timer.c b/drivers/clocksource/sun4i_timer.c index f5e227b06ad5..b581c93f20b3 100644 --- a/drivers/clocksource/sun4i_timer.c +++ b/drivers/clocksource/sun4i_timer.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -96,6 +97,11 @@ static struct irqaction sun4i_timer_irq = { .dev_id = &sun4i_clockevent, }; +static u32 sun4i_timer_sched_read(void) +{ + return ~readl(timer_base + TIMER_CNTVAL_REG(1)); +} + static void __init sun4i_timer_init(struct device_node *node) { unsigned long rate = 0; @@ -117,6 +123,15 @@ static void __init sun4i_timer_init(struct device_node *node) rate = clk_get_rate(clk); + writel(~0, timer_base + TIMER_INTVAL_REG(1)); + writel(TIMER_CTL_ENABLE | TIMER_CTL_RELOAD | + TIMER_CTL_CLK_SRC(TIMER_CTL_CLK_SRC_OSC24M), + timer_base + TIMER_CTL_REG(1)); + + setup_sched_clock(sun4i_timer_sched_read, 32, rate); + clocksource_mmio_init(timer_base + TIMER_CNTVAL_REG(1), node->name, + rate, 300, 32, clocksource_mmio_readl_down); + writel(rate / (TIMER_SCAL * HZ), timer_base + TIMER_INTVAL_REG(0)); From 8c31bec28b69a86aa83f072e6e00225380853a9e Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 16 Jul 2013 16:45:38 +0200 Subject: [PATCH 0200/3400] clocksource: sun4i: Don't forget to enable the clock we use Even if in our case, this clock was non-gatable, used as a parent clock for several IPs, it still is a good idea to enable it. Signed-off-by: Maxime Ripard Signed-off-by: Daniel Lezcano --- drivers/clocksource/sun4i_timer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clocksource/sun4i_timer.c b/drivers/clocksource/sun4i_timer.c index b581c93f20b3..8e9c65136451 100644 --- a/drivers/clocksource/sun4i_timer.c +++ b/drivers/clocksource/sun4i_timer.c @@ -120,6 +120,7 @@ static void __init sun4i_timer_init(struct device_node *node) clk = of_clk_get(node, 0); if (IS_ERR(clk)) panic("Can't get timer clock"); + clk_prepare_enable(clk); rate = clk_get_rate(clk); From 63d88f1ac71173e47c40ea116e4489f71c6ed9c7 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 16 Jul 2013 16:45:38 +0200 Subject: [PATCH 0201/3400] clocksource: sun4i: Fix the next event code The next_event logic was setting the next interval to fire in the current timer value instead of the interval value register, which is obviously wrong. Plus, the logic to set the actual value was wrong as well: the interval register can only be modified when the timer is disabled, and then enable it back, otherwise, it'll have no effect. Fix this logic as well since that code couldn't possibly work. Signed-off-by: Maxime Ripard Signed-off-by: Daniel Lezcano --- drivers/clocksource/sun4i_timer.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/drivers/clocksource/sun4i_timer.c b/drivers/clocksource/sun4i_timer.c index 8e9c65136451..7123f654ce71 100644 --- a/drivers/clocksource/sun4i_timer.c +++ b/drivers/clocksource/sun4i_timer.c @@ -38,6 +38,20 @@ static void __iomem *timer_base; +/* + * When we disable a timer, we need to wait at least for 2 cycles of + * the timer source clock. We will use for that the clocksource timer + * that is already setup and runs at the same frequency than the other + * timers, and we never will be disabled. + */ +static void sun4i_clkevt_sync(void) +{ + u32 old = readl(timer_base + TIMER_CNTVAL_REG(1)); + + while ((old - readl(timer_base + TIMER_CNTVAL_REG(1))) < 3) + cpu_relax(); +} + static void sun4i_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *clk) { @@ -63,9 +77,14 @@ static void sun4i_clkevt_mode(enum clock_event_mode mode, static int sun4i_clkevt_next_event(unsigned long evt, struct clock_event_device *unused) { - u32 u = readl(timer_base + TIMER_CTL_REG(0)); - writel(evt, timer_base + TIMER_CNTVAL_REG(0)); - writel(u | TIMER_CTL_ENABLE | TIMER_CTL_AUTORELOAD, + u32 val = readl(timer_base + TIMER_CTL_REG(0)); + writel(val & ~TIMER_CTL_ENABLE, timer_base + TIMER_CTL_REG(0)); + sun4i_clkevt_sync(); + + writel(evt, timer_base + TIMER_INTVAL_REG(0)); + + val = readl(timer_base + TIMER_CTL_REG(0)); + writel(val | TIMER_CTL_ENABLE | TIMER_CTL_AUTORELOAD, timer_base + TIMER_CTL_REG(0)); return 0; From 96651a0732d148f7e4a59cec6aa174049866cd0e Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 16 Jul 2013 16:45:38 +0200 Subject: [PATCH 0202/3400] clocksource: sun4i: Factor out some timer code The set_next_event and set_mode callbacks share a lot of common code we can easily factor to avoid duplication and mistakes. Signed-off-by: Maxime Ripard Signed-off-by: Daniel Lezcano --- drivers/clocksource/sun4i_timer.c | 48 ++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/drivers/clocksource/sun4i_timer.c b/drivers/clocksource/sun4i_timer.c index 7123f654ce71..dd78b63f3a24 100644 --- a/drivers/clocksource/sun4i_timer.c +++ b/drivers/clocksource/sun4i_timer.c @@ -52,24 +52,46 @@ static void sun4i_clkevt_sync(void) cpu_relax(); } +static void sun4i_clkevt_time_stop(u8 timer) +{ + u32 val = readl(timer_base + TIMER_CTL_REG(timer)); + writel(val & ~TIMER_CTL_ENABLE, timer_base + TIMER_CTL_REG(timer)); + sun4i_clkevt_sync(); +} + +static void sun4i_clkevt_time_setup(u8 timer, unsigned long delay) +{ + writel(delay, timer_base + TIMER_INTVAL_REG(timer)); +} + +static void sun4i_clkevt_time_start(u8 timer, bool periodic) +{ + u32 val = readl(timer_base + TIMER_CTL_REG(timer)); + + if (periodic) + val &= ~TIMER_CTL_ONESHOT; + else + val |= TIMER_CTL_ONESHOT; + + writel(val | TIMER_CTL_ENABLE, timer_base + TIMER_CTL_REG(timer)); +} + static void sun4i_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *clk) { - u32 u = readl(timer_base + TIMER_CTL_REG(0)); - switch (mode) { case CLOCK_EVT_MODE_PERIODIC: - u &= ~(TIMER_CTL_ONESHOT); - writel(u | TIMER_CTL_ENABLE, timer_base + TIMER_CTL_REG(0)); + sun4i_clkevt_time_stop(0); + sun4i_clkevt_time_start(0, true); break; - case CLOCK_EVT_MODE_ONESHOT: - writel(u | TIMER_CTL_ONESHOT, timer_base + TIMER_CTL_REG(0)); + sun4i_clkevt_time_stop(0); + sun4i_clkevt_time_start(0, false); break; case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_SHUTDOWN: default: - writel(u & ~(TIMER_CTL_ENABLE), timer_base + TIMER_CTL_REG(0)); + sun4i_clkevt_time_stop(0); break; } } @@ -77,15 +99,9 @@ static void sun4i_clkevt_mode(enum clock_event_mode mode, static int sun4i_clkevt_next_event(unsigned long evt, struct clock_event_device *unused) { - u32 val = readl(timer_base + TIMER_CTL_REG(0)); - writel(val & ~TIMER_CTL_ENABLE, timer_base + TIMER_CTL_REG(0)); - sun4i_clkevt_sync(); - - writel(evt, timer_base + TIMER_INTVAL_REG(0)); - - val = readl(timer_base + TIMER_CTL_REG(0)); - writel(val | TIMER_CTL_ENABLE | TIMER_CTL_AUTORELOAD, - timer_base + TIMER_CTL_REG(0)); + sun4i_clkevt_time_stop(0); + sun4i_clkevt_time_setup(0, evt); + sun4i_clkevt_time_start(0, false); return 0; } From c2b852f77b0d4c71967b61848d666c7a25e17627 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 16 Jul 2013 16:45:38 +0200 Subject: [PATCH 0203/3400] clocksource: sun4i: Remove TIMER_SCAL variable The prescaler is only used when using the internal low frequency oscillator (at 32kHz). Since we're using the higher frequency oscillator at 24MHz, we can just remove it. Signed-off-by: Maxime Ripard Signed-off-by: Daniel Lezcano --- drivers/clocksource/sun4i_timer.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/clocksource/sun4i_timer.c b/drivers/clocksource/sun4i_timer.c index dd78b63f3a24..3217adc7457c 100644 --- a/drivers/clocksource/sun4i_timer.c +++ b/drivers/clocksource/sun4i_timer.c @@ -34,8 +34,6 @@ #define TIMER_INTVAL_REG(val) (0x10 * (val) + 0x14) #define TIMER_CNTVAL_REG(val) (0x10 * (val) + 0x18) -#define TIMER_SCAL 16 - static void __iomem *timer_base; /* @@ -168,8 +166,7 @@ static void __init sun4i_timer_init(struct device_node *node) clocksource_mmio_init(timer_base + TIMER_CNTVAL_REG(1), node->name, rate, 300, 32, clocksource_mmio_readl_down); - writel(rate / (TIMER_SCAL * HZ), - timer_base + TIMER_INTVAL_REG(0)); + writel(rate / HZ, timer_base + TIMER_INTVAL_REG(0)); /* set clock source to HOSC, 16 pre-division */ val = readl(timer_base + TIMER_CTL_REG(0)); @@ -192,8 +189,8 @@ static void __init sun4i_timer_init(struct device_node *node) sun4i_clockevent.cpumask = cpumask_of(0); - clockevents_config_and_register(&sun4i_clockevent, rate / TIMER_SCAL, - 0x1, 0xff); + clockevents_config_and_register(&sun4i_clockevent, rate, 0x1, + 0xffffffff); } CLOCKSOURCE_OF_DECLARE(sun4i, "allwinner,sun4i-timer", sun4i_timer_init); From a2c49e7b553a28f10ab34e5da538ed4a45a697a7 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 16 Jul 2013 16:45:38 +0200 Subject: [PATCH 0204/3400] clocksource: sun4i: Cleanup parent clock setup The current bring-up code for the timer was overly complicated. The only thing we need is actually which clock we want to use as source and that's pretty much all. Let's keep it that way. Signed-off-by: Maxime Ripard Signed-off-by: Daniel Lezcano --- drivers/clocksource/sun4i_timer.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/drivers/clocksource/sun4i_timer.c b/drivers/clocksource/sun4i_timer.c index 3217adc7457c..2fadb3ba59db 100644 --- a/drivers/clocksource/sun4i_timer.c +++ b/drivers/clocksource/sun4i_timer.c @@ -30,6 +30,9 @@ #define TIMER_CTL_REG(val) (0x10 * val + 0x10) #define TIMER_CTL_ENABLE BIT(0) #define TIMER_CTL_RELOAD BIT(1) +#define TIMER_CTL_CLK_SRC(val) (((val) & 0x3) << 2) +#define TIMER_CTL_CLK_SRC_OSC24M (1) +#define TIMER_CTL_CLK_PRES(val) (((val) & 0x7) << 4) #define TIMER_CTL_ONESHOT BIT(7) #define TIMER_INTVAL_REG(val) (0x10 * (val) + 0x14) #define TIMER_CNTVAL_REG(val) (0x10 * (val) + 0x18) @@ -168,16 +171,8 @@ static void __init sun4i_timer_init(struct device_node *node) writel(rate / HZ, timer_base + TIMER_INTVAL_REG(0)); - /* set clock source to HOSC, 16 pre-division */ - val = readl(timer_base + TIMER_CTL_REG(0)); - val &= ~(0x07 << 4); - val &= ~(0x03 << 2); - val |= (4 << 4) | (1 << 2); - writel(val, timer_base + TIMER_CTL_REG(0)); - - /* set mode to auto reload */ - val = readl(timer_base + TIMER_CTL_REG(0)); - writel(val | TIMER_CTL_RELOAD, timer_base + TIMER_CTL_REG(0)); + writel(TIMER_CTL_CLK_SRC(TIMER_CTL_CLK_SRC_OSC24M) | TIMER_CTL_RELOAD, + timer_base + TIMER_CTL_REG(0)); ret = setup_irq(irq, &sun4i_timer_irq); if (ret) From 7e14183469d8aa2c7aa7675a6156e7846dda7748 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 16 Jul 2013 16:45:38 +0200 Subject: [PATCH 0205/3400] clocksource: sun4i: Fix bug when switching from periodic to oneshot modes The interval was firing at was set up at probe time, and only changed in the set_next_event, and never changed back, which is not really what is expected. When enabling the periodic mode, now set an interval to tick every jiffy. Signed-off-by: Maxime Ripard Signed-off-by: Daniel Lezcano --- drivers/clocksource/sun4i_timer.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/clocksource/sun4i_timer.c b/drivers/clocksource/sun4i_timer.c index 2fadb3ba59db..8ead0258740a 100644 --- a/drivers/clocksource/sun4i_timer.c +++ b/drivers/clocksource/sun4i_timer.c @@ -38,6 +38,7 @@ #define TIMER_CNTVAL_REG(val) (0x10 * (val) + 0x18) static void __iomem *timer_base; +static u32 ticks_per_jiffy; /* * When we disable a timer, we need to wait at least for 2 cycles of @@ -74,7 +75,8 @@ static void sun4i_clkevt_time_start(u8 timer, bool periodic) else val |= TIMER_CTL_ONESHOT; - writel(val | TIMER_CTL_ENABLE, timer_base + TIMER_CTL_REG(timer)); + writel(val | TIMER_CTL_ENABLE | TIMER_CTL_RELOAD, + timer_base + TIMER_CTL_REG(timer)); } static void sun4i_clkevt_mode(enum clock_event_mode mode, @@ -83,6 +85,7 @@ static void sun4i_clkevt_mode(enum clock_event_mode mode, switch (mode) { case CLOCK_EVT_MODE_PERIODIC: sun4i_clkevt_time_stop(0); + sun4i_clkevt_time_setup(0, ticks_per_jiffy); sun4i_clkevt_time_start(0, true); break; case CLOCK_EVT_MODE_ONESHOT: @@ -169,9 +172,9 @@ static void __init sun4i_timer_init(struct device_node *node) clocksource_mmio_init(timer_base + TIMER_CNTVAL_REG(1), node->name, rate, 300, 32, clocksource_mmio_readl_down); - writel(rate / HZ, timer_base + TIMER_INTVAL_REG(0)); + ticks_per_jiffy = DIV_ROUND_UP(rate, HZ); - writel(TIMER_CTL_CLK_SRC(TIMER_CTL_CLK_SRC_OSC24M) | TIMER_CTL_RELOAD, + writel(TIMER_CTL_CLK_SRC(TIMER_CTL_CLK_SRC_OSC24M), timer_base + TIMER_CTL_REG(0)); ret = setup_irq(irq, &sun4i_timer_irq); From 9bbf914043e04f65e619f3c0ff67c387812f9458 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Mon, 8 Jul 2013 09:51:37 -0700 Subject: [PATCH 0206/3400] clocksource: cadence_ttc: Remove unused header The clk-provider.h header is not required by this driver. Signed-off-by: Soren Brinkmann Signed-off-by: Daniel Lezcano --- drivers/clocksource/cadence_ttc_timer.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/clocksource/cadence_ttc_timer.c b/drivers/clocksource/cadence_ttc_timer.c index 4cbe28c74631..0eefc8d8622b 100644 --- a/drivers/clocksource/cadence_ttc_timer.c +++ b/drivers/clocksource/cadence_ttc_timer.c @@ -21,7 +21,6 @@ #include #include #include -#include /* * This driver configures the 2 16-bit count-up timers as follows: From 3d77b30efc72d126c2b74070b41a03869611228d Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Mon, 8 Jul 2013 09:51:38 -0700 Subject: [PATCH 0207/3400] clocksource: cadence_ttc: Reuse clocksource as sched_clock Reuse the TTC clocksource timer as sched clock provider. Signed-off-by: Soren Brinkmann Signed-off-by: Daniel Lezcano Acked-by: Michal Simek --- drivers/clocksource/cadence_ttc_timer.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/clocksource/cadence_ttc_timer.c b/drivers/clocksource/cadence_ttc_timer.c index 0eefc8d8622b..b2bb3a4bc205 100644 --- a/drivers/clocksource/cadence_ttc_timer.c +++ b/drivers/clocksource/cadence_ttc_timer.c @@ -21,6 +21,7 @@ #include #include #include +#include /* * This driver configures the 2 16-bit count-up timers as follows: @@ -94,6 +95,8 @@ struct ttc_timer_clockevent { #define to_ttc_timer_clkevent(x) \ container_of(x, struct ttc_timer_clockevent, ce) +static void __iomem *ttc_sched_clock_val_reg; + /** * ttc_set_interval - Set the timer interval value * @@ -155,6 +158,11 @@ static cycle_t __ttc_clocksource_read(struct clocksource *cs) TTC_COUNT_VAL_OFFSET); } +static u32 notrace ttc_sched_clock_read(void) +{ + return __raw_readl(ttc_sched_clock_val_reg); +} + /** * ttc_set_next_event - Sets the time interval for next event * @@ -296,6 +304,10 @@ static void __init ttc_setup_clocksource(struct clk *clk, void __iomem *base) kfree(ttccs); return; } + + ttc_sched_clock_val_reg = base + TTC_COUNT_VAL_OFFSET; + setup_sched_clock(ttc_sched_clock_read, 16, + clk_get_rate(ttccs->ttc.clk) / PRESCALE); } static int ttc_rate_change_clockevent_cb(struct notifier_block *nb, From 07862c1cd6675cde2dd4bd64e64d704ea2185b79 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Wed, 17 Jul 2013 10:04:57 +0200 Subject: [PATCH 0208/3400] ARM: clocksource: Add support for MOXA ART SoCs This patch adds an clocksource driver for the main timer(s) found on MOXA ART SoCs. The MOXA ART SoC provides three separate timers with individual count/load/match registers, two are used here: TIMER1: clockevents, used to support oneshot and periodic events TIMER2: set up as a free running counter, used as clocksource Timers are preconfigured by bootloader to count down and interrupt on match or zero. Count increments every APB clock cycle and is automatically reloaded when it reaches zero. Signed-off-by: Jonas Jensen Signed-off-by: Daniel Lezcano --- .../bindings/timer/moxa,moxart-timer.txt | 17 ++ drivers/clocksource/Makefile | 1 + drivers/clocksource/moxart_timer.c | 164 ++++++++++++++++++ 3 files changed, 182 insertions(+) create mode 100644 Documentation/devicetree/bindings/timer/moxa,moxart-timer.txt create mode 100644 drivers/clocksource/moxart_timer.c diff --git a/Documentation/devicetree/bindings/timer/moxa,moxart-timer.txt b/Documentation/devicetree/bindings/timer/moxa,moxart-timer.txt new file mode 100644 index 000000000000..77c4cfa198ee --- /dev/null +++ b/Documentation/devicetree/bindings/timer/moxa,moxart-timer.txt @@ -0,0 +1,17 @@ +MOXA ART timer + +Required properties: + +- compatible : Should be "moxa,moxart-timer" +- reg : Should contain registers location and length +- interrupts : Should contain the timer interrupt number +- clocks : Should contain phandle for APB clock "clkapb" + +Example: + + timer: timer@98400000 { + compatible = "moxa,moxart-timer"; + reg = <0x98400000 0x42>; + interrupts = <19 1>; + clocks = <&clkapb>; + }; diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 8b00c5cebfa4..704d6d342adc 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_ARMADA_370_XP_TIMER) += time-armada-370-xp.o obj-$(CONFIG_ORION_TIMER) += time-orion.o obj-$(CONFIG_ARCH_BCM2835) += bcm2835_timer.o obj-$(CONFIG_ARCH_MARCO) += timer-marco.o +obj-$(CONFIG_ARCH_MOXART) += moxart_timer.o obj-$(CONFIG_ARCH_MXS) += mxs_timer.o obj-$(CONFIG_ARCH_PRIMA2) += timer-prima2.o obj-$(CONFIG_SUN4I_TIMER) += sun4i_timer.o diff --git a/drivers/clocksource/moxart_timer.c b/drivers/clocksource/moxart_timer.c new file mode 100644 index 000000000000..08a5943b3e42 --- /dev/null +++ b/drivers/clocksource/moxart_timer.c @@ -0,0 +1,164 @@ +/* + * MOXA ART SoCs timer handling. + * + * Copyright (C) 2013 Jonas Jensen + * + * Jonas Jensen + * + * 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 + +#define TIMER1_BASE 0x00 +#define TIMER2_BASE 0x10 +#define TIMER3_BASE 0x20 + +#define REG_COUNT 0x0 /* writable */ +#define REG_LOAD 0x4 +#define REG_MATCH1 0x8 +#define REG_MATCH2 0xC + +#define TIMER_CR 0x30 +#define TIMER_INTR_STATE 0x34 +#define TIMER_INTR_MASK 0x38 + +/* + * TIMER_CR flags: + * + * TIMEREG_CR_*_CLOCK 0: PCLK, 1: EXT1CLK + * TIMEREG_CR_*_INT overflow interrupt enable bit + */ +#define TIMEREG_CR_1_ENABLE BIT(0) +#define TIMEREG_CR_1_CLOCK BIT(1) +#define TIMEREG_CR_1_INT BIT(2) +#define TIMEREG_CR_2_ENABLE BIT(3) +#define TIMEREG_CR_2_CLOCK BIT(4) +#define TIMEREG_CR_2_INT BIT(5) +#define TIMEREG_CR_3_ENABLE BIT(6) +#define TIMEREG_CR_3_CLOCK BIT(7) +#define TIMEREG_CR_3_INT BIT(8) +#define TIMEREG_CR_COUNT_UP BIT(9) + +#define TIMER1_ENABLE (TIMEREG_CR_2_ENABLE | TIMEREG_CR_1_ENABLE) +#define TIMER1_DISABLE (TIMEREG_CR_2_ENABLE) + +static void __iomem *base; +static unsigned int clock_count_per_tick; + +static void moxart_clkevt_mode(enum clock_event_mode mode, + struct clock_event_device *clk) +{ + switch (mode) { + case CLOCK_EVT_MODE_RESUME: + case CLOCK_EVT_MODE_ONESHOT: + writel(TIMER1_DISABLE, base + TIMER_CR); + writel(~0, base + TIMER1_BASE + REG_LOAD); + break; + case CLOCK_EVT_MODE_PERIODIC: + writel(clock_count_per_tick, base + TIMER1_BASE + REG_LOAD); + writel(TIMER1_ENABLE, base + TIMER_CR); + break; + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + default: + writel(TIMER1_DISABLE, base + TIMER_CR); + break; + } +} + +static int moxart_clkevt_next_event(unsigned long cycles, + struct clock_event_device *unused) +{ + u32 u; + + writel(TIMER1_DISABLE, base + TIMER_CR); + + u = readl(base + TIMER1_BASE + REG_COUNT) - cycles; + writel(u, base + TIMER1_BASE + REG_MATCH1); + + writel(TIMER1_ENABLE, base + TIMER_CR); + + return 0; +} + +static struct clock_event_device moxart_clockevent = { + .name = "moxart_timer", + .rating = 200, + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, + .set_mode = moxart_clkevt_mode, + .set_next_event = moxart_clkevt_next_event, +}; + +static irqreturn_t moxart_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *evt = dev_id; + evt->event_handler(evt); + return IRQ_HANDLED; +} + +static struct irqaction moxart_timer_irq = { + .name = "moxart-timer", + .flags = IRQF_TIMER, + .handler = moxart_timer_interrupt, + .dev_id = &moxart_clockevent, +}; + +static void __init moxart_timer_init(struct device_node *node) +{ + int ret, irq; + unsigned long pclk; + struct clk *clk; + + base = of_iomap(node, 0); + if (!base) + panic("%s: of_iomap failed\n", node->full_name); + + irq = irq_of_parse_and_map(node, 0); + if (irq <= 0) + panic("%s: irq_of_parse_and_map failed\n", node->full_name); + + ret = setup_irq(irq, &moxart_timer_irq); + if (ret) + panic("%s: setup_irq failed\n", node->full_name); + + clk = of_clk_get(node, 0); + if (IS_ERR(clk)) + panic("%s: of_clk_get failed\n", node->full_name); + + pclk = clk_get_rate(clk); + + if (clocksource_mmio_init(base + TIMER2_BASE + REG_COUNT, + "moxart_timer", pclk, 200, 32, + clocksource_mmio_readl_down)) + panic("%s: clocksource_mmio_init failed\n", node->full_name); + + clock_count_per_tick = DIV_ROUND_CLOSEST(pclk, HZ); + + writel(~0, base + TIMER2_BASE + REG_LOAD); + writel(TIMEREG_CR_2_ENABLE, base + TIMER_CR); + + moxart_clockevent.cpumask = cpumask_of(0); + moxart_clockevent.irq = irq; + + /* + * documentation is not publicly available: + * min_delta / max_delta obtained by trial-and-error, + * max_delta 0xfffffffe should be ok because count + * register size is u32 + */ + clockevents_config_and_register(&moxart_clockevent, pclk, + 0x4, 0xfffffffe); +} +CLOCKSOURCE_OF_DECLARE(moxart, "moxa,moxart-timer", moxart_timer_init); From a56d66a2f01b172bc00d73b0b0392423c8aaae19 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 18 Jul 2013 22:21:57 +0800 Subject: [PATCH 0209/3400] regulator: core: Allow fixed voltage range in multiple linear ranges Current code does not allow fixed voltage range in multiple linear ranges. If someone does set range->uV_step == 0 in one of the linear ranges, we hit divided by zero bug. This patch fixes this issue. For fixed voltage range, return any selector means the same voltage. Thus just return 0. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/core.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index e8604be4c66d..fd3f6e003729 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2436,9 +2436,15 @@ int regulator_map_voltage_linear_range(struct regulator_dev *rdev, if (min_uV <= range->min_uV) min_uV = range->min_uV; - ret = DIV_ROUND_UP(min_uV - range->min_uV, range->uV_step); - if (ret < 0) - return ret; + /* range->uV_step == 0 means fixed voltage range */ + if (range->uV_step == 0) { + ret = 0; + } else { + ret = DIV_ROUND_UP(min_uV - range->min_uV, + range->uV_step); + if (ret < 0) + return ret; + } break; } From 6c918d220925eeeca75b67e896eabffd061cd128 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 18 Jul 2013 16:06:33 +0100 Subject: [PATCH 0210/3400] regulator: core: Ensure selector is mapped Clearly the testing only covered the bottom range. Signed-off-by: Mark Brown --- drivers/regulator/core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index fd3f6e003729..42ae134797e0 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2446,6 +2446,8 @@ int regulator_map_voltage_linear_range(struct regulator_dev *rdev, return ret; } + ret += range->min_sel; + break; } From 078726ce6d56a767533064e0f2f2100d7cb6fc22 Mon Sep 17 00:00:00 2001 From: Sourav Poddar Date: Thu, 18 Jul 2013 15:31:25 +0530 Subject: [PATCH 0211/3400] driver: spi: Modify core to compute the message length Make spi core calculate the message length while populating the other transfer parameters. Usecase, driver can use it to populate framelength filed in their controller. Signed-off-by: Sourav Poddar Signed-off-by: Mark Brown --- drivers/spi/spi.c | 1 + include/linux/spi/spi.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 978dda2c5239..7e3446cab72f 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1375,6 +1375,7 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message) * it is not set for this transfer. */ list_for_each_entry(xfer, &message->transfers, transfer_list) { + message->frame_length += xfer->len; if (!xfer->bits_per_word) xfer->bits_per_word = spi->bits_per_word; if (!xfer->speed_hz) diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 28e440be1c07..aadd0a885a0f 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -578,6 +578,7 @@ struct spi_message { /* completion is reported through a callback */ void (*complete)(void *context); void *context; + unsigned frame_length; unsigned actual_length; int status; From 69b90f1aadd68fb61d7ff182886f11761086c04a Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Wed, 3 Jul 2013 12:51:36 +0200 Subject: [PATCH 0212/3400] ARM: at91/DT: at91sam9x5ek: fix USB host property to enable port C Device Tree "num-ports" property of USB host node has to be set to maximum number of ports available. The possibility to activate a particular port is done by specifying the proper gpio configuration for its vbus. This patch fixes the USB host node by configuring the 3 ports available on the product and letting "port A" available for USB gadget usage. Reported-by: Rodolfo Giometti Signed-off-by: Nicolas Ferre Acked-by: Jean-Christophe PLAGNIOL-VILLARD Cc: Bo Shen --- arch/arm/boot/dts/at91sam9x5ek.dtsi | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/at91sam9x5ek.dtsi b/arch/arm/boot/dts/at91sam9x5ek.dtsi index b753855b2058..49e3c45818c2 100644 --- a/arch/arm/boot/dts/at91sam9x5ek.dtsi +++ b/arch/arm/boot/dts/at91sam9x5ek.dtsi @@ -94,8 +94,9 @@ usb0: ohci@00600000 { status = "okay"; - num-ports = <2>; - atmel,vbus-gpio = <&pioD 19 GPIO_ACTIVE_LOW + num-ports = <3>; + atmel,vbus-gpio = <0 /* &pioD 18 GPIO_ACTIVE_LOW *//* Activate to have access to port A */ + &pioD 19 GPIO_ACTIVE_LOW &pioD 20 GPIO_ACTIVE_LOW >; }; From a39a9f7b6608c83b89ae404cc39e6607ccdccdde Mon Sep 17 00:00:00 2001 From: Rohit Vaswani Date: Tue, 18 Jun 2013 18:53:31 -0700 Subject: [PATCH 0213/3400] ARM: msm: dts: Fix the gpio register address for msm8960 Fix the the gpio reg address for the device tree entry. Signed-off-by: Rohit Vaswani Signed-off-by: David Brown --- arch/arm/boot/dts/msm8960-cdp.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/msm8960-cdp.dts b/arch/arm/boot/dts/msm8960-cdp.dts index db2060c46540..9c1167b0459b 100644 --- a/arch/arm/boot/dts/msm8960-cdp.dts +++ b/arch/arm/boot/dts/msm8960-cdp.dts @@ -26,7 +26,7 @@ cpu-offset = <0x80000>; }; - msmgpio: gpio@fd510000 { + msmgpio: gpio@800000 { compatible = "qcom,msm-gpio"; gpio-controller; #gpio-cells = <2>; @@ -34,7 +34,7 @@ interrupts = <0 32 0x4>; interrupt-controller; #interrupt-cells = <2>; - reg = <0xfd510000 0x4000>; + reg = <0x800000 0x4000>; }; serial@16440000 { From c7e85c42be68fca743df58a306edd29aa295e155 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Thu, 18 Jul 2013 20:47:47 +0900 Subject: [PATCH 0214/3400] kprobes/x86: Remove an incorrect comment about int3 in NMI/MCE Remove a comment about an int3 issue in NMI/MCE, since commit: 3f3c8b8c4b2a ("x86: Add workaround to NMI iret woes") already fixed that. Keeping this incorrect comment can mislead developers. Signed-off-by: Masami Hiramatsu Reviewed-by: Jiri Kosina Cc: H. Peter Anvin Cc: Steven Rostedt Cc: Jason Baron Cc: yrl.pp-manager.tt@hitachi.com Cc: Borislav Petkov Link: http://lkml.kernel.org/r/20130718114747.26675.84110.stgit@mhiramat-M0-7522 Signed-off-by: Ingo Molnar --- arch/x86/kernel/kprobes/opt.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/arch/x86/kernel/kprobes/opt.c b/arch/x86/kernel/kprobes/opt.c index 76dc6f095724..d7d8a8c10635 100644 --- a/arch/x86/kernel/kprobes/opt.c +++ b/arch/x86/kernel/kprobes/opt.c @@ -415,11 +415,6 @@ void __kprobes arch_optimize_kprobes(struct list_head *oplist) break; } - /* - * text_poke_smp doesn't support NMI/MCE code modifying. - * However, since kprobes itself also doesn't support NMI/MCE - * code probing, it's not a problem. - */ text_poke_smp_batch(jump_poke_params, c); } @@ -455,11 +450,6 @@ extern void arch_unoptimize_kprobes(struct list_head *oplist, break; } - /* - * text_poke_smp doesn't support NMI/MCE code modifying. - * However, since kprobes itself also doesn't support NMI/MCE - * code probing, it's not a problem. - */ text_poke_smp_batch(jump_poke_params, c); } From a7b0133ea94e4421a81702d5c0e6dcdbbbab8f6b Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Thu, 18 Jul 2013 20:47:50 +0900 Subject: [PATCH 0215/3400] kprobes/x86: Use text_poke_bp() instead of text_poke_smp*() Use text_poke_bp() for optimizing kprobes instead of text_poke_smp*(). Since the number of kprobes is usually not so large (<100) and text_poke_bp() is much lighter than text_poke_smp() [which uses stop_machine()], this just stops using batch processing. Signed-off-by: Masami Hiramatsu Reviewed-by: Jiri Kosina Cc: H. Peter Anvin Cc: Steven Rostedt Cc: Jason Baron Cc: yrl.pp-manager.tt@hitachi.com Cc: Borislav Petkov Link: http://lkml.kernel.org/r/20130718114750.26675.9174.stgit@mhiramat-M0-7522 Signed-off-by: Ingo Molnar --- arch/x86/kernel/kprobes/common.h | 5 -- arch/x86/kernel/kprobes/core.c | 2 +- arch/x86/kernel/kprobes/opt.c | 104 +++++++------------------------ 3 files changed, 25 insertions(+), 86 deletions(-) diff --git a/arch/x86/kernel/kprobes/common.h b/arch/x86/kernel/kprobes/common.h index 2e9d4b5af036..c6ee63f927ab 100644 --- a/arch/x86/kernel/kprobes/common.h +++ b/arch/x86/kernel/kprobes/common.h @@ -82,14 +82,9 @@ extern void synthesize_reljump(void *from, void *to); extern void synthesize_relcall(void *from, void *to); #ifdef CONFIG_OPTPROBES -extern int arch_init_optprobes(void); extern int setup_detour_execution(struct kprobe *p, struct pt_regs *regs, int reenter); extern unsigned long __recover_optprobed_insn(kprobe_opcode_t *buf, unsigned long addr); #else /* !CONFIG_OPTPROBES */ -static inline int arch_init_optprobes(void) -{ - return 0; -} static inline int setup_detour_execution(struct kprobe *p, struct pt_regs *regs, int reenter) { return 0; diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c index 211bce445522..cd49b2c96d32 100644 --- a/arch/x86/kernel/kprobes/core.c +++ b/arch/x86/kernel/kprobes/core.c @@ -1068,7 +1068,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) int __init arch_init_kprobes(void) { - return arch_init_optprobes(); + return 0; } int __kprobes arch_trampoline_kprobe(struct kprobe *p) diff --git a/arch/x86/kernel/kprobes/opt.c b/arch/x86/kernel/kprobes/opt.c index d7d8a8c10635..d71e99439376 100644 --- a/arch/x86/kernel/kprobes/opt.c +++ b/arch/x86/kernel/kprobes/opt.c @@ -371,31 +371,6 @@ int __kprobes arch_prepare_optimized_kprobe(struct optimized_kprobe *op) return 0; } -#define MAX_OPTIMIZE_PROBES 256 -static struct text_poke_param *jump_poke_params; -static struct jump_poke_buffer { - u8 buf[RELATIVEJUMP_SIZE]; -} *jump_poke_bufs; - -static void __kprobes setup_optimize_kprobe(struct text_poke_param *tprm, - u8 *insn_buf, - struct optimized_kprobe *op) -{ - s32 rel = (s32)((long)op->optinsn.insn - - ((long)op->kp.addr + RELATIVEJUMP_SIZE)); - - /* Backup instructions which will be replaced by jump address */ - memcpy(op->optinsn.copied_insn, op->kp.addr + INT3_SIZE, - RELATIVE_ADDR_SIZE); - - insn_buf[0] = RELATIVEJUMP_OPCODE; - *(s32 *)(&insn_buf[1]) = rel; - - tprm->addr = op->kp.addr; - tprm->opcode = insn_buf; - tprm->len = RELATIVEJUMP_SIZE; -} - /* * Replace breakpoints (int3) with relative jumps. * Caller must call with locking kprobe_mutex and text_mutex. @@ -403,32 +378,38 @@ static void __kprobes setup_optimize_kprobe(struct text_poke_param *tprm, void __kprobes arch_optimize_kprobes(struct list_head *oplist) { struct optimized_kprobe *op, *tmp; - int c = 0; + u8 insn_buf[RELATIVEJUMP_SIZE]; list_for_each_entry_safe(op, tmp, oplist, list) { - WARN_ON(kprobe_disabled(&op->kp)); - /* Setup param */ - setup_optimize_kprobe(&jump_poke_params[c], - jump_poke_bufs[c].buf, op); - list_del_init(&op->list); - if (++c >= MAX_OPTIMIZE_PROBES) - break; - } + s32 rel = (s32)((long)op->optinsn.insn - + ((long)op->kp.addr + RELATIVEJUMP_SIZE)); - text_poke_smp_batch(jump_poke_params, c); + WARN_ON(kprobe_disabled(&op->kp)); + + /* Backup instructions which will be replaced by jump address */ + memcpy(op->optinsn.copied_insn, op->kp.addr + INT3_SIZE, + RELATIVE_ADDR_SIZE); + + insn_buf[0] = RELATIVEJUMP_OPCODE; + *(s32 *)(&insn_buf[1]) = rel; + + text_poke_bp(op->kp.addr, insn_buf, RELATIVEJUMP_SIZE, + op->optinsn.insn); + + list_del_init(&op->list); + } } -static void __kprobes setup_unoptimize_kprobe(struct text_poke_param *tprm, - u8 *insn_buf, - struct optimized_kprobe *op) +/* Replace a relative jump with a breakpoint (int3). */ +void __kprobes arch_unoptimize_kprobe(struct optimized_kprobe *op) { + u8 insn_buf[RELATIVEJUMP_SIZE]; + /* Set int3 to first byte for kprobes */ insn_buf[0] = BREAKPOINT_INSTRUCTION; memcpy(insn_buf + 1, op->optinsn.copied_insn, RELATIVE_ADDR_SIZE); - - tprm->addr = op->kp.addr; - tprm->opcode = insn_buf; - tprm->len = RELATIVEJUMP_SIZE; + text_poke_bp(op->kp.addr, insn_buf, RELATIVEJUMP_SIZE, + op->optinsn.insn); } /* @@ -439,29 +420,11 @@ extern void arch_unoptimize_kprobes(struct list_head *oplist, struct list_head *done_list) { struct optimized_kprobe *op, *tmp; - int c = 0; list_for_each_entry_safe(op, tmp, oplist, list) { - /* Setup param */ - setup_unoptimize_kprobe(&jump_poke_params[c], - jump_poke_bufs[c].buf, op); + arch_unoptimize_kprobe(op); list_move(&op->list, done_list); - if (++c >= MAX_OPTIMIZE_PROBES) - break; } - - text_poke_smp_batch(jump_poke_params, c); -} - -/* Replace a relative jump with a breakpoint (int3). */ -void __kprobes arch_unoptimize_kprobe(struct optimized_kprobe *op) -{ - u8 buf[RELATIVEJUMP_SIZE]; - - /* Set int3 to first byte for kprobes */ - buf[0] = BREAKPOINT_INSTRUCTION; - memcpy(buf + 1, op->optinsn.copied_insn, RELATIVE_ADDR_SIZE); - text_poke_smp(op->kp.addr, buf, RELATIVEJUMP_SIZE); } int __kprobes @@ -481,22 +444,3 @@ setup_detour_execution(struct kprobe *p, struct pt_regs *regs, int reenter) } return 0; } - -int __kprobes arch_init_optprobes(void) -{ - /* Allocate code buffer and parameter array */ - jump_poke_bufs = kmalloc(sizeof(struct jump_poke_buffer) * - MAX_OPTIMIZE_PROBES, GFP_KERNEL); - if (!jump_poke_bufs) - return -ENOMEM; - - jump_poke_params = kmalloc(sizeof(struct text_poke_param) * - MAX_OPTIMIZE_PROBES, GFP_KERNEL); - if (!jump_poke_params) { - kfree(jump_poke_bufs); - jump_poke_bufs = NULL; - return -ENOMEM; - } - - return 0; -} From ea8596bb2d8d37957f3e92db9511c50801689180 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Thu, 18 Jul 2013 20:47:53 +0900 Subject: [PATCH 0216/3400] kprobes/x86: Remove unused text_poke_smp() and text_poke_smp_batch() functions Since introducing the text_poke_bp() for all text_poke_smp*() callers, text_poke_smp*() are now unused. This patch basically reverts: 3d55cc8a058e ("x86: Add text_poke_smp for SMP cross modifying code") 7deb18dcf047 ("x86: Introduce text_poke_smp_batch() for batch-code modifying") and related commits. This patch also fixes a Kconfig dependency issue on STOP_MACHINE in the case of CONFIG_SMP && !CONFIG_MODULE_UNLOAD. Signed-off-by: Masami Hiramatsu Reviewed-by: Jiri Kosina Cc: H. Peter Anvin Cc: Steven Rostedt Cc: Jason Baron Cc: yrl.pp-manager.tt@hitachi.com Cc: Borislav Petkov Link: http://lkml.kernel.org/r/20130718114753.26675.18714.stgit@mhiramat-M0-7522 Signed-off-by: Ingo Molnar --- arch/x86/Kconfig | 5 -- arch/x86/include/asm/alternative.h | 11 ---- arch/x86/kernel/alternative.c | 98 +----------------------------- 3 files changed, 2 insertions(+), 112 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index b32ebf92b0ce..3106e0e2647a 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -81,7 +81,6 @@ config X86 select HAVE_USER_RETURN_NOTIFIER select ARCH_BINFMT_ELF_RANDOMIZE_PIE select HAVE_ARCH_JUMP_LABEL - select HAVE_TEXT_POKE_SMP select HAVE_GENERIC_HARDIRQS select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE select SPARSE_IRQ @@ -2332,10 +2331,6 @@ config HAVE_ATOMIC_IOMAP def_bool y depends on X86_32 -config HAVE_TEXT_POKE_SMP - bool - select STOP_MACHINE if SMP - config X86_DEV_DMA_OPS bool depends on X86_64 || STA2X11 diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h index 3abf8dd6f44f..4daf8c501239 100644 --- a/arch/x86/include/asm/alternative.h +++ b/arch/x86/include/asm/alternative.h @@ -220,21 +220,10 @@ extern void *text_poke_early(void *addr, const void *opcode, size_t len); * no thread can be preempted in the instructions being modified (no iret to an * invalid instruction possible) or if the instructions are changed from a * consistent state to another consistent state atomically. - * More care must be taken when modifying code in the SMP case because of - * Intel's errata. text_poke_smp() takes care that errata, but still - * doesn't support NMI/MCE handler code modifying. * On the local CPU you need to be protected again NMI or MCE handlers seeing an * inconsistent instruction while you patch. */ -struct text_poke_param { - void *addr; - const void *opcode; - size_t len; -}; - extern void *text_poke(void *addr, const void *opcode, size_t len); extern void *text_poke_bp(void *addr, const void *opcode, size_t len, void *handler); -extern void *text_poke_smp(void *addr, const void *opcode, size_t len); -extern void text_poke_smp_batch(struct text_poke_param *params, int n); #endif /* _ASM_X86_ALTERNATIVE_H */ diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index 0ab49366a7a6..5d8782ee3dd7 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -633,8 +633,8 @@ static int int3_notify(struct notifier_block *self, unsigned long val, void *dat * @handler: address to jump to when the temporary breakpoint is hit * * Modify multi-byte instruction by using int3 breakpoint on SMP. - * In contrary to text_poke_smp(), we completely avoid stop_machine() here, - * and achieve the synchronization using int3 breakpoint. + * We completely avoid stop_machine() here, and achieve the + * synchronization using int3 breakpoint. * * The way it is done: * - add a int3 trap to the address that will be patched @@ -702,97 +702,3 @@ static int __init int3_init(void) } arch_initcall(int3_init); -/* - * Cross-modifying kernel text with stop_machine(). - * This code originally comes from immediate value. - */ -static atomic_t stop_machine_first; -static int wrote_text; - -struct text_poke_params { - struct text_poke_param *params; - int nparams; -}; - -static int __kprobes stop_machine_text_poke(void *data) -{ - struct text_poke_params *tpp = data; - struct text_poke_param *p; - int i; - - if (atomic_xchg(&stop_machine_first, 0)) { - for (i = 0; i < tpp->nparams; i++) { - p = &tpp->params[i]; - text_poke(p->addr, p->opcode, p->len); - } - smp_wmb(); /* Make sure other cpus see that this has run */ - wrote_text = 1; - } else { - while (!wrote_text) - cpu_relax(); - smp_mb(); /* Load wrote_text before following execution */ - } - - for (i = 0; i < tpp->nparams; i++) { - p = &tpp->params[i]; - flush_icache_range((unsigned long)p->addr, - (unsigned long)p->addr + p->len); - } - /* - * Intel Archiecture Software Developer's Manual section 7.1.3 specifies - * that a core serializing instruction such as "cpuid" should be - * executed on _each_ core before the new instruction is made visible. - */ - sync_core(); - return 0; -} - -/** - * text_poke_smp - Update instructions on a live kernel on SMP - * @addr: address to modify - * @opcode: source of the copy - * @len: length to copy - * - * Modify multi-byte instruction by using stop_machine() on SMP. This allows - * user to poke/set multi-byte text on SMP. Only non-NMI/MCE code modifying - * should be allowed, since stop_machine() does _not_ protect code against - * NMI and MCE. - * - * Note: Must be called under get_online_cpus() and text_mutex. - */ -void *__kprobes text_poke_smp(void *addr, const void *opcode, size_t len) -{ - struct text_poke_params tpp; - struct text_poke_param p; - - p.addr = addr; - p.opcode = opcode; - p.len = len; - tpp.params = &p; - tpp.nparams = 1; - atomic_set(&stop_machine_first, 1); - wrote_text = 0; - /* Use __stop_machine() because the caller already got online_cpus. */ - __stop_machine(stop_machine_text_poke, (void *)&tpp, cpu_online_mask); - return addr; -} - -/** - * text_poke_smp_batch - Update instructions on a live kernel on SMP - * @params: an array of text_poke parameters - * @n: the number of elements in params. - * - * Modify multi-byte instruction by using stop_machine() on SMP. Since the - * stop_machine() is heavy task, it is better to aggregate text_poke requests - * and do it once if possible. - * - * Note: Must be called under get_online_cpus() and text_mutex. - */ -void __kprobes text_poke_smp_batch(struct text_poke_param *params, int n) -{ - struct text_poke_params tpp = {.params = params, .nparams = n}; - - atomic_set(&stop_machine_first, 1); - wrote_text = 0; - __stop_machine(stop_machine_text_poke, (void *)&tpp, cpu_online_mask); -} From 95f1dc08c6f98a62b5dae6ed86fa04f40fb6b34f Mon Sep 17 00:00:00 2001 From: Chao Xie Date: Wed, 17 Jul 2013 23:07:03 -0400 Subject: [PATCH 0217/3400] regulator: 88pm800: add regulator driver for 88pm800 Add the regulator driver for PMIC 88pm800 including device tree support. 88pm800 is an I2C-based power-management IC containing voltage regulators, a real-time clock, and some general purpose ADC devices, Signed-off-by: Yi Zhang Signed-off-by: Chao Xie Signed-off-by: Mark Brown --- .../devicetree/bindings/regulator/88pm800.txt | 38 ++ drivers/regulator/88pm800.c | 377 ++++++++++++++++++ drivers/regulator/Kconfig | 10 + drivers/regulator/Makefile | 1 + 4 files changed, 426 insertions(+) create mode 100644 Documentation/devicetree/bindings/regulator/88pm800.txt create mode 100644 drivers/regulator/88pm800.c diff --git a/Documentation/devicetree/bindings/regulator/88pm800.txt b/Documentation/devicetree/bindings/regulator/88pm800.txt new file mode 100644 index 000000000000..e8a54c2a5821 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/88pm800.txt @@ -0,0 +1,38 @@ +Marvell 88PM800 regulator + +Required properties: +- compatible: "marvell,88pm800" +- reg: I2C slave address +- regulators: A node that houses a sub-node for each regulator within the + device. Each sub-node is identified using the node's name (or the deprecated + regulator-compatible property if present), with valid values listed below. + The content of each sub-node is defined by the standard binding for + regulators; see regulator.txt. + +The valid names for regulators are: + + buck1, buck2, buck3, buck4, buck5, ldo1, ldo2, ldo3, ldo4, ldo5, ldo6, ldo7, + ldo8, ldo9, ldo10, ldo11, ldo12, ldo13, ldo14, ldo15, ldo16, ldo17, ldo18, ldo19 + +Example: + + pmic: 88pm800@31 { + compatible = "marvell,88pm800"; + reg = <0x31>; + + regulators { + buck1 { + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <3950000>; + regulator-boot-on; + regulator-always-on; + }; + ldo1 { + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <15000000>; + regulator-boot-on; + regulator-always-on; + }; +... + }; + }; diff --git a/drivers/regulator/88pm800.c b/drivers/regulator/88pm800.c new file mode 100644 index 000000000000..a7d962f7a9b4 --- /dev/null +++ b/drivers/regulator/88pm800.c @@ -0,0 +1,377 @@ +/* + * Regulators driver for Marvell 88PM800 + * + * Copyright (C) 2012 Marvell International Ltd. + * Joseph(Yossi) Hanin + * Yi Zhang + * + * 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 + +/* LDO1 with DVC[0..3] */ +#define PM800_LDO1_VOUT (0x08) /* VOUT1 */ +#define PM800_LDO1_VOUT_2 (0x09) +#define PM800_LDO1_VOUT_3 (0x0A) +#define PM800_LDO2_VOUT (0x0B) +#define PM800_LDO3_VOUT (0x0C) +#define PM800_LDO4_VOUT (0x0D) +#define PM800_LDO5_VOUT (0x0E) +#define PM800_LDO6_VOUT (0x0F) +#define PM800_LDO7_VOUT (0x10) +#define PM800_LDO8_VOUT (0x11) +#define PM800_LDO9_VOUT (0x12) +#define PM800_LDO10_VOUT (0x13) +#define PM800_LDO11_VOUT (0x14) +#define PM800_LDO12_VOUT (0x15) +#define PM800_LDO13_VOUT (0x16) +#define PM800_LDO14_VOUT (0x17) +#define PM800_LDO15_VOUT (0x18) +#define PM800_LDO16_VOUT (0x19) +#define PM800_LDO17_VOUT (0x1A) +#define PM800_LDO18_VOUT (0x1B) +#define PM800_LDO19_VOUT (0x1C) + +/* BUCK1 with DVC[0..3] */ +#define PM800_BUCK1 (0x3C) +#define PM800_BUCK1_1 (0x3D) +#define PM800_BUCK1_2 (0x3E) +#define PM800_BUCK1_3 (0x3F) +#define PM800_BUCK2 (0x40) +#define PM800_BUCK3 (0x41) +#define PM800_BUCK3 (0x41) +#define PM800_BUCK4 (0x42) +#define PM800_BUCK4_1 (0x43) +#define PM800_BUCK4_2 (0x44) +#define PM800_BUCK4_3 (0x45) +#define PM800_BUCK5 (0x46) + +#define PM800_BUCK_ENA (0x50) +#define PM800_LDO_ENA1_1 (0x51) +#define PM800_LDO_ENA1_2 (0x52) +#define PM800_LDO_ENA1_3 (0x53) + +#define PM800_LDO_ENA2_1 (0x56) +#define PM800_LDO_ENA2_2 (0x57) +#define PM800_LDO_ENA2_3 (0x58) + +#define PM800_BUCK1_MISC1 (0x78) +#define PM800_BUCK3_MISC1 (0x7E) +#define PM800_BUCK4_MISC1 (0x81) +#define PM800_BUCK5_MISC1 (0x84) + +struct pm800_regulator_info { + struct regulator_desc desc; + int max_ua; +}; + +struct pm800_regulators { + struct regulator_dev *regulators[PM800_ID_RG_MAX]; + struct pm80x_chip *chip; + struct regmap *map; +}; + +/* + * vreg - the buck regs string. + * ereg - the string for the enable register. + * ebit - the bit number in the enable register. + * amax - the current + * Buck has 2 kinds of voltage steps. It is easy to find voltage by ranges, + * not the constant voltage table. + */ +#define PM800_BUCK(vreg, ereg, ebit, amax, volt_ranges) \ +{ \ + .desc = { \ + .name = #vreg, \ + .ops = &pm800_volt_range_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = PM800_ID_##vreg, \ + .owner = THIS_MODULE, \ + .linear_ranges = volt_ranges, \ + .n_linear_ranges = ARRAY_SIZE(volt_ranges), \ + .vsel_reg = PM800_##vreg, \ + .vsel_mask = 0x7f, \ + .enable_reg = PM800_##ereg, \ + .enable_mask = 1 << (ebit), \ + }, \ + .max_ua = (amax), \ +} + +/* + * vreg - the LDO regs string + * ereg - the string for the enable register. + * ebit - the bit number in the enable register. + * amax - the current + * volt_table - the LDO voltage table + * For all the LDOes, there are too many ranges. Using volt_table will be + * simpler and faster. + */ +#define PM800_LDO(vreg, ereg, ebit, amax, ldo_volt_table) \ +{ \ + .desc = { \ + .name = #vreg, \ + .ops = &pm800_volt_table_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = PM800_ID_##vreg, \ + .owner = THIS_MODULE, \ + .n_voltages = ARRAY_SIZE(ldo_volt_table), \ + .vsel_reg = PM800_##vreg##_VOUT, \ + .vsel_mask = 0x1f, \ + .enable_reg = PM800_##ereg, \ + .enable_mask = 1 << (ebit), \ + .volt_table = ldo_volt_table, \ + }, \ + .max_ua = (amax), \ +} + +/* Ranges are sorted in ascending order. */ +static const struct regulator_linear_range buck1_volt_range[] = { + { .min_uV = 600000, .max_uV = 1587500, .min_sel = 0, .max_sel = 0x4f, + .uV_step = 12500 }, + { .min_uV = 1600000, .max_uV = 1800000, .min_sel = 0x50, + .max_sel = 0x54, .uV_step = 50000 }, +}; + +/* BUCK 2~5 have same ranges. */ +static const struct regulator_linear_range buck2_5_volt_range[] = { + { .min_uV = 600000, .max_uV = 1587500, .min_sel = 0, .max_sel = 0x4f, + .uV_step = 12500 }, + { .min_uV = 1600000, .max_uV = 3300000, .min_sel = 0x50, + .max_sel = 0x72, .uV_step = 50000 }, +}; + +static const unsigned int ldo1_volt_table[] = { + 600000, 650000, 700000, 750000, 800000, 850000, 900000, 950000, + 1000000, 1050000, 1100000, 1150000, 1200000, 1300000, 1400000, 1500000, +}; + +static const unsigned int ldo2_volt_table[] = { + 1700000, 1800000, 1900000, 2000000, 2100000, 2500000, 2700000, 2800000, +}; + +/* LDO 3~17 have same voltage table. */ +static const unsigned int ldo3_17_volt_table[] = { + 1200000, 1250000, 1700000, 1800000, 1850000, 1900000, 2500000, 2600000, + 2700000, 2750000, 2800000, 2850000, 2900000, 3000000, 3100000, 3300000, +}; + +/* LDO 18~19 have same voltage table. */ +static const unsigned int ldo18_19_volt_table[] = { + 1700000, 1800000, 1900000, 2500000, 2800000, 2900000, 3100000, 3300000, +}; + +static int pm800_get_current_limit(struct regulator_dev *rdev) +{ + struct pm800_regulator_info *info = rdev_get_drvdata(rdev); + + return info->max_ua; +} + +static struct regulator_ops pm800_volt_range_ops = { + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .get_current_limit = pm800_get_current_limit, +}; + +static struct regulator_ops pm800_volt_table_ops = { + .list_voltage = regulator_list_voltage_table, + .map_voltage = regulator_map_voltage_iterate, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .get_current_limit = pm800_get_current_limit, +}; + +/* The array is indexed by id(PM800_ID_XXX) */ +static struct pm800_regulator_info pm800_regulator_info[] = { + PM800_BUCK(BUCK1, BUCK_ENA, 0, 3000000, buck1_volt_range), + PM800_BUCK(BUCK2, BUCK_ENA, 1, 1200000, buck2_5_volt_range), + PM800_BUCK(BUCK3, BUCK_ENA, 2, 1200000, buck2_5_volt_range), + PM800_BUCK(BUCK4, BUCK_ENA, 3, 1200000, buck2_5_volt_range), + PM800_BUCK(BUCK5, BUCK_ENA, 4, 1200000, buck2_5_volt_range), + + PM800_LDO(LDO1, LDO_ENA1_1, 0, 200000, ldo1_volt_table), + PM800_LDO(LDO2, LDO_ENA1_1, 1, 10000, ldo2_volt_table), + PM800_LDO(LDO3, LDO_ENA1_1, 2, 300000, ldo3_17_volt_table), + PM800_LDO(LDO4, LDO_ENA1_1, 3, 300000, ldo3_17_volt_table), + PM800_LDO(LDO5, LDO_ENA1_1, 4, 300000, ldo3_17_volt_table), + PM800_LDO(LDO6, LDO_ENA1_1, 5, 300000, ldo3_17_volt_table), + PM800_LDO(LDO7, LDO_ENA1_1, 6, 300000, ldo3_17_volt_table), + PM800_LDO(LDO8, LDO_ENA1_1, 7, 300000, ldo3_17_volt_table), + PM800_LDO(LDO9, LDO_ENA1_2, 0, 300000, ldo3_17_volt_table), + PM800_LDO(LDO10, LDO_ENA1_2, 1, 300000, ldo3_17_volt_table), + PM800_LDO(LDO11, LDO_ENA1_2, 2, 300000, ldo3_17_volt_table), + PM800_LDO(LDO12, LDO_ENA1_2, 3, 300000, ldo3_17_volt_table), + PM800_LDO(LDO13, LDO_ENA1_2, 4, 300000, ldo3_17_volt_table), + PM800_LDO(LDO14, LDO_ENA1_2, 5, 300000, ldo3_17_volt_table), + PM800_LDO(LDO15, LDO_ENA1_2, 6, 300000, ldo3_17_volt_table), + PM800_LDO(LDO16, LDO_ENA1_2, 7, 300000, ldo3_17_volt_table), + PM800_LDO(LDO17, LDO_ENA1_3, 0, 300000, ldo3_17_volt_table), + PM800_LDO(LDO18, LDO_ENA1_3, 1, 200000, ldo18_19_volt_table), + PM800_LDO(LDO19, LDO_ENA1_3, 2, 200000, ldo18_19_volt_table), +}; + +#define PM800_REGULATOR_OF_MATCH(_name, _id) \ + [PM800_ID_##_id] = { \ + .name = #_name, \ + .driver_data = &pm800_regulator_info[PM800_ID_##_id], \ + } + +static struct of_regulator_match pm800_regulator_matches[] = { + PM800_REGULATOR_OF_MATCH(buck1, BUCK1), + PM800_REGULATOR_OF_MATCH(buck2, BUCK2), + PM800_REGULATOR_OF_MATCH(buck3, BUCK3), + PM800_REGULATOR_OF_MATCH(buck4, BUCK4), + PM800_REGULATOR_OF_MATCH(buck5, BUCK5), + PM800_REGULATOR_OF_MATCH(ldo1, LDO1), + PM800_REGULATOR_OF_MATCH(ldo2, LDO2), + PM800_REGULATOR_OF_MATCH(ldo3, LDO3), + PM800_REGULATOR_OF_MATCH(ldo4, LDO4), + PM800_REGULATOR_OF_MATCH(ldo5, LDO5), + PM800_REGULATOR_OF_MATCH(ldo6, LDO6), + PM800_REGULATOR_OF_MATCH(ldo7, LDO7), + PM800_REGULATOR_OF_MATCH(ldo8, LDO8), + PM800_REGULATOR_OF_MATCH(ldo9, LDO9), + PM800_REGULATOR_OF_MATCH(ldo10, LDO10), + PM800_REGULATOR_OF_MATCH(ldo11, LDO11), + PM800_REGULATOR_OF_MATCH(ldo12, LDO12), + PM800_REGULATOR_OF_MATCH(ldo13, LDO13), + PM800_REGULATOR_OF_MATCH(ldo14, LDO14), + PM800_REGULATOR_OF_MATCH(ldo15, LDO15), + PM800_REGULATOR_OF_MATCH(ldo16, LDO16), + PM800_REGULATOR_OF_MATCH(ldo17, LDO17), + PM800_REGULATOR_OF_MATCH(ldo18, LDO18), + PM800_REGULATOR_OF_MATCH(ldo19, LDO19), +}; + +static int pm800_regulator_dt_init(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + int ret; + + ret = of_regulator_match(&pdev->dev, np, + pm800_regulator_matches, + ARRAY_SIZE(pm800_regulator_matches)); + if (ret < 0) + return ret; + + return 0; +} + +static int pm800_regulator_probe(struct platform_device *pdev) +{ + struct pm80x_chip *chip = dev_get_drvdata(pdev->dev.parent); + struct pm80x_platform_data *pdata = pdev->dev.parent->platform_data; + struct pm800_regulators *pm800_data; + struct pm800_regulator_info *info; + struct regulator_config config = { }; + struct regulator_init_data *init_data; + int i, ret; + + if (!pdata || pdata->num_regulators == 0) { + if (IS_ENABLED(CONFIG_OF)) { + ret = pm800_regulator_dt_init(pdev); + if (ret) + return ret; + } else { + return -ENODEV; + } + } else if (pdata->num_regulators) { + /* Check whether num_regulator is valid. */ + unsigned int count = 0; + for (i = 0; pdata->regulators[i]; i++) + count++; + if (count != pdata->num_regulators) + return -EINVAL; + } else { + return -EINVAL; + } + + pm800_data = devm_kzalloc(&pdev->dev, sizeof(*pm800_data), + GFP_KERNEL); + if (!pm800_data) { + dev_err(&pdev->dev, "Failed to allocate pm800_regualtors"); + return -ENOMEM; + } + + pm800_data->map = chip->subchip->regmap_power; + pm800_data->chip = chip; + + platform_set_drvdata(pdev, pm800_data); + + for (i = 0; i < PM800_ID_RG_MAX; i++) { + if (!pdata || pdata->num_regulators == 0) + init_data = pm800_regulator_matches[i].init_data; + else + init_data = pdata->regulators[i]; + if (!init_data) + continue; + info = pm800_regulator_matches[i].driver_data; + config.dev = &pdev->dev; + config.init_data = init_data; + config.driver_data = info; + config.regmap = pm800_data->map; + + pm800_data->regulators[i] = + regulator_register(&info->desc, &config); + if (IS_ERR(pm800_data->regulators[i])) { + ret = PTR_ERR(pm800_data->regulators[i]); + dev_err(&pdev->dev, "Failed to register %s\n", + info->desc.name); + + while (--i >= 0) + regulator_unregister(pm800_data->regulators[i]); + + return ret; + } + } + + return 0; +} + +static int pm800_regulator_remove(struct platform_device *pdev) +{ + struct pm800_regulators *pm800_data = platform_get_drvdata(pdev); + int i; + + for (i = 0; i < PM800_ID_RG_MAX; i++) + regulator_unregister(pm800_data->regulators[i]); + + return 0; +} + +static struct platform_driver pm800_regulator_driver = { + .driver = { + .name = "88pm80x-regulator", + .owner = THIS_MODULE, + }, + .probe = pm800_regulator_probe, + .remove = pm800_regulator_remove, +}; + +module_platform_driver(pm800_regulator_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Joseph(Yossi) Hanin "); +MODULE_DESCRIPTION("Regulator Driver for Marvell 88PM800 PMIC"); +MODULE_ALIAS("platform:88pm800-regulator"); diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 759b601b54ef..65b7d5b1bb39 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -64,6 +64,16 @@ config REGULATOR_USERSPACE_CONSUMER If unsure, say no. +config REGULATOR_88PM800 + tristate "Marvell 88PM800 Power regulators" + depends on MFD_88PM800=y + help + This driver supports Marvell 88PM800 voltage regulator chips. + It delivers digitally programmable output, + the voltage is programmed via I2C interface. + It's suitable to support PXA988 chips to control VCC_MAIN and + various voltages. + config REGULATOR_88PM8607 bool "Marvell 88PM8607 Power regulators" depends on MFD_88PM860X=y diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index d240772d90ee..e292f26a1fbd 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o +obj-$(CONFIG_REGULATOR_88PM800) += 88pm800.o obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o obj-$(CONFIG_REGULATOR_AAT2870) += aat2870-regulator.o obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o From e5e80f6dd65d27085d86c3c0eb598b4a1b49a271 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 19 Jul 2013 09:16:55 +0800 Subject: [PATCH 0218/3400] regulator: 88pm800: Add missing config.of_node setting for regulator register Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/88pm800.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/regulator/88pm800.c b/drivers/regulator/88pm800.c index a7d962f7a9b4..fc0c352c98df 100644 --- a/drivers/regulator/88pm800.c +++ b/drivers/regulator/88pm800.c @@ -331,6 +331,7 @@ static int pm800_regulator_probe(struct platform_device *pdev) config.init_data = init_data; config.driver_data = info; config.regmap = pm800_data->map; + config.of_node = pm800_regulator_matches[i].of_node; pm800_data->regulators[i] = regulator_register(&info->desc, &config); From 7c45f60b42e0f916aaf31fedf8e8afeaf585ee90 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 19 Jul 2013 09:17:53 +0800 Subject: [PATCH 0219/3400] regulator: 88pm800: Depend on MFD_88PM800 rather than MFD_88PM800=y This driver can be built as a module, make it depend on MFD_88PM800. Otherwise, we are not able to select this driver when MFD_88PM800=m. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 65b7d5b1bb39..b05fa9009e82 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -66,7 +66,7 @@ config REGULATOR_USERSPACE_CONSUMER config REGULATOR_88PM800 tristate "Marvell 88PM800 Power regulators" - depends on MFD_88PM800=y + depends on MFD_88PM800 help This driver supports Marvell 88PM800 voltage regulator chips. It delivers digitally programmable output, From 6625d9d297f28741d42a4ba712338a05f7464bd6 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 19 Jul 2013 13:06:22 +0800 Subject: [PATCH 0220/3400] regulator: 88pm800: Add missing n_voltages setting for bucks Some regulator APIs are broken if n_voltages setting is not set. e.g. regulator_count_voltages(), regulator_list_voltage(), and regulator_can_change_voltage() do not work if n_voltages setting is missing. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/88pm800.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/regulator/88pm800.c b/drivers/regulator/88pm800.c index fc0c352c98df..b4c29b1c52a5 100644 --- a/drivers/regulator/88pm800.c +++ b/drivers/regulator/88pm800.c @@ -91,8 +91,9 @@ struct pm800_regulators { * amax - the current * Buck has 2 kinds of voltage steps. It is easy to find voltage by ranges, * not the constant voltage table. + * n_volt - Number of available selectors */ -#define PM800_BUCK(vreg, ereg, ebit, amax, volt_ranges) \ +#define PM800_BUCK(vreg, ereg, ebit, amax, volt_ranges, n_volt) \ { \ .desc = { \ .name = #vreg, \ @@ -100,6 +101,7 @@ struct pm800_regulators { .type = REGULATOR_VOLTAGE, \ .id = PM800_ID_##vreg, \ .owner = THIS_MODULE, \ + .n_voltages = n_volt, \ .linear_ranges = volt_ranges, \ .n_linear_ranges = ARRAY_SIZE(volt_ranges), \ .vsel_reg = PM800_##vreg, \ @@ -204,11 +206,11 @@ static struct regulator_ops pm800_volt_table_ops = { /* The array is indexed by id(PM800_ID_XXX) */ static struct pm800_regulator_info pm800_regulator_info[] = { - PM800_BUCK(BUCK1, BUCK_ENA, 0, 3000000, buck1_volt_range), - PM800_BUCK(BUCK2, BUCK_ENA, 1, 1200000, buck2_5_volt_range), - PM800_BUCK(BUCK3, BUCK_ENA, 2, 1200000, buck2_5_volt_range), - PM800_BUCK(BUCK4, BUCK_ENA, 3, 1200000, buck2_5_volt_range), - PM800_BUCK(BUCK5, BUCK_ENA, 4, 1200000, buck2_5_volt_range), + PM800_BUCK(BUCK1, BUCK_ENA, 0, 3000000, buck1_volt_range, 0x55), + PM800_BUCK(BUCK2, BUCK_ENA, 1, 1200000, buck2_5_volt_range, 0x73), + PM800_BUCK(BUCK3, BUCK_ENA, 2, 1200000, buck2_5_volt_range, 0x73), + PM800_BUCK(BUCK4, BUCK_ENA, 3, 1200000, buck2_5_volt_range, 0x73), + PM800_BUCK(BUCK5, BUCK_ENA, 4, 1200000, buck2_5_volt_range, 0x73), PM800_LDO(LDO1, LDO_ENA1_1, 0, 200000, ldo1_volt_table), PM800_LDO(LDO2, LDO_ENA1_1, 1, 10000, ldo2_volt_table), From a1a8e1dc111d6f05e7164e851e58219d428359e1 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 16 Jul 2013 15:28:00 +0100 Subject: [PATCH 0221/3400] iio:trigger: Fix use_count race condition When using more than one trigger consumer it can happen that multiple threads perform a read-modify-update cycle on 'use_count' concurrently. This can cause updates to be lost and use_count can get stuck at non-zero value, in which case the IIO core assumes that at least one thread is still running and will wait for it to finish before running any trigger handlers again. This effectively renders the trigger disabled and a reboot is necessary before it can be used again. To fix this make use_count an atomic variable. Also set it to the number of consumers before starting the first consumer, otherwise it might happen that use_count drops to 0 even though not all consumers have been run yet. Signed-off-by: Lars-Peter Clausen Tested-by: Denis Ciocca Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-trigger.c | 34 +++++++++++++++++++----------- include/linux/iio/trigger.h | 3 ++- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c index ea8a4146620d..0dd9bb873130 100644 --- a/drivers/iio/industrialio-trigger.c +++ b/drivers/iio/industrialio-trigger.c @@ -127,12 +127,17 @@ static struct iio_trigger *iio_trigger_find_by_name(const char *name, void iio_trigger_poll(struct iio_trigger *trig, s64 time) { int i; - if (!trig->use_count) - for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++) - if (trig->subirqs[i].enabled) { - trig->use_count++; + + if (!atomic_read(&trig->use_count)) { + atomic_set(&trig->use_count, CONFIG_IIO_CONSUMERS_PER_TRIGGER); + + for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++) { + if (trig->subirqs[i].enabled) generic_handle_irq(trig->subirq_base + i); - } + else + iio_trigger_notify_done(trig); + } + } } EXPORT_SYMBOL(iio_trigger_poll); @@ -146,19 +151,24 @@ EXPORT_SYMBOL(iio_trigger_generic_data_rdy_poll); void iio_trigger_poll_chained(struct iio_trigger *trig, s64 time) { int i; - if (!trig->use_count) - for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++) - if (trig->subirqs[i].enabled) { - trig->use_count++; + + if (!atomic_read(&trig->use_count)) { + atomic_set(&trig->use_count, CONFIG_IIO_CONSUMERS_PER_TRIGGER); + + for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++) { + if (trig->subirqs[i].enabled) handle_nested_irq(trig->subirq_base + i); - } + else + iio_trigger_notify_done(trig); + } + } } EXPORT_SYMBOL(iio_trigger_poll_chained); void iio_trigger_notify_done(struct iio_trigger *trig) { - trig->use_count--; - if (trig->use_count == 0 && trig->ops && trig->ops->try_reenable) + if (atomic_dec_and_test(&trig->use_count) && trig->ops && + trig->ops->try_reenable) if (trig->ops->try_reenable(trig)) /* Missed an interrupt so launch new poll now */ iio_trigger_poll(trig, 0); diff --git a/include/linux/iio/trigger.h b/include/linux/iio/trigger.h index 3869c525b052..369cf2cd5144 100644 --- a/include/linux/iio/trigger.h +++ b/include/linux/iio/trigger.h @@ -8,6 +8,7 @@ */ #include #include +#include #ifndef _IIO_TRIGGER_H_ #define _IIO_TRIGGER_H_ @@ -61,7 +62,7 @@ struct iio_trigger { struct list_head list; struct list_head alloc_list; - int use_count; + atomic_t use_count; struct irq_chip subirq_chip; int subirq_base; From b1451e546899bc8f450773b2af02e0cd000cf1fa Mon Sep 17 00:00:00 2001 From: "Patil, Rachna" Date: Sat, 20 Jul 2013 17:27:00 +0100 Subject: [PATCH 0222/3400] iio: ti_am335x_adc: Fix wrong samples received on 1st read Previously we tried to read data form ADC even before ADC sequencer finished sampling. This led to wrong samples. We now wait on ADC status register idle bit to be set. Signed-off-by: Patil, Rachna Signed-off-by: Zubair Lutfullah Signed-off-by: Jonathan Cameron --- drivers/iio/adc/ti_am335x_adc.c | 30 ++++++++++++++++++++-------- include/linux/mfd/ti_am335x_tscadc.h | 16 +++++++++++++++ 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c index 0ad208a69c29..3ceac3e91dde 100644 --- a/drivers/iio/adc/ti_am335x_adc.c +++ b/drivers/iio/adc/ti_am335x_adc.c @@ -60,7 +60,6 @@ static void tiadc_step_config(struct tiadc_device *adc_dev) { unsigned int stepconfig; int i, steps; - u32 step_en; /* * There are 16 configurable steps and 8 analog input @@ -86,8 +85,7 @@ static void tiadc_step_config(struct tiadc_device *adc_dev) adc_dev->channel_step[i] = steps; steps++; } - step_en = get_adc_step_mask(adc_dev); - am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en); + } static const char * const chan_name_ain[] = { @@ -142,10 +140,22 @@ static int tiadc_read_raw(struct iio_dev *indio_dev, int *val, int *val2, long mask) { struct tiadc_device *adc_dev = iio_priv(indio_dev); - int i; - unsigned int fifo1count, read; + int i, map_val; + unsigned int fifo1count, read, stepid; u32 step = UINT_MAX; bool found = false; + u32 step_en; + unsigned long timeout = jiffies + usecs_to_jiffies + (IDLE_TIMEOUT * adc_dev->channels); + step_en = get_adc_step_mask(adc_dev); + am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en); + + /* Wait for ADC sequencer to complete sampling */ + while (tiadc_readl(adc_dev, REG_ADCFSM) & SEQ_STATUS) { + if (time_after(jiffies, timeout)) + return -EAGAIN; + } + map_val = chan->channel + TOTAL_CHANNELS; /* * When the sub-system is first enabled, @@ -170,12 +180,16 @@ static int tiadc_read_raw(struct iio_dev *indio_dev, fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT); for (i = 0; i < fifo1count; i++) { read = tiadc_readl(adc_dev, REG_FIFO1); - if (read >> 16 == step) { - *val = read & 0xfff; + stepid = read & FIFOREAD_CHNLID_MASK; + stepid = stepid >> 0x10; + + if (stepid == map_val) { + read = read & FIFOREAD_DATA_MASK; found = true; + *val = read; } } - am335x_tsc_se_update(adc_dev->mfd_tscadc); + if (found == false) return -EBUSY; return IIO_VAL_INT; diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h index 8d73fe29796a..db1791bb997a 100644 --- a/include/linux/mfd/ti_am335x_tscadc.h +++ b/include/linux/mfd/ti_am335x_tscadc.h @@ -113,11 +113,27 @@ #define CNTRLREG_8WIRE CNTRLREG_AFE_CTRL(3) #define CNTRLREG_TSCENB BIT(7) +/* FIFO READ Register */ +#define FIFOREAD_DATA_MASK (0xfff << 0) +#define FIFOREAD_CHNLID_MASK (0xf << 16) + +/* Sequencer Status */ +#define SEQ_STATUS BIT(5) + #define ADC_CLK 3000000 #define MAX_CLK_DIV 7 #define TOTAL_STEPS 16 #define TOTAL_CHANNELS 8 +/* +* ADC runs at 3MHz, and it takes +* 15 cycles to latch one data output. +* Hence the idle time for ADC to +* process one sample data would be +* around 5 micro seconds. +*/ +#define IDLE_TIMEOUT 5 /* microsec */ + #define TSCADC_CELLS 2 struct ti_tscadc_dev { From 87e3c8ae1c8676b9dd56b56456dafa14a4bacf97 Mon Sep 17 00:00:00 2001 From: Kirill Tkhai Date: Sun, 21 Jul 2013 04:32:07 +0400 Subject: [PATCH 0223/3400] sched/fair: Cleanup: remove duplicate variable declaration cfs_rq is declared twice, fix it. Also use 'se' instead of '&p->se'. Signed-off-by: Kirill Tkhai Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/169201374366727@web6d.yandex.ru Signed-off-by: Ingo Molnar --- kernel/sched/fair.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index bb456f44b7b1..ab599781129d 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -5889,11 +5889,9 @@ static void switched_from_fair(struct rq *rq, struct task_struct *p) * and ensure we don't carry in an old decay_count if we * switch back. */ - if (p->se.avg.decay_count) { - struct cfs_rq *cfs_rq = cfs_rq_of(&p->se); - __synchronize_entity_decay(&p->se); - subtract_blocked_load_contrib(cfs_rq, - p->se.avg.load_avg_contrib); + if (se->avg.decay_count) { + __synchronize_entity_decay(se); + subtract_blocked_load_contrib(cfs_rq, se->avg.load_avg_contrib); } #endif } From 1e40c2edef2537f87f94d0baf80aeaeb7d51cc23 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 19 Jul 2013 20:31:01 +0200 Subject: [PATCH 0224/3400] mutex: Fix/document access-once assumption in mutex_can_spin_on_owner() mutex_can_spin_on_owner() is technically broken in that it would in theory allow the compiler to load lock->owner twice, seeing a pointer first time and a NULL pointer the second time. Linus pointed out that a compiler has to be seriously broken to not compile this correctly - but nevertheless this change is correct as it will better document the implementation. Signed-off-by: Peter Zijlstra Acked-by: Davidlohr Bueso Acked-by: Waiman Long Acked-by: Linus Torvalds Acked-by: Thomas Gleixner Acked-by: Rik van Riel Cc: Paul E. McKenney Cc: David Howells Link: http://lkml.kernel.org/r/20130719183101.GA20909@twins.programming.kicks-ass.net Signed-off-by: Ingo Molnar --- kernel/mutex.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/kernel/mutex.c b/kernel/mutex.c index ff05f4bd86eb..7ff48c55a98b 100644 --- a/kernel/mutex.c +++ b/kernel/mutex.c @@ -209,11 +209,13 @@ int mutex_spin_on_owner(struct mutex *lock, struct task_struct *owner) */ static inline int mutex_can_spin_on_owner(struct mutex *lock) { + struct task_struct *owner; int retval = 1; rcu_read_lock(); - if (lock->owner) - retval = lock->owner->on_cpu; + owner = ACCESS_ONCE(lock->owner); + if (owner) + retval = owner->on_cpu; rcu_read_unlock(); /* * if lock->owner is not set, the mutex owner may have just acquired From a0842b704b0f7c2d925473676f2012ea5dc39976 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Fri, 19 Jul 2013 11:47:48 -0600 Subject: [PATCH 0225/3400] mm/hotplug, x86: Disable ARCH_MEMORY_PROBE by default CONFIG_ARCH_MEMORY_PROBE enables the /sys/devices/system/memory/probe interface, which allows a given memory address to be hot-added as follows: # echo start_address_of_new_memory > /sys/devices/system/memory/probe (See Documentation/memory-hotplug.txt for more details.) This probe interface is required on powerpc. On x86, however, ACPI notifies a memory hotplug event to the kernel, which performs its hotplug operation as the result. Therefore, regular users do not need this interface on x86. This probe interface is also error-prone and misleading that the kernel blindly adds a given memory address without checking if the memory is present on the system; no probing is done despite of its name. The kernel crashes when a user requests to online a memory block that is not present on the system. This interface is currently used for testing as it can fake a hotplug event. This patch disables CONFIG_ARCH_MEMORY_PROBE by default on x86, adds its Kconfig menu entry on x86, and clarifies its use in Documentation/ memory-hotplug.txt. Signed-off-by: Toshi Kani Acked-by: KOSAKI Motohiro Cc: linux-mm@kvack.org Cc: dave@sr71.net Cc: isimatu.yasuaki@jp.fujitsu.com Cc: tangchen@cn.fujitsu.com Cc: vasilis.liaskovitis@profitbricks.com Link: http://lkml.kernel.org/r/1374256068-26016-1-git-send-email-toshi.kani@hp.com [ Edited it slightly. ] Signed-off-by: Ingo Molnar --- Documentation/memory-hotplug.txt | 14 ++++++++------ arch/x86/Kconfig | 6 +++++- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/Documentation/memory-hotplug.txt b/Documentation/memory-hotplug.txt index 8e5eacbdcfa3..8fd254c73589 100644 --- a/Documentation/memory-hotplug.txt +++ b/Documentation/memory-hotplug.txt @@ -210,13 +210,15 @@ If memory device is found, memory hotplug code will be called. 4.2 Notify memory hot-add event by hand ------------ -In some environments, especially virtualized environment, firmware will not -notify memory hotplug event to the kernel. For such environment, "probe" -interface is supported. This interface depends on CONFIG_ARCH_MEMORY_PROBE. +On powerpc, the firmware does not notify a memory hotplug event to the kernel. +Therefore, "probe" interface is supported to notify the event to the kernel. +This interface depends on CONFIG_ARCH_MEMORY_PROBE. -Now, CONFIG_ARCH_MEMORY_PROBE is supported only by powerpc but it does not -contain highly architecture codes. Please add config if you need "probe" -interface. +CONFIG_ARCH_MEMORY_PROBE is supported on powerpc only. On x86, this config +option is disabled by default since ACPI notifies a memory hotplug event to +the kernel, which performs its hotplug operation as the result. Please +enable this option if you need the "probe" interface for testing purposes +on x86. Probe interface is located at /sys/devices/system/memory/probe diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index b32ebf92b0ce..2f9d95775d27 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1344,8 +1344,12 @@ config ARCH_SELECT_MEMORY_MODEL depends on ARCH_SPARSEMEM_ENABLE config ARCH_MEMORY_PROBE - def_bool y + bool "Enable sysfs memory/probe interface" depends on X86_64 && MEMORY_HOTPLUG + help + This option enables a sysfs memory/probe interface for testing. + See Documentation/memory-hotplug.txt for more information. + If you are unsure how to answer this question, answer N. config ARCH_PROC_KCORE_TEXT def_bool y From 796305a2e2d11748637c9d9e2ac71dfbb6af2372 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sun, 21 Jul 2013 22:29:54 -0300 Subject: [PATCH 0226/3400] spi: spi-mxs: Remove unneeded check for platform_get_resource() As devm_ioremap_resource() is used on probe, there is no need to explicitly check the return value from platform_get_resource(), as this is something that devm_ioremap_resource() takes care by itself. Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown --- drivers/spi/spi-mxs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c index 5b0a8e309197..d7b3e4311f72 100644 --- a/drivers/spi/spi-mxs.c +++ b/drivers/spi/spi-mxs.c @@ -513,7 +513,7 @@ static int mxs_spi_probe(struct platform_device *pdev) iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq_err = platform_get_irq(pdev, 0); - if (!iores || irq_err < 0) + if (irq_err < 0) return -EINVAL; base = devm_ioremap_resource(&pdev->dev, iores); From 2eaa1b407aa6592a884f1be061ef61de7012c97a Mon Sep 17 00:00:00 2001 From: David Ahern Date: Thu, 18 Jul 2013 16:06:15 -0600 Subject: [PATCH 0227/3400] perf script: Fix named threads support Commit 73994dc broke named thread support in perf-script. The thread struct in al is the main thread for a multithreaded process. The thread struct used for analysis (e.g., dumping events) should be the specific thread for the sample. Signed-off-by: David Ahern Cc: Feng Tang Link: http://lkml.kernel.org/r/1374185175-28272-1-git-send-email-dsahern@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 6 +++--- .../perf/util/scripting-engines/trace-event-perl.c | 14 ++++++++------ .../util/scripting-engines/trace-event-python.c | 9 +++++---- tools/perf/util/trace-event-scripting.c | 3 ++- tools/perf/util/trace-event.h | 4 +++- 5 files changed, 21 insertions(+), 15 deletions(-) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index ecb697998d3b..1cad37014673 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -397,10 +397,10 @@ static void print_sample_bts(union perf_event *event, static void process_event(union perf_event *event, struct perf_sample *sample, struct perf_evsel *evsel, struct machine *machine, - struct addr_location *al) + struct thread *thread, + struct addr_location *al __maybe_unused) { struct perf_event_attr *attr = &evsel->attr; - struct thread *thread = al->thread; if (output[attr->type].fields == 0) return; @@ -511,7 +511,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused, if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) return 0; - scripting_ops->process_event(event, sample, evsel, machine, &al); + scripting_ops->process_event(event, sample, evsel, machine, thread, &al); evsel->hists.stats.total_period += sample->period; return 0; diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c index eacec859f299..a85e4ae5f3ac 100644 --- a/tools/perf/util/scripting-engines/trace-event-perl.c +++ b/tools/perf/util/scripting-engines/trace-event-perl.c @@ -261,7 +261,8 @@ static void perl_process_tracepoint(union perf_event *perf_event __maybe_unused, struct perf_sample *sample, struct perf_evsel *evsel, struct machine *machine __maybe_unused, - struct addr_location *al) + struct thread *thread, + struct addr_location *al) { struct format_field *field; static char handler[256]; @@ -272,7 +273,6 @@ static void perl_process_tracepoint(union perf_event *perf_event __maybe_unused, int cpu = sample->cpu; void *data = sample->raw_data; unsigned long long nsecs = sample->time; - struct thread *thread = al->thread; char *comm = thread->comm; dSP; @@ -351,7 +351,8 @@ static void perl_process_event_generic(union perf_event *event, struct perf_sample *sample, struct perf_evsel *evsel, struct machine *machine __maybe_unused, - struct addr_location *al __maybe_unused) + struct thread *thread __maybe_unused, + struct addr_location *al __maybe_unused) { dSP; @@ -377,10 +378,11 @@ static void perl_process_event(union perf_event *event, struct perf_sample *sample, struct perf_evsel *evsel, struct machine *machine, - struct addr_location *al) + struct thread *thread, + struct addr_location *al) { - perl_process_tracepoint(event, sample, evsel, machine, al); - perl_process_event_generic(event, sample, evsel, machine, al); + perl_process_tracepoint(event, sample, evsel, machine, thread, al); + perl_process_event_generic(event, sample, evsel, machine, thread, al); } static void run_start_sub(void) diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index e87aa5d9696b..cc75a3cef388 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -225,6 +225,7 @@ static void python_process_tracepoint(union perf_event *perf_event struct perf_sample *sample, struct perf_evsel *evsel, struct machine *machine __maybe_unused, + struct thread *thread, struct addr_location *al) { PyObject *handler, *retval, *context, *t, *obj, *dict = NULL; @@ -238,7 +239,6 @@ static void python_process_tracepoint(union perf_event *perf_event int cpu = sample->cpu; void *data = sample->raw_data; unsigned long long nsecs = sample->time; - struct thread *thread = al->thread; char *comm = thread->comm; t = PyTuple_New(MAX_FIELDS); @@ -345,12 +345,12 @@ static void python_process_general_event(union perf_event *perf_event struct perf_sample *sample, struct perf_evsel *evsel, struct machine *machine __maybe_unused, + struct thread *thread, struct addr_location *al) { PyObject *handler, *retval, *t, *dict; static char handler_name[64]; unsigned n = 0; - struct thread *thread = al->thread; /* * Use the MAX_FIELDS to make the function expandable, though @@ -404,17 +404,18 @@ static void python_process_event(union perf_event *perf_event, struct perf_sample *sample, struct perf_evsel *evsel, struct machine *machine, + struct thread *thread, struct addr_location *al) { switch (evsel->attr.type) { case PERF_TYPE_TRACEPOINT: python_process_tracepoint(perf_event, sample, evsel, - machine, al); + machine, thread, al); break; /* Reserve for future process_hw/sw/raw APIs */ default: python_process_general_event(perf_event, sample, evsel, - machine, al); + machine, thread, al); } } diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c index 8715a1006d00..95199e4eea97 100644 --- a/tools/perf/util/trace-event-scripting.c +++ b/tools/perf/util/trace-event-scripting.c @@ -39,7 +39,8 @@ static void process_event_unsupported(union perf_event *event __maybe_unused, struct perf_sample *sample __maybe_unused, struct perf_evsel *evsel __maybe_unused, struct machine *machine __maybe_unused, - struct addr_location *al __maybe_unused) + struct thread *thread __maybe_unused, + struct addr_location *al __maybe_unused) { } diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h index 669a64a660d7..fafe1a40444a 100644 --- a/tools/perf/util/trace-event.h +++ b/tools/perf/util/trace-event.h @@ -9,6 +9,7 @@ struct machine; struct perf_sample; union perf_event; struct perf_tool; +struct thread; extern struct pevent *perf_pevent; @@ -68,7 +69,8 @@ struct scripting_ops { struct perf_sample *sample, struct perf_evsel *evsel, struct machine *machine, - struct addr_location *al); + struct thread *thread, + struct addr_location *al); int (*generate_script) (struct pevent *pevent, const char *outfile); }; From 2b821cce1c950cead081d779db0dda680192c4bd Mon Sep 17 00:00:00 2001 From: David Ahern Date: Thu, 18 Jul 2013 17:27:59 -0600 Subject: [PATCH 0228/3400] perf evsel: Handle ENODEV on default cycles event Some systems (e.g., VMs on qemu-0.13 with the default vcpu model) report an unsupported CPU model: Performance Events: unsupported p6 CPU model 2 no PMU driver, software events only. Subsequent invocations of perf fail with: The sys_perf_event_open() syscall returned with 19 (No such device) for event (cycles). /bin/dmesg may provide additional information. No CONFIG_PERF_EVENTS=y kernel support configured? Add ENODEV to the list of errno's to fallback to cpu-clock. Signed-off-by: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1374190079-28507-1-git-send-email-dsahern@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/evsel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index a6354619fa5d..8bed0c1a1399 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -1482,7 +1482,7 @@ out: bool perf_evsel__fallback(struct perf_evsel *evsel, int err, char *msg, size_t msgsize) { - if ((err == ENOENT || err == ENXIO) && + if ((err == ENOENT || err == ENXIO || err == ENODEV) && evsel->attr.type == PERF_TYPE_HARDWARE && evsel->attr.config == PERF_COUNT_HW_CPU_CYCLES) { /* From a198996c7afae0097c67a61851f19863e59697b2 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Thu, 18 Jul 2013 15:33:46 -0700 Subject: [PATCH 0229/3400] perf bench: Fix memcpy benchmark for large sizes The glibc calloc() function has an optimization to not explicitely memset() very large calloc allocations that just came from mmap(), because they are known to be zero. This could result in the perf memcpy benchmark reading only from the zero page, which gives unrealistic results. Always call memset explicitly on the source area to avoid this problem. Signed-off-by: Andi Kleen Cc: Hitoshi Mitake Cc: Kirill A. Shutemov Link: http://lkml.kernel.org/n/tip-pzz2qrdq9eymxda0y8yxdn33@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/bench/mem-memcpy.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/perf/bench/mem-memcpy.c b/tools/perf/bench/mem-memcpy.c index 25fd3f1966f1..8cdca43016b2 100644 --- a/tools/perf/bench/mem-memcpy.c +++ b/tools/perf/bench/mem-memcpy.c @@ -117,6 +117,8 @@ static void alloc_mem(void **dst, void **src, size_t length) *src = zalloc(length); if (!*src) die("memory allocation failed - maybe length is too large?\n"); + /* Make sure to always replace the zero pages even if MMAP_THRESH is crossed */ + memset(*src, 0, length); } static u64 do_memcpy_cycle(memcpy_t fn, size_t len, bool prefault) From 99571ab3d9b342a717295a9c7e2b4495ee19e32a Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Thu, 18 Jul 2013 15:33:57 -0700 Subject: [PATCH 0230/3400] perf tools: Support callchain sorting based on addresses With programs with very large functions it can be useful to distinguish the callgraph nodes on more than just function names. So for example if you have multiple calls to the same function, it ends up being separate nodes in the chain. This patch adds a new key field to the callgraph options, that allows comparing nodes on functions (as today, default) and addresses. Longer term it would be nice to also handle src lines, but that would need more changes and address is a reasonable proxy for it today. I right now reference the global params, as there was no simple way to register a params pointer. Signed-off-by: Andi Kleen Cc: Frederic Weisbecker Link: http://lkml.kernel.org/n/tip-0uskktybf0e7wrnoi5e9b9it@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-report.txt | 8 ++++++-- tools/perf/builtin-report.c | 19 +++++++++++++++---- tools/perf/util/callchain.c | 7 +++++-- tools/perf/util/callchain.h | 6 ++++++ tools/perf/util/hist.c | 3 ++- 5 files changed, 34 insertions(+), 9 deletions(-) diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index 747ff50284b7..2b8097ee39d8 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt @@ -115,7 +115,7 @@ OPTIONS --dump-raw-trace:: Dump raw trace in ASCII. --g [type,min[,limit],order]:: +-g [type,min[,limit],order[,key]]:: --call-graph:: Display call chains using type, min percent threshold, optional print limit and order. @@ -129,7 +129,11 @@ OPTIONS - callee: callee based call graph. - caller: inverted caller based call graph. - Default: fractal,0.5,callee. + key can be: + - function: compare on functions + - address: compare on individual code addresses + + Default: fractal,0.5,callee,function. -G:: --inverted:: diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index a34c587900c7..d785d89ed226 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -667,12 +667,23 @@ parse_callchain_opt(const struct option *opt, const char *arg, int unset) } /* get the call chain order */ - if (!strcmp(tok2, "caller")) + if (!strncmp(tok2, "caller", strlen("caller"))) callchain_param.order = ORDER_CALLER; - else if (!strcmp(tok2, "callee")) + else if (!strncmp(tok2, "callee", strlen("callee"))) callchain_param.order = ORDER_CALLEE; else return -1; + + /* Get the sort key */ + tok2 = strtok(NULL, ","); + if (!tok2) + goto setup; + if (!strncmp(tok2, "function", strlen("function"))) + callchain_param.key = CCKEY_FUNCTION; + else if (!strncmp(tok2, "address", strlen("address"))) + callchain_param.key = CCKEY_ADDRESS; + else + return -1; setup: if (callchain_register_param(&callchain_param) < 0) { fprintf(stderr, "Can't register callchain params\n"); @@ -784,8 +795,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other, "Only display entries with parent-match"), OPT_CALLBACK_DEFAULT('g', "call-graph", &report, "output_type,min_percent[,print_limit],call_order", - "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold, optional print limit and callchain order. " - "Default: fractal,0.5,callee", &parse_callchain_opt, callchain_default_opt), + "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold, optional print limit, callchain order, key (function or address). " + "Default: fractal,0.5,callee,function", &parse_callchain_opt, callchain_default_opt), OPT_BOOLEAN('G', "inverted", &report.inverted_callchain, "alias for inverted call graph"), OPT_CALLBACK(0, "ignore-callees", NULL, "regex", diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index 42b6a632fe7b..4fee33b229b0 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -15,6 +15,7 @@ #include #include +#include "hist.h" #include "util.h" #include "callchain.h" @@ -327,7 +328,8 @@ append_chain(struct callchain_node *root, /* * Lookup in the current node * If we have a symbol, then compare the start to match - * anywhere inside a function. + * anywhere inside a function, unless function + * mode is disabled. */ list_for_each_entry(cnode, &root->val, list) { struct callchain_cursor_node *node; @@ -339,7 +341,8 @@ append_chain(struct callchain_node *root, sym = node->sym; - if (cnode->ms.sym && sym) { + if (cnode->ms.sym && sym && + callchain_param.key == CCKEY_FUNCTION) { if (cnode->ms.sym->start != sym->start) break; } else if (cnode->ip != node->ip) diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index 3ee9f67d5af0..812d5a0ff2bc 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h @@ -41,12 +41,18 @@ struct callchain_param; typedef void (*sort_chain_func_t)(struct rb_root *, struct callchain_root *, u64, struct callchain_param *); +enum chain_key { + CCKEY_FUNCTION, + CCKEY_ADDRESS +}; + struct callchain_param { enum chain_mode mode; u32 print_limit; double min_percent; sort_chain_func_t sort; enum chain_order order; + enum chain_key key; }; struct callchain_list { diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index a9dd1b9d8907..46a0d35a05e1 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -24,7 +24,8 @@ enum hist_filter { struct callchain_param callchain_param = { .mode = CHAIN_GRAPH_REL, .min_percent = 0.5, - .order = ORDER_CALLEE + .order = ORDER_CALLEE, + .key = CCKEY_FUNCTION }; u16 hists__col_len(struct hists *hists, enum hist_column col) From 575bf1d04e908469d26da424b52fc1b12a1db9d8 Mon Sep 17 00:00:00 2001 From: "Kirill A. Shutemov" Date: Mon, 24 Jun 2013 11:43:14 +0300 Subject: [PATCH 0231/3400] perf tools: Fix build with perl 5.18 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit perl.h from new Perl release doesn't like -Wundef and -Wswitch-default: /usr/lib/perl5/core_perl/CORE/perl.h:548:5: error: "SILENT_NO_TAINT_SUPPORT" is not defined [-Werror=undef] #if SILENT_NO_TAINT_SUPPORT && !defined(NO_TAINT_SUPPORT) ^ /usr/lib/perl5/core_perl/CORE/perl.h:556:5: error: "NO_TAINT_SUPPORT" is not defined [-Werror=undef] #if NO_TAINT_SUPPORT ^ In file included from /usr/lib/perl5/core_perl/CORE/perl.h:3471:0, from util/scripting-engines/trace-event-perl.c:30: /usr/lib/perl5/core_perl/CORE/sv.h:1455:5: error: "NO_TAINT_SUPPORT" is not defined [-Werror=undef] #if NO_TAINT_SUPPORT ^ In file included from /usr/lib/perl5/core_perl/CORE/perl.h:3472:0, from util/scripting-engines/trace-event-perl.c:30: /usr/lib/perl5/core_perl/CORE/regexp.h:436:5: error: "NO_TAINT_SUPPORT" is not defined [-Werror=undef] #if NO_TAINT_SUPPORT ^ In file included from /usr/lib/perl5/core_perl/CORE/hv.h:592:0, from /usr/lib/perl5/core_perl/CORE/perl.h:3480, from util/scripting-engines/trace-event-perl.c:30: /usr/lib/perl5/core_perl/CORE/hv_func.h: In function ‘S_perl_hash_siphash_2_4’: /usr/lib/perl5/core_perl/CORE/hv_func.h:222:3: error: switch missing default case [-Werror=switch-default] switch( left ) ^ /usr/lib/perl5/core_perl/CORE/hv_func.h: In function ‘S_perl_hash_superfast’: /usr/lib/perl5/core_perl/CORE/hv_func.h:274:5: error: switch missing default case [-Werror=switch-default] switch (rem) { \ ^ /usr/lib/perl5/core_perl/CORE/hv_func.h: In function ‘S_perl_hash_murmur3’: /usr/lib/perl5/core_perl/CORE/hv_func.h:398:5: error: switch missing default case [-Werror=switch-default] switch(bytes_in_carry) { /* how many bytes in carry */ ^ Let's disable the warnings for code which uses perl.h. Signed-off-by: Kirill A. Shutemov Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1372063394-20126-1-git-send-email-kirill@shutemov.name Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 2a6902677141..024680b23ddc 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -631,10 +631,10 @@ $(OUTPUT)util/parse-events.o: util/parse-events.c $(OUTPUT)PERF-CFLAGS $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-redundant-decls $< $(OUTPUT)util/scripting-engines/trace-event-perl.o: util/scripting-engines/trace-event-perl.c $(OUTPUT)PERF-CFLAGS - $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $< + $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow -Wno-undef -Wno-switch-default $< $(OUTPUT)scripts/perl/Perf-Trace-Util/Context.o: scripts/perl/Perf-Trace-Util/Context.c $(OUTPUT)PERF-CFLAGS - $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs $< + $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs -Wno-undef -Wno-switch-default $< $(OUTPUT)util/scripting-engines/trace-event-python.o: util/scripting-engines/trace-event-python.c $(OUTPUT)PERF-CFLAGS $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $< From 0659e66981ab137c11a746899672c886e1973a7b Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 22 Jul 2013 14:43:30 +0200 Subject: [PATCH 0232/3400] perf tests: Run ctags/cscope make tests only with needed binaries Running tags and cscope make tests only if the 'ctags' and 'cscope' binaries are installed, so we don't have false alarm test failures. Signed-off-by: Jiri Olsa Cc: Borislav Petkov Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1374497014-2817-2-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/make | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tools/perf/tests/make b/tools/perf/tests/make index c441a2875128..d1efef9c7576 100644 --- a/tools/perf/tests/make +++ b/tools/perf/tests/make @@ -1,6 +1,8 @@ PERF := . MK := Makefile +has = $(shell which $1 2>/dev/null) + # standard single make variable specified make_clean_all := clean all make_python_perf_so := python/perf.so @@ -50,14 +52,19 @@ run += make_no_backtrace run += make_no_libnuma run += make_no_libaudit run += make_no_libbionic -run += make_tags -run += make_cscope run += make_help run += make_doc run += make_perf_o run += make_util_map_o run += make_minimal +ifneq ($(call has,ctags),) +run += make_tags +endif +ifneq ($(call has,cscope),) +run += make_cscope +endif + # $(run_O) contains same portion of $(run) tests with '_O' attached # to distinguish O=... tests run_O := $(addsuffix _O,$(run)) From 8ba7cdea321d4d5bb53ac210f4e0a4bca5b0dba5 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 22 Jul 2013 14:43:31 +0200 Subject: [PATCH 0233/3400] perf tests: Rename TMP to TMP_O tests/make variable Renaming TMP to TMP_O tests/make variable to make a name space for other temp variables. Signed-off-by: Jiri Olsa Cc: Borislav Petkov Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1374497014-2817-3-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/make | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/perf/tests/make b/tools/perf/tests/make index d1efef9c7576..dbbb62c0d0f3 100644 --- a/tools/perf/tests/make +++ b/tools/perf/tests/make @@ -102,7 +102,7 @@ test_make_util_map_o_O := true test_default = test -x $(PERF)/perf test = $(if $(test_$1),$(test_$1),$(test_default)) -test_default_O = test -x $$TMP/perf +test_default_O = test -x $$TMP_O/perf test_O = $(if $(test_$1),$(test_$1),$(test_default_O)) all: @@ -127,14 +127,14 @@ $(run): $(run_O): $(call clean) - @TMP=$$(mktemp -d); \ - cmd="cd $(PERF) && make -f $(MK) $($(patsubst %_O,%,$@)) O=$$TMP"; \ + @TMP_O=$$(mktemp -d); \ + cmd="cd $(PERF) && make -f $(MK) $($(patsubst %_O,%,$@)) O=$$TMP_O"; \ echo "- $@: $$cmd" && echo $$cmd > $@ && \ ( eval $$cmd ) >> $@ 2>&1 && \ echo " test: $(call test_O,$@)"; \ $(call test_O,$@) && \ rm -f $@ && \ - rm -rf $$TMP + rm -rf $$TMP_O all: $(run) $(run_O) @echo OK From c9311674e73345d4d02595c80d43f4bcf9ff3a3f Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 22 Jul 2013 14:43:32 +0200 Subject: [PATCH 0234/3400] perf tests: Add DESTDIR=TMP_DEST tests/make variable Adding TMP_DEST tests/make variable to provide the DESTDIR directory for installation tests. Adding this to existing test targets, since DESTDIR variable 'should not' affect other than install* targets. We can always separate this if there's a need for DESTDIR-free build test. Signed-off-by: Jiri Olsa Cc: Borislav Petkov Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1374497014-2817-4-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/make | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tools/perf/tests/make b/tools/perf/tests/make index dbbb62c0d0f3..7646a0076356 100644 --- a/tools/perf/tests/make +++ b/tools/perf/tests/make @@ -118,23 +118,27 @@ clean := @(cd $(PERF); make -s -f $(MK) clean >/dev/null) $(run): $(call clean) - @cmd="cd $(PERF) && make -f $(MK) $($@)"; \ + @TMP_DEST=$$(mktemp -d); \ + cmd="cd $(PERF) && make -f $(MK) DESTDIR=$$TMP_DEST $($@)"; \ echo "- $@: $$cmd" && echo $$cmd > $@ && \ ( eval $$cmd ) >> $@ 2>&1; \ echo " test: $(call test,$@)"; \ $(call test,$@) && \ - rm -f $@ + rm -f $@ \ + rm -rf $$TMP_DEST $(run_O): $(call clean) @TMP_O=$$(mktemp -d); \ - cmd="cd $(PERF) && make -f $(MK) $($(patsubst %_O,%,$@)) O=$$TMP_O"; \ + TMP_DEST=$$(mktemp -d); \ + cmd="cd $(PERF) && make -f $(MK) O=$$TMP_O DESTDIR=$$TMP_DEST $($(patsubst %_O,%,$@))"; \ echo "- $@: $$cmd" && echo $$cmd > $@ && \ ( eval $$cmd ) >> $@ 2>&1 && \ echo " test: $(call test_O,$@)"; \ $(call test_O,$@) && \ rm -f $@ && \ - rm -rf $$TMP_O + rm -rf $$TMP_O \ + rm -rf $$TMP_DEST all: $(run) $(run_O) @echo OK From c0ec11088800e1a5efbccc291a42580727798123 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 22 Jul 2013 14:43:33 +0200 Subject: [PATCH 0235/3400] perf tests: Add 'make install/install-bin' tests into tests/make Adding 'make install' and 'make install-bin' tests into tests/make. It's run as part of the suite, but could be run separately like: $ make -f tests/make make_install - make_install: cd . && make -f Makefile DESTDIR=/tmp/tmp.LpkYbk5pfs install test: test -x /tmp/tmp.LpkYbk5pfs/bin/perf $ make -f tests/make make_install_bin - make_install_bin: cd . && make -f Makefile DESTDIR=/tmp/tmp.dMxePBMcFT install-bin test: test -x /tmp/tmp.dMxePBMcFT/bin/perf Signed-off-by: Jiri Olsa Cc: Borislav Petkov Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1374497014-2817-5-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/make | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tools/perf/tests/make b/tools/perf/tests/make index 7646a0076356..d3819f210876 100644 --- a/tools/perf/tests/make +++ b/tools/perf/tests/make @@ -27,6 +27,8 @@ make_help := help make_doc := doc make_perf_o := perf.o make_util_map_o := util/map.o +make_install := install +make_install_bin := install-bin # all the NO_* variable combined make_minimal := NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1 @@ -56,6 +58,8 @@ run += make_help run += make_doc run += make_perf_o run += make_util_map_o +run += make_install +run += make_install_bin run += make_minimal ifneq ($(call has,ctags),) @@ -91,6 +95,11 @@ test_make_python_perf_so := test -f $(PERF)/python/perf.so test_make_perf_o := test -f $(PERF)/perf.o test_make_util_map_o := test -f $(PERF)/util/map.o +test_make_install := test -x $$TMP_DEST/bin/perf +test_make_install_O := $(test_make_install) +test_make_install_bin := $(test_make_install) +test_make_install_bin_O := $(test_make_install) + # Kbuild tests only #test_make_python_perf_so_O := test -f $$TMP/tools/perf/python/perf.so #test_make_perf_o_O := test -f $$TMP/tools/perf/perf.o From dbad41893c7941f3c53805f8206993719f971bfa Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 22 Jul 2013 14:43:34 +0200 Subject: [PATCH 0236/3400] perf tests: Add broken install-* tests into tests/make Adding install-* tests into tests/make. Those tests are broken, so commenting them out right away. * Nothing get installed for install-man, install_doc and install_html targets, they just rebuild the documentation. * I've got following error for 'install-info': $ make -f tests/make make_install_info - make_install_info: cd . && make -f Makefile DESTDIR=/tmp/tmp.Xi4mb9J1a0 install-info $ tail -f make_install_info ... PERF_VERSION = 3.11.rc1.g9b3c2d make[2]: *** No rule to make target `user-manual.xml', needed by `user-manual.texi'. Stop. make[1]: *** [install-info] Error 2 * I've got following error for 'install-pdf': $ make -f tests/make make_install_pdf - make_install_pdf: cd . && make -f Makefile DESTDIR=/tmp/tmp.fXseECBbt1 install-pdf $ tail -f make_install_pdf ... PERF_VERSION = 3.11.rc1.g9b3c2d make[2]: *** No rule to make target `user-manual.xml', needed by `user-manual.pdf'. Stop. make[1]: *** [install-pdf] Error 2 Signed-off-by: Jiri Olsa Cc: Borislav Petkov Cc: Corey Ashford Cc: David Ahern Cc: Frederic Weisbecker Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1374497014-2817-6-git-send-email-jolsa@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/make | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tools/perf/tests/make b/tools/perf/tests/make index d3819f210876..2ca0abf1b2b6 100644 --- a/tools/perf/tests/make +++ b/tools/perf/tests/make @@ -29,6 +29,11 @@ make_perf_o := perf.o make_util_map_o := util/map.o make_install := install make_install_bin := install-bin +make_install_doc := install-doc +make_install_man := install-man +make_install_html := install-html +make_install_info := install-info +make_install_pdf := install-pdf # all the NO_* variable combined make_minimal := NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1 @@ -60,6 +65,12 @@ run += make_perf_o run += make_util_map_o run += make_install run += make_install_bin +# FIXME 'install-*' commented out till they're fixed +# run += make_install_doc +# run += make_install_man +# run += make_install_html +# run += make_install_info +# run += make_install_pdf run += make_minimal ifneq ($(call has,ctags),) @@ -100,6 +111,26 @@ test_make_install_O := $(test_make_install) test_make_install_bin := $(test_make_install) test_make_install_bin_O := $(test_make_install) +# FIXME nothing gets installed +test_make_install_man := test -f $$TMP_DEST/share/man/man1/perf.1 +test_make_install_man_O := $(test_make_install_man) + +# FIXME nothing gets installed +test_make_install_doc := $(test_ok) +test_make_install_doc_O := $(test_ok) + +# FIXME nothing gets installed +test_make_install_html := $(test_ok) +test_make_install_html_O := $(test_ok) + +# FIXME nothing gets installed +test_make_install_info := $(test_ok) +test_make_install_info_O := $(test_ok) + +# FIXME nothing gets installed +test_make_install_pdf := $(test_ok) +test_make_install_pdf_O := $(test_ok) + # Kbuild tests only #test_make_python_perf_so_O := test -f $$TMP/tools/perf/python/perf.so #test_make_perf_o_O := test -f $$TMP/tools/perf/perf.o From f9ea55d0ddf66ed030b2a478625cd5792d30df16 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Thu, 18 Jul 2013 15:58:53 -0700 Subject: [PATCH 0237/3400] perf tools: Move weight back to common sort keys This is a partial revert of Namhyung's patch afab87b91f3f331d55664172dad8e476e6ffca9d perf sort: Separate out memory-specific sort keys He wrote For global/local weights, I'm not entirely sure to place them into the memory dimension. But it's the only user at this time. Well TSX is another (in fact the original) user of the flags, and it needs them to be common. So move local/global weight back to the common sort keys. Signed-off-by: Andi Kleen Cc: Jiri Olsa Cc: Namhyung Kim Link: http://lkml.kernel.org/r/1374188333-17899-1-git-send-email-andi@firstfloor.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/sort.c | 4 ++-- tools/perf/util/sort.h | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index cb2b108635ee..5f118a089519 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -874,6 +874,8 @@ static struct sort_dimension common_sort_dimensions[] = { DIM(SORT_PARENT, "parent", sort_parent), DIM(SORT_CPU, "cpu", sort_cpu), DIM(SORT_SRCLINE, "srcline", sort_srcline), + DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight), + DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight), }; #undef DIM @@ -893,8 +895,6 @@ static struct sort_dimension bstack_sort_dimensions[] = { #define DIM(d, n, func) [d - __SORT_MEMORY_MODE] = { .name = n, .entry = &(func) } static struct sort_dimension memory_sort_dimensions[] = { - DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight), - DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight), DIM(SORT_MEM_DADDR_SYMBOL, "symbol_daddr", sort_mem_daddr_sym), DIM(SORT_MEM_DADDR_DSO, "dso_daddr", sort_mem_daddr_dso), DIM(SORT_MEM_LOCKED, "locked", sort_mem_locked), diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index 586022dc3264..4e80dbd271e7 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h @@ -143,6 +143,8 @@ enum sort_type { SORT_PARENT, SORT_CPU, SORT_SRCLINE, + SORT_LOCAL_WEIGHT, + SORT_GLOBAL_WEIGHT, /* branch stack specific sort keys */ __SORT_BRANCH_STACK, @@ -154,9 +156,7 @@ enum sort_type { /* memory mode specific sort keys */ __SORT_MEMORY_MODE, - SORT_LOCAL_WEIGHT = __SORT_MEMORY_MODE, - SORT_GLOBAL_WEIGHT, - SORT_MEM_DADDR_SYMBOL, + SORT_MEM_DADDR_SYMBOL = __SORT_MEMORY_MODE, SORT_MEM_DADDR_DSO, SORT_MEM_LOCKED, SORT_MEM_TLB, From a7d5caf6d21814a855422df75c2d8c093cb2019a Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Wed, 17 Jul 2013 09:48:15 +0800 Subject: [PATCH 0238/3400] ACPICA: Update comments about behavior when _STA does not exist No functional change. Add some comments concerning behavior when the _STA method does not exist. According to the ACPI specification, in this case the device should be assumed to be present, functional, and enabled. Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Acked-by: Len Brown Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/nsxfname.c | 7 ++++++- drivers/acpi/acpica/uteval.c | 8 +++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/acpica/nsxfname.c b/drivers/acpi/acpica/nsxfname.c index f3a4d95899f7..21a2ef363ad4 100644 --- a/drivers/acpi/acpica/nsxfname.c +++ b/drivers/acpi/acpica/nsxfname.c @@ -379,9 +379,14 @@ acpi_get_object_info(acpi_handle handle, * Get extra info for ACPI Device/Processor objects only: * Run the _STA, _ADR and, sx_w, and _sx_d methods. * - * Note: none of these methods are required, so they may or may + * Notes: none of these methods are required, so they may or may * not be present for this device. The Info->Valid bitfield is used * to indicate which methods were found and run successfully. + * + * For _STA, if the method does not exist, then (as per the ACPI + * specification), the returned current_status flags will indicate + * that the device is present/functional/enabled. Otherwise, the + * current_status flags reflect the value returned from _STA. */ /* Execute the Device._STA method */ diff --git a/drivers/acpi/acpica/uteval.c b/drivers/acpi/acpica/uteval.c index ee83adb97b1e..4fd68971019b 100644 --- a/drivers/acpi/acpica/uteval.c +++ b/drivers/acpi/acpica/uteval.c @@ -239,7 +239,8 @@ acpi_ut_evaluate_numeric_object(char *object_name, * RETURN: Status * * DESCRIPTION: Executes _STA for selected device and stores results in - * *Flags. + * *Flags. If _STA does not exist, then the device is assumed + * to be present/functional/enabled (as per the ACPI spec). * * NOTE: Internal function, no parameter validation * @@ -257,6 +258,11 @@ acpi_ut_execute_STA(struct acpi_namespace_node *device_node, u32 * flags) ACPI_BTYPE_INTEGER, &obj_desc); if (ACPI_FAILURE(status)) { if (AE_NOT_FOUND == status) { + /* + * if _STA does not exist, then (as per the ACPI specification), + * the returned flags will indicate that the device is present, + * functional, and enabled. + */ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "_STA on %4.4s was not found, assuming device is present\n", acpi_ut_get_node_name(device_node))); From 57987ca2b7c3b16aeeaeacb69b52372181cb7c58 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Wed, 17 Jul 2013 09:48:27 +0800 Subject: [PATCH 0239/3400] ACPICA: TableManager: Export acpi_tb_scan_memory_for_rsdp() This patch exports this function to be used by other ACPICA utilities. Chao Guan, Bob Moore. Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Acked-by: Len Brown Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/actables.h | 5 +++++ drivers/acpi/acpica/tbxfroot.c | 4 +--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/acpi/acpica/actables.h b/drivers/acpi/acpica/actables.h index 7755e915a007..917315ec21dd 100644 --- a/drivers/acpi/acpica/actables.h +++ b/drivers/acpi/acpica/actables.h @@ -46,6 +46,11 @@ acpi_status acpi_allocate_root_table(u32 initial_table_count); +/* + * tbxfroot - Root pointer utilities + */ +u8 *acpi_tb_scan_memory_for_rsdp(u8 *start_address, u32 length); + /* * tbfadt - FADT parse/convert/validate */ diff --git a/drivers/acpi/acpica/tbxfroot.c b/drivers/acpi/acpica/tbxfroot.c index 7c2ecfb7c2c3..e76ed0f07826 100644 --- a/drivers/acpi/acpica/tbxfroot.c +++ b/drivers/acpi/acpica/tbxfroot.c @@ -49,8 +49,6 @@ ACPI_MODULE_NAME("tbxfroot") /* Local prototypes */ -static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length); - static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp); /******************************************************************************* @@ -231,7 +229,7 @@ acpi_status acpi_find_root_pointer(acpi_size *table_address) * DESCRIPTION: Search a block of memory for the RSDP signature * ******************************************************************************/ -static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length) +u8 *acpi_tb_scan_memory_for_rsdp(u8 *start_address, u32 length) { acpi_status status; u8 *mem_rover; From 0fb3adf8099160c0a1b1952b6ccf7ac05c218d38 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Wed, 17 Jul 2013 09:48:40 +0800 Subject: [PATCH 0240/3400] ACPICA: Disassembler: Expand maximum output string length to 64K Was 256 bytes max. The original purpose of this constraint was to limit the amount of debug output. However, the string function in question (UtPrintString) is now used for the disassembler also, where 256 bytes is insufficient. Reported by RehabMan@GitHub. Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Acked-by: Len Brown Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acutils.h | 2 +- drivers/acpi/acpica/utstring.c | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h index 3c76edea6803..4c081c436089 100644 --- a/drivers/acpi/acpica/acutils.h +++ b/drivers/acpi/acpica/acutils.h @@ -616,7 +616,7 @@ int acpi_ut_stricmp(char *string1, char *string2); acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer); -void acpi_ut_print_string(char *string, u8 max_length); +void acpi_ut_print_string(char *string, u16 max_length); void ut_convert_backslashes(char *pathname); diff --git a/drivers/acpi/acpica/utstring.c b/drivers/acpi/acpica/utstring.c index c53759b76a3f..cb1e9cc32d5f 100644 --- a/drivers/acpi/acpica/utstring.c +++ b/drivers/acpi/acpica/utstring.c @@ -333,7 +333,8 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer) * FUNCTION: acpi_ut_print_string * * PARAMETERS: string - Null terminated ASCII string - * max_length - Maximum output length + * max_length - Maximum output length. Used to constrain the + * length of strings during debug output only. * * RETURN: None * @@ -342,7 +343,7 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer) * ******************************************************************************/ -void acpi_ut_print_string(char *string, u8 max_length) +void acpi_ut_print_string(char *string, u16 max_length) { u32 i; From 2c48e3eacb0998dc483860e63da47909313c314e Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Wed, 17 Jul 2013 09:48:50 +0800 Subject: [PATCH 0241/3400] ACPICA: Remove restriction of 256 maximum GPEs in any GPE block The FADT can support over 1000 GPEs, so remove any restriction on the GPE numbers. Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Acked-by: Len Brown Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/evgpeinit.c | 11 ----------- include/acpi/actypes.h | 7 ------- 2 files changed, 18 deletions(-) diff --git a/drivers/acpi/acpica/evgpeinit.c b/drivers/acpi/acpica/evgpeinit.c index 9037f17c9608..7842700346a4 100644 --- a/drivers/acpi/acpica/evgpeinit.c +++ b/drivers/acpi/acpica/evgpeinit.c @@ -125,7 +125,6 @@ acpi_status acpi_ev_gpe_initialize(void) /* GPE block 0 exists (has both length and address > 0) */ register_count0 = (u16)(acpi_gbl_FADT.gpe0_block_length / 2); - gpe_number_max = (register_count0 * ACPI_GPE_REGISTER_WIDTH) - 1; @@ -204,16 +203,6 @@ acpi_status acpi_ev_gpe_initialize(void) goto cleanup; } - /* Check for Max GPE number out-of-range */ - - if (gpe_number_max > ACPI_GPE_MAX) { - ACPI_ERROR((AE_INFO, - "Maximum GPE number from FADT is too large: 0x%X", - gpe_number_max)); - status = AE_BAD_VALUE; - goto cleanup; - } - cleanup: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return_ACPI_STATUS(AE_OK); diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 22b03c9286e9..787a977ece9d 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -668,13 +668,6 @@ typedef u32 acpi_event_status; #define ACPI_EVENT_FLAG_SET (acpi_event_status) 0x04 #define ACPI_EVENT_FLAG_HANDLE (acpi_event_status) 0x08 -/* - * General Purpose Events (GPE) - */ -#define ACPI_GPE_INVALID 0xFF -#define ACPI_GPE_MAX 0xFF -#define ACPI_NUM_GPE 256 - /* Actions for acpi_set_gpe, acpi_gpe_wakeup, acpi_hw_low_set_gpe */ #define ACPI_GPE_ENABLE 0 From bbe707eddca7f5d03613f38ad8d6b0253a47f5a8 Mon Sep 17 00:00:00 2001 From: Jung-uk Kim Date: Wed, 17 Jul 2013 09:48:58 +0800 Subject: [PATCH 0242/3400] ACPICA: Fix compiler warnings for casting issues (only some compilers) Fixes compiler warnings from GCC 4.2 and perhaps other compilers. Jung-uk Kim Signed-off-by: Jung-uk Kim Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Acked-by: Len Brown Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/exdump.c | 6 +++--- drivers/acpi/acpica/nsxfname.c | 4 +++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/acpica/exdump.c b/drivers/acpi/acpica/exdump.c index c740f24e3101..4d046faac48c 100644 --- a/drivers/acpi/acpica/exdump.c +++ b/drivers/acpi/acpica/exdump.c @@ -338,6 +338,7 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc, { u8 *target; char *name; + const char *reference_name; u8 count; if (!info) { @@ -426,10 +427,9 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc, case ACPI_EXD_REFERENCE: + reference_name = acpi_ut_get_reference_name(obj_desc); acpi_ex_out_string("Class Name", - ACPI_CAST_PTR(char, - acpi_ut_get_reference_name - (obj_desc))); + ACPI_CAST_PTR(char, reference_name)); acpi_ex_dump_reference_obj(obj_desc); break; diff --git a/drivers/acpi/acpica/nsxfname.c b/drivers/acpi/acpica/nsxfname.c index 21a2ef363ad4..83c164434580 100644 --- a/drivers/acpi/acpica/nsxfname.c +++ b/drivers/acpi/acpica/nsxfname.c @@ -158,6 +158,7 @@ acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer) { acpi_status status; struct acpi_namespace_node *node; + char *node_name; /* Parameter validation */ @@ -202,7 +203,8 @@ acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer) /* Just copy the ACPI name from the Node and zero terminate it */ - ACPI_MOVE_NAME(buffer->pointer, acpi_ut_get_node_name(node)); + node_name = acpi_ut_get_node_name(node); + ACPI_MOVE_NAME(buffer->pointer, node_name); ((char *)buffer->pointer)[ACPI_NAME_SIZE] = 0; status = AE_OK; From 53b1631e3a274f84686853fa2531d1aa918ee36c Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Wed, 17 Jul 2013 09:49:08 +0800 Subject: [PATCH 0243/3400] ACPICA: Update version to 20130626 Version 20130626. Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Acked-by: Len Brown Signed-off-by: Rafael J. Wysocki --- include/acpi/acpixf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 22d497ee6ef9..292af0c0b896 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -46,7 +46,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20130517 +#define ACPI_CA_VERSION 0x20130626 #include #include From 53c035204253efe373d9ff166fae6147e8c693b6 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Wed, 17 Jul 2013 12:46:53 +0300 Subject: [PATCH 0244/3400] sched_clock: Fix integer overflow The expression '(1 << 32)' happens to evaluate as 0 on ARM, but it evaluates as 1 on xtensa and x86_64. This zeros sched_clock_mask, and breaks sched_clock(). Set the type of 1 to 'unsigned long long' to get the value we need. Reported-by: Max Filippov Tested-by: Max Filippov Acked-by: Russell King Signed-off-by: Baruch Siach Signed-off-by: John Stultz --- kernel/time/sched_clock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/time/sched_clock.c b/kernel/time/sched_clock.c index a326f27d7f09..0b479a6a22bb 100644 --- a/kernel/time/sched_clock.c +++ b/kernel/time/sched_clock.c @@ -121,7 +121,7 @@ void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate) BUG_ON(bits > 32); WARN_ON(!irqs_disabled()); read_sched_clock = read; - sched_clock_mask = (1 << bits) - 1; + sched_clock_mask = (1ULL << bits) - 1; cd.rate = rate; /* calculate the mult/shift to convert counter ticks to ns. */ From c70d65052a1c792bae8d1bb84845f15526b74997 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Wed, 3 Jul 2013 17:04:48 +0300 Subject: [PATCH 0245/3400] x86 / PCI: prevent re-allocation of already existing bridge and ROM resources In hotplug case (especially with Thunderbolt enabled systems) we might need to call pcibios_resource_survey_bus() several times for a bus. The function ends up calling pci_claim_resource() for each bridge resource that then fails claiming that the resource exists already (which it does). Once this happens the resource is invalidated thus preventing devices behind the bridge to allocate their resources. To fix this we do what has been done in pcibios_allocate_dev_resources() and check 'parent' of the given resource. If it is non-NULL it means that the resource has been allocated already and we can skip it. We do the same for ROM resources as well. Signed-off-by: Mika Westerberg Acked-by: Bjorn Helgaas Signed-off-by: Rafael J. Wysocki --- arch/x86/pci/i386.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c index 94919e307f8e..db6b1ab43255 100644 --- a/arch/x86/pci/i386.c +++ b/arch/x86/pci/i386.c @@ -210,6 +210,8 @@ static void pcibios_allocate_bridge_resources(struct pci_dev *dev) r = &dev->resource[idx]; if (!r->flags) continue; + if (r->parent) /* Already allocated */ + continue; if (!r->start || pci_claim_resource(dev, idx) < 0) { /* * Something is wrong with the region. @@ -318,6 +320,8 @@ static void pcibios_allocate_dev_rom_resource(struct pci_dev *dev) r = &dev->resource[PCI_ROM_RESOURCE]; if (!r->flags || !r->start) return; + if (r->parent) /* Already allocated */ + return; if (pci_claim_resource(dev, PCI_ROM_RESOURCE) < 0) { r->end -= r->start; From be1c9de98d8904c75a5ab8b2a0d97bea0f7c07cc Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 13 Jul 2013 23:27:23 +0200 Subject: [PATCH 0246/3400] ACPI / PCI: Make bus registration and unregistration symmetric Since acpi_pci_slot_enumerate() and acpiphp_enumerate_slots() can get the ACPI device handle they need from bus->bridge, it is not necessary to pass that handle to them as an argument. Drop the second argument of acpi_pci_slot_enumerate() and acpiphp_enumerate_slots(), rework them to obtain the ACPI handle from bus->bridge and make acpi_pci_add_bus() and acpi_pci_remove_bus() entirely symmetrical. Tested-by: Mika Westerberg Signed-off-by: Rafael J. Wysocki Acked-by: Yinghai Lu --- drivers/acpi/pci_slot.c | 14 +++++++++----- drivers/pci/hotplug/acpiphp_glue.c | 6 ++++-- drivers/pci/pci-acpi.c | 16 ++++------------ include/linux/pci-acpi.h | 10 ++++------ 4 files changed, 21 insertions(+), 25 deletions(-) diff --git a/drivers/acpi/pci_slot.c b/drivers/acpi/pci_slot.c index 033d1179bdb5..d678a180ca2a 100644 --- a/drivers/acpi/pci_slot.c +++ b/drivers/acpi/pci_slot.c @@ -159,12 +159,16 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) return AE_OK; } -void acpi_pci_slot_enumerate(struct pci_bus *bus, acpi_handle handle) +void acpi_pci_slot_enumerate(struct pci_bus *bus) { - mutex_lock(&slot_list_lock); - acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, - register_slot, NULL, bus, NULL); - mutex_unlock(&slot_list_lock); + acpi_handle handle = ACPI_HANDLE(bus->bridge); + + if (handle) { + mutex_lock(&slot_list_lock); + acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, + register_slot, NULL, bus, NULL); + mutex_unlock(&slot_list_lock); + } } void acpi_pci_slot_remove(struct pci_bus *bus) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 8bfad0dc29ab..a203ba529fef 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -1147,14 +1147,16 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type, * Create hotplug slots for the PCI bus. * It should always return 0 to avoid skipping following notifiers. */ -void acpiphp_enumerate_slots(struct pci_bus *bus, acpi_handle handle) +void acpiphp_enumerate_slots(struct pci_bus *bus) { + acpi_handle handle; struct acpiphp_bridge *bridge; if (acpiphp_disabled) return; - if (detect_ejectable_slots(handle) <= 0) + handle = ACPI_HANDLE(bus->bridge); + if (!handle || detect_ejectable_slots(handle) <= 0) return; bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index dbdc5f7e2b29..c78cc432edab 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -290,24 +290,16 @@ static struct pci_platform_pm_ops acpi_pci_platform_pm = { void acpi_pci_add_bus(struct pci_bus *bus) { - acpi_handle handle = NULL; - - if (bus->bridge) - handle = ACPI_HANDLE(bus->bridge); - if (acpi_pci_disabled || handle == NULL) + if (acpi_pci_disabled || !bus->bridge) return; - acpi_pci_slot_enumerate(bus, handle); - acpiphp_enumerate_slots(bus, handle); + acpi_pci_slot_enumerate(bus); + acpiphp_enumerate_slots(bus); } void acpi_pci_remove_bus(struct pci_bus *bus) { - /* - * bus->bridge->acpi_node.handle has already been reset to NULL - * when acpi_pci_remove_bus() is called, so don't check ACPI handle. - */ - if (acpi_pci_disabled) + if (acpi_pci_disabled || !bus->bridge) return; acpiphp_remove_slots(bus); diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h index 170447977278..d006f0ca60f4 100644 --- a/include/linux/pci-acpi.h +++ b/include/linux/pci-acpi.h @@ -47,24 +47,22 @@ void acpi_pci_remove_bus(struct pci_bus *bus); #ifdef CONFIG_ACPI_PCI_SLOT void acpi_pci_slot_init(void); -void acpi_pci_slot_enumerate(struct pci_bus *bus, acpi_handle handle); +void acpi_pci_slot_enumerate(struct pci_bus *bus); void acpi_pci_slot_remove(struct pci_bus *bus); #else static inline void acpi_pci_slot_init(void) { } -static inline void acpi_pci_slot_enumerate(struct pci_bus *bus, - acpi_handle handle) { } +static inline void acpi_pci_slot_enumerate(struct pci_bus *bus) { } static inline void acpi_pci_slot_remove(struct pci_bus *bus) { } #endif #ifdef CONFIG_HOTPLUG_PCI_ACPI void acpiphp_init(void); -void acpiphp_enumerate_slots(struct pci_bus *bus, acpi_handle handle); +void acpiphp_enumerate_slots(struct pci_bus *bus); void acpiphp_remove_slots(struct pci_bus *bus); void acpiphp_check_host_bridge(acpi_handle handle); #else static inline void acpiphp_init(void) { } -static inline void acpiphp_enumerate_slots(struct pci_bus *bus, - acpi_handle handle) { } +static inline void acpiphp_enumerate_slots(struct pci_bus *bus) { } static inline void acpiphp_remove_slots(struct pci_bus *bus) { } static inline void acpiphp_check_host_bridge(acpi_handle handle) { } #endif From 2552002a46cd6a7a262ea1718db33d1a1517008e Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 13 Jul 2013 23:27:23 +0200 Subject: [PATCH 0247/3400] ACPI / hotplug / PCI: Consolidate acpiphp_enumerate_slots() The acpiphp_enumerate_slots() function is now split into two parts, acpiphp_enumerate_slots() proper and init_bridge_misc() which is only called by the former. If these functions are combined, it is possible to make the code easier to follow and to clean up the error handling (to prevent memory leaks on error from happening in particular), so do that. Signed-off-by: Rafael J. Wysocki Tested-by: Mika Westerberg --- drivers/pci/hotplug/acpiphp_glue.c | 92 +++++++++++++++--------------- 1 file changed, 45 insertions(+), 47 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index a203ba529fef..68c3809ed7ce 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -353,46 +353,6 @@ static int detect_ejectable_slots(acpi_handle handle) return found; } -/* initialize miscellaneous stuff for both root and PCI-to-PCI bridge */ -static void init_bridge_misc(struct acpiphp_bridge *bridge) -{ - acpi_status status; - - /* must be added to the list prior to calling register_slot */ - mutex_lock(&bridge_mutex); - list_add(&bridge->list, &bridge_list); - mutex_unlock(&bridge_mutex); - - /* register all slot objects under this bridge */ - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1, - register_slot, NULL, bridge, NULL); - if (ACPI_FAILURE(status)) { - mutex_lock(&bridge_mutex); - list_del(&bridge->list); - mutex_unlock(&bridge_mutex); - return; - } - - /* install notify handler for P2P bridges */ - if (!pci_is_root_bus(bridge->pci_bus)) { - if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) { - status = acpi_remove_notify_handler(bridge->func->handle, - ACPI_SYSTEM_NOTIFY, - handle_hotplug_event_func); - if (ACPI_FAILURE(status)) - err("failed to remove notify handler\n"); - } - status = acpi_install_notify_handler(bridge->handle, - ACPI_SYSTEM_NOTIFY, - handle_hotplug_event_bridge, - bridge); - - if (ACPI_FAILURE(status)) { - err("failed to register interrupt notify handler\n"); - } - } -} - /* find acpiphp_func from acpiphp_bridge */ static struct acpiphp_func *acpiphp_bridge_handle_to_function(acpi_handle handle) @@ -1149,8 +1109,9 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type, */ void acpiphp_enumerate_slots(struct pci_bus *bus) { - acpi_handle handle; struct acpiphp_bridge *bridge; + acpi_handle handle; + acpi_status status; if (acpiphp_disabled) return; @@ -1178,14 +1139,51 @@ void acpiphp_enumerate_slots(struct pci_bus *bus) */ get_device(&bus->dev); - if (!pci_is_root_bus(bridge->pci_bus) && - acpi_has_method(bridge->handle, "_EJ0")) { - dbg("found ejectable p2p bridge\n"); - bridge->flags |= BRIDGE_HAS_EJ0; - bridge->func = acpiphp_bridge_handle_to_function(handle); + /* must be added to the list prior to calling register_slot */ + mutex_lock(&bridge_mutex); + list_add(&bridge->list, &bridge_list); + mutex_unlock(&bridge_mutex); + + /* register all slot objects under this bridge */ + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, 1, + register_slot, NULL, bridge, NULL); + if (ACPI_FAILURE(status)) { + acpi_handle_err(bridge->handle, "failed to register slots\n"); + goto err; } - init_bridge_misc(bridge); + if (pci_is_root_bus(bridge->pci_bus)) + return; + + /* install notify handler for P2P bridges */ + status = acpi_install_notify_handler(bridge->handle, ACPI_SYSTEM_NOTIFY, + handle_hotplug_event_bridge, + bridge); + if (ACPI_FAILURE(status)) { + acpi_handle_err(bridge->handle, + "failed to register notify handler\n"); + goto err; + } + + if (!acpi_has_method(bridge->handle, "_EJ0")) + return; + + dbg("found ejectable p2p bridge\n"); + bridge->flags |= BRIDGE_HAS_EJ0; + bridge->func = acpiphp_bridge_handle_to_function(bridge->handle); + if (bridge->func) { + status = acpi_remove_notify_handler(bridge->func->handle, + ACPI_SYSTEM_NOTIFY, + handle_hotplug_event_func); + if (ACPI_FAILURE(status)) + acpi_handle_err(bridge->func->handle, + "failed to remove notify handler\n"); + } + return; + + err: + cleanup_bridge(bridge); + put_bridge(bridge); } /* Destroy hotplug slots associated with the PCI bus */ From 2e862c51904ddd12be2d256513160e1f87beafee Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 13 Jul 2013 23:27:23 +0200 Subject: [PATCH 0248/3400] ACPI / hotplug / PCI: Always return success after adding a function When a new ACPIPHP function is added by register_slot() and the notify handler cannot be installed for it, register_slot() returns an error status without cleaning up, which causes the entire namespace walk in acpiphp_enumerate_slots() to be aborted, although it still may be possible to successfully install the function notify handler for other device objects under the given brigde. To address this issue make register_slot() return success after a new function has been added, even if the addition of the notify handler for it has failed. Signed-off-by: Rafael J. Wysocki Tested-by: Mika Westerberg --- drivers/pci/hotplug/acpiphp_glue.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 68c3809ed7ce..d75ba7e0ca8d 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -325,10 +325,9 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) if (ACPI_FAILURE(status)) err("failed to register interrupt notify handler\n"); - } else - status = AE_OK; + } - return status; + return AE_OK; err_exit: bridge->nr_slots--; From cb7b8cedf6c88b9d1d08e0565e8da52180921071 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 13 Jul 2013 23:27:24 +0200 Subject: [PATCH 0249/3400] ACPI / hotplug / PCI: Hotplug context objects for bridges and functions When either a new hotplug bridge or a new hotplug function is added by the ACPI-based PCI hotplug (ACPIPHP) code, attach a context object to its ACPI handle to store hotplug-related information in it. To start with, put the handle's bridge and function pointers into that object. Count references to the context objects and drop them when they are not needed any more. First of all, this makes it possible to find out if the given bridge has been registered as a function already in a much more straightforward way and acpiphp_bridge_handle_to_function() can be dropped (Yay!). This also will allow some more simplifications to be made going forward. Signed-off-by: Rafael J. Wysocki Tested-by: Mika Westerberg --- drivers/pci/hotplug/acpiphp.h | 10 ++ drivers/pci/hotplug/acpiphp_glue.c | 179 ++++++++++++++++++++++------- 2 files changed, 146 insertions(+), 43 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 6c781edabcc6..f946e47eca7c 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -49,6 +49,7 @@ #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg) #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg) +struct acpiphp_context; struct acpiphp_bridge; struct acpiphp_slot; @@ -77,6 +78,7 @@ struct acpiphp_bridge { struct kref ref; acpi_handle handle; + struct acpiphp_context *context; /* Ejectable PCI-to-PCI bridge (PCI bridge and PCI function) */ struct acpiphp_func *func; @@ -119,6 +121,7 @@ struct acpiphp_slot { * typically 8 objects per slot (i.e. for each PCI function) */ struct acpiphp_func { + struct acpiphp_context *context; struct acpiphp_slot *slot; /* parent */ struct list_head sibling; @@ -128,6 +131,13 @@ struct acpiphp_func { u32 flags; /* see below */ }; +struct acpiphp_context { + acpi_handle handle; + struct acpiphp_func *func; + struct acpiphp_bridge *bridge; + unsigned int refcount; +}; + /* * struct acpiphp_attention_info - device specific attention registration * diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index d75ba7e0ca8d..a0c518c2185e 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -55,6 +55,7 @@ static LIST_HEAD(bridge_list); static DEFINE_MUTEX(bridge_mutex); +static DEFINE_MUTEX(acpiphp_context_lock); #define MY_NAME "acpiphp_glue" @@ -79,6 +80,74 @@ is_pci_dock_device(acpi_handle handle, u32 lvl, void *context, void **rv) } } +static void acpiphp_context_handler(acpi_handle handle, void *context) +{ + /* Intentionally empty. */ +} + +/** + * acpiphp_init_context - Create hotplug context and grab a reference to it. + * @handle: ACPI object handle to create the context for. + * + * Call under acpiphp_context_lock. + */ +static struct acpiphp_context *acpiphp_init_context(acpi_handle handle) +{ + struct acpiphp_context *context; + acpi_status status; + + context = kzalloc(sizeof(*context), GFP_KERNEL); + if (!context) + return NULL; + + context->handle = handle; + context->refcount = 1; + status = acpi_attach_data(handle, acpiphp_context_handler, context); + if (ACPI_FAILURE(status)) { + kfree(context); + return NULL; + } + return context; +} + +/** + * acpiphp_get_context - Get hotplug context and grab a reference to it. + * @handle: ACPI object handle to get the context for. + * + * Call under acpiphp_context_lock. + */ +static struct acpiphp_context *acpiphp_get_context(acpi_handle handle) +{ + struct acpiphp_context *context = NULL; + acpi_status status; + void *data; + + status = acpi_get_data(handle, acpiphp_context_handler, &data); + if (ACPI_SUCCESS(status)) { + context = data; + context->refcount++; + } + return context; +} + +/** + * acpiphp_put_context - Drop a reference to ACPI hotplug context. + * @handle: ACPI object handle to put the context for. + * + * The context object is removed if there are no more references to it. + * + * Call under acpiphp_context_lock. + */ +static void acpiphp_put_context(struct acpiphp_context *context) +{ + if (--context->refcount) + return; + + WARN_ON(context->func || context->bridge); + acpi_detach_data(context->handle, acpiphp_context_handler); + kfree(context); +} + static inline void get_bridge(struct acpiphp_bridge *bridge) { kref_get(&bridge->ref); @@ -91,25 +160,37 @@ static inline void put_bridge(struct acpiphp_bridge *bridge) static void free_bridge(struct kref *kref) { + struct acpiphp_context *context; struct acpiphp_bridge *bridge; struct acpiphp_slot *slot, *next; struct acpiphp_func *func, *tmp; + mutex_lock(&acpiphp_context_lock); + bridge = container_of(kref, struct acpiphp_bridge, ref); list_for_each_entry_safe(slot, next, &bridge->slots, node) { list_for_each_entry_safe(func, tmp, &slot->funcs, sibling) { + context = func->context; + context->func = NULL; + acpiphp_put_context(context); kfree(func); } kfree(slot); } - /* Release reference acquired by acpiphp_bridge_handle_to_function() */ + /* Release the reference acquired by acpiphp_enumerate_slots(). */ if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) put_bridge(bridge->func->slot->bridge); + put_device(&bridge->pci_bus->dev); pci_dev_put(bridge->pci_dev); + context = bridge->context; + context->bridge = NULL; + acpiphp_put_context(context); kfree(bridge); + + mutex_unlock(&acpiphp_context_lock); } /* @@ -194,10 +275,11 @@ static void acpiphp_dock_release(void *data) } /* callback routine to register each ACPI PCI slot object */ -static acpi_status -register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) +static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data, + void **rv) { - struct acpiphp_bridge *bridge = (struct acpiphp_bridge *)context; + struct acpiphp_bridge *bridge = data; + struct acpiphp_context *context; struct acpiphp_slot *slot; struct acpiphp_func *newfunc; acpi_status status = AE_OK; @@ -230,6 +312,18 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) newfunc->handle = handle; newfunc->function = function; + mutex_lock(&acpiphp_context_lock); + context = acpiphp_init_context(handle); + if (!context) { + mutex_unlock(&acpiphp_context_lock); + acpi_handle_err(handle, "No hotplug context\n"); + kfree(newfunc); + return AE_NOT_EXIST; + } + newfunc->context = context; + context->func = newfunc; + mutex_unlock(&acpiphp_context_lock); + if (acpi_has_method(handle, "_EJ0")) newfunc->flags = FUNC_HAS_EJ0; @@ -266,8 +360,8 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) if (!found) { slot = kzalloc(sizeof(struct acpiphp_slot), GFP_KERNEL); if (!slot) { - kfree(newfunc); - return AE_NO_MEMORY; + status = AE_NO_MEMORY; + goto err_out; } slot->bridge = bridge; @@ -291,7 +385,9 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) else warn("acpiphp_register_hotplug_slot failed " "(err code = 0x%x)\n", retval); - goto err_exit; + + status = AE_OK; + goto err; } } @@ -329,15 +425,20 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) return AE_OK; - err_exit: + err: bridge->nr_slots--; mutex_lock(&bridge_mutex); list_del(&slot->node); mutex_unlock(&bridge_mutex); kfree(slot); - kfree(newfunc); - return AE_OK; + err_out: + mutex_lock(&acpiphp_context_lock); + context->func = NULL; + acpiphp_put_context(context); + mutex_unlock(&acpiphp_context_lock); + kfree(newfunc); + return status; } @@ -352,32 +453,6 @@ static int detect_ejectable_slots(acpi_handle handle) return found; } - -/* find acpiphp_func from acpiphp_bridge */ -static struct acpiphp_func *acpiphp_bridge_handle_to_function(acpi_handle handle) -{ - struct acpiphp_bridge *bridge; - struct acpiphp_slot *slot; - struct acpiphp_func *func = NULL; - - mutex_lock(&bridge_mutex); - list_for_each_entry(bridge, &bridge_list, list) { - list_for_each_entry(slot, &bridge->slots, node) { - list_for_each_entry(func, &slot->funcs, sibling) { - if (func->handle == handle) { - get_bridge(func->slot->bridge); - mutex_unlock(&bridge_mutex); - return func; - } - } - } - } - mutex_unlock(&bridge_mutex); - - return NULL; -} - - static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle) { struct acpiphp_bridge *bridge; @@ -1108,6 +1183,7 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type, */ void acpiphp_enumerate_slots(struct pci_bus *bus) { + struct acpiphp_context *context; struct acpiphp_bridge *bridge; acpi_handle handle; acpi_status status; @@ -1120,8 +1196,8 @@ void acpiphp_enumerate_slots(struct pci_bus *bus) return; bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); - if (bridge == NULL) { - err("out of memory\n"); + if (!bridge) { + acpi_handle_err(handle, "No memory for bridge object\n"); return; } @@ -1131,6 +1207,21 @@ void acpiphp_enumerate_slots(struct pci_bus *bus) bridge->pci_dev = pci_dev_get(bus->self); bridge->pci_bus = bus; + mutex_lock(&acpiphp_context_lock); + context = acpiphp_get_context(handle); + if (!context) { + context = acpiphp_init_context(handle); + if (!context) { + mutex_unlock(&acpiphp_context_lock); + acpi_handle_err(handle, "No hotplug context\n"); + kfree(bridge); + return; + } + } + bridge->context = context; + context->bridge = bridge; + mutex_unlock(&acpiphp_context_lock); + /* * Grab a ref to the subordinate PCI bus in case the bus is * removed via PCI core logical hotplug. The ref pins the bus @@ -1169,13 +1260,15 @@ void acpiphp_enumerate_slots(struct pci_bus *bus) dbg("found ejectable p2p bridge\n"); bridge->flags |= BRIDGE_HAS_EJ0; - bridge->func = acpiphp_bridge_handle_to_function(bridge->handle); - if (bridge->func) { - status = acpi_remove_notify_handler(bridge->func->handle, - ACPI_SYSTEM_NOTIFY, + if (context->func) { + get_bridge(context->func->slot->bridge); + bridge->func = context->func; + handle = context->handle; + WARN_ON(bridge->handle != handle); + status = acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY, handle_hotplug_event_func); if (ACPI_FAILURE(status)) - acpi_handle_err(bridge->func->handle, + acpi_handle_err(handle, "failed to remove notify handler\n"); } return; From 87831273438d66167dddc6d73e42d49671cb56bb Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 13 Jul 2013 23:27:24 +0200 Subject: [PATCH 0250/3400] ACPI / hotplug / PCI: Unified notify handler for hotplug events Using the hotplug context objects introduced previously rework the ACPI-based PCI hotplug (ACPIPHP) core code so that all notifications for ACPI device objects corresponding to the hotplug PCI devices are handled by one function, handle_hotplug_event(), which recognizes whether it has to handle a bridge or a function. In addition to code size reduction it allows some ugly pieces of code where notify handlers have to be uninstalled and installed again to go away. Moreover, it fixes a theoretically possible race between handle_hotplug_event() and free_bridge() tearing down data structures for the same handle. Signed-off-by: Rafael J. Wysocki Tested-by: Mika Westerberg --- drivers/pci/hotplug/acpiphp.h | 1 + drivers/pci/hotplug/acpiphp_glue.c | 132 ++++++++++++----------------- 2 files changed, 53 insertions(+), 80 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index f946e47eca7c..b96a8a9c39c7 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -136,6 +136,7 @@ struct acpiphp_context { struct acpiphp_func *func; struct acpiphp_bridge *bridge; unsigned int refcount; + bool handler_for_func; }; /* diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index a0c518c2185e..ef7b25c1db57 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -59,11 +59,10 @@ static DEFINE_MUTEX(acpiphp_context_lock); #define MY_NAME "acpiphp_glue" -static void handle_hotplug_event_bridge (acpi_handle, u32, void *); +static void handle_hotplug_event(acpi_handle handle, u32 type, void *data); static void acpiphp_sanitize_bus(struct pci_bus *bus); static void acpiphp_set_hpp_values(struct pci_bus *bus); static void hotplug_event_func(acpi_handle handle, u32 type, void *context); -static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context); static void free_bridge(struct kref *kref); /* callback routine to check for the existence of a pci dock device */ @@ -179,13 +178,13 @@ static void free_bridge(struct kref *kref) kfree(slot); } + context = bridge->context; /* Release the reference acquired by acpiphp_enumerate_slots(). */ - if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) + if (context->handler_for_func) put_bridge(bridge->func->slot->bridge); put_device(&bridge->pci_bus->dev); pci_dev_put(bridge->pci_dev); - context = bridge->context; context->bridge = NULL; acpiphp_put_context(context); kfree(bridge); @@ -414,12 +413,12 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data, /* install notify handler */ if (!(newfunc->flags & FUNC_HAS_DCK)) { - status = acpi_install_notify_handler(handle, - ACPI_SYSTEM_NOTIFY, - handle_hotplug_event_func, - newfunc); - - if (ACPI_FAILURE(status)) + status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, + handle_hotplug_event, + context); + if (ACPI_SUCCESS(status)) + context->handler_for_func = true; + else err("failed to register interrupt notify handler\n"); } @@ -476,32 +475,23 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) acpi_status status; acpi_handle handle = bridge->handle; - if (!pci_is_root_bus(bridge->pci_bus)) { - status = acpi_remove_notify_handler(handle, - ACPI_SYSTEM_NOTIFY, - handle_hotplug_event_bridge); + if (!bridge->context->handler_for_func) { + status = acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY, + handle_hotplug_event); if (ACPI_FAILURE(status)) err("failed to remove notify handler\n"); } - if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) { - status = acpi_install_notify_handler(bridge->func->handle, - ACPI_SYSTEM_NOTIFY, - handle_hotplug_event_func, - bridge->func); - if (ACPI_FAILURE(status)) - err("failed to install interrupt notify handler\n"); - } - list_for_each_entry(slot, &bridge->slots, node) { list_for_each_entry(func, &slot->funcs, sibling) { if (is_dock_device(func->handle)) { unregister_hotplug_dock_device(func->handle); } if (!(func->flags & FUNC_HAS_DCK)) { + func->context->handler_for_func = false; status = acpi_remove_notify_handler(func->handle, - ACPI_SYSTEM_NOTIFY, - handle_hotplug_event_func); + ACPI_SYSTEM_NOTIFY, + handle_hotplug_event); if (ACPI_FAILURE(status)) err("failed to remove notify handler\n"); } @@ -1071,31 +1061,6 @@ static void _handle_hotplug_event_bridge(struct work_struct *work) put_bridge(bridge); } -/** - * handle_hotplug_event_bridge - handle ACPI event on bridges - * @handle: Notify()'ed acpi_handle - * @type: Notify code - * @context: pointer to acpiphp_bridge structure - * - * Handles ACPI event notification on {host,p2p} bridges. - */ -static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, - void *context) -{ - struct acpiphp_bridge *bridge = context; - - /* - * Currently the code adds all hotplug events to the kacpid_wq - * queue when it should add hotplug events to the kacpi_hotplug_wq. - * The proper way to fix this is to reorganize the code so that - * drivers (dock, etc.) do not call acpi_os_execute(), etc. - * For now just re-add this work to the kacpi_hotplug_wq so we - * don't deadlock on hotplug actions. - */ - get_bridge(bridge); - alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_bridge); -} - static void hotplug_event_func(acpi_handle handle, u32 type, void *context) { struct acpiphp_func *func = context; @@ -1153,17 +1118,33 @@ static void _handle_hotplug_event_func(struct work_struct *work) } /** - * handle_hotplug_event_func - handle ACPI event on functions (i.e. slots) + * handle_hotplug_event - handle ACPI hotplug event * @handle: Notify()'ed acpi_handle * @type: Notify code - * @context: pointer to acpiphp_func structure + * @data: pointer to acpiphp_context structure * * Handles ACPI event notification on slots. */ -static void handle_hotplug_event_func(acpi_handle handle, u32 type, - void *context) +static void handle_hotplug_event(acpi_handle handle, u32 type, void *data) { - struct acpiphp_func *func = context; + struct acpiphp_context *context; + void (*work_func)(struct work_struct *work) = NULL; + + mutex_lock(&acpiphp_context_lock); + context = acpiphp_get_context(handle); + if (context) { + if (context->bridge) { + get_bridge(context->bridge); + data = context->bridge; + work_func = _handle_hotplug_event_bridge; + } else if (context->func) { + get_bridge(context->func->slot->bridge); + data = context->func; + work_func = _handle_hotplug_event_func; + } + acpiphp_put_context(context); + } + mutex_unlock(&acpiphp_context_lock); /* * Currently the code adds all hotplug events to the kacpid_wq @@ -1173,8 +1154,8 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type, * For now just re-add this work to the kacpi_hotplug_wq so we * don't deadlock on hotplug actions. */ - get_bridge(func->slot->bridge); - alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_func); + if (work_func) + alloc_acpi_hp_work(handle, type, data, work_func); } /* @@ -1245,33 +1226,24 @@ void acpiphp_enumerate_slots(struct pci_bus *bus) if (pci_is_root_bus(bridge->pci_bus)) return; + if (acpi_has_method(bridge->handle, "_EJ0")) { + dbg("found ejectable p2p bridge\n"); + bridge->flags |= BRIDGE_HAS_EJ0; + } + if (context->handler_for_func) { + /* Notify handler already installed. */ + bridge->func = context->func; + get_bridge(context->func->slot->bridge); + return; + } + /* install notify handler for P2P bridges */ status = acpi_install_notify_handler(bridge->handle, ACPI_SYSTEM_NOTIFY, - handle_hotplug_event_bridge, - bridge); - if (ACPI_FAILURE(status)) { - acpi_handle_err(bridge->handle, - "failed to register notify handler\n"); - goto err; - } - - if (!acpi_has_method(bridge->handle, "_EJ0")) + handle_hotplug_event, NULL); + if (ACPI_SUCCESS(status)) return; - dbg("found ejectable p2p bridge\n"); - bridge->flags |= BRIDGE_HAS_EJ0; - if (context->func) { - get_bridge(context->func->slot->bridge); - bridge->func = context->func; - handle = context->handle; - WARN_ON(bridge->handle != handle); - status = acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY, - handle_hotplug_event_func); - if (ACPI_FAILURE(status)) - acpi_handle_err(handle, - "failed to remove notify handler\n"); - } - return; + acpi_handle_err(bridge->handle, "failed to register notify handler\n"); err: cleanup_bridge(bridge); From ed13febf8fac1a08f939f97378574937a7d2f121 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 13 Jul 2013 23:27:24 +0200 Subject: [PATCH 0251/3400] ACPI / hotplug / PCI: Rework acpiphp_handle_to_bridge() Using the hotplug context objects introduced previously rework the ACPI-based PCI hotplug (ACPIPHP) core code to get to acpiphp_bridge objects associated with hotplug bridges from those context objects rather than from the global list of hotplug bridges. Signed-off-by: Rafael J. Wysocki Tested-by: Mika Westerberg --- drivers/pci/hotplug/acpiphp_glue.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index ef7b25c1db57..6cfd8a684766 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -454,18 +454,20 @@ static int detect_ejectable_slots(acpi_handle handle) static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle) { - struct acpiphp_bridge *bridge; + struct acpiphp_context *context; + struct acpiphp_bridge *bridge = NULL; - mutex_lock(&bridge_mutex); - list_for_each_entry(bridge, &bridge_list, list) - if (bridge->handle == handle) { + mutex_lock(&acpiphp_context_lock); + context = acpiphp_get_context(handle); + if (context) { + bridge = context->bridge; + if (bridge) get_bridge(bridge); - mutex_unlock(&bridge_mutex); - return bridge; - } - mutex_unlock(&bridge_mutex); - return NULL; + acpiphp_put_context(context); + } + mutex_unlock(&acpiphp_context_lock); + return bridge; } static void cleanup_bridge(struct acpiphp_bridge *bridge) From c8ebcf1ff91a8f64b09c4df0ee21ae80a953c39c Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 13 Jul 2013 23:27:24 +0200 Subject: [PATCH 0252/3400] ACPI / hotplug / PCI: Pass hotplug context objects to event handlers Modify handle_hotplug_event() to pass the entire context object (instead of its fields individually) to work functions started by it. This change makes the subsequent consolidation of the event handling work functions a bit more straightforward. Signed-off-by: Rafael J. Wysocki Tested-by: Mika Westerberg --- drivers/pci/hotplug/acpiphp_glue.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 6cfd8a684766..b5a98f4baa3a 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -989,6 +989,7 @@ void acpiphp_check_host_bridge(acpi_handle handle) static void _handle_hotplug_event_bridge(struct work_struct *work) { + struct acpiphp_context *context; struct acpiphp_bridge *bridge; char objname[64]; struct acpi_buffer buffer = { .length = sizeof(objname), @@ -1000,7 +1001,8 @@ static void _handle_hotplug_event_bridge(struct work_struct *work) hp_work = container_of(work, struct acpi_hp_work, work); handle = hp_work->handle; type = hp_work->type; - bridge = (struct acpiphp_bridge *)hp_work->context; + context = hp_work->context; + bridge = context->bridge; acpi_scan_lock_acquire(); @@ -1105,18 +1107,18 @@ static void hotplug_event_func(acpi_handle handle, u32 type, void *context) static void _handle_hotplug_event_func(struct work_struct *work) { + struct acpiphp_context *context; struct acpi_hp_work *hp_work; - struct acpiphp_func *func; hp_work = container_of(work, struct acpi_hp_work, work); - func = hp_work->context; + context = hp_work->context; acpi_scan_lock_acquire(); - hotplug_event_func(hp_work->handle, hp_work->type, func); + hotplug_event_func(hp_work->handle, hp_work->type, context->func); acpi_scan_lock_release(); kfree(hp_work); /* allocated in handle_hotplug_event_func */ - put_bridge(func->slot->bridge); + put_bridge(context->func->slot->bridge); } /** @@ -1137,11 +1139,9 @@ static void handle_hotplug_event(acpi_handle handle, u32 type, void *data) if (context) { if (context->bridge) { get_bridge(context->bridge); - data = context->bridge; work_func = _handle_hotplug_event_bridge; } else if (context->func) { get_bridge(context->func->slot->bridge); - data = context->func; work_func = _handle_hotplug_event_func; } acpiphp_put_context(context); @@ -1157,7 +1157,7 @@ static void handle_hotplug_event(acpi_handle handle, u32 type, void *data) * don't deadlock on hotplug actions. */ if (work_func) - alloc_acpi_hp_work(handle, type, data, work_func); + alloc_acpi_hp_work(handle, type, context, work_func); } /* From 43e5c091c797616170b11f4a1b32ea8c81ad0100 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 13 Jul 2013 23:27:24 +0200 Subject: [PATCH 0253/3400] ACPI / hotplug / PCI: Merge hotplug event handling functions There are separate handling event functions for hotplug bridges and for hotplug functions, but they may be combined into one common hotplug event handling function which simplifies the code slightly. That also allows a theoretical bug to be dealt with which in principle may occur if a hotplug bridge is on a dock station, because in that case the bridge-specific notification should be used instead of the function-specific one, but the dock station always uses the latter. Signed-off-by: Rafael J. Wysocki Tested-by: Mika Westerberg --- drivers/pci/hotplug/acpiphp_glue.c | 152 ++++++++++++----------------- 1 file changed, 65 insertions(+), 87 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index b5a98f4baa3a..e2f9ea03aece 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -62,7 +62,7 @@ static DEFINE_MUTEX(acpiphp_context_lock); static void handle_hotplug_event(acpi_handle handle, u32 type, void *data); static void acpiphp_sanitize_bus(struct pci_bus *bus); static void acpiphp_set_hpp_values(struct pci_bus *bus); -static void hotplug_event_func(acpi_handle handle, u32 type, void *context); +static void hotplug_event(acpi_handle handle, u32 type, void *data); static void free_bridge(struct kref *kref); /* callback routine to check for the existence of a pci dock device */ @@ -201,8 +201,8 @@ static void free_bridge(struct kref *kref) */ static void post_dock_fixups(acpi_handle not_used, u32 event, void *data) { - struct acpiphp_func *func = data; - struct pci_bus *bus = func->slot->bridge->pci_bus; + struct acpiphp_context *context = data; + struct pci_bus *bus = context->func->slot->bridge->pci_bus; u32 buses; if (!bus->self) @@ -227,7 +227,7 @@ static void post_dock_fixups(acpi_handle not_used, u32 event, void *data) static const struct acpi_dock_ops acpiphp_dock_ops = { .fixup = post_dock_fixups, - .handler = hotplug_event_func, + .handler = hotplug_event, }; /* Check whether the PCI device is managed by native PCIe hotplug driver */ @@ -261,16 +261,16 @@ static bool device_is_managed_by_native_pciehp(struct pci_dev *pdev) static void acpiphp_dock_init(void *data) { - struct acpiphp_func *func = data; + struct acpiphp_context *context = data; - get_bridge(func->slot->bridge); + get_bridge(context->func->slot->bridge); } static void acpiphp_dock_release(void *data) { - struct acpiphp_func *func = data; + struct acpiphp_context *context = data; - put_bridge(func->slot->bridge); + put_bridge(context->func->slot->bridge); } /* callback routine to register each ACPI PCI slot object */ @@ -406,7 +406,7 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data, */ newfunc->flags &= ~FUNC_HAS_EJ0; if (register_hotplug_dock_device(handle, - &acpiphp_dock_ops, newfunc, + &acpiphp_dock_ops, context, acpiphp_dock_init, acpiphp_dock_release)) dbg("failed to register dock device\n"); } @@ -987,24 +987,26 @@ void acpiphp_check_host_bridge(acpi_handle handle) ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL, NULL); } -static void _handle_hotplug_event_bridge(struct work_struct *work) +static void hotplug_event(acpi_handle handle, u32 type, void *data) { - struct acpiphp_context *context; + struct acpiphp_context *context = data; struct acpiphp_bridge *bridge; + struct acpiphp_func *func; char objname[64]; struct acpi_buffer buffer = { .length = sizeof(objname), .pointer = objname }; - struct acpi_hp_work *hp_work; - acpi_handle handle; - u32 type; - hp_work = container_of(work, struct acpi_hp_work, work); - handle = hp_work->handle; - type = hp_work->type; - context = hp_work->context; + mutex_lock(&acpiphp_context_lock); bridge = context->bridge; + if (bridge) + get_bridge(bridge); - acpi_scan_lock_acquire(); + /* + * If context->func is not NULL, we are holding a reference to its + * parent bridge, so it won't go away until we drop that reference. + */ + func = context->func; + mutex_unlock(&acpiphp_context_lock); acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); @@ -1013,15 +1015,24 @@ static void _handle_hotplug_event_bridge(struct work_struct *work) /* bus re-enumerate */ dbg("%s: Bus check notify on %s\n", __func__, objname); dbg("%s: re-enumerating slots under %s\n", __func__, objname); - acpiphp_check_bridge(bridge); - acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, - ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL, NULL); + if (bridge) { + acpiphp_check_bridge(bridge); + acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, + ACPI_UINT32_MAX, check_sub_bridges, + NULL, NULL, NULL); + } else { + acpiphp_enable_slot(func->slot); + } break; case ACPI_NOTIFY_DEVICE_CHECK: /* device check */ dbg("%s: Device check notify on %s\n", __func__, objname); - acpiphp_check_bridge(bridge); + if (bridge) + acpiphp_check_bridge(bridge); + else + acpiphp_check_bridge(func->slot->bridge); + break; case ACPI_NOTIFY_DEVICE_WAKE: @@ -1032,12 +1043,15 @@ static void _handle_hotplug_event_bridge(struct work_struct *work) case ACPI_NOTIFY_EJECT_REQUEST: /* request device eject */ dbg("%s: Device eject notify on %s\n", __func__, objname); - if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) { - struct acpiphp_slot *slot; - slot = bridge->func->slot; - if (!acpiphp_disable_slot(slot)) - acpiphp_eject_slot(slot); - } + if (!func) + break; + + if (bridge && !(bridge->flags & BRIDGE_HAS_EJ0)) + break; + + if (!(acpiphp_disable_slot(func->slot))) + acpiphp_eject_slot(func->slot); + break; case ACPI_NOTIFY_FREQUENCY_MISMATCH: @@ -1056,56 +1070,16 @@ static void _handle_hotplug_event_bridge(struct work_struct *work) break; default: - warn("notify_handler: unknown event type 0x%x for %s\n", type, objname); + warn("notify_handler: unknown event type 0x%x for %s\n", type, + objname); break; } - acpi_scan_lock_release(); - kfree(hp_work); /* allocated in handle_hotplug_event_bridge */ - put_bridge(bridge); + if (bridge) + put_bridge(bridge); } -static void hotplug_event_func(acpi_handle handle, u32 type, void *context) -{ - struct acpiphp_func *func = context; - char objname[64]; - struct acpi_buffer buffer = { .length = sizeof(objname), - .pointer = objname }; - - acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); - - switch (type) { - case ACPI_NOTIFY_BUS_CHECK: - /* bus re-enumerate */ - dbg("%s: Bus check notify on %s\n", __func__, objname); - acpiphp_enable_slot(func->slot); - break; - - case ACPI_NOTIFY_DEVICE_CHECK: - /* device check : re-enumerate from parent bus */ - dbg("%s: Device check notify on %s\n", __func__, objname); - acpiphp_check_bridge(func->slot->bridge); - break; - - case ACPI_NOTIFY_DEVICE_WAKE: - /* wake event */ - dbg("%s: Device wake notify on %s\n", __func__, objname); - break; - - case ACPI_NOTIFY_EJECT_REQUEST: - /* request device eject */ - dbg("%s: Device eject notify on %s\n", __func__, objname); - if (!(acpiphp_disable_slot(func->slot))) - acpiphp_eject_slot(func->slot); - break; - - default: - warn("notify_handler: unknown event type 0x%x for %s\n", type, objname); - break; - } -} - -static void _handle_hotplug_event_func(struct work_struct *work) +static void hotplug_event_work(struct work_struct *work) { struct acpiphp_context *context; struct acpi_hp_work *hp_work; @@ -1114,11 +1088,18 @@ static void _handle_hotplug_event_func(struct work_struct *work) context = hp_work->context; acpi_scan_lock_acquire(); - hotplug_event_func(hp_work->handle, hp_work->type, context->func); + hotplug_event(hp_work->handle, hp_work->type, context); acpi_scan_lock_release(); - kfree(hp_work); /* allocated in handle_hotplug_event_func */ - put_bridge(context->func->slot->bridge); + kfree(hp_work); /* allocated in handle_hotplug_event() */ + + mutex_lock(&acpiphp_context_lock); + if (context->func) + put_bridge(context->func->slot->bridge); + else + acpiphp_put_context(context); + + mutex_unlock(&acpiphp_context_lock); } /** @@ -1132,22 +1113,19 @@ static void _handle_hotplug_event_func(struct work_struct *work) static void handle_hotplug_event(acpi_handle handle, u32 type, void *data) { struct acpiphp_context *context; - void (*work_func)(struct work_struct *work) = NULL; mutex_lock(&acpiphp_context_lock); context = acpiphp_get_context(handle); if (context) { - if (context->bridge) { - get_bridge(context->bridge); - work_func = _handle_hotplug_event_bridge; - } else if (context->func) { + if (context->func) { get_bridge(context->func->slot->bridge); - work_func = _handle_hotplug_event_func; + acpiphp_put_context(context); + } else if (!context->bridge) { + acpiphp_put_context(context); + context = NULL; } - acpiphp_put_context(context); } mutex_unlock(&acpiphp_context_lock); - /* * Currently the code adds all hotplug events to the kacpid_wq * queue when it should add hotplug events to the kacpi_hotplug_wq. @@ -1156,8 +1134,8 @@ static void handle_hotplug_event(acpi_handle handle, u32 type, void *data) * For now just re-add this work to the kacpi_hotplug_wq so we * don't deadlock on hotplug actions. */ - if (work_func) - alloc_acpi_hp_work(handle, type, context, work_func); + if (context) + alloc_acpi_hp_work(handle, type, context, hotplug_event_work); } /* From f28181109e85b49b5b4b1c381d889b4ea7315988 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 13 Jul 2013 23:27:24 +0200 Subject: [PATCH 0254/3400] ACPI / hotplug / PCI: Drop func field from struct acpiphp_bridge Since the func pointer in struct acpiphp_context can always be used instead of the func pointer in struct acpiphp_bridge, drop the latter. Signed-off-by: Rafael J. Wysocki Tested-by: Mika Westerberg --- drivers/pci/hotplug/acpiphp.h | 2 -- drivers/pci/hotplug/acpiphp_glue.c | 3 +-- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index b96a8a9c39c7..4980ff4919a6 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -79,8 +79,6 @@ struct acpiphp_bridge { acpi_handle handle; struct acpiphp_context *context; - /* Ejectable PCI-to-PCI bridge (PCI bridge and PCI function) */ - struct acpiphp_func *func; int nr_slots; diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index e2f9ea03aece..a83ce9db16bb 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -181,7 +181,7 @@ static void free_bridge(struct kref *kref) context = bridge->context; /* Release the reference acquired by acpiphp_enumerate_slots(). */ if (context->handler_for_func) - put_bridge(bridge->func->slot->bridge); + put_bridge(context->func->slot->bridge); put_device(&bridge->pci_bus->dev); pci_dev_put(bridge->pci_dev); @@ -1212,7 +1212,6 @@ void acpiphp_enumerate_slots(struct pci_bus *bus) } if (context->handler_for_func) { /* Notify handler already installed. */ - bridge->func = context->func; get_bridge(context->func->slot->bridge); return; } From ac372338b750648355bcc64bb0bca13fc6f0a3d5 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 13 Jul 2013 23:27:24 +0200 Subject: [PATCH 0255/3400] ACPI / hotplug / PCI: Refactor slot allocation code in register_slot() To make the code in register_slot() a bit easier to follow, change the way the slot allocation part is organized. Drop one local variable that's not used any more after that modification. This code change should not lead to any changes in behavior. Signed-off-by: Rafael J. Wysocki Tested-by: Mika Westerberg --- drivers/pci/hotplug/acpiphp_glue.c | 82 +++++++++++++++--------------- 1 file changed, 40 insertions(+), 42 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index a83ce9db16bb..95af39c9a396 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -283,7 +283,7 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data, struct acpiphp_func *newfunc; acpi_status status = AE_OK; unsigned long long adr, sun; - int device, function, retval, found = 0; + int device, function, retval; struct pci_bus *pbus = bridge->pci_bus; struct pci_dev *pdev; u32 val; @@ -352,44 +352,49 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data, if (slot->device == device) { if (slot->sun != sun) warn("sibling found, but _SUN doesn't match!\n"); - found = 1; - break; + + goto slot_found; } - if (!found) { - slot = kzalloc(sizeof(struct acpiphp_slot), GFP_KERNEL); - if (!slot) { - status = AE_NO_MEMORY; - goto err_out; - } - - slot->bridge = bridge; - slot->device = device; - slot->sun = sun; - INIT_LIST_HEAD(&slot->funcs); - mutex_init(&slot->crit_sect); - - mutex_lock(&bridge_mutex); - list_add_tail(&slot->node, &bridge->slots); - mutex_unlock(&bridge_mutex); - bridge->nr_slots++; - - dbg("found ACPI PCI Hotplug slot %llu at PCI %04x:%02x:%02x\n", - slot->sun, pci_domain_nr(pbus), pbus->number, device); - retval = acpiphp_register_hotplug_slot(slot); - if (retval) { - if (retval == -EBUSY) - warn("Slot %llu already registered by another " - "hotplug driver\n", slot->sun); - else - warn("acpiphp_register_hotplug_slot failed " - "(err code = 0x%x)\n", retval); - - status = AE_OK; - goto err; - } + slot = kzalloc(sizeof(struct acpiphp_slot), GFP_KERNEL); + if (!slot) { + status = AE_NO_MEMORY; + goto err; } + slot->bridge = bridge; + slot->device = device; + slot->sun = sun; + INIT_LIST_HEAD(&slot->funcs); + mutex_init(&slot->crit_sect); + + mutex_lock(&bridge_mutex); + list_add_tail(&slot->node, &bridge->slots); + mutex_unlock(&bridge_mutex); + bridge->nr_slots++; + + dbg("found ACPI PCI Hotplug slot %llu at PCI %04x:%02x:%02x\n", + slot->sun, pci_domain_nr(pbus), pbus->number, device); + + retval = acpiphp_register_hotplug_slot(slot); + if (retval) { + if (retval == -EBUSY) + warn("Slot %llu already registered by another " + "hotplug driver\n", slot->sun); + else + warn("acpiphp_register_hotplug_slot failed " + "(err code = 0x%x)\n", retval); + + bridge->nr_slots--; + mutex_lock(&bridge_mutex); + list_del(&slot->node); + mutex_unlock(&bridge_mutex); + kfree(slot); + status = AE_OK; + goto err; + } + + slot_found: newfunc->slot = slot; mutex_lock(&bridge_mutex); list_add_tail(&newfunc->sibling, &slot->funcs); @@ -425,13 +430,6 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data, return AE_OK; err: - bridge->nr_slots--; - mutex_lock(&bridge_mutex); - list_del(&slot->node); - mutex_unlock(&bridge_mutex); - kfree(slot); - - err_out: mutex_lock(&acpiphp_context_lock); context->func = NULL; acpiphp_put_context(context); From bbd34fcdd1b201e996235731a7c98fd5197d9e51 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 13 Jul 2013 23:27:24 +0200 Subject: [PATCH 0256/3400] ACPI / hotplug / PCI: Register all devices under the given bridge Rework register_slot() to create a struct acpiphp_func object for every function it is called for and to create acpiphp slots for all of them. Although acpiphp_register_hotplug_slot() is only called for the slots whose functions are identified as "ejectable", so that user space can manipulate them, the ACPIPHP notify handler, handle_hotplug_event(), is now installed for all of the registered functions (that aren't dock stations) and hotplug events may be handled for all of them. As a result, essentially, all PCI bridges represented by objects in the ACPI namespace are now going to be "hotplug" bridges and that may affect resources allocation in general, although it shouldn't lead to problems. This allows the code to be simplified substantially and addresses the problem where bus check or device check notifications for some PCI bridges or devices are not handled, because those devices are not recognized as "ejectable" or there appear to be no "ejectable" devices under those bridges. Signed-off-by: Rafael J. Wysocki Tested-by: Mika Westerberg --- drivers/pci/hotplug/acpiphp.h | 1 - drivers/pci/hotplug/acpiphp_glue.c | 230 ++++++++++------------------- 2 files changed, 75 insertions(+), 156 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 4980ff4919a6..76a1c979a251 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -134,7 +134,6 @@ struct acpiphp_context { struct acpiphp_func *func; struct acpiphp_bridge *bridge; unsigned int refcount; - bool handler_for_func; }; /* diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 95af39c9a396..b306e993ad08 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -65,20 +65,6 @@ static void acpiphp_set_hpp_values(struct pci_bus *bus); static void hotplug_event(acpi_handle handle, u32 type, void *data); static void free_bridge(struct kref *kref); -/* callback routine to check for the existence of a pci dock device */ -static acpi_status -is_pci_dock_device(acpi_handle handle, u32 lvl, void *context, void **rv) -{ - int *count = (int *)context; - - if (is_dock_device(handle)) { - (*count)++; - return AE_CTRL_TERMINATE; - } else { - return AE_OK; - } -} - static void acpiphp_context_handler(acpi_handle handle, void *context) { /* Intentionally empty. */ @@ -179,14 +165,16 @@ static void free_bridge(struct kref *kref) } context = bridge->context; - /* Release the reference acquired by acpiphp_enumerate_slots(). */ - if (context->handler_for_func) + /* Root bridges will not have hotplug context. */ + if (context) { + /* Release the reference taken by acpiphp_enumerate_slots(). */ put_bridge(context->func->slot->bridge); + context->bridge = NULL; + acpiphp_put_context(context); + } put_device(&bridge->pci_bus->dev); pci_dev_put(bridge->pci_dev); - context->bridge = NULL; - acpiphp_put_context(context); kfree(bridge); mutex_unlock(&acpiphp_context_lock); @@ -282,28 +270,24 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data, struct acpiphp_slot *slot; struct acpiphp_func *newfunc; acpi_status status = AE_OK; - unsigned long long adr, sun; - int device, function, retval; + unsigned long long adr; + int device, function; struct pci_bus *pbus = bridge->pci_bus; - struct pci_dev *pdev; + struct pci_dev *pdev = bridge->pci_dev; u32 val; - if (!acpi_pci_check_ejectable(pbus, handle) && !is_dock_device(handle)) + if (pdev && device_is_managed_by_native_pciehp(pdev)) return AE_OK; status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr); if (ACPI_FAILURE(status)) { - warn("can't evaluate _ADR (%#x)\n", status); + acpi_handle_warn(handle, "can't evaluate _ADR (%#x)\n", status); return AE_OK; } device = (adr >> 16) & 0xffff; function = adr & 0xffff; - pdev = bridge->pci_dev; - if (pdev && device_is_managed_by_native_pciehp(pdev)) - return AE_OK; - newfunc = kzalloc(sizeof(struct acpiphp_func), GFP_KERNEL); if (!newfunc) return AE_NO_MEMORY; @@ -338,23 +322,10 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data, if (acpi_has_method(handle, "_DCK")) newfunc->flags |= FUNC_HAS_DCK; - status = acpi_evaluate_integer(handle, "_SUN", NULL, &sun); - if (ACPI_FAILURE(status)) { - /* - * use the count of the number of slots we've found - * for the number of the slot - */ - sun = bridge->nr_slots+1; - } - /* search for objects that share the same slot */ list_for_each_entry(slot, &bridge->slots, node) - if (slot->device == device) { - if (slot->sun != sun) - warn("sibling found, but _SUN doesn't match!\n"); - + if (slot->device == device) goto slot_found; - } slot = kzalloc(sizeof(struct acpiphp_slot), GFP_KERNEL); if (!slot) { @@ -364,34 +335,38 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data, slot->bridge = bridge; slot->device = device; - slot->sun = sun; INIT_LIST_HEAD(&slot->funcs); mutex_init(&slot->crit_sect); mutex_lock(&bridge_mutex); list_add_tail(&slot->node, &bridge->slots); mutex_unlock(&bridge_mutex); - bridge->nr_slots++; - dbg("found ACPI PCI Hotplug slot %llu at PCI %04x:%02x:%02x\n", - slot->sun, pci_domain_nr(pbus), pbus->number, device); + /* Register slots for ejectable funtions only. */ + if (acpi_pci_check_ejectable(pbus, handle) || is_dock_device(handle)) { + unsigned long long sun; + int retval; - retval = acpiphp_register_hotplug_slot(slot); - if (retval) { - if (retval == -EBUSY) - warn("Slot %llu already registered by another " - "hotplug driver\n", slot->sun); - else - warn("acpiphp_register_hotplug_slot failed " - "(err code = 0x%x)\n", retval); + bridge->nr_slots++; + status = acpi_evaluate_integer(handle, "_SUN", NULL, &sun); + if (ACPI_FAILURE(status)) + sun = bridge->nr_slots; - bridge->nr_slots--; - mutex_lock(&bridge_mutex); - list_del(&slot->node); - mutex_unlock(&bridge_mutex); - kfree(slot); - status = AE_OK; - goto err; + slot->sun = sun; + dbg("found ACPI PCI Hotplug slot %llu at PCI %04x:%02x:%02x\n", + slot->sun, pci_domain_nr(pbus), pbus->number, device); + + retval = acpiphp_register_hotplug_slot(slot); + if (retval) { + bridge->nr_slots--; + if (retval == -EBUSY) + warn("Slot %llu already registered by another " + "hotplug driver\n", slot->sun); + else + warn("acpiphp_register_hotplug_slot failed " + "(err code = 0x%x)\n", retval); + } + /* Even if the slot registration fails, we can still use it. */ } slot_found: @@ -421,10 +396,9 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data, status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, handle_hotplug_event, context); - if (ACPI_SUCCESS(status)) - context->handler_for_func = true; - else - err("failed to register interrupt notify handler\n"); + if (ACPI_FAILURE(status)) + acpi_handle_err(handle, + "failed to install notify handler\n"); } return AE_OK; @@ -438,18 +412,6 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data, return status; } - -/* see if it's worth looking at this bridge */ -static int detect_ejectable_slots(acpi_handle handle) -{ - int found = acpi_pci_detect_ejectable(handle); - if (!found) { - acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, - is_pci_dock_device, NULL, (void *)&found, NULL); - } - return found; -} - static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle) { struct acpiphp_context *context; @@ -473,14 +435,6 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) struct acpiphp_slot *slot; struct acpiphp_func *func; acpi_status status; - acpi_handle handle = bridge->handle; - - if (!bridge->context->handler_for_func) { - status = acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY, - handle_hotplug_event); - if (ACPI_FAILURE(status)) - err("failed to remove notify handler\n"); - } list_for_each_entry(slot, &bridge->slots, node) { list_for_each_entry(func, &slot->funcs, sibling) { @@ -488,7 +442,6 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) unregister_hotplug_dock_device(func->handle); } if (!(func->flags & FUNC_HAS_DCK)) { - func->context->handler_for_func = false; status = acpi_remove_notify_handler(func->handle, ACPI_SYSTEM_NOTIFY, handle_hotplug_event); @@ -678,9 +631,7 @@ static void check_hotplug_bridge(struct acpiphp_slot *slot, struct pci_dev *dev) list_for_each_entry(func, &slot->funcs, sibling) { if (PCI_FUNC(dev->devfn) == func->function) { - /* check if this bridge has ejectable slots */ - if ((detect_ejectable_slots(func->handle) > 0)) - dev->is_hotplug_bridge = 1; + dev->is_hotplug_bridge = 1; break; } } @@ -988,8 +939,8 @@ void acpiphp_check_host_bridge(acpi_handle handle) static void hotplug_event(acpi_handle handle, u32 type, void *data) { struct acpiphp_context *context = data; + struct acpiphp_func *func = context->func; struct acpiphp_bridge *bridge; - struct acpiphp_func *func; char objname[64]; struct acpi_buffer buffer = { .length = sizeof(objname), .pointer = objname }; @@ -999,11 +950,6 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data) if (bridge) get_bridge(bridge); - /* - * If context->func is not NULL, we are holding a reference to its - * parent bridge, so it won't go away until we drop that reference. - */ - func = context->func; mutex_unlock(&acpiphp_context_lock); acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); @@ -1041,9 +987,6 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data) case ACPI_NOTIFY_EJECT_REQUEST: /* request device eject */ dbg("%s: Device eject notify on %s\n", __func__, objname); - if (!func) - break; - if (bridge && !(bridge->flags & BRIDGE_HAS_EJ0)) break; @@ -1090,14 +1033,7 @@ static void hotplug_event_work(struct work_struct *work) acpi_scan_lock_release(); kfree(hp_work); /* allocated in handle_hotplug_event() */ - - mutex_lock(&acpiphp_context_lock); - if (context->func) - put_bridge(context->func->slot->bridge); - else - acpiphp_put_context(context); - - mutex_unlock(&acpiphp_context_lock); + put_bridge(context->func->slot->bridge); } /** @@ -1115,13 +1051,8 @@ static void handle_hotplug_event(acpi_handle handle, u32 type, void *data) mutex_lock(&acpiphp_context_lock); context = acpiphp_get_context(handle); if (context) { - if (context->func) { - get_bridge(context->func->slot->bridge); - acpiphp_put_context(context); - } else if (!context->bridge) { - acpiphp_put_context(context); - context = NULL; - } + get_bridge(context->func->slot->bridge); + acpiphp_put_context(context); } mutex_unlock(&acpiphp_context_lock); /* @@ -1142,7 +1073,6 @@ static void handle_hotplug_event(acpi_handle handle, u32 type, void *data) */ void acpiphp_enumerate_slots(struct pci_bus *bus) { - struct acpiphp_context *context; struct acpiphp_bridge *bridge; acpi_handle handle; acpi_status status; @@ -1151,7 +1081,7 @@ void acpiphp_enumerate_slots(struct pci_bus *bus) return; handle = ACPI_HANDLE(bus->bridge); - if (!handle || detect_ejectable_slots(handle) <= 0) + if (!handle) return; bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); @@ -1166,21 +1096,6 @@ void acpiphp_enumerate_slots(struct pci_bus *bus) bridge->pci_dev = pci_dev_get(bus->self); bridge->pci_bus = bus; - mutex_lock(&acpiphp_context_lock); - context = acpiphp_get_context(handle); - if (!context) { - context = acpiphp_init_context(handle); - if (!context) { - mutex_unlock(&acpiphp_context_lock); - acpi_handle_err(handle, "No hotplug context\n"); - kfree(bridge); - return; - } - } - bridge->context = context; - context->bridge = bridge; - mutex_unlock(&acpiphp_context_lock); - /* * Grab a ref to the subordinate PCI bus in case the bus is * removed via PCI core logical hotplug. The ref pins the bus @@ -1188,6 +1103,35 @@ void acpiphp_enumerate_slots(struct pci_bus *bus) */ get_device(&bus->dev); + if (!pci_is_root_bus(bridge->pci_bus)) { + struct acpiphp_context *context; + + /* + * This bridge should have been registered as a hotplug function + * under its parent, so the context has to be there. If not, we + * are in deep goo. + */ + mutex_lock(&acpiphp_context_lock); + context = acpiphp_get_context(handle); + if (WARN_ON(!context || !context->func)) { + mutex_unlock(&acpiphp_context_lock); + put_device(&bus->dev); + kfree(bridge); + return; + } + bridge->context = context; + context->bridge = bridge; + /* Get a reference to the parent bridge. */ + get_bridge(context->func->slot->bridge); + mutex_unlock(&acpiphp_context_lock); + } + + status = acpi_get_handle(bridge->handle, "_EJ0", &handle); + if (ACPI_SUCCESS(status)) { + dbg("found ejectable p2p bridge\n"); + bridge->flags |= BRIDGE_HAS_EJ0; + } + /* must be added to the list prior to calling register_slot */ mutex_lock(&bridge_mutex); list_add(&bridge->list, &bridge_list); @@ -1198,33 +1142,9 @@ void acpiphp_enumerate_slots(struct pci_bus *bus) register_slot, NULL, bridge, NULL); if (ACPI_FAILURE(status)) { acpi_handle_err(bridge->handle, "failed to register slots\n"); - goto err; + cleanup_bridge(bridge); + put_bridge(bridge); } - - if (pci_is_root_bus(bridge->pci_bus)) - return; - - if (acpi_has_method(bridge->handle, "_EJ0")) { - dbg("found ejectable p2p bridge\n"); - bridge->flags |= BRIDGE_HAS_EJ0; - } - if (context->handler_for_func) { - /* Notify handler already installed. */ - get_bridge(context->func->slot->bridge); - return; - } - - /* install notify handler for P2P bridges */ - status = acpi_install_notify_handler(bridge->handle, ACPI_SYSTEM_NOTIFY, - handle_hotplug_event, NULL); - if (ACPI_SUCCESS(status)) - return; - - acpi_handle_err(bridge->handle, "failed to register notify handler\n"); - - err: - cleanup_bridge(bridge); - put_bridge(bridge); } /* Destroy hotplug slots associated with the PCI bus */ From 7342798d0ab850a630877a362bc5a4f033100f37 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 13 Jul 2013 23:27:25 +0200 Subject: [PATCH 0257/3400] ACPI / hotplug / PCI: Drop sun field from struct acpiphp_slot If the slot unique number is passed as an additional argument to acpiphp_register_hotplug_slot(), the 'sun' field in struct acpiphp_slot is only used by ibm_[s|g]et_attention_status(), but then it's more efficient to store it in struct slot. Thus move the 'sun' field from struct acpiphp_slot to struct slot changing its data type to unsigned int in the process, and redefine acpiphp_register_hotplug_slot() to take the slot number as separate argument. Signed-off-by: Rafael J. Wysocki Tested-by: Mika Westerberg --- drivers/pci/hotplug/acpiphp.h | 5 ++--- drivers/pci/hotplug/acpiphp_core.c | 6 ++++-- drivers/pci/hotplug/acpiphp_glue.c | 7 +++---- drivers/pci/hotplug/acpiphp_ibm.c | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 76a1c979a251..4f10aec81b82 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -60,6 +60,7 @@ struct slot { struct hotplug_slot *hotplug_slot; struct acpiphp_slot *acpi_slot; struct hotplug_slot_info info; + unsigned int sun; /* ACPI _SUN (Slot User Number) value */ }; static inline const char *slot_name(struct slot *slot) @@ -106,8 +107,6 @@ struct acpiphp_slot { struct mutex crit_sect; u8 device; /* pci device# */ - - unsigned long long sun; /* ACPI _SUN (slot unique number) */ u32 flags; /* see below */ }; @@ -179,7 +178,7 @@ struct acpiphp_attention_info /* acpiphp_core.c */ int acpiphp_register_attention(struct acpiphp_attention_info*info); int acpiphp_unregister_attention(struct acpiphp_attention_info *info); -int acpiphp_register_hotplug_slot(struct acpiphp_slot *slot); +int acpiphp_register_hotplug_slot(struct acpiphp_slot *slot, unsigned int sun); void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *slot); /* acpiphp_glue.c */ diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c index ca8127950fcd..1798740f7e18 100644 --- a/drivers/pci/hotplug/acpiphp_core.c +++ b/drivers/pci/hotplug/acpiphp_core.c @@ -290,7 +290,8 @@ static void release_slot(struct hotplug_slot *hotplug_slot) } /* callback routine to initialize 'struct slot' for each slot */ -int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot) +int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot, + unsigned int sun) { struct slot *slot; int retval = -ENOMEM; @@ -317,7 +318,8 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot) slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_status(slot->acpi_slot); acpiphp_slot->slot = slot; - snprintf(name, SLOT_NAME_SIZE, "%llu", slot->acpi_slot->sun); + slot->sun = sun; + snprintf(name, SLOT_NAME_SIZE, "%u", sun); retval = pci_hp_register(slot->hotplug_slot, acpiphp_slot->bridge->pci_bus, diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index b306e993ad08..a251071b7d79 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -352,16 +352,15 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data, if (ACPI_FAILURE(status)) sun = bridge->nr_slots; - slot->sun = sun; dbg("found ACPI PCI Hotplug slot %llu at PCI %04x:%02x:%02x\n", - slot->sun, pci_domain_nr(pbus), pbus->number, device); + sun, pci_domain_nr(pbus), pbus->number, device); - retval = acpiphp_register_hotplug_slot(slot); + retval = acpiphp_register_hotplug_slot(slot, sun); if (retval) { bridge->nr_slots--; if (retval == -EBUSY) warn("Slot %llu already registered by another " - "hotplug driver\n", slot->sun); + "hotplug driver\n", sun); else warn("acpiphp_register_hotplug_slot failed " "(err code = 0x%x)\n", retval); diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c index c35e8ad6db01..8d45f6d69540 100644 --- a/drivers/pci/hotplug/acpiphp_ibm.c +++ b/drivers/pci/hotplug/acpiphp_ibm.c @@ -66,7 +66,7 @@ do { \ #define IBM_HARDWARE_ID1 "IBM37D0" #define IBM_HARDWARE_ID2 "IBM37D4" -#define hpslot_to_sun(A) (((struct slot *)((A)->private))->acpi_slot->sun) +#define hpslot_to_sun(A) (((struct slot *)((A)->private))->sun) /* union apci_descriptor - allows access to the * various device descriptors that are embedded in the From 75a33ed1b58005e455cb6533a7689ac0eb6bedd6 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 13 Jul 2013 23:27:25 +0200 Subject: [PATCH 0258/3400] ACPI / hotplug / PCI: Drop flags field from struct acpiphp_bridge The only bridge flag used by the ACPI-based PCI hotplug (ACPIPHP) code is BRIDGE_HAS_EJ0, but it is only used by the event handling function hotplug_event() and if that flag is set, the corresponding function flag FUNC_HAS_EJ0 is set as well, so that bridge flag is redundant. For this reason, drop BRIDGE_HAS_EJ0 and all code referring to it and since it is the only bridge flag defined, drop the flags field from struct acpiphp_bridge entirely. Signed-off-by: Rafael J. Wysocki Tested-by: Mika Westerberg --- drivers/pci/hotplug/acpiphp.h | 5 ----- drivers/pci/hotplug/acpiphp_glue.c | 9 --------- 2 files changed, 14 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 4f10aec81b82..990fbfd110f1 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -83,8 +83,6 @@ struct acpiphp_bridge { int nr_slots; - u32 flags; - /* This bus (host bridge) or Secondary bus (PCI-to-PCI bridge) */ struct pci_bus *pci_bus; @@ -154,9 +152,6 @@ struct acpiphp_attention_info /* ACPI _STA method value (ignore bit 4; battery present) */ #define ACPI_STA_ALL (0x0000000f) -/* bridge flags */ -#define BRIDGE_HAS_EJ0 (0x00000001) - /* slot flags */ #define SLOT_POWEREDON (0x00000001) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index a251071b7d79..5d79175b9a09 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -986,9 +986,6 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data) case ACPI_NOTIFY_EJECT_REQUEST: /* request device eject */ dbg("%s: Device eject notify on %s\n", __func__, objname); - if (bridge && !(bridge->flags & BRIDGE_HAS_EJ0)) - break; - if (!(acpiphp_disable_slot(func->slot))) acpiphp_eject_slot(func->slot); @@ -1125,12 +1122,6 @@ void acpiphp_enumerate_slots(struct pci_bus *bus) mutex_unlock(&acpiphp_context_lock); } - status = acpi_get_handle(bridge->handle, "_EJ0", &handle); - if (ACPI_SUCCESS(status)) { - dbg("found ejectable p2p bridge\n"); - bridge->flags |= BRIDGE_HAS_EJ0; - } - /* must be added to the list prior to calling register_slot */ mutex_lock(&bridge_mutex); list_add(&bridge->list, &bridge_list); From bd4674dfc5fc704837148f36af41e1e0a640dfec Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 13 Jul 2013 23:27:25 +0200 Subject: [PATCH 0259/3400] ACPI / hotplug / PCI: Embed function struct into struct acpiphp_context Since there has to be a struct acpiphp_func object for every struct acpiphp_context created by register_slot(), the struct acpiphp_func one can be embedded into the struct acpiphp_context one, which allows some code simplifications to be made. Signed-off-by: Rafael J. Wysocki Tested-by: Mika Westerberg --- drivers/pci/hotplug/acpiphp.h | 8 ++++-- drivers/pci/hotplug/acpiphp_glue.c | 44 +++++++++++------------------- 2 files changed, 22 insertions(+), 30 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 990fbfd110f1..31c84bdd2bef 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -116,7 +116,6 @@ struct acpiphp_slot { * typically 8 objects per slot (i.e. for each PCI function) */ struct acpiphp_func { - struct acpiphp_context *context; struct acpiphp_slot *slot; /* parent */ struct list_head sibling; @@ -128,11 +127,16 @@ struct acpiphp_func { struct acpiphp_context { acpi_handle handle; - struct acpiphp_func *func; + struct acpiphp_func func; struct acpiphp_bridge *bridge; unsigned int refcount; }; +static inline struct acpiphp_context *func_to_context(struct acpiphp_func *func) +{ + return container_of(func, struct acpiphp_context, func); +} + /* * struct acpiphp_attention_info - device specific attention registration * diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 5d79175b9a09..cc7453e0722e 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -128,7 +128,7 @@ static void acpiphp_put_context(struct acpiphp_context *context) if (--context->refcount) return; - WARN_ON(context->func || context->bridge); + WARN_ON(context->bridge); acpi_detach_data(context->handle, acpiphp_context_handler); kfree(context); } @@ -155,12 +155,9 @@ static void free_bridge(struct kref *kref) bridge = container_of(kref, struct acpiphp_bridge, ref); list_for_each_entry_safe(slot, next, &bridge->slots, node) { - list_for_each_entry_safe(func, tmp, &slot->funcs, sibling) { - context = func->context; - context->func = NULL; - acpiphp_put_context(context); - kfree(func); - } + list_for_each_entry_safe(func, tmp, &slot->funcs, sibling) + acpiphp_put_context(func_to_context(func)); + kfree(slot); } @@ -168,7 +165,7 @@ static void free_bridge(struct kref *kref) /* Root bridges will not have hotplug context. */ if (context) { /* Release the reference taken by acpiphp_enumerate_slots(). */ - put_bridge(context->func->slot->bridge); + put_bridge(context->func.slot->bridge); context->bridge = NULL; acpiphp_put_context(context); } @@ -190,7 +187,7 @@ static void free_bridge(struct kref *kref) static void post_dock_fixups(acpi_handle not_used, u32 event, void *data) { struct acpiphp_context *context = data; - struct pci_bus *bus = context->func->slot->bridge->pci_bus; + struct pci_bus *bus = context->func.slot->bridge->pci_bus; u32 buses; if (!bus->self) @@ -251,14 +248,14 @@ static void acpiphp_dock_init(void *data) { struct acpiphp_context *context = data; - get_bridge(context->func->slot->bridge); + get_bridge(context->func.slot->bridge); } static void acpiphp_dock_release(void *data) { struct acpiphp_context *context = data; - put_bridge(context->func->slot->bridge); + put_bridge(context->func.slot->bridge); } /* callback routine to register each ACPI PCI slot object */ @@ -288,23 +285,16 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data, device = (adr >> 16) & 0xffff; function = adr & 0xffff; - newfunc = kzalloc(sizeof(struct acpiphp_func), GFP_KERNEL); - if (!newfunc) - return AE_NO_MEMORY; - - newfunc->handle = handle; - newfunc->function = function; - mutex_lock(&acpiphp_context_lock); context = acpiphp_init_context(handle); if (!context) { mutex_unlock(&acpiphp_context_lock); acpi_handle_err(handle, "No hotplug context\n"); - kfree(newfunc); return AE_NOT_EXIST; } - newfunc->context = context; - context->func = newfunc; + newfunc = &context->func; + newfunc->handle = handle; + newfunc->function = function; mutex_unlock(&acpiphp_context_lock); if (acpi_has_method(handle, "_EJ0")) @@ -404,10 +394,8 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data, err: mutex_lock(&acpiphp_context_lock); - context->func = NULL; acpiphp_put_context(context); mutex_unlock(&acpiphp_context_lock); - kfree(newfunc); return status; } @@ -938,7 +926,7 @@ void acpiphp_check_host_bridge(acpi_handle handle) static void hotplug_event(acpi_handle handle, u32 type, void *data) { struct acpiphp_context *context = data; - struct acpiphp_func *func = context->func; + struct acpiphp_func *func = &context->func; struct acpiphp_bridge *bridge; char objname[64]; struct acpi_buffer buffer = { .length = sizeof(objname), @@ -1029,7 +1017,7 @@ static void hotplug_event_work(struct work_struct *work) acpi_scan_lock_release(); kfree(hp_work); /* allocated in handle_hotplug_event() */ - put_bridge(context->func->slot->bridge); + put_bridge(context->func.slot->bridge); } /** @@ -1047,7 +1035,7 @@ static void handle_hotplug_event(acpi_handle handle, u32 type, void *data) mutex_lock(&acpiphp_context_lock); context = acpiphp_get_context(handle); if (context) { - get_bridge(context->func->slot->bridge); + get_bridge(context->func.slot->bridge); acpiphp_put_context(context); } mutex_unlock(&acpiphp_context_lock); @@ -1109,7 +1097,7 @@ void acpiphp_enumerate_slots(struct pci_bus *bus) */ mutex_lock(&acpiphp_context_lock); context = acpiphp_get_context(handle); - if (WARN_ON(!context || !context->func)) { + if (WARN_ON(!context)) { mutex_unlock(&acpiphp_context_lock); put_device(&bus->dev); kfree(bridge); @@ -1118,7 +1106,7 @@ void acpiphp_enumerate_slots(struct pci_bus *bus) bridge->context = context; context->bridge = bridge; /* Get a reference to the parent bridge. */ - get_bridge(context->func->slot->bridge); + get_bridge(context->func.slot->bridge); mutex_unlock(&acpiphp_context_lock); } From 5a3bc573ae32a71bb9e307812d4de1bdcab6b9fb Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 13 Jul 2013 23:27:25 +0200 Subject: [PATCH 0260/3400] ACPI / hotplug / PCI: Drop handle field from struct acpiphp_func The ACPI handle stored in struct acpiphp_func is also stored in the struct acpiphp_context object containing it and it is trivial to get from a struct acpiphp_func pointer to the handle field of the outer struct acpiphp_context. Hence, the handle field of struct acpiphp_func is redundant, so drop it and provide a helper function, func_to_handle(), allowing it users to get the ACPI handle for the given struct acpiphp_func pointer. Signed-off-by: Rafael J. Wysocki Tested-by: Mika Westerberg --- drivers/pci/hotplug/acpiphp.h | 6 +++- drivers/pci/hotplug/acpiphp_glue.c | 54 +++++++++++++++++------------- 2 files changed, 36 insertions(+), 24 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 31c84bdd2bef..dbb94258da57 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -119,7 +119,6 @@ struct acpiphp_func { struct acpiphp_slot *slot; /* parent */ struct list_head sibling; - acpi_handle handle; u8 function; /* pci function# */ u32 flags; /* see below */ @@ -137,6 +136,11 @@ static inline struct acpiphp_context *func_to_context(struct acpiphp_func *func) return container_of(func, struct acpiphp_context, func); } +static inline acpi_handle func_to_handle(struct acpiphp_func *func) +{ + return func_to_context(func)->handle; +} + /* * struct acpiphp_attention_info - device specific attention registration * diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index cc7453e0722e..9e4ad6f37647 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -293,7 +293,6 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data, return AE_NOT_EXIST; } newfunc = &context->func; - newfunc->handle = handle; newfunc->function = function; mutex_unlock(&acpiphp_context_lock); @@ -425,11 +424,13 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) list_for_each_entry(slot, &bridge->slots, node) { list_for_each_entry(func, &slot->funcs, sibling) { - if (is_dock_device(func->handle)) { - unregister_hotplug_dock_device(func->handle); - } + acpi_handle handle = func_to_handle(func); + + if (is_dock_device(handle)) + unregister_hotplug_dock_device(handle); + if (!(func->flags & FUNC_HAS_DCK)) { - status = acpi_remove_notify_handler(func->handle, + status = acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY, handle_hotplug_event); if (ACPI_FAILURE(status)) @@ -457,7 +458,8 @@ static int power_on_slot(struct acpiphp_slot *slot) list_for_each_entry(func, &slot->funcs, sibling) { if (func->flags & FUNC_HAS_PS0) { dbg("%s: executing _PS0\n", __func__); - status = acpi_evaluate_object(func->handle, "_PS0", NULL, NULL); + status = acpi_evaluate_object(func_to_handle(func), + "_PS0", NULL, NULL); if (ACPI_FAILURE(status)) { warn("%s: _PS0 failed\n", __func__); retval = -1; @@ -489,7 +491,8 @@ static int power_off_slot(struct acpiphp_slot *slot) list_for_each_entry(func, &slot->funcs, sibling) { if (func->flags & FUNC_HAS_PS3) { - status = acpi_evaluate_object(func->handle, "_PS3", NULL, NULL); + status = acpi_evaluate_object(func_to_handle(func), + "_PS3", NULL, NULL); if (ACPI_FAILURE(status)) { warn("%s: _PS3 failed\n", __func__); retval = -1; @@ -543,10 +546,11 @@ static unsigned char acpiphp_max_busnr(struct pci_bus *bus) */ static int acpiphp_bus_add(struct acpiphp_func *func) { + acpi_handle handle = func_to_handle(func); struct acpi_device *device; int ret_val; - if (!acpi_bus_get_device(func->handle, &device)) { + if (!acpi_bus_get_device(handle, &device)) { dbg("bus exists... trim\n"); /* this shouldn't be in here, so remove * the bus then re-add it... @@ -554,9 +558,9 @@ static int acpiphp_bus_add(struct acpiphp_func *func) acpi_bus_trim(device); } - ret_val = acpi_bus_scan(func->handle); + ret_val = acpi_bus_scan(handle); if (!ret_val) - ret_val = acpi_bus_get_device(func->handle, &device); + ret_val = acpi_bus_get_device(handle, &device); if (ret_val) dbg("error adding bus, %x\n", -ret_val); @@ -598,7 +602,8 @@ static void acpiphp_set_acpi_region(struct acpiphp_slot *slot) params[1].type = ACPI_TYPE_INTEGER; params[1].integer.value = 1; /* _REG is optional, we don't care about if there is failure */ - acpi_evaluate_object(func->handle, "_REG", &arg_list, NULL); + acpi_evaluate_object(func_to_handle(func), "_REG", &arg_list, + NULL); } } @@ -739,9 +744,8 @@ static int disable_device(struct acpiphp_slot *slot) pci_dev_put(pdev); } - list_for_each_entry(func, &slot->funcs, sibling) { - acpiphp_bus_trim(func->handle); - } + list_for_each_entry(func, &slot->funcs, sibling) + acpiphp_bus_trim(func_to_handle(func)); slot->flags &= (~SLOT_ENABLED); @@ -763,17 +767,20 @@ static int disable_device(struct acpiphp_slot *slot) */ static unsigned int get_slot_status(struct acpiphp_slot *slot) { - acpi_status status; unsigned long long sta = 0; - u32 dvid; struct acpiphp_func *func; list_for_each_entry(func, &slot->funcs, sibling) { if (func->flags & FUNC_HAS_STA) { - status = acpi_evaluate_integer(func->handle, "_STA", NULL, &sta); + acpi_status status; + + status = acpi_evaluate_integer(func_to_handle(func), + "_STA", NULL, &sta); if (ACPI_SUCCESS(status) && sta) break; } else { + u32 dvid; + pci_bus_read_config_dword(slot->bridge->pci_bus, PCI_DEVFN(slot->device, func->function), @@ -798,12 +805,13 @@ int acpiphp_eject_slot(struct acpiphp_slot *slot) list_for_each_entry(func, &slot->funcs, sibling) { /* We don't want to call _EJ0 on non-existing functions. */ - if ((func->flags & FUNC_HAS_EJ0)) { - if (ACPI_FAILURE(acpi_evaluate_ej0(func->handle))) - return -1; - else - break; - } + if (!(func->flags & FUNC_HAS_EJ0)) + continue; + + if (ACPI_FAILURE(acpi_evaluate_ej0(func_to_handle(func)))) + return -1; + else + break; } return 0; } From 89373a55d294b53e85792dbc636015b83d492f67 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 13 Jul 2013 23:27:25 +0200 Subject: [PATCH 0261/3400] ACPI / hotplug / PCI: Drop handle field from struct acpiphp_bridge The handle field in struct acpiphp_bridge is only used by acpiphp_enumerate_slots(), but in that function the local handle variable can be used instead, so make that happen and drop handle from struct acpiphp_bridge. Signed-off-by: Rafael J. Wysocki Tested-by: Mika Westerberg --- drivers/pci/hotplug/acpiphp.h | 1 - drivers/pci/hotplug/acpiphp_glue.c | 5 ++--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index dbb94258da57..afd7110a1ca8 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -77,7 +77,6 @@ struct acpiphp_bridge { struct list_head list; struct list_head slots; struct kref ref; - acpi_handle handle; struct acpiphp_context *context; diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 9e4ad6f37647..bbbf8f4e8482 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -1084,7 +1084,6 @@ void acpiphp_enumerate_slots(struct pci_bus *bus) INIT_LIST_HEAD(&bridge->slots); kref_init(&bridge->ref); - bridge->handle = handle; bridge->pci_dev = pci_dev_get(bus->self); bridge->pci_bus = bus; @@ -1124,10 +1123,10 @@ void acpiphp_enumerate_slots(struct pci_bus *bus) mutex_unlock(&bridge_mutex); /* register all slot objects under this bridge */ - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, 1, + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, register_slot, NULL, bridge, NULL); if (ACPI_FAILURE(status)) { - acpi_handle_err(bridge->handle, "failed to register slots\n"); + acpi_handle_err(handle, "failed to register slots\n"); cleanup_bridge(bridge); put_bridge(bridge); } From bda46dbb6626c923a800b4033c86fefa613cd64c Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 13 Jul 2013 23:27:25 +0200 Subject: [PATCH 0262/3400] ACPI / hotplug / PCI: Store parent in functions and bus in slots To avoid chasing more pointers than necessary in some situations, move the bridge pointer from struct acpiphp_slot to struct acpiphp_func (and call it 'parent') and add a bus pointer to struct acpiphp_slot. Signed-off-by: Rafael J. Wysocki Tested-by: Mika Westerberg --- drivers/pci/hotplug/acpiphp.h | 5 +++-- drivers/pci/hotplug/acpiphp_core.c | 6 ++---- drivers/pci/hotplug/acpiphp_glue.c | 25 +++++++++++++------------ 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index afd7110a1ca8..7d3251d2f4ad 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -97,7 +97,7 @@ struct acpiphp_bridge { */ struct acpiphp_slot { struct list_head node; - struct acpiphp_bridge *bridge; /* parent */ + struct pci_bus *bus; struct list_head funcs; /* one slot may have different objects (i.e. for each function) */ struct slot *slot; @@ -115,7 +115,8 @@ struct acpiphp_slot { * typically 8 objects per slot (i.e. for each PCI function) */ struct acpiphp_func { - struct acpiphp_slot *slot; /* parent */ + struct acpiphp_bridge *parent; + struct acpiphp_slot *slot; struct list_head sibling; diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c index 1798740f7e18..8f20e6021611 100644 --- a/drivers/pci/hotplug/acpiphp_core.c +++ b/drivers/pci/hotplug/acpiphp_core.c @@ -321,10 +321,8 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot, slot->sun = sun; snprintf(name, SLOT_NAME_SIZE, "%u", sun); - retval = pci_hp_register(slot->hotplug_slot, - acpiphp_slot->bridge->pci_bus, - acpiphp_slot->device, - name); + retval = pci_hp_register(slot->hotplug_slot, acpiphp_slot->bus, + acpiphp_slot->device, name); if (retval == -EBUSY) goto error_hpslot; if (retval) { diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index bbbf8f4e8482..7ac315afa430 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -165,7 +165,7 @@ static void free_bridge(struct kref *kref) /* Root bridges will not have hotplug context. */ if (context) { /* Release the reference taken by acpiphp_enumerate_slots(). */ - put_bridge(context->func.slot->bridge); + put_bridge(context->func.parent); context->bridge = NULL; acpiphp_put_context(context); } @@ -187,7 +187,7 @@ static void free_bridge(struct kref *kref) static void post_dock_fixups(acpi_handle not_used, u32 event, void *data) { struct acpiphp_context *context = data; - struct pci_bus *bus = context->func.slot->bridge->pci_bus; + struct pci_bus *bus = context->func.slot->bus; u32 buses; if (!bus->self) @@ -248,14 +248,14 @@ static void acpiphp_dock_init(void *data) { struct acpiphp_context *context = data; - get_bridge(context->func.slot->bridge); + get_bridge(context->func.parent); } static void acpiphp_dock_release(void *data) { struct acpiphp_context *context = data; - put_bridge(context->func.slot->bridge); + put_bridge(context->func.parent); } /* callback routine to register each ACPI PCI slot object */ @@ -294,6 +294,7 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data, } newfunc = &context->func; newfunc->function = function; + newfunc->parent = bridge; mutex_unlock(&acpiphp_context_lock); if (acpi_has_method(handle, "_EJ0")) @@ -322,7 +323,7 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data, goto err; } - slot->bridge = bridge; + slot->bus = bridge->pci_bus; slot->device = device; INIT_LIST_HEAD(&slot->funcs); mutex_init(&slot->crit_sect); @@ -639,7 +640,7 @@ static void check_hotplug_bridge(struct acpiphp_slot *slot, struct pci_dev *dev) static int __ref enable_device(struct acpiphp_slot *slot) { struct pci_dev *dev; - struct pci_bus *bus = slot->bridge->pci_bus; + struct pci_bus *bus = slot->bus; struct acpiphp_func *func; int num, max, pass; LIST_HEAD(add_list); @@ -709,7 +710,7 @@ static int __ref enable_device(struct acpiphp_slot *slot) /* return first device in slot, acquiring a reference on it */ static struct pci_dev *dev_in_slot(struct acpiphp_slot *slot) { - struct pci_bus *bus = slot->bridge->pci_bus; + struct pci_bus *bus = slot->bus; struct pci_dev *dev; struct pci_dev *ret = NULL; @@ -781,7 +782,7 @@ static unsigned int get_slot_status(struct acpiphp_slot *slot) } else { u32 dvid; - pci_bus_read_config_dword(slot->bridge->pci_bus, + pci_bus_read_config_dword(slot->bus, PCI_DEVFN(slot->device, func->function), PCI_VENDOR_ID, &dvid); @@ -970,7 +971,7 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data) if (bridge) acpiphp_check_bridge(bridge); else - acpiphp_check_bridge(func->slot->bridge); + acpiphp_check_bridge(func->parent); break; @@ -1025,7 +1026,7 @@ static void hotplug_event_work(struct work_struct *work) acpi_scan_lock_release(); kfree(hp_work); /* allocated in handle_hotplug_event() */ - put_bridge(context->func.slot->bridge); + put_bridge(context->func.parent); } /** @@ -1043,7 +1044,7 @@ static void handle_hotplug_event(acpi_handle handle, u32 type, void *data) mutex_lock(&acpiphp_context_lock); context = acpiphp_get_context(handle); if (context) { - get_bridge(context->func.slot->bridge); + get_bridge(context->func.parent); acpiphp_put_context(context); } mutex_unlock(&acpiphp_context_lock); @@ -1113,7 +1114,7 @@ void acpiphp_enumerate_slots(struct pci_bus *bus) bridge->context = context; context->bridge = bridge; /* Get a reference to the parent bridge. */ - get_bridge(context->func.slot->bridge); + get_bridge(context->func.parent); mutex_unlock(&acpiphp_context_lock); } From 236e26245a6a437c4afbf33a5ad94cf61d1a7a7c Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 13 Jul 2013 23:27:25 +0200 Subject: [PATCH 0263/3400] ACPI / hotplug / PCI: Rework namespace scanning and trimming routines The acpiphp_bus_trim() and acpiphp_bus_add() functions need not return error codes that are never checked, so redefine them and simplify them a bit. Signed-off-by: Rafael J. Wysocki Tested-by: Mika Westerberg --- drivers/pci/hotplug/acpiphp_glue.c | 52 ++++++++---------------------- 1 file changed, 13 insertions(+), 39 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 7ac315afa430..b136eee7a93b 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -540,53 +540,27 @@ static unsigned char acpiphp_max_busnr(struct pci_bus *bus) return max; } - /** - * acpiphp_bus_add - add a new bus to acpi subsystem - * @func: acpiphp_func of the bridge + * acpiphp_bus_trim - Trim device objects in an ACPI namespace subtree. + * @handle: ACPI device object handle to start from. */ -static int acpiphp_bus_add(struct acpiphp_func *func) +static void acpiphp_bus_trim(acpi_handle handle) { - acpi_handle handle = func_to_handle(func); - struct acpi_device *device; - int ret_val; + struct acpi_device *adev = NULL; - if (!acpi_bus_get_device(handle, &device)) { - dbg("bus exists... trim\n"); - /* this shouldn't be in here, so remove - * the bus then re-add it... - */ - acpi_bus_trim(device); - } - - ret_val = acpi_bus_scan(handle); - if (!ret_val) - ret_val = acpi_bus_get_device(handle, &device); - - if (ret_val) - dbg("error adding bus, %x\n", -ret_val); - - return ret_val; + acpi_bus_get_device(handle, &adev); + if (adev) + acpi_bus_trim(adev); } - /** - * acpiphp_bus_trim - trim a bus from acpi subsystem - * @handle: handle to acpi namespace + * acpiphp_bus_add - Scan ACPI namespace subtree. + * @handle: ACPI object handle to start the scan from. */ -static int acpiphp_bus_trim(acpi_handle handle) +static void acpiphp_bus_add(acpi_handle handle) { - struct acpi_device *device; - int retval; - - retval = acpi_bus_get_device(handle, &device); - if (retval) { - dbg("acpi_device not found\n"); - return retval; - } - - acpi_bus_trim(device); - return 0; + acpiphp_bus_trim(handle); + acpi_bus_scan(handle); } static void acpiphp_set_acpi_region(struct acpiphp_slot *slot) @@ -649,7 +623,7 @@ static int __ref enable_device(struct acpiphp_slot *slot) goto err_exit; list_for_each_entry(func, &slot->funcs, sibling) - acpiphp_bus_add(func); + acpiphp_bus_add(func_to_handle(func)); num = pci_scan_slot(bus, PCI_DEVFN(slot->device, 0)); if (num == 0) { From 07bb735378919e4b5863077f5c1b4037b6ca1a99 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 13 Jul 2013 23:27:25 +0200 Subject: [PATCH 0264/3400] ACPI / hotplug / PCI: Drop redundant checks from check_hotplug_bridge() Two checks in check_hotplug_bridge() are redundant (they have been done by the caller already), so drop them. Signed-off-by: Rafael J. Wysocki Tested-by: Mika Westerberg --- drivers/pci/hotplug/acpiphp_glue.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index b136eee7a93b..f131512b7bba 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -586,16 +586,10 @@ static void check_hotplug_bridge(struct acpiphp_slot *slot, struct pci_dev *dev) { struct acpiphp_func *func; - if (!dev->subordinate) - return; - /* quirk, or pcie could set it already */ if (dev->is_hotplug_bridge) return; - if (PCI_SLOT(dev->devfn) != slot->device) - return; - list_for_each_entry(func, &slot->funcs, sibling) { if (PCI_FUNC(dev->devfn) == func->function) { dev->is_hotplug_bridge = 1; From ad21d2d046a8a6bbf1b10c04770ec835a4e379e6 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Sat, 13 Jul 2013 23:27:26 +0200 Subject: [PATCH 0265/3400] ACPI / hotplug / PCI: Consolidate slot disabling and ejecting Both acpiphp_disable_slot() and acpiphp_eject_slot() are always called together so instead of calling each separately we can consolidate them into one function acpiphp_disable_and_eject_slot() that does both (but it will return success on _EJ0 failures that were ignored in the majority of call sites anyway). [rjw: Rebased plus minor tweaks] Signed-off-by: Mika Westerberg Signed-off-by: Rafael J. Wysocki --- drivers/pci/hotplug/acpiphp.h | 3 +- drivers/pci/hotplug/acpiphp_core.c | 6 +--- drivers/pci/hotplug/acpiphp_glue.c | 50 +++++++++++------------------- 3 files changed, 20 insertions(+), 39 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 7d3251d2f4ad..fe6c79bb8eed 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -188,8 +188,7 @@ void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *slot); typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data); int acpiphp_enable_slot(struct acpiphp_slot *slot); -int acpiphp_disable_slot(struct acpiphp_slot *slot); -int acpiphp_eject_slot(struct acpiphp_slot *slot); +int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot); u8 acpiphp_get_power_status(struct acpiphp_slot *slot); u8 acpiphp_get_attention_status(struct acpiphp_slot *slot); u8 acpiphp_get_latch_status(struct acpiphp_slot *slot); diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c index 8f20e6021611..bf2203ef1308 100644 --- a/drivers/pci/hotplug/acpiphp_core.c +++ b/drivers/pci/hotplug/acpiphp_core.c @@ -155,15 +155,11 @@ static int enable_slot(struct hotplug_slot *hotplug_slot) static int disable_slot(struct hotplug_slot *hotplug_slot) { struct slot *slot = hotplug_slot->private; - int retval; dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); /* disable the specified slot */ - retval = acpiphp_disable_slot(slot->acpi_slot); - if (!retval) - retval = acpiphp_eject_slot(slot->acpi_slot); - return retval; + return acpiphp_disable_and_eject_slot(slot->acpi_slot); } diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index f131512b7bba..6db790ebd1eb 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -764,27 +764,6 @@ static unsigned int get_slot_status(struct acpiphp_slot *slot) return (unsigned int)sta; } -/** - * acpiphp_eject_slot - physically eject the slot - * @slot: ACPI PHP slot - */ -int acpiphp_eject_slot(struct acpiphp_slot *slot) -{ - struct acpiphp_func *func; - - list_for_each_entry(func, &slot->funcs, sibling) { - /* We don't want to call _EJ0 on non-existing functions. */ - if (!(func->flags & FUNC_HAS_EJ0)) - continue; - - if (ACPI_FAILURE(acpi_evaluate_ej0(func_to_handle(func)))) - return -1; - else - break; - } - return 0; -} - /** * acpiphp_check_bridge - re-enumerate devices * @bridge: where to begin re-enumeration @@ -805,13 +784,11 @@ static int acpiphp_check_bridge(struct acpiphp_bridge *bridge) if (slot->flags & SLOT_ENABLED) { if (status == ACPI_STA_ALL) continue; - retval = acpiphp_disable_slot(slot); - if (retval) { - err("Error occurred in disabling\n"); + + retval = acpiphp_disable_and_eject_slot(slot); + if (retval) goto err_exit; - } else { - acpiphp_eject_slot(slot); - } + disabled++; } else { if (status != ACPI_STA_ALL) @@ -951,9 +928,7 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data) case ACPI_NOTIFY_EJECT_REQUEST: /* request device eject */ dbg("%s: Device eject notify on %s\n", __func__, objname); - if (!(acpiphp_disable_slot(func->slot))) - acpiphp_eject_slot(func->slot); - + acpiphp_disable_and_eject_slot(func->slot); break; case ACPI_NOTIFY_FREQUENCY_MISMATCH: @@ -1148,11 +1123,12 @@ int acpiphp_enable_slot(struct acpiphp_slot *slot) } /** - * acpiphp_disable_slot - power off slot + * acpiphp_disable_and_eject_slot - power off and eject slot * @slot: ACPI PHP slot */ -int acpiphp_disable_slot(struct acpiphp_slot *slot) +int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot) { + struct acpiphp_func *func; int retval = 0; mutex_lock(&slot->crit_sect); @@ -1167,6 +1143,16 @@ int acpiphp_disable_slot(struct acpiphp_slot *slot) if (retval) goto err_exit; + list_for_each_entry(func, &slot->funcs, sibling) + if (func->flags & FUNC_HAS_EJ0) { + acpi_handle handle = func_to_handle(func); + + if (ACPI_FAILURE(acpi_evaluate_ej0(handle))) + acpi_handle_err(handle, "_EJ0 failed\n"); + + break; + } + err_exit: mutex_unlock(&slot->crit_sect); return retval; From 5c8d0e1dc475f0f35b5a774c92c68c3f7dbd3f5f Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 13 Jul 2013 23:27:26 +0200 Subject: [PATCH 0266/3400] ACPI / hotplug / PCI: Do not queue up event handling work items in vain Modify handle_hotplug_event() to avoid queing up the execution of handle_hotplug_event_work_fn() as a work item on kacpi_hotplug_wq for non-hotplug events, such as ACPI_NOTIFY_DEVICE_WAKE. Move the code printing diagnostic messages for those events into handle_hotplug_event(). In addition to that, remove the bogus comment about how the core should distinguish between hotplug and non-hotplug events and queue them up on different workqueues. The core clearly cannot know in advance what events will be interesting to the given caller of acpi_install_notify_handler(). Signed-off-by: Rafael J. Wysocki Tested-by: Mika Westerberg --- drivers/pci/hotplug/acpiphp_glue.c | 64 ++++++++++++++---------------- 1 file changed, 29 insertions(+), 35 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 6db790ebd1eb..44191db1f050 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -920,36 +920,11 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data) break; - case ACPI_NOTIFY_DEVICE_WAKE: - /* wake event */ - dbg("%s: Device wake notify on %s\n", __func__, objname); - break; - case ACPI_NOTIFY_EJECT_REQUEST: /* request device eject */ dbg("%s: Device eject notify on %s\n", __func__, objname); acpiphp_disable_and_eject_slot(func->slot); break; - - case ACPI_NOTIFY_FREQUENCY_MISMATCH: - printk(KERN_ERR "Device %s cannot be configured due" - " to a frequency mismatch\n", objname); - break; - - case ACPI_NOTIFY_BUS_MODE_MISMATCH: - printk(KERN_ERR "Device %s cannot be configured due" - " to a bus mode mismatch\n", objname); - break; - - case ACPI_NOTIFY_POWER_FAULT: - printk(KERN_ERR "Device %s has suffered a power fault\n", - objname); - break; - - default: - warn("notify_handler: unknown event type 0x%x for %s\n", type, - objname); - break; } if (bridge) @@ -984,23 +959,42 @@ static void handle_hotplug_event(acpi_handle handle, u32 type, void *data) { struct acpiphp_context *context; + switch (type) { + case ACPI_NOTIFY_BUS_CHECK: + case ACPI_NOTIFY_DEVICE_CHECK: + case ACPI_NOTIFY_EJECT_REQUEST: + break; + + case ACPI_NOTIFY_DEVICE_WAKE: + return; + + case ACPI_NOTIFY_FREQUENCY_MISMATCH: + acpi_handle_err(handle, "Device cannot be configured due " + "to a frequency mismatch\n"); + return; + + case ACPI_NOTIFY_BUS_MODE_MISMATCH: + acpi_handle_err(handle, "Device cannot be configured due " + "to a bus mode mismatch\n"); + return; + + case ACPI_NOTIFY_POWER_FAULT: + acpi_handle_err(handle, "Device has suffered a power fault\n"); + return; + + default: + acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type); + return; + } + mutex_lock(&acpiphp_context_lock); context = acpiphp_get_context(handle); if (context) { get_bridge(context->func.parent); acpiphp_put_context(context); + alloc_acpi_hp_work(handle, type, context, hotplug_event_work); } mutex_unlock(&acpiphp_context_lock); - /* - * Currently the code adds all hotplug events to the kacpid_wq - * queue when it should add hotplug events to the kacpi_hotplug_wq. - * The proper way to fix this is to reorganize the code so that - * drivers (dock, etc.) do not call acpi_os_execute(), etc. - * For now just re-add this work to the kacpi_hotplug_wq so we - * don't deadlock on hotplug actions. - */ - if (context) - alloc_acpi_hp_work(handle, type, context, hotplug_event_work); } /* From bc805a55392a7cb3e9b1251d00449c70e3967fc5 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 13 Jul 2013 23:27:26 +0200 Subject: [PATCH 0267/3400] ACPI / hotplug / PCI: Do not exectute _PS0 and _PS3 directly The ACPI-based PCI hotplug (acpiphp) core code need not and really should not execute _PS0 and _PS3 directly for devices it handles. First of all, it is not necessary to put devices into D3 after acpi_bus_trim() has walked through them, because acpi_device_unregister() invoked by it puts each device into D3cold before returning. Thus after disable_device() the slot should be powered down already. Second, calling _PS0 directly on ACPI device objects may not be appropriate, because it may require power resources to be set up in a specific way in advance and that must be taken care of by the ACPI core. Thus modify acpiphp_bus_add() to power up the device using the appropriate interface after it has run acpi_bus_scan() on its handle. After that, the functions executing _PS0 and _PS3, power_on_slot() and power_off_slot(), are not necessary any more, so drop them and update the code calling them accordingly. Also drop the function flags related to device power states, since they aren't useful any more too. Signed-off-by: Rafael J. Wysocki Tested-by: Mika Westerberg --- drivers/pci/hotplug/acpiphp.h | 7 +- drivers/pci/hotplug/acpiphp_glue.c | 106 +++-------------------------- 2 files changed, 10 insertions(+), 103 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index fe6c79bb8eed..ca2c91df3d1a 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -162,7 +162,6 @@ struct acpiphp_attention_info /* slot flags */ -#define SLOT_POWEREDON (0x00000001) #define SLOT_ENABLED (0x00000002) #define SLOT_MULTIFUNCTION (0x00000004) @@ -170,11 +169,7 @@ struct acpiphp_attention_info #define FUNC_HAS_STA (0x00000001) #define FUNC_HAS_EJ0 (0x00000002) -#define FUNC_HAS_PS0 (0x00000010) -#define FUNC_HAS_PS1 (0x00000020) -#define FUNC_HAS_PS2 (0x00000040) -#define FUNC_HAS_PS3 (0x00000080) -#define FUNC_HAS_DCK (0x00000100) +#define FUNC_HAS_DCK (0x00000004) /* function prototypes */ diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 44191db1f050..b6691cc8230b 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -303,12 +303,6 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data, if (acpi_has_method(handle, "_STA")) newfunc->flags |= FUNC_HAS_STA; - if (acpi_has_method(handle, "_PS0")) - newfunc->flags |= FUNC_HAS_PS0; - - if (acpi_has_method(handle, "_PS3")) - newfunc->flags |= FUNC_HAS_PS3; - if (acpi_has_method(handle, "_DCK")) newfunc->flags |= FUNC_HAS_DCK; @@ -366,7 +360,7 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data, if (pci_bus_read_dev_vendor_id(pbus, PCI_DEVFN(device, function), &val, 60*1000)) - slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON); + slot->flags |= SLOT_ENABLED; if (is_dock_device(handle)) { /* we don't want to call this device's _EJ0 @@ -446,73 +440,6 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) mutex_unlock(&bridge_mutex); } -static int power_on_slot(struct acpiphp_slot *slot) -{ - acpi_status status; - struct acpiphp_func *func; - int retval = 0; - - /* if already enabled, just skip */ - if (slot->flags & SLOT_POWEREDON) - goto err_exit; - - list_for_each_entry(func, &slot->funcs, sibling) { - if (func->flags & FUNC_HAS_PS0) { - dbg("%s: executing _PS0\n", __func__); - status = acpi_evaluate_object(func_to_handle(func), - "_PS0", NULL, NULL); - if (ACPI_FAILURE(status)) { - warn("%s: _PS0 failed\n", __func__); - retval = -1; - goto err_exit; - } else - break; - } - } - - /* TBD: evaluate _STA to check if the slot is enabled */ - - slot->flags |= SLOT_POWEREDON; - - err_exit: - return retval; -} - - -static int power_off_slot(struct acpiphp_slot *slot) -{ - acpi_status status; - struct acpiphp_func *func; - - int retval = 0; - - /* if already disabled, just skip */ - if ((slot->flags & SLOT_POWEREDON) == 0) - goto err_exit; - - list_for_each_entry(func, &slot->funcs, sibling) { - if (func->flags & FUNC_HAS_PS3) { - status = acpi_evaluate_object(func_to_handle(func), - "_PS3", NULL, NULL); - if (ACPI_FAILURE(status)) { - warn("%s: _PS3 failed\n", __func__); - retval = -1; - goto err_exit; - } else - break; - } - } - - /* TBD: evaluate _STA to check if the slot is disabled */ - - slot->flags &= (~SLOT_POWEREDON); - - err_exit: - return retval; -} - - - /** * acpiphp_max_busnr - return the highest reserved bus number under the given bus. * @bus: bus to start search with @@ -559,8 +486,13 @@ static void acpiphp_bus_trim(acpi_handle handle) */ static void acpiphp_bus_add(acpi_handle handle) { + struct acpi_device *adev = NULL; + acpiphp_bus_trim(handle); acpi_bus_scan(handle); + acpi_bus_get_device(handle, &adev); + if (adev) + acpi_device_set_power(adev, ACPI_STATE_D0); } static void acpiphp_set_acpi_region(struct acpiphp_slot *slot) @@ -1095,23 +1027,8 @@ int acpiphp_enable_slot(struct acpiphp_slot *slot) int retval; mutex_lock(&slot->crit_sect); - - /* wake up all functions */ - retval = power_on_slot(slot); - if (retval) - goto err_exit; - - if (get_slot_status(slot) == ACPI_STA_ALL) { - /* configure all functions */ - retval = enable_device(slot); - if (retval) - power_off_slot(slot); - } else { - dbg("%s: Slot status is not ACPI_STA_ALL\n", __func__); - power_off_slot(slot); - } - - err_exit: + /* configure all functions */ + retval = enable_device(slot); mutex_unlock(&slot->crit_sect); return retval; } @@ -1132,11 +1049,6 @@ int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot) if (retval) goto err_exit; - /* power off all functions */ - retval = power_off_slot(slot); - if (retval) - goto err_exit; - list_for_each_entry(func, &slot->funcs, sibling) if (func->flags & FUNC_HAS_EJ0) { acpi_handle handle = func_to_handle(func); @@ -1159,7 +1071,7 @@ int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot) */ u8 acpiphp_get_power_status(struct acpiphp_slot *slot) { - return (slot->flags & SLOT_POWEREDON); + return (slot->flags & SLOT_ENABLED); } From 55502ddb2d83ada0661733361ec14b9cbef157a5 Mon Sep 17 00:00:00 2001 From: "Kirill A. Shutemov" Date: Sat, 13 Jul 2013 23:27:26 +0200 Subject: [PATCH 0268/3400] ACPI / hotplug / PCI: Do not check SLOT_ENABLED in enable_device() With Thunderbolt you can daisy chain devices: connect new devices to an already plugged one. In that case the "hotplug slot" is already enabled, but we still want to look for new PCI devices behind it. Reuse enable_device() to scan for new PCI devices on enabled slots and push the SLOT_ENABLED check up into acpiphp_enable_slot(). [rjw: Rebased, modified the changelog] Signed-off-by: Kirill A. Shutemov Signed-off-by: Mika Westerberg Signed-off-by: Rafael J. Wysocki --- drivers/pci/hotplug/acpiphp_glue.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index b6691cc8230b..c7a668e1fc12 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -545,9 +545,6 @@ static int __ref enable_device(struct acpiphp_slot *slot) int num, max, pass; LIST_HEAD(add_list); - if (slot->flags & SLOT_ENABLED) - goto err_exit; - list_for_each_entry(func, &slot->funcs, sibling) acpiphp_bus_add(func_to_handle(func)); @@ -1024,11 +1021,14 @@ void acpiphp_remove_slots(struct pci_bus *bus) */ int acpiphp_enable_slot(struct acpiphp_slot *slot) { - int retval; + int retval = 0; mutex_lock(&slot->crit_sect); + /* configure all functions */ - retval = enable_device(slot); + if (!(slot->flags & SLOT_ENABLED)) + retval = enable_device(slot); + mutex_unlock(&slot->crit_sect); return retval; } From b91182a67c53db227e34921838dd683090ecfabc Mon Sep 17 00:00:00 2001 From: "Kirill A. Shutemov" Date: Sat, 13 Jul 2013 23:27:26 +0200 Subject: [PATCH 0269/3400] ACPI / hotplug / PCI: Allow slots without new devices to be rescanned Currently, enable_device() checks the return value of pci_scan_slot() and returns immediately if that's 0 (meaning that no new functions have been found in the slot). However, if one of the functions in the slot is a bridge, some new devices may appear below it even if the bridge itself is present continuously, so it generally is necessary to do the rescan anyway just in case. [In particular, that's necessary with the Thunderbolt daisy chaining in which case new devices may be connected to the existing ones down the chain.] The correctness of this change relies on the ability of pcibios_resource_survey_bus() to detect if it has already been called for the given bus and to skip it if so. Failure to do that will lead to resource allocation conflicts. [rjw: Changelog] Signed-off-by: Kirill A. Shutemov Signed-off-by: Mika Westerberg Signed-off-by: Rafael J. Wysocki --- drivers/pci/hotplug/acpiphp_glue.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index c7a668e1fc12..21a6269501e1 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -542,18 +542,13 @@ static int __ref enable_device(struct acpiphp_slot *slot) struct pci_dev *dev; struct pci_bus *bus = slot->bus; struct acpiphp_func *func; - int num, max, pass; + int max, pass; LIST_HEAD(add_list); list_for_each_entry(func, &slot->funcs, sibling) acpiphp_bus_add(func_to_handle(func)); - num = pci_scan_slot(bus, PCI_DEVFN(slot->device, 0)); - if (num == 0) { - /* Maybe only part of funcs are added. */ - dbg("No new device found\n"); - goto err_exit; - } + pci_scan_slot(bus, PCI_DEVFN(slot->device, 0)); max = acpiphp_max_busnr(bus); for (pass = 0; pass < 2; pass++) { @@ -599,8 +594,6 @@ static int __ref enable_device(struct acpiphp_slot *slot) } } - - err_exit: return 0; } From 4ebe34503baa0644c9352bcd76d4cf573bffe206 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 16 Jul 2013 22:10:35 +0200 Subject: [PATCH 0270/3400] ACPI / hotplug / PCI: Check for new devices on enabled slots The current implementation of acpiphp_check_bridge() is pretty dumb: - It enables a slot if it's not enabled and the slot status is ACPI_STA_ALL. - It disables a slot if it's enabled and the slot status is not ACPI_STA_ALL. This behavior is not sufficient to handle the Thunderbolt daisy chaining case properly, however, because in that case the bus behind the already enabled slot needs to be rescanned for new devices. For this reason, modify acpiphp_check_bridge() so that slots are disabled and stopped if they are not in the ACPI_STA_ALL state. For slots in the ACPI_STA_ALL state, devices behind them that don't respond are trimmed using a new function, trim_stale_devices(), introduced specifically for this purpose. That function walks the given bus and checks each device on it. If the device doesn't respond, it is assumed to be gone and is removed. Once all of the stale devices directy behind the slot have been removed, acpiphp_check_bridge() will start looking for new devices that might have appeared on the given bus. It will do that even if the slot is already enabled (SLOT_ENABLED is set for it). In addition to that, make the bus check notification ignore SLOT_ENABLED and go for enable_device() directly if bridge is NULL, so that devices behind the slot are re-enumerated in that case too. This change is based on earlier patches from Kirill A Shutemov and Mika Westerberg. Signed-off-by: Rafael J. Wysocki Tested-by: Mika Westerberg --- drivers/pci/hotplug/acpiphp_glue.c | 87 ++++++++++++++++++++---------- 1 file changed, 60 insertions(+), 27 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 21a6269501e1..e2e5e3088816 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -686,6 +687,45 @@ static unsigned int get_slot_status(struct acpiphp_slot *slot) return (unsigned int)sta; } +/** + * trim_stale_devices - remove PCI devices that are not responding. + * @dev: PCI device to start walking the hierarchy from. + */ +static void trim_stale_devices(struct pci_dev *dev) +{ + acpi_handle handle = ACPI_HANDLE(&dev->dev); + struct pci_bus *bus = dev->subordinate; + bool alive = false; + + if (handle) { + acpi_status status; + unsigned long long sta; + + status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); + alive = ACPI_SUCCESS(status) && sta == ACPI_STA_ALL; + } + if (!alive) { + u32 v; + + /* Check if the device responds. */ + alive = pci_bus_read_dev_vendor_id(dev->bus, dev->devfn, &v, 0); + } + if (!alive) { + pci_stop_and_remove_bus_device(dev); + if (handle) + acpiphp_bus_trim(handle); + } else if (bus) { + struct pci_dev *child, *tmp; + + /* The device is a bridge. so check the bus below it. */ + pm_runtime_get_sync(&dev->dev); + list_for_each_entry_safe(child, tmp, &bus->devices, bus_list) + trim_stale_devices(child); + + pm_runtime_put(&dev->dev); + } +} + /** * acpiphp_check_bridge - re-enumerate devices * @bridge: where to begin re-enumeration @@ -693,41 +733,30 @@ static unsigned int get_slot_status(struct acpiphp_slot *slot) * Iterate over all slots under this bridge and make sure that if a * card is present they are enabled, and if not they are disabled. */ -static int acpiphp_check_bridge(struct acpiphp_bridge *bridge) +static void acpiphp_check_bridge(struct acpiphp_bridge *bridge) { struct acpiphp_slot *slot; - int retval = 0; - int enabled, disabled; - - enabled = disabled = 0; list_for_each_entry(slot, &bridge->slots, node) { - unsigned int status = get_slot_status(slot); - if (slot->flags & SLOT_ENABLED) { - if (status == ACPI_STA_ALL) - continue; + struct pci_bus *bus = slot->bus; + struct pci_dev *dev, *tmp; - retval = acpiphp_disable_and_eject_slot(slot); - if (retval) - goto err_exit; + mutex_lock(&slot->crit_sect); + /* wake up all functions */ + if (get_slot_status(slot) == ACPI_STA_ALL) { + /* remove stale devices if any */ + list_for_each_entry_safe(dev, tmp, &bus->devices, + bus_list) + if (PCI_SLOT(dev->devfn) == slot->device) + trim_stale_devices(dev); - disabled++; + /* configure all functions */ + enable_device(slot); } else { - if (status != ACPI_STA_ALL) - continue; - retval = acpiphp_enable_slot(slot); - if (retval) { - err("Error occurred in enabling\n"); - goto err_exit; - } - enabled++; + disable_device(slot); } + mutex_unlock(&slot->crit_sect); } - - dbg("%s: %d enabled, %d disabled\n", __func__, enabled, disabled); - - err_exit: - return retval; } static void acpiphp_set_hpp_values(struct pci_bus *bus) @@ -828,7 +857,11 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data) ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL, NULL); } else { - acpiphp_enable_slot(func->slot); + struct acpiphp_slot *slot = func->slot; + + mutex_lock(&slot->crit_sect); + enable_device(slot); + mutex_unlock(&slot->crit_sect); } break; From c38f82cf1b7dc8aad2bce8e30113fd6aa3159dab Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Sat, 13 Jul 2013 23:27:26 +0200 Subject: [PATCH 0271/3400] ACPI / hotplug / PCI: Get rid of unused constants in acpiphp.h Drop some unused symbols from acpiphp.h and redefine SLOT_ENABLED (which is the only slot flag now) as 1. [rjw: Redefinition of SLOT_ENABLED, changelog] Signed-off-by: Mika Westerberg Signed-off-by: Kirill A. Shutemov Signed-off-by: Rafael J. Wysocki --- drivers/pci/hotplug/acpiphp.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index ca2c91df3d1a..f4e028924667 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -154,16 +154,12 @@ struct acpiphp_attention_info struct module *owner; }; -/* PCI bus bridge HID */ -#define ACPI_PCI_HOST_HID "PNP0A03" - /* ACPI _STA method value (ignore bit 4; battery present) */ #define ACPI_STA_ALL (0x0000000f) /* slot flags */ -#define SLOT_ENABLED (0x00000002) -#define SLOT_MULTIFUNCTION (0x00000004) +#define SLOT_ENABLED (0x00000001) /* function flags */ From 1ad3790ac7cfac699993a3f2e189a69a82f8fe4d Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Sat, 13 Jul 2013 23:27:26 +0200 Subject: [PATCH 0272/3400] ACPI / hotplug / PCI: Sanitize acpiphp_get_(latch)|(adapter)_status() There is no need for a temporary variable and all the tricks with ternary operators in acpiphp_get_(latch)|(adapter)_status(). Change those functions to be a bit more straightforward. [rjw: Changelog] Signed-off-by: Kirill A. Shutemov Signed-off-by: Mika Westerberg Signed-off-by: Rafael J. Wysocki --- drivers/pci/hotplug/acpiphp_glue.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index e2e5e3088816..d8748a4a18a7 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -1107,11 +1107,7 @@ u8 acpiphp_get_power_status(struct acpiphp_slot *slot) */ u8 acpiphp_get_latch_status(struct acpiphp_slot *slot) { - unsigned int sta; - - sta = get_slot_status(slot); - - return (sta & ACPI_STA_DEVICE_UI) ? 0 : 1; + return !(get_slot_status(slot) & ACPI_STA_DEVICE_UI); } @@ -1121,9 +1117,5 @@ u8 acpiphp_get_latch_status(struct acpiphp_slot *slot) */ u8 acpiphp_get_adapter_status(struct acpiphp_slot *slot) { - unsigned int sta; - - sta = get_slot_status(slot); - - return (sta == 0) ? 0 : 1; + return !!get_slot_status(slot); } From a1d0abcea845730c4ff2f47897e28c2f11c79d4f Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 13 Jul 2013 23:27:26 +0200 Subject: [PATCH 0273/3400] ACPI / hotplug / PCI: Redefine enable_device() and disable_device() Notice that functions enable_device() and disable_device() cannot fail and their return values are ignored in the majority of places, so redefine them as void and use the opportunity to change their names to enable_slot() and disable_slot(), respectively, which much better reflects what they do. Signed-off-by: Rafael J. Wysocki Tested-by: Mika Westerberg --- drivers/pci/hotplug/acpiphp_glue.c | 33 +++++++++++------------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index d8748a4a18a7..18c9e54990ee 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -532,13 +532,13 @@ static void check_hotplug_bridge(struct acpiphp_slot *slot, struct pci_dev *dev) } /** - * enable_device - enable, configure a slot + * enable_slot - enable, configure a slot * @slot: slot to be enabled * * This function should be called per *physical slot*, * not per each slot object in ACPI namespace. */ -static int __ref enable_device(struct acpiphp_slot *slot) +static void __ref enable_slot(struct acpiphp_slot *slot) { struct pci_dev *dev; struct pci_bus *bus = slot->bus; @@ -556,6 +556,7 @@ static int __ref enable_device(struct acpiphp_slot *slot) list_for_each_entry(dev, &bus->devices, bus_list) { if (PCI_SLOT(dev->devfn) != slot->device) continue; + if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) { max = pci_scan_bridge(bus, dev, max, pass); @@ -594,8 +595,6 @@ static int __ref enable_device(struct acpiphp_slot *slot) continue; } } - - return 0; } /* return first device in slot, acquiring a reference on it */ @@ -617,16 +616,16 @@ static struct pci_dev *dev_in_slot(struct acpiphp_slot *slot) } /** - * disable_device - disable a slot + * disable_slot - disable a slot * @slot: ACPI PHP slot */ -static int disable_device(struct acpiphp_slot *slot) +static void disable_slot(struct acpiphp_slot *slot) { struct acpiphp_func *func; struct pci_dev *pdev; /* - * enable_device() enumerates all functions in this device via + * enable_slot() enumerates all functions in this device via * pci_scan_slot(), whether they have associated ACPI hotplug * methods (_EJ0, etc.) or not. Therefore, we remove all functions * here. @@ -640,8 +639,6 @@ static int disable_device(struct acpiphp_slot *slot) acpiphp_bus_trim(func_to_handle(func)); slot->flags &= (~SLOT_ENABLED); - - return 0; } @@ -751,9 +748,9 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge) trim_stale_devices(dev); /* configure all functions */ - enable_device(slot); + enable_slot(slot); } else { - disable_device(slot); + disable_slot(slot); } mutex_unlock(&slot->crit_sect); } @@ -860,7 +857,7 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data) struct acpiphp_slot *slot = func->slot; mutex_lock(&slot->crit_sect); - enable_device(slot); + enable_slot(slot); mutex_unlock(&slot->crit_sect); } break; @@ -1047,16 +1044,13 @@ void acpiphp_remove_slots(struct pci_bus *bus) */ int acpiphp_enable_slot(struct acpiphp_slot *slot) { - int retval = 0; - mutex_lock(&slot->crit_sect); - /* configure all functions */ if (!(slot->flags & SLOT_ENABLED)) - retval = enable_device(slot); + enable_slot(slot); mutex_unlock(&slot->crit_sect); - return retval; + return 0; } /** @@ -1071,9 +1065,7 @@ int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot) mutex_lock(&slot->crit_sect); /* unconfigure all functions */ - retval = disable_device(slot); - if (retval) - goto err_exit; + disable_slot(slot); list_for_each_entry(func, &slot->funcs, sibling) if (func->flags & FUNC_HAS_EJ0) { @@ -1085,7 +1077,6 @@ int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot) break; } - err_exit: mutex_unlock(&slot->crit_sect); return retval; } From ff181e5a4f6b536e5f3f1601cd5c54e792cd9abc Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 13 Jul 2013 23:27:26 +0200 Subject: [PATCH 0274/3400] ACPI / hotplug / PCI: Clean up bridge_mutex usage Do not acquire bridge_mutex around the addition of a slot to its bridge's list of slots and arount the addition of a function to its slot's list of functions, because that doesn't help anything right now (those lists are walked without any locking anyway). However, acquire bridge_mutex around the list walk in acpiphp_remove_slots() and use list_for_each_entry() there, because we terminate the walk as soon as we find the first matching entry. This prevents that list walk from colliding with bridge addition and removal. Signed-off-by: Rafael J. Wysocki Tested-by: Mika Westerberg --- drivers/pci/hotplug/acpiphp_glue.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 18c9e54990ee..e4b7f2bc94df 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -323,9 +323,7 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data, INIT_LIST_HEAD(&slot->funcs); mutex_init(&slot->crit_sect); - mutex_lock(&bridge_mutex); list_add_tail(&slot->node, &bridge->slots); - mutex_unlock(&bridge_mutex); /* Register slots for ejectable funtions only. */ if (acpi_pci_check_ejectable(pbus, handle) || is_dock_device(handle)) { @@ -355,9 +353,7 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data, slot_found: newfunc->slot = slot; - mutex_lock(&bridge_mutex); list_add_tail(&newfunc->sibling, &slot->funcs); - mutex_unlock(&bridge_mutex); if (pci_bus_read_dev_vendor_id(pbus, PCI_DEVFN(device, function), &val, 60*1000)) @@ -1025,17 +1021,21 @@ void acpiphp_enumerate_slots(struct pci_bus *bus) /* Destroy hotplug slots associated with the PCI bus */ void acpiphp_remove_slots(struct pci_bus *bus) { - struct acpiphp_bridge *bridge, *tmp; + struct acpiphp_bridge *bridge; if (acpiphp_disabled) return; - list_for_each_entry_safe(bridge, tmp, &bridge_list, list) + mutex_lock(&bridge_mutex); + list_for_each_entry(bridge, &bridge_list, list) if (bridge->pci_bus == bus) { + mutex_unlock(&bridge_mutex); cleanup_bridge(bridge); put_bridge(bridge); - break; + return; } + + mutex_unlock(&bridge_mutex); } /** From 2d8b1d566a5f4874f4d92361f5cdbb50baa396f8 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Sat, 13 Jul 2013 20:09:59 +0300 Subject: [PATCH 0275/3400] ACPI / hotplug / PCI: Get rid of check_sub_bridges() Now that acpiphp_check_bridge() always enumerates devices behind the bridge, there is no need to do that for each sub-bridge anymore like it is done in the current ACPI-based PCI hotplug (ACPIPHP) code. Given this we don't need check_sub_bridges() anymore, so drop that function completely. This also simplifies the ACPIPHP code a bit. Signed-off-by: Mika Westerberg Signed-off-by: Rafael J. Wysocki --- drivers/pci/hotplug/acpiphp_glue.c | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index e4b7f2bc94df..05e463db11de 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -788,25 +788,6 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus) * ACPI event handlers */ -static acpi_status -check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) -{ - struct acpiphp_bridge *bridge; - char objname[64]; - struct acpi_buffer buffer = { .length = sizeof(objname), - .pointer = objname }; - - bridge = acpiphp_handle_to_bridge(handle); - if (bridge) { - acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); - dbg("%s: re-enumerating slots under %s\n", - __func__, objname); - acpiphp_check_bridge(bridge); - put_bridge(bridge); - } - return AE_OK ; -} - void acpiphp_check_host_bridge(acpi_handle handle) { struct acpiphp_bridge *bridge; @@ -816,9 +797,6 @@ void acpiphp_check_host_bridge(acpi_handle handle) acpiphp_check_bridge(bridge); put_bridge(bridge); } - - acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, - ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL, NULL); } static void hotplug_event(acpi_handle handle, u32 type, void *data) @@ -846,9 +824,6 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data) dbg("%s: re-enumerating slots under %s\n", __func__, objname); if (bridge) { acpiphp_check_bridge(bridge); - acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, - ACPI_UINT32_MAX, check_sub_bridges, - NULL, NULL, NULL); } else { struct acpiphp_slot *slot = func->slot; From 2cf9f5bcc8d8cb31d6ea7baebac5056f39fb4f40 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Mon, 22 Jul 2013 16:08:16 +0800 Subject: [PATCH 0276/3400] ACPICA: Add acpi_update_interfaces() public interface Add new API to allow OSPM to disable/enable specific types of _OSI interface strings. ACPICA does not have the knowledge about whether an _OSI interface string is an OS vendor string or a feature group string and there isn't any API interface to allow OSPM to install a new interface string as a feature group string. This patch simply adds all feature group strings defined by ACPI specification into the acpi_default_supported_interfaces with ACPI_OSI_FEATURE flag set to fix this gap. This patch also adds codes to keep their default states as ACPI_OSI_INVALID before the initialization and after the termination. Signed-off-by: Lv Zheng Reviewed-by: Zhang Rui Signed-off-by: Bob Moore Acked-by: Len Brown Signed-off-by: Rafael J. Wysocki Conflicts: include/acpi/actypes.h (with commit 242b228) --- drivers/acpi/acpica/aclocal.h | 3 ++ drivers/acpi/acpica/acutils.h | 2 + drivers/acpi/acpica/utosi.c | 77 +++++++++++++++++++++++++++++------ drivers/acpi/acpica/utxface.c | 29 +++++++++++++ include/acpi/acpixf.h | 2 + include/acpi/actypes.h | 14 +++++++ 6 files changed, 114 insertions(+), 13 deletions(-) diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index d4a4901637cd..b0e3d15cfe96 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -942,6 +942,9 @@ struct acpi_interface_info { #define ACPI_OSI_INVALID 0x01 #define ACPI_OSI_DYNAMIC 0x02 +#define ACPI_OSI_FEATURE 0x04 +#define ACPI_OSI_DEFAULT_INVALID 0x08 +#define ACPI_OSI_OPTIONAL_FEATURE (ACPI_OSI_FEATURE | ACPI_OSI_DEFAULT_INVALID | ACPI_OSI_INVALID) struct acpi_port_info { char *name; diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h index 4c081c436089..d5a62a6182bb 100644 --- a/drivers/acpi/acpica/acutils.h +++ b/drivers/acpi/acpica/acutils.h @@ -470,6 +470,8 @@ acpi_status acpi_ut_install_interface(acpi_string interface_name); acpi_status acpi_ut_remove_interface(acpi_string interface_name); +acpi_status acpi_ut_update_interfaces(u8 action); + struct acpi_interface_info *acpi_ut_get_interface(acpi_string interface_name); acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state); diff --git a/drivers/acpi/acpica/utosi.c b/drivers/acpi/acpica/utosi.c index 7e807725c636..8856bd37bc76 100644 --- a/drivers/acpi/acpica/utosi.c +++ b/drivers/acpi/acpica/utosi.c @@ -77,21 +77,20 @@ static struct acpi_interface_info acpi_default_supported_interfaces[] = { /* Feature Group Strings */ - {"Extended Address Space Descriptor", NULL, 0, 0} + {"Extended Address Space Descriptor", NULL, ACPI_OSI_FEATURE, 0}, /* * All "optional" feature group strings (features that are implemented - * by the host) should be dynamically added by the host via - * acpi_install_interface and should not be manually added here. - * - * Examples of optional feature group strings: - * - * "Module Device" - * "Processor Device" - * "3.0 Thermal Model" - * "3.0 _SCP Extensions" - * "Processor Aggregator Device" + * by the host) should be dynamically modified to VALID by the host via + * acpi_install_interface or acpi_update_interfaces. Such optional feature + * group strings are set as INVALID by default here. */ + + {"Module Device", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0}, + {"Processor Device", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0}, + {"3.0 Thermal Model", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0}, + {"3.0 _SCP Extensions", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0}, + {"Processor Aggregator Device", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0} }; /******************************************************************************* @@ -158,11 +157,20 @@ acpi_status acpi_ut_interface_terminate(void) while (next_interface) { acpi_gbl_supported_interfaces = next_interface->next; - /* Only interfaces added at runtime can be freed */ - if (next_interface->flags & ACPI_OSI_DYNAMIC) { + + /* Only interfaces added at runtime can be freed */ + ACPI_FREE(next_interface->name); ACPI_FREE(next_interface); + } else { + /* Interface is in static list. Reset it to invalid or valid. */ + + if (next_interface->flags & ACPI_OSI_DEFAULT_INVALID) { + next_interface->flags |= ACPI_OSI_INVALID; + } else { + next_interface->flags &= ~ACPI_OSI_INVALID; + } } next_interface = acpi_gbl_supported_interfaces; @@ -276,6 +284,49 @@ acpi_status acpi_ut_remove_interface(acpi_string interface_name) return (AE_NOT_EXIST); } +/******************************************************************************* + * + * FUNCTION: acpi_ut_update_interfaces + * + * PARAMETERS: action - Actions to be performed during the + * update + * + * RETURN: Status + * + * DESCRIPTION: Update _OSI interface strings, disabling or enabling OS vendor + * strings or/and feature group strings. + * Caller MUST hold acpi_gbl_osi_mutex + * + ******************************************************************************/ + +acpi_status acpi_ut_update_interfaces(u8 action) +{ + struct acpi_interface_info *next_interface; + + next_interface = acpi_gbl_supported_interfaces; + while (next_interface) { + if (((next_interface->flags & ACPI_OSI_FEATURE) && + (action & ACPI_FEATURE_STRINGS)) || + (!(next_interface->flags & ACPI_OSI_FEATURE) && + (action & ACPI_VENDOR_STRINGS))) { + if (action & ACPI_DISABLE_INTERFACES) { + + /* Mark the interfaces as invalid */ + + next_interface->flags |= ACPI_OSI_INVALID; + } else { + /* Mark the interfaces as valid */ + + next_interface->flags &= ~ACPI_OSI_INVALID; + } + } + + next_interface = next_interface->next; + } + + return (AE_OK); +} + /******************************************************************************* * * FUNCTION: acpi_ut_get_interface diff --git a/drivers/acpi/acpica/utxface.c b/drivers/acpi/acpica/utxface.c index 6505774f223e..03a211e6e26a 100644 --- a/drivers/acpi/acpica/utxface.c +++ b/drivers/acpi/acpica/utxface.c @@ -387,6 +387,34 @@ acpi_status acpi_install_interface_handler(acpi_interface_handler handler) ACPI_EXPORT_SYMBOL(acpi_install_interface_handler) +/***************************************************************************** + * + * FUNCTION: acpi_update_interfaces + * + * PARAMETERS: action - Actions to be performed during the + * update + * + * RETURN: Status + * + * DESCRIPTION: Update _OSI interface strings, disabling or enabling OS vendor + * string or/and feature group strings. + * + ****************************************************************************/ +acpi_status acpi_update_interfaces(u8 action) +{ + acpi_status status; + + status = acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER); + if (ACPI_FAILURE(status)) { + return (status); + } + + status = acpi_ut_update_interfaces(action); + + acpi_os_release_mutex(acpi_gbl_osi_mutex); + return (status); +} + /***************************************************************************** * * FUNCTION: acpi_check_address_range @@ -402,6 +430,7 @@ ACPI_EXPORT_SYMBOL(acpi_install_interface_handler) * ASL operation region address ranges. * ****************************************************************************/ + u32 acpi_check_address_range(acpi_adr_space_type space_id, acpi_physical_address address, diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 292af0c0b896..0dd03f226a68 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -147,6 +147,8 @@ acpi_status acpi_install_interface(acpi_string interface_name); acpi_status acpi_remove_interface(acpi_string interface_name); +acpi_status acpi_update_interfaces(u8 action); + u32 acpi_check_address_range(acpi_adr_space_type space_id, acpi_physical_address address, diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 787a977ece9d..eae55fb74905 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -1152,4 +1152,18 @@ struct acpi_memory_list { #define ACPI_OSI_WIN_7 0x0B #define ACPI_OSI_WIN_8 0x0C +/* _OSI update actions */ + +#define ACPI_VENDOR_STRINGS 0x01 +#define ACPI_FEATURE_STRINGS 0x02 +#define ACPI_ENABLE_INTERFACES 0x00 +#define ACPI_DISABLE_INTERFACES 0x04 + +#define ACPI_DISABLE_ALL_VENDOR_STRINGS (ACPI_DISABLE_INTERFACES | ACPI_VENDOR_STRINGS) +#define ACPI_DISABLE_ALL_FEATURE_STRINGS (ACPI_DISABLE_INTERFACES | ACPI_FEATURE_STRINGS) +#define ACPI_DISABLE_ALL_STRINGS (ACPI_DISABLE_INTERFACES | ACPI_VENDOR_STRINGS | ACPI_FEATURE_STRINGS) +#define ACPI_ENABLE_ALL_VENDOR_STRINGS (ACPI_ENABLE_INTERFACES | ACPI_VENDOR_STRINGS) +#define ACPI_ENABLE_ALL_FEATURE_STRINGS (ACPI_ENABLE_INTERFACES | ACPI_FEATURE_STRINGS) +#define ACPI_ENABLE_ALL_STRINGS (ACPI_ENABLE_INTERFACES | ACPI_VENDOR_STRINGS | ACPI_FEATURE_STRINGS) + #endif /* __ACTYPES_H__ */ From 5dc17986fdc3d2425838cb8d699152c3c30d1208 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Mon, 22 Jul 2013 16:08:25 +0800 Subject: [PATCH 0277/3400] ACPI: Add facility to disable all _OSI OS vendor strings This patch introduces "acpi_osi=!" command line to force Linux replying "UNSUPPORTED" to all of the _OSI strings. This patch is based on an ACPICA enhancement - the new API acpi_update_interfaces(). The _OSI object provides the platform with the ability to query OSPM to determine the set of ACPI related interfaces, behaviors, or features that the operating system supports. The argument passed to the _OSI is a string like the followings: 1. Feature Group String, examples include Module Device Processor Device 3.0 _SCP Extensions Processor Aggregator Device ... 2. OS Vendor String, examples include Linux FreeBSD Windows ... There are AML codes provided in the ACPI namespace written in the following style to determine OSPM interfaces / features: Method(OSCK) { if (CondRefOf(_OSI, Local0)) { if (\_OSI("Windows")) { Return (One) } if (\_OSI("Windows 2006")) { Return (Ones) } Return (Zero) } Return (Zero) } There is a debugging facility implemented in Linux. Users can pass "acpi_osi=" boot parameters to the kernel to tune the _OSI evaluation result so that certain AML codes can be executed. Current implementation includes: 1. 'acpi_osi=' - this makes CondRefOf(_OSI, Local0) TRUE 2. 'acpi_osi="Windows"' - this makes \_OSI("Windows") TRUE 3. 'acpi_osi="!Windows"' - this makes \_OSI("Windows") FALSE The function to implement this feature is also used as a quirk mechanism in the Linux ACPI subystem. When _OSI is evaluatated by the AML codes, ACPICA replies "SUPPORTED" to all Windows operating system vendor strings. This is because Windows operating systems return "SUPPORTED" if the argument to the _OSI method specifies an earlier version of Windows. Please refer to the following MSDN document: How to Identify the Windows Version in ACPI by Using _OSI http://msdn.microsoft.com/en-us/library/hardware/gg463275.aspx This adds difficulties when developers want to feed specific Windows operating system vendor string to the BIOS codes for debugging purpose, multiple acpi_osi="!xxx" have to be specified in the command line to force Linux replying "UNSUPPORTED" to the Windows OS vendor strings listed in the AML codes. Signed-off-by: Lv Zheng Reviewed-by: Zhang Rui Acked-by: Len Brown Signed-off-by: Rafael J. Wysocki --- Documentation/kernel-parameters.txt | 29 +++++++++++++++++++++++++++-- drivers/acpi/osl.c | 14 +++++++++++++- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 15356aca938c..d0d9cf278ae3 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -235,10 +235,35 @@ bytes respectively. Such letter suffixes can also be entirely omitted. Format: To spoof as Windows 98: ="Microsoft Windows" acpi_osi= [HW,ACPI] Modify list of supported OS interface strings - acpi_osi="string1" # add string1 -- only one string - acpi_osi="!string2" # remove built-in string2 + acpi_osi="string1" # add string1 + acpi_osi="!string2" # remove string2 + acpi_osi=! # disable all built-in OS vendor + strings acpi_osi= # disable all strings + 'acpi_osi=!' can be used in combination with single or + multiple 'acpi_osi="string1"' to support specific OS + vendor string(s). Note that such command can only + affect the default state of the OS vendor strings, thus + it cannot affect the default state of the feature group + strings and the current state of the OS vendor strings, + specifying it multiple times through kernel command line + is meaningless. + Examples: + 1. 'acpi_osi=! acpi_osi="Windows 2000"' is equivalent + to 'acpi_osi="Windows 2000" acpi_osi=!', they all + can make '_OSI("Windows 2000")' TRUE. + + 'acpi_osi=' cannot be used in combination with other + 'acpi_osi=' command lines, the _OSI method will not + exist in the ACPI namespace. NOTE that such command can + only affect the _OSI support state, thus specifying it + multiple times through kernel command line is also + meaningless. + Examples: + 1. 'acpi_osi=' can make 'CondRefOf(_OSI, Local1)' + FALSE. + acpi_pm_good [X86] Override the pmtimer bug detection: force the kernel to assume that this machine's pmtimer latches its value diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 6ab2c3505520..e8baa408faef 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -140,7 +140,8 @@ static struct osi_linux { unsigned int enable:1; unsigned int dmi:1; unsigned int cmdline:1; -} osi_linux = {0, 0, 0}; + unsigned int default_disabling:1; +} osi_linux = {0, 0, 0, 0}; static u32 acpi_osi_handler(acpi_string interface, u32 supported) { @@ -1376,6 +1377,10 @@ void __init acpi_osi_setup(char *str) if (*str == '!') { str++; + if (*str == '\0') { + osi_linux.default_disabling = 1; + return; + } enable = false; } @@ -1441,6 +1446,13 @@ static void __init acpi_osi_setup_late(void) int i; acpi_status status; + if (osi_linux.default_disabling) { + status = acpi_update_interfaces(ACPI_DISABLE_ALL_VENDOR_STRINGS); + + if (ACPI_SUCCESS(status)) + printk(KERN_INFO PREFIX "Disabled all _OSI OS vendors\n"); + } + for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) { osi = &osi_setup_entries[i]; str = osi->string; From 741d81280ad2b31fc3d76c49fa5c1fe09f3a6f68 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Mon, 22 Jul 2013 16:08:36 +0800 Subject: [PATCH 0278/3400] ACPI: Add facility to remove all _OSI strings This patch changes the "acpi_osi=" boot parameter implementation so that: 1. "acpi_osi=!" can be used to disable all _OSI OS vendor strings by default. It is meaningless to specify "acpi_osi=!" multiple times as it can only affect the default state of the target _OSI strings. 2. "acpi_osi=!*" can be used to remove all _OSI OS vendor strings and all _OSI feature group strings. It is useful to specify "acpi_osi=!*" multiple times through kernel command line to override the current state of the target _OSI strings. Signed-off-by: Lv Zheng Reviewed-by: Zhang Rui Acked-by: Len Brown Signed-off-by: Rafael J. Wysocki --- Documentation/kernel-parameters.txt | 28 +++++++++++++++++++++++++++- drivers/acpi/osl.c | 7 +++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index d0d9cf278ae3..5ec77aad1773 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -237,6 +237,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted. acpi_osi= [HW,ACPI] Modify list of supported OS interface strings acpi_osi="string1" # add string1 acpi_osi="!string2" # remove string2 + acpi_osi=!* # remove all strings acpi_osi=! # disable all built-in OS vendor strings acpi_osi= # disable all strings @@ -248,7 +249,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted. it cannot affect the default state of the feature group strings and the current state of the OS vendor strings, specifying it multiple times through kernel command line - is meaningless. + is meaningless. This command is useful when one do not + care about the state of the feature group strings which + should be controlled by the OSPM. Examples: 1. 'acpi_osi=! acpi_osi="Windows 2000"' is equivalent to 'acpi_osi="Windows 2000" acpi_osi=!', they all @@ -264,6 +267,29 @@ bytes respectively. Such letter suffixes can also be entirely omitted. 1. 'acpi_osi=' can make 'CondRefOf(_OSI, Local1)' FALSE. + 'acpi_osi=!*' can be used in combination with single or + multiple 'acpi_osi="string1"' to support specific + string(s). Note that such command can affect the + current state of both the OS vendor strings and the + feature group strings, thus specifying it multiple times + through kernel command line is meaningful. But it may + still not able to affect the final state of a string if + there are quirks related to this string. This command + is useful when one want to control the state of the + feature group strings to debug BIOS issues related to + the OSPM features. + Examples: + 1. 'acpi_osi="Module Device" acpi_osi=!*' can make + '_OSI("Module Device")' FALSE. + 2. 'acpi_osi=!* acpi_osi="Module Device"' can make + '_OSI("Module Device")' TRUE. + 3. 'acpi_osi=! acpi_osi=!* acpi_osi="Windows 2000"' is + equivalent to + 'acpi_osi=!* acpi_osi=! acpi_osi="Windows 2000"' + and + 'acpi_osi=!* acpi_osi="Windows 2000" acpi_osi=!', + they all will make '_OSI("Windows 2000")' TRUE. + acpi_pm_good [X86] Override the pmtimer bug detection: force the kernel to assume that this machine's pmtimer latches its value diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index e8baa408faef..cc1ed12d0b89 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -1380,6 +1380,13 @@ void __init acpi_osi_setup(char *str) if (*str == '\0') { osi_linux.default_disabling = 1; return; + } else if (*str == '*') { + acpi_update_interfaces(ACPI_DISABLE_ALL_STRINGS); + for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) { + osi = &osi_setup_entries[i]; + osi->enable = false; + } + return; } enable = false; } From 68c034fefe20eaf7d5569aae84584b07987ce50a Mon Sep 17 00:00:00 2001 From: Yoshihiro YUNOMAE Date: Tue, 23 Jul 2013 11:30:49 +0930 Subject: [PATCH 0279/3400] virtio/console: Quit from splice_write if pipe->nrbufs is 0 Quit from splice_write if pipe->nrbufs is 0 for avoiding oops in virtio-serial. When an application was doing splice from a kernel buffer to virtio-serial on a guest, the application received signal(SIGINT). This situation will normally happen, but the kernel executed a kernel panic by oops as follows: BUG: unable to handle kernel paging request at ffff882071c8ef28 IP: [] sg_init_table+0x2f/0x50 PGD 1fac067 PUD 0 Oops: 0000 [#1] SMP Modules linked in: lockd sunrpc bnep bluetooth rfkill ip6t_REJECT nf_conntrack_ipv6 nf_defrag_ipv6 xt_state nf_conntrack ip6table_filter ip6_tables snd_hda_intel snd_hda_codec snd_hwdep snd_pcm snd_page_alloc snd_timer snd microcode virtio_balloon virtio_net pcspkr soundcore i2c_piix4 i2c_core uinput floppy CPU: 1 PID: 908 Comm: trace-cmd Not tainted 3.10.0+ #49 Hardware name: Bochs Bochs, BIOS Bochs 01/01/2007 task: ffff880071c64650 ti: ffff88007bf24000 task.ti: ffff88007bf24000 RIP: 0010:[] [] sg_init_table+0x2f/0x50 RSP: 0018:ffff88007bf25dd8 EFLAGS: 00010286 RAX: 0000001fffffffe0 RBX: ffff882071c8ef28 RCX: 0000000000000000 RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff880071c8ef48 RBP: ffff88007bf25de8 R08: ffff88007fd15d40 R09: ffff880071c8ef48 R10: ffffea0001c71040 R11: ffffffff8139c555 R12: 0000000000000000 R13: ffff88007506a3c0 R14: ffff88007c862500 R15: ffff880071c8ef00 FS: 00007f0a3646c740(0000) GS:ffff88007fd00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: ffff882071c8ef28 CR3: 000000007acbb000 CR4: 00000000000006e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Stack: ffff880071c8ef48 ffff88007bf25e20 ffff88007bf25e88 ffffffff8139d6fa ffff88007bf25e28 ffffffff8127a3f4 0000000000000000 0000000000000000 ffff880071c8ef48 0000100000000000 0000000000000003 ffff88007bf25e08 Call Trace: [] port_fops_splice_write+0xaa/0x130 [] ? selinux_file_permission+0xc4/0x120 [] ? wait_port_writable+0x1b0/0x1b0 [] do_splice_from+0xa0/0x110 [] SyS_splice+0x5ff/0x6b0 [] system_call_fastpath+0x16/0x1b Code: c1 e2 05 48 89 e5 48 83 ec 10 4c 89 65 f8 41 89 f4 31 f6 48 89 5d f0 48 89 fb e8 8d ce ff ff 41 8d 44 24 ff 48 c1 e0 05 48 01 c3 <48> 8b 03 48 83 e0 fe 48 83 c8 02 48 89 03 48 8b 5d f0 4c 8b 65 RIP [] sg_init_table+0x2f/0x50 RSP CR2: ffff882071c8ef28 ---[ end trace 86323505eb42ea8f ]--- It seems to induce pagefault in sg_init_tabel() when pipe->nrbufs is equal to zero. This may happen in a following situation: (1) The application normally does splice(read) from a kernel buffer, then does splice(write) to virtio-serial. (2) The application receives SIGINT when is doing splice(read), so splice(read) is failed by EINTR. However, the application does not finish the operation. (3) The application tries to do splice(write) without pipe->nrbufs. (4) The virtio-console driver tries to touch scatterlist structure sgl in sg_init_table(), but the region is out of bound. To avoid the case, a kernel should check whether pipe->nrbufs is empty or not when splice_write is executed in the virtio-console driver. V3: Add Reviewed-by lines and stable@ line in sign-off area. Signed-off-by: Yoshihiro YUNOMAE Reviewed-by: Amit Shah Reviewed-by: Masami Hiramatsu Cc: Amit Shah Cc: Arnd Bergmann Cc: Greg Kroah-Hartman Cc: stable@vger.kernel.org Signed-off-by: Rusty Russell --- drivers/char/virtio_console.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 1b456fe9b87a..8722656cdebf 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -932,6 +932,13 @@ static ssize_t port_fops_splice_write(struct pipe_inode_info *pipe, if (is_rproc_serial(port->out_vq->vdev)) return -EINVAL; + /* + * pipe->nrbufs == 0 means there are no data to transfer, + * so this returns just 0 for no data. + */ + if (!pipe->nrbufs) + return 0; + ret = wait_port_writable(port, filp->f_flags & O_NONBLOCK); if (ret < 0) return ret; From 2b4fbf029dff5a28d9bf646346dea891ec43398a Mon Sep 17 00:00:00 2001 From: Yoshihiro YUNOMAE Date: Tue, 23 Jul 2013 11:30:49 +0930 Subject: [PATCH 0280/3400] virtio/console: Add pipe_lock/unlock for splice_write Add pipe_lock/unlock for splice_write to avoid oops by following competition: (1) An application gets fds of a trace buffer, virtio-serial, pipe. (2) The application does fork() (3) The processes execute splice_read(trace buffer) and splice_write(virtio-serial) via same pipe. get fds of a trace buffer, virtio-serial, pipe | fork()----------create--------+ | | splice(read) | ---+ splice(write) | +-- no competition | splice(read) | | splice(write) ---+ | | splice(read) | splice(write) splice(read) ------ competition | splice(write) Two processes share a pipe_inode_info structure. If the child execute splice(read) when the parent tries to execute splice(write), the structure can be broken. Existing virtio-serial driver does not get lock for the structure in splice_write, so this competition will induce oops. BUG: unable to handle kernel NULL pointer dereference at 0000000000000018 IP: [] splice_from_pipe_feed+0x6f/0x130 PGD 7223e067 PUD 72391067 PMD 0 Oops: 0000 [#1] SMP Modules linked in: lockd bnep bluetooth rfkill sunrpc ip6t_REJECT nf_conntrack_ipv6 nf_defrag_ipv6 xt_state nf_conntrack ip6table_filter ip6_tables snd_hda_intel snd_hda_codec snd_hwdep snd_pcm snd_page_alloc snd_timer snd soundcore pcspkr virtio_net virtio_balloon i2c_piix4 i2c_core microcode uinput floppy CPU: 0 PID: 1072 Comm: compete-test Not tainted 3.10.0ws+ #55 Hardware name: Bochs Bochs, BIOS Bochs 01/01/2007 task: ffff880071b98000 ti: ffff88007b55e000 task.ti: ffff88007b55e000 RIP: 0010:[] [] splice_from_pipe_feed+0x6f/0x130 RSP: 0018:ffff88007b55fd78 EFLAGS: 00010287 RAX: 0000000000000000 RBX: ffff88007b55fe20 RCX: 0000000000000000 RDX: 0000000000001000 RSI: ffff88007a95ba30 RDI: ffff880036f9e6c0 RBP: ffff88007b55fda8 R08: 00000000000006ec R09: ffff880077626708 R10: 0000000000000003 R11: ffffffff8139ca59 R12: ffff88007a95ba30 R13: 0000000000000000 R14: ffffffff8139dd00 R15: ffff880036f9e6c0 FS: 00007f2e2e3a0740(0000) GS:ffff88007fc00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 0000000000000018 CR3: 0000000071bd1000 CR4: 00000000000006f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Stack: ffffffff8139ca59 ffff88007b55fe20 ffff880036f9e6c0 ffffffff8139dd00 ffff8800776266c0 ffff880077626708 ffff88007b55fde8 ffffffff811a6e8e ffff88007b55fde8 ffffffff8139ca59 ffff880036f9e6c0 ffff88007b55fe20 Call Trace: [] ? alloc_buf.isra.13+0x39/0xb0 [] ? virtcons_restore+0x100/0x100 [] __splice_from_pipe+0x7e/0x90 [] ? alloc_buf.isra.13+0x39/0xb0 [] port_fops_splice_write+0xe9/0x140 [] ? selinux_file_permission+0xc4/0x120 [] ? wait_port_writable+0x1b0/0x1b0 [] do_splice_from+0xa0/0x110 [] SyS_splice+0x5ff/0x6b0 [] tracesys+0xdd/0xe2 Code: 49 8b 87 80 00 00 00 4c 8d 24 d0 8b 53 04 41 8b 44 24 0c 4d 8b 6c 24 10 39 d0 89 03 76 02 89 13 49 8b 44 24 10 4c 89 e6 4c 89 ff 50 18 85 c0 0f 85 aa 00 00 00 48 89 da 4c 89 e6 4c 89 ff 41 RIP [] splice_from_pipe_feed+0x6f/0x130 RSP CR2: 0000000000000018 ---[ end trace 24572beb7764de59 ]--- V2: Fix a locking problem for error V3: Add Reviewed-by lines and stable@ line in sign-off area Signed-off-by: Yoshihiro YUNOMAE Reviewed-by: Amit Shah Reviewed-by: Masami Hiramatsu Cc: Amit Shah Cc: Arnd Bergmann Cc: Greg Kroah-Hartman Cc: stable@vger.kernel.org Signed-off-by: Rusty Russell --- drivers/char/virtio_console.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 8722656cdebf..8a15af3e1a9d 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -936,16 +936,21 @@ static ssize_t port_fops_splice_write(struct pipe_inode_info *pipe, * pipe->nrbufs == 0 means there are no data to transfer, * so this returns just 0 for no data. */ - if (!pipe->nrbufs) - return 0; + pipe_lock(pipe); + if (!pipe->nrbufs) { + ret = 0; + goto error_out; + } ret = wait_port_writable(port, filp->f_flags & O_NONBLOCK); if (ret < 0) - return ret; + goto error_out; buf = alloc_buf(port->out_vq, 0, pipe->nrbufs); - if (!buf) - return -ENOMEM; + if (!buf) { + ret = -ENOMEM; + goto error_out; + } sgl.n = 0; sgl.len = 0; @@ -953,12 +958,17 @@ static ssize_t port_fops_splice_write(struct pipe_inode_info *pipe, sgl.sg = buf->sg; sg_init_table(sgl.sg, sgl.size); ret = __splice_from_pipe(pipe, &sd, pipe_to_sg); + pipe_unlock(pipe); if (likely(ret > 0)) ret = __send_to_port(port, buf->sg, sgl.n, sgl.len, buf, true); if (unlikely(ret <= 0)) free_buf(buf, true); return ret; + +error_out: + pipe_unlock(pipe); + return ret; } static unsigned int port_fops_poll(struct file *filp, poll_table *wait) From 82982d729319e975115d88cae4927dffb02bfea7 Mon Sep 17 00:00:00 2001 From: Tang Chen Date: Tue, 23 Jul 2013 16:00:19 +0800 Subject: [PATCH 0281/3400] x86/acpi: Fix incorrect sanity check in acpi_register_lapic() We wanted to check if the APIC ID is out of range. It should be: if (id >= MAX_LOCAL_APIC) There's no known bad effect of this bug. Signed-off-by: Tang Chen Reviewed-by: Len Brown Cc: pavel@ucw.cz Cc: rjw@sisk.pl Link: http://lkml.kernel.org/r/1374566419-21120-1-git-send-email-tangchen@cn.fujitsu.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/acpi/boot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 2627a81253ee..872a2d255e41 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -199,7 +199,7 @@ static void acpi_register_lapic(int id, u8 enabled) { unsigned int ver = 0; - if (id >= (MAX_LOCAL_APIC-1)) { + if (id >= MAX_LOCAL_APIC) { printk(KERN_INFO PREFIX "skipped apicid that is too big\n"); return; } From 17f41571bb2c4a398785452ac2718a6c5d77180e Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Tue, 23 Jul 2013 10:09:28 +0200 Subject: [PATCH 0282/3400] kprobes/x86: Call out into INT3 handler directly instead of using notifier In fd4363fff3d96 ("x86: Introduce int3 (breakpoint)-based instruction patching"), the mechanism that was introduced for notifying alternatives code from int3 exception handler that and exception occured was die_notifier. This is however problematic, as early code might be using jump labels even before the notifier registration has been performed, which will then lead to an oops due to unhandled exception. One of such occurences has been encountered by Fengguang: int3: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC Modules linked in: CPU: 1 PID: 0 Comm: swapper/1 Not tainted 3.11.0-rc1-01429-g04bf576 #8 task: ffff88000da1b040 ti: ffff88000da1c000 task.ti: ffff88000da1c000 RIP: 0010:[] [] ttwu_do_wakeup+0x28/0x225 RSP: 0000:ffff88000dd03f10 EFLAGS: 00000006 RAX: 0000000000000000 RBX: ffff88000dd12940 RCX: ffffffff81769c40 RDX: 0000000000000002 RSI: 0000000000000000 RDI: 0000000000000001 RBP: ffff88000dd03f28 R08: ffffffff8176a8c0 R09: 0000000000000002 R10: ffffffff810ff484 R11: ffff88000dd129e8 R12: ffff88000dbc90c0 R13: ffff88000dbc90c0 R14: ffff88000da1dfd8 R15: ffff88000da1dfd8 FS: 0000000000000000(0000) GS:ffff88000dd00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 00000000ffffffff CR3: 0000000001c88000 CR4: 00000000000006e0 Stack: ffff88000dd12940 ffff88000dbc90c0 ffff88000da1dfd8 ffff88000dd03f48 ffffffff81109e2b ffff88000dd12940 0000000000000000 ffff88000dd03f68 ffffffff81109e9e 0000000000000000 0000000000012940 ffff88000dd03f98 Call Trace: [] ttwu_do_activate.constprop.56+0x6d/0x79 [] sched_ttwu_pending+0x67/0x84 [] scheduler_ipi+0x15a/0x2b0 [] smp_reschedule_interrupt+0x38/0x41 [] reschedule_interrupt+0x6d/0x80 [] ? __atomic_notifier_call_chain+0x5/0xc1 [] ? native_safe_halt+0xd/0x16 [] default_idle+0x147/0x282 [] arch_cpu_idle+0x3d/0x5d [] cpu_idle_loop+0x46d/0x5db [] cpu_startup_entry+0x84/0x84 [] start_secondary+0x3c8/0x3d5 [...] Fix this by directly calling poke_int3_handler() from the int3 exception handler (analogically to what ftrace has been doing already), instead of relying on notifier, registration of which might not have yet been finalized by the time of the first trap. Reported-and-tested-by: Fengguang Wu Signed-off-by: Jiri Kosina Acked-by: Masami Hiramatsu Cc: H. Peter Anvin Cc: Fengguang Wu Cc: Steven Rostedt Link: http://lkml.kernel.org/r/alpine.LNX.2.00.1307231007490.14024@pobox.suse.cz Signed-off-by: Ingo Molnar --- arch/x86/include/asm/alternative.h | 2 ++ arch/x86/kernel/alternative.c | 31 ++++++++---------------------- arch/x86/kernel/traps.c | 4 ++++ kernel/kprobes.c | 2 +- 4 files changed, 15 insertions(+), 24 deletions(-) diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h index 4daf8c501239..0a3f9c9f98d5 100644 --- a/arch/x86/include/asm/alternative.h +++ b/arch/x86/include/asm/alternative.h @@ -5,6 +5,7 @@ #include #include #include +#include /* * Alternative inline assembly for SMP. @@ -224,6 +225,7 @@ extern void *text_poke_early(void *addr, const void *opcode, size_t len); * inconsistent instruction while you patch. */ extern void *text_poke(void *addr, const void *opcode, size_t len); +extern int poke_int3_handler(struct pt_regs *regs); extern void *text_poke_bp(void *addr, const void *opcode, size_t len, void *handler); #endif /* _ASM_X86_ALTERNATIVE_H */ diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index 5d8782ee3dd7..15e8563e5c24 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -605,26 +605,24 @@ static void do_sync_core(void *info) static bool bp_patching_in_progress; static void *bp_int3_handler, *bp_int3_addr; -static int int3_notify(struct notifier_block *self, unsigned long val, void *data) +int poke_int3_handler(struct pt_regs *regs) { - struct die_args *args = data; - /* bp_patching_in_progress */ smp_rmb(); if (likely(!bp_patching_in_progress)) - return NOTIFY_DONE; + return 0; - /* we are not interested in non-int3 faults and ring > 0 faults */ - if (val != DIE_INT3 || !args->regs || user_mode_vm(args->regs) - || args->regs->ip != (unsigned long)bp_int3_addr) - return NOTIFY_DONE; + if (user_mode_vm(regs) || regs->ip != (unsigned long)bp_int3_addr) + return 0; /* set up the specified breakpoint handler */ - args->regs->ip = (unsigned long) bp_int3_handler; + regs->ip = (unsigned long) bp_int3_handler; + + return 1; - return NOTIFY_STOP; } + /** * text_poke_bp() -- update instructions on live kernel on SMP * @addr: address to patch @@ -689,16 +687,3 @@ void *text_poke_bp(void *addr, const void *opcode, size_t len, void *handler) return addr; } -/* this one needs to run before anything else handles it as a - * regular exception */ -static struct notifier_block int3_nb = { - .priority = 0x7fffffff, - .notifier_call = int3_notify -}; - -static int __init int3_init(void) -{ - return register_die_notifier(&int3_nb); -} - -arch_initcall(int3_init); diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 1b23a1c92746..8c8093b146ca 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -58,6 +58,7 @@ #include #include #include +#include #ifdef CONFIG_X86_64 #include @@ -327,6 +328,9 @@ dotraplinkage void __kprobes notrace do_int3(struct pt_regs *regs, long error_co ftrace_int3_handler(regs)) return; #endif + if (poke_int3_handler(regs)) + return; + prev_state = exception_enter(); #ifdef CONFIG_KGDB_LOW_LEVEL_TRAP if (kgdb_ll_trap(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP, diff --git a/kernel/kprobes.c b/kernel/kprobes.c index b58b490fa439..6e33498d665c 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -1709,7 +1709,7 @@ EXPORT_SYMBOL_GPL(unregister_kprobes); static struct notifier_block kprobe_exceptions_nb = { .notifier_call = kprobe_exceptions_notify, - .priority = 0x7ffffff0 /* High priority, but not first. */ + .priority = 0x7fffffff /* we need to be notified first */ }; unsigned long __weak arch_deref_entry_point(void *entry) From d2475b8ff81ebeed88d8fcbc22876aced5a0807a Mon Sep 17 00:00:00 2001 From: Ramkumar Ramachandra Date: Wed, 10 Jul 2013 23:34:28 +0530 Subject: [PATCH 0283/3400] x86/ia32/asm: Remove unused argument in macro Commit 3fe26fa ("x86: get rid of pt_regs argument in sigreturn variants", from 2012-11-12) changed the body of PTREGSCALL to drop arg, and updated the callsites; unfortunately, it forgot to update the macro argument list, leaving an unused argument. Fix this. Signed-off-by: Ramkumar Ramachandra Cc: Al Viro Link: http://lkml.kernel.org/r/1373479468-7175-1-git-send-email-artagnon@gmail.com Signed-off-by: Ingo Molnar --- arch/x86/ia32/ia32entry.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S index 474dc1b59f72..4299eb05023c 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S @@ -452,7 +452,7 @@ ia32_badsys: CFI_ENDPROC - .macro PTREGSCALL label, func, arg + .macro PTREGSCALL label, func ALIGN GLOBAL(\label) leaq \func(%rip),%rax From 803075dba31c17af110e1d9a915fe7262165b213 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Wed, 17 Jul 2013 07:13:59 -0400 Subject: [PATCH 0284/3400] x86/iommu/vt-d: Expand interrupt remapping quirk to cover x58 chipset Recently we added an early quirk to detect 5500/5520 chipsets with early revisions that had problems with irq draining with interrupt remapping enabled: commit 03bbcb2e7e292838bb0244f5a7816d194c911d62 Author: Neil Horman Date: Tue Apr 16 16:38:32 2013 -0400 iommu/vt-d: add quirk for broken interrupt remapping on 55XX chipsets It turns out this same problem is present in the intel X58 chipset as well. See errata 69 here: http://www.intel.com/content/www/us/en/chipsets/x58-express-specification-update.html This patch extends the pci early quirk so that the chip devices/revisions specified in the above update are also covered in the same way: Signed-off-by: Neil Horman Reviewed-by: Jan Beulich Acked-by: Donald Dutile Cc: Joerg Roedel Cc: Andrew Cooper Cc: Malcolm Crossley Cc: Prarit Bhargava Cc: Don Zickus Cc: stable@vger.kernel.org Link: http://lkml.kernel.org/r/1374059639-8631-1-git-send-email-nhorman@tuxdriver.com [ Small edits. ] Signed-off-by: Ingo Molnar --- arch/x86/kernel/early-quirks.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c index 94ab6b90dd3f..63bdb29b2549 100644 --- a/arch/x86/kernel/early-quirks.c +++ b/arch/x86/kernel/early-quirks.c @@ -196,15 +196,23 @@ static void __init ati_bugs_contd(int num, int slot, int func) static void __init intel_remapping_check(int num, int slot, int func) { u8 revision; + u16 device; + device = read_pci_config_16(num, slot, func, PCI_DEVICE_ID); revision = read_pci_config_byte(num, slot, func, PCI_REVISION_ID); /* - * Revision 0x13 of this chipset supports irq remapping - * but has an erratum that breaks its behavior, flag it as such + * Revision 13 of all triggering devices id in this quirk have + * a problem draining interrupts when irq remapping is enabled, + * and should be flagged as broken. Additionally revisions 0x12 + * and 0x22 of device id 0x3405 has this problem. */ if (revision == 0x13) set_irq_remapping_broken(); + else if ((device == 0x3405) && + ((revision == 0x12) || + (revision == 0x22))) + set_irq_remapping_broken(); } @@ -239,6 +247,8 @@ static struct chipset early_qrk[] __initdata = { PCI_CLASS_SERIAL_SMBUS, PCI_ANY_ID, 0, ati_bugs_contd }, { PCI_VENDOR_ID_INTEL, 0x3403, PCI_CLASS_BRIDGE_HOST, PCI_BASE_CLASS_BRIDGE, 0, intel_remapping_check }, + { PCI_VENDOR_ID_INTEL, 0x3405, PCI_CLASS_BRIDGE_HOST, + PCI_BASE_CLASS_BRIDGE, 0, intel_remapping_check }, { PCI_VENDOR_ID_INTEL, 0x3406, PCI_CLASS_BRIDGE_HOST, PCI_BASE_CLASS_BRIDGE, 0, intel_remapping_check }, {} From ec83f425dbca47e19c6737e8e7db0d0924a5de1b Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Fri, 28 Jun 2013 13:13:18 -0700 Subject: [PATCH 0285/3400] mutex: Do not unnecessarily deal with waiters Upon entering the slowpath, we immediately attempt to acquire the lock by checking if it is already unlocked. If we are lucky enough that this is the case, then we don't need to deal with any waiter related logic. Furthermore any checks for an empty wait_list are unnecessary as we already know that count is non-negative and hence no one is waiting for the lock. Move the count check and xchg calls to be done before any waiters are setup - including waiter debugging. Upon failure to acquire the lock, the xchg sets the counter to 0, instead of -1 as it was originally. This can be done here since we set it back to -1 right at the beginning of the loop so other waiters are woken up when the lock is released. When tested on a 8-socket (80 core) system against a vanilla 3.10-rc1 kernel, this patch provides some small performance benefits (+2-6%). While it could be considered in the noise level, the average percentages were stable across multiple runs and no performance regressions were seen. Two big winners, for small amounts of users (10-100), were the short and compute workloads had a +19.36% and +%15.76% in jobs per minute. Also change some break statements to 'goto slowpath', which IMO makes a little more intuitive to read. Signed-off-by: Davidlohr Bueso Acked-by: Rik van Riel Acked-by: Maarten Lankhorst Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1372450398.2106.1.camel@buesod1.americas.hpqcorp.net Signed-off-by: Ingo Molnar --- kernel/mutex.c | 43 +++++++++++++++++++------------------------ 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/kernel/mutex.c b/kernel/mutex.c index 7ff48c55a98b..386ad5da47a5 100644 --- a/kernel/mutex.c +++ b/kernel/mutex.c @@ -463,7 +463,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass, * performed the optimistic spinning cannot be done. */ if (ACCESS_ONCE(ww->ctx)) - break; + goto slowpath; } /* @@ -474,7 +474,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass, owner = ACCESS_ONCE(lock->owner); if (owner && !mutex_spin_on_owner(lock, owner)) { mspin_unlock(MLOCK(lock), &node); - break; + goto slowpath; } if ((atomic_read(&lock->count) == 1) && @@ -489,8 +489,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass, mutex_set_owner(lock); mspin_unlock(MLOCK(lock), &node); - preempt_enable(); - return 0; + goto done; } mspin_unlock(MLOCK(lock), &node); @@ -501,7 +500,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass, * the owner complete. */ if (!owner && (need_resched() || rt_task(task))) - break; + goto slowpath; /* * The cpu_relax() call is a compiler barrier which forces @@ -515,6 +514,10 @@ slowpath: #endif spin_lock_mutex(&lock->wait_lock, flags); + /* once more, can we acquire the lock? */ + if (MUTEX_SHOW_NO_WAITER(lock) && (atomic_xchg(&lock->count, 0) == 1)) + goto skip_wait; + debug_mutex_lock_common(lock, &waiter); debug_mutex_add_waiter(lock, &waiter, task_thread_info(task)); @@ -522,9 +525,6 @@ slowpath: list_add_tail(&waiter.list, &lock->wait_list); waiter.task = task; - if (MUTEX_SHOW_NO_WAITER(lock) && (atomic_xchg(&lock->count, -1) == 1)) - goto done; - lock_contended(&lock->dep_map, ip); for (;;) { @@ -538,7 +538,7 @@ slowpath: * other waiters: */ if (MUTEX_SHOW_NO_WAITER(lock) && - (atomic_xchg(&lock->count, -1) == 1)) + (atomic_xchg(&lock->count, -1) == 1)) break; /* @@ -563,24 +563,25 @@ slowpath: schedule_preempt_disabled(); spin_lock_mutex(&lock->wait_lock, flags); } - -done: - lock_acquired(&lock->dep_map, ip); - /* got the lock - rejoice! */ mutex_remove_waiter(lock, &waiter, current_thread_info()); + /* set it to 0 if there are no waiters left: */ + if (likely(list_empty(&lock->wait_list))) + atomic_set(&lock->count, 0); + debug_mutex_free_waiter(&waiter); + +skip_wait: + /* got the lock - cleanup and rejoice! */ + lock_acquired(&lock->dep_map, ip); mutex_set_owner(lock); if (!__builtin_constant_p(ww_ctx == NULL)) { - struct ww_mutex *ww = container_of(lock, - struct ww_mutex, - base); + struct ww_mutex *ww = container_of(lock, struct ww_mutex, base); struct mutex_waiter *cur; /* * This branch gets optimized out for the common case, * and is only important for ww_mutex_lock. */ - ww_mutex_lock_acquired(ww, ww_ctx); ww->ctx = ww_ctx; @@ -594,15 +595,9 @@ done: } } - /* set it to 0 if there are no waiters left: */ - if (likely(list_empty(&lock->wait_list))) - atomic_set(&lock->count, 0); - spin_unlock_mutex(&lock->wait_lock, flags); - - debug_mutex_free_waiter(&waiter); +done: preempt_enable(); - return 0; err: From a5cdd40c9877e9aba704c020fd65d26b5cfecf18 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 16 Jul 2013 17:09:07 +0200 Subject: [PATCH 0286/3400] perf: Update perf_event_type documentation Due to a discussion with Adrian I had a good look at the perf_event_type record layout and found the documentation to be somewhat unclear. Cc: Adrian Hunter Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/20130716150907.GL23818@dyad.programming.kicks-ass.net Signed-off-by: Ingo Molnar --- include/uapi/linux/perf_event.h | 18 +++++++++++++++++- kernel/events/core.c | 31 ++++++++++++++++--------------- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h index 0b1df41691e8..00d8274730b4 100644 --- a/include/uapi/linux/perf_event.h +++ b/include/uapi/linux/perf_event.h @@ -478,6 +478,16 @@ enum perf_event_type { * file will be supported by older perf tools, with these new optional * fields being ignored. * + * struct sample_id { + * { u32 pid, tid; } && PERF_SAMPLE_TID + * { u64 time; } && PERF_SAMPLE_TIME + * { u64 id; } && PERF_SAMPLE_ID + * { u64 stream_id;} && PERF_SAMPLE_STREAM_ID + * { u32 cpu, res; } && PERF_SAMPLE_CPU + * } && perf_event_attr::sample_id_all + */ + + /* * The MMAP events record the PROT_EXEC mappings so that we can * correlate userspace IPs to code. They have the following structure: * @@ -498,6 +508,7 @@ enum perf_event_type { * struct perf_event_header header; * u64 id; * u64 lost; + * struct sample_id sample_id; * }; */ PERF_RECORD_LOST = 2, @@ -508,6 +519,7 @@ enum perf_event_type { * * u32 pid, tid; * char comm[]; + * struct sample_id sample_id; * }; */ PERF_RECORD_COMM = 3, @@ -518,6 +530,7 @@ enum perf_event_type { * u32 pid, ppid; * u32 tid, ptid; * u64 time; + * struct sample_id sample_id; * }; */ PERF_RECORD_EXIT = 4, @@ -528,6 +541,7 @@ enum perf_event_type { * u64 time; * u64 id; * u64 stream_id; + * struct sample_id sample_id; * }; */ PERF_RECORD_THROTTLE = 5, @@ -539,6 +553,7 @@ enum perf_event_type { * u32 pid, ppid; * u32 tid, ptid; * u64 time; + * struct sample_id sample_id; * }; */ PERF_RECORD_FORK = 7, @@ -549,6 +564,7 @@ enum perf_event_type { * u32 pid, tid; * * struct read_format values; + * struct sample_id sample_id; * }; */ PERF_RECORD_READ = 8, @@ -596,7 +612,7 @@ enum perf_event_type { * u64 dyn_size; } && PERF_SAMPLE_STACK_USER * * { u64 weight; } && PERF_SAMPLE_WEIGHT - * { u64 data_src; } && PERF_SAMPLE_DATA_SRC + * { u64 data_src; } && PERF_SAMPLE_DATA_SRC * }; */ PERF_RECORD_SAMPLE = 9, diff --git a/kernel/events/core.c b/kernel/events/core.c index 5e2bce90b477..127411400116 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -4462,20 +4462,6 @@ void perf_output_sample(struct perf_output_handle *handle, } } - if (!event->attr.watermark) { - int wakeup_events = event->attr.wakeup_events; - - if (wakeup_events) { - struct ring_buffer *rb = handle->rb; - int events = local_inc_return(&rb->events); - - if (events >= wakeup_events) { - local_sub(wakeup_events, &rb->events); - local_inc(&rb->wakeup); - } - } - } - if (sample_type & PERF_SAMPLE_BRANCH_STACK) { if (data->br_stack) { size_t size; @@ -4511,16 +4497,31 @@ void perf_output_sample(struct perf_output_handle *handle, } } - if (sample_type & PERF_SAMPLE_STACK_USER) + if (sample_type & PERF_SAMPLE_STACK_USER) { perf_output_sample_ustack(handle, data->stack_user_size, data->regs_user.regs); + } if (sample_type & PERF_SAMPLE_WEIGHT) perf_output_put(handle, data->weight); if (sample_type & PERF_SAMPLE_DATA_SRC) perf_output_put(handle, data->data_src.val); + + if (!event->attr.watermark) { + int wakeup_events = event->attr.wakeup_events; + + if (wakeup_events) { + struct ring_buffer *rb = handle->rb; + int events = local_inc_return(&rb->events); + + if (events >= wakeup_events) { + local_sub(wakeup_events, &rb->events); + local_inc(&rb->wakeup); + } + } + } } void perf_prepare_sample(struct perf_event_header *header, From 860f085b74e9f0075de8140ed3a1e5b5e3e39aa8 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 28 Jun 2013 16:22:17 +0300 Subject: [PATCH 0287/3400] perf: Fix broken union in 'struct perf_event_mmap_page' The capabilities bits must not be "union'ed" together. Put them in a separate struct. Signed-off-by: Adrian Hunter Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1372425741-1676-2-git-send-email-adrian.hunter@intel.com Signed-off-by: Ingo Molnar --- include/uapi/linux/perf_event.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h index 00d8274730b4..0041aedf2297 100644 --- a/include/uapi/linux/perf_event.h +++ b/include/uapi/linux/perf_event.h @@ -375,9 +375,11 @@ struct perf_event_mmap_page { __u64 time_running; /* time event on cpu */ union { __u64 capabilities; - __u64 cap_usr_time : 1, - cap_usr_rdpmc : 1, - cap_____res : 62; + struct { + __u64 cap_usr_time : 1, + cap_usr_rdpmc : 1, + cap_____res : 62; + }; }; /* From c73deb6aecda2955716f31572516f09d930ef450 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 28 Jun 2013 16:22:18 +0300 Subject: [PATCH 0288/3400] perf/x86: Add ability to calculate TSC from perf sample timestamps For modern CPUs, perf clock is directly related to TSC. TSC can be calculated from perf clock and vice versa using a simple calculation. Two of the three componenets of that calculation are already exported in struct perf_event_mmap_page. This patch exports the third. Signed-off-by: Adrian Hunter Signed-off-by: Peter Zijlstra Cc: "H. Peter Anvin" Link: http://lkml.kernel.org/r/1372425741-1676-3-git-send-email-adrian.hunter@intel.com Signed-off-by: Ingo Molnar --- arch/x86/include/asm/tsc.h | 1 + arch/x86/kernel/cpu/perf_event.c | 6 ++++++ arch/x86/kernel/tsc.c | 6 ++++++ include/uapi/linux/perf_event.h | 22 ++++++++++++++++++++-- 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/tsc.h b/arch/x86/include/asm/tsc.h index c91e8b9d588b..235be70d5bb4 100644 --- a/arch/x86/include/asm/tsc.h +++ b/arch/x86/include/asm/tsc.h @@ -49,6 +49,7 @@ extern void tsc_init(void); extern void mark_tsc_unstable(char *reason); extern int unsynchronized_tsc(void); extern int check_tsc_unstable(void); +extern int check_tsc_disabled(void); extern unsigned long native_calibrate_tsc(void); extern int tsc_clocksource_reliable; diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index a7c7305030cc..8355c84b9729 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -1884,6 +1884,7 @@ static struct pmu pmu = { void arch_perf_update_userpage(struct perf_event_mmap_page *userpg, u64 now) { userpg->cap_usr_time = 0; + userpg->cap_usr_time_zero = 0; userpg->cap_usr_rdpmc = x86_pmu.attr_rdpmc; userpg->pmc_width = x86_pmu.cntval_bits; @@ -1897,6 +1898,11 @@ void arch_perf_update_userpage(struct perf_event_mmap_page *userpg, u64 now) userpg->time_mult = this_cpu_read(cyc2ns); userpg->time_shift = CYC2NS_SCALE_FACTOR; userpg->time_offset = this_cpu_read(cyc2ns_offset) - now; + + if (sched_clock_stable && !check_tsc_disabled()) { + userpg->cap_usr_time_zero = 1; + userpg->time_zero = this_cpu_read(cyc2ns_offset); + } } /* diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 6ff49247edf8..930e5d48f560 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -89,6 +89,12 @@ int check_tsc_unstable(void) } EXPORT_SYMBOL_GPL(check_tsc_unstable); +int check_tsc_disabled(void) +{ + return tsc_disabled; +} +EXPORT_SYMBOL_GPL(check_tsc_disabled); + #ifdef CONFIG_X86_TSC int __init notsc_setup(char *str) { diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h index 0041aedf2297..efef1d37a371 100644 --- a/include/uapi/linux/perf_event.h +++ b/include/uapi/linux/perf_event.h @@ -378,7 +378,8 @@ struct perf_event_mmap_page { struct { __u64 cap_usr_time : 1, cap_usr_rdpmc : 1, - cap_____res : 62; + cap_usr_time_zero : 1, + cap_____res : 61; }; }; @@ -420,12 +421,29 @@ struct perf_event_mmap_page { __u16 time_shift; __u32 time_mult; __u64 time_offset; + /* + * If cap_usr_time_zero, the hardware clock (e.g. TSC) can be calculated + * from sample timestamps. + * + * time = timestamp - time_zero; + * quot = time / time_mult; + * rem = time % time_mult; + * cyc = (quot << time_shift) + (rem << time_shift) / time_mult; + * + * And vice versa: + * + * quot = cyc >> time_shift; + * rem = cyc & ((1 << time_shift) - 1); + * timestamp = time_zero + quot * time_mult + + * ((rem * time_mult) >> time_shift); + */ + __u64 time_zero; /* * Hole for extension of the self monitor capabilities */ - __u64 __reserved[120]; /* align to 1k */ + __u64 __reserved[119]; /* align to 1k */ /* * Control data for the mmap() data buffer. From 3bd5a5fc8c6b9fe769777abf74b0ab5fbd7930b4 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 28 Jun 2013 16:22:19 +0300 Subject: [PATCH 0289/3400] perf tools: Add test for converting perf time to/from TSC The test uses the newly added cap_usr_time_zero and time_zero of perf_event_mmap_page. TSC from rdtsc is compared with the time from 2 perf events. The test passes if the calculated times are all in the correct order. Signed-off-by: Adrian Hunter Signed-off-by: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Link: http://lkml.kernel.org/r/1372425741-1676-4-git-send-email-adrian.hunter@intel.com Signed-off-by: Ingo Molnar --- tools/perf/Makefile | 3 + tools/perf/arch/x86/Makefile | 2 + tools/perf/arch/x86/util/tsc.c | 59 ++++++++++ tools/perf/arch/x86/util/tsc.h | 20 ++++ tools/perf/tests/builtin-test.c | 6 + tools/perf/tests/perf-time-to-tsc.c | 177 ++++++++++++++++++++++++++++ tools/perf/tests/tests.h | 1 + 7 files changed, 268 insertions(+) create mode 100644 tools/perf/arch/x86/util/tsc.c create mode 100644 tools/perf/arch/x86/util/tsc.h create mode 100644 tools/perf/tests/perf-time-to-tsc.c diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 024680b23ddc..bfd12d02a304 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -389,6 +389,9 @@ LIB_OBJS += $(OUTPUT)tests/bp_signal.o LIB_OBJS += $(OUTPUT)tests/bp_signal_overflow.o LIB_OBJS += $(OUTPUT)tests/task-exit.o LIB_OBJS += $(OUTPUT)tests/sw-clock.o +ifeq ($(ARCH),x86) +LIB_OBJS += $(OUTPUT)tests/perf-time-to-tsc.o +endif BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o BUILTIN_OBJS += $(OUTPUT)builtin-bench.o diff --git a/tools/perf/arch/x86/Makefile b/tools/perf/arch/x86/Makefile index 815841c04eb2..8801fe02f206 100644 --- a/tools/perf/arch/x86/Makefile +++ b/tools/perf/arch/x86/Makefile @@ -6,3 +6,5 @@ ifndef NO_LIBUNWIND LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind.o endif LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o +LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/tsc.o +LIB_H += arch/$(ARCH)/util/tsc.h diff --git a/tools/perf/arch/x86/util/tsc.c b/tools/perf/arch/x86/util/tsc.c new file mode 100644 index 000000000000..f1117441cdcd --- /dev/null +++ b/tools/perf/arch/x86/util/tsc.c @@ -0,0 +1,59 @@ +#include +#include + +#include + +#include "../../perf.h" +#include "../../util/types.h" +#include "../../util/debug.h" +#include "tsc.h" + +u64 perf_time_to_tsc(u64 ns, struct perf_tsc_conversion *tc) +{ + u64 time, quot, rem; + + time = ns - tc->time_zero; + quot = time / tc->time_mult; + rem = time % tc->time_mult; + return (quot << tc->time_shift) + + (rem << tc->time_shift) / tc->time_mult; +} + +u64 tsc_to_perf_time(u64 cyc, struct perf_tsc_conversion *tc) +{ + u64 quot, rem; + + quot = cyc >> tc->time_shift; + rem = cyc & ((1 << tc->time_shift) - 1); + return tc->time_zero + quot * tc->time_mult + + ((rem * tc->time_mult) >> tc->time_shift); +} + +int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc, + struct perf_tsc_conversion *tc) +{ + bool cap_usr_time_zero; + u32 seq; + int i = 0; + + while (1) { + seq = pc->lock; + rmb(); + tc->time_mult = pc->time_mult; + tc->time_shift = pc->time_shift; + tc->time_zero = pc->time_zero; + cap_usr_time_zero = pc->cap_usr_time_zero; + rmb(); + if (pc->lock == seq && !(seq & 1)) + break; + if (++i > 10000) { + pr_debug("failed to get perf_event_mmap_page lock\n"); + return -EINVAL; + } + } + + if (!cap_usr_time_zero) + return -EOPNOTSUPP; + + return 0; +} diff --git a/tools/perf/arch/x86/util/tsc.h b/tools/perf/arch/x86/util/tsc.h new file mode 100644 index 000000000000..a24dec81c795 --- /dev/null +++ b/tools/perf/arch/x86/util/tsc.h @@ -0,0 +1,20 @@ +#ifndef TOOLS_PERF_ARCH_X86_UTIL_TSC_H__ +#define TOOLS_PERF_ARCH_X86_UTIL_TSC_H__ + +#include "../../util/types.h" + +struct perf_tsc_conversion { + u16 time_shift; + u32 time_mult; + u64 time_zero; +}; + +struct perf_event_mmap_page; + +int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc, + struct perf_tsc_conversion *tc); + +u64 perf_time_to_tsc(u64 ns, struct perf_tsc_conversion *tc); +u64 tsc_to_perf_time(u64 cyc, struct perf_tsc_conversion *tc); + +#endif /* TOOLS_PERF_ARCH_X86_UTIL_TSC_H__ */ diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 35b45f1466b5..b7b4049fabbb 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -93,6 +93,12 @@ static struct test { .desc = "Test software clock events have valid period values", .func = test__sw_clock_freq, }, +#if defined(__x86_64__) || defined(__i386__) + { + .desc = "Test converting perf time to TSC", + .func = test__perf_time_to_tsc, + }, +#endif { .func = NULL, }, diff --git a/tools/perf/tests/perf-time-to-tsc.c b/tools/perf/tests/perf-time-to-tsc.c new file mode 100644 index 000000000000..0ab61b1f408e --- /dev/null +++ b/tools/perf/tests/perf-time-to-tsc.c @@ -0,0 +1,177 @@ +#include +#include +#include +#include +#include + +#include "parse-events.h" +#include "evlist.h" +#include "evsel.h" +#include "thread_map.h" +#include "cpumap.h" +#include "tests.h" + +#include "../arch/x86/util/tsc.h" + +#define CHECK__(x) { \ + while ((x) < 0) { \ + pr_debug(#x " failed!\n"); \ + goto out_err; \ + } \ +} + +#define CHECK_NOT_NULL__(x) { \ + while ((x) == NULL) { \ + pr_debug(#x " failed!\n"); \ + goto out_err; \ + } \ +} + +static u64 rdtsc(void) +{ + unsigned int low, high; + + asm volatile("rdtsc" : "=a" (low), "=d" (high)); + + return low | ((u64)high) << 32; +} + +/** + * test__perf_time_to_tsc - test converting perf time to TSC. + * + * This function implements a test that checks that the conversion of perf time + * to and from TSC is consistent with the order of events. If the test passes + * %0 is returned, otherwise %-1 is returned. If TSC conversion is not + * supported then then the test passes but " (not supported)" is printed. + */ +int test__perf_time_to_tsc(void) +{ + struct perf_record_opts opts = { + .mmap_pages = UINT_MAX, + .user_freq = UINT_MAX, + .user_interval = ULLONG_MAX, + .freq = 4000, + .target = { + .uses_mmap = true, + }, + .sample_time = true, + }; + struct thread_map *threads = NULL; + struct cpu_map *cpus = NULL; + struct perf_evlist *evlist = NULL; + struct perf_evsel *evsel = NULL; + int err = -1, ret, i; + const char *comm1, *comm2; + struct perf_tsc_conversion tc; + struct perf_event_mmap_page *pc; + union perf_event *event; + u64 test_tsc, comm1_tsc, comm2_tsc; + u64 test_time, comm1_time = 0, comm2_time = 0; + + threads = thread_map__new(-1, getpid(), UINT_MAX); + CHECK_NOT_NULL__(threads); + + cpus = cpu_map__new(NULL); + CHECK_NOT_NULL__(cpus); + + evlist = perf_evlist__new(); + CHECK_NOT_NULL__(evlist); + + perf_evlist__set_maps(evlist, cpus, threads); + + CHECK__(parse_events(evlist, "cycles:u")); + + perf_evlist__config(evlist, &opts); + + evsel = perf_evlist__first(evlist); + + evsel->attr.comm = 1; + evsel->attr.disabled = 1; + evsel->attr.enable_on_exec = 0; + + CHECK__(perf_evlist__open(evlist)); + + CHECK__(perf_evlist__mmap(evlist, UINT_MAX, false)); + + pc = evlist->mmap[0].base; + ret = perf_read_tsc_conversion(pc, &tc); + if (ret) { + if (ret == -EOPNOTSUPP) { + fprintf(stderr, " (not supported)"); + return 0; + } + goto out_err; + } + + perf_evlist__enable(evlist); + + comm1 = "Test COMM 1"; + CHECK__(prctl(PR_SET_NAME, (unsigned long)comm1, 0, 0, 0)); + + test_tsc = rdtsc(); + + comm2 = "Test COMM 2"; + CHECK__(prctl(PR_SET_NAME, (unsigned long)comm2, 0, 0, 0)); + + perf_evlist__disable(evlist); + + for (i = 0; i < evlist->nr_mmaps; i++) { + while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { + struct perf_sample sample; + + if (event->header.type != PERF_RECORD_COMM || + (pid_t)event->comm.pid != getpid() || + (pid_t)event->comm.tid != getpid()) + continue; + + if (strcmp(event->comm.comm, comm1) == 0) { + CHECK__(perf_evsel__parse_sample(evsel, event, + &sample)); + comm1_time = sample.time; + } + if (strcmp(event->comm.comm, comm2) == 0) { + CHECK__(perf_evsel__parse_sample(evsel, event, + &sample)); + comm2_time = sample.time; + } + } + } + + if (!comm1_time || !comm2_time) + goto out_err; + + test_time = tsc_to_perf_time(test_tsc, &tc); + comm1_tsc = perf_time_to_tsc(comm1_time, &tc); + comm2_tsc = perf_time_to_tsc(comm2_time, &tc); + + pr_debug("1st event perf time %"PRIu64" tsc %"PRIu64"\n", + comm1_time, comm1_tsc); + pr_debug("rdtsc time %"PRIu64" tsc %"PRIu64"\n", + test_time, test_tsc); + pr_debug("2nd event perf time %"PRIu64" tsc %"PRIu64"\n", + comm2_time, comm2_tsc); + + if (test_time <= comm1_time || + test_time >= comm2_time) + goto out_err; + + if (test_tsc <= comm1_tsc || + test_tsc >= comm2_tsc) + goto out_err; + + err = 0; + +out_err: + if (evlist) { + perf_evlist__disable(evlist); + perf_evlist__munmap(evlist); + perf_evlist__close(evlist); + perf_evlist__delete(evlist); + } + if (cpus) + cpu_map__delete(cpus); + if (threads) + thread_map__delete(threads); + + return err; +} diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index 07a92f9c6712..d22202aa16e9 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h @@ -35,5 +35,6 @@ int test__bp_signal(void); int test__bp_signal_overflow(void); int test__task_exit(void); int test__sw_clock_freq(void); +int test__perf_time_to_tsc(void); #endif /* TESTS_H */ From 685207963be973fbb73550db6edaf920a283e1a7 Mon Sep 17 00:00:00 2001 From: Vladimir Davydov Date: Mon, 15 Jul 2013 17:49:19 +0400 Subject: [PATCH 0290/3400] sched: Move h_load calculation to task_h_load() The bad thing about update_h_load(), which computes hierarchical load factor for task groups, is that it is called for each task group in the system before every load balancer run, and since rebalance can be triggered very often, this function can eat really a lot of cpu time if there are many cpu cgroups in the system. Although the situation was improved significantly by commit a35b646 ('sched, cgroup: Reduce rq->lock hold times for large cgroup hierarchies'), the problem still can arise under some kinds of loads, e.g. when cpus are switching from idle to busy and back very frequently. For instance, when I start 1000 of processes that wake up every millisecond on my 8 cpus host, 'top' and 'perf top' show: Cpu(s): 17.8%us, 24.3%sy, 0.0%ni, 57.9%id, 0.0%wa, 0.0%hi, 0.0%si Events: 243K cycles 7.57% [kernel] [k] __schedule 7.08% [kernel] [k] timerqueue_add 6.13% libc-2.12.so [.] usleep Then if I create 10000 *idle* cpu cgroups (no processes in them), cpu usage increases significantly although the 'wakers' are still executing in the root cpu cgroup: Cpu(s): 19.1%us, 48.7%sy, 0.0%ni, 31.6%id, 0.0%wa, 0.0%hi, 0.7%si Events: 230K cycles 24.56% [kernel] [k] tg_load_down 5.76% [kernel] [k] __schedule This happens because this particular kind of load triggers 'new idle' rebalance very frequently, which requires calling update_h_load(), which, in turn, calls tg_load_down() for every *idle* cpu cgroup even though it is absolutely useless, because idle cpu cgroups have no tasks to pull. This patch tries to improve the situation by making h_load calculation proceed only when h_load is really necessary. To achieve this, it substitutes update_h_load() with update_cfs_rq_h_load(), which computes h_load only for a given cfs_rq and all its ascendants, and makes the load balancer call this function whenever it considers if a task should be pulled, i.e. it moves h_load calculations directly to task_h_load(). For h_load of the same cfs_rq not to be updated multiple times (in case several tasks in the same cgroup are considered during the same balance run), the patch keeps the time of the last h_load update for each cfs_rq and breaks calculation when it finds h_load to be uptodate. The benefit of it is that h_load is computed only for those cfs_rq's, which really need it, in particular all idle task groups are skipped. Although this, in fact, moves h_load calculation under rq lock, it should not affect latency much, because the amount of work done under rq lock while trying to pull tasks is limited by sched_nr_migrate. After the patch applied with the setup described above (1000 wakers in the root cgroup and 10000 idle cgroups), I get: Cpu(s): 16.9%us, 24.8%sy, 0.0%ni, 58.4%id, 0.0%wa, 0.0%hi, 0.0%si Events: 242K cycles 7.57% [kernel] [k] __schedule 6.70% [kernel] [k] timerqueue_add 5.93% libc-2.12.so [.] usleep Signed-off-by: Vladimir Davydov Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1373896159-1278-1-git-send-email-vdavydov@parallels.com Signed-off-by: Ingo Molnar --- kernel/sched/fair.c | 58 +++++++++++++++++++++----------------------- kernel/sched/sched.h | 7 +++--- 2 files changed, 30 insertions(+), 35 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index bb456f44b7b1..765d87acdf05 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -4171,47 +4171,48 @@ static void update_blocked_averages(int cpu) } /* - * Compute the cpu's hierarchical load factor for each task group. + * Compute the hierarchical load factor for cfs_rq and all its ascendants. * This needs to be done in a top-down fashion because the load of a child * group is a fraction of its parents load. */ -static int tg_load_down(struct task_group *tg, void *data) +static void update_cfs_rq_h_load(struct cfs_rq *cfs_rq) { - unsigned long load; - long cpu = (long)data; - - if (!tg->parent) { - load = cpu_rq(cpu)->avg.load_avg_contrib; - } else { - load = tg->parent->cfs_rq[cpu]->h_load; - load = div64_ul(load * tg->se[cpu]->avg.load_avg_contrib, - tg->parent->cfs_rq[cpu]->runnable_load_avg + 1); - } - - tg->cfs_rq[cpu]->h_load = load; - - return 0; -} - -static void update_h_load(long cpu) -{ - struct rq *rq = cpu_rq(cpu); + struct rq *rq = rq_of(cfs_rq); + struct sched_entity *se = cfs_rq->tg->se[cpu_of(rq)]; unsigned long now = jiffies; + unsigned long load; - if (rq->h_load_throttle == now) + if (cfs_rq->last_h_load_update == now) return; - rq->h_load_throttle = now; + cfs_rq->h_load_next = NULL; + for_each_sched_entity(se) { + cfs_rq = cfs_rq_of(se); + cfs_rq->h_load_next = se; + if (cfs_rq->last_h_load_update == now) + break; + } - rcu_read_lock(); - walk_tg_tree(tg_load_down, tg_nop, (void *)cpu); - rcu_read_unlock(); + if (!se) { + cfs_rq->h_load = rq->avg.load_avg_contrib; + cfs_rq->last_h_load_update = now; + } + + while ((se = cfs_rq->h_load_next) != NULL) { + load = cfs_rq->h_load; + load = div64_ul(load * se->avg.load_avg_contrib, + cfs_rq->runnable_load_avg + 1); + cfs_rq = group_cfs_rq(se); + cfs_rq->h_load = load; + cfs_rq->last_h_load_update = now; + } } static unsigned long task_h_load(struct task_struct *p) { struct cfs_rq *cfs_rq = task_cfs_rq(p); + update_cfs_rq_h_load(cfs_rq); return div64_ul(p->se.avg.load_avg_contrib * cfs_rq->h_load, cfs_rq->runnable_load_avg + 1); } @@ -4220,10 +4221,6 @@ static inline void update_blocked_averages(int cpu) { } -static inline void update_h_load(long cpu) -{ -} - static unsigned long task_h_load(struct task_struct *p) { return p->se.avg.load_avg_contrib; @@ -5108,7 +5105,6 @@ redo: env.src_rq = busiest; env.loop_max = min(sysctl_sched_nr_migrate, busiest->nr_running); - update_h_load(env.src_cpu); more_balance: local_irq_save(flags); double_rq_lock(env.dst_rq, busiest); diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index ef0a7b2439dd..5e129efb84ce 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -285,7 +285,6 @@ struct cfs_rq { /* Required to track per-cpu representation of a task_group */ u32 tg_runnable_contrib; unsigned long tg_load_contrib; -#endif /* CONFIG_FAIR_GROUP_SCHED */ /* * h_load = weight * f(tg) @@ -294,6 +293,9 @@ struct cfs_rq { * this group. */ unsigned long h_load; + u64 last_h_load_update; + struct sched_entity *h_load_next; +#endif /* CONFIG_FAIR_GROUP_SCHED */ #endif /* CONFIG_SMP */ #ifdef CONFIG_FAIR_GROUP_SCHED @@ -429,9 +431,6 @@ struct rq { #ifdef CONFIG_FAIR_GROUP_SCHED /* list of leaf cfs_rq on this cpu: */ struct list_head leaf_cfs_rq_list; -#ifdef CONFIG_SMP - unsigned long h_load_throttle; -#endif /* CONFIG_SMP */ #endif /* CONFIG_FAIR_GROUP_SCHED */ #ifdef CONFIG_RT_GROUP_SCHED From 62470419e993f8d9d93db0effd3af4296ecb79a5 Mon Sep 17 00:00:00 2001 From: Michael Wang Date: Thu, 4 Jul 2013 12:55:51 +0800 Subject: [PATCH 0291/3400] sched: Implement smarter wake-affine logic The wake-affine scheduler feature is currently always trying to pull the wakee close to the waker. In theory this should be beneficial if the waker's CPU caches hot data for the wakee, and it's also beneficial in the extreme ping-pong high context switch rate case. Testing shows it can benefit hackbench up to 15%. However, the feature is somewhat blind, from which some workloads such as pgbench suffer. It's also time-consuming algorithmically. Testing shows it can damage pgbench up to 50% - far more than the benefit it brings in the best case. So wake-affine should be smarter and it should realize when to stop its thankless effort at trying to find a suitable CPU to wake on. This patch introduces 'wakee_flips', which will be increased each time the task flips (switches) its wakee target. So a high 'wakee_flips' value means the task has more than one wakee, and the bigger the number, the higher the wakeup frequency. Now when making the decision on whether to pull or not, pay attention to the wakee with a high 'wakee_flips', pulling such a task may benefit the wakee. Also imply that the waker will face cruel competition later, it could be very cruel or very fast depends on the story behind 'wakee_flips', waker therefore suffers. Furthermore, if waker also has a high 'wakee_flips', that implies that multiple tasks rely on it, then waker's higher latency will damage all of them, so pulling wakee seems to be a bad deal. Thus, when 'waker->wakee_flips / wakee->wakee_flips' becomes higher and higher, the cost of pulling seems to be worse and worse. The patch therefore helps the wake-affine feature to stop its pulling work when: wakee->wakee_flips > factor && waker->wakee_flips > (factor * wakee->wakee_flips) The 'factor' here is the number of CPUs in the current CPU's NUMA node, so a bigger node will lead to more pulling since the trial becomes more severe. After applying the patch, pgbench shows up to 40% improvements and no regressions. Tested with 12 cpu x86 server and tip 3.10.0-rc7. The percentages in the final column highlight the areas with the biggest wins, all other areas improved as well: pgbench base smart | db_size | clients | tps | | tps | +---------+---------+-------+ +-------+ | 22 MB | 1 | 10598 | | 10796 | | 22 MB | 2 | 21257 | | 21336 | | 22 MB | 4 | 41386 | | 41622 | | 22 MB | 8 | 51253 | | 57932 | | 22 MB | 12 | 48570 | | 54000 | | 22 MB | 16 | 46748 | | 55982 | +19.75% | 22 MB | 24 | 44346 | | 55847 | +25.93% | 22 MB | 32 | 43460 | | 54614 | +25.66% | 7484 MB | 1 | 8951 | | 9193 | | 7484 MB | 2 | 19233 | | 19240 | | 7484 MB | 4 | 37239 | | 37302 | | 7484 MB | 8 | 46087 | | 50018 | | 7484 MB | 12 | 42054 | | 48763 | | 7484 MB | 16 | 40765 | | 51633 | +26.66% | 7484 MB | 24 | 37651 | | 52377 | +39.11% | 7484 MB | 32 | 37056 | | 51108 | +37.92% | 15 GB | 1 | 8845 | | 9104 | | 15 GB | 2 | 19094 | | 19162 | | 15 GB | 4 | 36979 | | 36983 | | 15 GB | 8 | 46087 | | 49977 | | 15 GB | 12 | 41901 | | 48591 | | 15 GB | 16 | 40147 | | 50651 | +26.16% | 15 GB | 24 | 37250 | | 52365 | +40.58% | 15 GB | 32 | 36470 | | 50015 | +37.14% Signed-off-by: Michael Wang Cc: Mike Galbraith Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/51D50057.9000809@linux.vnet.ibm.com [ Improved the changelog. ] Signed-off-by: Ingo Molnar --- include/linux/sched.h | 3 +++ kernel/sched/fair.c | 47 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/include/linux/sched.h b/include/linux/sched.h index 50d04b92ceda..4f163a8ffabf 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1034,6 +1034,9 @@ struct task_struct { #ifdef CONFIG_SMP struct llist_node wake_entry; int on_cpu; + struct task_struct *last_wakee; + unsigned long wakee_flips; + unsigned long wakee_flip_decay_ts; #endif int on_rq; diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 765d87acdf05..860063a8c849 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -3017,6 +3017,23 @@ static unsigned long cpu_avg_load_per_task(int cpu) return 0; } +static void record_wakee(struct task_struct *p) +{ + /* + * Rough decay (wiping) for cost saving, don't worry + * about the boundary, really active task won't care + * about the loss. + */ + if (jiffies > current->wakee_flip_decay_ts + HZ) { + current->wakee_flips = 0; + current->wakee_flip_decay_ts = jiffies; + } + + if (current->last_wakee != p) { + current->last_wakee = p; + current->wakee_flips++; + } +} static void task_waking_fair(struct task_struct *p) { @@ -3037,6 +3054,7 @@ static void task_waking_fair(struct task_struct *p) #endif se->vruntime -= min_vruntime; + record_wakee(p); } #ifdef CONFIG_FAIR_GROUP_SCHED @@ -3155,6 +3173,28 @@ static inline unsigned long effective_load(struct task_group *tg, int cpu, #endif +static int wake_wide(struct task_struct *p) +{ + int factor = nr_cpus_node(cpu_to_node(smp_processor_id())); + + /* + * Yeah, it's the switching-frequency, could means many wakee or + * rapidly switch, use factor here will just help to automatically + * adjust the loose-degree, so bigger node will lead to more pull. + */ + if (p->wakee_flips > factor) { + /* + * wakee is somewhat hot, it needs certain amount of cpu + * resource, so if waker is far more hot, prefer to leave + * it alone. + */ + if (current->wakee_flips > (factor * p->wakee_flips)) + return 1; + } + + return 0; +} + static int wake_affine(struct sched_domain *sd, struct task_struct *p, int sync) { s64 this_load, load; @@ -3164,6 +3204,13 @@ static int wake_affine(struct sched_domain *sd, struct task_struct *p, int sync) unsigned long weight; int balanced; + /* + * If we wake multiple tasks be careful to not bounce + * ourselves around too much. + */ + if (wake_wide(p)) + return 0; + idx = sd->wake_idx; this_cpu = smp_processor_id(); prev_cpu = task_cpu(p); From 7d9ffa8961482232d964173cccba6e14d2d543b2 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 4 Jul 2013 12:56:46 +0800 Subject: [PATCH 0292/3400] sched: Micro-optimize the smart wake-affine logic Smart wake-affine is using node-size as the factor currently, but the overhead of the mask operation is high. Thus, this patch introduce the 'sd_llc_size' percpu variable, which will record the highest cache-share domain size, and make it to be the new factor, in order to reduce the overhead and make it more reasonable. Tested-by: Davidlohr Bueso Tested-by: Michael Wang Signed-off-by: Peter Zijlstra Acked-by: Michael Wang Cc: Mike Galbraith Link: http://lkml.kernel.org/r/51D5008E.6030102@linux.vnet.ibm.com [ Tidied up the changelog. ] Signed-off-by: Ingo Molnar --- kernel/sched/core.c | 7 ++++++- kernel/sched/fair.c | 2 +- kernel/sched/sched.h | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index b7c32cb7bfeb..6df0fbe53767 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -5083,18 +5083,23 @@ static void destroy_sched_domains(struct sched_domain *sd, int cpu) * two cpus are in the same cache domain, see cpus_share_cache(). */ DEFINE_PER_CPU(struct sched_domain *, sd_llc); +DEFINE_PER_CPU(int, sd_llc_size); DEFINE_PER_CPU(int, sd_llc_id); static void update_top_cache_domain(int cpu) { struct sched_domain *sd; int id = cpu; + int size = 1; sd = highest_flag_domain(cpu, SD_SHARE_PKG_RESOURCES); - if (sd) + if (sd) { id = cpumask_first(sched_domain_span(sd)); + size = cpumask_weight(sched_domain_span(sd)); + } rcu_assign_pointer(per_cpu(sd_llc, cpu), sd); + per_cpu(sd_llc_size, cpu) = size; per_cpu(sd_llc_id, cpu) = id; } diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 860063a8c849..f237437446e5 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -3175,7 +3175,7 @@ static inline unsigned long effective_load(struct task_group *tg, int cpu, static int wake_wide(struct task_struct *p) { - int factor = nr_cpus_node(cpu_to_node(smp_processor_id())); + int factor = this_cpu_read(sd_llc_size); /* * Yeah, it's the switching-frequency, could means many wakee or diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 5e129efb84ce..4c1cb8029feb 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -594,6 +594,7 @@ static inline struct sched_domain *highest_flag_domain(int cpu, int flag) } DECLARE_PER_CPU(struct sched_domain *, sd_llc); +DECLARE_PER_CPU(int, sd_llc_size); DECLARE_PER_CPU(int, sd_llc_id); struct sched_group_power { From 4f6cc9ab5337879c4a79564b3aed4fa429d1cd12 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Mon, 15 Jul 2013 22:27:04 +0800 Subject: [PATCH 0293/3400] staging/lustre: replace num_physpages with totalram_pages The global variable num_physpages is going away. Replace it with totalram_pages. Cc: Jiang Liu Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../lustre/include/linux/libcfs/linux/linux-mem.h | 4 ++-- drivers/staging/lustre/lustre/ldlm/ldlm_lib.c | 10 +++++----- .../lustre/lustre/libcfs/linux/linux-tracefile.c | 2 +- drivers/staging/lustre/lustre/llite/lproc_llite.c | 8 ++++---- drivers/staging/lustre/lustre/obdclass/class_obd.c | 6 +++--- .../lustre/lustre/obdclass/linux/linux-sysctl.c | 6 +++--- drivers/staging/lustre/lustre/obdclass/lu_object.c | 2 +- drivers/staging/lustre/lustre/osc/lproc_osc.c | 2 +- drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c | 2 +- drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c | 4 ++-- 10 files changed, 23 insertions(+), 23 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/linux-mem.h b/drivers/staging/lustre/include/linux/libcfs/linux/linux-mem.h index 042a2bc432be..63efb7b456c6 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/linux-mem.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/linux-mem.h @@ -63,9 +63,9 @@ #if BITS_PER_LONG == 32 /* limit to lowmem on 32-bit systems */ #define NUM_CACHEPAGES \ - min(num_physpages, 1UL << (30 - PAGE_CACHE_SHIFT) * 3 / 4) + min(totalram_pages, 1UL << (30 - PAGE_CACHE_SHIFT) * 3 / 4) #else -#define NUM_CACHEPAGES num_physpages +#define NUM_CACHEPAGES totalram_pages #endif /* diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c index 42df53072dc3..aace5342b76a 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c @@ -339,8 +339,8 @@ int client_obd_setup(struct obd_device *obddev, struct lustre_cfg *lcfg) cli->cl_avail_grant = 0; /* FIXME: Should limit this for the sum of all cl_dirty_max. */ cli->cl_dirty_max = OSC_MAX_DIRTY_DEFAULT * 1024 * 1024; - if (cli->cl_dirty_max >> PAGE_CACHE_SHIFT > num_physpages / 8) - cli->cl_dirty_max = num_physpages << (PAGE_CACHE_SHIFT - 3); + if (cli->cl_dirty_max >> PAGE_CACHE_SHIFT > totalram_pages / 8) + cli->cl_dirty_max = totalram_pages << (PAGE_CACHE_SHIFT - 3); INIT_LIST_HEAD(&cli->cl_cache_waiters); INIT_LIST_HEAD(&cli->cl_loi_ready_list); INIT_LIST_HEAD(&cli->cl_loi_hp_ready_list); @@ -388,11 +388,11 @@ int client_obd_setup(struct obd_device *obddev, struct lustre_cfg *lcfg) if (!strcmp(name, LUSTRE_MDC_NAME)) { cli->cl_max_rpcs_in_flight = MDC_MAX_RIF_DEFAULT; - } else if (num_physpages >> (20 - PAGE_CACHE_SHIFT) <= 128 /* MB */) { + } else if (totalram_pages >> (20 - PAGE_CACHE_SHIFT) <= 128 /* MB */) { cli->cl_max_rpcs_in_flight = 2; - } else if (num_physpages >> (20 - PAGE_CACHE_SHIFT) <= 256 /* MB */) { + } else if (totalram_pages >> (20 - PAGE_CACHE_SHIFT) <= 256 /* MB */) { cli->cl_max_rpcs_in_flight = 3; - } else if (num_physpages >> (20 - PAGE_CACHE_SHIFT) <= 512 /* MB */) { + } else if (totalram_pages >> (20 - PAGE_CACHE_SHIFT) <= 512 /* MB */) { cli->cl_max_rpcs_in_flight = 4; } else { if (osc_on_mdt(obddev->obd_name)) diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-tracefile.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-tracefile.c index 6f563436a255..a500a0b5ba9f 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-tracefile.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-tracefile.c @@ -269,7 +269,7 @@ void cfs_print_to_console(struct ptldebug_header *hdr, int mask, int cfs_trace_max_debug_mb(void) { - int total_mb = (num_physpages >> (20 - PAGE_SHIFT)); + int total_mb = (totalram_pages >> (20 - PAGE_SHIFT)); return MAX(512, (total_mb * 80)/100); } diff --git a/drivers/staging/lustre/lustre/llite/lproc_llite.c b/drivers/staging/lustre/lustre/llite/lproc_llite.c index 6a82505c7933..a30c411b583b 100644 --- a/drivers/staging/lustre/lustre/llite/lproc_llite.c +++ b/drivers/staging/lustre/lustre/llite/lproc_llite.c @@ -243,9 +243,9 @@ static ssize_t ll_max_readahead_mb_seq_write(struct file *file, const char *buff if (rc) return rc; - if (pages_number < 0 || pages_number > num_physpages / 2) { + if (pages_number < 0 || pages_number > totalram_pages / 2) { CERROR("can't set file readahead more than %lu MB\n", - num_physpages >> (20 - PAGE_CACHE_SHIFT + 1)); /*1/2 of RAM*/ + totalram_pages >> (20 - PAGE_CACHE_SHIFT + 1)); /*1/2 of RAM*/ return -ERANGE; } @@ -388,10 +388,10 @@ static ssize_t ll_max_cached_mb_seq_write(struct file *file, const char *buffer, if (rc) RETURN(rc); - if (pages_number < 0 || pages_number > num_physpages) { + if (pages_number < 0 || pages_number > totalram_pages) { CERROR("%s: can't set max cache more than %lu MB\n", ll_get_fsname(sb, NULL, 0), - num_physpages >> (20 - PAGE_CACHE_SHIFT)); + totalram_pages >> (20 - PAGE_CACHE_SHIFT)); RETURN(-ERANGE); } diff --git a/drivers/staging/lustre/lustre/obdclass/class_obd.c b/drivers/staging/lustre/lustre/obdclass/class_obd.c index af1c2d09c47b..0715cf2af3ce 100644 --- a/drivers/staging/lustre/lustre/obdclass/class_obd.c +++ b/drivers/staging/lustre/lustre/obdclass/class_obd.c @@ -558,10 +558,10 @@ static int __init init_obdclass(void) /* Default the dirty page cache cap to 1/2 of system memory. * For clients with less memory, a larger fraction is needed * for other purposes (mostly for BGL). */ - if (num_physpages <= 512 << (20 - PAGE_CACHE_SHIFT)) - obd_max_dirty_pages = num_physpages / 4; + if (totalram_pages <= 512 << (20 - PAGE_CACHE_SHIFT)) + obd_max_dirty_pages = totalram_pages / 4; else - obd_max_dirty_pages = num_physpages / 2; + obd_max_dirty_pages = totalram_pages / 2; err = obd_init_caches(); if (err) diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c index 46aad6813cab..7b94cb7b58e0 100644 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c +++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c @@ -202,12 +202,12 @@ int LL_PROC_PROTO(proc_max_dirty_pages_in_mb) 1 << (20 - PAGE_CACHE_SHIFT)); /* Don't allow them to let dirty pages exceed 90% of system * memory and set a hard minimum of 4MB. */ - if (obd_max_dirty_pages > ((num_physpages / 10) * 9)) { + if (obd_max_dirty_pages > ((totalram_pages / 10) * 9)) { CERROR("Refusing to set max dirty pages to %u, which " "is more than 90%% of available RAM; setting " "to %lu\n", obd_max_dirty_pages, - ((num_physpages / 10) * 9)); - obd_max_dirty_pages = ((num_physpages / 10) * 9); + ((totalram_pages / 10) * 9)); + obd_max_dirty_pages = ((totalram_pages / 10) * 9); } else if (obd_max_dirty_pages < 4 << (20 - PAGE_CACHE_SHIFT)) { obd_max_dirty_pages = 4 << (20 - PAGE_CACHE_SHIFT); } diff --git a/drivers/staging/lustre/lustre/obdclass/lu_object.c b/drivers/staging/lustre/lustre/obdclass/lu_object.c index fdf0ed367693..fdaf4f8c3349 100644 --- a/drivers/staging/lustre/lustre/obdclass/lu_object.c +++ b/drivers/staging/lustre/lustre/obdclass/lu_object.c @@ -849,7 +849,7 @@ static int lu_htable_order(void) * * Size of lu_object is (arbitrary) taken as 1K (together with inode). */ - cache_size = num_physpages; + cache_size = totalram_pages; #if BITS_PER_LONG == 32 /* limit hashtable size for lowmem systems to low RAM */ diff --git a/drivers/staging/lustre/lustre/osc/lproc_osc.c b/drivers/staging/lustre/lustre/osc/lproc_osc.c index 198cf3ba1374..d2f219877927 100644 --- a/drivers/staging/lustre/lustre/osc/lproc_osc.c +++ b/drivers/staging/lustre/lustre/osc/lproc_osc.c @@ -146,7 +146,7 @@ static ssize_t osc_max_dirty_mb_seq_write(struct file *file, const char *buffer, if (pages_number <= 0 || pages_number > OSC_MAX_DIRTY_MB_MAX << (20 - PAGE_CACHE_SHIFT) || - pages_number > num_physpages / 4) /* 1/4 of RAM */ + pages_number > totalram_pages / 4) /* 1/4 of RAM */ return -ERANGE; client_obd_list_lock(&cli->cl_loi_list_lock); diff --git a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c index 3e7325499d01..2bd0d985bf1d 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c +++ b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c @@ -302,7 +302,7 @@ ptlrpc_lprocfs_req_history_max_seq_write(struct file *file, const char *buffer, * hose a kernel by allowing the request history to grow too * far. */ bufpages = (svc->srv_buf_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; - if (val > num_physpages/(2 * bufpages)) + if (val > totalram_pages / (2 * bufpages)) return -ERANGE; spin_lock(&svc->srv_lock); diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c index bf53f1bc1742..9013745ab105 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c @@ -156,7 +156,7 @@ int sptlrpc_proc_enc_pool_seq_show(struct seq_file *m, void *v) "max waitqueue depth: %u\n" "max wait time: "CFS_TIME_T"/%u\n" , - num_physpages, + totalram_pages, PAGES_PER_POOL, page_pools.epp_max_pages, page_pools.epp_max_pools, @@ -705,7 +705,7 @@ int sptlrpc_enc_pool_init(void) * maximum capacity is 1/8 of total physical memory. * is the 1/8 a good number? */ - page_pools.epp_max_pages = num_physpages / 8; + page_pools.epp_max_pages = totalram_pages / 8; page_pools.epp_max_pools = npages_to_npools(page_pools.epp_max_pages); init_waitqueue_head(&page_pools.epp_waitq); From eba32e16374beb2f479bbbf37dfa8fcf785bac3f Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Mon, 15 Jul 2013 22:27:05 +0800 Subject: [PATCH 0294/3400] staging/lustre: fix Lustre code link order Change Makefiles to keep link order in match with Lustre module dependency, so that when Lustre is built in kernel, we'll have the same dependency. Otherwise we'll crash kernel if Lustre is builtin due to missing internal dependency. Reported-by: Fengguang Wu Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/Makefile | 2 +- drivers/staging/lustre/lnet/Makefile | 2 +- drivers/staging/lustre/lustre/Makefile | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/lustre/Makefile b/drivers/staging/lustre/Makefile index 26162893fd20..fb0e0faf0760 100644 --- a/drivers/staging/lustre/Makefile +++ b/drivers/staging/lustre/Makefile @@ -1,4 +1,4 @@ subdir-ccflags-y := -I$(src)/include/ -obj-$(CONFIG_LUSTRE_FS) += lustre/ obj-$(CONFIG_LNET) += lnet/ +obj-$(CONFIG_LUSTRE_FS) += lustre/ diff --git a/drivers/staging/lustre/lnet/Makefile b/drivers/staging/lustre/lnet/Makefile index 374212b1555a..f6f03e304d81 100644 --- a/drivers/staging/lustre/lnet/Makefile +++ b/drivers/staging/lustre/lnet/Makefile @@ -1 +1 @@ -obj-$(CONFIG_LNET) := klnds/ lnet/ selftest/ +obj-$(CONFIG_LNET) += lnet/ klnds/ selftest/ diff --git a/drivers/staging/lustre/lustre/Makefile b/drivers/staging/lustre/lustre/Makefile index 3fb94fc12068..d1eb0bdef06b 100644 --- a/drivers/staging/lustre/lustre/Makefile +++ b/drivers/staging/lustre/lustre/Makefile @@ -1,2 +1,2 @@ -obj-$(CONFIG_LUSTRE_FS) := fid/ lvfs/ obdclass/ ptlrpc/ obdecho/ mgc/ lov/ \ - osc/ mdc/ lmv/ llite/ fld/ libcfs/ +obj-$(CONFIG_LUSTRE_FS) += libcfs/ lvfs/ obdclass/ ptlrpc/ fld/ osc/ mgc/ \ + fid/ lov/ mdc/ lmv/ llite/ obdecho/ From 4d2d6e29a8d56bd05cc7ea30ddfb4d3f75290cfe Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Mon, 15 Jul 2013 22:27:06 +0800 Subject: [PATCH 0295/3400] staging/lustre: don't assert module owner It can well be NULL if Lustre is builtin. Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/lu_object.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/staging/lustre/lustre/obdclass/lu_object.c b/drivers/staging/lustre/lustre/obdclass/lu_object.c index fdaf4f8c3349..5559732c0437 100644 --- a/drivers/staging/lustre/lustre/obdclass/lu_object.c +++ b/drivers/staging/lustre/lustre/obdclass/lu_object.c @@ -1315,7 +1315,6 @@ int lu_context_key_register(struct lu_context_key *key) LASSERT(key->lct_init != NULL); LASSERT(key->lct_fini != NULL); LASSERT(key->lct_tags != 0); - LASSERT(key->lct_owner != NULL); result = -ENFILE; spin_lock(&lu_keys_guard); @@ -1349,7 +1348,6 @@ static void key_fini(struct lu_context *ctx, int index) lu_ref_del(&key->lct_reference, "ctx", ctx); atomic_dec(&key->lct_used); - LASSERT(key->lct_owner != NULL); if ((ctx->lc_tags & LCT_NOREF) == 0) { #ifdef CONFIG_MODULE_UNLOAD LINVRNT(module_refcount(key->lct_owner) > 0); @@ -1557,7 +1555,6 @@ static int keys_fill(struct lu_context *ctx) if (unlikely(IS_ERR(value))) return PTR_ERR(value); - LASSERT(key->lct_owner != NULL); if (!(ctx->lc_tags & LCT_NOREF)) try_module_get(key->lct_owner); lu_ref_add_atomic(&key->lct_reference, "ctx", ctx); From 4b1e84ed8883d4f24f99417cb84165ff77a99d66 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Mon, 15 Jul 2013 22:27:07 +0800 Subject: [PATCH 0296/3400] staging/lustre: don't assert ln_refcount in LNetGetId If LNetNIInit() fails, we'll get zero ln_refcount. So fail LNetGetId() properly instead of asserting. We can get to it when socklnd fails to scan network interfaces, which is possible if Lustre is builtin. Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/lnet/api-ni.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lnet/lnet/api-ni.c b/drivers/staging/lustre/lnet/lnet/api-ni.c index e88bee362497..250c61868704 100644 --- a/drivers/staging/lustre/lnet/lnet/api-ni.c +++ b/drivers/staging/lustre/lnet/lnet/api-ni.c @@ -1541,7 +1541,10 @@ LNetGetId(unsigned int index, lnet_process_id_t *id) int rc = -ENOENT; LASSERT(the_lnet.ln_init); - LASSERT(the_lnet.ln_refcount > 0); + + /* LNetNI initilization failed? */ + if (the_lnet.ln_refcount == 0) + return rc; cpt = lnet_net_lock_current(); From c1042ed805e5c8829e0b60d4c7722b5099da40c9 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Mon, 15 Jul 2013 22:27:08 +0800 Subject: [PATCH 0297/3400] stating/lustre: only build if configured as module Lustre internal dependency needs to be cleaned up. Currently, libcfs is acting as a basis of all other modules, while other modules in lustre/ directory in turn depend on lnet modules. It creates a dependency loop that need to be fixed. Hopefully we will remove libcfs in the end. So just disable buildin for now. Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/Kconfig b/drivers/staging/lustre/lustre/Kconfig index e0eb8303a50c..c59ea5564c24 100644 --- a/drivers/staging/lustre/lustre/Kconfig +++ b/drivers/staging/lustre/lustre/Kconfig @@ -1,6 +1,6 @@ config LUSTRE_FS tristate "Lustre file system client support" - depends on STAGING && INET && BROKEN + depends on STAGING && INET && m && BROKEN select LNET select CRYPTO select CRYPTO_CRC32 From 5e8f6920eb2af88e101a1b1fc0f5fb829fe2d799 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Mon, 15 Jul 2013 22:27:09 +0800 Subject: [PATCH 0298/3400] staging/lustre: remove HIPQUAD Stephen Rothwell reported below error on powerpc: In file included from drivers/staging/lustre/include/linux/libcfs/libcfs.h:203:0, from drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h:67, from drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c:41: drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c: In function 'kiblnd_dev_need_failover': drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h:215:16: error: implicit declaration of function 'NIPQUAD' [-Werror=implicit-function-declaration] static struct libcfs_debug_msg_data msgdata; \ ^ We should just remove HIPQUAD and replace it with %pI4h. Reported-by: Stephen Rothwell Cc: Joe Perches Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../include/linux/libcfs/linux/linux-tcpip.h | 15 --- .../lustre/lnet/klnds/o2iblnd/o2iblnd.c | 8 +- .../lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c | 12 +-- .../lustre/lnet/klnds/socklnd/socklnd.c | 50 +++++----- .../lustre/lnet/klnds/socklnd/socklnd_cb.c | 94 +++++++++---------- .../lustre/lnet/klnds/socklnd/socklnd_proto.c | 60 ++++++------ drivers/staging/lustre/lnet/lnet/acceptor.c | 62 ++++++------ .../lustre/lustre/libcfs/linux/linux-tcpip.c | 4 +- 8 files changed, 145 insertions(+), 160 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/linux-tcpip.h b/drivers/staging/lustre/include/linux/libcfs/linux/linux-tcpip.h index 687f33f4e8a7..7a8d006903b9 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/linux-tcpip.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/linux-tcpip.h @@ -48,21 +48,6 @@ #include -#ifndef HIPQUAD -// XXX Should just kill all users -#if defined(__LITTLE_ENDIAN) -#define HIPQUAD(addr) \ - ((unsigned char *)&addr)[3], \ - ((unsigned char *)&addr)[2], \ - ((unsigned char *)&addr)[1], \ - ((unsigned char *)&addr)[0] -#elif defined(__BIG_ENDIAN) -#define HIPQUAD NIPQUAD -#else -#error "Please fix asm/byteorder.h" -#endif /* __LITTLE_ENDIAN */ -#endif - typedef struct socket socket_t; #define SOCK_SNDBUF(so) ((so)->sk->sk_sndbuf) diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c index 29a97943e4c7..eb6b66aa1ab3 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c @@ -2574,8 +2574,8 @@ kiblnd_dev_need_failover(kib_dev_t *dev) rc = rdma_resolve_addr(cmid, (struct sockaddr *)&srcaddr, (struct sockaddr *)&dstaddr, 1); if (rc != 0 || cmid->device == NULL) { - CERROR("Failed to bind %s:%u.%u.%u.%u to device(%p): %d\n", - dev->ibd_ifname, HIPQUAD(dev->ibd_ifip), + CERROR("Failed to bind %s:%pI4h to device(%p): %d\n", + dev->ibd_ifname, &dev->ibd_ifip, cmid->device, rc); rdma_destroy_id(cmid); return rc; @@ -2647,8 +2647,8 @@ kiblnd_dev_failover(kib_dev_t *dev) /* Bind to failover device or port */ rc = rdma_bind_addr(cmid, (struct sockaddr *)&addr); if (rc != 0 || cmid->device == NULL) { - CERROR("Failed to bind %s:%u.%u.%u.%u to device(%p): %d\n", - dev->ibd_ifname, HIPQUAD(dev->ibd_ifip), + CERROR("Failed to bind %s:%pI4h to device(%p): %d\n", + dev->ibd_ifname, &dev->ibd_ifip, cmid->device, rc); rdma_destroy_id(cmid); goto out; diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c index cc6232126dd0..63a4258ac261 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c @@ -1319,9 +1319,9 @@ kiblnd_connect_peer (kib_peer_t *peer) } LASSERT (cmid->device != NULL); - CDEBUG(D_NET, "%s: connection bound to %s:%u.%u.%u.%u:%s\n", + CDEBUG(D_NET, "%s: connection bound to %s:%pI4h:%s\n", libcfs_nid2str(peer->ibp_nid), dev->ibd_ifname, - HIPQUAD(dev->ibd_ifip), cmid->device->name); + &dev->ibd_ifip, cmid->device->name); return; @@ -2209,8 +2209,8 @@ kiblnd_passive_connect (struct rdma_cm_id *cmid, void *priv, int priv_nob) if (*kiblnd_tunables.kib_require_priv_port && ntohs(peer_addr->sin_port) >= PROT_SOCK) { __u32 ip = ntohl(peer_addr->sin_addr.s_addr); - CERROR("Peer's port (%u.%u.%u.%u:%hu) is not privileged\n", - HIPQUAD(ip), ntohs(peer_addr->sin_port)); + CERROR("Peer's port (%pI4h:%hu) is not privileged\n", + &ip, ntohs(peer_addr->sin_port)); goto failed; } @@ -2254,11 +2254,11 @@ kiblnd_passive_connect (struct rdma_cm_id *cmid, void *priv, int priv_nob) if (ni == NULL || /* no matching net */ ni->ni_nid != reqmsg->ibm_dstnid || /* right NET, wrong NID! */ net->ibn_dev != ibdev) { /* wrong device */ - CERROR("Can't accept %s on %s (%s:%d:%u.%u.%u.%u): " + CERROR("Can't accept %s on %s (%s:%d:%pI4h): " "bad dst nid %s\n", libcfs_nid2str(nid), ni == NULL ? "NA" : libcfs_nid2str(ni->ni_nid), ibdev->ibd_ifname, ibdev->ibd_nnets, - HIPQUAD(ibdev->ibd_ifip), + &ibdev->ibd_ifip, libcfs_nid2str(reqmsg->ibm_dstnid)); goto failed; diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c index c826bf9d49ac..d7b01e78ed7a 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c @@ -334,17 +334,17 @@ ksocknal_associate_route_conn_locked(ksock_route_t *route, ksock_conn_t *conn) if (route->ksnr_myipaddr != conn->ksnc_myipaddr) { if (route->ksnr_myipaddr == 0) { /* route wasn't bound locally yet (the initial route) */ - CDEBUG(D_NET, "Binding %s %u.%u.%u.%u to %u.%u.%u.%u\n", + CDEBUG(D_NET, "Binding %s %pI4h to %pI4h\n", libcfs_id2str(peer->ksnp_id), - HIPQUAD(route->ksnr_ipaddr), - HIPQUAD(conn->ksnc_myipaddr)); + &route->ksnr_ipaddr, + &conn->ksnc_myipaddr); } else { - CDEBUG(D_NET, "Rebinding %s %u.%u.%u.%u from " - "%u.%u.%u.%u to %u.%u.%u.%u\n", + CDEBUG(D_NET, "Rebinding %s %pI4h from " + "%pI4h to %pI4h\n", libcfs_id2str(peer->ksnp_id), - HIPQUAD(route->ksnr_ipaddr), - HIPQUAD(route->ksnr_myipaddr), - HIPQUAD(conn->ksnc_myipaddr)); + &route->ksnr_ipaddr, + &route->ksnr_myipaddr, + &conn->ksnc_myipaddr); iface = ksocknal_ip2iface(route->ksnr_peer->ksnp_ni, route->ksnr_myipaddr); @@ -384,9 +384,9 @@ ksocknal_add_route_locked (ksock_peer_t *peer, ksock_route_t *route) route2 = list_entry(tmp, ksock_route_t, ksnr_list); if (route2->ksnr_ipaddr == route->ksnr_ipaddr) { - CERROR ("Duplicate route %s %u.%u.%u.%u\n", + CERROR("Duplicate route %s %pI4h\n", libcfs_id2str(peer->ksnp_id), - HIPQUAD(route->ksnr_ipaddr)); + &route->ksnr_ipaddr); LBUG(); } } @@ -982,8 +982,8 @@ ksocknal_accept (lnet_ni_t *ni, socket_t *sock) LIBCFS_ALLOC(cr, sizeof(*cr)); if (cr == NULL) { LCONSOLE_ERROR_MSG(0x12f, "Dropping connection request from " - "%u.%u.%u.%u: memory exhausted\n", - HIPQUAD(peer_ip)); + "%pI4h: memory exhausted\n", + &peer_ip); return -ENOMEM; } @@ -1236,10 +1236,10 @@ ksocknal_create_conn (lnet_ni_t *ni, ksock_route_t *route, * code below probably isn't going to work. */ if (active && route->ksnr_ipaddr != conn->ksnc_ipaddr) { - CERROR("Route %s %u.%u.%u.%u connected to %u.%u.%u.%u\n", + CERROR("Route %s %pI4h connected to %pI4h\n", libcfs_id2str(peer->ksnp_id), - HIPQUAD(route->ksnr_ipaddr), - HIPQUAD(conn->ksnc_ipaddr)); + &route->ksnr_ipaddr, + &conn->ksnc_ipaddr); } /* Search for a route corresponding to the new connection and @@ -1297,10 +1297,10 @@ ksocknal_create_conn (lnet_ni_t *ni, ksock_route_t *route, * socket callbacks. */ - CDEBUG(D_NET, "New conn %s p %d.x %u.%u.%u.%u -> %u.%u.%u.%u/%d" + CDEBUG(D_NET, "New conn %s p %d.x %pI4h -> %pI4h/%d" " incarnation:"LPD64" sched[%d:%d]\n", libcfs_id2str(peerid), conn->ksnc_proto->pro_version, - HIPQUAD(conn->ksnc_myipaddr), HIPQUAD(conn->ksnc_ipaddr), + &conn->ksnc_myipaddr, &conn->ksnc_ipaddr, conn->ksnc_port, incarnation, cpt, (int)(sched - &sched->kss_info->ksi_scheds[0])); @@ -1648,10 +1648,10 @@ ksocknal_destroy_conn (ksock_conn_t *conn) last_rcv = conn->ksnc_rx_deadline - cfs_time_seconds(*ksocknal_tunables.ksnd_timeout); CERROR("Completing partial receive from %s[%d]" - ", ip %d.%d.%d.%d:%d, with error, wanted: %d, left: %d, " + ", ip %pI4h:%d, with error, wanted: %d, left: %d, " "last alive is %ld secs ago\n", libcfs_id2str(conn->ksnc_peer->ksnp_id), conn->ksnc_type, - HIPQUAD(conn->ksnc_ipaddr), conn->ksnc_port, + &conn->ksnc_ipaddr, conn->ksnc_port, conn->ksnc_rx_nob_wanted, conn->ksnc_rx_nob_left, cfs_duration_sec(cfs_time_sub(cfs_time_current(), last_rcv))); @@ -1661,25 +1661,25 @@ ksocknal_destroy_conn (ksock_conn_t *conn) case SOCKNAL_RX_LNET_HEADER: if (conn->ksnc_rx_started) CERROR("Incomplete receive of lnet header from %s" - ", ip %d.%d.%d.%d:%d, with error, protocol: %d.x.\n", + ", ip %pI4h:%d, with error, protocol: %d.x.\n", libcfs_id2str(conn->ksnc_peer->ksnp_id), - HIPQUAD(conn->ksnc_ipaddr), conn->ksnc_port, + &conn->ksnc_ipaddr, conn->ksnc_port, conn->ksnc_proto->pro_version); break; case SOCKNAL_RX_KSM_HEADER: if (conn->ksnc_rx_started) CERROR("Incomplete receive of ksock message from %s" - ", ip %d.%d.%d.%d:%d, with error, protocol: %d.x.\n", + ", ip %pI4h:%d, with error, protocol: %d.x.\n", libcfs_id2str(conn->ksnc_peer->ksnp_id), - HIPQUAD(conn->ksnc_ipaddr), conn->ksnc_port, + &conn->ksnc_ipaddr, conn->ksnc_port, conn->ksnc_proto->pro_version); break; case SOCKNAL_RX_SLOP: if (conn->ksnc_rx_started) CERROR("Incomplete receive of slops from %s" - ", ip %d.%d.%d.%d:%d, with error\n", + ", ip %pI4h:%d, with error\n", libcfs_id2str(conn->ksnc_peer->ksnp_id), - HIPQUAD(conn->ksnc_ipaddr), conn->ksnc_port); + &conn->ksnc_ipaddr, conn->ksnc_port); break; default: LBUG (); diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c index ad5e24104238..a3b8f77399ba 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c @@ -553,21 +553,21 @@ ksocknal_process_transmit (ksock_conn_t *conn, ksock_tx_t *tx) if (!conn->ksnc_closing) { switch (rc) { case -ECONNRESET: - LCONSOLE_WARN("Host %u.%u.%u.%u reset our connection " + LCONSOLE_WARN("Host %pI4h reset our connection " "while we were sending data; it may have " "rebooted.\n", - HIPQUAD(conn->ksnc_ipaddr)); + &conn->ksnc_ipaddr); break; default: LCONSOLE_WARN("There was an unexpected network error " - "while writing to %u.%u.%u.%u: %d.\n", - HIPQUAD(conn->ksnc_ipaddr), rc); + "while writing to %pI4h: %d.\n", + &conn->ksnc_ipaddr, rc); break; } CDEBUG(D_NET, "[%p] Error %d on write to %s" - " ip %d.%d.%d.%d:%d\n", conn, rc, + " ip %pI4h:%d\n", conn, rc, libcfs_id2str(conn->ksnc_peer->ksnp_id), - HIPQUAD(conn->ksnc_ipaddr), + &conn->ksnc_ipaddr, conn->ksnc_port); } @@ -700,9 +700,9 @@ ksocknal_queue_tx_locked (ksock_tx_t *tx, ksock_conn_t *conn) * ksnc_sock... */ LASSERT(!conn->ksnc_closing); - CDEBUG (D_NET, "Sending to %s ip %d.%d.%d.%d:%d\n", + CDEBUG(D_NET, "Sending to %s ip %pI4h:%d\n", libcfs_id2str(conn->ksnc_peer->ksnp_id), - HIPQUAD(conn->ksnc_ipaddr), + &conn->ksnc_ipaddr, conn->ksnc_port); ksocknal_tx_prep(conn, tx); @@ -801,9 +801,9 @@ ksocknal_find_connectable_route_locked (ksock_peer_t *peer) if (!(route->ksnr_retry_interval == 0 || /* first attempt */ cfs_time_aftereq(now, route->ksnr_timeout))) { CDEBUG(D_NET, - "Too soon to retry route %u.%u.%u.%u " + "Too soon to retry route %pI4h " "(cnted %d, interval %ld, %ld secs later)\n", - HIPQUAD(route->ksnr_ipaddr), + &route->ksnr_ipaddr, route->ksnr_connected, route->ksnr_retry_interval, cfs_duration_sec(route->ksnr_timeout - now)); @@ -1133,17 +1133,17 @@ ksocknal_process_receive (ksock_conn_t *conn) LASSERT (rc != -EAGAIN); if (rc == 0) - CDEBUG (D_NET, "[%p] EOF from %s" - " ip %d.%d.%d.%d:%d\n", conn, + CDEBUG(D_NET, "[%p] EOF from %s" + " ip %pI4h:%d\n", conn, libcfs_id2str(conn->ksnc_peer->ksnp_id), - HIPQUAD(conn->ksnc_ipaddr), + &conn->ksnc_ipaddr, conn->ksnc_port); else if (!conn->ksnc_closing) - CERROR ("[%p] Error %d on read from %s" - " ip %d.%d.%d.%d:%d\n", + CERROR("[%p] Error %d on read from %s" + " ip %pI4h:%d\n", conn, rc, libcfs_id2str(conn->ksnc_peer->ksnp_id), - HIPQUAD(conn->ksnc_ipaddr), + &conn->ksnc_ipaddr, conn->ksnc_port); /* it's not an error if conn is being closed */ @@ -1722,8 +1722,8 @@ ksocknal_recv_hello (lnet_ni_t *ni, ksock_conn_t *conn, rc = libcfs_sock_read(sock, &hello->kshm_magic, sizeof (hello->kshm_magic), timeout); if (rc != 0) { - CERROR ("Error %d reading HELLO from %u.%u.%u.%u\n", - rc, HIPQUAD(conn->ksnc_ipaddr)); + CERROR("Error %d reading HELLO from %pI4h\n", + rc, &conn->ksnc_ipaddr); LASSERT (rc < 0); return rc; } @@ -1732,18 +1732,18 @@ ksocknal_recv_hello (lnet_ni_t *ni, ksock_conn_t *conn, hello->kshm_magic != __swab32(LNET_PROTO_MAGIC) && hello->kshm_magic != le32_to_cpu (LNET_PROTO_TCP_MAGIC)) { /* Unexpected magic! */ - CERROR ("Bad magic(1) %#08x (%#08x expected) from " - "%u.%u.%u.%u\n", __cpu_to_le32 (hello->kshm_magic), + CERROR("Bad magic(1) %#08x (%#08x expected) from " + "%pI4h\n", __cpu_to_le32 (hello->kshm_magic), LNET_PROTO_TCP_MAGIC, - HIPQUAD(conn->ksnc_ipaddr)); + &conn->ksnc_ipaddr); return -EPROTO; } rc = libcfs_sock_read(sock, &hello->kshm_version, sizeof(hello->kshm_version), timeout); if (rc != 0) { - CERROR ("Error %d reading HELLO from %u.%u.%u.%u\n", - rc, HIPQUAD(conn->ksnc_ipaddr)); + CERROR("Error %d reading HELLO from %pI4h\n", + rc, &conn->ksnc_ipaddr); LASSERT (rc < 0); return rc; } @@ -1763,10 +1763,10 @@ ksocknal_recv_hello (lnet_ni_t *ni, ksock_conn_t *conn, ksocknal_send_hello(ni, conn, ni->ni_nid, hello); } - CERROR ("Unknown protocol version (%d.x expected)" - " from %u.%u.%u.%u\n", + CERROR("Unknown protocol version (%d.x expected)" + " from %pI4h\n", conn->ksnc_proto->pro_version, - HIPQUAD(conn->ksnc_ipaddr)); + &conn->ksnc_ipaddr); return -EPROTO; } @@ -1777,8 +1777,8 @@ ksocknal_recv_hello (lnet_ni_t *ni, ksock_conn_t *conn, /* receive the rest of hello message anyway */ rc = conn->ksnc_proto->pro_recv_hello(conn, hello, timeout); if (rc != 0) { - CERROR("Error %d reading or checking hello from from %u.%u.%u.%u\n", - rc, HIPQUAD(conn->ksnc_ipaddr)); + CERROR("Error %d reading or checking hello from from %pI4h\n", + rc, &conn->ksnc_ipaddr); LASSERT (rc < 0); return rc; } @@ -1787,7 +1787,7 @@ ksocknal_recv_hello (lnet_ni_t *ni, ksock_conn_t *conn, if (hello->kshm_src_nid == LNET_NID_ANY) { CERROR("Expecting a HELLO hdr with a NID, but got LNET_NID_ANY" - "from %u.%u.%u.%u\n", HIPQUAD(conn->ksnc_ipaddr)); + "from %pI4h\n", &conn->ksnc_ipaddr); return -EPROTO; } @@ -1807,9 +1807,9 @@ ksocknal_recv_hello (lnet_ni_t *ni, ksock_conn_t *conn, /* peer determines type */ conn->ksnc_type = ksocknal_invert_type(hello->kshm_ctype); if (conn->ksnc_type == SOCKLND_CONN_NONE) { - CERROR ("Unexpected type %d from %s ip %u.%u.%u.%u\n", + CERROR("Unexpected type %d from %s ip %pI4h\n", hello->kshm_ctype, libcfs_id2str(*peerid), - HIPQUAD(conn->ksnc_ipaddr)); + &conn->ksnc_ipaddr); return -EPROTO; } @@ -1819,11 +1819,11 @@ ksocknal_recv_hello (lnet_ni_t *ni, ksock_conn_t *conn, if (peerid->pid != recv_id.pid || peerid->nid != recv_id.nid) { LCONSOLE_ERROR_MSG(0x130, "Connected successfully to %s on host" - " %u.%u.%u.%u, but they claimed they were " + " %pI4h, but they claimed they were " "%s; please check your Lustre " "configuration.\n", libcfs_id2str(*peerid), - HIPQUAD(conn->ksnc_ipaddr), + &conn->ksnc_ipaddr, libcfs_id2str(recv_id)); return -EPROTO; } @@ -1834,9 +1834,9 @@ ksocknal_recv_hello (lnet_ni_t *ni, ksock_conn_t *conn, } if (ksocknal_invert_type(hello->kshm_ctype) != conn->ksnc_type) { - CERROR ("Mismatched types: me %d, %s ip %u.%u.%u.%u %d\n", + CERROR("Mismatched types: me %d, %s ip %pI4h %d\n", conn->ksnc_type, libcfs_id2str(*peerid), - HIPQUAD(conn->ksnc_ipaddr), + &conn->ksnc_ipaddr, hello->kshm_ctype); return -EPROTO; } @@ -2208,8 +2208,8 @@ ksocknal_connd (void *arg) /* consecutive retry */ if (cons_retry++ > SOCKNAL_INSANITY_RECONN) { CWARN("massive consecutive " - "re-connecting to %u.%u.%u.%u\n", - HIPQUAD(route->ksnr_ipaddr)); + "re-connecting to %pI4h\n", + &route->ksnr_ipaddr); cons_retry = 0; } } else { @@ -2274,26 +2274,26 @@ ksocknal_find_timed_out_conn (ksock_peer_t *peer) switch (error) { case ECONNRESET: CNETERR("A connection with %s " - "(%u.%u.%u.%u:%d) was reset; " + "(%pI4h:%d) was reset; " "it may have rebooted.\n", libcfs_id2str(peer->ksnp_id), - HIPQUAD(conn->ksnc_ipaddr), + &conn->ksnc_ipaddr, conn->ksnc_port); break; case ETIMEDOUT: CNETERR("A connection with %s " - "(%u.%u.%u.%u:%d) timed out; the " + "(%pI4h:%d) timed out; the " "network or node may be down.\n", libcfs_id2str(peer->ksnp_id), - HIPQUAD(conn->ksnc_ipaddr), + &conn->ksnc_ipaddr, conn->ksnc_port); break; default: CNETERR("An unexpected network error %d " "occurred with %s " - "(%u.%u.%u.%u:%d\n", error, + "(%pI4h:%d\n", error, libcfs_id2str(peer->ksnp_id), - HIPQUAD(conn->ksnc_ipaddr), + &conn->ksnc_ipaddr, conn->ksnc_port); break; } @@ -2306,10 +2306,10 @@ ksocknal_find_timed_out_conn (ksock_peer_t *peer) conn->ksnc_rx_deadline)) { /* Timed out incomplete incoming message */ ksocknal_conn_addref(conn); - CNETERR("Timeout receiving from %s (%u.%u.%u.%u:%d), " + CNETERR("Timeout receiving from %s (%pI4h:%d), " "state %d wanted %d left %d\n", libcfs_id2str(peer->ksnp_id), - HIPQUAD(conn->ksnc_ipaddr), + &conn->ksnc_ipaddr, conn->ksnc_port, conn->ksnc_rx_state, conn->ksnc_rx_nob_wanted, @@ -2324,10 +2324,10 @@ ksocknal_find_timed_out_conn (ksock_peer_t *peer) /* Timed out messages queued for sending or * buffered in the socket's send buffer */ ksocknal_conn_addref(conn); - CNETERR("Timeout sending data to %s (%u.%u.%u.%u:%d) " + CNETERR("Timeout sending data to %s (%pI4h:%d) " "the network or that node may be down.\n", libcfs_id2str(peer->ksnp_id), - HIPQUAD(conn->ksnc_ipaddr), + &conn->ksnc_ipaddr, conn->ksnc_port); return (conn); } diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c index ec57179f8d2b..6f7147dd36e5 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c @@ -496,8 +496,8 @@ ksocknal_send_hello_v1 (ksock_conn_t *conn, ksock_hello_msg_t *hello) rc = libcfs_sock_write(sock, hdr, sizeof(*hdr),lnet_acceptor_timeout()); if (rc != 0) { - CNETERR("Error %d sending HELLO hdr to %u.%u.%u.%u/%d\n", - rc, HIPQUAD(conn->ksnc_ipaddr), conn->ksnc_port); + CNETERR("Error %d sending HELLO hdr to %pI4h/%d\n", + rc, &conn->ksnc_ipaddr, conn->ksnc_port); goto out; } @@ -513,8 +513,8 @@ ksocknal_send_hello_v1 (ksock_conn_t *conn, ksock_hello_msg_t *hello) lnet_acceptor_timeout()); if (rc != 0) { CNETERR("Error %d sending HELLO payload (%d)" - " to %u.%u.%u.%u/%d\n", rc, hello->kshm_nips, - HIPQUAD(conn->ksnc_ipaddr), conn->ksnc_port); + " to %pI4h/%d\n", rc, hello->kshm_nips, + &conn->ksnc_ipaddr, conn->ksnc_port); } out: LIBCFS_FREE(hdr, sizeof(*hdr)); @@ -545,8 +545,8 @@ ksocknal_send_hello_v2 (ksock_conn_t *conn, ksock_hello_msg_t *hello) lnet_acceptor_timeout()); if (rc != 0) { - CNETERR("Error %d sending HELLO hdr to %u.%u.%u.%u/%d\n", - rc, HIPQUAD(conn->ksnc_ipaddr), conn->ksnc_port); + CNETERR("Error %d sending HELLO hdr to %pI4h/%d\n", + rc, &conn->ksnc_ipaddr, conn->ksnc_port); return rc; } @@ -558,8 +558,8 @@ ksocknal_send_hello_v2 (ksock_conn_t *conn, ksock_hello_msg_t *hello) lnet_acceptor_timeout()); if (rc != 0) { CNETERR("Error %d sending HELLO payload (%d)" - " to %u.%u.%u.%u/%d\n", rc, hello->kshm_nips, - HIPQUAD(conn->ksnc_ipaddr), conn->ksnc_port); + " to %pI4h/%d\n", rc, hello->kshm_nips, + &conn->ksnc_ipaddr, conn->ksnc_port); } return rc; @@ -583,18 +583,18 @@ ksocknal_recv_hello_v1(ksock_conn_t *conn, ksock_hello_msg_t *hello,int timeout) sizeof (*hdr) - offsetof (lnet_hdr_t, src_nid), timeout); if (rc != 0) { - CERROR ("Error %d reading rest of HELLO hdr from %u.%u.%u.%u\n", - rc, HIPQUAD(conn->ksnc_ipaddr)); + CERROR("Error %d reading rest of HELLO hdr from %pI4h\n", + rc, &conn->ksnc_ipaddr); LASSERT (rc < 0 && rc != -EALREADY); goto out; } /* ...and check we got what we expected */ if (hdr->type != cpu_to_le32 (LNET_MSG_HELLO)) { - CERROR ("Expecting a HELLO hdr," - " but got type %d from %u.%u.%u.%u\n", + CERROR("Expecting a HELLO hdr," + " but got type %d from %pI4h\n", le32_to_cpu (hdr->type), - HIPQUAD(conn->ksnc_ipaddr)); + &conn->ksnc_ipaddr); rc = -EPROTO; goto out; } @@ -607,8 +607,8 @@ ksocknal_recv_hello_v1(ksock_conn_t *conn, ksock_hello_msg_t *hello,int timeout) sizeof (__u32); if (hello->kshm_nips > LNET_MAX_INTERFACES) { - CERROR("Bad nips %d from ip %u.%u.%u.%u\n", - hello->kshm_nips, HIPQUAD(conn->ksnc_ipaddr)); + CERROR("Bad nips %d from ip %pI4h\n", + hello->kshm_nips, &conn->ksnc_ipaddr); rc = -EPROTO; goto out; } @@ -619,9 +619,9 @@ ksocknal_recv_hello_v1(ksock_conn_t *conn, ksock_hello_msg_t *hello,int timeout) rc = libcfs_sock_read(sock, hello->kshm_ips, hello->kshm_nips * sizeof(__u32), timeout); if (rc != 0) { - CERROR ("Error %d reading IPs from ip %u.%u.%u.%u\n", - rc, HIPQUAD(conn->ksnc_ipaddr)); - LASSERT (rc < 0 && rc != -EALREADY); + CERROR("Error %d reading IPs from ip %pI4h\n", + rc, &conn->ksnc_ipaddr); + LASSERT(rc < 0 && rc != -EALREADY); goto out; } @@ -629,8 +629,8 @@ ksocknal_recv_hello_v1(ksock_conn_t *conn, ksock_hello_msg_t *hello,int timeout) hello->kshm_ips[i] = __le32_to_cpu(hello->kshm_ips[i]); if (hello->kshm_ips[i] == 0) { - CERROR("Zero IP[%d] from ip %u.%u.%u.%u\n", - i, HIPQUAD(conn->ksnc_ipaddr)); + CERROR("Zero IP[%d] from ip %pI4h\n", + i, &conn->ksnc_ipaddr); rc = -EPROTO; break; } @@ -658,9 +658,9 @@ ksocknal_recv_hello_v2 (ksock_conn_t *conn, ksock_hello_msg_t *hello, int timeou offsetof(ksock_hello_msg_t, kshm_src_nid), timeout); if (rc != 0) { - CERROR ("Error %d reading HELLO from %u.%u.%u.%u\n", - rc, HIPQUAD(conn->ksnc_ipaddr)); - LASSERT (rc < 0 && rc != -EALREADY); + CERROR("Error %d reading HELLO from %pI4h\n", + rc, &conn->ksnc_ipaddr); + LASSERT(rc < 0 && rc != -EALREADY); return rc; } @@ -676,8 +676,8 @@ ksocknal_recv_hello_v2 (ksock_conn_t *conn, ksock_hello_msg_t *hello, int timeou } if (hello->kshm_nips > LNET_MAX_INTERFACES) { - CERROR("Bad nips %d from ip %u.%u.%u.%u\n", - hello->kshm_nips, HIPQUAD(conn->ksnc_ipaddr)); + CERROR("Bad nips %d from ip %pI4h\n", + hello->kshm_nips, &conn->ksnc_ipaddr); return -EPROTO; } @@ -687,9 +687,9 @@ ksocknal_recv_hello_v2 (ksock_conn_t *conn, ksock_hello_msg_t *hello, int timeou rc = libcfs_sock_read(sock, hello->kshm_ips, hello->kshm_nips * sizeof(__u32), timeout); if (rc != 0) { - CERROR ("Error %d reading IPs from ip %u.%u.%u.%u\n", - rc, HIPQUAD(conn->ksnc_ipaddr)); - LASSERT (rc < 0 && rc != -EALREADY); + CERROR("Error %d reading IPs from ip %pI4h\n", + rc, &conn->ksnc_ipaddr); + LASSERT(rc < 0 && rc != -EALREADY); return rc; } @@ -698,8 +698,8 @@ ksocknal_recv_hello_v2 (ksock_conn_t *conn, ksock_hello_msg_t *hello, int timeou __swab32s(&hello->kshm_ips[i]); if (hello->kshm_ips[i] == 0) { - CERROR("Zero IP[%d] from ip %u.%u.%u.%u\n", - i, HIPQUAD(conn->ksnc_ipaddr)); + CERROR("Zero IP[%d] from ip %pI4h\n", + i, &conn->ksnc_ipaddr); return -EPROTO; } } diff --git a/drivers/staging/lustre/lnet/lnet/acceptor.c b/drivers/staging/lustre/lnet/lnet/acceptor.c index 81ef28bbcba0..bb15bde0704c 100644 --- a/drivers/staging/lustre/lnet/lnet/acceptor.c +++ b/drivers/staging/lustre/lnet/lnet/acceptor.c @@ -101,52 +101,52 @@ lnet_connect_console_error (int rc, lnet_nid_t peer_nid, switch (rc) { /* "normal" errors */ case -ECONNREFUSED: - CNETERR("Connection to %s at host %u.%u.%u.%u on port %d was " + CNETERR("Connection to %s at host %pI4h on port %d was " "refused: check that Lustre is running on that node.\n", libcfs_nid2str(peer_nid), - HIPQUAD(peer_ip), peer_port); + &peer_ip, peer_port); break; case -EHOSTUNREACH: case -ENETUNREACH: - CNETERR("Connection to %s at host %u.%u.%u.%u " + CNETERR("Connection to %s at host %pI4h " "was unreachable: the network or that node may " "be down, or Lustre may be misconfigured.\n", - libcfs_nid2str(peer_nid), HIPQUAD(peer_ip)); + libcfs_nid2str(peer_nid), &peer_ip); break; case -ETIMEDOUT: - CNETERR("Connection to %s at host %u.%u.%u.%u on " + CNETERR("Connection to %s at host %pI4h on " "port %d took too long: that node may be hung " "or experiencing high load.\n", libcfs_nid2str(peer_nid), - HIPQUAD(peer_ip), peer_port); + &peer_ip, peer_port); break; case -ECONNRESET: - LCONSOLE_ERROR_MSG(0x11b, "Connection to %s at host %u.%u.%u.%u" + LCONSOLE_ERROR_MSG(0x11b, "Connection to %s at host %pI4h" " on port %d was reset: " "is it running a compatible version of " "Lustre and is %s one of its NIDs?\n", libcfs_nid2str(peer_nid), - HIPQUAD(peer_ip), peer_port, + &peer_ip, peer_port, libcfs_nid2str(peer_nid)); break; case -EPROTO: LCONSOLE_ERROR_MSG(0x11c, "Protocol error connecting to %s at " - "host %u.%u.%u.%u on port %d: is it running " + "host %pI4h on port %d: is it running " "a compatible version of Lustre?\n", libcfs_nid2str(peer_nid), - HIPQUAD(peer_ip), peer_port); + &peer_ip, peer_port); break; case -EADDRINUSE: LCONSOLE_ERROR_MSG(0x11d, "No privileged ports available to " - "connect to %s at host %u.%u.%u.%u on port " + "connect to %s at host %pI4h on port " "%d\n", libcfs_nid2str(peer_nid), - HIPQUAD(peer_ip), peer_port); + &peer_ip, peer_port); break; default: LCONSOLE_ERROR_MSG(0x11e, "Unexpected error %d connecting to %s" - " at host %u.%u.%u.%u on port %d\n", rc, + " at host %pI4h on port %d\n", rc, libcfs_nid2str(peer_nid), - HIPQUAD(peer_ip), peer_port); + &peer_ip, peer_port); break; } } @@ -253,8 +253,8 @@ lnet_accept(socket_t *sock, __u32 magic) if (rc != 0) CERROR("Error sending magic+version in response" - "to LNET magic from %u.%u.%u.%u: %d\n", - HIPQUAD(peer_ip), rc); + "to LNET magic from %pI4h: %d\n", + &peer_ip, rc); return -EPROTO; } @@ -265,9 +265,9 @@ lnet_accept(socket_t *sock, __u32 magic) else str = "unrecognised"; - LCONSOLE_ERROR_MSG(0x11f, "Refusing connection from %u.%u.%u.%u" + LCONSOLE_ERROR_MSG(0x11f, "Refusing connection from %pI4h" " magic %08x: %s acceptor protocol\n", - HIPQUAD(peer_ip), magic, str); + &peer_ip, magic, str); return -EPROTO; } @@ -278,7 +278,7 @@ lnet_accept(socket_t *sock, __u32 magic) accept_timeout); if (rc != 0) { CERROR("Error %d reading connection request version from " - "%u.%u.%u.%u\n", rc, HIPQUAD(peer_ip)); + "%pI4h\n", rc, &peer_ip); return -EIO; } @@ -301,8 +301,8 @@ lnet_accept(socket_t *sock, __u32 magic) if (rc != 0) CERROR("Error sending magic+version in response" - "to version %d from %u.%u.%u.%u: %d\n", - peer_version, HIPQUAD(peer_ip), rc); + "to version %d from %pI4h: %d\n", + peer_version, &peer_ip, rc); return -EPROTO; } @@ -312,7 +312,7 @@ lnet_accept(socket_t *sock, __u32 magic) accept_timeout); if (rc != 0) { CERROR("Error %d reading connection request from " - "%u.%u.%u.%u\n", rc, HIPQUAD(peer_ip)); + "%pI4h\n", rc, &peer_ip); return -EIO; } @@ -324,23 +324,23 @@ lnet_accept(socket_t *sock, __u32 magic) ni->ni_nid != cr.acr_nid) { /* right NET, wrong NID! */ if (ni != NULL) lnet_ni_decref(ni); - LCONSOLE_ERROR_MSG(0x120, "Refusing connection from %u.%u.%u.%u" + LCONSOLE_ERROR_MSG(0x120, "Refusing connection from %pI4h" " for %s: No matching NI\n", - HIPQUAD(peer_ip), libcfs_nid2str(cr.acr_nid)); + &peer_ip, libcfs_nid2str(cr.acr_nid)); return -EPERM; } if (ni->ni_lnd->lnd_accept == NULL) { /* This catches a request for the loopback LND */ lnet_ni_decref(ni); - LCONSOLE_ERROR_MSG(0x121, "Refusing connection from %u.%u.%u.%u" + LCONSOLE_ERROR_MSG(0x121, "Refusing connection from %pI4h" " for %s: NI doesn not accept IP connections\n", - HIPQUAD(peer_ip), libcfs_nid2str(cr.acr_nid)); + &peer_ip, libcfs_nid2str(cr.acr_nid)); return -EPERM; } - CDEBUG(D_NET, "Accept %s from %u.%u.%u.%u\n", - libcfs_nid2str(cr.acr_nid), HIPQUAD(peer_ip)); + CDEBUG(D_NET, "Accept %s from %pI4h\n", + libcfs_nid2str(cr.acr_nid), &peer_ip); rc = ni->ni_lnd->lnd_accept(ni, sock); @@ -410,9 +410,9 @@ lnet_acceptor(void *arg) } if (secure && peer_port > LNET_ACCEPTOR_MAX_RESERVED_PORT) { - CERROR("Refusing connection from %u.%u.%u.%u: " + CERROR("Refusing connection from %pI4h: " "insecure port %d\n", - HIPQUAD(peer_ip), peer_port); + &peer_ip, peer_port); goto failed; } @@ -420,7 +420,7 @@ lnet_acceptor(void *arg) accept_timeout); if (rc != 0) { CERROR("Error %d reading connection request from " - "%u.%u.%u.%u\n", rc, HIPQUAD(peer_ip)); + "%pI4h\n", rc, &peer_ip); goto failed; } diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-tcpip.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-tcpip.c index 855c7e87d96f..f5e78b54b3e7 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-tcpip.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-tcpip.c @@ -641,8 +641,8 @@ libcfs_sock_connect (struct socket **sockp, int *fatal, *fatal = !(rc == -EADDRNOTAVAIL); CDEBUG_LIMIT(*fatal ? D_NETERROR : D_NET, - "Error %d connecting %u.%u.%u.%u/%d -> %u.%u.%u.%u/%d\n", rc, - HIPQUAD(local_ip), local_port, HIPQUAD(peer_ip), peer_port); + "Error %d connecting %pI4h/%d -> %pI4h/%d\n", rc, + &local_ip, local_port, &peer_ip, peer_port); sock_release(*sockp); return rc; From 3867ea5a4bc4d428f8d93557fb0fbc2cac2f2cdf Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Mon, 15 Jul 2013 22:27:10 +0800 Subject: [PATCH 0299/3400] staging/lustre: fix build error when !CONFIG_SMP Three functions cfs_cpu_ht_nsiblings, cfs_cpt_cpumask and cfs_cpt_table_print are missing if !CONFIG_SMP. cpumask_t/nodemask_t/__read_mostly/____cacheline_aligned are redefined. Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../lustre/include/linux/libcfs/libcfs_cpu.h | 46 +++++++++---------- .../include/linux/libcfs/linux/linux-cpu.h | 6 --- .../lustre/lnet/klnds/o2iblnd/o2iblnd.c | 2 + .../lustre/lustre/libcfs/linux/linux-cpu.c | 46 ++----------------- .../staging/lustre/lustre/ptlrpc/service.c | 11 ++++- 5 files changed, 37 insertions(+), 74 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_cpu.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_cpu.h index 6ae7415a3b99..c87efb49ebc2 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_cpu.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_cpu.h @@ -75,11 +75,19 @@ #ifndef __LIBCFS_CPU_H__ #define __LIBCFS_CPU_H__ -#ifndef HAVE_LIBCFS_CPT - -typedef unsigned long cpumask_t; -typedef unsigned long nodemask_t; +/* any CPU partition */ +#define CFS_CPT_ANY (-1) +#ifdef CONFIG_SMP +/** + * return cpumask of CPU partition \a cpt + */ +cpumask_t *cfs_cpt_cpumask(struct cfs_cpt_table *cptab, int cpt); +/** + * print string information of cpt-table + */ +int cfs_cpt_table_print(struct cfs_cpt_table *cptab, char *buf, int len); +#else /* !CONFIG_SMP */ struct cfs_cpt_table { /* # of CPU partitions */ int ctb_nparts; @@ -91,10 +99,18 @@ struct cfs_cpt_table { __u64 ctb_version; }; -#endif /* !HAVE_LIBCFS_CPT */ +static inline cpumask_t * +cfs_cpt_cpumask(struct cfs_cpt_table *cptab, int cpt) +{ + return NULL; +} -/* any CPU partition */ -#define CFS_CPT_ANY (-1) +static inline int +cfs_cpt_table_print(struct cfs_cpt_table *cptab, char *buf, int len) +{ + return 0; +} +#endif /* CONFIG_SMP */ extern struct cfs_cpt_table *cfs_cpt_table; @@ -106,10 +122,6 @@ void cfs_cpt_table_free(struct cfs_cpt_table *cptab); * create a cfs_cpt_table with \a ncpt number of partitions */ struct cfs_cpt_table *cfs_cpt_table_alloc(unsigned int ncpt); -/** - * print string information of cpt-table - */ -int cfs_cpt_table_print(struct cfs_cpt_table *cptab, char *buf, int len); /** * return total number of CPU partitions in \a cptab */ @@ -123,10 +135,6 @@ int cfs_cpt_weight(struct cfs_cpt_table *cptab, int cpt); * is there any online CPU in CPU partition \a cpt */ int cfs_cpt_online(struct cfs_cpt_table *cptab, int cpt); -/** - * return cpumask of CPU partition \a cpt - */ -cpumask_t *cfs_cpt_cpumask(struct cfs_cpt_table *cptab, int cpt); /** * return nodemask of CPU partition \a cpt */ @@ -200,14 +208,6 @@ int cfs_cpt_spread_node(struct cfs_cpt_table *cptab, int cpt); #define cfs_cpt_for_each(i, cptab) \ for (i = 0; i < cfs_cpt_number(cptab); i++) -#ifndef __read_mostly -# define __read_mostly -#endif - -#ifndef ____cacheline_aligned -#define ____cacheline_aligned -#endif - int cfs_cpu_init(void); void cfs_cpu_fini(void); diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/linux-cpu.h b/drivers/staging/lustre/include/linux/libcfs/linux/linux-cpu.h index 224371c92f7c..5f793f223750 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/linux-cpu.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/linux-cpu.h @@ -81,12 +81,6 @@ struct cfs_cpt_table { nodemask_t *ctb_nodemask; }; -void cfs_cpu_core_siblings(int cpu, cpumask_t *mask); -void cfs_cpu_ht_siblings(int cpu, cpumask_t *mask); -void cfs_node_to_cpumask(int node, cpumask_t *mask); -int cfs_cpu_core_nsiblings(int cpu); -int cfs_cpu_ht_nsiblings(int cpu); - /** * comment out definitions for compatible layer * #define CFS_CPU_NR NR_CPUS diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c index eb6b66aa1ab3..86397f96b033 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c @@ -702,6 +702,8 @@ kiblnd_get_completion_vector(kib_conn_t *conn, int cpt) return 0; mask = cfs_cpt_cpumask(lnet_cpt_table(), cpt); + if (mask == NULL) + return 0; /* hash NID to CPU id in this partition... */ off = do_div(nid, cpus_weight(*mask)); diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-cpu.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-cpu.c index 95142d190971..00ab8fdc1053 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-cpu.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-cpu.c @@ -76,62 +76,22 @@ struct cfs_cpt_data { static struct cfs_cpt_data cpt_data; -void -cfs_cpu_core_siblings(int cpu, cpumask_t *mask) +static void cfs_cpu_core_siblings(int cpu, cpumask_t *mask) { /* return cpumask of cores in the same socket */ cpumask_copy(mask, topology_core_cpumask(cpu)); } -EXPORT_SYMBOL(cfs_cpu_core_siblings); - -/* return number of cores in the same socket of \a cpu */ -int -cfs_cpu_core_nsiblings(int cpu) -{ - int num; - - down(&cpt_data.cpt_mutex); - - cfs_cpu_core_siblings(cpu, cpt_data.cpt_cpumask); - num = cpus_weight(*cpt_data.cpt_cpumask); - - up(&cpt_data.cpt_mutex); - - return num; -} -EXPORT_SYMBOL(cfs_cpu_core_nsiblings); /* return cpumask of HTs in the same core */ -void -cfs_cpu_ht_siblings(int cpu, cpumask_t *mask) +static void cfs_cpu_ht_siblings(int cpu, cpumask_t *mask) { cpumask_copy(mask, topology_thread_cpumask(cpu)); } -EXPORT_SYMBOL(cfs_cpu_ht_siblings); -/* return number of HTs in the same core of \a cpu */ -int -cfs_cpu_ht_nsiblings(int cpu) -{ - int num; - - down(&cpt_data.cpt_mutex); - - cfs_cpu_ht_siblings(cpu, cpt_data.cpt_cpumask); - num = cpus_weight(*cpt_data.cpt_cpumask); - - up(&cpt_data.cpt_mutex); - - return num; -} -EXPORT_SYMBOL(cfs_cpu_ht_nsiblings); - -void -cfs_node_to_cpumask(int node, cpumask_t *mask) +static void cfs_node_to_cpumask(int node, cpumask_t *mask) { cpumask_copy(mask, cpumask_of_node(node)); } -EXPORT_SYMBOL(cfs_node_to_cpumask); void cfs_cpt_table_free(struct cfs_cpt_table *cptab) diff --git a/drivers/staging/lustre/lustre/ptlrpc/service.c b/drivers/staging/lustre/lustre/ptlrpc/service.c index 1667b8e86012..cd1bab5a2520 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/service.c +++ b/drivers/staging/lustre/lustre/ptlrpc/service.c @@ -551,6 +551,7 @@ ptlrpc_server_nthreads_check(struct ptlrpc_service *svc, if (tc->tc_thr_factor != 0) { int factor = tc->tc_thr_factor; const int fade = 4; + cpumask_t mask; /* * User wants to increase number of threads with for @@ -564,7 +565,8 @@ ptlrpc_server_nthreads_check(struct ptlrpc_service *svc, * have too many threads no matter how many cores/HTs * there are. */ - if (cfs_cpu_ht_nsiblings(0) > 1) { /* weight is # of HTs */ + cpumask_copy(&mask, topology_thread_cpumask(0)); + if (cpus_weight(mask) > 1) { /* weight is # of HTs */ /* depress thread factor for hyper-thread */ factor = factor - (factor >> 1) + (factor >> 3); } @@ -2776,11 +2778,13 @@ int ptlrpc_start_thread(struct ptlrpc_service_part *svcpt, int wait) int ptlrpc_hr_init(void) { + cpumask_t mask; struct ptlrpc_hr_partition *hrp; struct ptlrpc_hr_thread *hrt; int rc; int i; int j; + int weight; ENTRY; memset(&ptlrpc_hr, 0, sizeof(ptlrpc_hr)); @@ -2793,6 +2797,9 @@ int ptlrpc_hr_init(void) init_waitqueue_head(&ptlrpc_hr.hr_waitq); + cpumask_copy(&mask, topology_thread_cpumask(0)); + weight = cpus_weight(mask); + cfs_percpt_for_each(hrp, i, ptlrpc_hr.hr_partitions) { hrp->hrp_cpt = i; @@ -2800,7 +2807,7 @@ int ptlrpc_hr_init(void) atomic_set(&hrp->hrp_nstopped, 0); hrp->hrp_nthrs = cfs_cpt_weight(ptlrpc_hr.hr_cpt_table, i); - hrp->hrp_nthrs /= cfs_cpu_ht_nsiblings(0); + hrp->hrp_nthrs /= weight; LASSERT(hrp->hrp_nthrs > 0); OBD_CPT_ALLOC(hrp->hrp_thrs, ptlrpc_hr.hr_cpt_table, i, From 0e145b443e7b8c73e29470f069b0aa61835e4a11 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Mon, 15 Jul 2013 22:27:11 +0800 Subject: [PATCH 0300/3400] staging/lustre: fix build on s390 As reported by Fengguang: In file included from drivers/staging/lustre/lustre/obdclass/../include/lustre/lustre_idl.h:99:0, from drivers/staging/lustre/lustre/obdclass/../include/lprocfs_status.h:46, from drivers/staging/lustre/lustre/obdclass/../include/obd_support.h:42, from drivers/staging/lustre/lustre/obdclass/../include/obd_class.h:40, from drivers/staging/lustre/lustre/obdclass/lu_object.c:53: drivers/staging/lustre/lustre/obdclass/../include/lustre/lustre_user.h:356:10: error: field 'lmd_st' has incomplete type drivers/staging/lustre/lustre/obdclass/../include/lustre/lustre_user.h:361:10: error: field 'lmd_st' has incomplete type Reported-by: Fengguang Wu Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../lustre/lustre/include/linux/lustre_user.h | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_user.h b/drivers/staging/lustre/lustre/include/linux/lustre_user.h index ebaf92977f7f..ea9393c625cc 100644 --- a/drivers/staging/lustre/lustre/include/linux/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/linux/lustre_user.h @@ -53,15 +53,19 @@ #include -#if defined(__x86_64__) || defined(__ia64__) || defined(__ppc64__) || \ - defined(__craynv) || defined (__mips64__) || defined(__powerpc64__) -typedef struct stat lstat_t; -#define lstat_f lstat -#define HAVE_LOV_USER_MDS_DATA -#else +/* + * We need to always use 64bit version because the structure + * is shared across entire cluster where 32bit and 64bit machines + * are co-existing. + */ +#if __BITS_PER_LONG != 64 || defined(__ARCH_WANT_STAT64) typedef struct stat64 lstat_t; #define lstat_f lstat64 -#define HAVE_LOV_USER_MDS_DATA +#else +typedef struct stat lstat_t; +#define lstat_f lstat #endif +#define HAVE_LOV_USER_MDS_DATA + #endif /* _LUSTRE_USER_H */ From 2870cd102c1acdab10908625ec0772729d7ec6dc Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Mon, 15 Jul 2013 22:27:12 +0800 Subject: [PATCH 0301/3400] staging/lustre/llite: add missing include file for prefetchw Got below errors on s390 build: CC [M] drivers/staging/lustre/lustre/llite/dir.o drivers/staging/lustre/lustre/llite/dir.c: In function 'll_dir_filler': drivers/staging/lustre/lustre/llite/dir.c:225:3: error: implicit declaration of function 'prefetchw' [-Werror=implicit-function-declaration] Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/dir.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 23c61fe81965..13a6426bdd9f 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -45,6 +45,7 @@ #include #include // for wait_on_buffer #include +#include #define DEBUG_SUBSYSTEM S_LLITE From 9147dc8d54a1c15f407aca3beeae5797d0b47d1b Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Mon, 15 Jul 2013 22:27:13 +0800 Subject: [PATCH 0302/3400] staging/lustre/llite: fix build erorr if CONFIG_FS_POSIX_ACL is off Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../lustre/lustre/llite/llite_internal.h | 21 ++++++++++++------- drivers/staging/lustre/lustre/llite/xattr.c | 2 ++ 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 5227c5c4ebe2..1069b8dd84dc 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -438,14 +438,6 @@ struct rmtacl_ctl_table { #define EE_HASHES 32 -struct eacl_entry { - struct list_head ee_list; - pid_t ee_key; /* hash key */ - struct lu_fid ee_fid; - int ee_type; /* ACL type for ACCESS or DEFAULT */ - ext_acl_xattr_header *ee_acl; -}; - struct eacl_table { spinlock_t et_lock; struct list_head et_entries[EE_HASHES]; @@ -1168,6 +1160,14 @@ void ll_ra_stats_inc(struct address_space *mapping, enum ra_stat which); /* llite/llite_rmtacl.c */ #ifdef CONFIG_FS_POSIX_ACL +struct eacl_entry { + struct list_head ee_list; + pid_t ee_key; /* hash key */ + struct lu_fid ee_fid; + int ee_type; /* ACL type for ACCESS or DEFAULT */ + ext_acl_xattr_header *ee_acl; +}; + obd_valid rce_ops2valid(int ops); struct rmtacl_ctl_entry *rct_search(struct rmtacl_ctl_table *rct, pid_t key); int rct_add(struct rmtacl_ctl_table *rct, pid_t key, int ops); @@ -1183,6 +1183,11 @@ struct eacl_entry *et_search_del(struct eacl_table *et, pid_t key, void et_search_free(struct eacl_table *et, pid_t key); void et_init(struct eacl_table *et); void et_fini(struct eacl_table *et); +#else +static inline obd_valid rce_ops2valid(int ops) +{ + return 0; +} #endif /* statahead.c */ diff --git a/drivers/staging/lustre/lustre/llite/xattr.c b/drivers/staging/lustre/lustre/llite/xattr.c index 4176264984bb..0a11902c4d2b 100644 --- a/drivers/staging/lustre/lustre/llite/xattr.c +++ b/drivers/staging/lustre/lustre/llite/xattr.c @@ -112,9 +112,11 @@ int ll_setxattr_common(struct inode *inode, const char *name, struct ptlrpc_request *req; int xattr_type, rc; struct obd_capa *oc; +#ifdef CONFIG_FS_POSIX_ACL posix_acl_xattr_header *new_value = NULL; struct rmtacl_ctl_entry *rce = NULL; ext_acl_xattr_header *acl = NULL; +#endif const char *pv = value; ENTRY; From 4b1a25f06b30b203b35c227b163c8191b091dad8 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Mon, 15 Jul 2013 22:27:14 +0800 Subject: [PATCH 0303/3400] staging/lustre: fix build when CONFIG_UIDGID_STRICT_TYPE_CHECKS is on kuid_t/kgid_t are wrappered when CONFIG_UIDGID_STRICT_TYPE_CHECKS is on. Lustre build is broken because we always treat them as plain __u32. The patch fixes it. Internally, Lustre always use __u32 uid/gid, and convert to kuid_t/kgid_t when necessary. Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../lustre/include/linux/libcfs/curproc.h | 2 -- .../lustre/lustre/include/linux/lvfs.h | 8 +++--- .../lustre/lustre/include/lustre_cfg.h | 4 --- .../lustre/libcfs/linux/linux-curproc.c | 16 ------------ .../lustre/lustre/libcfs/linux/linux-module.c | 2 +- drivers/staging/lustre/lustre/llite/dir.c | 9 ++++--- .../staging/lustre/lustre/llite/llite_lib.c | 13 +++++----- .../staging/lustre/lustre/llite/lproc_llite.c | 3 ++- drivers/staging/lustre/lustre/llite/namei.c | 7 +++--- .../staging/lustre/lustre/llite/remote_perm.c | 11 ++++---- .../staging/lustre/lustre/llite/vvp_object.c | 8 +++--- drivers/staging/lustre/lustre/lmv/lmv_obd.c | 12 ++++----- drivers/staging/lustre/lustre/mdc/mdc_lib.c | 25 ++++++++++--------- .../staging/lustre/lustre/mdc/mdc_request.c | 8 ++---- .../lustre/lustre/obdclass/class_obd.c | 3 ++- .../staging/lustre/lustre/obdclass/idmap.c | 12 ++++++--- .../lustre/lustre/obdclass/linux/linux-obdo.c | 4 +-- drivers/staging/lustre/lustre/obdclass/obdo.c | 16 ++++++------ .../lustre/lustre/obdecho/echo_client.c | 12 ++++++--- drivers/staging/lustre/lustre/ptlrpc/sec.c | 19 +++++++------- 20 files changed, 93 insertions(+), 101 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/curproc.h b/drivers/staging/lustre/include/linux/libcfs/curproc.h index 90d7ce630e94..de8e35b796ab 100644 --- a/drivers/staging/lustre/include/linux/libcfs/curproc.h +++ b/drivers/staging/lustre/include/linux/libcfs/curproc.h @@ -49,8 +49,6 @@ * Implemented in portals/include/libcfs// */ int cfs_curproc_groups_nr(void); -int current_is_in_group(gid_t group); -void cfs_curproc_groups_dump(gid_t *array, int size); /* * Plus, platform-specific constant diff --git a/drivers/staging/lustre/lustre/include/linux/lvfs.h b/drivers/staging/lustre/lustre/include/linux/lvfs.h index eb59ac7d5946..e61f1b87f822 100644 --- a/drivers/staging/lustre/lustre/include/linux/lvfs.h +++ b/drivers/staging/lustre/lustre/include/linux/lvfs.h @@ -54,10 +54,10 @@ /* simple.c */ struct lvfs_ucred { - __u32 luc_uid; - __u32 luc_gid; - __u32 luc_fsuid; - __u32 luc_fsgid; + kuid_t luc_uid; + kgid_t luc_gid; + kuid_t luc_fsuid; + kgid_t luc_fsgid; kernel_cap_t luc_cap; __u32 luc_umask; struct group_info *luc_ginfo; diff --git a/drivers/staging/lustre/lustre/include/lustre_cfg.h b/drivers/staging/lustre/lustre/include/lustre_cfg.h index f12429f38215..fbf94a081ffd 100644 --- a/drivers/staging/lustre/lustre/include/lustre_cfg.h +++ b/drivers/staging/lustre/lustre/include/lustre_cfg.h @@ -290,10 +290,6 @@ static inline int lustre_cfg_sanity_check(void *buf, int len) #include -#ifndef INVALID_UID -#define INVALID_UID (-1) -#endif - /** @} cfg */ #endif // _LUSTRE_CFG_H diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c index f236510a2f3f..706dfb39fc28 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c @@ -65,20 +65,6 @@ int cfs_curproc_groups_nr(void) return nr; } -void cfs_curproc_groups_dump(gid_t *array, int size) -{ - task_lock(current); - size = min_t(int, size, current_cred()->group_info->ngroups); - memcpy(array, current_cred()->group_info->blocks[0], size * sizeof(__u32)); - task_unlock(current); -} - - -int current_is_in_group(gid_t gid) -{ - return in_group_p(gid); -} - /* Currently all the CFS_CAP_* defines match CAP_* ones. */ #define cfs_cap_pack(cap) (cap) #define cfs_cap_unpack(cap) (cap) @@ -318,8 +304,6 @@ out: EXPORT_SYMBOL(cfs_get_environ); EXPORT_SYMBOL(cfs_curproc_groups_nr); -EXPORT_SYMBOL(cfs_curproc_groups_dump); -EXPORT_SYMBOL(current_is_in_group); EXPORT_SYMBOL(cfs_cap_raise); EXPORT_SYMBOL(cfs_cap_lower); EXPORT_SYMBOL(cfs_cap_raised); diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c index 2c7d4a3d660f..6b0054ff7915 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c @@ -137,7 +137,7 @@ static long libcfs_ioctl(struct file *file, struct cfs_psdev_file pfile; int rc = 0; - if (current_fsuid() != 0) + if (!capable(CAP_SYS_ADMIN)) return -EACCES; if ( _IOC_TYPE(cmd) != IOC_LIBCFS_TYPE || diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 13a6426bdd9f..e2afb9730343 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -685,7 +685,8 @@ int ll_dir_setdirstripe(struct inode *dir, struct lmv_user_md *lump, op_data->op_cli_flags |= CLI_SET_MEA; err = md_create(sbi->ll_md_exp, op_data, lump, sizeof(*lump), mode, - current_fsuid(), current_fsgid(), + from_kuid(&init_user_ns, current_fsuid()), + from_kgid(&init_user_ns, current_fsgid()), cfs_curproc_cap_pack(), 0, &request); ll_finish_md_op_data(op_data); if (err) @@ -1105,8 +1106,10 @@ static int quotactl_ioctl(struct ll_sb_info *sbi, struct if_quotactl *qctl) RETURN(-EPERM); break; case Q_GETQUOTA: - if (((type == USRQUOTA && current_euid() != id) || - (type == GRPQUOTA && !in_egroup_p(id))) && + if (((type == USRQUOTA && + uid_eq(current_euid(), make_kuid(&init_user_ns, id))) || + (type == GRPQUOTA && + !in_egroup_p(make_kgid(&init_user_ns, id)))) && (!cfs_capable(CFS_CAP_SYS_ADMIN) || sbi->ll_flags & LL_SBI_RMT_CLIENT)) RETURN(-EPERM); diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index afae8010623d..1eb5779c1bda 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -1400,7 +1400,7 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr) /* POSIX: check before ATTR_*TIME_SET set (from inode_change_ok) */ if (attr->ia_valid & TIMES_SET_FLAGS) { - if (current_fsuid() != inode->i_uid && + if ((!uid_eq(current_fsuid(), inode->i_uid)) && !cfs_capable(CFS_CAP_FOWNER)) RETURN(-EPERM); } @@ -1707,9 +1707,9 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md) inode->i_blkbits = inode->i_sb->s_blocksize_bits; } if (body->valid & OBD_MD_FLUID) - inode->i_uid = body->uid; + inode->i_uid = make_kuid(&init_user_ns, body->uid); if (body->valid & OBD_MD_FLGID) - inode->i_gid = body->gid; + inode->i_gid = make_kgid(&init_user_ns, body->gid); if (body->valid & OBD_MD_FLFLAGS) inode->i_flags = ll_ext_to_inode_flags(body->flags); if (body->valid & OBD_MD_FLNLINK) @@ -1959,7 +1959,8 @@ int ll_flush_ctx(struct inode *inode) { struct ll_sb_info *sbi = ll_i2sbi(inode); - CDEBUG(D_SEC, "flush context for user %d\n", current_uid()); + CDEBUG(D_SEC, "flush context for user %d\n", + from_kuid(&init_user_ns, current_uid())); obd_set_info_async(NULL, sbi->ll_md_exp, sizeof(KEY_FLUSH_CTX), KEY_FLUSH_CTX, @@ -2238,8 +2239,8 @@ struct md_op_data * ll_prep_md_op_data(struct md_op_data *op_data, op_data->op_namelen = namelen; op_data->op_mode = mode; op_data->op_mod_time = cfs_time_current_sec(); - op_data->op_fsuid = current_fsuid(); - op_data->op_fsgid = current_fsgid(); + op_data->op_fsuid = from_kuid(&init_user_ns, current_fsuid()); + op_data->op_fsgid = from_kgid(&init_user_ns, current_fsgid()); op_data->op_cap = cfs_curproc_cap_pack(); op_data->op_bias = 0; op_data->op_cli_flags = 0; diff --git a/drivers/staging/lustre/lustre/llite/lproc_llite.c b/drivers/staging/lustre/lustre/llite/lproc_llite.c index a30c411b583b..5c7368c358a0 100644 --- a/drivers/staging/lustre/lustre/llite/lproc_llite.c +++ b/drivers/staging/lustre/lustre/llite/lproc_llite.c @@ -822,7 +822,8 @@ void ll_stats_ops_tally(struct ll_sb_info *sbi, int op, int count) sbi->ll_stats_track_id == current->parent->pid) lprocfs_counter_add(sbi->ll_stats, op, count); else if (sbi->ll_stats_track_type == STATS_TRACK_GID && - sbi->ll_stats_track_id == current_gid()) + sbi->ll_stats_track_id == + from_kgid(&init_user_ns, current_gid())) lprocfs_counter_add(sbi->ll_stats, op, count); } EXPORT_SYMBOL(ll_stats_ops_tally); diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index ff8f63de5612..8e948a71dd64 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -302,8 +302,8 @@ int ll_md_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc, __u32 ll_i2suppgid(struct inode *i) { - if (current_is_in_group(i->i_gid)) - return (__u32)i->i_gid; + if (in_group_p(i->i_gid)) + return (__u32)from_kgid(&init_user_ns, i->i_gid); else return (__u32)(-1); } @@ -805,7 +805,8 @@ static int ll_new_node(struct inode *dir, struct qstr *name, GOTO(err_exit, err = PTR_ERR(op_data)); err = md_create(sbi->ll_md_exp, op_data, tgt, tgt_len, mode, - current_fsuid(), current_fsgid(), + from_kuid(&init_user_ns, current_fsuid()), + from_kgid(&init_user_ns, current_fsgid()), cfs_curproc_cap_pack(), rdev, &request); ll_finish_md_op_data(op_data); if (err) diff --git a/drivers/staging/lustre/lustre/llite/remote_perm.c b/drivers/staging/lustre/lustre/llite/remote_perm.c index 68b2dc4a7b62..4f176e16e01c 100644 --- a/drivers/staging/lustre/lustre/llite/remote_perm.c +++ b/drivers/staging/lustre/lustre/llite/remote_perm.c @@ -129,17 +129,18 @@ static int do_check_remote_perm(struct ll_inode_info *lli, int mask) if (!lli->lli_remote_perms) RETURN(-ENOENT); - head = lli->lli_remote_perms + remote_perm_hashfunc(current_uid()); + head = lli->lli_remote_perms + + remote_perm_hashfunc(from_kuid(&init_user_ns, current_uid())); spin_lock(&lli->lli_lock); hlist_for_each_entry(lrp, head, lrp_list) { - if (lrp->lrp_uid != current_uid()) + if (lrp->lrp_uid != from_kuid(&init_user_ns, current_uid())) continue; - if (lrp->lrp_gid != current_gid()) + if (lrp->lrp_gid != from_kgid(&init_user_ns, current_gid())) continue; - if (lrp->lrp_fsuid != current_fsuid()) + if (lrp->lrp_fsuid != from_kuid(&init_user_ns, current_fsuid())) continue; - if (lrp->lrp_fsgid != current_fsgid()) + if (lrp->lrp_fsgid != from_kgid(&init_user_ns, current_fsgid())) continue; found = 1; break; diff --git a/drivers/staging/lustre/lustre/llite/vvp_object.c b/drivers/staging/lustre/lustre/llite/vvp_object.c index 01edc5b63e13..33173fce478f 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_object.c +++ b/drivers/staging/lustre/lustre/llite/vvp_object.c @@ -91,8 +91,8 @@ static int vvp_attr_get(const struct lu_env *env, struct cl_object *obj, attr->cat_atime = LTIME_S(inode->i_atime); attr->cat_ctime = LTIME_S(inode->i_ctime); attr->cat_blocks = inode->i_blocks; - attr->cat_uid = inode->i_uid; - attr->cat_gid = inode->i_gid; + attr->cat_uid = from_kuid(&init_user_ns, inode->i_uid); + attr->cat_gid = from_kgid(&init_user_ns, inode->i_gid); /* KMS is not known by this layer */ return 0; /* layers below have to fill in the rest */ } @@ -103,9 +103,9 @@ static int vvp_attr_set(const struct lu_env *env, struct cl_object *obj, struct inode *inode = ccc_object_inode(obj); if (valid & CAT_UID) - inode->i_uid = attr->cat_uid; + inode->i_uid = make_kuid(&init_user_ns, attr->cat_uid); if (valid & CAT_GID) - inode->i_gid = attr->cat_gid; + inode->i_gid = make_kgid(&init_user_ns, attr->cat_gid); if (valid & CAT_ATIME) LTIME_S(inode->i_atime) = attr->cat_atime; if (valid & CAT_MTIME) diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 1eebfbf34871..d10f7fc553d3 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -1757,8 +1757,8 @@ static int lmv_link(struct obd_export *exp, struct md_op_data *op_data, PFID(&op_data->op_fid2), op_data->op_namelen, op_data->op_name, PFID(&op_data->op_fid1)); - op_data->op_fsuid = current_fsuid(); - op_data->op_fsgid = current_fsgid(); + op_data->op_fsuid = from_kuid(&init_user_ns, current_fsuid()); + op_data->op_fsgid = from_kgid(&init_user_ns, current_fsgid()); op_data->op_cap = cfs_curproc_cap_pack(); tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid2); if (IS_ERR(tgt)) @@ -1799,8 +1799,8 @@ static int lmv_rename(struct obd_export *exp, struct md_op_data *op_data, if (rc) RETURN(rc); - op_data->op_fsuid = current_fsuid(); - op_data->op_fsgid = current_fsgid(); + op_data->op_fsuid = from_kuid(&init_user_ns, current_fsuid()); + op_data->op_fsgid = from_kgid(&init_user_ns, current_fsgid()); op_data->op_cap = cfs_curproc_cap_pack(); src_tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid1); if (IS_ERR(src_tgt)) @@ -2061,8 +2061,8 @@ retry: if (IS_ERR(tgt)) RETURN(PTR_ERR(tgt)); - op_data->op_fsuid = current_fsuid(); - op_data->op_fsgid = current_fsgid(); + op_data->op_fsuid = from_kuid(&init_user_ns, current_fsuid()); + op_data->op_fsgid = from_kgid(&init_user_ns, current_fsgid()); op_data->op_cap = cfs_curproc_cap_pack(); /* diff --git a/drivers/staging/lustre/lustre/mdc/mdc_lib.c b/drivers/staging/lustre/lustre/mdc/mdc_lib.c index e789aed98de0..2e5c7cef61ce 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_lib.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_lib.c @@ -45,10 +45,10 @@ static void __mdc_pack_body(struct mdt_body *b, __u32 suppgid) LASSERT (b != NULL); b->suppgid = suppgid; - b->uid = current_uid(); - b->gid = current_gid(); - b->fsuid = current_fsuid(); - b->fsgid = current_fsgid(); + b->uid = from_kuid(&init_user_ns, current_uid()); + b->gid = from_kgid(&init_user_ns, current_gid()); + b->fsuid = from_kuid(&init_user_ns, current_fsuid()); + b->fsgid = from_kgid(&init_user_ns, current_fsgid()); b->capability = cfs_curproc_cap_pack(); } @@ -219,8 +219,8 @@ void mdc_open_pack(struct ptlrpc_request *req, struct md_op_data *op_data, /* XXX do something about time, uid, gid */ rec->cr_opcode = REINT_OPEN; - rec->cr_fsuid = current_fsuid(); - rec->cr_fsgid = current_fsgid(); + rec->cr_fsuid = from_kuid(&init_user_ns, current_fsuid()); + rec->cr_fsgid = from_kgid(&init_user_ns, current_fsgid()); rec->cr_cap = cfs_curproc_cap_pack(); if (op_data != NULL) { rec->cr_fid1 = op_data->op_fid1; @@ -299,16 +299,16 @@ static void mdc_setattr_pack_rec(struct mdt_rec_setattr *rec, struct md_op_data *op_data) { rec->sa_opcode = REINT_SETATTR; - rec->sa_fsuid = current_fsuid(); - rec->sa_fsgid = current_fsgid(); + rec->sa_fsuid = from_kuid(&init_user_ns, current_fsuid()); + rec->sa_fsgid = from_kgid(&init_user_ns, current_fsgid()); rec->sa_cap = cfs_curproc_cap_pack(); rec->sa_suppgid = -1; rec->sa_fid = op_data->op_fid1; rec->sa_valid = attr_pack(op_data->op_attr.ia_valid); rec->sa_mode = op_data->op_attr.ia_mode; - rec->sa_uid = op_data->op_attr.ia_uid; - rec->sa_gid = op_data->op_attr.ia_gid; + rec->sa_uid = from_kuid(&init_user_ns, op_data->op_attr.ia_uid); + rec->sa_gid = from_kgid(&init_user_ns, op_data->op_attr.ia_gid); rec->sa_size = op_data->op_attr.ia_size; rec->sa_blocks = op_data->op_attr_blocks; rec->sa_atime = LTIME_S(op_data->op_attr.ia_atime); @@ -316,8 +316,9 @@ static void mdc_setattr_pack_rec(struct mdt_rec_setattr *rec, rec->sa_ctime = LTIME_S(op_data->op_attr.ia_ctime); rec->sa_attr_flags = ((struct ll_iattr *)&op_data->op_attr)->ia_attr_flags; if ((op_data->op_attr.ia_valid & ATTR_GID) && - current_is_in_group(op_data->op_attr.ia_gid)) - rec->sa_suppgid = op_data->op_attr.ia_gid; + in_group_p(op_data->op_attr.ia_gid)) + rec->sa_suppgid = + from_kgid(&init_user_ns, op_data->op_attr.ia_gid); else rec->sa_suppgid = op_data->op_suppgids[0]; diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 3cf9d8d3f2ec..21e8a9d16130 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -377,12 +377,8 @@ static int mdc_xattr_common(struct obd_export *exp,const struct req_format *fmt, sizeof(struct mdt_rec_reint)); rec = req_capsule_client_get(&req->rq_pill, &RMF_REC_REINT); rec->sx_opcode = REINT_SETXATTR; - /* TODO: - * cfs_curproc_fs{u,g}id() should replace - * current->fs{u,g}id for portability. - */ - rec->sx_fsuid = current_fsuid(); - rec->sx_fsgid = current_fsgid(); + rec->sx_fsuid = from_kuid(&init_user_ns, current_fsuid()); + rec->sx_fsgid = from_kgid(&init_user_ns, current_fsgid()); rec->sx_cap = cfs_curproc_cap_pack(); rec->sx_suppgid1 = suppgid; rec->sx_suppgid2 = -1; diff --git a/drivers/staging/lustre/lustre/obdclass/class_obd.c b/drivers/staging/lustre/lustre/obdclass/class_obd.c index 0715cf2af3ce..799a1ed8701f 100644 --- a/drivers/staging/lustre/lustre/obdclass/class_obd.c +++ b/drivers/staging/lustre/lustre/obdclass/class_obd.c @@ -122,7 +122,8 @@ int lustre_get_jobid(char *jobid) /* Use process name + fsuid as jobid */ if (strcmp(obd_jobid_var, JOBSTATS_PROCNAME_UID) == 0) { snprintf(jobid, JOBSTATS_JOBID_SIZE, "%s.%u", - current_comm(), current_fsuid()); + current_comm(), + from_kuid(&init_user_ns, current_fsuid())); RETURN(0); } diff --git a/drivers/staging/lustre/lustre/obdclass/idmap.c b/drivers/staging/lustre/lustre/obdclass/idmap.c index 622f8d165275..afb66a49f828 100644 --- a/drivers/staging/lustre/lustre/obdclass/idmap.c +++ b/drivers/staging/lustre/lustre/obdclass/idmap.c @@ -71,7 +71,8 @@ static int lustre_groups_search(group_info_t *group_info, right = group_info->ngroups; while (left < right) { int mid = (left + right) / 2; - int cmp = grp - CFS_GROUP_AT(group_info, mid); + int cmp = grp - + from_kgid(&init_user_ns, CFS_GROUP_AT(group_info, mid)); if (cmp > 0) left = mid + 1; @@ -116,16 +117,19 @@ void lustre_groups_sort(group_info_t *group_info) for (base = 0; base < max; base++) { int left = base; int right = left + stride; - gid_t tmp = CFS_GROUP_AT(group_info, right); + gid_t tmp = from_kgid(&init_user_ns, + CFS_GROUP_AT(group_info, right)); while (left >= 0 && - CFS_GROUP_AT(group_info, left) > tmp) { + tmp < from_kgid(&init_user_ns, + CFS_GROUP_AT(group_info, left))) { CFS_GROUP_AT(group_info, right) = CFS_GROUP_AT(group_info, left); right = left; left -= stride; } - CFS_GROUP_AT(group_info, right) = tmp; + CFS_GROUP_AT(group_info, right) = + make_kgid(&init_user_ns, tmp); } stride /= 3; } diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-obdo.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-obdo.c index 6ee347153a16..d3bb5ffc564b 100644 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-obdo.c +++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-obdo.c @@ -213,9 +213,9 @@ void obdo_to_inode(struct inode *dst, struct obdo *src, obd_flag valid) if (valid & OBD_MD_FLMODE) dst->i_mode = (dst->i_mode & S_IFMT) | (src->o_mode & ~S_IFMT); if (valid & OBD_MD_FLUID) - dst->i_uid = src->o_uid; + dst->i_uid = make_kuid(&init_user_ns, src->o_uid); if (valid & OBD_MD_FLGID) - dst->i_gid = src->o_gid; + dst->i_gid = make_kgid(&init_user_ns, src->o_gid); if (valid & OBD_MD_FLFLAGS) dst->i_flags = src->o_flags; } diff --git a/drivers/staging/lustre/lustre/obdclass/obdo.c b/drivers/staging/lustre/lustre/obdclass/obdo.c index 01a0e1f83a68..70997648a4f3 100644 --- a/drivers/staging/lustre/lustre/obdclass/obdo.c +++ b/drivers/staging/lustre/lustre/obdclass/obdo.c @@ -100,11 +100,11 @@ void obdo_from_inode(struct obdo *dst, struct inode *src, obd_flag valid) newvalid |= OBD_MD_FLMODE; } if (valid & OBD_MD_FLUID) { - dst->o_uid = src->i_uid; + dst->o_uid = from_kuid(&init_user_ns, src->i_uid); newvalid |= OBD_MD_FLUID; } if (valid & OBD_MD_FLGID) { - dst->o_gid = src->i_gid; + dst->o_gid = from_kgid(&init_user_ns, src->i_gid); newvalid |= OBD_MD_FLGID; } if (valid & OBD_MD_FLFLAGS) { @@ -232,16 +232,16 @@ void obdo_from_iattr(struct obdo *oa, struct iattr *attr, unsigned int ia_valid) if (ia_valid & ATTR_MODE) { oa->o_mode = attr->ia_mode; oa->o_valid |= OBD_MD_FLTYPE | OBD_MD_FLMODE; - if (!current_is_in_group(oa->o_gid) && + if (!in_group_p(make_kgid(&init_user_ns, oa->o_gid)) && !cfs_capable(CFS_CAP_FSETID)) oa->o_mode &= ~S_ISGID; } if (ia_valid & ATTR_UID) { - oa->o_uid = attr->ia_uid; + oa->o_uid = from_kuid(&init_user_ns, attr->ia_uid); oa->o_valid |= OBD_MD_FLUID; } if (ia_valid & ATTR_GID) { - oa->o_gid = attr->ia_gid; + oa->o_gid = from_kgid(&init_user_ns, attr->ia_gid); oa->o_valid |= OBD_MD_FLGID; } } @@ -281,16 +281,16 @@ void iattr_from_obdo(struct iattr *attr, struct obdo *oa, obd_flag valid) if (valid & OBD_MD_FLMODE) { attr->ia_mode = (attr->ia_mode & S_IFMT)|(oa->o_mode & ~S_IFMT); attr->ia_valid |= ATTR_MODE; - if (!current_is_in_group(oa->o_gid) && + if (!in_group_p(make_kgid(&init_user_ns, oa->o_gid)) && !cfs_capable(CFS_CAP_FSETID)) attr->ia_mode &= ~S_ISGID; } if (valid & OBD_MD_FLUID) { - attr->ia_uid = oa->o_uid; + attr->ia_uid = make_kuid(&init_user_ns, oa->o_uid); attr->ia_valid |= ATTR_UID; } if (valid & OBD_MD_FLGID) { - attr->ia_gid = oa->o_gid; + attr->ia_gid = make_kgid(&init_user_ns, oa->o_gid); attr->ia_valid |= ATTR_GID; } } diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c index 184195fde621..ae89ea6f893c 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c @@ -2097,10 +2097,14 @@ static void echo_ucred_init(struct lu_env *env) ucred->uc_suppgids[0] = -1; ucred->uc_suppgids[1] = -1; - ucred->uc_uid = ucred->uc_o_uid = current_uid(); - ucred->uc_gid = ucred->uc_o_gid = current_gid(); - ucred->uc_fsuid = ucred->uc_o_fsuid = current_fsuid(); - ucred->uc_fsgid = ucred->uc_o_fsgid = current_fsgid(); + ucred->uc_uid = ucred->uc_o_uid = + from_kuid(&init_user_ns, current_uid()); + ucred->uc_gid = ucred->uc_o_gid = + from_kgid(&init_user_ns, current_gid()); + ucred->uc_fsuid = ucred->uc_o_fsuid = + from_kuid(&init_user_ns, current_fsuid()); + ucred->uc_fsgid = ucred->uc_o_fsgid = + from_kgid(&init_user_ns, current_fsgid()); ucred->uc_cap = cfs_curproc_cap_pack(); /* remove fs privilege for non-root user. */ diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec.c b/drivers/staging/lustre/lustre/ptlrpc/sec.c index 36e8bed5458a..349c57b6d78a 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec.c @@ -269,8 +269,8 @@ struct ptlrpc_cli_ctx *get_my_ctx(struct ptlrpc_sec *sec) remove_dead = 0; } } else { - vcred.vc_uid = current_uid(); - vcred.vc_gid = current_gid(); + vcred.vc_uid = from_kuid(&init_user_ns, current_uid()); + vcred.vc_gid = from_kgid(&init_user_ns, current_gid()); } return sec->ps_policy->sp_cops->lookup_ctx(sec, &vcred, @@ -1523,7 +1523,8 @@ void sptlrpc_import_flush_root_ctx(struct obd_import *imp) void sptlrpc_import_flush_my_ctx(struct obd_import *imp) { - import_flush_ctx_common(imp, current_uid(), 1, 1); + import_flush_ctx_common(imp, from_kuid(&init_user_ns, current_uid()), + 1, 1); } EXPORT_SYMBOL(sptlrpc_import_flush_my_ctx); @@ -2055,8 +2056,8 @@ int sptlrpc_svc_unwrap_request(struct ptlrpc_request *req) req->rq_flvr.sf_rpc = WIRE_FLVR(msg->lm_secflvr); req->rq_sp_from = LUSTRE_SP_ANY; - req->rq_auth_uid = INVALID_UID; - req->rq_auth_mapped_uid = INVALID_UID; + req->rq_auth_uid = -1; + req->rq_auth_mapped_uid = -1; policy = sptlrpc_wireflavor2policy(req->rq_flvr.sf_rpc); if (!policy) { @@ -2314,10 +2315,10 @@ int sptlrpc_pack_user_desc(struct lustre_msg *msg, int offset) pud = lustre_msg_buf(msg, offset, 0); - pud->pud_uid = current_uid(); - pud->pud_gid = current_gid(); - pud->pud_fsuid = current_fsuid(); - pud->pud_fsgid = current_fsgid(); + pud->pud_uid = from_kuid(&init_user_ns, current_uid()); + pud->pud_gid = from_kgid(&init_user_ns, current_gid()); + pud->pud_fsuid = from_kuid(&init_user_ns, current_fsuid()); + pud->pud_fsgid = from_kgid(&init_user_ns, current_fsgid()); pud->pud_cap = cfs_curproc_cap_pack(); pud->pud_ngroups = (msg->lm_buflens[offset] - sizeof(*pud)) / 4; From 5d4450c41fe308e10a1805cb90d26adbf1267146 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Mon, 15 Jul 2013 22:27:15 +0800 Subject: [PATCH 0304/3400] staging/lustre: fix build error on non-x86 platforms dump_trace() is only available on X86. Without it, Lustre's own watchdog is broken. We can only dump current task's stack. The client-side this code is much less likely to hit deadlocks and it's probably OK to drop this altogether, since we hardly have any ptlrpc threads on clients, most notable ones are ldlm cb threads that should not really be blocking on the client anyway. Remove libcfs watchdog for now, until the upstream kernel watchdog can detect distributed deadlocks and dump other kernel threads. Cc: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../lustre/include/linux/libcfs/libcfs.h | 25 - .../include/linux/libcfs/libcfs_private.h | 1 - .../staging/lustre/lustre/include/linux/obd.h | 5 +- .../lustre/lustre/include/lustre_net.h | 7 +- .../staging/lustre/lustre/ldlm/ldlm_lock.c | 2 +- drivers/staging/lustre/lustre/libcfs/Makefile | 2 +- .../lustre/lustre/libcfs/linux/linux-debug.c | 45 +- .../staging/lustre/lustre/libcfs/watchdog.c | 516 ------------------ drivers/staging/lustre/lustre/llite/dcache.c | 2 +- drivers/staging/lustre/lustre/llite/rw.c | 2 +- drivers/staging/lustre/lustre/osc/osc_io.c | 2 +- .../staging/lustre/lustre/ptlrpc/service.c | 8 + 12 files changed, 21 insertions(+), 596 deletions(-) delete mode 100644 drivers/staging/lustre/lustre/libcfs/watchdog.c diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs.h b/drivers/staging/lustre/include/linux/libcfs/libcfs.h index 1ab1f2be9aa5..2983ce412b66 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs.h @@ -117,31 +117,6 @@ int libcfs_sock_write(socket_t *sock, void *buffer, int nob, int timeout); int libcfs_sock_read(socket_t *sock, void *buffer, int nob, int timeout); void libcfs_sock_release(socket_t *sock); -/* libcfs watchdogs */ -struct lc_watchdog; - -/* Add a watchdog which fires after "time" milliseconds of delay. You have to - * touch it once to enable it. */ -struct lc_watchdog *lc_watchdog_add(int time, - void (*cb)(pid_t pid, void *), - void *data); - -/* Enables a watchdog and resets its timer. */ -void lc_watchdog_touch(struct lc_watchdog *lcw, int timeout); -#define CFS_GET_TIMEOUT(svc) (max_t(int, obd_timeout, \ - AT_OFF ? 0 : at_get(&svc->srv_at_estimate)) * \ - svc->srv_watchdog_factor) - -/* Disable a watchdog; touch it to restart it. */ -void lc_watchdog_disable(struct lc_watchdog *lcw); - -/* Clean up the watchdog */ -void lc_watchdog_delete(struct lc_watchdog *lcw); - -/* Dump a debug log */ -void lc_watchdog_dumplog(pid_t pid, void *data); - - /* need both kernel and user-land acceptor */ #define LNET_ACCEPTOR_MIN_RESERVED_PORT 512 #define LNET_ACCEPTOR_MAX_RESERVED_PORT 1023 diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h index 056caa467126..62ef8a749002 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h @@ -210,7 +210,6 @@ do { \ #define ntohs(x) ___ntohs(x) #endif -void libcfs_debug_dumpstack(task_t *tsk); void libcfs_run_upcall(char **argv); void libcfs_run_lbug_upcall(struct libcfs_debug_msg_data *); void libcfs_debug_dumplog(void); diff --git a/drivers/staging/lustre/lustre/include/linux/obd.h b/drivers/staging/lustre/lustre/include/linux/obd.h index 2c36c0d19d06..01a50265239d 100644 --- a/drivers/staging/lustre/lustre/include/linux/obd.h +++ b/drivers/staging/lustre/lustre/include/linux/obd.h @@ -93,11 +93,8 @@ static inline void __client_obd_list_lock(client_obd_lock_t *lock, lock, task->comm, task->pid, lock->func, lock->line, (jiffies - lock->time) / HZ); - LCONSOLE_WARN("====== for process holding the " - "lock =====\n"); - libcfs_debug_dumpstack(task); LCONSOLE_WARN("====== for current process =====\n"); - libcfs_debug_dumpstack(NULL); + dump_stack(); LCONSOLE_WARN("====== end =======\n"); cfs_pause(1000 * HZ); } diff --git a/drivers/staging/lustre/lustre/include/lustre_net.h b/drivers/staging/lustre/lustre/include/lustre_net.h index 293dd90e5b6c..1b99b5d2b4f1 100644 --- a/drivers/staging/lustre/lustre/include/lustre_net.h +++ b/drivers/staging/lustre/lustre/include/lustre_net.h @@ -2322,8 +2322,13 @@ struct ptlrpc_thread { pid_t t_pid; /** * put watchdog in the structure per thread b=14840 + * + * Lustre watchdog is removed for client in the hope + * of a generic watchdog can be merged in kernel. + * When that happens, we should add below back. + * + * struct lc_watchdog *t_watchdog; */ - struct lc_watchdog *t_watchdog; /** * the svc this thread belonged to b=18582 */ diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c index 33b76a1e5dec..93badf5c2957 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c @@ -1548,7 +1548,7 @@ int ldlm_fill_lvb(struct ldlm_lock *lock, struct req_capsule *pill, break; default: LDLM_ERROR(lock, "Unknown LVB type: %d\n", lock->l_lvb_type); - libcfs_debug_dumpstack(NULL); + dump_stack(); RETURN(-EINVAL); } diff --git a/drivers/staging/lustre/lustre/libcfs/Makefile b/drivers/staging/lustre/lustre/libcfs/Makefile index bf5c563dcacc..6e489d7aaa8b 100644 --- a/drivers/staging/lustre/lustre/libcfs/Makefile +++ b/drivers/staging/lustre/lustre/libcfs/Makefile @@ -11,7 +11,7 @@ libcfs-linux-objs += linux-crypto-adler.o libcfs-linux-objs := $(addprefix linux/,$(libcfs-linux-objs)) libcfs-all-objs := debug.o fail.o nidstrings.o module.o tracefile.o \ - watchdog.o libcfs_string.o hash.o kernel_user_comm.o \ + libcfs_string.o hash.o kernel_user_comm.o \ prng.o workitem.o upcall_cache.o libcfs_cpu.o \ libcfs_mem.o libcfs_lock.o diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c index e2c195b8dd53..9b5fa919aa4a 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c @@ -168,7 +168,7 @@ void lbug_with_loc(struct libcfs_debug_msg_data *msgdata) /* not reached */ } - libcfs_debug_dumpstack(NULL); + dump_stack(); if (!libcfs_panic_on_lbug) libcfs_debug_dumplog(); libcfs_run_lbug_upcall(msgdata); @@ -179,48 +179,6 @@ void lbug_with_loc(struct libcfs_debug_msg_data *msgdata) schedule(); } - -#include -#include - - -static int print_trace_stack(void *data, char *name) -{ - printk(" <%s> ", name); - return 0; -} - -# define RELIABLE reliable -# define DUMP_TRACE_CONST const -static void print_trace_address(void *data, unsigned long addr, int reliable) -{ - char fmt[32]; - touch_nmi_watchdog(); - sprintf(fmt, " [<%016lx>] %s%%s\n", addr, RELIABLE ? "": "? "); - __print_symbol(fmt, addr); -} - -static DUMP_TRACE_CONST struct stacktrace_ops print_trace_ops = { - .stack = print_trace_stack, - .address = print_trace_address, - .walk_stack = print_context_stack, -}; - -void libcfs_debug_dumpstack(struct task_struct *tsk) -{ - /* dump_stack() */ - /* show_trace() */ - if (tsk == NULL) - tsk = current; - printk("Pid: %d, comm: %.20s\n", tsk->pid, tsk->comm); - /* show_trace_log_lvl() */ - printk("\nCall Trace:\n"); - dump_trace(tsk, NULL, NULL, - 0, - &print_trace_ops, NULL); - printk("\n"); -} - task_t *libcfs_current(void) { CWARN("current task struct is %p\n", current); @@ -255,7 +213,6 @@ void libcfs_unregister_panic_notifier(void) atomic_notifier_chain_unregister(&panic_notifier_list, &libcfs_panic_notifier); } -EXPORT_SYMBOL(libcfs_debug_dumpstack); EXPORT_SYMBOL(libcfs_current); diff --git a/drivers/staging/lustre/lustre/libcfs/watchdog.c b/drivers/staging/lustre/lustre/libcfs/watchdog.c deleted file mode 100644 index 7c385ada3e10..000000000000 --- a/drivers/staging/lustre/lustre/libcfs/watchdog.c +++ /dev/null @@ -1,516 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * 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 version 2 for more details (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - * - * GPL HEADER END - */ -/* - * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. - * Use is subject to license terms. - * - * Copyright (c) 2012, Intel Corporation. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - * - * libcfs/libcfs/watchdog.c - * - * Author: Jacob Berkman - */ - -#define DEBUG_SUBSYSTEM S_LNET - -#include -#include "tracefile.h" - -struct lc_watchdog { - spinlock_t lcw_lock; /* check or change lcw_list */ - int lcw_refcount; /* must hold lcw_pending_timers_lock */ - timer_list_t lcw_timer; /* kernel timer */ - struct list_head lcw_list; /* chain on pending list */ - cfs_time_t lcw_last_touched; /* last touched stamp */ - task_t *lcw_task; /* owner task */ - void (*lcw_callback)(pid_t, void *); - void *lcw_data; - - pid_t lcw_pid; - - enum { - LC_WATCHDOG_DISABLED, - LC_WATCHDOG_ENABLED, - LC_WATCHDOG_EXPIRED - } lcw_state; -}; - -#ifdef WITH_WATCHDOG -/* - * The dispatcher will complete lcw_start_completion when it starts, - * and lcw_stop_completion when it exits. - * Wake lcw_event_waitq to signal timer callback dispatches. - */ -static struct completion lcw_start_completion; -static struct completion lcw_stop_completion; -static wait_queue_head_t lcw_event_waitq; - -/* - * Set this and wake lcw_event_waitq to stop the dispatcher. - */ -enum { - LCW_FLAG_STOP = 0 -}; -static unsigned long lcw_flags = 0; - -/* - * Number of outstanding watchdogs. - * When it hits 1, we start the dispatcher. - * When it hits 0, we stop the dispatcher. - */ -static __u32 lcw_refcount = 0; -static DEFINE_MUTEX(lcw_refcount_mutex); - -/* - * List of timers that have fired that need their callbacks run by the - * dispatcher. - */ -/* BH lock! */ -static DEFINE_SPINLOCK(lcw_pending_timers_lock); -static struct list_head lcw_pending_timers = LIST_HEAD_INIT(lcw_pending_timers); - -/* Last time a watchdog expired */ -static cfs_time_t lcw_last_watchdog_time; -static int lcw_recent_watchdog_count; - -static void -lcw_dump(struct lc_watchdog *lcw) -{ - ENTRY; - rcu_read_lock(); - if (lcw->lcw_task == NULL) { - LCONSOLE_WARN("Process " LPPID " was not found in the task " - "list; watchdog callback may be incomplete\n", - (int)lcw->lcw_pid); - } else { - libcfs_debug_dumpstack(lcw->lcw_task); - } - - rcu_read_unlock(); - EXIT; -} - -static void lcw_cb(ulong_ptr_t data) -{ - struct lc_watchdog *lcw = (struct lc_watchdog *)data; - ENTRY; - - if (lcw->lcw_state != LC_WATCHDOG_ENABLED) { - EXIT; - return; - } - - lcw->lcw_state = LC_WATCHDOG_EXPIRED; - - spin_lock_bh(&lcw->lcw_lock); - LASSERT(list_empty(&lcw->lcw_list)); - - spin_lock_bh(&lcw_pending_timers_lock); - lcw->lcw_refcount++; /* +1 for pending list */ - list_add(&lcw->lcw_list, &lcw_pending_timers); - wake_up(&lcw_event_waitq); - - spin_unlock_bh(&lcw_pending_timers_lock); - spin_unlock_bh(&lcw->lcw_lock); - EXIT; -} - -static int is_watchdog_fired(void) -{ - int rc; - - if (test_bit(LCW_FLAG_STOP, &lcw_flags)) - return 1; - - spin_lock_bh(&lcw_pending_timers_lock); - rc = !list_empty(&lcw_pending_timers); - spin_unlock_bh(&lcw_pending_timers_lock); - return rc; -} - -static void lcw_dump_stack(struct lc_watchdog *lcw) -{ - cfs_time_t current_time; - cfs_duration_t delta_time; - struct timeval timediff; - - current_time = cfs_time_current(); - delta_time = cfs_time_sub(current_time, lcw->lcw_last_touched); - cfs_duration_usec(delta_time, &timediff); - - /* - * Check to see if we should throttle the watchdog timer to avoid - * too many dumps going to the console thus triggering an NMI. - */ - delta_time = cfs_duration_sec(cfs_time_sub(current_time, - lcw_last_watchdog_time)); - - if (delta_time < libcfs_watchdog_ratelimit && - lcw_recent_watchdog_count > 3) { - LCONSOLE_WARN("Service thread pid %u was inactive for " - "%lu.%.02lus. Watchdog stack traces are limited " - "to 3 per %d seconds, skipping this one.\n", - (int)lcw->lcw_pid, - timediff.tv_sec, - timediff.tv_usec / 10000, - libcfs_watchdog_ratelimit); - } else { - if (delta_time < libcfs_watchdog_ratelimit) { - lcw_recent_watchdog_count++; - } else { - memcpy(&lcw_last_watchdog_time, ¤t_time, - sizeof(current_time)); - lcw_recent_watchdog_count = 0; - } - - LCONSOLE_WARN("Service thread pid %u was inactive for " - "%lu.%.02lus. The thread might be hung, or it " - "might only be slow and will resume later. " - "Dumping the stack trace for debugging purposes:" - "\n", - (int)lcw->lcw_pid, - timediff.tv_sec, - timediff.tv_usec / 10000); - lcw_dump(lcw); - } -} - -static int lcw_dispatch_main(void *data) -{ - int rc = 0; - struct lc_watchdog *lcw; - LIST_HEAD (zombies); - - ENTRY; - - complete(&lcw_start_completion); - - while (1) { - int dumplog = 1; - - cfs_wait_event_interruptible(lcw_event_waitq, - is_watchdog_fired(), rc); - CDEBUG(D_INFO, "Watchdog got woken up...\n"); - if (test_bit(LCW_FLAG_STOP, &lcw_flags)) { - CDEBUG(D_INFO, "LCW_FLAG_STOP set, shutting down...\n"); - - spin_lock_bh(&lcw_pending_timers_lock); - rc = !list_empty(&lcw_pending_timers); - spin_unlock_bh(&lcw_pending_timers_lock); - if (rc) { - CERROR("pending timers list was not empty at " - "time of watchdog dispatch shutdown\n"); - } - break; - } - - spin_lock_bh(&lcw_pending_timers_lock); - while (!list_empty(&lcw_pending_timers)) { - int is_dumplog; - - lcw = list_entry(lcw_pending_timers.next, - struct lc_watchdog, lcw_list); - /* +1 ref for callback to make sure lwc wouldn't be - * deleted after releasing lcw_pending_timers_lock */ - lcw->lcw_refcount++; - spin_unlock_bh(&lcw_pending_timers_lock); - - /* lock ordering */ - spin_lock_bh(&lcw->lcw_lock); - spin_lock_bh(&lcw_pending_timers_lock); - - if (list_empty(&lcw->lcw_list)) { - /* already removed from pending list */ - lcw->lcw_refcount--; /* -1 ref for callback */ - if (lcw->lcw_refcount == 0) - list_add(&lcw->lcw_list, &zombies); - spin_unlock_bh(&lcw->lcw_lock); - /* still hold lcw_pending_timers_lock */ - continue; - } - - list_del_init(&lcw->lcw_list); - lcw->lcw_refcount--; /* -1 ref for pending list */ - - spin_unlock_bh(&lcw_pending_timers_lock); - spin_unlock_bh(&lcw->lcw_lock); - - CDEBUG(D_INFO, "found lcw for pid " LPPID "\n", - lcw->lcw_pid); - lcw_dump_stack(lcw); - - is_dumplog = lcw->lcw_callback == lc_watchdog_dumplog; - if (lcw->lcw_state != LC_WATCHDOG_DISABLED && - (dumplog || !is_dumplog)) { - lcw->lcw_callback(lcw->lcw_pid, lcw->lcw_data); - if (dumplog && is_dumplog) - dumplog = 0; - } - - spin_lock_bh(&lcw_pending_timers_lock); - lcw->lcw_refcount--; /* -1 ref for callback */ - if (lcw->lcw_refcount == 0) - list_add(&lcw->lcw_list, &zombies); - } - spin_unlock_bh(&lcw_pending_timers_lock); - - while (!list_empty(&zombies)) { - lcw = list_entry(lcw_pending_timers.next, - struct lc_watchdog, lcw_list); - list_del(&lcw->lcw_list); - LIBCFS_FREE(lcw, sizeof(*lcw)); - } - } - - complete(&lcw_stop_completion); - - RETURN(rc); -} - -static void lcw_dispatch_start(void) -{ - task_t *task; - - ENTRY; - LASSERT(lcw_refcount == 1); - - init_completion(&lcw_stop_completion); - init_completion(&lcw_start_completion); - init_waitqueue_head(&lcw_event_waitq); - - CDEBUG(D_INFO, "starting dispatch thread\n"); - task = kthread_run(lcw_dispatch_main, NULL, "lc_watchdogd"); - if (IS_ERR(task)) { - CERROR("error spawning watchdog dispatch thread: %ld\n", - PTR_ERR(task)); - EXIT; - return; - } - wait_for_completion(&lcw_start_completion); - CDEBUG(D_INFO, "watchdog dispatcher initialization complete.\n"); - - EXIT; -} - -static void lcw_dispatch_stop(void) -{ - ENTRY; - LASSERT(lcw_refcount == 0); - - CDEBUG(D_INFO, "trying to stop watchdog dispatcher.\n"); - - set_bit(LCW_FLAG_STOP, &lcw_flags); - wake_up(&lcw_event_waitq); - - wait_for_completion(&lcw_stop_completion); - - CDEBUG(D_INFO, "watchdog dispatcher has shut down.\n"); - - EXIT; -} - -struct lc_watchdog *lc_watchdog_add(int timeout, - void (*callback)(pid_t, void *), - void *data) -{ - struct lc_watchdog *lcw = NULL; - ENTRY; - - LIBCFS_ALLOC(lcw, sizeof(*lcw)); - if (lcw == NULL) { - CDEBUG(D_INFO, "Could not allocate new lc_watchdog\n"); - RETURN(ERR_PTR(-ENOMEM)); - } - - spin_lock_init(&lcw->lcw_lock); - lcw->lcw_refcount = 1; /* refcount for owner */ - lcw->lcw_task = current; - lcw->lcw_pid = current_pid(); - lcw->lcw_callback = (callback != NULL) ? callback : lc_watchdog_dumplog; - lcw->lcw_data = data; - lcw->lcw_state = LC_WATCHDOG_DISABLED; - - INIT_LIST_HEAD(&lcw->lcw_list); - cfs_timer_init(&lcw->lcw_timer, lcw_cb, lcw); - - mutex_lock(&lcw_refcount_mutex); - if (++lcw_refcount == 1) - lcw_dispatch_start(); - mutex_unlock(&lcw_refcount_mutex); - - /* Keep this working in case we enable them by default */ - if (lcw->lcw_state == LC_WATCHDOG_ENABLED) { - lcw->lcw_last_touched = cfs_time_current(); - cfs_timer_arm(&lcw->lcw_timer, cfs_time_seconds(timeout) + - cfs_time_current()); - } - - RETURN(lcw); -} -EXPORT_SYMBOL(lc_watchdog_add); - -static void lcw_update_time(struct lc_watchdog *lcw, const char *message) -{ - cfs_time_t newtime = cfs_time_current();; - - if (lcw->lcw_state == LC_WATCHDOG_EXPIRED) { - struct timeval timediff; - cfs_time_t delta_time = cfs_time_sub(newtime, - lcw->lcw_last_touched); - cfs_duration_usec(delta_time, &timediff); - - LCONSOLE_WARN("Service thread pid %u %s after %lu.%.02lus. " - "This indicates the system was overloaded (too " - "many service threads, or there were not enough " - "hardware resources).\n", - lcw->lcw_pid, - message, - timediff.tv_sec, - timediff.tv_usec / 10000); - } - lcw->lcw_last_touched = newtime; -} - -static void lc_watchdog_del_pending(struct lc_watchdog *lcw) -{ - spin_lock_bh(&lcw->lcw_lock); - if (unlikely(!list_empty(&lcw->lcw_list))) { - spin_lock_bh(&lcw_pending_timers_lock); - list_del_init(&lcw->lcw_list); - lcw->lcw_refcount--; /* -1 ref for pending list */ - spin_unlock_bh(&lcw_pending_timers_lock); - } - - spin_unlock_bh(&lcw->lcw_lock); -} - -void lc_watchdog_touch(struct lc_watchdog *lcw, int timeout) -{ - ENTRY; - LASSERT(lcw != NULL); - - lc_watchdog_del_pending(lcw); - - lcw_update_time(lcw, "resumed"); - lcw->lcw_state = LC_WATCHDOG_ENABLED; - - cfs_timer_arm(&lcw->lcw_timer, cfs_time_current() + - cfs_time_seconds(timeout)); - - EXIT; -} -EXPORT_SYMBOL(lc_watchdog_touch); - -void lc_watchdog_disable(struct lc_watchdog *lcw) -{ - ENTRY; - LASSERT(lcw != NULL); - - lc_watchdog_del_pending(lcw); - - lcw_update_time(lcw, "completed"); - lcw->lcw_state = LC_WATCHDOG_DISABLED; - - EXIT; -} -EXPORT_SYMBOL(lc_watchdog_disable); - -void lc_watchdog_delete(struct lc_watchdog *lcw) -{ - int dead; - - ENTRY; - LASSERT(lcw != NULL); - - cfs_timer_disarm(&lcw->lcw_timer); - - lcw_update_time(lcw, "stopped"); - - spin_lock_bh(&lcw->lcw_lock); - spin_lock_bh(&lcw_pending_timers_lock); - if (unlikely(!list_empty(&lcw->lcw_list))) { - list_del_init(&lcw->lcw_list); - lcw->lcw_refcount--; /* -1 ref for pending list */ - } - - lcw->lcw_refcount--; /* -1 ref for owner */ - dead = lcw->lcw_refcount == 0; - spin_unlock_bh(&lcw_pending_timers_lock); - spin_unlock_bh(&lcw->lcw_lock); - - if (dead) - LIBCFS_FREE(lcw, sizeof(*lcw)); - - mutex_lock(&lcw_refcount_mutex); - if (--lcw_refcount == 0) - lcw_dispatch_stop(); - mutex_unlock(&lcw_refcount_mutex); - - EXIT; -} -EXPORT_SYMBOL(lc_watchdog_delete); - -/* - * Provided watchdog handlers - */ - -void lc_watchdog_dumplog(pid_t pid, void *data) -{ - libcfs_debug_dumplog_internal((void *)((long_ptr_t)pid)); -} -EXPORT_SYMBOL(lc_watchdog_dumplog); - -#else /* !defined(WITH_WATCHDOG) */ - -struct lc_watchdog *lc_watchdog_add(int timeout, - void (*callback)(pid_t pid, void *), - void *data) -{ - static struct lc_watchdog watchdog; - return &watchdog; -} -EXPORT_SYMBOL(lc_watchdog_add); - -void lc_watchdog_touch(struct lc_watchdog *lcw, int timeout) -{ -} -EXPORT_SYMBOL(lc_watchdog_touch); - -void lc_watchdog_disable(struct lc_watchdog *lcw) -{ -} -EXPORT_SYMBOL(lc_watchdog_disable); - -void lc_watchdog_delete(struct lc_watchdog *lcw) -{ -} -EXPORT_SYMBOL(lc_watchdog_delete); - -#endif diff --git a/drivers/staging/lustre/lustre/llite/dcache.c b/drivers/staging/lustre/lustre/llite/dcache.c index ff0d085077c8..40b0f3b1debc 100644 --- a/drivers/staging/lustre/lustre/llite/dcache.c +++ b/drivers/staging/lustre/lustre/llite/dcache.c @@ -300,7 +300,7 @@ void ll_invalidate_aliases(struct inode *inode) CERROR("called on root (?) dentry=%p, inode=%p " "ino=%lu\n", dentry, inode, inode->i_ino); lustre_dump_dentry(dentry, 1); - libcfs_debug_dumpstack(NULL); + dump_stack(); } d_lustre_invalidate(dentry, 0); diff --git a/drivers/staging/lustre/lustre/llite/rw.c b/drivers/staging/lustre/lustre/llite/rw.c index fac117889011..f48766e6a212 100644 --- a/drivers/staging/lustre/lustre/llite/rw.c +++ b/drivers/staging/lustre/lustre/llite/rw.c @@ -132,7 +132,7 @@ static struct ll_cl_context *ll_cl_init(struct file *file, * add dirty pages into cache during truncate */ CERROR("Proc %s is dirting page w/o inode lock, this" "will break truncate.\n", current->comm); - libcfs_debug_dumpstack(NULL); + dump_stack(); LBUG(); return ERR_PTR(-EIO); } diff --git a/drivers/staging/lustre/lustre/osc/osc_io.c b/drivers/staging/lustre/lustre/osc/osc_io.c index 1b277045b3e4..70aad1aeec63 100644 --- a/drivers/staging/lustre/lustre/osc/osc_io.c +++ b/drivers/staging/lustre/lustre/osc/osc_io.c @@ -785,7 +785,7 @@ static void osc_req_attr_set(const struct lu_env *env, "no cover page!\n"); CL_PAGE_DEBUG(D_ERROR, env, apage, "dump uncover page!\n"); - libcfs_debug_dumpstack(NULL); + dump_stack(); LBUG(); } diff --git a/drivers/staging/lustre/lustre/ptlrpc/service.c b/drivers/staging/lustre/lustre/ptlrpc/service.c index cd1bab5a2520..687171102319 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/service.c +++ b/drivers/staging/lustre/lustre/ptlrpc/service.c @@ -2254,7 +2254,9 @@ ptlrpc_wait_event(struct ptlrpc_service_part *svcpt, struct l_wait_info lwi = LWI_TIMEOUT(svcpt->scp_rqbd_timeout, ptlrpc_retry_rqbds, svcpt); + /* XXX: Add this back when libcfs watchdog is merged upstream lc_watchdog_disable(thread->t_watchdog); + */ cond_resched(); @@ -2268,8 +2270,10 @@ ptlrpc_wait_event(struct ptlrpc_service_part *svcpt, if (ptlrpc_thread_stopping(thread)) return -EINTR; + /* lc_watchdog_touch(thread->t_watchdog, ptlrpc_server_get_timeout(svcpt)); + */ return 0; } @@ -2372,8 +2376,10 @@ static int ptlrpc_main(void *arg) /* wake up our creator in case he's still waiting. */ wake_up(&thread->t_ctl_waitq); + /* thread->t_watchdog = lc_watchdog_add(ptlrpc_server_get_timeout(svcpt), NULL, NULL); + */ spin_lock(&svcpt->scp_rep_lock); list_add(&rs->rs_list, &svcpt->scp_rep_idle); @@ -2428,8 +2434,10 @@ static int ptlrpc_main(void *arg) } } + /* lc_watchdog_delete(thread->t_watchdog); thread->t_watchdog = NULL; + */ out_srv_fini: /* From b69835a2c41dead0d5d44265e797d9d4a3b67174 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Mon, 15 Jul 2013 22:27:16 +0800 Subject: [PATCH 0305/3400] staging/lustre: fix build warnning on 32bit system MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Building on 32bit system, I got warnings like below: drivers/staging/lustre/lustre/llite/../include/lprocfs_status.h:666:7: note: expected ‘long unsigned int *’ but argument is of type ‘size_t *’ char *lprocfs_find_named_value(const char *buffer, const char *name, drivers/staging/lustre/lustre/lov/lov_io.c: In function ‘lov_io_rw_iter_init’: include/asm-generic/div64.h:43:28: warning: comparison of distinct pointer types lacks a cast [enabled by default] (void)(((typeof((n)) *)0) == ((uint64_t *)0)); \ Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lprocfs_status.h | 4 ++-- drivers/staging/lustre/lustre/lov/lov_io.c | 2 +- drivers/staging/lustre/lustre/obdclass/lprocfs_status.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/lprocfs_status.h b/drivers/staging/lustre/lustre/include/lprocfs_status.h index 55f182205d78..294fb7807c8c 100644 --- a/drivers/staging/lustre/lustre/include/lprocfs_status.h +++ b/drivers/staging/lustre/lustre/include/lprocfs_status.h @@ -663,8 +663,8 @@ extern int lprocfs_write_u64_helper(const char *buffer, unsigned long count, extern int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count, __u64 *val, int mult); -char *lprocfs_find_named_value(const char *buffer, const char *name, - unsigned long *count); +extern char *lprocfs_find_named_value(const char *buffer, const char *name, + size_t *count); void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value); void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value); void lprocfs_oh_clear(struct obd_histogram *oh); diff --git a/drivers/staging/lustre/lustre/lov/lov_io.c b/drivers/staging/lustre/lustre/lov/lov_io.c index 1a87abdf0953..022e0f4911c6 100644 --- a/drivers/staging/lustre/lustre/lov/lov_io.c +++ b/drivers/staging/lustre/lustre/lov/lov_io.c @@ -430,7 +430,7 @@ static int lov_io_rw_iter_init(const struct lu_env *env, struct lov_io *lio = cl2lov_io(env, ios); struct cl_io *io = ios->cis_io; struct lov_stripe_md *lsm = lio->lis_object->lo_lsm; - loff_t start = io->u.ci_rw.crw_pos; + __u64 start = io->u.ci_rw.crw_pos; loff_t next; unsigned long ssize = lsm->lsm_stripe_size; diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c index f7af3d6a4efc..85163f42892e 100644 --- a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c +++ b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c @@ -1873,7 +1873,7 @@ static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len) * If \a name is not found the original \a buffer is returned. */ char *lprocfs_find_named_value(const char *buffer, const char *name, - unsigned long *count) + size_t *count) { char *val; size_t buflen = *count; From 5237c44194a5605257b09af5b421dd6995645e65 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Mon, 15 Jul 2013 22:27:17 +0800 Subject: [PATCH 0306/3400] staging/lustre: fix for invalidatepage() API change somehow this got dropped during merge window... Signed-off-by: Stephen Rothwell Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../lustre/lustre/include/linux/lustre_patchless_compat.h | 2 +- drivers/staging/lustre/lustre/llite/rw26.c | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_patchless_compat.h b/drivers/staging/lustre/lustre/include/linux/lustre_patchless_compat.h index a8e9c0c8ffd2..a260e99a4447 100644 --- a/drivers/staging/lustre/lustre/include/linux/lustre_patchless_compat.h +++ b/drivers/staging/lustre/lustre/include/linux/lustre_patchless_compat.h @@ -53,7 +53,7 @@ truncate_complete_page(struct address_space *mapping, struct page *page) return; if (PagePrivate(page)) - page->mapping->a_ops->invalidatepage(page, 0); + page->mapping->a_ops->invalidatepage(page, 0, PAGE_CACHE_SIZE); cancel_dirty_page(page, PAGE_SIZE); ClearPageMappedToDisk(page); diff --git a/drivers/staging/lustre/lustre/llite/rw26.c b/drivers/staging/lustre/lustre/llite/rw26.c index 27e4e64bc1e7..f1a1c5f40a1d 100644 --- a/drivers/staging/lustre/lustre/llite/rw26.c +++ b/drivers/staging/lustre/lustre/llite/rw26.c @@ -72,7 +72,8 @@ * aligned truncate). Lustre leaves partially truncated page in the cache, * relying on struct inode::i_size to limit further accesses. */ -static void ll_invalidatepage(struct page *vmpage, unsigned long offset) +static void ll_invalidatepage(struct page *vmpage, unsigned int offset, + unsigned int length) { struct inode *inode; struct lu_env *env; @@ -89,7 +90,7 @@ static void ll_invalidatepage(struct page *vmpage, unsigned long offset) * below because they are run with page locked and all our io is * happening with locked page too */ - if (offset == 0) { + if (offset == 0 && length == PAGE_CACHE_SIZE) { env = cl_env_get(&refcheck); if (!IS_ERR(env)) { inode = vmpage->mapping->host; From 90181e1d03b2a1bc054a11c061ef61ddd1dd7b87 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Mon, 15 Jul 2013 22:27:18 +0800 Subject: [PATCH 0307/3400] staging/lustre/llite: fix for d_compare API change Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/dcache.c | 3 +-- drivers/staging/lustre/lustre/llite/llite_internal.h | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/dcache.c b/drivers/staging/lustre/lustre/llite/dcache.c index 40b0f3b1debc..a160a840d582 100644 --- a/drivers/staging/lustre/lustre/llite/dcache.c +++ b/drivers/staging/lustre/lustre/llite/dcache.c @@ -84,8 +84,7 @@ static void ll_release(struct dentry *de) * an AST before calling d_revalidate_it(). The dentry still exists (marked * INVALID) so d_lookup() matches it, but we have no lock on it (so * lock_match() fails) and we spin around real_lookup(). */ -int ll_dcompare(const struct dentry *parent, const struct inode *pinode, - const struct dentry *dentry, const struct inode *inode, +int ll_dcompare(const struct dentry *parent, const struct dentry *dentry, unsigned int len, const char *str, const struct qstr *name) { ENTRY; diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 1069b8dd84dc..cbcd11847aac 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -784,8 +784,7 @@ void ll_intent_release(struct lookup_intent *); void ll_invalidate_aliases(struct inode *); void ll_frob_intent(struct lookup_intent **itp, struct lookup_intent *deft); void ll_lookup_finish_locks(struct lookup_intent *it, struct dentry *dentry); -int ll_dcompare(const struct dentry *parent, const struct inode *pinode, - const struct dentry *dentry, const struct inode *inode, +int ll_dcompare(const struct dentry *parent, const struct dentry *dentry, unsigned int len, const char *str, const struct qstr *d_name); int ll_revalidate_it_finish(struct ptlrpc_request *request, struct lookup_intent *it, struct dentry *de); From 0b09d381bb2b4ccab15711cf98858a7146b24749 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Mon, 15 Jul 2013 22:27:19 +0800 Subject: [PATCH 0308/3400] staging/lustre/llite: readdir convert to iterate Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/dir.c | 45 +++++++++---------- .../lustre/lustre/llite/llite_internal.h | 4 +- .../staging/lustre/lustre/llite/llite_nfs.c | 13 +++--- 3 files changed, 28 insertions(+), 34 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index e2afb9730343..1084999be959 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -483,12 +483,11 @@ fail: goto out_unlock; } -int ll_dir_read(struct inode *inode, __u64 *_pos, void *cookie, - filldir_t filldir) +int ll_dir_read(struct inode *inode, struct dir_context *ctx) { struct ll_inode_info *info = ll_i2info(inode); struct ll_sb_info *sbi = ll_i2sbi(inode); - __u64 pos = *_pos; + __u64 pos = ctx->pos; int api32 = ll_need_32bit_api(sbi); int hash64 = sbi->ll_flags & LL_SBI_64BIT_HASH; struct page *page; @@ -548,12 +547,14 @@ int ll_dir_read(struct inode *inode, __u64 *_pos, void *cookie, fid_le_to_cpu(&fid, &ent->lde_fid); ino = cl_fid_build_ino(&fid, api32); type = ll_dirent_type_get(ent); + ctx->pos = lhash; /* For 'll_nfs_get_name_filldir()', it will try * to access the 'ent' through its 'lde_name', - * so the parameter 'name' for 'filldir()' must - * be part of the 'ent'. */ - done = filldir(cookie, ent->lde_name, namelen, - lhash, ino, type); + * so the parameter 'name' for 'ctx->actor()' + * must be part of the 'ent'. + */ + done = !dir_emit(ctx, ent->lde_name, + namelen, ino, type); } next = le64_to_cpu(dp->ldp_hash_end); if (!done) { @@ -594,50 +595,44 @@ int ll_dir_read(struct inode *inode, __u64 *_pos, void *cookie, } } - *_pos = pos; + ctx->pos = pos; ll_dir_chain_fini(&chain); RETURN(rc); } -static int ll_readdir(struct file *filp, void *cookie, filldir_t filldir) +static int ll_readdir(struct file *filp, struct dir_context *ctx) { struct inode *inode = filp->f_dentry->d_inode; struct ll_file_data *lfd = LUSTRE_FPRIVATE(filp); struct ll_sb_info *sbi = ll_i2sbi(inode); - __u64 pos = lfd->lfd_pos; int hash64 = sbi->ll_flags & LL_SBI_64BIT_HASH; int api32 = ll_need_32bit_api(sbi); int rc; - struct path path; ENTRY; CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p) pos %lu/%llu " " 32bit_api %d\n", inode->i_ino, inode->i_generation, - inode, (unsigned long)pos, i_size_read(inode), api32); + inode, (unsigned long)lfd->lfd_pos, i_size_read(inode), api32); - if (pos == MDS_DIR_END_OFF) + if (lfd->lfd_pos == MDS_DIR_END_OFF) /* * end-of-file. */ GOTO(out, rc = 0); - rc = ll_dir_read(inode, &pos, cookie, filldir); - lfd->lfd_pos = pos; - if (pos == MDS_DIR_END_OFF) { + ctx->pos = lfd->lfd_pos; + rc = ll_dir_read(inode, ctx); + lfd->lfd_pos = ctx->pos; + if (ctx->pos == MDS_DIR_END_OFF) { if (api32) - filp->f_pos = LL_DIR_END_OFF_32BIT; + ctx->pos = LL_DIR_END_OFF_32BIT; else - filp->f_pos = LL_DIR_END_OFF; + ctx->pos = LL_DIR_END_OFF; } else { if (api32 && hash64) - filp->f_pos = pos >> 32; - else - filp->f_pos = pos; + ctx->pos >>= 32; } filp->f_version = inode->i_version; - path.mnt = filp->f_path.mnt; - path.dentry = filp->f_dentry; - touch_atime(&path); out: if (!rc) @@ -1976,7 +1971,7 @@ struct file_operations ll_dir_operations = { .open = ll_dir_open, .release = ll_dir_release, .read = generic_read_dir, - .readdir = ll_readdir, + .iterate = ll_readdir, .unlocked_ioctl = ll_dir_ioctl, .fsync = ll_fsync, }; diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index cbcd11847aac..0534665df905 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -90,6 +90,7 @@ extern struct file_operations ll_pgcache_seq_fops; #define REMOTE_PERM_HASHSIZE 16 struct ll_getname_data { + struct dir_context ctx; char *lgd_name; /* points to a buffer with NAME_MAX+1 size */ struct lu_fid lgd_fid; /* target fid we are looking for */ int lgd_found; /* inode matched? */ @@ -679,8 +680,7 @@ extern struct file_operations ll_dir_operations; extern struct inode_operations ll_dir_inode_operations; struct page *ll_get_dir_page(struct inode *dir, __u64 hash, struct ll_dir_chain *chain); -int ll_dir_read(struct inode *inode, __u64 *_pos, void *cookie, - filldir_t filldir); +int ll_dir_read(struct inode *inode, struct dir_context *ctx); int ll_get_mdt_idx(struct inode *inode); /* llite/namei.c */ diff --git a/drivers/staging/lustre/lustre/llite/llite_nfs.c b/drivers/staging/lustre/lustre/llite/llite_nfs.c index 28cc41e90581..f142a1ec3f86 100644 --- a/drivers/staging/lustre/lustre/llite/llite_nfs.c +++ b/drivers/staging/lustre/lustre/llite/llite_nfs.c @@ -214,9 +214,12 @@ static int ll_get_name(struct dentry *dentry, char *name, struct dentry *child) { struct inode *dir = dentry->d_inode; - struct ll_getname_data lgd; - __u64 offset = 0; int rc; + struct ll_getname_data lgd = { + .lgd_name = name, + .lgd_fid = ll_i2info(child->d_inode)->lli_fid, + .ctx.actor = ll_nfs_get_name_filldir, + }; ENTRY; if (!dir || !S_ISDIR(dir->i_mode)) @@ -225,12 +228,8 @@ static int ll_get_name(struct dentry *dentry, char *name, if (!dir->i_fop) GOTO(out, rc = -EINVAL); - lgd.lgd_name = name; - lgd.lgd_fid = ll_i2info(child->d_inode)->lli_fid; - lgd.lgd_found = 0; - mutex_lock(&dir->i_mutex); - rc = ll_dir_read(dir, &offset, &lgd, ll_nfs_get_name_filldir); + rc = ll_dir_read(dir, &lgd.ctx); mutex_unlock(&dir->i_mutex); if (!rc && !lgd.lgd_found) rc = -ENOENT; From 22eb2c3d900b558ea1e300cbf2f74a9edaef6ecc Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Mon, 15 Jul 2013 22:27:20 +0800 Subject: [PATCH 0309/3400] staging/lustre: drop CONFIG_BROKEN This reverts commit 0ad1ea69545b1965be4c93ee03fdc685c6beb23d I didn't use git revert because it can not be done cleanly. Hopefully it will be the last time we do it... Cc: Stephen Rothwell Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/Kconfig b/drivers/staging/lustre/lustre/Kconfig index c59ea5564c24..893a3c6fe785 100644 --- a/drivers/staging/lustre/lustre/Kconfig +++ b/drivers/staging/lustre/lustre/Kconfig @@ -1,6 +1,6 @@ config LUSTRE_FS tristate "Lustre file system client support" - depends on STAGING && INET && m && BROKEN + depends on STAGING && INET && m select LNET select CRYPTO select CRYPTO_CRC32 From 5e8ebf13465a732c542b7e59a004e4e901e574c5 Mon Sep 17 00:00:00 2001 From: Zhao Hongjiang Date: Mon, 8 Jul 2013 17:06:14 +0800 Subject: [PATCH 0310/3400] staging/lustre: remove the second argument of ll_kmap_atomic() kmap_atomic allows only one argument now, just remove the second. Signed-off-by: Zhao Hongjiang Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/include/linux/lustre_compat25.h | 3 --- drivers/staging/lustre/lustre/llite/rw26.c | 8 ++++---- drivers/staging/lustre/lustre/llite/vvp_io.c | 4 ++-- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h b/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h index dff04688945b..426533b5d135 100644 --- a/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h +++ b/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h @@ -266,9 +266,6 @@ static inline int ll_quota_off(struct super_block *sb, int off, int remount) #define queue_max_phys_segments(rq) queue_max_segments(rq) #define queue_max_hw_segments(rq) queue_max_segments(rq) -#define ll_kmap_atomic(a, b) kmap_atomic(a) -#define ll_kunmap_atomic(a, b) kunmap_atomic(a) - #define ll_d_hlist_node hlist_node #define ll_d_hlist_empty(list) hlist_empty(list) diff --git a/drivers/staging/lustre/lustre/llite/rw26.c b/drivers/staging/lustre/lustre/llite/rw26.c index f1a1c5f40a1d..97088e6ddea0 100644 --- a/drivers/staging/lustre/lustre/llite/rw26.c +++ b/drivers/staging/lustre/lustre/llite/rw26.c @@ -287,11 +287,11 @@ ssize_t ll_direct_rw_pages(const struct lu_env *env, struct cl_io *io, src_page = (rw == WRITE) ? pages[i] : vmpage; dst_page = (rw == WRITE) ? vmpage : pages[i]; - src = ll_kmap_atomic(src_page, KM_USER0); - dst = ll_kmap_atomic(dst_page, KM_USER1); + src = kmap_atomic(src_page); + dst = kmap_atomic(dst_page); memcpy(dst, src, min(page_size, size)); - ll_kunmap_atomic(dst, KM_USER1); - ll_kunmap_atomic(src, KM_USER0); + kunmap_atomic(dst); + kunmap_atomic(src); /* make sure page will be added to the transfer by * cl_io_submit()->...->vvp_page_prep_write(). */ diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index eb964acad45c..bbd6351e1f55 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -887,10 +887,10 @@ static int vvp_io_prepare_partial(const struct lu_env *env, struct cl_io *io, * purposes here we can treat it like i_size. */ if (attr->cat_kms <= offset) { - char *kaddr = ll_kmap_atomic(cp->cpg_page, KM_USER0); + char *kaddr = kmap_atomic(cp->cpg_page); memset(kaddr, 0, cl_page_size(obj)); - ll_kunmap_atomic(kaddr, KM_USER0); + kunmap_atomic(kaddr); } else if (cp->cpg_defer_uptodate) cp->cpg_ra_used = 1; else From 7522fd7cfbc87bafc91a25b7681d8828412c1959 Mon Sep 17 00:00:00 2001 From: Dragos Foianu Date: Wed, 17 Jul 2013 12:05:24 +0100 Subject: [PATCH 0311/3400] staging/lustre/libcfs: removed dead code from libcfs_string Confirmed by cscope that the functions are not used anymore. A fresh compilation does not yield any errors. Signed-off-by: Dragos Foianu Reviewed-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../lustre/lustre/libcfs/libcfs_string.c | 48 ------------------- 1 file changed, 48 deletions(-) diff --git a/drivers/staging/lustre/lustre/libcfs/libcfs_string.c b/drivers/staging/lustre/lustre/libcfs/libcfs_string.c index 9edccc99683e..c7a19711bb6a 100644 --- a/drivers/staging/lustre/lustre/libcfs/libcfs_string.c +++ b/drivers/staging/lustre/lustre/libcfs/libcfs_string.c @@ -132,54 +132,6 @@ int cfs_str2mask(const char *str, const char *(*bit2str)(int bit), } EXPORT_SYMBOL(cfs_str2mask); -/* Duplicate a string in a platform-independent way */ -char *cfs_strdup(const char *str, u_int32_t flags) -{ - size_t lenz; /* length of str + zero byte */ - char *dup_str; - - lenz = strlen(str) + 1; - - dup_str = kmalloc(lenz, flags); - if (dup_str == NULL) - return NULL; - - memcpy(dup_str, str, lenz); - - return dup_str; -} -EXPORT_SYMBOL(cfs_strdup); - -/** - * cfs_{v}snprintf() return the actual size that is printed rather than - * the size that would be printed in standard functions. - */ -/* safe vsnprintf */ -int cfs_vsnprintf(char *buf, size_t size, const char *fmt, va_list args) -{ - int i; - - LASSERT(size > 0); - i = vsnprintf(buf, size, fmt, args); - - return (i >= size ? size - 1 : i); -} -EXPORT_SYMBOL(cfs_vsnprintf); - -/* safe snprintf */ -int cfs_snprintf(char *buf, size_t size, const char *fmt, ...) -{ - va_list args; - int i; - - va_start(args, fmt); - i = cfs_vsnprintf(buf, size, fmt, args); - va_end(args); - - return i; -} -EXPORT_SYMBOL(cfs_snprintf); - /* get the first string out of @str */ char *cfs_firststr(char *str, size_t size) { From 68a8029799ad368ee82a5cf509a2b5b802837ce9 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Sat, 13 Jul 2013 20:46:39 +0200 Subject: [PATCH 0312/3400] staging/lustre/libcfs: drop bogus Kconfig default Commit 4b5b4c7222 ("staging/lustre/libcfs: restore LINVRNT") added "default false" to this Kconfig file. It was obviously meant to use "default n" here. But we might as well drop this line, as a Kconfig bool defaults to 'n' anyway. Signed-off-by: Paul Bolle Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/Kconfig b/drivers/staging/lustre/lustre/Kconfig index 893a3c6fe785..605fca73628d 100644 --- a/drivers/staging/lustre/lustre/Kconfig +++ b/drivers/staging/lustre/lustre/Kconfig @@ -43,7 +43,6 @@ config LUSTRE_OBD_MAX_IOCTL_BUFFER config LUSTRE_DEBUG_EXPENSIVE_CHECK bool "Enable Lustre DEBUG checks" depends on LUSTRE_FS - default false help This option is mainly for debug purpose. It enables Lustre code to do expensive checks that may have a performance impact. From 2c922ba54fcfbad313a7cfe9be53698b0fcbf075 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Tue, 23 Jul 2013 00:06:22 +0800 Subject: [PATCH 0313/3400] staging/lustre: remove bogus ifndef EXPORT_SYMBOL Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/libcfs_prim.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_prim.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_prim.h index 9c40ed904da5..36def3615d01 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_prim.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_prim.h @@ -40,10 +40,6 @@ #ifndef __LIBCFS_PRIM_H__ #define __LIBCFS_PRIM_H__ -#ifndef EXPORT_SYMBOL -# define EXPORT_SYMBOL(s) -#endif - /* * Schedule */ From 4f37bc04805e20f2a8907a49f06b310e4ebf82b8 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Tue, 23 Jul 2013 00:06:24 +0800 Subject: [PATCH 0314/3400] staging/lustre/llite: use READ, WRITE around ll_rw_stats_tally() In vvp_io_write_start() the stats function ll_rw_stats_tally() was incorrectly called with a rw argument of 0. Correct this and use the macros READ and WRITE in and around ll_rw_stats_tally() for clarity. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3384 Lustre-change: http://review.whamcloud.com/6447 Signed-off-by: John L. Hammond Reviewed-by: Andreas Dilger Reviewed-by: Jinshan Xiong Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/lproc_llite.c | 10 ++++++---- drivers/staging/lustre/lustre/llite/vvp_io.c | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/lproc_llite.c b/drivers/staging/lustre/lustre/llite/lproc_llite.c index 5c7368c358a0..a7b12fdd76b1 100644 --- a/drivers/staging/lustre/lustre/llite/lproc_llite.c +++ b/drivers/staging/lustre/lustre/llite/lproc_llite.c @@ -1303,8 +1303,9 @@ static int ll_rw_offset_stats_seq_show(struct seq_file *seq, void *v) /* We stored the discontiguous offsets here; print them first */ for(i = 0; i < LL_OFFSET_HIST_MAX; i++) { if (offset[i].rw_pid != 0) - seq_printf(seq,"%3c %10d %14Lu %14Lu %17lu %17lu %14Lu", - offset[i].rw_op ? 'W' : 'R', + seq_printf(seq, + "%3c %10d %14Lu %14Lu %17lu %17lu %14Lu", + offset[i].rw_op == READ ? 'R' : 'W', offset[i].rw_pid, offset[i].rw_range_start, offset[i].rw_range_end, @@ -1315,8 +1316,9 @@ static int ll_rw_offset_stats_seq_show(struct seq_file *seq, void *v) /* Then print the current offsets for each process */ for(i = 0; i < LL_PROCESS_HIST_MAX; i++) { if (process[i].rw_pid != 0) - seq_printf(seq,"%3c %10d %14Lu %14Lu %17lu %17lu %14Lu", - process[i].rw_op ? 'W' : 'R', + seq_printf(seq, + "%3c %10d %14Lu %14Lu %17lu %17lu %14Lu", + process[i].rw_op == READ ? 'R' : 'W', process[i].rw_pid, process[i].rw_range_start, process[i].rw_last_file_pos, diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index bbd6351e1f55..20eac2fd63c3 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -525,7 +525,7 @@ out: io->ci_continue = 0; io->ci_nob += result; ll_rw_stats_tally(ll_i2sbi(inode), current->pid, - cio->cui_fd, pos, result, 0); + cio->cui_fd, pos, result, READ); result = 0; } return result; @@ -580,7 +580,7 @@ static int vvp_io_write_start(const struct lu_env *env, io->ci_continue = 0; io->ci_nob += result; ll_rw_stats_tally(ll_i2sbi(inode), current->pid, - cio->cui_fd, pos, result, 0); + cio->cui_fd, pos, result, WRITE); result = 0; } RETURN(result); From 1253b2e850850a66a71a512d2f830d4e0205ac72 Mon Sep 17 00:00:00 2001 From: wang di Date: Tue, 23 Jul 2013 00:06:25 +0800 Subject: [PATCH 0315/3400] staging/lustre/llite: missing last bit in ll_have_md_lock Missing the last bit during INODELOCK check in ll_have_md_lock. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3385 Lustre-change: http://review.whamcloud.com/6438 Signed-off-by: wang di Reviewed-by: Oleg Drokin Reviewed-by: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index ed1e3f7b4e58..efe66d996f5e 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -2448,7 +2448,7 @@ int ll_have_md_lock(struct inode *inode, __u64 *bits, ldlm_mode_t l_req_mode) ldlm_lockname[mode]); flags = LDLM_FL_BLOCK_GRANTED | LDLM_FL_CBPENDING | LDLM_FL_TEST_LOCK; - for (i = 0; i < MDS_INODELOCK_MAXSHIFT && *bits != 0; i++) { + for (i = 0; i <= MDS_INODELOCK_MAXSHIFT && *bits != 0; i++) { policy.l_inodebits.bits = *bits & (1 << i); if (policy.l_inodebits.bits == 0) continue; From 2753e6f8207355ab72574d48287cec187272a151 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Mon, 22 Jul 2013 17:15:52 +0200 Subject: [PATCH 0316/3400] regmap: irq: Allow to acknowledge masked interrupts during initialization In case the hardware interrupt mask register does not prevent the chip level irq from being asserted by the corresponding interrupt status bit, already set interrupt bits should to be cleared once after masking them during initialization. Add a flag to let drivers enable this behavior. Signed-off-by: Philipp Zabel Signed-off-by: Mark Brown --- drivers/base/regmap/regmap-irq.c | 25 +++++++++++++++++++++++++ include/linux/regmap.h | 2 ++ 2 files changed, 27 insertions(+) diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c index 1643e889bafc..d10456ffd811 100644 --- a/drivers/base/regmap/regmap-irq.c +++ b/drivers/base/regmap/regmap-irq.c @@ -418,6 +418,31 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, reg, ret); goto err_alloc; } + + if (!chip->init_ack_masked) + continue; + + /* Ack masked but set interrupts */ + reg = chip->status_base + + (i * map->reg_stride * d->irq_reg_stride); + ret = regmap_read(map, reg, &d->status_buf[i]); + if (ret != 0) { + dev_err(map->dev, "Failed to read IRQ status: %d\n", + ret); + goto err_alloc; + } + + if (d->status_buf[i] && chip->ack_base) { + reg = chip->ack_base + + (i * map->reg_stride * d->irq_reg_stride); + ret = regmap_write(map, reg, + d->status_buf[i] & d->mask_buf[i]); + if (ret != 0) { + dev_err(map->dev, "Failed to ack 0x%x: %d\n", + reg, ret); + goto err_alloc; + } + } } /* Wake is disabled by default */ diff --git a/include/linux/regmap.h b/include/linux/regmap.h index 75981d0b57dc..34ebe7778033 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h @@ -470,6 +470,7 @@ struct regmap_irq { * @ack_base: Base ack address. If zero then the chip is clear on read. * @wake_base: Base address for wake enables. If zero unsupported. * @irq_reg_stride: Stride to use for chips where registers are not contiguous. + * @init_ack_masked: Ack all masked interrupts once during initalization. * @runtime_pm: Hold a runtime PM lock on the device when accessing it. * * @num_regs: Number of registers in each control bank. @@ -485,6 +486,7 @@ struct regmap_irq_chip { unsigned int ack_base; unsigned int wake_base; unsigned int irq_reg_stride; + bool init_ack_masked; unsigned int mask_invert; unsigned int wake_invert; bool runtime_pm; From f8c47be4e883bc49171a85985e6fb54d4680c6eb Mon Sep 17 00:00:00 2001 From: Sebastien Buisson Date: Tue, 23 Jul 2013 00:06:26 +0800 Subject: [PATCH 0317/3400] staging/lustre: fix 'program hangs' errors Fix 'program hangs' defects found by Coverity version 6.5.1: Missing unlock (LOCK) Returning without unlocking. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3054 Lustre-change: http://review.whamcloud.com/5870 Signed-off-by: Sebastien Buisson Reviewed-by: Dmitry Eremin Reviewed-by: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/selftest/rpc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lnet/selftest/rpc.c b/drivers/staging/lustre/lnet/selftest/rpc.c index bc1f38b80486..0dfc76e02e0b 100644 --- a/drivers/staging/lustre/lnet/selftest/rpc.c +++ b/drivers/staging/lustre/lnet/selftest/rpc.c @@ -661,8 +661,10 @@ srpc_finish_service(struct srpc_service *sv) cfs_percpt_for_each(scd, i, sv->sv_cpt_data) { spin_lock(&scd->scd_lock); - if (!swi_deschedule_workitem(&scd->scd_buf_wi)) + if (!swi_deschedule_workitem(&scd->scd_buf_wi)) { + spin_unlock(&scd->scd_lock); return 0; + } if (scd->scd_buf_nposted > 0) { CDEBUG(D_NET, "waiting for %d posted buffers to unlink", From 73863d83b8066b3f7973fd5671162c846b7aea8f Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Tue, 23 Jul 2013 00:06:27 +0800 Subject: [PATCH 0318/3400] staging/lustre/llite: check alloc in ll_file_data_get, ll_dir_ioctl In ll_file_data_get() and ll_dir_ioctl() return error on failed allocations. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2753 Lustre-change: http://review.whamcloud.com/5845 Signed-off-by: John L. Hammond Reviewed-by: Andreas Dilger Reviewed-by: Dmitry Eremin Reviewed-by: Sebastien Buisson Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/dir.c | 2 ++ drivers/staging/lustre/lustre/llite/file.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 1084999be959..bfc914e4be08 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -1561,6 +1561,8 @@ out_rmdir: RETURN(rc); OBD_ALLOC_LARGE(lmm, lmmsize); + if (lmm == NULL) + RETURN(-ENOMEM); if (copy_from_user(lmm, lum, lmmsize)) GOTO(free_lmm, rc = -EFAULT); diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index efe66d996f5e..927b3a03e654 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -55,6 +55,8 @@ struct ll_file_data *ll_file_data_get(void) struct ll_file_data *fd; OBD_SLAB_ALLOC_PTR_GFP(fd, ll_file_data_slab, __GFP_IO); + if (fd == NULL) + return NULL; fd->fd_write_failed = false; return fd; } From e06c9dfec0f3738409b3936dcd0a4ae126acac07 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin Date: Tue, 23 Jul 2013 00:06:28 +0800 Subject: [PATCH 0319/3400] staging/lustre/llite: A not locked mutex can be unlocked. In case of memory pressure a not locked mutex can be unlocked in function ll_file_open(). This is not allowed and subsequent behavior is not defined. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3157 Lustre-change: http://review.whamcloud.com/6028 Signed-off-by: Dmitry Eremin Reviewed-by: John Hammond Reviewed-by: Nikitas Angelinas Reviewed-by: Sebastien Buisson Reviewed-by: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 927b3a03e654..717682c162ec 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -526,7 +526,7 @@ int ll_file_open(struct inode *inode, struct file *file) fd = ll_file_data_get(); if (fd == NULL) - GOTO(out_och_free, rc = -ENOMEM); + GOTO(out_openerr, rc = -ENOMEM); fd->fd_file = file; if (S_ISDIR(inode->i_mode)) { From 79a8726a8453a2350f463fc3182bae43a5417181 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Tue, 23 Jul 2013 00:06:29 +0800 Subject: [PATCH 0320/3400] staging/lustre/llite: check ll_prep_md_op_data() using IS_ERR() In ll_file_ioctl() and ll_swap_layouts() check the result of ll_prep_md_op_data() using IS_ERR(). Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3283 Lustre-change: http://review.whamcloud.com/6275 Signed-off-by: John L. Hammond Reviewed-by: Jinshan Xiong Reviewed-by: Fan Yong Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/file.c | 24 +++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 717682c162ec..50ef6a587dc3 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -1832,12 +1832,12 @@ static int ll_swap_layouts(struct file *file1, struct file *file2, rc = -ENOMEM; op_data = ll_prep_md_op_data(NULL, llss->inode1, llss->inode2, NULL, 0, 0, LUSTRE_OPC_ANY, &msl); - if (op_data != NULL) { - rc = obd_iocontrol(LL_IOC_LOV_SWAP_LAYOUTS, - ll_i2mdexp(llss->inode1), - sizeof(*op_data), op_data, NULL); - ll_finish_md_op_data(op_data); - } + if (IS_ERR(op_data)) + GOTO(free, rc = PTR_ERR(op_data)); + + rc = obd_iocontrol(LL_IOC_LOV_SWAP_LAYOUTS, ll_i2mdexp(llss->inode1), + sizeof(*op_data), op_data, NULL); + ll_finish_md_op_data(op_data); putgl: if (gid != 0) { @@ -2031,9 +2031,9 @@ long ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0, LUSTRE_OPC_ANY, hus); - if (op_data == NULL) { + if (IS_ERR(op_data)) { OBD_FREE_PTR(hus); - RETURN(-ENOMEM); + RETURN(PTR_ERR(op_data)); } rc = obd_iocontrol(cmd, ll_i2mdexp(inode), sizeof(*op_data), @@ -2069,9 +2069,9 @@ long ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0, LUSTRE_OPC_ANY, hss); - if (op_data == NULL) { + if (IS_ERR(op_data)) { OBD_FREE_PTR(hss); - RETURN(-ENOMEM); + RETURN(PTR_ERR(op_data)); } rc = obd_iocontrol(cmd, ll_i2mdexp(inode), sizeof(*op_data), @@ -2093,9 +2093,9 @@ long ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0, LUSTRE_OPC_ANY, hca); - if (op_data == NULL) { + if (IS_ERR(op_data)) { OBD_FREE_PTR(hca); - RETURN(-ENOMEM); + RETURN(PTR_ERR(op_data)); } rc = obd_iocontrol(cmd, ll_i2mdexp(inode), sizeof(*op_data), From c5b60ba79d67797ab6fffcab5edd9364b14d1dd7 Mon Sep 17 00:00:00 2001 From: Andreas Dilger Date: Tue, 23 Jul 2013 00:06:30 +0800 Subject: [PATCH 0321/3400] staging/lustre/ldlm: print FID in lvbo_init(), lvbo_update Print the namespace and OBD device name, as well as the first two lock resource fields (typically the FID) if there is an error with loading the object from disk. This will be more important with FID-on-OST and also the MDS. Using fid_extract_from_res_name() isn't possible in the LDLM code, since the lock resource may not be a FID. Make fid_extract_quota_resid() argument order and name consistent with other fid_*_res() functions, with FID first and resource second. Fix a bug in ofd_lvbo_init() where NULL lvb is accessed on error. Print FID in ofd_lvbo_update() CDEBUG() and CERROR() messages. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2193 Lustre-change: http://review.whamcloud.com/4501 Signed-off-by: Andreas Dilger Reviewed-by: Jinshan Xiong Reviewed-by: Bobi Jam Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../lustre/lustre/include/lustre/lustre_idl.h | 4 +- .../lustre/lustre/include/lustre_fid.h | 89 ++++++++++--------- .../lustre/lustre/ldlm/ldlm_resource.c | 5 +- 3 files changed, 50 insertions(+), 48 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 8825460f12ac..1cfebfea7b77 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -911,7 +911,7 @@ static inline int lu_fid_cmp(const struct lu_fid *f0, __diff_normalize(fid_ver(f0), fid_ver(f1)); } -static inline void ostid_cpu_to_le(struct ost_id *src_oi, +static inline void ostid_cpu_to_le(const struct ost_id *src_oi, struct ost_id *dst_oi) { if (fid_seq_is_mdt0(ostid_seq(src_oi))) { @@ -922,7 +922,7 @@ static inline void ostid_cpu_to_le(struct ost_id *src_oi, } } -static inline void ostid_le_to_cpu(struct ost_id *src_oi, +static inline void ostid_le_to_cpu(const struct ost_id *src_oi, struct ost_id *dst_oi) { if (fid_seq_is_mdt0(ostid_seq(src_oi))) { diff --git a/drivers/staging/lustre/lustre/include/lustre_fid.h b/drivers/staging/lustre/lustre/include/lustre_fid.h index 7d20cba07287..7523b407488e 100644 --- a/drivers/staging/lustre/lustre/include/lustre_fid.h +++ b/drivers/staging/lustre/lustre/include/lustre_fid.h @@ -488,74 +488,75 @@ struct ldlm_namespace; * renaming name[2,3] fields that need to be used for the quota identifier. */ static inline struct ldlm_res_id * -fid_build_reg_res_name(const struct lu_fid *f, - struct ldlm_res_id *name) +fid_build_reg_res_name(const struct lu_fid *fid, struct ldlm_res_id *res) { - memset(name, 0, sizeof *name); - name->name[LUSTRE_RES_ID_SEQ_OFF] = fid_seq(f); - name->name[LUSTRE_RES_ID_VER_OID_OFF] = fid_ver_oid(f); - return name; + memset(res, 0, sizeof(*res)); + res->name[LUSTRE_RES_ID_SEQ_OFF] = fid_seq(fid); + res->name[LUSTRE_RES_ID_VER_OID_OFF] = fid_ver_oid(fid); + + return res; +} + +/* + * Return true if resource is for object identified by FID. + */ +static inline int fid_res_name_eq(const struct lu_fid *fid, + const struct ldlm_res_id *res) +{ + return res->name[LUSTRE_RES_ID_SEQ_OFF] == fid_seq(fid) && + res->name[LUSTRE_RES_ID_VER_OID_OFF] == fid_ver_oid(fid); +} + +/* + * Extract FID from LDLM resource. Reverse of fid_build_reg_res_name(). + */ +static inline struct lu_fid * +fid_extract_from_res_name(struct lu_fid *fid, const struct ldlm_res_id *res) +{ + fid->f_seq = res->name[LUSTRE_RES_ID_SEQ_OFF]; + fid->f_oid = (__u32)(res->name[LUSTRE_RES_ID_VER_OID_OFF]); + fid->f_ver = (__u32)(res->name[LUSTRE_RES_ID_VER_OID_OFF] >> 32); + LASSERT(fid_res_name_eq(fid, res)); + + return fid; } /* * Build (DLM) resource identifier from global quota FID and quota ID. */ static inline struct ldlm_res_id * -fid_build_quota_resid(const struct lu_fid *glb_fid, union lquota_id *qid, +fid_build_quota_res_name(const struct lu_fid *glb_fid, union lquota_id *qid, struct ldlm_res_id *res) { fid_build_reg_res_name(glb_fid, res); res->name[LUSTRE_RES_ID_QUOTA_SEQ_OFF] = fid_seq(&qid->qid_fid); res->name[LUSTRE_RES_ID_QUOTA_VER_OID_OFF] = fid_ver_oid(&qid->qid_fid); + return res; } /* * Extract global FID and quota ID from resource name */ -static inline void fid_extract_quota_resid(struct ldlm_res_id *res, - struct lu_fid *glb_fid, - union lquota_id *qid) +static inline void fid_extract_from_quota_res(struct lu_fid *glb_fid, + union lquota_id *qid, + const struct ldlm_res_id *res) { - glb_fid->f_seq = res->name[LUSTRE_RES_ID_SEQ_OFF]; - glb_fid->f_oid = (__u32)res->name[LUSTRE_RES_ID_VER_OID_OFF]; - glb_fid->f_ver = (__u32)(res->name[LUSTRE_RES_ID_VER_OID_OFF] >> 32); - + fid_extract_from_res_name(glb_fid, res); qid->qid_fid.f_seq = res->name[LUSTRE_RES_ID_QUOTA_SEQ_OFF]; qid->qid_fid.f_oid = (__u32)res->name[LUSTRE_RES_ID_QUOTA_VER_OID_OFF]; qid->qid_fid.f_ver = (__u32)(res->name[LUSTRE_RES_ID_QUOTA_VER_OID_OFF] >> 32); } -/* - * Return true if resource is for object identified by fid. - */ -static inline int fid_res_name_eq(const struct lu_fid *f, - const struct ldlm_res_id *name) -{ - return name->name[LUSTRE_RES_ID_SEQ_OFF] == fid_seq(f) && - name->name[LUSTRE_RES_ID_VER_OID_OFF] == fid_ver_oid(f); -} - -/* reverse function of fid_build_reg_res_name() */ -static inline void fid_build_from_res_name(struct lu_fid *f, - const struct ldlm_res_id *name) -{ - fid_zero(f); - f->f_seq = name->name[LUSTRE_RES_ID_SEQ_OFF]; - f->f_oid = name->name[LUSTRE_RES_ID_VER_OID_OFF] & 0xffffffff; - f->f_ver = name->name[LUSTRE_RES_ID_VER_OID_OFF] >> 32; - LASSERT(fid_res_name_eq(f, name)); -} - static inline struct ldlm_res_id * -fid_build_pdo_res_name(const struct lu_fid *f, - unsigned int hash, - struct ldlm_res_id *name) +fid_build_pdo_res_name(const struct lu_fid *fid, unsigned int hash, + struct ldlm_res_id *res) { - fid_build_reg_res_name(f, name); - name->name[LUSTRE_RES_ID_HSH_OFF] = hash; - return name; + fid_build_reg_res_name(fid, res); + res->name[LUSTRE_RES_ID_HSH_OFF] = hash; + + return res; } /** @@ -584,7 +585,7 @@ static inline void ostid_build_res_name(struct ost_id *oi, name->name[LUSTRE_RES_ID_SEQ_OFF] = ostid_id(oi); name->name[LUSTRE_RES_ID_VER_OID_OFF] = ostid_seq(oi); } else { - fid_build_reg_res_name((struct lu_fid *)oi, name); + fid_build_reg_res_name(&oi->oi_fid, name); } } @@ -597,7 +598,7 @@ static inline void ostid_res_name_to_id(struct ost_id *oi, ostid_set_id(oi, name->name[LUSTRE_RES_ID_SEQ_OFF]); } else { /* new resid */ - fid_build_from_res_name((struct lu_fid *)oi, name); + fid_extract_from_res_name(&oi->oi_fid, name); } } @@ -644,7 +645,7 @@ static inline void ost_fid_from_resid(struct lu_fid *fid, ostid_to_fid(fid, &oi, 0); } else { /* new resid */ - fid_build_from_res_name(fid, name); + fid_extract_from_res_name(fid, name); } } diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c index 9052dc5e7ad2..cb8659f71149 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c @@ -1128,8 +1128,9 @@ ldlm_resource_get(struct ldlm_namespace *ns, struct ldlm_resource *parent, OBD_FAIL_TIMEOUT(OBD_FAIL_LDLM_CREATE_RESOURCE, 2); rc = ns->ns_lvbo->lvbo_init(res); if (rc < 0) { - CERROR("lvbo_init failed for resource " - LPU64": rc %d\n", name->name[0], rc); + CERROR("%s: lvbo_init failed for resource "LPX64":" + LPX64": rc = %d\n", ns->ns_obd->obd_name, + name->name[0], name->name[1], rc); if (res->lr_lvb_data) { OBD_FREE(res->lr_lvb_data, res->lr_lvb_len); res->lr_lvb_data = NULL; From 2080205729edf2a59296f17081c9aa25a7ed6368 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin Date: Tue, 23 Jul 2013 00:06:31 +0800 Subject: [PATCH 0322/3400] staging/lustre/ptlrpc: race in pinger (use-after-free situation) The race is result of use-after-free situation: ~ ptlrpc_stop_pinger() ~ ptlrpc_pinger_main() --------------------------------------------------------------- thread_set_flags(SVC_STOPPING) cfs_waitq_signal(pinger_thread) ... ... thread_set_flags(SVC_STOPPED) l_wait_event(thread_is_stopped) OBD_FREE_PTR(pinger_thread) ... cfs_waitq_signal(pinger_thread) --------------------------------------------------------------- The memory used by pinger_thread might have been freed and reallocated to something else, when ptlrpc_pinger_main() used it in cvs_waitq_signal(). Signed-off-by: Li Wei Signed-off-by: Dmitry Eremin Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3032 Lustre-change: http://review.whamcloud.com/6040 Reviewed-by: Faccini Bruno Reviewed-by: Mike Pershin Reviewed-by: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ptlrpc/pinger.c | 39 ++++++++----------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/drivers/staging/lustre/lustre/ptlrpc/pinger.c b/drivers/staging/lustre/lustre/ptlrpc/pinger.c index ef5269aee0de..f521251a1a6e 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pinger.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pinger.c @@ -369,7 +369,7 @@ static int ptlrpc_pinger_main(void *arg) return 0; } -static struct ptlrpc_thread *pinger_thread = NULL; +static struct ptlrpc_thread pinger_thread; int ptlrpc_start_pinger(void) { @@ -377,29 +377,25 @@ int ptlrpc_start_pinger(void) int rc; ENTRY; - if (pinger_thread != NULL) + if (!thread_is_init(&pinger_thread) && + !thread_is_stopped(&pinger_thread)) RETURN(-EALREADY); - OBD_ALLOC_PTR(pinger_thread); - if (pinger_thread == NULL) - RETURN(-ENOMEM); - init_waitqueue_head(&pinger_thread->t_ctl_waitq); + init_waitqueue_head(&pinger_thread.t_ctl_waitq); init_waitqueue_head(&suspend_timeouts_waitq); - strcpy(pinger_thread->t_name, "ll_ping"); + strcpy(pinger_thread.t_name, "ll_ping"); /* CLONE_VM and CLONE_FILES just avoid a needless copy, because we * just drop the VM and FILES in cfs_daemonize_ctxt() right away. */ rc = PTR_ERR(kthread_run(ptlrpc_pinger_main, - pinger_thread, pinger_thread->t_name)); + &pinger_thread, pinger_thread.t_name)); if (IS_ERR_VALUE(rc)) { CERROR("cannot start thread: %d\n", rc); - OBD_FREE(pinger_thread, sizeof(*pinger_thread)); - pinger_thread = NULL; RETURN(rc); } - l_wait_event(pinger_thread->t_ctl_waitq, - thread_is_running(pinger_thread), &lwi); + l_wait_event(pinger_thread.t_ctl_waitq, + thread_is_running(&pinger_thread), &lwi); if (suppress_pings) CWARN("Pings will be suppressed at the request of the " @@ -419,20 +415,17 @@ int ptlrpc_stop_pinger(void) int rc = 0; ENTRY; - if (pinger_thread == NULL) + if (!thread_is_init(&pinger_thread) && + !thread_is_stopped(&pinger_thread)) RETURN(-EALREADY); ptlrpc_pinger_remove_timeouts(); - mutex_lock(&pinger_mutex); - thread_set_flags(pinger_thread, SVC_STOPPING); - wake_up(&pinger_thread->t_ctl_waitq); - mutex_unlock(&pinger_mutex); + thread_set_flags(&pinger_thread, SVC_STOPPING); + wake_up(&pinger_thread.t_ctl_waitq); - l_wait_event(pinger_thread->t_ctl_waitq, - thread_is_stopped(pinger_thread), &lwi); + l_wait_event(pinger_thread.t_ctl_waitq, + thread_is_stopped(&pinger_thread), &lwi); - OBD_FREE_PTR(pinger_thread); - pinger_thread = NULL; RETURN(rc); } @@ -617,8 +610,8 @@ int ptlrpc_pinger_remove_timeouts(void) void ptlrpc_pinger_wake_up() { - thread_add_flags(pinger_thread, SVC_EVENT); - wake_up(&pinger_thread->t_ctl_waitq); + thread_add_flags(&pinger_thread, SVC_EVENT); + wake_up(&pinger_thread.t_ctl_waitq); } /* Ping evictor thread */ From 2d58de78b2f6c53688a154b02bae3ada19ed15a9 Mon Sep 17 00:00:00 2001 From: Li Wei Date: Tue, 23 Jul 2013 00:06:32 +0800 Subject: [PATCH 0323/3400] staging/lustre/ptlrpc: Translate between host and network errnos Lustre puts system errors (e.g., ENOTCONN) on wire as numbers essentially specific to senders' architectures. While this is fine for x86-only sites, where receivers share the same error number definition with senders, problems will arise, however, for sites involving multiple architectures with different error number definitions. For instance, an ENOTCONN reply from a sparc server will be put on wire as -57, which, for an x86 client, means EBADSLT instead. To solve the problem, this patch defines a set of network errors for on-wire or on-disk uses. These errors correspond to a subset of the x86 system errors and share the same number definition, maintaining compatibility with existing x86 clients and servers. Then, either error numbers could be translated at run time, or all host errors going on wire could be replaced with network errors in the code. This patch does the former by introducing both generic and field-specific translation routines and calling them at proper places, so that translations for existing fields are transparent. (Personally, I tend to think the latter way might be worthwhile, as it is more straightforward conceptually. Do we really need so many different errors? Should errors returned by kernel routines really be passed up and eventually put on wire? There could even be security implications in that.) Thank Fujitsu for the original idea and their contributions that make this available upstream. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2743 Lustre-change: http://review.whamcloud.com/5577 Signed-off-by: Li Wei Reviewed-by: Andreas Dilger Reviewed-by: Hiroya Nozaki Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/Kconfig | 5 + .../lustre/include/lustre/lustre_errno.h | 215 ++++++++++ .../lustre/lustre/include/lustre/lustre_idl.h | 2 + .../lustre/lustre/include/lustre_net.h | 32 ++ .../staging/lustre/lustre/ldlm/ldlm_lock.c | 3 +- .../staging/lustre/lustre/ldlm/ldlm_lockd.c | 2 + .../staging/lustre/lustre/ldlm/ldlm_request.c | 6 +- drivers/staging/lustre/lustre/mdc/mdc_locks.c | 10 + .../staging/lustre/lustre/mdc/mdc_request.c | 1 + .../staging/lustre/lustre/osc/osc_request.c | 2 + drivers/staging/lustre/lustre/ptlrpc/Makefile | 1 + drivers/staging/lustre/lustre/ptlrpc/errno.c | 382 ++++++++++++++++++ drivers/staging/lustre/lustre/ptlrpc/niobuf.c | 3 +- .../lustre/lustre/ptlrpc/pack_generic.c | 3 + 14 files changed, 662 insertions(+), 5 deletions(-) create mode 100644 drivers/staging/lustre/lustre/include/lustre/lustre_errno.h create mode 100644 drivers/staging/lustre/lustre/ptlrpc/errno.c diff --git a/drivers/staging/lustre/lustre/Kconfig b/drivers/staging/lustre/lustre/Kconfig index 605fca73628d..9ae7fa86b5a8 100644 --- a/drivers/staging/lustre/lustre/Kconfig +++ b/drivers/staging/lustre/lustre/Kconfig @@ -48,3 +48,8 @@ config LUSTRE_DEBUG_EXPENSIVE_CHECK expensive checks that may have a performance impact. Use with caution. If unsure, say N. + +config LUSTRE_TRANSLATE_ERRNOS + bool + depends on LUSTRE_FS && !X86 + default true diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_errno.h b/drivers/staging/lustre/lustre/include/lustre/lustre_errno.h new file mode 100644 index 000000000000..2870487dd286 --- /dev/null +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_errno.h @@ -0,0 +1,215 @@ +/* + * GPL HEADER START + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * 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 version 2 for more details (a copy is included + * in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * GPL HEADER END + */ +/* + * Copyright (C) 2011 FUJITSU LIMITED. All rights reserved. + * + * Copyright (c) 2013, Intel Corporation. + */ + +#ifndef LUSTRE_ERRNO_H +#define LUSTRE_ERRNO_H + +/* + * Only "network" errnos, which are defined below, are allowed on wire (or on + * disk). Generic routines exist to help translate between these and a subset + * of the "host" errnos. Some host errnos (e.g., EDEADLOCK) are intentionally + * left out. See also the comment on lustre_errno_hton_mapping[]. + * + * To maintain compatibility with existing x86 clients and servers, each of + * these network errnos has the same numerical value as its corresponding host + * errno on x86. + */ +#define LUSTRE_EPERM 1 /* Operation not permitted */ +#define LUSTRE_ENOENT 2 /* No such file or directory */ +#define LUSTRE_ESRCH 3 /* No such process */ +#define LUSTRE_EINTR 4 /* Interrupted system call */ +#define LUSTRE_EIO 5 /* I/O error */ +#define LUSTRE_ENXIO 6 /* No such device or address */ +#define LUSTRE_E2BIG 7 /* Argument list too long */ +#define LUSTRE_ENOEXEC 8 /* Exec format error */ +#define LUSTRE_EBADF 9 /* Bad file number */ +#define LUSTRE_ECHILD 10 /* No child processes */ +#define LUSTRE_EAGAIN 11 /* Try again */ +#define LUSTRE_ENOMEM 12 /* Out of memory */ +#define LUSTRE_EACCES 13 /* Permission denied */ +#define LUSTRE_EFAULT 14 /* Bad address */ +#define LUSTRE_ENOTBLK 15 /* Block device required */ +#define LUSTRE_EBUSY 16 /* Device or resource busy */ +#define LUSTRE_EEXIST 17 /* File exists */ +#define LUSTRE_EXDEV 18 /* Cross-device link */ +#define LUSTRE_ENODEV 19 /* No such device */ +#define LUSTRE_ENOTDIR 20 /* Not a directory */ +#define LUSTRE_EISDIR 21 /* Is a directory */ +#define LUSTRE_EINVAL 22 /* Invalid argument */ +#define LUSTRE_ENFILE 23 /* File table overflow */ +#define LUSTRE_EMFILE 24 /* Too many open files */ +#define LUSTRE_ENOTTY 25 /* Not a typewriter */ +#define LUSTRE_ETXTBSY 26 /* Text file busy */ +#define LUSTRE_EFBIG 27 /* File too large */ +#define LUSTRE_ENOSPC 28 /* No space left on device */ +#define LUSTRE_ESPIPE 29 /* Illegal seek */ +#define LUSTRE_EROFS 30 /* Read-only file system */ +#define LUSTRE_EMLINK 31 /* Too many links */ +#define LUSTRE_EPIPE 32 /* Broken pipe */ +#define LUSTRE_EDOM 33 /* Math argument out of domain of + func */ +#define LUSTRE_ERANGE 34 /* Math result not representable */ +#define LUSTRE_EDEADLK 35 /* Resource deadlock would occur */ +#define LUSTRE_ENAMETOOLONG 36 /* File name too long */ +#define LUSTRE_ENOLCK 37 /* No record locks available */ +#define LUSTRE_ENOSYS 38 /* Function not implemented */ +#define LUSTRE_ENOTEMPTY 39 /* Directory not empty */ +#define LUSTRE_ELOOP 40 /* Too many symbolic links + encountered */ +#define LUSTRE_ENOMSG 42 /* No message of desired type */ +#define LUSTRE_EIDRM 43 /* Identifier removed */ +#define LUSTRE_ECHRNG 44 /* Channel number out of range */ +#define LUSTRE_EL2NSYNC 45 /* Level 2 not synchronized */ +#define LUSTRE_EL3HLT 46 /* Level 3 halted */ +#define LUSTRE_EL3RST 47 /* Level 3 reset */ +#define LUSTRE_ELNRNG 48 /* Link number out of range */ +#define LUSTRE_EUNATCH 49 /* Protocol driver not attached */ +#define LUSTRE_ENOCSI 50 /* No CSI structure available */ +#define LUSTRE_EL2HLT 51 /* Level 2 halted */ +#define LUSTRE_EBADE 52 /* Invalid exchange */ +#define LUSTRE_EBADR 53 /* Invalid request descriptor */ +#define LUSTRE_EXFULL 54 /* Exchange full */ +#define LUSTRE_ENOANO 55 /* No anode */ +#define LUSTRE_EBADRQC 56 /* Invalid request code */ +#define LUSTRE_EBADSLT 57 /* Invalid slot */ +#define LUSTRE_EBFONT 59 /* Bad font file format */ +#define LUSTRE_ENOSTR 60 /* Device not a stream */ +#define LUSTRE_ENODATA 61 /* No data available */ +#define LUSTRE_ETIME 62 /* Timer expired */ +#define LUSTRE_ENOSR 63 /* Out of streams resources */ +#define LUSTRE_ENONET 64 /* Machine is not on the network */ +#define LUSTRE_ENOPKG 65 /* Package not installed */ +#define LUSTRE_EREMOTE 66 /* Object is remote */ +#define LUSTRE_ENOLINK 67 /* Link has been severed */ +#define LUSTRE_EADV 68 /* Advertise error */ +#define LUSTRE_ESRMNT 69 /* Srmount error */ +#define LUSTRE_ECOMM 70 /* Communication error on send */ +#define LUSTRE_EPROTO 71 /* Protocol error */ +#define LUSTRE_EMULTIHOP 72 /* Multihop attempted */ +#define LUSTRE_EDOTDOT 73 /* RFS specific error */ +#define LUSTRE_EBADMSG 74 /* Not a data message */ +#define LUSTRE_EOVERFLOW 75 /* Value too large for defined data + type */ +#define LUSTRE_ENOTUNIQ 76 /* Name not unique on network */ +#define LUSTRE_EBADFD 77 /* File descriptor in bad state */ +#define LUSTRE_EREMCHG 78 /* Remote address changed */ +#define LUSTRE_ELIBACC 79 /* Can not access a needed shared + library */ +#define LUSTRE_ELIBBAD 80 /* Accessing a corrupted shared + library */ +#define LUSTRE_ELIBSCN 81 /* .lib section in a.out corrupted */ +#define LUSTRE_ELIBMAX 82 /* Attempting to link in too many shared + libraries */ +#define LUSTRE_ELIBEXEC 83 /* Cannot exec a shared library + directly */ +#define LUSTRE_EILSEQ 84 /* Illegal byte sequence */ +#define LUSTRE_ERESTART 85 /* Interrupted system call should be + restarted */ +#define LUSTRE_ESTRPIPE 86 /* Streams pipe error */ +#define LUSTRE_EUSERS 87 /* Too many users */ +#define LUSTRE_ENOTSOCK 88 /* Socket operation on non-socket */ +#define LUSTRE_EDESTADDRREQ 89 /* Destination address required */ +#define LUSTRE_EMSGSIZE 90 /* Message too long */ +#define LUSTRE_EPROTOTYPE 91 /* Protocol wrong type for socket */ +#define LUSTRE_ENOPROTOOPT 92 /* Protocol not available */ +#define LUSTRE_EPROTONOSUPPORT 93 /* Protocol not supported */ +#define LUSTRE_ESOCKTNOSUPPORT 94 /* Socket type not supported */ +#define LUSTRE_EOPNOTSUPP 95 /* Operation not supported on transport + endpoint */ +#define LUSTRE_EPFNOSUPPORT 96 /* Protocol family not supported */ +#define LUSTRE_EAFNOSUPPORT 97 /* Address family not supported by + protocol */ +#define LUSTRE_EADDRINUSE 98 /* Address already in use */ +#define LUSTRE_EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define LUSTRE_ENETDOWN 100 /* Network is down */ +#define LUSTRE_ENETUNREACH 101 /* Network is unreachable */ +#define LUSTRE_ENETRESET 102 /* Network dropped connection because of + reset */ +#define LUSTRE_ECONNABORTED 103 /* Software caused connection abort */ +#define LUSTRE_ECONNRESET 104 /* Connection reset by peer */ +#define LUSTRE_ENOBUFS 105 /* No buffer space available */ +#define LUSTRE_EISCONN 106 /* Transport endpoint is already + connected */ +#define LUSTRE_ENOTCONN 107 /* Transport endpoint is not + connected */ +#define LUSTRE_ESHUTDOWN 108 /* Cannot send after transport endpoint + shutdown */ +#define LUSTRE_ETOOMANYREFS 109 /* Too many references: cannot splice */ +#define LUSTRE_ETIMEDOUT 110 /* Connection timed out */ +#define LUSTRE_ECONNREFUSED 111 /* Connection refused */ +#define LUSTRE_EHOSTDOWN 112 /* Host is down */ +#define LUSTRE_EHOSTUNREACH 113 /* No route to host */ +#define LUSTRE_EALREADY 114 /* Operation already in progress */ +#define LUSTRE_EINPROGRESS 115 /* Operation now in progress */ +#define LUSTRE_ESTALE 116 /* Stale NFS file handle */ +#define LUSTRE_EUCLEAN 117 /* Structure needs cleaning */ +#define LUSTRE_ENOTNAM 118 /* Not a XENIX named type file */ +#define LUSTRE_ENAVAIL 119 /* No XENIX semaphores available */ +#define LUSTRE_EISNAM 120 /* Is a named type file */ +#define LUSTRE_EREMOTEIO 121 /* Remote I/O error */ +#define LUSTRE_EDQUOT 122 /* Quota exceeded */ +#define LUSTRE_ENOMEDIUM 123 /* No medium found */ +#define LUSTRE_EMEDIUMTYPE 124 /* Wrong medium type */ +#define LUSTRE_ECANCELED 125 /* Operation Canceled */ +#define LUSTRE_ENOKEY 126 /* Required key not available */ +#define LUSTRE_EKEYEXPIRED 127 /* Key has expired */ +#define LUSTRE_EKEYREVOKED 128 /* Key has been revoked */ +#define LUSTRE_EKEYREJECTED 129 /* Key was rejected by service */ +#define LUSTRE_EOWNERDEAD 130 /* Owner died */ +#define LUSTRE_ENOTRECOVERABLE 131 /* State not recoverable */ +#define LUSTRE_ERESTARTSYS 512 +#define LUSTRE_ERESTARTNOINTR 513 +#define LUSTRE_ERESTARTNOHAND 514 /* restart if no handler.. */ +#define LUSTRE_ENOIOCTLCMD 515 /* No ioctl command */ +#define LUSTRE_ERESTART_RESTARTBLOCK 516 /* restart by calling + sys_restart_syscall */ +#define LUSTRE_EBADHANDLE 521 /* Illegal NFS file handle */ +#define LUSTRE_ENOTSYNC 522 /* Update synchronization mismatch */ +#define LUSTRE_EBADCOOKIE 523 /* Cookie is stale */ +#define LUSTRE_ENOTSUPP 524 /* Operation is not supported */ +#define LUSTRE_ETOOSMALL 525 /* Buffer or request is too small */ +#define LUSTRE_ESERVERFAULT 526 /* An untranslatable error occurred */ +#define LUSTRE_EBADTYPE 527 /* Type not supported by server */ +#define LUSTRE_EJUKEBOX 528 /* Request initiated, but will not + complete before timeout */ +#define LUSTRE_EIOCBQUEUED 529 /* iocb queued, will get completion + event */ +#define LUSTRE_EIOCBRETRY 530 /* iocb queued, will trigger a retry */ + +/* + * Translations are optimized away on x86. Host errnos that shouldn't be put + * on wire could leak through as a result. Do not count on this side effect. + */ +#ifdef CONFIG_LUSTRE_TRANSLATE_ERRNOS +unsigned int lustre_errno_hton(unsigned int h); +unsigned int lustre_errno_ntoh(unsigned int n); +#else +#define lustre_errno_hton(h) (h) +#define lustre_errno_ntoh(n) (n) +#endif + +#endif /* LUSTRE_ERRNO_H */ diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 1cfebfea7b77..4829419a75d3 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -98,6 +98,8 @@ /* Defn's shared with user-space. */ #include +#include + /* * GENERAL STUFF */ diff --git a/drivers/staging/lustre/lustre/include/lustre_net.h b/drivers/staging/lustre/lustre/include/lustre_net.h index 1b99b5d2b4f1..8d7cc7ab0039 100644 --- a/drivers/staging/lustre/lustre/include/lustre_net.h +++ b/drivers/staging/lustre/lustre/include/lustre_net.h @@ -3166,6 +3166,38 @@ lustre_shrink_reply(struct ptlrpc_request *req, int segment, req->rq_replen = lustre_shrink_msg(req->rq_repmsg, segment, newlen, move_data); } + +#ifdef CONFIG_LUSTRE_TRANSLATE_ERRNOS + +static inline int ptlrpc_status_hton(int h) +{ + /* + * Positive errnos must be network errnos, such as LUSTRE_EDEADLK, + * ELDLM_LOCK_ABORTED, etc. + */ + if (h < 0) + return -lustre_errno_hton(-h); + else + return h; +} + +static inline int ptlrpc_status_ntoh(int n) +{ + /* + * See the comment in ptlrpc_status_hton(). + */ + if (n < 0) + return -lustre_errno_ntoh(-n); + else + return n; +} + +#else + +#define ptlrpc_status_hton(h) (h) +#define ptlrpc_status_ntoh(n) (n) + +#endif /** @} */ /** Change request phase of \a req to \a new_phase */ diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c index 93badf5c2957..0b3ea88ae5b0 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c @@ -2208,7 +2208,8 @@ struct ldlm_resource *ldlm_lock_convert(struct ldlm_lock *lock, int new_mode, /* I can't check the type of lock here because the bitlock of lock * is not held here, so do the allocation blindly. -jay */ OBD_SLAB_ALLOC_PTR_GFP(node, ldlm_interval_slab, __GFP_IO); - if (node == NULL) /* Actually, this causes EDEADLOCK to be returned */ + if (node == NULL) + /* Actually, this causes EDEADLOCK to be returned */ RETURN(NULL); LASSERTF((new_mode == LCK_PW && lock->l_granted_mode == LCK_PR), diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c index 324d5e4286dc..f79b244d1a68 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c @@ -555,6 +555,8 @@ static int ldlm_handle_qc_callback(struct ptlrpc_request *req) RETURN(-EPROTO); } + oqctl->qc_stat = ptlrpc_status_ntoh(oqctl->qc_stat); + cli->cl_qchk_stat = oqctl->qc_stat; return 0; } diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c index 1a690edaba03..ab41fea4aa07 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c @@ -1023,7 +1023,7 @@ static int ldlm_cli_convert_local(struct ldlm_lock *lock, int new_mode, ldlm_reprocess_all(res); rc = 0; } else { - rc = EDEADLOCK; + rc = LUSTRE_EDEADLK; } LDLM_DEBUG(lock, "client-side local convert handler END"); LDLM_LOCK_PUT(lock); @@ -1095,7 +1095,7 @@ int ldlm_cli_convert(struct lustre_handle *lockh, int new_mode, __u32 *flags) GOTO(out, rc); } } else { - rc = EDEADLOCK; + rc = LUSTRE_EDEADLK; } EXIT; out: @@ -1248,7 +1248,7 @@ int ldlm_cli_cancel_req(struct obd_export *exp, struct list_head *cancels, } else { rc = ptlrpc_queue_wait(req); } - if (rc == ESTALE) { + if (rc == LUSTRE_ESTALE) { CDEBUG(D_DLMTRACE, "client/server (nid %s) " "out of sync -- not fatal\n", libcfs_nid2str(req->rq_import-> diff --git a/drivers/staging/lustre/lustre/mdc/mdc_locks.c b/drivers/staging/lustre/lustre/mdc/mdc_locks.c index 1cc90b635fb5..bae2d67e7fa4 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_locks.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_locks.c @@ -840,6 +840,9 @@ resend: lockrep = req_capsule_server_get(&req->rq_pill, &RMF_DLM_REP); LASSERT(lockrep != NULL); + lockrep->lock_policy_res2 = + ptlrpc_status_ntoh(lockrep->lock_policy_res2); + /* Retry the create infinitely when we get -EINPROGRESS from * server. This is required by the new quota design. */ if (it && it->it_op & IT_CREAT && @@ -1139,6 +1142,7 @@ static int mdc_intent_getattr_async_interpret(const struct lu_env *env, struct lookup_intent *it; struct lustre_handle *lockh; struct obd_device *obddev; + struct ldlm_reply *lockrep; __u64 flags = LDLM_FL_HAS_INTENT; ENTRY; @@ -1159,6 +1163,12 @@ static int mdc_intent_getattr_async_interpret(const struct lu_env *env, GOTO(out, rc); } + lockrep = req_capsule_server_get(&req->rq_pill, &RMF_DLM_REP); + LASSERT(lockrep != NULL); + + lockrep->lock_policy_res2 = + ptlrpc_status_ntoh(lockrep->lock_policy_res2); + rc = mdc_finish_enqueue(exp, req, einfo, it, lockh, rc); if (rc) GOTO(out, rc); diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 21e8a9d16130..b8bf2dcee09f 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -1189,6 +1189,7 @@ static int mdc_ioc_hsm_progress(struct obd_export *exp, GOTO(out, rc = -EPROTO); *req_hpk = *hpk; + req_hpk->hpk_errval = lustre_errno_hton(hpk->hpk_errval); ptlrpc_request_set_replen(req); diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 53d6a35c80b9..0c0e07b6f18e 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -2347,6 +2347,8 @@ static int osc_enqueue_fini(struct ptlrpc_request *req, struct ost_lvb *lvb, &RMF_DLM_REP); LASSERT(rep != NULL); + rep->lock_policy_res1 = + ptlrpc_status_ntoh(rep->lock_policy_res1); if (rep->lock_policy_res1) rc = rep->lock_policy_res1; } diff --git a/drivers/staging/lustre/lustre/ptlrpc/Makefile b/drivers/staging/lustre/lustre/ptlrpc/Makefile index 983eb66a554d..a379558bc687 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/Makefile +++ b/drivers/staging/lustre/lustre/ptlrpc/Makefile @@ -16,6 +16,7 @@ ptlrpc_objs += sec.o sec_bulk.o sec_gc.o sec_config.o sec_lproc.o ptlrpc_objs += sec_null.o sec_plain.o nrs.o nrs_fifo.o ptlrpc-y := $(ldlm_objs) $(ptlrpc_objs) +ptlrpc-$(CONFIG_LUSTRE_TRANSLATE_ERRNOS) += errno.c obj-$(CONFIG_PTLRPC_GSS) += gss/ diff --git a/drivers/staging/lustre/lustre/ptlrpc/errno.c b/drivers/staging/lustre/lustre/ptlrpc/errno.c new file mode 100644 index 000000000000..46e259e4098b --- /dev/null +++ b/drivers/staging/lustre/lustre/ptlrpc/errno.c @@ -0,0 +1,382 @@ +/* + * GPL HEADER START + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * 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 version 2 for more details (a copy is included + * in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see + * http://www.gnu.org/licenses/gpl-2.0.txt + * + * GPL HEADER END + */ +/* + * Copyright (C) 2011 FUJITSU LIMITED. All rights reserved. + * + * Copyright (c) 2013, Intel Corporation. + */ + +#include +#include + +/* + * The two translation tables below must define a one-to-one mapping between + * host and network errnos. + * + * EWOULDBLOCK is equal to EAGAIN on all architectures except for parisc, which + * appears irrelevant. Thus, existing references to EWOULDBLOCK are fine. + * + * EDEADLOCK is equal to EDEADLK on x86 but not on sparc, at least. A sparc + * host has no context-free way to determine if a LUSTRE_EDEADLK represents an + * EDEADLK or an EDEADLOCK. Therefore, all existing references to EDEADLOCK + * that need to be transferred on wire have been replaced with EDEADLK. + */ +static int lustre_errno_hton_mapping[] = { + [EPERM] = LUSTRE_EPERM, + [ENOENT] = LUSTRE_ENOENT, + [ESRCH] = LUSTRE_ESRCH, + [EINTR] = LUSTRE_EINTR, + [EIO] = LUSTRE_EIO, + [ENXIO] = LUSTRE_ENXIO, + [E2BIG] = LUSTRE_E2BIG, + [ENOEXEC] = LUSTRE_ENOEXEC, + [EBADF] = LUSTRE_EBADF, + [ECHILD] = LUSTRE_ECHILD, + [EAGAIN] = LUSTRE_EAGAIN, + [ENOMEM] = LUSTRE_ENOMEM, + [EACCES] = LUSTRE_EACCES, + [EFAULT] = LUSTRE_EFAULT, + [ENOTBLK] = LUSTRE_ENOTBLK, + [EBUSY] = LUSTRE_EBUSY, + [EEXIST] = LUSTRE_EEXIST, + [EXDEV] = LUSTRE_EXDEV, + [ENODEV] = LUSTRE_ENODEV, + [ENOTDIR] = LUSTRE_ENOTDIR, + [EISDIR] = LUSTRE_EISDIR, + [EINVAL] = LUSTRE_EINVAL, + [ENFILE] = LUSTRE_ENFILE, + [EMFILE] = LUSTRE_EMFILE, + [ENOTTY] = LUSTRE_ENOTTY, + [ETXTBSY] = LUSTRE_ETXTBSY, + [EFBIG] = LUSTRE_EFBIG, + [ENOSPC] = LUSTRE_ENOSPC, + [ESPIPE] = LUSTRE_ESPIPE, + [EROFS] = LUSTRE_EROFS, + [EMLINK] = LUSTRE_EMLINK, + [EPIPE] = LUSTRE_EPIPE, + [EDOM] = LUSTRE_EDOM, + [ERANGE] = LUSTRE_ERANGE, + [EDEADLK] = LUSTRE_EDEADLK, + [ENAMETOOLONG] = LUSTRE_ENAMETOOLONG, + [ENOLCK] = LUSTRE_ENOLCK, + [ENOSYS] = LUSTRE_ENOSYS, + [ENOTEMPTY] = LUSTRE_ENOTEMPTY, + [ELOOP] = LUSTRE_ELOOP, + [ENOMSG] = LUSTRE_ENOMSG, + [EIDRM] = LUSTRE_EIDRM, + [ECHRNG] = LUSTRE_ECHRNG, + [EL2NSYNC] = LUSTRE_EL2NSYNC, + [EL3HLT] = LUSTRE_EL3HLT, + [EL3RST] = LUSTRE_EL3RST, + [ELNRNG] = LUSTRE_ELNRNG, + [EUNATCH] = LUSTRE_EUNATCH, + [ENOCSI] = LUSTRE_ENOCSI, + [EL2HLT] = LUSTRE_EL2HLT, + [EBADE] = LUSTRE_EBADE, + [EBADR] = LUSTRE_EBADR, + [EXFULL] = LUSTRE_EXFULL, + [ENOANO] = LUSTRE_ENOANO, + [EBADRQC] = LUSTRE_EBADRQC, + [EBADSLT] = LUSTRE_EBADSLT, + [EBFONT] = LUSTRE_EBFONT, + [ENOSTR] = LUSTRE_ENOSTR, + [ENODATA] = LUSTRE_ENODATA, + [ETIME] = LUSTRE_ETIME, + [ENOSR] = LUSTRE_ENOSR, + [ENONET] = LUSTRE_ENONET, + [ENOPKG] = LUSTRE_ENOPKG, + [EREMOTE] = LUSTRE_EREMOTE, + [ENOLINK] = LUSTRE_ENOLINK, + [EADV] = LUSTRE_EADV, + [ESRMNT] = LUSTRE_ESRMNT, + [ECOMM] = LUSTRE_ECOMM, + [EPROTO] = LUSTRE_EPROTO, + [EMULTIHOP] = LUSTRE_EMULTIHOP, + [EDOTDOT] = LUSTRE_EDOTDOT, + [EBADMSG] = LUSTRE_EBADMSG, + [EOVERFLOW] = LUSTRE_EOVERFLOW, + [ENOTUNIQ] = LUSTRE_ENOTUNIQ, + [EBADFD] = LUSTRE_EBADFD, + [EREMCHG] = LUSTRE_EREMCHG, + [ELIBACC] = LUSTRE_ELIBACC, + [ELIBBAD] = LUSTRE_ELIBBAD, + [ELIBSCN] = LUSTRE_ELIBSCN, + [ELIBMAX] = LUSTRE_ELIBMAX, + [ELIBEXEC] = LUSTRE_ELIBEXEC, + [EILSEQ] = LUSTRE_EILSEQ, + [ERESTART] = LUSTRE_ERESTART, + [ESTRPIPE] = LUSTRE_ESTRPIPE, + [EUSERS] = LUSTRE_EUSERS, + [ENOTSOCK] = LUSTRE_ENOTSOCK, + [EDESTADDRREQ] = LUSTRE_EDESTADDRREQ, + [EMSGSIZE] = LUSTRE_EMSGSIZE, + [EPROTOTYPE] = LUSTRE_EPROTOTYPE, + [ENOPROTOOPT] = LUSTRE_ENOPROTOOPT, + [EPROTONOSUPPORT] = LUSTRE_EPROTONOSUPPORT, + [ESOCKTNOSUPPORT] = LUSTRE_ESOCKTNOSUPPORT, + [EOPNOTSUPP] = LUSTRE_EOPNOTSUPP, + [EPFNOSUPPORT] = LUSTRE_EPFNOSUPPORT, + [EAFNOSUPPORT] = LUSTRE_EAFNOSUPPORT, + [EADDRINUSE] = LUSTRE_EADDRINUSE, + [EADDRNOTAVAIL] = LUSTRE_EADDRNOTAVAIL, + [ENETDOWN] = LUSTRE_ENETDOWN, + [ENETUNREACH] = LUSTRE_ENETUNREACH, + [ENETRESET] = LUSTRE_ENETRESET, + [ECONNABORTED] = LUSTRE_ECONNABORTED, + [ECONNRESET] = LUSTRE_ECONNRESET, + [ENOBUFS] = LUSTRE_ENOBUFS, + [EISCONN] = LUSTRE_EISCONN, + [ENOTCONN] = LUSTRE_ENOTCONN, + [ESHUTDOWN] = LUSTRE_ESHUTDOWN, + [ETOOMANYREFS] = LUSTRE_ETOOMANYREFS, + [ETIMEDOUT] = LUSTRE_ETIMEDOUT, + [ECONNREFUSED] = LUSTRE_ECONNREFUSED, + [EHOSTDOWN] = LUSTRE_EHOSTDOWN, + [EHOSTUNREACH] = LUSTRE_EHOSTUNREACH, + [EALREADY] = LUSTRE_EALREADY, + [EINPROGRESS] = LUSTRE_EINPROGRESS, + [ESTALE] = LUSTRE_ESTALE, + [EUCLEAN] = LUSTRE_EUCLEAN, + [ENOTNAM] = LUSTRE_ENOTNAM, + [ENAVAIL] = LUSTRE_ENAVAIL, + [EISNAM] = LUSTRE_EISNAM, + [EREMOTEIO] = LUSTRE_EREMOTEIO, + [EDQUOT] = LUSTRE_EDQUOT, + [ENOMEDIUM] = LUSTRE_ENOMEDIUM, + [EMEDIUMTYPE] = LUSTRE_EMEDIUMTYPE, + [ECANCELED] = LUSTRE_ECANCELED, + [ENOKEY] = LUSTRE_ENOKEY, + [EKEYEXPIRED] = LUSTRE_EKEYEXPIRED, + [EKEYREVOKED] = LUSTRE_EKEYREVOKED, + [EKEYREJECTED] = LUSTRE_EKEYREJECTED, + [EOWNERDEAD] = LUSTRE_EOWNERDEAD, + [ENOTRECOVERABLE] = LUSTRE_ENOTRECOVERABLE, + [ERESTARTSYS] = LUSTRE_ERESTARTSYS, + [ERESTARTNOINTR] = LUSTRE_ERESTARTNOINTR, + [ERESTARTNOHAND] = LUSTRE_ERESTARTNOHAND, + [ENOIOCTLCMD] = LUSTRE_ENOIOCTLCMD, + [ERESTART_RESTARTBLOCK] = LUSTRE_ERESTART_RESTARTBLOCK, + [EBADHANDLE] = LUSTRE_EBADHANDLE, + [ENOTSYNC] = LUSTRE_ENOTSYNC, + [EBADCOOKIE] = LUSTRE_EBADCOOKIE, + [ENOTSUPP] = LUSTRE_ENOTSUPP, + [ETOOSMALL] = LUSTRE_ETOOSMALL, + [ESERVERFAULT] = LUSTRE_ESERVERFAULT, + [EBADTYPE] = LUSTRE_EBADTYPE, + [EJUKEBOX] = LUSTRE_EJUKEBOX, + [EIOCBQUEUED] = LUSTRE_EIOCBQUEUED, + [EIOCBRETRY] = LUSTRE_EIOCBRETRY +}; + +static int lustre_errno_ntoh_mapping[] = { + [LUSTRE_EPERM] = EPERM, + [LUSTRE_ENOENT] = ENOENT, + [LUSTRE_ESRCH] = ESRCH, + [LUSTRE_EINTR] = EINTR, + [LUSTRE_EIO] = EIO, + [LUSTRE_ENXIO] = ENXIO, + [LUSTRE_E2BIG] = E2BIG, + [LUSTRE_ENOEXEC] = ENOEXEC, + [LUSTRE_EBADF] = EBADF, + [LUSTRE_ECHILD] = ECHILD, + [LUSTRE_EAGAIN] = EAGAIN, + [LUSTRE_ENOMEM] = ENOMEM, + [LUSTRE_EACCES] = EACCES, + [LUSTRE_EFAULT] = EFAULT, + [LUSTRE_ENOTBLK] = ENOTBLK, + [LUSTRE_EBUSY] = EBUSY, + [LUSTRE_EEXIST] = EEXIST, + [LUSTRE_EXDEV] = EXDEV, + [LUSTRE_ENODEV] = ENODEV, + [LUSTRE_ENOTDIR] = ENOTDIR, + [LUSTRE_EISDIR] = EISDIR, + [LUSTRE_EINVAL] = EINVAL, + [LUSTRE_ENFILE] = ENFILE, + [LUSTRE_EMFILE] = EMFILE, + [LUSTRE_ENOTTY] = ENOTTY, + [LUSTRE_ETXTBSY] = ETXTBSY, + [LUSTRE_EFBIG] = EFBIG, + [LUSTRE_ENOSPC] = ENOSPC, + [LUSTRE_ESPIPE] = ESPIPE, + [LUSTRE_EROFS] = EROFS, + [LUSTRE_EMLINK] = EMLINK, + [LUSTRE_EPIPE] = EPIPE, + [LUSTRE_EDOM] = EDOM, + [LUSTRE_ERANGE] = ERANGE, + [LUSTRE_EDEADLK] = EDEADLK, + [LUSTRE_ENAMETOOLONG] = ENAMETOOLONG, + [LUSTRE_ENOLCK] = ENOLCK, + [LUSTRE_ENOSYS] = ENOSYS, + [LUSTRE_ENOTEMPTY] = ENOTEMPTY, + [LUSTRE_ELOOP] = ELOOP, + [LUSTRE_ENOMSG] = ENOMSG, + [LUSTRE_EIDRM] = EIDRM, + [LUSTRE_ECHRNG] = ECHRNG, + [LUSTRE_EL2NSYNC] = EL2NSYNC, + [LUSTRE_EL3HLT] = EL3HLT, + [LUSTRE_EL3RST] = EL3RST, + [LUSTRE_ELNRNG] = ELNRNG, + [LUSTRE_EUNATCH] = EUNATCH, + [LUSTRE_ENOCSI] = ENOCSI, + [LUSTRE_EL2HLT] = EL2HLT, + [LUSTRE_EBADE] = EBADE, + [LUSTRE_EBADR] = EBADR, + [LUSTRE_EXFULL] = EXFULL, + [LUSTRE_ENOANO] = ENOANO, + [LUSTRE_EBADRQC] = EBADRQC, + [LUSTRE_EBADSLT] = EBADSLT, + [LUSTRE_EBFONT] = EBFONT, + [LUSTRE_ENOSTR] = ENOSTR, + [LUSTRE_ENODATA] = ENODATA, + [LUSTRE_ETIME] = ETIME, + [LUSTRE_ENOSR] = ENOSR, + [LUSTRE_ENONET] = ENONET, + [LUSTRE_ENOPKG] = ENOPKG, + [LUSTRE_EREMOTE] = EREMOTE, + [LUSTRE_ENOLINK] = ENOLINK, + [LUSTRE_EADV] = EADV, + [LUSTRE_ESRMNT] = ESRMNT, + [LUSTRE_ECOMM] = ECOMM, + [LUSTRE_EPROTO] = EPROTO, + [LUSTRE_EMULTIHOP] = EMULTIHOP, + [LUSTRE_EDOTDOT] = EDOTDOT, + [LUSTRE_EBADMSG] = EBADMSG, + [LUSTRE_EOVERFLOW] = EOVERFLOW, + [LUSTRE_ENOTUNIQ] = ENOTUNIQ, + [LUSTRE_EBADFD] = EBADFD, + [LUSTRE_EREMCHG] = EREMCHG, + [LUSTRE_ELIBACC] = ELIBACC, + [LUSTRE_ELIBBAD] = ELIBBAD, + [LUSTRE_ELIBSCN] = ELIBSCN, + [LUSTRE_ELIBMAX] = ELIBMAX, + [LUSTRE_ELIBEXEC] = ELIBEXEC, + [LUSTRE_EILSEQ] = EILSEQ, + [LUSTRE_ERESTART] = ERESTART, + [LUSTRE_ESTRPIPE] = ESTRPIPE, + [LUSTRE_EUSERS] = EUSERS, + [LUSTRE_ENOTSOCK] = ENOTSOCK, + [LUSTRE_EDESTADDRREQ] = EDESTADDRREQ, + [LUSTRE_EMSGSIZE] = EMSGSIZE, + [LUSTRE_EPROTOTYPE] = EPROTOTYPE, + [LUSTRE_ENOPROTOOPT] = ENOPROTOOPT, + [LUSTRE_EPROTONOSUPPORT] = EPROTONOSUPPORT, + [LUSTRE_ESOCKTNOSUPPORT] = ESOCKTNOSUPPORT, + [LUSTRE_EOPNOTSUPP] = EOPNOTSUPP, + [LUSTRE_EPFNOSUPPORT] = EPFNOSUPPORT, + [LUSTRE_EAFNOSUPPORT] = EAFNOSUPPORT, + [LUSTRE_EADDRINUSE] = EADDRINUSE, + [LUSTRE_EADDRNOTAVAIL] = EADDRNOTAVAIL, + [LUSTRE_ENETDOWN] = ENETDOWN, + [LUSTRE_ENETUNREACH] = ENETUNREACH, + [LUSTRE_ENETRESET] = ENETRESET, + [LUSTRE_ECONNABORTED] = ECONNABORTED, + [LUSTRE_ECONNRESET] = ECONNRESET, + [LUSTRE_ENOBUFS] = ENOBUFS, + [LUSTRE_EISCONN] = EISCONN, + [LUSTRE_ENOTCONN] = ENOTCONN, + [LUSTRE_ESHUTDOWN] = ESHUTDOWN, + [LUSTRE_ETOOMANYREFS] = ETOOMANYREFS, + [LUSTRE_ETIMEDOUT] = ETIMEDOUT, + [LUSTRE_ECONNREFUSED] = ECONNREFUSED, + [LUSTRE_EHOSTDOWN] = EHOSTDOWN, + [LUSTRE_EHOSTUNREACH] = EHOSTUNREACH, + [LUSTRE_EALREADY] = EALREADY, + [LUSTRE_EINPROGRESS] = EINPROGRESS, + [LUSTRE_ESTALE] = ESTALE, + [LUSTRE_EUCLEAN] = EUCLEAN, + [LUSTRE_ENOTNAM] = ENOTNAM, + [LUSTRE_ENAVAIL] = ENAVAIL, + [LUSTRE_EISNAM] = EISNAM, + [LUSTRE_EREMOTEIO] = EREMOTEIO, + [LUSTRE_EDQUOT] = EDQUOT, + [LUSTRE_ENOMEDIUM] = ENOMEDIUM, + [LUSTRE_EMEDIUMTYPE] = EMEDIUMTYPE, + [LUSTRE_ECANCELED] = ECANCELED, + [LUSTRE_ENOKEY] = ENOKEY, + [LUSTRE_EKEYEXPIRED] = EKEYEXPIRED, + [LUSTRE_EKEYREVOKED] = EKEYREVOKED, + [LUSTRE_EKEYREJECTED] = EKEYREJECTED, + [LUSTRE_EOWNERDEAD] = EOWNERDEAD, + [LUSTRE_ENOTRECOVERABLE] = ENOTRECOVERABLE, + [LUSTRE_ERESTARTSYS] = ERESTARTSYS, + [LUSTRE_ERESTARTNOINTR] = ERESTARTNOINTR, + [LUSTRE_ERESTARTNOHAND] = ERESTARTNOHAND, + [LUSTRE_ENOIOCTLCMD] = ENOIOCTLCMD, + [LUSTRE_ERESTART_RESTARTBLOCK] = ERESTART_RESTARTBLOCK, + [LUSTRE_EBADHANDLE] = EBADHANDLE, + [LUSTRE_ENOTSYNC] = ENOTSYNC, + [LUSTRE_EBADCOOKIE] = EBADCOOKIE, + [LUSTRE_ENOTSUPP] = ENOTSUPP, + [LUSTRE_ETOOSMALL] = ETOOSMALL, + [LUSTRE_ESERVERFAULT] = ESERVERFAULT, + [LUSTRE_EBADTYPE] = EBADTYPE, + [LUSTRE_EJUKEBOX] = EJUKEBOX, + [LUSTRE_EIOCBQUEUED] = EIOCBQUEUED, + [LUSTRE_EIOCBRETRY] = EIOCBRETRY +}; + +unsigned int lustre_errno_hton(unsigned int h) +{ + unsigned int n; + + if (h == 0) { + n = 0; + } else if (h < ARRAY_SIZE(lustre_errno_hton_mapping)) { + n = lustre_errno_hton_mapping[h]; + if (n == 0) + goto generic; + } else { +generic: + /* + * A generic errno is better than the unknown one that could + * mean anything to a different host. + */ + n = LUSTRE_EIO; + } + + return n; +} +EXPORT_SYMBOL(lustre_errno_hton); + +unsigned int lustre_errno_ntoh(unsigned int n) +{ + unsigned int h; + + if (n == 0) { + h = 0; + } else if (n < ARRAY_SIZE(lustre_errno_ntoh_mapping)) { + h = lustre_errno_ntoh_mapping[n]; + if (h == 0) + goto generic; + } else { +generic: + /* + * Similar to the situation in lustre_errno_hton(), an unknown + * network errno could coincide with anything. Hence, it is + * better to return a generic errno. + */ + h = EIO; + } + + return h; +} +EXPORT_SYMBOL(lustre_errno_ntoh); diff --git a/drivers/staging/lustre/lustre/ptlrpc/niobuf.c b/drivers/staging/lustre/lustre/ptlrpc/niobuf.c index de3f0db0ba47..5f1b889e5277 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/niobuf.c +++ b/drivers/staging/lustre/lustre/ptlrpc/niobuf.c @@ -400,7 +400,8 @@ int ptlrpc_send_reply(struct ptlrpc_request *req, int flags) req->rq_type = PTL_RPC_MSG_REPLY; lustre_msg_set_type(req->rq_repmsg, req->rq_type); - lustre_msg_set_status(req->rq_repmsg, req->rq_status); + lustre_msg_set_status(req->rq_repmsg, + ptlrpc_status_hton(req->rq_status)); lustre_msg_set_opc(req->rq_repmsg, req->rq_reqmsg ? lustre_msg_get_opc(req->rq_reqmsg) : 0); diff --git a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c index 1437636dfe28..be246d491886 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c @@ -642,6 +642,9 @@ static inline int lustre_unpack_ptlrpc_body_v2(struct ptlrpc_request *req, return -EINVAL; } + if (!inout) + pb->pb_status = ptlrpc_status_ntoh(pb->pb_status); + return 0; } From bdf43213f9e7faf980025f44ec82b80caf453e8d Mon Sep 17 00:00:00 2001 From: jcl Date: Tue, 23 Jul 2013 00:06:33 +0800 Subject: [PATCH 0324/3400] staging/lustre/mdc: layout lock rpc must not take rpc_lock When a client issue an RPC to get a layout lock, it must not hold rpc_lock because in case of a restore the rpc can be blocking for a long time Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3200 Lustre-change: http://review.whamcloud.com/6115 Signed-off-by: JC Lafoucriere Reviewed-by: Jinshan Xiong Reviewed-by: Johann Lombardi Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lustre_mdc.h | 6 ++++-- drivers/staging/lustre/lustre/mdc/mdc_locks.c | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/lustre_mdc.h b/drivers/staging/lustre/lustre/include/lustre_mdc.h index fb1561a809b9..82d1f2f13031 100644 --- a/drivers/staging/lustre/lustre/include/lustre_mdc.h +++ b/drivers/staging/lustre/lustre/include/lustre_mdc.h @@ -86,7 +86,8 @@ static inline void mdc_get_rpc_lock(struct mdc_rpc_lock *lck, { ENTRY; - if (it != NULL && (it->it_op == IT_GETATTR || it->it_op == IT_LOOKUP)) + if (it != NULL && (it->it_op == IT_GETATTR || it->it_op == IT_LOOKUP || + it->it_op == IT_LAYOUT)) return; /* This would normally block until the existing request finishes. @@ -123,7 +124,8 @@ static inline void mdc_get_rpc_lock(struct mdc_rpc_lock *lck, static inline void mdc_put_rpc_lock(struct mdc_rpc_lock *lck, struct lookup_intent *it) { - if (it != NULL && (it->it_op == IT_GETATTR || it->it_op == IT_LOOKUP)) + if (it != NULL && (it->it_op == IT_GETATTR || it->it_op == IT_LOOKUP || + it->it_op == IT_LAYOUT)) goto out; if (lck->rpcl_it == MDC_FAKE_RPCL_IT) { /* OBD_FAIL_MDC_RPCS_SEM */ diff --git a/drivers/staging/lustre/lustre/mdc/mdc_locks.c b/drivers/staging/lustre/lustre/mdc/mdc_locks.c index bae2d67e7fa4..9532134e16c6 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_locks.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_locks.c @@ -884,7 +884,7 @@ static int mdc_finish_intent_lock(struct obd_export *exp, struct mdt_body *mdt_body; struct ldlm_lock *lock; int rc; - + ENTRY; LASSERT(request != NULL); LASSERT(request != LP_POISON); From 91a50030f05ebf5f96e9091514b5f2858fcead50 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Tue, 23 Jul 2013 00:06:34 +0800 Subject: [PATCH 0325/3400] staging/lustre/ldlm: split client namespaces into active and inactive The main reason behind this is ldlm_poold walks all namespaces currently no matter if there are any locks or not. On large systems this could take quite a bit of time, esp. since ldlm_poold is currently woken up once per second. Now every time a client namespace loses it's last resource it is placed into an inactive list that is not touched by ldlm_poold as pointless. On creation of a first resource in a namespace it is placed back into the active list. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2924 Lustre-change: http://review.whamcloud.com/5624 Signed-off-by: Oleg Drokin Reviewed-by: Hiroya Nozaki Reviewed-by: Niu Yawei Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../lustre/lustre/include/lustre_dlm.h | 2 - .../lustre/lustre/ldlm/ldlm_internal.h | 46 +++++++++++++-- .../staging/lustre/lustre/ldlm/ldlm_pool.c | 59 +++++++++++++++---- .../lustre/lustre/ldlm/ldlm_resource.c | 55 ++++++++++++++--- 4 files changed, 135 insertions(+), 27 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/lustre_dlm.h b/drivers/staging/lustre/lustre/include/lustre_dlm.h index 317f928fc151..48cb6f89cb0a 100644 --- a/drivers/staging/lustre/lustre/include/lustre_dlm.h +++ b/drivers/staging/lustre/lustre/include/lustre_dlm.h @@ -1471,8 +1471,6 @@ void ldlm_namespace_free(struct ldlm_namespace *ns, struct obd_import *imp, int force); void ldlm_namespace_register(struct ldlm_namespace *ns, ldlm_side_t client); void ldlm_namespace_unregister(struct ldlm_namespace *ns, ldlm_side_t client); -void ldlm_namespace_move_locked(struct ldlm_namespace *ns, ldlm_side_t client); -struct ldlm_namespace *ldlm_namespace_first_locked(ldlm_side_t client); void ldlm_namespace_get(struct ldlm_namespace *ns); void ldlm_namespace_put(struct ldlm_namespace *ns); int ldlm_proc_setup(void); diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h b/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h index 141a957462f1..785c1a19da57 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h @@ -36,23 +36,46 @@ #define MAX_STRING_SIZE 128 -extern atomic_t ldlm_srv_namespace_nr; -extern atomic_t ldlm_cli_namespace_nr; +extern int ldlm_srv_namespace_nr; +extern int ldlm_cli_namespace_nr; extern struct mutex ldlm_srv_namespace_lock; extern struct list_head ldlm_srv_namespace_list; extern struct mutex ldlm_cli_namespace_lock; -extern struct list_head ldlm_cli_namespace_list; +extern struct list_head ldlm_cli_active_namespace_list; +extern struct list_head ldlm_cli_inactive_namespace_list; -static inline atomic_t *ldlm_namespace_nr(ldlm_side_t client) +static inline int ldlm_namespace_nr_read(ldlm_side_t client) { return client == LDLM_NAMESPACE_SERVER ? - &ldlm_srv_namespace_nr : &ldlm_cli_namespace_nr; + ldlm_srv_namespace_nr : ldlm_cli_namespace_nr; +} + +static inline void ldlm_namespace_nr_inc(ldlm_side_t client) +{ + if (client == LDLM_NAMESPACE_SERVER) + ldlm_srv_namespace_nr++; + else + ldlm_cli_namespace_nr++; +} + +static inline void ldlm_namespace_nr_dec(ldlm_side_t client) +{ + if (client == LDLM_NAMESPACE_SERVER) + ldlm_srv_namespace_nr--; + else + ldlm_cli_namespace_nr--; } static inline struct list_head *ldlm_namespace_list(ldlm_side_t client) { return client == LDLM_NAMESPACE_SERVER ? - &ldlm_srv_namespace_list : &ldlm_cli_namespace_list; + &ldlm_srv_namespace_list : &ldlm_cli_active_namespace_list; +} + +static inline struct list_head *ldlm_namespace_inactive_list(ldlm_side_t client) +{ + return client == LDLM_NAMESPACE_SERVER ? + &ldlm_srv_namespace_list : &ldlm_cli_inactive_namespace_list; } static inline struct mutex *ldlm_namespace_lock(ldlm_side_t client) @@ -61,6 +84,17 @@ static inline struct mutex *ldlm_namespace_lock(ldlm_side_t client) &ldlm_srv_namespace_lock : &ldlm_cli_namespace_lock; } +/* ns_bref is the number of resources in this namespace with the notable + * exception of quota namespaces which have their empty refcount at 1 */ +static inline int ldlm_ns_empty(struct ldlm_namespace *ns) +{ + return atomic_read(&ns->ns_bref) == 0; +} + +void ldlm_namespace_move_to_active_locked(struct ldlm_namespace *, ldlm_side_t); +void ldlm_namespace_move_to_inactive_locked(struct ldlm_namespace *, ldlm_side_t); +struct ldlm_namespace *ldlm_namespace_first_locked(ldlm_side_t); + /* ldlm_request.c */ /* Cancel lru flag, it indicates we cancel aged locks. */ enum { diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c b/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c index b3b60288e5f5..1e6802fa0a7b 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c @@ -1039,6 +1039,7 @@ static int ldlm_pools_shrink(ldlm_side_t client, int nr, { int total = 0, cached = 0, nr_ns; struct ldlm_namespace *ns; + struct ldlm_namespace *ns_old = NULL; /* loop detection */ void *cookie; if (client == LDLM_NAMESPACE_CLIENT && nr != 0 && @@ -1053,7 +1054,7 @@ static int ldlm_pools_shrink(ldlm_side_t client, int nr, /* * Find out how many resources we may release. */ - for (nr_ns = atomic_read(ldlm_namespace_nr(client)); + for (nr_ns = ldlm_namespace_nr_read(client); nr_ns > 0; nr_ns--) { mutex_lock(ldlm_namespace_lock(client)); @@ -1063,8 +1064,23 @@ static int ldlm_pools_shrink(ldlm_side_t client, int nr, return 0; } ns = ldlm_namespace_first_locked(client); + + if (ns == ns_old) { + mutex_unlock(ldlm_namespace_lock(client)); + break; + } + + if (ldlm_ns_empty(ns)) { + ldlm_namespace_move_to_inactive_locked(ns, client); + mutex_unlock(ldlm_namespace_lock(client)); + continue; + } + + if (ns_old == NULL) + ns_old = ns; + ldlm_namespace_get(ns); - ldlm_namespace_move_locked(ns, client); + ldlm_namespace_move_to_active_locked(ns, client); mutex_unlock(ldlm_namespace_lock(client)); total += ldlm_pool_shrink(&ns->ns_pool, 0, gfp_mask); ldlm_namespace_put(ns); @@ -1078,7 +1094,7 @@ static int ldlm_pools_shrink(ldlm_side_t client, int nr, /* * Shrink at least ldlm_namespace_nr(client) namespaces. */ - for (nr_ns = atomic_read(ldlm_namespace_nr(client)); + for (nr_ns = ldlm_namespace_nr_read(client) - nr_ns; nr_ns > 0; nr_ns--) { int cancel, nr_locks; @@ -1099,7 +1115,7 @@ static int ldlm_pools_shrink(ldlm_side_t client, int nr, } ns = ldlm_namespace_first_locked(client); ldlm_namespace_get(ns); - ldlm_namespace_move_locked(ns, client); + ldlm_namespace_move_to_active_locked(ns, client); mutex_unlock(ldlm_namespace_lock(client)); nr_locks = ldlm_pool_granted(&ns->ns_pool); @@ -1132,6 +1148,7 @@ void ldlm_pools_recalc(ldlm_side_t client) { __u32 nr_l = 0, nr_p = 0, l; struct ldlm_namespace *ns; + struct ldlm_namespace *ns_old = NULL; int nr, equal = 0; /* @@ -1190,16 +1207,14 @@ void ldlm_pools_recalc(ldlm_side_t client) * for _all_ pools. */ l = LDLM_POOL_HOST_L / - atomic_read( - ldlm_namespace_nr(client)); + ldlm_namespace_nr_read(client); } else { /* * All the rest of greedy pools will have * all locks in equal parts. */ l = (LDLM_POOL_HOST_L - nr_l) / - (atomic_read( - ldlm_namespace_nr(client)) - + (ldlm_namespace_nr_read(client) - nr_p); } ldlm_pool_setup(&ns->ns_pool, l); @@ -1210,7 +1225,7 @@ void ldlm_pools_recalc(ldlm_side_t client) /* * Recalc at least ldlm_namespace_nr(client) namespaces. */ - for (nr = atomic_read(ldlm_namespace_nr(client)); nr > 0; nr--) { + for (nr = ldlm_namespace_nr_read(client); nr > 0; nr--) { int skip; /* * Lock the list, get first @ns in the list, getref, move it @@ -1226,6 +1241,30 @@ void ldlm_pools_recalc(ldlm_side_t client) } ns = ldlm_namespace_first_locked(client); + if (ns_old == ns) { /* Full pass complete */ + mutex_unlock(ldlm_namespace_lock(client)); + break; + } + + /* We got an empty namespace, need to move it back to inactive + * list. + * The race with parallel resource creation is fine: + * - If they do namespace_get before our check, we fail the + * check and they move this item to the end of the list anyway + * - If we do the check and then they do namespace_get, then + * we move the namespace to inactive and they will move + * it back to active (synchronised by the lock, so no clash + * there). + */ + if (ldlm_ns_empty(ns)) { + ldlm_namespace_move_to_inactive_locked(ns, client); + mutex_unlock(ldlm_namespace_lock(client)); + continue; + } + + if (ns_old == NULL) + ns_old = ns; + spin_lock(&ns->ns_lock); /* * skip ns which is being freed, and we don't want to increase @@ -1239,7 +1278,7 @@ void ldlm_pools_recalc(ldlm_side_t client) } spin_unlock(&ns->ns_lock); - ldlm_namespace_move_locked(ns, client); + ldlm_namespace_move_to_active_locked(ns, client); mutex_unlock(ldlm_namespace_lock(client)); /* diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c index cb8659f71149..716283859d72 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c @@ -48,14 +48,19 @@ struct kmem_cache *ldlm_resource_slab, *ldlm_lock_slab; -atomic_t ldlm_srv_namespace_nr = ATOMIC_INIT(0); -atomic_t ldlm_cli_namespace_nr = ATOMIC_INIT(0); +int ldlm_srv_namespace_nr = 0; +int ldlm_cli_namespace_nr = 0; struct mutex ldlm_srv_namespace_lock; LIST_HEAD(ldlm_srv_namespace_list); struct mutex ldlm_cli_namespace_lock; -LIST_HEAD(ldlm_cli_namespace_list); +/* Client Namespaces that have active resources in them. + * Once all resources go away, ldlm_poold moves such namespaces to the + * inactive list */ +LIST_HEAD(ldlm_cli_active_namespace_list); +/* Client namespaces that don't have any locks in them */ +LIST_HEAD(ldlm_cli_inactive_namespace_list); proc_dir_entry_t *ldlm_type_proc_dir = NULL; proc_dir_entry_t *ldlm_ns_proc_dir = NULL; @@ -636,7 +641,7 @@ struct ldlm_namespace *ldlm_namespace_new(struct obd_device *obd, char *name, GOTO(out_hash, rc); } - idx = atomic_read(ldlm_namespace_nr(client)); + idx = ldlm_namespace_nr_read(client); rc = ldlm_pool_init(&ns->ns_pool, ns, idx, client); if (rc) { CERROR("Can't initialize lock pool, rc %d\n", rc); @@ -953,6 +958,12 @@ void ldlm_namespace_get(struct ldlm_namespace *ns) } EXPORT_SYMBOL(ldlm_namespace_get); +/* This is only for callers that care about refcount */ +int ldlm_namespace_get_return(struct ldlm_namespace *ns) +{ + return atomic_inc_return(&ns->ns_bref); +} + void ldlm_namespace_put(struct ldlm_namespace *ns) { if (atomic_dec_and_lock(&ns->ns_bref, &ns->ns_lock)) { @@ -967,8 +978,8 @@ void ldlm_namespace_register(struct ldlm_namespace *ns, ldlm_side_t client) { mutex_lock(ldlm_namespace_lock(client)); LASSERT(list_empty(&ns->ns_list_chain)); - list_add(&ns->ns_list_chain, ldlm_namespace_list(client)); - atomic_inc(ldlm_namespace_nr(client)); + list_add(&ns->ns_list_chain, ldlm_namespace_inactive_list(client)); + ldlm_namespace_nr_inc(client); mutex_unlock(ldlm_namespace_lock(client)); } @@ -981,18 +992,29 @@ void ldlm_namespace_unregister(struct ldlm_namespace *ns, ldlm_side_t client) * using list_empty(&ns->ns_list_chain). This is why it is * important to use list_del_init() here. */ list_del_init(&ns->ns_list_chain); - atomic_dec(ldlm_namespace_nr(client)); + ldlm_namespace_nr_dec(client); mutex_unlock(ldlm_namespace_lock(client)); } /** Should be called with ldlm_namespace_lock(client) taken. */ -void ldlm_namespace_move_locked(struct ldlm_namespace *ns, ldlm_side_t client) +void ldlm_namespace_move_to_active_locked(struct ldlm_namespace *ns, + ldlm_side_t client) { LASSERT(!list_empty(&ns->ns_list_chain)); LASSERT(mutex_is_locked(ldlm_namespace_lock(client))); list_move_tail(&ns->ns_list_chain, ldlm_namespace_list(client)); } +/** Should be called with ldlm_namespace_lock(client) taken. */ +void ldlm_namespace_move_to_inactive_locked(struct ldlm_namespace *ns, + ldlm_side_t client) +{ + LASSERT(!list_empty(&ns->ns_list_chain)); + LASSERT(mutex_is_locked(ldlm_namespace_lock(client))); + list_move_tail(&ns->ns_list_chain, + ldlm_namespace_inactive_list(client)); +} + /** Should be called with ldlm_namespace_lock(client) taken. */ struct ldlm_namespace *ldlm_namespace_first_locked(ldlm_side_t client) { @@ -1049,6 +1071,7 @@ ldlm_resource_get(struct ldlm_namespace *ns, struct ldlm_resource *parent, struct ldlm_resource *res; cfs_hash_bd_t bd; __u64 version; + int ns_refcount = 0; LASSERT(ns != NULL); LASSERT(parent == NULL); @@ -1119,7 +1142,7 @@ ldlm_resource_get(struct ldlm_namespace *ns, struct ldlm_resource *parent, /* We won! Let's add the resource. */ cfs_hash_bd_add_locked(ns->ns_rs_hash, &bd, &res->lr_hash); if (cfs_hash_bd_count_get(&bd) == 1) - ldlm_namespace_get(ns); + ns_refcount = ldlm_namespace_get_return(ns); cfs_hash_bd_unlock(ns->ns_rs_hash, &bd, 1); if (ns->ns_lvbo && ns->ns_lvbo->lvbo_init) { @@ -1145,6 +1168,20 @@ ldlm_resource_get(struct ldlm_namespace *ns, struct ldlm_resource *parent, /* We create resource with locked lr_lvb_mutex. */ mutex_unlock(&res->lr_lvb_mutex); + /* Let's see if we happened to be the very first resource in this + * namespace. If so, and this is a client namespace, we need to move + * the namespace into the active namespaces list to be patrolled by + * the ldlm_poold. + * A notable exception, for quota namespaces qsd_lib.c already took a + * namespace reference, so it won't be participating in all of this, + * but I guess that's ok since we have no business cancelling quota + * locks anyway */ + if (ns_is_client(ns) && ns_refcount == 1) { + mutex_lock(ldlm_namespace_lock(LDLM_NAMESPACE_CLIENT)); + ldlm_namespace_move_to_active_locked(ns, LDLM_NAMESPACE_CLIENT); + mutex_unlock(ldlm_namespace_lock(LDLM_NAMESPACE_CLIENT)); + } + return res; } EXPORT_SYMBOL(ldlm_resource_get); From 3eface5946de342cfdf4f345353a35dcfa2cf972 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Tue, 23 Jul 2013 00:06:35 +0800 Subject: [PATCH 0326/3400] staging/lustre: Only wake up ldlm_poold as frequently as the check interval We used to wake up ldlm poold every second, but that's overkill, we should just see how much time is left until next closest recalc interval hits and sleep this much. This will make "per-second" client grant statistic not actually per-second, but I don't think we need any precision in that code Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2924 Lustre-change: http://review.whamcloud.com/5793 Signed-off-by: Oleg Drokin Reviewed-by: Vitaly Fertman Reviewed-by: Hiroya Nozaki Reviewed-by: Niu Yawei Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../lustre/lustre/include/lustre_dlm.h | 2 +- .../staging/lustre/lustre/ldlm/ldlm_pool.c | 24 ++++++++++++------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/lustre_dlm.h b/drivers/staging/lustre/lustre/include/lustre_dlm.h index 48cb6f89cb0a..25437b7c2026 100644 --- a/drivers/staging/lustre/lustre/include/lustre_dlm.h +++ b/drivers/staging/lustre/lustre/include/lustre_dlm.h @@ -1643,7 +1643,7 @@ void unlock_res_and_lock(struct ldlm_lock *lock); * There are not used outside of ldlm. * @{ */ -void ldlm_pools_recalc(ldlm_side_t client); +int ldlm_pools_recalc(ldlm_side_t client); int ldlm_pools_init(void); void ldlm_pools_fini(void); diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c b/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c index 1e6802fa0a7b..3277a0dca31e 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c @@ -578,7 +578,6 @@ int ldlm_pool_recalc(struct ldlm_pool *pl) goto recalc; spin_lock(&pl->pl_lock); - recalc_interval_sec = cfs_time_current_sec() - pl->pl_recalc_time; if (recalc_interval_sec > 0) { /* * Update pool statistics every 1s. @@ -598,12 +597,12 @@ int ldlm_pool_recalc(struct ldlm_pool *pl) count = pl->pl_ops->po_recalc(pl); lprocfs_counter_add(pl->pl_stats, LDLM_POOL_RECALC_STAT, count); - return count; } + recalc_interval_sec = pl->pl_recalc_time - cfs_time_current_sec() + + pl->pl_recalc_period; - return 0; + return recalc_interval_sec; } -EXPORT_SYMBOL(ldlm_pool_recalc); /** * Pool shrink wrapper. Will call either client or server pool recalc callback @@ -1144,12 +1143,13 @@ static int ldlm_pools_cli_shrink(SHRINKER_ARGS(sc, nr_to_scan, gfp_mask)) shrink_param(sc, gfp_mask)); } -void ldlm_pools_recalc(ldlm_side_t client) +int ldlm_pools_recalc(ldlm_side_t client) { __u32 nr_l = 0, nr_p = 0, l; struct ldlm_namespace *ns; struct ldlm_namespace *ns_old = NULL; int nr, equal = 0; + int time = 50; /* seconds of sleep if no active namespaces */ /* * No need to setup pool limit for client pools. @@ -1285,16 +1285,22 @@ void ldlm_pools_recalc(ldlm_side_t client) * After setup is done - recalc the pool. */ if (!skip) { - ldlm_pool_recalc(&ns->ns_pool); + int ttime = ldlm_pool_recalc(&ns->ns_pool); + + if (ttime < time) + time = ttime; + ldlm_namespace_put(ns); } } + return time; } EXPORT_SYMBOL(ldlm_pools_recalc); static int ldlm_pools_thread_main(void *arg) { struct ptlrpc_thread *thread = (struct ptlrpc_thread *)arg; + int s_time, c_time; ENTRY; thread_set_flags(thread, SVC_RUNNING); @@ -1309,14 +1315,14 @@ static int ldlm_pools_thread_main(void *arg) /* * Recal all pools on this tick. */ - ldlm_pools_recalc(LDLM_NAMESPACE_SERVER); - ldlm_pools_recalc(LDLM_NAMESPACE_CLIENT); + s_time = ldlm_pools_recalc(LDLM_NAMESPACE_SERVER); + c_time = ldlm_pools_recalc(LDLM_NAMESPACE_CLIENT); /* * Wait until the next check time, or until we're * stopped. */ - lwi = LWI_TIMEOUT(cfs_time_seconds(LDLM_POOLS_THREAD_PERIOD), + lwi = LWI_TIMEOUT(cfs_time_seconds(min(s_time, c_time)), NULL, NULL); l_wait_event(thread->t_ctl_waitq, thread_is_stopping(thread) || From df9fcbeb7730ec77a8f643ff1e00b99167cbeabe Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Tue, 23 Jul 2013 00:06:36 +0800 Subject: [PATCH 0327/3400] staging/lustre: Make quota namespace refcounting consistent It seems quota namespace is needlessly referenced on connect, but that's not necessary as it could not go away until entire obd goes away. On the other hand this extra reference disturbs other logic depending on empty namespace having zero refcount, so this patch drops such extra referencing. This picks client side change of the original patch. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2924 Lustre-change: http://review.whamcloud.com/6234 Signed-off-by: Oleg Drokin Reviewed-by: Niu Yawei Reviewed-by: Johann Lombardi Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ldlm/ldlm_internal.h | 3 +-- drivers/staging/lustre/lustre/ldlm/ldlm_resource.c | 6 +----- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h b/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h index 785c1a19da57..bf6f00341a76 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h @@ -84,8 +84,7 @@ static inline struct mutex *ldlm_namespace_lock(ldlm_side_t client) &ldlm_srv_namespace_lock : &ldlm_cli_namespace_lock; } -/* ns_bref is the number of resources in this namespace with the notable - * exception of quota namespaces which have their empty refcount at 1 */ +/* ns_bref is the number of resources in this namespace */ static inline int ldlm_ns_empty(struct ldlm_namespace *ns) { return atomic_read(&ns->ns_bref) == 0; diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c index 716283859d72..17eab79ba839 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c @@ -1171,11 +1171,7 @@ ldlm_resource_get(struct ldlm_namespace *ns, struct ldlm_resource *parent, /* Let's see if we happened to be the very first resource in this * namespace. If so, and this is a client namespace, we need to move * the namespace into the active namespaces list to be patrolled by - * the ldlm_poold. - * A notable exception, for quota namespaces qsd_lib.c already took a - * namespace reference, so it won't be participating in all of this, - * but I guess that's ok since we have no business cancelling quota - * locks anyway */ + * the ldlm_poold. */ if (ns_is_client(ns) && ns_refcount == 1) { mutex_lock(ldlm_namespace_lock(LDLM_NAMESPACE_CLIENT)); ldlm_namespace_move_to_active_locked(ns, LDLM_NAMESPACE_CLIENT); From f2145eae3d4d7c93fcbd7013bbf31db76bdd0ad4 Mon Sep 17 00:00:00 2001 From: Bruce Korb Date: Tue, 23 Jul 2013 00:06:37 +0800 Subject: [PATCH 0328/3400] staging/lustre/dlmlock: compress out unused space * lustre/include/lustre_dlm.h: Remove all bit fields and the unused weighing callback procedure. respell LDLM_AST_DISCARD_DATA as LDLM_FL_AST_DISCARD_DATA to match other flags. * .gitignore: ignore emacs temporary files * autogen.sh: rebuild the lock bits, if autogen is available. * contrib/bit-masks/lustre_dlm_flags.def: define the ldlm_lock flags * contrib/bit-masks/lustre_dlm_flags.tpl: template for emitting text * contrib/bit-masks/Makefile: construct the .c and .h files The .c file is for constructing a crash extension and is not preserved. * contrib/bit-masks/.gitignore: ignore built products * lustre/contrib/wireshark/packet-lustre.c: use built files instead of local versions of the defines. In the rest of the modified sources, replace flag field references with bit mask references. * lustre/osc/osc_lock.c: removed osc_lock_weigh, too Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2771 Lustre-change: http://review.whamcloud.com/5312 Signed-off-by: Bruce Korb Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin Reviewed-by: Keith Mannthey Reviewed-by: Keith Mannthey Reviewed-by: Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../lustre/lustre/include/lustre_dlm.h | 198 +------- .../lustre/lustre/include/lustre_dlm_flags.h | 460 ++++++++++++++++++ drivers/staging/lustre/lustre/ldlm/l_lock.c | 8 +- .../staging/lustre/lustre/ldlm/ldlm_flock.c | 2 +- .../staging/lustre/lustre/ldlm/ldlm_lock.c | 48 +- .../staging/lustre/lustre/ldlm/ldlm_lockd.c | 4 +- .../staging/lustre/lustre/ldlm/ldlm_request.c | 7 +- .../lustre/lustre/ldlm/ldlm_resource.c | 4 +- drivers/staging/lustre/lustre/llite/dir.c | 15 +- drivers/staging/lustre/lustre/llite/file.c | 19 +- drivers/staging/lustre/lustre/mdc/mdc_locks.c | 9 +- .../staging/lustre/lustre/mgc/mgc_request.c | 8 +- drivers/staging/lustre/lustre/osc/osc_lock.c | 122 ++--- 13 files changed, 572 insertions(+), 332 deletions(-) create mode 100644 drivers/staging/lustre/lustre/include/lustre_dlm_flags.h diff --git a/drivers/staging/lustre/lustre/include/lustre_dlm.h b/drivers/staging/lustre/lustre/include/lustre_dlm.h index 25437b7c2026..66db562c5caa 100644 --- a/drivers/staging/lustre/lustre/include/lustre_dlm.h +++ b/drivers/staging/lustre/lustre/include/lustre_dlm.h @@ -57,6 +57,8 @@ #include /* for interval_node{}, ldlm_extent */ #include +#include "lustre_dlm_flags.h" + struct obd_ops; struct obd_device; @@ -95,161 +97,6 @@ typedef enum { LDLM_NAMESPACE_CLIENT = 1 << 1 } ldlm_side_t; -/** - * Declaration of flags sent through the wire. - **/ -#define LDLM_FL_LOCK_CHANGED 0x000001 /* extent, mode, or resource changed */ - -/** - * If the server returns one of these flags, then the lock was put on that list. - * If the client sends one of these flags (during recovery ONLY!), it wants the - * lock added to the specified list, no questions asked. - */ -#define LDLM_FL_BLOCK_GRANTED 0x000002 -#define LDLM_FL_BLOCK_CONV 0x000004 -#define LDLM_FL_BLOCK_WAIT 0x000008 - -/* Used to be LDLM_FL_CBPENDING 0x000010 moved to non-wire flags */ - -#define LDLM_FL_AST_SENT 0x000020 /* blocking or cancel packet was - * queued for sending. */ -/* Used to be LDLM_FL_WAIT_NOREPROC 0x000040 moved to non-wire flags */ -/* Used to be LDLM_FL_CANCEL 0x000080 moved to non-wire flags */ - -/** - * Lock is being replayed. This could probably be implied by the fact that one - * of BLOCK_{GRANTED,CONV,WAIT} is set, but that is pretty dangerous. - */ -#define LDLM_FL_REPLAY 0x000100 - -#define LDLM_FL_INTENT_ONLY 0x000200 /* Don't grant lock, just do intent. */ - -/* Used to be LDLM_FL_LOCAL_ONLY 0x000400 moved to non-wire flags */ -/* Used to be LDLM_FL_FAILED 0x000800 moved to non-wire flags */ - -#define LDLM_FL_HAS_INTENT 0x001000 /* lock request has intent */ - -/* Used to be LDLM_FL_CANCELING 0x002000 moved to non-wire flags */ -/* Used to be LDLM_FL_LOCAL 0x004000 moved to non-wire flags */ - -#define LDLM_FL_DISCARD_DATA 0x010000 /* discard (no writeback) on cancel */ - -#define LDLM_FL_NO_TIMEOUT 0x020000 /* Blocked by group lock - wait - * indefinitely */ - -/** file & record locking */ -#define LDLM_FL_BLOCK_NOWAIT 0x040000 /* Server told not to wait if blocked. - * For AGL, OST will not send glimpse - * callback. */ -#define LDLM_FL_TEST_LOCK 0x080000 // return blocking lock - -/* Used to be LDLM_FL_LVB_READY 0x100000 moved to non-wire flags */ -/* Used to be LDLM_FL_KMS_IGNORE 0x200000 moved to non-wire flags */ -/* Used to be LDLM_FL_NO_LRU 0x400000 moved to non-wire flags */ - -/* Immediatelly cancel such locks when they block some other locks. Send - * cancel notification to original lock holder, but expect no reply. This is - * for clients (like liblustre) that cannot be expected to reliably response - * to blocking AST. */ -#define LDLM_FL_CANCEL_ON_BLOCK 0x800000 - -/* Flags flags inherited from parent lock when doing intents. */ -#define LDLM_INHERIT_FLAGS (LDLM_FL_CANCEL_ON_BLOCK) - -/* Used to be LDLM_FL_CP_REQD 0x1000000 moved to non-wire flags */ -/* Used to be LDLM_FL_CLEANED 0x2000000 moved to non-wire flags */ -/* Used to be LDLM_FL_ATOMIC_CB 0x4000000 moved to non-wire flags */ -/* Used to be LDLM_FL_BL_AST 0x10000000 moved to non-wire flags */ -/* Used to be LDLM_FL_BL_DONE 0x20000000 moved to non-wire flags */ - -/* measure lock contention and return -EUSERS if locking contention is high */ -#define LDLM_FL_DENY_ON_CONTENTION 0x40000000 - -/* These are flags that are mapped into the flags and ASTs of blocking locks */ -#define LDLM_AST_DISCARD_DATA 0x80000000 /* Add FL_DISCARD to blocking ASTs */ - -/* Flags sent in AST lock_flags to be mapped into the receiving lock. */ -#define LDLM_AST_FLAGS (LDLM_FL_DISCARD_DATA) - -/* - * -------------------------------------------------------------------------- - * NOTE! Starting from this point, that is, LDLM_FL_* flags with values above - * 0x80000000 will not be sent over the wire. - * -------------------------------------------------------------------------- - */ - -/** - * Declaration of flags not sent through the wire. - **/ - -/** - * Used for marking lock as a target for -EINTR while cp_ast sleep - * emulation + race with upcoming bl_ast. - */ -#define LDLM_FL_FAIL_LOC 0x100000000ULL - -/** - * Used while processing the unused list to know that we have already - * handled this lock and decided to skip it. - */ -#define LDLM_FL_SKIPPED 0x200000000ULL -/* this lock is being destroyed */ -#define LDLM_FL_CBPENDING 0x400000000ULL -/* not a real flag, not saved in lock */ -#define LDLM_FL_WAIT_NOREPROC 0x800000000ULL -/* cancellation callback already run */ -#define LDLM_FL_CANCEL 0x1000000000ULL -#define LDLM_FL_LOCAL_ONLY 0x2000000000ULL -/* don't run the cancel callback under ldlm_cli_cancel_unused */ -#define LDLM_FL_FAILED 0x4000000000ULL -/* lock cancel has already been sent */ -#define LDLM_FL_CANCELING 0x8000000000ULL -/* local lock (ie, no srv/cli split) */ -#define LDLM_FL_LOCAL 0x10000000000ULL -/* XXX FIXME: This is being added to b_size as a low-risk fix to the fact that - * the LVB filling happens _after_ the lock has been granted, so another thread - * can match it before the LVB has been updated. As a dirty hack, we set - * LDLM_FL_LVB_READY only after we've done the LVB poop. - * this is only needed on LOV/OSC now, where LVB is actually used and callers - * must set it in input flags. - * - * The proper fix is to do the granting inside of the completion AST, which can - * be replaced with a LVB-aware wrapping function for OSC locks. That change is - * pretty high-risk, though, and would need a lot more testing. */ -#define LDLM_FL_LVB_READY 0x20000000000ULL -/* A lock contributes to the known minimum size (KMS) calculation until it has - * finished the part of its cancelation that performs write back on its dirty - * pages. It can remain on the granted list during this whole time. Threads - * racing to update the KMS after performing their writeback need to know to - * exclude each other's locks from the calculation as they walk the granted - * list. */ -#define LDLM_FL_KMS_IGNORE 0x40000000000ULL -/* completion AST to be executed */ -#define LDLM_FL_CP_REQD 0x80000000000ULL -/* cleanup_resource has already handled the lock */ -#define LDLM_FL_CLEANED 0x100000000000ULL -/* optimization hint: LDLM can run blocking callback from current context - * w/o involving separate thread. in order to decrease cs rate */ -#define LDLM_FL_ATOMIC_CB 0x200000000000ULL - -/* It may happen that a client initiates two operations, e.g. unlink and - * mkdir, such that the server sends a blocking AST for conflicting - * locks to this client for the first operation, whereas the second - * operation has canceled this lock and is waiting for rpc_lock which is - * taken by the first operation. LDLM_FL_BL_AST is set by - * ldlm_callback_handler() in the lock to prevent the Early Lock Cancel - * (ELC) code from cancelling it. - * - * LDLM_FL_BL_DONE is to be set by ldlm_cancel_callback() when lock - * cache is dropped to let ldlm_callback_handler() return EINVAL to the - * server. It is used when ELC RPC is already prepared and is waiting - * for rpc_lock, too late to send a separate CANCEL RPC. */ -#define LDLM_FL_BL_AST 0x400000000000ULL -#define LDLM_FL_BL_DONE 0x800000000000ULL -/* Don't put lock into the LRU list, so that it is not canceled due to aging. - * Used by MGC locks, they are cancelled only at unmount or by callback. */ -#define LDLM_FL_NO_LRU 0x1000000000000ULL - /** * The blocking callback is overloaded to perform two functions. These flags * indicate which operation should be performed. @@ -720,8 +567,6 @@ typedef int (*ldlm_completion_callback)(struct ldlm_lock *lock, __u64 flags, void *data); /** Type for glimpse callback function of a lock. */ typedef int (*ldlm_glimpse_callback)(struct ldlm_lock *lock, void *data); -/** Type for weight callback function of a lock. */ -typedef unsigned long (*ldlm_weigh_callback)(struct ldlm_lock *lock); /** Work list for sending GL ASTs to multiple locks. */ struct ldlm_glimpse_work { @@ -890,9 +735,6 @@ struct ldlm_lock { */ ldlm_glimpse_callback l_glimpse_ast; - /** XXX apparently unused "weight" handler. To be removed? */ - ldlm_weigh_callback l_weigh_ast; - /** * Lock export. * This is a pointer to actual client export for locks that were granted @@ -919,11 +761,11 @@ struct ldlm_lock { ldlm_policy_data_t l_policy_data; /** - * Lock state flags. - * Like whenever we receive any blocking requests for this lock, etc. - * Protected by lr_lock. + * Lock state flags. Protected by lr_lock. + * \see lustre_dlm_flags.h where the bits are defined. */ __u64 l_flags; + /** * Lock r/w usage counters. * Protected by lr_lock. @@ -952,34 +794,6 @@ struct ldlm_lock { /** Originally requested extent for the extent lock. */ struct ldlm_extent l_req_extent; - unsigned int l_failed:1, - /** - * Set for locks that were removed from class hash table and will be - * destroyed when last reference to them is released. Set by - * ldlm_lock_destroy_internal(). - * - * Protected by lock and resource locks. - */ - l_destroyed:1, - /* - * it's set in lock_res_and_lock() and unset in unlock_res_and_lock(). - * - * NB: compared with check_res_locked(), checking this bit is cheaper. - * Also, spin_is_locked() is deprecated for kernel code; one reason is - * because it works only for SMP so user needs to add extra macros like - * LASSERT_SPIN_LOCKED for uniprocessor kernels. - */ - l_res_locked:1, - /* - * It's set once we call ldlm_add_waiting_lock_res_locked() - * to start the lock-timeout timer and it will never be reset. - * - * Protected by lock_res_and_lock(). - */ - l_waited:1, - /** Flag whether this is a server namespace lock. */ - l_ns_srv:1; - /* * Client-side-only members. */ @@ -1230,7 +1044,6 @@ struct ldlm_enqueue_info { void *ei_cb_bl; /** blocking lock callback */ void *ei_cb_cp; /** lock completion callback */ void *ei_cb_gl; /** lock glimpse callback */ - void *ei_cb_wg; /** lock weigh callback */ void *ei_cbdata; /** Data to be passed into callbacks. */ }; @@ -1328,7 +1141,6 @@ struct ldlm_callback_suite { ldlm_completion_callback lcs_completion; ldlm_blocking_callback lcs_blocking; ldlm_glimpse_callback lcs_glimpse; - ldlm_weigh_callback lcs_weigh; }; /* ldlm_lockd.c */ diff --git a/drivers/staging/lustre/lustre/include/lustre_dlm_flags.h b/drivers/staging/lustre/lustre/include/lustre_dlm_flags.h new file mode 100644 index 000000000000..8c34d9d4d258 --- /dev/null +++ b/drivers/staging/lustre/lustre/include/lustre_dlm_flags.h @@ -0,0 +1,460 @@ +/* -*- buffer-read-only: t -*- vi: set ro: + * + * DO NOT EDIT THIS FILE (lustre_dlm_flags.h) + * + * It has been AutoGen-ed + * From the definitions lustre_dlm_flags.def + * and the template file lustre_dlm_flags.tpl + * + * lustre 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 3 of the License, or + * (at your option) any later version. + * + * lustre 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, see . + */ +/** + * \file lustre_dlm_flags.h + * The flags and collections of flags (masks) for \see struct ldlm_lock. + * This file is derived from flag definitions in lustre_dlm_flags.def. + * The format is defined in the lustre_dlm_flags.tpl template file. + * + * \addtogroup LDLM Lustre Distributed Lock Manager + * @{ + * + * \name flags + * The flags and collections of flags (masks) for \see struct ldlm_lock. + * @{ + */ +#ifndef LDLM_ALL_FLAGS_MASK + +/** l_flags bits marked as "all_flags" bits */ +#define LDLM_FL_ALL_FLAGS_MASK 0x007FFFFFC08F132FULL + +/** l_flags bits marked as "ast" bits */ +#define LDLM_FL_AST_MASK 0x0000000080000000ULL + +/** l_flags bits marked as "blocked" bits */ +#define LDLM_FL_BLOCKED_MASK 0x000000000000000EULL + +/** l_flags bits marked as "gone" bits */ +#define LDLM_FL_GONE_MASK 0x0006004000000000ULL + +/** l_flags bits marked as "hide_lock" bits */ +#define LDLM_FL_HIDE_LOCK_MASK 0x0000206400000000ULL + +/** l_flags bits marked as "inherit" bits */ +#define LDLM_FL_INHERIT_MASK 0x0000000000800000ULL + +/** l_flags bits marked as "local_only" bits */ +#define LDLM_FL_LOCAL_ONLY_MASK 0x007FFFFF00000000ULL + +/** l_flags bits marked as "on_wire" bits */ +#define LDLM_FL_ON_WIRE_MASK 0x00000000C08F132FULL + +/** extent, mode, or resource changed */ +#define LDLM_FL_LOCK_CHANGED 0x0000000000000001ULL // bit 0 +#define ldlm_is_lock_changed(_l) LDLM_TEST_FLAG(( _l), 1ULL << 0) +#define ldlm_set_lock_changed(_l) LDLM_SET_FLAG(( _l), 1ULL << 0) +#define ldlm_clear_lock_changed(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 0) + +/** + * Server placed lock on granted list, or a recovering client wants the + * lock added to the granted list, no questions asked. */ +#define LDLM_FL_BLOCK_GRANTED 0x0000000000000002ULL // bit 1 +#define ldlm_is_block_granted(_l) LDLM_TEST_FLAG(( _l), 1ULL << 1) +#define ldlm_set_block_granted(_l) LDLM_SET_FLAG(( _l), 1ULL << 1) +#define ldlm_clear_block_granted(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 1) + +/** + * Server placed lock on conv list, or a recovering client wants the lock + * added to the conv list, no questions asked. */ +#define LDLM_FL_BLOCK_CONV 0x0000000000000004ULL // bit 2 +#define ldlm_is_block_conv(_l) LDLM_TEST_FLAG(( _l), 1ULL << 2) +#define ldlm_set_block_conv(_l) LDLM_SET_FLAG(( _l), 1ULL << 2) +#define ldlm_clear_block_conv(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 2) + +/** + * Server placed lock on wait list, or a recovering client wants the lock + * added to the wait list, no questions asked. */ +#define LDLM_FL_BLOCK_WAIT 0x0000000000000008ULL // bit 3 +#define ldlm_is_block_wait(_l) LDLM_TEST_FLAG(( _l), 1ULL << 3) +#define ldlm_set_block_wait(_l) LDLM_SET_FLAG(( _l), 1ULL << 3) +#define ldlm_clear_block_wait(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 3) + +/** blocking or cancel packet was queued for sending. */ +#define LDLM_FL_AST_SENT 0x0000000000000020ULL // bit 5 +#define ldlm_is_ast_sent(_l) LDLM_TEST_FLAG(( _l), 1ULL << 5) +#define ldlm_set_ast_sent(_l) LDLM_SET_FLAG(( _l), 1ULL << 5) +#define ldlm_clear_ast_sent(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 5) + +/** + * Lock is being replayed. This could probably be implied by the fact that + * one of BLOCK_{GRANTED,CONV,WAIT} is set, but that is pretty dangerous. */ +#define LDLM_FL_REPLAY 0x0000000000000100ULL // bit 8 +#define ldlm_is_replay(_l) LDLM_TEST_FLAG(( _l), 1ULL << 8) +#define ldlm_set_replay(_l) LDLM_SET_FLAG(( _l), 1ULL << 8) +#define ldlm_clear_replay(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 8) + +/** Don't grant lock, just do intent. */ +#define LDLM_FL_INTENT_ONLY 0x0000000000000200ULL // bit 9 +#define ldlm_is_intent_only(_l) LDLM_TEST_FLAG(( _l), 1ULL << 9) +#define ldlm_set_intent_only(_l) LDLM_SET_FLAG(( _l), 1ULL << 9) +#define ldlm_clear_intent_only(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 9) + +/** lock request has intent */ +#define LDLM_FL_HAS_INTENT 0x0000000000001000ULL // bit 12 +#define ldlm_is_has_intent(_l) LDLM_TEST_FLAG(( _l), 1ULL << 12) +#define ldlm_set_has_intent(_l) LDLM_SET_FLAG(( _l), 1ULL << 12) +#define ldlm_clear_has_intent(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 12) + +/** discard (no writeback) on cancel */ +#define LDLM_FL_DISCARD_DATA 0x0000000000010000ULL // bit 16 +#define ldlm_is_discard_data(_l) LDLM_TEST_FLAG(( _l), 1ULL << 16) +#define ldlm_set_discard_data(_l) LDLM_SET_FLAG(( _l), 1ULL << 16) +#define ldlm_clear_discard_data(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 16) + +/** Blocked by group lock - wait indefinitely */ +#define LDLM_FL_NO_TIMEOUT 0x0000000000020000ULL // bit 17 +#define ldlm_is_no_timeout(_l) LDLM_TEST_FLAG(( _l), 1ULL << 17) +#define ldlm_set_no_timeout(_l) LDLM_SET_FLAG(( _l), 1ULL << 17) +#define ldlm_clear_no_timeout(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 17) + +/** + * Server told not to wait if blocked. For AGL, OST will not send glimpse + * callback. */ +#define LDLM_FL_BLOCK_NOWAIT 0x0000000000040000ULL // bit 18 +#define ldlm_is_block_nowait(_l) LDLM_TEST_FLAG(( _l), 1ULL << 18) +#define ldlm_set_block_nowait(_l) LDLM_SET_FLAG(( _l), 1ULL << 18) +#define ldlm_clear_block_nowait(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 18) + +/** return blocking lock */ +#define LDLM_FL_TEST_LOCK 0x0000000000080000ULL // bit 19 +#define ldlm_is_test_lock(_l) LDLM_TEST_FLAG(( _l), 1ULL << 19) +#define ldlm_set_test_lock(_l) LDLM_SET_FLAG(( _l), 1ULL << 19) +#define ldlm_clear_test_lock(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 19) + +/** + * Immediatelly cancel such locks when they block some other locks. Send + * cancel notification to original lock holder, but expect no reply. This + * is for clients (like liblustre) that cannot be expected to reliably + * response to blocking AST. */ +#define LDLM_FL_CANCEL_ON_BLOCK 0x0000000000800000ULL // bit 23 +#define ldlm_is_cancel_on_block(_l) LDLM_TEST_FLAG(( _l), 1ULL << 23) +#define ldlm_set_cancel_on_block(_l) LDLM_SET_FLAG(( _l), 1ULL << 23) +#define ldlm_clear_cancel_on_block(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 23) + +/** + * measure lock contention and return -EUSERS if locking contention is high */ +#define LDLM_FL_DENY_ON_CONTENTION 0x0000000040000000ULL // bit 30 +#define ldlm_is_deny_on_contention(_l) LDLM_TEST_FLAG(( _l), 1ULL << 30) +#define ldlm_set_deny_on_contention(_l) LDLM_SET_FLAG(( _l), 1ULL << 30) +#define ldlm_clear_deny_on_contention(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 30) + +/** + * These are flags that are mapped into the flags and ASTs of blocking + * locks Add FL_DISCARD to blocking ASTs */ +#define LDLM_FL_AST_DISCARD_DATA 0x0000000080000000ULL // bit 31 +#define ldlm_is_ast_discard_data(_l) LDLM_TEST_FLAG(( _l), 1ULL << 31) +#define ldlm_set_ast_discard_data(_l) LDLM_SET_FLAG(( _l), 1ULL << 31) +#define ldlm_clear_ast_discard_data(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 31) + +/** + * Used for marking lock as a target for -EINTR while cp_ast sleep emulation + * + race with upcoming bl_ast. */ +#define LDLM_FL_FAIL_LOC 0x0000000100000000ULL // bit 32 +#define ldlm_is_fail_loc(_l) LDLM_TEST_FLAG(( _l), 1ULL << 32) +#define ldlm_set_fail_loc(_l) LDLM_SET_FLAG(( _l), 1ULL << 32) +#define ldlm_clear_fail_loc(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 32) + +/** + * Used while processing the unused list to know that we have already + * handled this lock and decided to skip it. */ +#define LDLM_FL_SKIPPED 0x0000000200000000ULL // bit 33 +#define ldlm_is_skipped(_l) LDLM_TEST_FLAG(( _l), 1ULL << 33) +#define ldlm_set_skipped(_l) LDLM_SET_FLAG(( _l), 1ULL << 33) +#define ldlm_clear_skipped(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 33) + +/** this lock is being destroyed */ +#define LDLM_FL_CBPENDING 0x0000000400000000ULL // bit 34 +#define ldlm_is_cbpending(_l) LDLM_TEST_FLAG(( _l), 1ULL << 34) +#define ldlm_set_cbpending(_l) LDLM_SET_FLAG(( _l), 1ULL << 34) +#define ldlm_clear_cbpending(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 34) + +/** not a real flag, not saved in lock */ +#define LDLM_FL_WAIT_NOREPROC 0x0000000800000000ULL // bit 35 +#define ldlm_is_wait_noreproc(_l) LDLM_TEST_FLAG(( _l), 1ULL << 35) +#define ldlm_set_wait_noreproc(_l) LDLM_SET_FLAG(( _l), 1ULL << 35) +#define ldlm_clear_wait_noreproc(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 35) + +/** cancellation callback already run */ +#define LDLM_FL_CANCEL 0x0000001000000000ULL // bit 36 +#define ldlm_is_cancel(_l) LDLM_TEST_FLAG(( _l), 1ULL << 36) +#define ldlm_set_cancel(_l) LDLM_SET_FLAG(( _l), 1ULL << 36) +#define ldlm_clear_cancel(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 36) + +/** whatever it might mean */ +#define LDLM_FL_LOCAL_ONLY 0x0000002000000000ULL // bit 37 +#define ldlm_is_local_only(_l) LDLM_TEST_FLAG(( _l), 1ULL << 37) +#define ldlm_set_local_only(_l) LDLM_SET_FLAG(( _l), 1ULL << 37) +#define ldlm_clear_local_only(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 37) + +/** don't run the cancel callback under ldlm_cli_cancel_unused */ +#define LDLM_FL_FAILED 0x0000004000000000ULL // bit 38 +#define ldlm_is_failed(_l) LDLM_TEST_FLAG(( _l), 1ULL << 38) +#define ldlm_set_failed(_l) LDLM_SET_FLAG(( _l), 1ULL << 38) +#define ldlm_clear_failed(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 38) + +/** lock cancel has already been sent */ +#define LDLM_FL_CANCELING 0x0000008000000000ULL // bit 39 +#define ldlm_is_canceling(_l) LDLM_TEST_FLAG(( _l), 1ULL << 39) +#define ldlm_set_canceling(_l) LDLM_SET_FLAG(( _l), 1ULL << 39) +#define ldlm_clear_canceling(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 39) + +/** local lock (ie, no srv/cli split) */ +#define LDLM_FL_LOCAL 0x0000010000000000ULL // bit 40 +#define ldlm_is_local(_l) LDLM_TEST_FLAG(( _l), 1ULL << 40) +#define ldlm_set_local(_l) LDLM_SET_FLAG(( _l), 1ULL << 40) +#define ldlm_clear_local(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 40) + +/** + * XXX FIXME: This is being added to b_size as a low-risk fix to the + * fact that the LVB filling happens _after_ the lock has been granted, + * so another thread can match it before the LVB has been updated. As a + * dirty hack, we set LDLM_FL_LVB_READY only after we've done the LVB poop. + * this is only needed on LOV/OSC now, where LVB is actually used and + * callers must set it in input flags. + * + * The proper fix is to do the granting inside of the completion AST, + * which can be replaced with a LVB-aware wrapping function for OSC locks. + * That change is pretty high-risk, though, and would need a lot more + * testing. */ +#define LDLM_FL_LVB_READY 0x0000020000000000ULL // bit 41 +#define ldlm_is_lvb_ready(_l) LDLM_TEST_FLAG(( _l), 1ULL << 41) +#define ldlm_set_lvb_ready(_l) LDLM_SET_FLAG(( _l), 1ULL << 41) +#define ldlm_clear_lvb_ready(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 41) + +/** + * A lock contributes to the known minimum size (KMS) calculation until it + * has finished the part of its cancelation that performs write back on its + * dirty pages. It can remain on the granted list during this whole time. + * Threads racing to update the KMS after performing their writeback need + * to know to exclude each other's locks from the calculation as they walk + * the granted list. */ +#define LDLM_FL_KMS_IGNORE 0x0000040000000000ULL // bit 42 +#define ldlm_is_kms_ignore(_l) LDLM_TEST_FLAG(( _l), 1ULL << 42) +#define ldlm_set_kms_ignore(_l) LDLM_SET_FLAG(( _l), 1ULL << 42) +#define ldlm_clear_kms_ignore(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 42) + +/** completion AST to be executed */ +#define LDLM_FL_CP_REQD 0x0000080000000000ULL // bit 43 +#define ldlm_is_cp_reqd(_l) LDLM_TEST_FLAG(( _l), 1ULL << 43) +#define ldlm_set_cp_reqd(_l) LDLM_SET_FLAG(( _l), 1ULL << 43) +#define ldlm_clear_cp_reqd(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 43) + +/** cleanup_resource has already handled the lock */ +#define LDLM_FL_CLEANED 0x0000100000000000ULL // bit 44 +#define ldlm_is_cleaned(_l) LDLM_TEST_FLAG(( _l), 1ULL << 44) +#define ldlm_set_cleaned(_l) LDLM_SET_FLAG(( _l), 1ULL << 44) +#define ldlm_clear_cleaned(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 44) + +/** + * optimization hint: LDLM can run blocking callback from current context + * w/o involving separate thread. in order to decrease cs rate */ +#define LDLM_FL_ATOMIC_CB 0x0000200000000000ULL // bit 45 +#define ldlm_is_atomic_cb(_l) LDLM_TEST_FLAG(( _l), 1ULL << 45) +#define ldlm_set_atomic_cb(_l) LDLM_SET_FLAG(( _l), 1ULL << 45) +#define ldlm_clear_atomic_cb(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 45) + +/** + * It may happen that a client initiates two operations, e.g. unlink and + * mkdir, such that the server sends a blocking AST for conflicting locks + * to this client for the first operation, whereas the second operation + * has canceled this lock and is waiting for rpc_lock which is taken by + * the first operation. LDLM_FL_BL_AST is set by ldlm_callback_handler() in + * the lock to prevent the Early Lock Cancel (ELC) code from cancelling it. + * + * LDLM_FL_BL_DONE is to be set by ldlm_cancel_callback() when lock cache is + * dropped to let ldlm_callback_handler() return EINVAL to the server. It + * is used when ELC RPC is already prepared and is waiting for rpc_lock, + * too late to send a separate CANCEL RPC. */ +#define LDLM_FL_BL_AST 0x0000400000000000ULL // bit 46 +#define ldlm_is_bl_ast(_l) LDLM_TEST_FLAG(( _l), 1ULL << 46) +#define ldlm_set_bl_ast(_l) LDLM_SET_FLAG(( _l), 1ULL << 46) +#define ldlm_clear_bl_ast(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 46) + +/** whatever it might mean */ +#define LDLM_FL_BL_DONE 0x0000800000000000ULL // bit 47 +#define ldlm_is_bl_done(_l) LDLM_TEST_FLAG(( _l), 1ULL << 47) +#define ldlm_set_bl_done(_l) LDLM_SET_FLAG(( _l), 1ULL << 47) +#define ldlm_clear_bl_done(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 47) + +/** + * Don't put lock into the LRU list, so that it is not canceled due + * to aging. Used by MGC locks, they are cancelled only at unmount or + * by callback. */ +#define LDLM_FL_NO_LRU 0x0001000000000000ULL // bit 48 +#define ldlm_is_no_lru(_l) LDLM_TEST_FLAG(( _l), 1ULL << 48) +#define ldlm_set_no_lru(_l) LDLM_SET_FLAG(( _l), 1ULL << 48) +#define ldlm_clear_no_lru(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 48) + +/** + * Set for locks that failed and where the server has been notified. + * + * Protected by lock and resource locks. */ +#define LDLM_FL_FAIL_NOTIFIED 0x0002000000000000ULL // bit 49 +#define ldlm_is_fail_notified(_l) LDLM_TEST_FLAG(( _l), 1ULL << 49) +#define ldlm_set_fail_notified(_l) LDLM_SET_FLAG(( _l), 1ULL << 49) +#define ldlm_clear_fail_notified(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 49) + +/** + * Set for locks that were removed from class hash table and will + * be destroyed when last reference to them is released. Set by + * ldlm_lock_destroy_internal(). + * + * Protected by lock and resource locks. */ +#define LDLM_FL_DESTROYED 0x0004000000000000ULL // bit 50 +#define ldlm_is_destroyed(_l) LDLM_TEST_FLAG(( _l), 1ULL << 50) +#define ldlm_set_destroyed(_l) LDLM_SET_FLAG(( _l), 1ULL << 50) +#define ldlm_clear_destroyed(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 50) + +/** flag whether this is a server namespace lock */ +#define LDLM_FL_SERVER_LOCK 0x0008000000000000ULL // bit 51 +#define ldlm_is_server_lock(_l) LDLM_TEST_FLAG(( _l), 1ULL << 51) +#define ldlm_set_server_lock(_l) LDLM_SET_FLAG(( _l), 1ULL << 51) +#define ldlm_clear_server_lock(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 51) + +/** + * It's set in lock_res_and_lock() and unset in unlock_res_and_lock(). + * + * NB: compared with check_res_locked(), checking this bit is cheaper. + * Also, spin_is_locked() is deprecated for kernel code; one reason is + * because it works only for SMP so user needs to add extra macros like + * LASSERT_SPIN_LOCKED for uniprocessor kernels. */ +#define LDLM_FL_RES_LOCKED 0x0010000000000000ULL // bit 52 +#define ldlm_is_res_locked(_l) LDLM_TEST_FLAG(( _l), 1ULL << 52) +#define ldlm_set_res_locked(_l) LDLM_SET_FLAG(( _l), 1ULL << 52) +#define ldlm_clear_res_locked(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 52) + +/** + * It's set once we call ldlm_add_waiting_lock_res_locked() to start the + * lock-timeout timer and it will never be reset. + * + * Protected by lock and resource locks. */ +#define LDLM_FL_WAITED 0x0020000000000000ULL // bit 53 +#define ldlm_is_waited(_l) LDLM_TEST_FLAG(( _l), 1ULL << 53) +#define ldlm_set_waited(_l) LDLM_SET_FLAG(( _l), 1ULL << 53) +#define ldlm_clear_waited(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 53) + +/** Flag whether this is a server namespace lock. */ +#define LDLM_FL_NS_SRV 0x0040000000000000ULL // bit 54 +#define ldlm_is_ns_srv(_l) LDLM_TEST_FLAG(( _l), 1ULL << 54) +#define ldlm_set_ns_srv(_l) LDLM_SET_FLAG(( _l), 1ULL << 54) +#define ldlm_clear_ns_srv(_l) LDLM_CLEAR_FLAG((_l), 1ULL << 54) + +/** test for ldlm_lock flag bit set */ +#define LDLM_TEST_FLAG(_l, _b) (((_l)->l_flags & (_b)) != 0) + +/** set a ldlm_lock flag bit */ +#define LDLM_SET_FLAG(_l, _b) (((_l)->l_flags |= (_b)) + +/** clear a ldlm_lock flag bit */ +#define LDLM_CLEAR_FLAG(_l, _b) (((_l)->l_flags &= ~(_b)) + +/** Mask of flags inherited from parent lock when doing intents. */ +#define LDLM_INHERIT_FLAGS LDLM_FL_INHERIT_MASK + +/** Mask of Flags sent in AST lock_flags to map into the receiving lock. */ +#define LDLM_AST_FLAGS LDLM_FL_AST_MASK + +/** @} subgroup */ +/** @} group */ +#ifdef WIRESHARK_COMPILE +static int hf_lustre_ldlm_fl_lock_changed = -1; +static int hf_lustre_ldlm_fl_block_granted = -1; +static int hf_lustre_ldlm_fl_block_conv = -1; +static int hf_lustre_ldlm_fl_block_wait = -1; +static int hf_lustre_ldlm_fl_ast_sent = -1; +static int hf_lustre_ldlm_fl_replay = -1; +static int hf_lustre_ldlm_fl_intent_only = -1; +static int hf_lustre_ldlm_fl_has_intent = -1; +static int hf_lustre_ldlm_fl_discard_data = -1; +static int hf_lustre_ldlm_fl_no_timeout = -1; +static int hf_lustre_ldlm_fl_block_nowait = -1; +static int hf_lustre_ldlm_fl_test_lock = -1; +static int hf_lustre_ldlm_fl_cancel_on_block = -1; +static int hf_lustre_ldlm_fl_deny_on_contention = -1; +static int hf_lustre_ldlm_fl_ast_discard_data = -1; +static int hf_lustre_ldlm_fl_fail_loc = -1; +static int hf_lustre_ldlm_fl_skipped = -1; +static int hf_lustre_ldlm_fl_cbpending = -1; +static int hf_lustre_ldlm_fl_wait_noreproc = -1; +static int hf_lustre_ldlm_fl_cancel = -1; +static int hf_lustre_ldlm_fl_local_only = -1; +static int hf_lustre_ldlm_fl_failed = -1; +static int hf_lustre_ldlm_fl_canceling = -1; +static int hf_lustre_ldlm_fl_local = -1; +static int hf_lustre_ldlm_fl_lvb_ready = -1; +static int hf_lustre_ldlm_fl_kms_ignore = -1; +static int hf_lustre_ldlm_fl_cp_reqd = -1; +static int hf_lustre_ldlm_fl_cleaned = -1; +static int hf_lustre_ldlm_fl_atomic_cb = -1; +static int hf_lustre_ldlm_fl_bl_ast = -1; +static int hf_lustre_ldlm_fl_bl_done = -1; +static int hf_lustre_ldlm_fl_no_lru = -1; +static int hf_lustre_ldlm_fl_fail_notified = -1; +static int hf_lustre_ldlm_fl_destroyed = -1; +static int hf_lustre_ldlm_fl_server_lock = -1; +static int hf_lustre_ldlm_fl_res_locked = -1; +static int hf_lustre_ldlm_fl_waited = -1; +static int hf_lustre_ldlm_fl_ns_srv = -1; + +const value_string lustre_ldlm_flags_vals[] = { + {LDLM_FL_LOCK_CHANGED, "LDLM_FL_LOCK_CHANGED"}, + {LDLM_FL_BLOCK_GRANTED, "LDLM_FL_BLOCK_GRANTED"}, + {LDLM_FL_BLOCK_CONV, "LDLM_FL_BLOCK_CONV"}, + {LDLM_FL_BLOCK_WAIT, "LDLM_FL_BLOCK_WAIT"}, + {LDLM_FL_AST_SENT, "LDLM_FL_AST_SENT"}, + {LDLM_FL_REPLAY, "LDLM_FL_REPLAY"}, + {LDLM_FL_INTENT_ONLY, "LDLM_FL_INTENT_ONLY"}, + {LDLM_FL_HAS_INTENT, "LDLM_FL_HAS_INTENT"}, + {LDLM_FL_DISCARD_DATA, "LDLM_FL_DISCARD_DATA"}, + {LDLM_FL_NO_TIMEOUT, "LDLM_FL_NO_TIMEOUT"}, + {LDLM_FL_BLOCK_NOWAIT, "LDLM_FL_BLOCK_NOWAIT"}, + {LDLM_FL_TEST_LOCK, "LDLM_FL_TEST_LOCK"}, + {LDLM_FL_CANCEL_ON_BLOCK, "LDLM_FL_CANCEL_ON_BLOCK"}, + {LDLM_FL_DENY_ON_CONTENTION, "LDLM_FL_DENY_ON_CONTENTION"}, + {LDLM_FL_AST_DISCARD_DATA, "LDLM_FL_AST_DISCARD_DATA"}, + {LDLM_FL_FAIL_LOC, "LDLM_FL_FAIL_LOC"}, + {LDLM_FL_SKIPPED, "LDLM_FL_SKIPPED"}, + {LDLM_FL_CBPENDING, "LDLM_FL_CBPENDING"}, + {LDLM_FL_WAIT_NOREPROC, "LDLM_FL_WAIT_NOREPROC"}, + {LDLM_FL_CANCEL, "LDLM_FL_CANCEL"}, + {LDLM_FL_LOCAL_ONLY, "LDLM_FL_LOCAL_ONLY"}, + {LDLM_FL_FAILED, "LDLM_FL_FAILED"}, + {LDLM_FL_CANCELING, "LDLM_FL_CANCELING"}, + {LDLM_FL_LOCAL, "LDLM_FL_LOCAL"}, + {LDLM_FL_LVB_READY, "LDLM_FL_LVB_READY"}, + {LDLM_FL_KMS_IGNORE, "LDLM_FL_KMS_IGNORE"}, + {LDLM_FL_CP_REQD, "LDLM_FL_CP_REQD"}, + {LDLM_FL_CLEANED, "LDLM_FL_CLEANED"}, + {LDLM_FL_ATOMIC_CB, "LDLM_FL_ATOMIC_CB"}, + {LDLM_FL_BL_AST, "LDLM_FL_BL_AST"}, + {LDLM_FL_BL_DONE, "LDLM_FL_BL_DONE"}, + {LDLM_FL_NO_LRU, "LDLM_FL_NO_LRU"}, + {LDLM_FL_FAIL_NOTIFIED, "LDLM_FL_FAIL_NOTIFIED"}, + {LDLM_FL_DESTROYED, "LDLM_FL_DESTROYED"}, + {LDLM_FL_SERVER_LOCK, "LDLM_FL_SERVER_LOCK"}, + {LDLM_FL_RES_LOCKED, "LDLM_FL_RES_LOCKED"}, + {LDLM_FL_WAITED, "LDLM_FL_WAITED"}, + {LDLM_FL_NS_SRV, "LDLM_FL_NS_SRV"}, + { 0, NULL } +}; +#endif /* WIRESHARK_COMPILE */ +#endif /* LDLM_ALL_FLAGS_MASK */ diff --git a/drivers/staging/lustre/lustre/ldlm/l_lock.c b/drivers/staging/lustre/lustre/ldlm/l_lock.c index 853409aa945d..32f4d52b5362 100644 --- a/drivers/staging/lustre/lustre/ldlm/l_lock.c +++ b/drivers/staging/lustre/lustre/ldlm/l_lock.c @@ -51,12 +51,12 @@ struct ldlm_resource *lock_res_and_lock(struct ldlm_lock *lock) { /* on server-side resource of lock doesn't change */ - if (!lock->l_ns_srv) + if ((lock->l_flags & LDLM_FL_NS_SRV) == 0) spin_lock(&lock->l_lock); lock_res(lock->l_resource); - lock->l_res_locked = 1; + lock->l_flags |= LDLM_FL_RES_LOCKED; return lock->l_resource; } EXPORT_SYMBOL(lock_res_and_lock); @@ -67,10 +67,10 @@ EXPORT_SYMBOL(lock_res_and_lock); void unlock_res_and_lock(struct ldlm_lock *lock) { /* on server-side resource of lock doesn't change */ - lock->l_res_locked = 0; + lock->l_flags &= ~LDLM_FL_RES_LOCKED; unlock_res(lock->l_resource); - if (!lock->l_ns_srv) + if ((lock->l_flags & LDLM_FL_NS_SRV) == 0) spin_unlock(&lock->l_lock); } EXPORT_SYMBOL(unlock_res_and_lock); diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c index f100a84bde73..aca1073d18b5 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c @@ -639,7 +639,7 @@ ldlm_flock_completion_ast(struct ldlm_lock *lock, __u64 flags, void *data) granted: OBD_FAIL_TIMEOUT(OBD_FAIL_LDLM_CP_CB_WAIT, 10); - if (lock->l_destroyed) { + if (lock->l_flags & LDLM_FL_DESTROYED) { LDLM_DEBUG(lock, "client-side enqueue waking up: destroyed"); RETURN(0); } diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c index 0b3ea88ae5b0..c10ba9c33f42 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c @@ -199,7 +199,7 @@ void ldlm_lock_put(struct ldlm_lock *lock) "final lock_put on destroyed lock, freeing it."); res = lock->l_resource; - LASSERT(lock->l_destroyed); + LASSERT(lock->l_flags & LDLM_FL_DESTROYED); LASSERT(list_empty(&lock->l_res_link)); LASSERT(list_empty(&lock->l_pending_chain)); @@ -254,7 +254,7 @@ int ldlm_lock_remove_from_lru(struct ldlm_lock *lock) int rc; ENTRY; - if (lock->l_ns_srv) { + if (lock->l_flags & LDLM_FL_NS_SRV) { LASSERT(list_empty(&lock->l_lru)); RETURN(0); } @@ -305,7 +305,7 @@ void ldlm_lock_touch_in_lru(struct ldlm_lock *lock) struct ldlm_namespace *ns = ldlm_lock_to_ns(lock); ENTRY; - if (lock->l_ns_srv) { + if (lock->l_flags & LDLM_FL_NS_SRV) { LASSERT(list_empty(&lock->l_lru)); EXIT; return; @@ -353,12 +353,12 @@ int ldlm_lock_destroy_internal(struct ldlm_lock *lock) LBUG(); } - if (lock->l_destroyed) { + if (lock->l_flags & LDLM_FL_DESTROYED) { LASSERT(list_empty(&lock->l_lru)); EXIT; return 0; } - lock->l_destroyed = 1; + lock->l_flags |= LDLM_FL_DESTROYED; if (lock->l_export && lock->l_export->exp_lock_hash) { /* NB: it's safe to call cfs_hash_del() even lock isn't @@ -596,7 +596,7 @@ struct ldlm_lock *__ldlm_handle2lock(const struct lustre_handle *handle, /* It's unlikely but possible that someone marked the lock as * destroyed after we did handle2object on it */ - if (flags == 0 && !lock->l_destroyed) { + if (flags == 0 && ((lock->l_flags & LDLM_FL_DESTROYED)== 0)) { lu_ref_add(&lock->l_reference, "handle", current); RETURN(lock); } @@ -606,7 +606,7 @@ struct ldlm_lock *__ldlm_handle2lock(const struct lustre_handle *handle, LASSERT(lock->l_resource != NULL); lu_ref_add_atomic(&lock->l_reference, "handle", current); - if (unlikely(lock->l_destroyed)) { + if (unlikely(lock->l_flags & LDLM_FL_DESTROYED)) { unlock_res_and_lock(lock); CDEBUG(D_INFO, "lock already destroyed: lock %p\n", lock); LDLM_LOCK_PUT(lock); @@ -695,7 +695,7 @@ void ldlm_add_bl_work_item(struct ldlm_lock *lock, struct ldlm_lock *new, lock->l_flags |= LDLM_FL_AST_SENT; /* If the enqueuing client said so, tell the AST recipient to * discard dirty data, rather than writing back. */ - if (new->l_flags & LDLM_AST_DISCARD_DATA) + if (new->l_flags & LDLM_FL_AST_DISCARD_DATA) lock->l_flags |= LDLM_FL_DISCARD_DATA; LASSERT(list_empty(&lock->l_bl_ast)); list_add(&lock->l_bl_ast, work_list); @@ -873,7 +873,7 @@ void ldlm_lock_decref_internal(struct ldlm_lock *lock, __u32 mode) (lock->l_flags & LDLM_FL_CBPENDING)) { /* If we received a blocked AST and this was the last reference, * run the callback. */ - if (lock->l_ns_srv && lock->l_export) + if ((lock->l_flags & LDLM_FL_NS_SRV) && lock->l_export) CERROR("FL_CBPENDING set on non-local lock--just a " "warning\n"); @@ -1069,7 +1069,7 @@ static void ldlm_granted_list_add_lock(struct ldlm_lock *lock, ldlm_resource_dump(D_INFO, res); LDLM_DEBUG(lock, "About to add lock:"); - if (lock->l_destroyed) { + if (lock->l_flags & LDLM_FL_DESTROYED) { CDEBUG(D_OTHER, "Lock destroyed, not adding to resource\n"); return; } @@ -1203,9 +1203,7 @@ static struct ldlm_lock *search_queue(struct list_head *queue, policy->l_inodebits.bits)) continue; - if (!unref && - (lock->l_destroyed || lock->l_flags & LDLM_FL_FAILED || - lock->l_failed)) + if (!unref && (lock->l_flags & LDLM_FL_GONE_MASK)) continue; if ((flags & LDLM_FL_LOCAL_ONLY) && @@ -1227,8 +1225,8 @@ static struct ldlm_lock *search_queue(struct list_head *queue, void ldlm_lock_fail_match_locked(struct ldlm_lock *lock) { - if (!lock->l_failed) { - lock->l_failed = 1; + if ((lock->l_flags & LDLM_FL_FAIL_NOTIFIED) == 0) { + lock->l_flags |= LDLM_FL_FAIL_NOTIFIED; wake_up_all(&lock->l_waitq); } } @@ -1352,6 +1350,8 @@ ldlm_mode_t ldlm_lock_match(struct ldlm_namespace *ns, __u64 flags, ldlm_lock2handle(lock, lockh); if ((flags & LDLM_FL_LVB_READY) && (!(lock->l_flags & LDLM_FL_LVB_READY))) { + __u64 wait_flags = LDLM_FL_LVB_READY | + LDLM_FL_DESTROYED | LDLM_FL_FAIL_NOTIFIED; struct l_wait_info lwi; if (lock->l_completion_ast) { int err = lock->l_completion_ast(lock, @@ -1373,8 +1373,7 @@ ldlm_mode_t ldlm_lock_match(struct ldlm_namespace *ns, __u64 flags, /* XXX FIXME see comment on CAN_MATCH in lustre_dlm.h */ l_wait_event(lock->l_waitq, - lock->l_flags & LDLM_FL_LVB_READY || - lock->l_destroyed || lock->l_failed, + lock->l_flags & wait_flags, &lwi); if (!(lock->l_flags & LDLM_FL_LVB_READY)) { if (flags & LDLM_FL_TEST_LOCK) @@ -1431,8 +1430,7 @@ ldlm_mode_t ldlm_revalidate_lock_handle(struct lustre_handle *lockh, lock = ldlm_handle2lock(lockh); if (lock != NULL) { lock_res_and_lock(lock); - if (lock->l_destroyed || lock->l_flags & LDLM_FL_FAILED || - lock->l_failed) + if (lock->l_flags & LDLM_FL_GONE_MASK) GOTO(out, mode); if (lock->l_flags & LDLM_FL_CBPENDING && @@ -1583,12 +1581,12 @@ struct ldlm_lock *ldlm_lock_create(struct ldlm_namespace *ns, lock->l_req_mode = mode; lock->l_ast_data = data; lock->l_pid = current_pid(); - lock->l_ns_srv = !!ns_is_server(ns); + if (ns_is_server(ns)) + lock->l_flags |= LDLM_FL_NS_SRV; if (cbs) { lock->l_blocking_ast = cbs->lcs_blocking; lock->l_completion_ast = cbs->lcs_completion; lock->l_glimpse_ast = cbs->lcs_glimpse; - lock->l_weigh_ast = cbs->lcs_weigh; } lock->l_tree_node = NULL; @@ -1693,7 +1691,7 @@ ldlm_error_t ldlm_lock_enqueue(struct ldlm_namespace *ns, /* Some flags from the enqueue want to make it into the AST, via the * lock's l_flags. */ - lock->l_flags |= *flags & LDLM_AST_DISCARD_DATA; + lock->l_flags |= *flags & LDLM_FL_AST_DISCARD_DATA; /* This distinction between local lock trees is very important; a client * namespace only has information about locks taken by that client, and @@ -2046,15 +2044,15 @@ void ldlm_lock_cancel(struct ldlm_lock *lock) LBUG(); } - if (lock->l_waited) + if (lock->l_flags & LDLM_FL_WAITED) ldlm_del_waiting_lock(lock); /* Releases cancel callback. */ ldlm_cancel_callback(lock); /* Yes, second time, just in case it was added again while we were - running with no res lock in ldlm_cancel_callback */ - if (lock->l_waited) + * running with no res lock in ldlm_cancel_callback */ + if (lock->l_flags & LDLM_FL_WAITED) ldlm_del_waiting_lock(lock); ldlm_resource_unlink_lock(lock); diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c index f79b244d1a68..d18936a059d8 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c @@ -198,7 +198,7 @@ static void ldlm_handle_cp_callback(struct ptlrpc_request *req, schedule_timeout_and_set_state( TASK_INTERRUPTIBLE, to); if (lock->l_granted_mode == lock->l_req_mode || - lock->l_destroyed) + lock->l_flags & LDLM_FL_DESTROYED) break; } } @@ -238,7 +238,7 @@ static void ldlm_handle_cp_callback(struct ptlrpc_request *req, } lock_res_and_lock(lock); - if (lock->l_destroyed || + if ((lock->l_flags & LDLM_FL_DESTROYED) || lock->l_granted_mode == lock->l_req_mode) { /* bug 11300: the lock has already been granted */ unlock_res_and_lock(lock); diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c index ab41fea4aa07..c900706a9c8d 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c @@ -160,7 +160,7 @@ static int ldlm_completion_tail(struct ldlm_lock *lock) long delay; int result; - if (lock->l_destroyed || lock->l_flags & LDLM_FL_FAILED) { + if (lock->l_flags & (LDLM_FL_DESTROYED | LDLM_FL_FAILED)) { LDLM_DEBUG(lock, "client-side enqueue: destroyed"); result = -EIO; } else { @@ -888,9 +888,8 @@ int ldlm_cli_enqueue(struct obd_export *exp, struct ptlrpc_request **reqp, } else { const struct ldlm_callback_suite cbs = { .lcs_completion = einfo->ei_cb_cp, - .lcs_blocking = einfo->ei_cb_bl, - .lcs_glimpse = einfo->ei_cb_gl, - .lcs_weigh = einfo->ei_cb_wg + .lcs_blocking = einfo->ei_cb_bl, + .lcs_glimpse = einfo->ei_cb_gl }; lock = ldlm_lock_create(ns, res_id, einfo->ei_type, einfo->ei_mode, &cbs, einfo->ei_cbdata, diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c index 17eab79ba839..616cb17efc30 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c @@ -1283,7 +1283,7 @@ void ldlm_resource_add_lock(struct ldlm_resource *res, struct list_head *head, LDLM_DEBUG(lock, "About to add this lock:\n"); - if (lock->l_destroyed) { + if (lock->l_flags & LDLM_FL_DESTROYED) { CDEBUG(D_OTHER, "Lock destroyed, not adding to resource\n"); return; } @@ -1308,7 +1308,7 @@ void ldlm_resource_insert_lock_after(struct ldlm_lock *original, ldlm_resource_dump(D_INFO, res); LDLM_DEBUG(new, "About to insert this lock after %p:\n", original); - if (new->l_destroyed) { + if (new->l_flags & LDLM_FL_DESTROYED) { CDEBUG(D_OTHER, "Lock destroyed, not adding to resource\n"); goto out; } diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index bfc914e4be08..a94e463f0498 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -356,15 +356,12 @@ struct page *ll_get_dir_page(struct inode *dir, __u64 hash, rc = md_lock_match(ll_i2sbi(dir)->ll_md_exp, LDLM_FL_BLOCK_GRANTED, ll_inode2fid(dir), LDLM_IBITS, &policy, mode, &lockh); if (!rc) { - struct ldlm_enqueue_info einfo = {.ei_type = LDLM_IBITS, - .ei_mode = mode, - .ei_cb_bl = - ll_md_blocking_ast, - .ei_cb_cp = - ldlm_completion_ast, - .ei_cb_gl = NULL, - .ei_cb_wg = NULL, - .ei_cbdata = NULL}; + struct ldlm_enqueue_info einfo = { + .ei_type = LDLM_IBITS, + .ei_mode = mode, + .ei_cb_bl = ll_md_blocking_ast, + .ei_cb_cp = ldlm_completion_ast, + }; struct lookup_intent it = { .it_op = IT_READDIR }; struct ptlrpc_request *request; struct md_op_data *op_data; diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 50ef6a587dc3..d51f1eee36e2 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -2290,9 +2290,11 @@ int ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock) { struct inode *inode = file->f_dentry->d_inode; struct ll_sb_info *sbi = ll_i2sbi(inode); - struct ldlm_enqueue_info einfo = { .ei_type = LDLM_FLOCK, - .ei_cb_cp =ldlm_flock_completion_ast, - .ei_cbdata = file_lock }; + struct ldlm_enqueue_info einfo = { + .ei_type = LDLM_FLOCK, + .ei_cb_cp = ldlm_flock_completion_ast, + .ei_cbdata = file_lock, + }; struct md_op_data *op_data; struct lustre_handle lockh = {0}; ldlm_policy_data_t flock = {{0}}; @@ -3116,11 +3118,12 @@ int ll_layout_refresh(struct inode *inode, __u32 *gen) struct lookup_intent it; struct lustre_handle lockh; ldlm_mode_t mode; - struct ldlm_enqueue_info einfo = { .ei_type = LDLM_IBITS, - .ei_mode = LCK_CR, - .ei_cb_bl = ll_md_blocking_ast, - .ei_cb_cp = ldlm_completion_ast, - .ei_cbdata = NULL }; + struct ldlm_enqueue_info einfo = { + .ei_type = LDLM_IBITS, + .ei_mode = LCK_CR, + .ei_cb_bl = ll_md_blocking_ast, + .ei_cb_cp = ldlm_completion_ast, + }; int rc; ENTRY; diff --git a/drivers/staging/lustre/lustre/mdc/mdc_locks.c b/drivers/staging/lustre/lustre/mdc/mdc_locks.c index 9532134e16c6..ab88a46c1a27 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_locks.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_locks.c @@ -1102,9 +1102,12 @@ int mdc_intent_lock(struct obd_export *exp, struct md_op_data *op_data, * this and use the request from revalidate. In this case, revalidate * never dropped its reference, so the refcounts are all OK */ if (!it_disposition(it, DISP_ENQ_COMPLETE)) { - struct ldlm_enqueue_info einfo = - { LDLM_IBITS, it_to_lock_mode(it), cb_blocking, - ldlm_completion_ast, NULL, NULL, NULL }; + struct ldlm_enqueue_info einfo = { + .ei_type = LDLM_IBITS, + .ei_mode = it_to_lock_mode(it), + .ei_cb_bl = cb_blocking, + .ei_cb_cp = ldlm_completion_ast, + }; /* For case if upper layer did not alloc fid, do it now. */ if (!fid_is_sane(&op_data->op_fid2) && it->it_op & IT_CREAT) { diff --git a/drivers/staging/lustre/lustre/mgc/mgc_request.c b/drivers/staging/lustre/lustre/mgc/mgc_request.c index c6c84d97ce4e..51677678fc75 100644 --- a/drivers/staging/lustre/lustre/mgc/mgc_request.c +++ b/drivers/staging/lustre/lustre/mgc/mgc_request.c @@ -900,8 +900,12 @@ static int mgc_enqueue(struct obd_export *exp, struct lov_stripe_md *lsm, struct lustre_handle *lockh) { struct config_llog_data *cld = (struct config_llog_data *)data; - struct ldlm_enqueue_info einfo = { type, mode, mgc_blocking_ast, - ldlm_completion_ast, NULL, NULL, NULL }; + struct ldlm_enqueue_info einfo = { + .ei_type = type, + .ei_mode = mode, + .ei_cb_bl = mgc_blocking_ast, + .ei_cb_cp = ldlm_completion_ast, + }; struct ptlrpc_request *req; int short_limit = cld_is_sptlrpc(cld); int rc; diff --git a/drivers/staging/lustre/lustre/osc/osc_lock.c b/drivers/staging/lustre/lustre/osc/osc_lock.c index 640bc3d34709..98478d24f9be 100644 --- a/drivers/staging/lustre/lustre/osc/osc_lock.c +++ b/drivers/staging/lustre/lustre/osc/osc_lock.c @@ -89,35 +89,49 @@ static struct ldlm_lock *osc_handle_ptr(struct lustre_handle *handle) */ static int osc_lock_invariant(struct osc_lock *ols) { - struct ldlm_lock *lock = osc_handle_ptr(&ols->ols_handle); - struct ldlm_lock *olock = ols->ols_lock; - int handle_used = lustre_handle_is_used(&ols->ols_handle); + struct ldlm_lock *lock = osc_handle_ptr(&ols->ols_handle); + struct ldlm_lock *olock = ols->ols_lock; + int handle_used = lustre_handle_is_used(&ols->ols_handle); - return - ergo(osc_lock_is_lockless(ols), - ols->ols_locklessable && ols->ols_lock == NULL) || - (ergo(olock != NULL, handle_used) && - ergo(olock != NULL, - olock->l_handle.h_cookie == ols->ols_handle.cookie) && - /* - * Check that ->ols_handle and ->ols_lock are consistent, but - * take into account that they are set at the different time. - */ - ergo(handle_used, - ergo(lock != NULL && olock != NULL, lock == olock) && - ergo(lock == NULL, olock == NULL)) && - ergo(ols->ols_state == OLS_CANCELLED, - olock == NULL && !handle_used) && - /* - * DLM lock is destroyed only after we have seen cancellation - * ast. - */ - ergo(olock != NULL && ols->ols_state < OLS_CANCELLED, - !olock->l_destroyed) && - ergo(ols->ols_state == OLS_GRANTED, - olock != NULL && - olock->l_req_mode == olock->l_granted_mode && - ols->ols_hold)); + if (ergo(osc_lock_is_lockless(ols), + ols->ols_locklessable && ols->ols_lock == NULL)) + return 1; + + /* + * If all the following "ergo"s are true, return 1, otherwise 0 + */ + if (! ergo(olock != NULL, handle_used)) + return 0; + + if (! ergo(olock != NULL, + olock->l_handle.h_cookie == ols->ols_handle.cookie)) + return 0; + + if (! ergo(handle_used, + ergo(lock != NULL && olock != NULL, lock == olock) && + ergo(lock == NULL, olock == NULL))) + return 0; + /* + * Check that ->ols_handle and ->ols_lock are consistent, but + * take into account that they are set at the different time. + */ + if (! ergo(ols->ols_state == OLS_CANCELLED, + olock == NULL && !handle_used)) + return 0; + /* + * DLM lock is destroyed only after we have seen cancellation + * ast. + */ + if (! ergo(olock != NULL && ols->ols_state < OLS_CANCELLED, + ((olock->l_flags & LDLM_FL_DESTROYED) == 0))) + return 0; + + if (! ergo(ols->ols_state == OLS_GRANTED, + olock != NULL && + olock->l_req_mode == olock->l_granted_mode && + ols->ols_hold)) + return 0; + return 1; } /***************************************************************************** @@ -261,7 +275,7 @@ static __u64 osc_enq2ldlm_flags(__u32 enqflags) if (enqflags & CEF_ASYNC) result |= LDLM_FL_HAS_INTENT; if (enqflags & CEF_DISCARD_DATA) - result |= LDLM_AST_DISCARD_DATA; + result |= LDLM_FL_AST_DISCARD_DATA; return result; } @@ -896,55 +910,6 @@ static unsigned long osc_lock_weigh(const struct lu_env *env, return cl_object_header(slice->cls_obj)->coh_pages; } -/** - * Get the weight of dlm lock for early cancellation. - * - * XXX: it should return the pages covered by this \a dlmlock. - */ -static unsigned long osc_ldlm_weigh_ast(struct ldlm_lock *dlmlock) -{ - struct cl_env_nest nest; - struct lu_env *env; - struct osc_lock *lock; - struct cl_lock *cll; - unsigned long weight; - ENTRY; - - might_sleep(); - /* - * osc_ldlm_weigh_ast has a complex context since it might be called - * because of lock canceling, or from user's input. We have to make - * a new environment for it. Probably it is implementation safe to use - * the upper context because cl_lock_put don't modify environment - * variables. But in case of .. - */ - env = cl_env_nested_get(&nest); - if (IS_ERR(env)) - /* Mostly because lack of memory, tend to eliminate this lock*/ - RETURN(0); - - LASSERT(dlmlock->l_resource->lr_type == LDLM_EXTENT); - lock = osc_ast_data_get(dlmlock); - if (lock == NULL) { - /* cl_lock was destroyed because of memory pressure. - * It is much reasonable to assign this type of lock - * a lower cost. - */ - GOTO(out, weight = 0); - } - - cll = lock->ols_cl.cls_lock; - cl_lock_mutex_get(env, cll); - weight = cl_lock_weigh(env, cll); - cl_lock_mutex_put(env, cll); - osc_ast_data_put(env, lock); - EXIT; - -out: - cl_env_nested_put(&nest, env); - return weight; -} - static void osc_lock_build_einfo(const struct lu_env *env, const struct cl_lock *clock, struct osc_lock *lock, @@ -966,7 +931,6 @@ static void osc_lock_build_einfo(const struct lu_env *env, einfo->ei_cb_bl = osc_ldlm_blocking_ast; einfo->ei_cb_cp = osc_ldlm_completion_ast; einfo->ei_cb_gl = osc_ldlm_glimpse_ast; - einfo->ei_cb_wg = osc_ldlm_weigh_ast; einfo->ei_cbdata = lock; /* value to be put into ->l_ast_data */ } From b62b9c0630a859bc5b6073b8449c9f5c178ece05 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Tue, 23 Jul 2013 00:06:38 +0800 Subject: [PATCH 0329/3400] staging/lustre/md: fix lu_ucred.c boilerplate In preparing Ie3a3cd99 (LU-1330 obdclass: splits server-side object stack from client) the lu_ucred infrastructure was put in its own file. Fixup the boilerplate of this file to give the proper path, short description, and authors. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-1330 Lustre-change: http://review.whamcloud.com/5910 Signed-off-by: John L. Hammond Reviewed-by: Fan Yong Reviewed-by: Vitaly Fertman Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/lu_ucred.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/lustre/lustre/obdclass/lu_ucred.c b/drivers/staging/lustre/lustre/obdclass/lu_ucred.c index 229db6c39b78..e23e545b0d66 100644 --- a/drivers/staging/lustre/lustre/obdclass/lu_ucred.c +++ b/drivers/staging/lustre/lustre/obdclass/lu_ucred.c @@ -33,13 +33,13 @@ * This file is part of Lustre, http://www.lustre.org/ * Lustre is a trademark of Sun Microsystems, Inc. * - * lustre/obdclass/lu_object.c + * lustre/obdclass/lu_ucred.c * - * Lustre Object. - * These are the only exported functions, they provide some generic - * infrastructure for managing object devices + * Lustre user credentials context infrastructure. * * Author: Nikita Danilov + * Author: Fan Yong + * Author: Vitaly Fertman */ #define DEBUG_SUBSYSTEM S_CLASS From 5dd16419919787eed5a3ade9f03a58ecfc9e8630 Mon Sep 17 00:00:00 2001 From: Jinshan Xiong Date: Tue, 23 Jul 2013 00:06:39 +0800 Subject: [PATCH 0330/3400] staging/lustre/layout: introduce new layout for released files Released files now have a standard layout (with generation, pool, ...) and a stripe count 0 and lmm_pattern flag LOV_PATTERN_F_RELEASED. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2482 Lustre-change: http://review.whamcloud.com/4816 Signed-off-by: Jinshan Xiong Signed-off-by: Johann Lombardi Reviewed-by: Keith Mannthey Reviewed-by: Fan Yong Reviewed-by: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../lustre/lustre/include/lustre/lustre_idl.h | 14 +++- drivers/staging/lustre/lustre/include/obd.h | 14 ++++ .../lustre/lustre/lclient/lcommon_cl.c | 2 +- drivers/staging/lustre/lustre/llite/file.c | 27 ++++--- .../staging/lustre/lustre/llite/llite_lib.c | 22 +++--- drivers/staging/lustre/lustre/llite/vvp_io.c | 10 ++- .../lustre/lustre/lov/lov_cl_internal.h | 11 ++- drivers/staging/lustre/lustre/lov/lov_ea.c | 23 +++++- drivers/staging/lustre/lustre/lov/lov_io.c | 34 +++++++++ drivers/staging/lustre/lustre/lov/lov_obd.c | 2 +- .../staging/lustre/lustre/lov/lov_object.c | 73 ++++++++++++++++--- drivers/staging/lustre/lustre/lov/lov_pack.c | 19 +++-- 12 files changed, 197 insertions(+), 54 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 4829419a75d3..30c03317fb6f 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -1546,10 +1546,16 @@ enum obdo_flags { #define LOV_MAGIC_V1_DEF 0x0CD10BD0 #define LOV_MAGIC_V3_DEF 0x0CD30BD0 -#define LOV_PATTERN_RAID0 0x001 /* stripes are used round-robin */ -#define LOV_PATTERN_RAID1 0x002 /* stripes are mirrors of each other */ -#define LOV_PATTERN_FIRST 0x100 /* first stripe is not in round-robin */ -#define LOV_PATTERN_CMOBD 0x200 +#define LOV_PATTERN_RAID0 0x001 /* stripes are used round-robin */ +#define LOV_PATTERN_RAID1 0x002 /* stripes are mirrors of each other */ +#define LOV_PATTERN_FIRST 0x100 /* first stripe is not in round-robin */ +#define LOV_PATTERN_CMOBD 0x200 + +#define LOV_PATTERN_F_MASK 0xffff0000 +#define LOV_PATTERN_F_RELEASED 0x80000000 /* HSM released file */ + +#define lov_pattern(pattern) (pattern & ~LOV_PATTERN_F_MASK) +#define lov_pattern_flags(pattern) (pattern & LOV_PATTERN_F_MASK) #define lov_ost_data lov_ost_data_v1 struct lov_ost_data_v1 { /* per-stripe data structure (little-endian)*/ diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 0a251fdfe167..11d10fe682d0 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -119,6 +119,20 @@ struct lov_stripe_md { #define lsm_stripe_count lsm_wire.lw_stripe_count #define lsm_pool_name lsm_wire.lw_pool_name +static inline bool lsm_is_released(struct lov_stripe_md *lsm) +{ + return !!(lsm->lsm_pattern & LOV_PATTERN_F_RELEASED); +} + +static inline bool lsm_has_objects(struct lov_stripe_md *lsm) +{ + if (lsm == NULL) + return false; + if (lsm_is_released(lsm)) + return false; + return true; +} + struct obd_info; typedef int (*obd_enqueue_update_f)(void *cookie, int rc); diff --git a/drivers/staging/lustre/lustre/lclient/lcommon_cl.c b/drivers/staging/lustre/lustre/lclient/lcommon_cl.c index 4a0166687f07..c8690cb7731d 100644 --- a/drivers/staging/lustre/lustre/lclient/lcommon_cl.c +++ b/drivers/staging/lustre/lustre/lclient/lcommon_cl.c @@ -1166,7 +1166,7 @@ int cl_file_inode_init(struct inode *inode, struct lustre_md *md) * locked by I_NEW bit. */ lli->lli_clob = clob; - lli->lli_has_smd = md->lsm != NULL; + lli->lli_has_smd = lsm_has_objects(md->lsm); lu_object_ref_add(&clob->co_lu, "inode", inode); } else result = PTR_ERR(clob); diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index d51f1eee36e2..549384582d49 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -1143,7 +1143,7 @@ static int ll_lov_recreate(struct inode *inode, struct ost_id *oi, RETURN(-ENOMEM); lsm = ccc_inode_lsm_get(inode); - if (lsm == NULL) + if (!lsm_has_objects(lsm)) GOTO(out, rc = -ENOENT); lsm_size = sizeof(*lsm) + (sizeof(struct lov_oinfo) * @@ -1299,6 +1299,12 @@ int ll_lov_getstripe_ea_info(struct inode *inode, const char *filename, * passing it to userspace. */ if (LOV_MAGIC != cpu_to_le32(LOV_MAGIC)) { + int stripe_count; + + stripe_count = le16_to_cpu(lmm->lmm_stripe_count); + if (le32_to_cpu(lmm->lmm_pattern) & LOV_PATTERN_F_RELEASED) + stripe_count = 0; + /* if function called for directory - we should * avoid swab not existent lsm objects */ if (lmm->lmm_magic == cpu_to_le32(LOV_MAGIC_V1)) { @@ -1306,13 +1312,13 @@ int ll_lov_getstripe_ea_info(struct inode *inode, const char *filename, if (S_ISREG(body->mode)) lustre_swab_lov_user_md_objects( ((struct lov_user_md_v1 *)lmm)->lmm_objects, - ((struct lov_user_md_v1 *)lmm)->lmm_stripe_count); + stripe_count); } else if (lmm->lmm_magic == cpu_to_le32(LOV_MAGIC_V3)) { lustre_swab_lov_user_md_v3((struct lov_user_md_v3 *)lmm); if (S_ISREG(body->mode)) lustre_swab_lov_user_md_objects( ((struct lov_user_md_v3 *)lmm)->lmm_objects, - ((struct lov_user_md_v3 *)lmm)->lmm_stripe_count); + stripe_count); } } @@ -1698,20 +1704,18 @@ int ll_data_version(struct inode *inode, __u64 *data_version, /* If no stripe, we consider version is 0. */ lsm = ccc_inode_lsm_get(inode); - if (lsm == NULL) { + if (!lsm_has_objects(lsm)) { *data_version = 0; CDEBUG(D_INODE, "No object for inode\n"); - RETURN(0); + GOTO(out, rc = 0); } OBD_ALLOC_PTR(obdo); - if (obdo == NULL) { - ccc_inode_lsm_put(inode, lsm); - RETURN(-ENOMEM); - } + if (obdo == NULL) + GOTO(out, rc = -ENOMEM); rc = ll_lsm_getattr(lsm, sbi->ll_dt_exp, NULL, obdo, 0, extent_lock); - if (!rc) { + if (rc == 0) { if (!(obdo->o_valid & OBD_MD_FLDATAVERSION)) rc = -EOPNOTSUPP; else @@ -1719,8 +1723,9 @@ int ll_data_version(struct inode *inode, __u64 *data_version, } OBD_FREE_PTR(obdo); + EXIT; +out: ccc_inode_lsm_put(inode, lsm); - RETURN(rc); } diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 1eb5779c1bda..b9cbe9505d4a 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -1282,13 +1282,6 @@ int ll_md_setattr(struct dentry *dentry, struct md_op_data *op_data, RETURN(rc); } - ia_valid = op_data->op_attr.ia_valid; - /* inode size will be in ll_setattr_ost, can't do it now since dirty - * cache is not cleared yet. */ - op_data->op_attr.ia_valid &= ~(TIMES_SET_FLAGS | ATTR_SIZE); - rc = simple_setattr(dentry, &op_data->op_attr); - op_data->op_attr.ia_valid = ia_valid; - /* Extract epoch data if obtained. */ op_data->op_handle = md.body->handle; op_data->op_ioepoch = md.body->ioepoch; @@ -1371,6 +1364,7 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr) struct ll_inode_info *lli = ll_i2info(inode); struct md_op_data *op_data = NULL; struct md_open_data *mod = NULL; + unsigned int valid = attr->ia_valid; int rc = 0, rc1 = 0; ENTRY; @@ -1482,6 +1476,13 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr) rc = ll_setattr_ost(inode, attr); EXIT; out: + if (rc == 0) { + /* Update inode attribute after dirty cache is cleaned + * by truncating OST objects. */ + attr->ia_valid |= ATTR_FORCE; + rc = simple_setattr(dentry, attr); + LASSERT(rc == 0); + } if (op_data) { if (op_data->op_ioepoch) { rc1 = ll_setattr_done_writing(inode, op_data, mod); @@ -1500,7 +1501,8 @@ out: ll_stats_ops_tally(ll_i2sbi(inode), (attr->ia_valid & ATTR_SIZE) ? LPROC_LL_TRUNC : LPROC_LL_SETATTR, 1); - return rc; + attr->ia_valid = valid; + RETURN(rc); } int ll_setattr(struct dentry *de, struct iattr *attr) @@ -1923,8 +1925,10 @@ int ll_iocontrol(struct inode *inode, struct file *file, inode->i_flags = ll_ext_to_inode_flags(flags); lsm = ccc_inode_lsm_get(inode); - if (lsm == NULL) + if (!lsm_has_objects(lsm)) { + ccc_inode_lsm_put(inode, lsm); RETURN(0); + } OBDO_ALLOC(oinfo.oi_oa); if (!oinfo.oi_oa) { diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index 20eac2fd63c3..23149f96f136 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -407,13 +407,15 @@ static int vvp_io_setattr_start(const struct lu_env *env, { struct cl_io *io = ios->cis_io; struct inode *inode = ccc_object_inode(io->ci_obj); + int result = 0; mutex_lock(&inode->i_mutex); if (cl_io_is_trunc(io)) - return vvp_io_setattr_trunc(env, ios, inode, - io->u.ci_setattr.sa_attr.lvb_size); - else - return vvp_io_setattr_time(env, ios); + result = vvp_io_setattr_trunc(env, ios, inode, + io->u.ci_setattr.sa_attr.lvb_size); + if (result == 0) + result = vvp_io_setattr_time(env, ios); + return result; } static void vvp_io_setattr_end(const struct lu_env *env, diff --git a/drivers/staging/lustre/lustre/lov/lov_cl_internal.h b/drivers/staging/lustre/lustre/lov/lov_cl_internal.h index 28801b8b5fdf..a82dfeab5921 100644 --- a/drivers/staging/lustre/lustre/lov/lov_cl_internal.h +++ b/drivers/staging/lustre/lustre/lov/lov_cl_internal.h @@ -162,10 +162,9 @@ struct lov_device { * Layout type. */ enum lov_layout_type { - /** empty file without body */ - LLT_EMPTY, - /** striped file */ - LLT_RAID0, + LLT_EMPTY, /** empty file without body (mknod + truncate) */ + LLT_RAID0, /** striped file */ + LLT_RELEASED, /** file with no objects (data in HSM) */ LLT_NR }; @@ -255,6 +254,8 @@ struct lov_object { } raid0; struct lov_layout_state_empty { } empty; + struct lov_layout_state_released { + } released; } u; /** * Thread that acquired lov_object::lo_type_guard in an exclusive @@ -582,6 +583,8 @@ int lov_io_init_raid0 (const struct lu_env *env, struct cl_object *obj, struct cl_io *io); int lov_io_init_empty (const struct lu_env *env, struct cl_object *obj, struct cl_io *io); +int lov_io_init_released(const struct lu_env *env, struct cl_object *obj, + struct cl_io *io); void lov_lock_unlink (const struct lu_env *env, struct lov_lock_link *link, struct lovsub_lock *sub); diff --git a/drivers/staging/lustre/lustre/lov/lov_ea.c b/drivers/staging/lustre/lustre/lov/lov_ea.c index 340dbcf829e8..e6c60151dc65 100644 --- a/drivers/staging/lustre/lustre/lov/lov_ea.c +++ b/drivers/staging/lustre/lustre/lov/lov_ea.c @@ -57,7 +57,7 @@ struct lovea_unpack_args { static int lsm_lmm_verify_common(struct lov_mds_md *lmm, int lmm_bytes, __u16 stripe_count) { - if (stripe_count == 0 || stripe_count > LOV_V1_INSANE_STRIPE_COUNT) { + if (stripe_count > LOV_V1_INSANE_STRIPE_COUNT) { CERROR("bad stripe count %d\n", stripe_count); lov_dump_lmm_common(D_WARNING, lmm); return -EINVAL; @@ -69,7 +69,7 @@ static int lsm_lmm_verify_common(struct lov_mds_md *lmm, int lmm_bytes, return -EINVAL; } - if (lmm->lmm_pattern != cpu_to_le32(LOV_PATTERN_RAID0)) { + if (lov_pattern(le32_to_cpu(lmm->lmm_pattern)) != LOV_PATTERN_RAID0) { CERROR("bad striping pattern\n"); lov_dump_lmm_common(D_WARNING, lmm); return -EINVAL; @@ -197,6 +197,8 @@ static int lsm_lmm_verify_v1(struct lov_mds_md_v1 *lmm, int lmm_bytes, } *stripe_count = le16_to_cpu(lmm->lmm_stripe_count); + if (le32_to_cpu(lmm->lmm_pattern) & LOV_PATTERN_F_RELEASED) + *stripe_count = 0; if (lmm_bytes < lov_mds_md_size(*stripe_count, LOV_MAGIC_V1)) { CERROR("LOV EA V1 too small: %d, need %d\n", @@ -213,11 +215,14 @@ int lsm_unpackmd_v1(struct lov_obd *lov, struct lov_stripe_md *lsm, { struct lov_oinfo *loi; int i; + int stripe_count; __u64 stripe_maxbytes = OBD_OBJECT_EOF; lsm_unpackmd_common(lsm, lmm); - for (i = 0; i < lsm->lsm_stripe_count; i++) { + stripe_count = lsm_is_released(lsm) ? 0 : lsm->lsm_stripe_count; + + for (i = 0; i < stripe_count; i++) { /* XXX LOV STACKING call down to osc_unpackmd() */ loi = lsm->lsm_oinfo[i]; ostid_le_to_cpu(&lmm->lmm_objects[i].l_ost_oi, &loi->loi_oi); @@ -240,6 +245,8 @@ int lsm_unpackmd_v1(struct lov_obd *lov, struct lov_stripe_md *lsm, } lsm->lsm_maxbytes = stripe_maxbytes * lsm->lsm_stripe_count; + if (lsm->lsm_stripe_count == 0) + lsm->lsm_maxbytes = stripe_maxbytes * lov->desc.ld_tgt_count; return 0; } @@ -267,6 +274,8 @@ static int lsm_lmm_verify_v3(struct lov_mds_md *lmmv1, int lmm_bytes, } *stripe_count = le16_to_cpu(lmm->lmm_stripe_count); + if (le32_to_cpu(lmm->lmm_pattern) & LOV_PATTERN_F_RELEASED) + *stripe_count = 0; if (lmm_bytes < lov_mds_md_size(*stripe_count, LOV_MAGIC_V3)) { CERROR("LOV EA V3 too small: %d, need %d\n", @@ -285,18 +294,22 @@ int lsm_unpackmd_v3(struct lov_obd *lov, struct lov_stripe_md *lsm, struct lov_mds_md_v3 *lmm; struct lov_oinfo *loi; int i; + int stripe_count; __u64 stripe_maxbytes = OBD_OBJECT_EOF; int cplen = 0; lmm = (struct lov_mds_md_v3 *)lmmv1; lsm_unpackmd_common(lsm, (struct lov_mds_md_v1 *)lmm); + + stripe_count = lsm_is_released(lsm) ? 0 : lsm->lsm_stripe_count; + cplen = strlcpy(lsm->lsm_pool_name, lmm->lmm_pool_name, sizeof(lsm->lsm_pool_name)); if (cplen >= sizeof(lsm->lsm_pool_name)) return -E2BIG; - for (i = 0; i < lsm->lsm_stripe_count; i++) { + for (i = 0; i < stripe_count; i++) { /* XXX LOV STACKING call down to osc_unpackmd() */ loi = lsm->lsm_oinfo[i]; ostid_le_to_cpu(&lmm->lmm_objects[i].l_ost_oi, &loi->loi_oi); @@ -319,6 +332,8 @@ int lsm_unpackmd_v3(struct lov_obd *lov, struct lov_stripe_md *lsm, } lsm->lsm_maxbytes = stripe_maxbytes * lsm->lsm_stripe_count; + if (lsm->lsm_stripe_count == 0) + lsm->lsm_maxbytes = stripe_maxbytes * lov->desc.ld_tgt_count; return 0; } diff --git a/drivers/staging/lustre/lustre/lov/lov_io.c b/drivers/staging/lustre/lustre/lov/lov_io.c index 022e0f4911c6..e78cdb7633ca 100644 --- a/drivers/staging/lustre/lustre/lov/lov_io.c +++ b/drivers/staging/lustre/lustre/lov/lov_io.c @@ -964,4 +964,38 @@ int lov_io_init_empty(const struct lu_env *env, struct cl_object *obj, RETURN(result != 0); } +int lov_io_init_released(const struct lu_env *env, struct cl_object *obj, + struct cl_io *io) +{ + struct lov_object *lov = cl2lov(obj); + struct lov_io *lio = lov_env_io(env); + int result; + ENTRY; + + LASSERT(lov->lo_lsm != NULL); + lio->lis_object = lov; + + switch (io->ci_type) { + default: + LASSERTF(0, "invalid type %d\n", io->ci_type); + case CIT_MISC: + case CIT_FSYNC: + case CIT_SETATTR: + result = +1; + break; + case CIT_READ: + case CIT_WRITE: + case CIT_FAULT: + /* TODO: need to restore the file. */ + result = -EBADF; + break; + } + if (result == 0) { + cl_io_slice_add(io, &lio->lis_cl, obj, &lov_empty_io_ops); + atomic_inc(&lov->lo_active_ios); + } + + io->ci_result = result < 0 ? result : 0; + RETURN(result != 0); +} /** @} lov */ diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c index ef7ff091f048..0a9e40de8fae 100644 --- a/drivers/staging/lustre/lustre/lov/lov_obd.c +++ b/drivers/staging/lustre/lustre/lov/lov_obd.c @@ -2259,7 +2259,7 @@ static int lov_fiemap(struct lov_obd *lov, __u32 keylen, void *key, int cur_stripe = 0, cur_stripe_wrap = 0, stripe_count; unsigned int buffer_size = FIEMAP_BUFFER_SIZE; - if (lsm == NULL) + if (!lsm_has_objects(lsm)) GOTO(out, rc = 0); if (fiemap_count_to_size(fm_key->fiemap.fm_extent_count) < buffer_size) diff --git a/drivers/staging/lustre/lustre/lov/lov_object.c b/drivers/staging/lustre/lustre/lov/lov_object.c index aa8ae80e8121..e7cc6502237f 100644 --- a/drivers/staging/lustre/lustre/lov/lov_object.c +++ b/drivers/staging/lustre/lustre/lov/lov_object.c @@ -258,10 +258,25 @@ out: RETURN(result); } +static int lov_init_released(const struct lu_env *env, + struct lov_device *dev, struct lov_object *lov, + const struct cl_object_conf *conf, + union lov_layout_state *state) +{ + struct lov_stripe_md *lsm = conf->u.coc_md->lsm; + + LASSERT(lsm != NULL); + LASSERT(lsm_is_released(lsm)); + LASSERT(lov->lo_lsm == NULL); + + lov->lo_lsm = lsm_addref(lsm); + return 0; +} + static int lov_delete_empty(const struct lu_env *env, struct lov_object *lov, union lov_layout_state *state) { - LASSERT(lov->lo_type == LLT_EMPTY); + LASSERT(lov->lo_type == LLT_EMPTY || lov->lo_type == LLT_RELEASED); lov_layout_wait(env, lov); @@ -349,7 +364,7 @@ static int lov_delete_raid0(const struct lu_env *env, struct lov_object *lov, static void lov_fini_empty(const struct lu_env *env, struct lov_object *lov, union lov_layout_state *state) { - LASSERT(lov->lo_type == LLT_EMPTY); + LASSERT(lov->lo_type == LLT_EMPTY || lov->lo_type == LLT_RELEASED); } static void lov_fini_raid0(const struct lu_env *env, struct lov_object *lov, @@ -369,6 +384,15 @@ static void lov_fini_raid0(const struct lu_env *env, struct lov_object *lov, EXIT; } +static void lov_fini_released(const struct lu_env *env, struct lov_object *lov, + union lov_layout_state *state) +{ + ENTRY; + dump_lsm(D_INODE, lov->lo_lsm); + lov_free_memmd(&lov->lo_lsm); + EXIT; +} + static int lov_print_empty(const struct lu_env *env, void *cookie, lu_printer_t p, const struct lu_object *o) { @@ -400,6 +424,13 @@ static int lov_print_raid0(const struct lu_env *env, void *cookie, return 0; } +static int lov_print_released(const struct lu_env *env, void *cookie, + lu_printer_t p, const struct lu_object *o) +{ + (*p)(env, cookie, "released\n"); + return 0; +} + /** * Implements cl_object_operations::coo_attr_get() method for an object * without stripes (LLT_EMPTY layout type). @@ -503,10 +534,20 @@ const static struct lov_layout_operations lov_dispatch[] = { .llo_lock_init = lov_lock_init_raid0, .llo_io_init = lov_io_init_raid0, .llo_getattr = lov_attr_get_raid0 + }, + [LLT_RELEASED] = { + .llo_init = lov_init_released, + .llo_delete = lov_delete_empty, + .llo_fini = lov_fini_released, + .llo_install = lov_install_empty, + .llo_print = lov_print_released, + .llo_page_init = lov_page_init_empty, + .llo_lock_init = lov_lock_init_empty, + .llo_io_init = lov_io_init_released, + .llo_getattr = lov_attr_get_empty } }; - /** * Performs a double-dispatch based on the layout type of an object. */ @@ -520,6 +561,18 @@ const static struct lov_layout_operations lov_dispatch[] = { lov_dispatch[__llt].op(__VA_ARGS__); \ }) +/** + * Return lov_layout_type associated with a given lsm + */ +enum lov_layout_type lov_type(struct lov_stripe_md *lsm) +{ + if (lsm == NULL) + return LLT_EMPTY; + if (lsm_is_released(lsm)) + return LLT_RELEASED; + return LLT_RAID0; +} + static inline void lov_conf_freeze(struct lov_object *lov) { if (lov->lo_owner != current) @@ -612,8 +665,8 @@ static int lov_layout_change(const struct lu_env *unused, LASSERT(0 <= lov->lo_type && lov->lo_type < ARRAY_SIZE(lov_dispatch)); - if (conf->u.coc_md != NULL && conf->u.coc_md->lsm != NULL) - llt = LLT_RAID0; /* only raid0 is supported. */ + if (conf->u.coc_md != NULL) + llt = lov_type(conf->u.coc_md->lsm); LASSERT(0 <= llt && llt < ARRAY_SIZE(lov_dispatch)); cookie = cl_env_reenter(); @@ -658,7 +711,6 @@ static int lov_layout_change(const struct lu_env *unused, * Lov object operations. * */ - int lov_object_init(const struct lu_env *env, struct lu_object *obj, const struct lu_object_conf *conf) { @@ -677,7 +729,7 @@ int lov_object_init(const struct lu_env *env, struct lu_object *obj, cl_object_page_init(lu2cl(obj), sizeof(struct lov_page)); /* no locking is necessary, as object is being created */ - lov->lo_type = cconf->u.coc_md->lsm != NULL ? LLT_RAID0 : LLT_EMPTY; + lov->lo_type = lov_type(cconf->u.coc_md->lsm); ops = &lov_dispatch[lov->lo_type]; result = ops->llo_init(env, dev, lov, cconf, set); if (result == 0) @@ -688,9 +740,9 @@ int lov_object_init(const struct lu_env *env, struct lu_object *obj, static int lov_conf_set(const struct lu_env *env, struct cl_object *obj, const struct cl_object_conf *conf) { - struct lov_stripe_md *lsm = NULL; - struct lov_object *lov = cl2lov(obj); - int result = 0; + struct lov_stripe_md *lsm = NULL; + struct lov_object *lov = cl2lov(obj); + int result = 0; ENTRY; lov_conf_lock(lov); @@ -928,6 +980,7 @@ int lov_read_and_clear_async_rc(struct cl_object *clob) loi->loi_ar.ar_rc = 0; } } + case LLT_RELEASED: case LLT_EMPTY: break; default: diff --git a/drivers/staging/lustre/lustre/lov/lov_pack.c b/drivers/staging/lustre/lustre/lov/lov_pack.c index 492948aad685..9c99e4a2c5d8 100644 --- a/drivers/staging/lustre/lustre/lov/lov_pack.c +++ b/drivers/staging/lustre/lustre/lov/lov_pack.c @@ -168,10 +168,12 @@ int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmmp, * to the actual number of OSTs in this filesystem. */ if (!lmmp) { stripe_count = lov_get_stripecnt(lov, lmm_magic, - lsm->lsm_stripe_count); + lsm->lsm_stripe_count); lsm->lsm_stripe_count = stripe_count; - } else { + } else if (!lsm_is_released(lsm)) { stripe_count = lsm->lsm_stripe_count; + } else { + stripe_count = 0; } } else { /* No need to allocate more than maximum supported stripes. @@ -325,7 +327,8 @@ int lov_alloc_memmd(struct lov_stripe_md **lsmp, __u16 stripe_count, (*lsmp)->lsm_pattern = pattern; (*lsmp)->lsm_pool_name[0] = '\0'; (*lsmp)->lsm_layout_gen = 0; - (*lsmp)->lsm_oinfo[0]->loi_ost_idx = ~0; + if (stripe_count > 0) + (*lsmp)->lsm_oinfo[0]->loi_ost_idx = ~0; for (i = 0; i < stripe_count; i++) loi_init((*lsmp)->lsm_oinfo[i]); @@ -359,6 +362,7 @@ int lov_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, int rc = 0, lsm_size; __u16 stripe_count; __u32 magic; + __u32 pattern; ENTRY; /* If passed an MDS struct use values from there, otherwise defaults */ @@ -384,8 +388,8 @@ int lov_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, RETURN(0); } - lsm_size = lov_alloc_memmd(lsmp, stripe_count, LOV_PATTERN_RAID0, - magic); + pattern = le32_to_cpu(lmm->lmm_pattern); + lsm_size = lov_alloc_memmd(lsmp, stripe_count, pattern, magic); if (lsm_size < 0) RETURN(lsm_size); @@ -430,7 +434,7 @@ static int __lov_setstripe(struct obd_export *exp, int max_lmm_size, lov->desc.ld_pattern : LOV_PATTERN_RAID0; } - if (lumv1->lmm_pattern != LOV_PATTERN_RAID0) { + if (lov_pattern(lumv1->lmm_pattern) != LOV_PATTERN_RAID0) { CDEBUG(D_IOCTL, "bad userland stripe pattern: %#x\n", lumv1->lmm_pattern); RETURN(-EINVAL); @@ -490,6 +494,9 @@ static int __lov_setstripe(struct obd_export *exp, int max_lmm_size, } } + if (lumv1->lmm_pattern & LOV_PATTERN_F_RELEASED) + stripe_count = 0; + rc = lov_alloc_memmd(lsmp, stripe_count, lumv1->lmm_pattern, lmm_magic); if (rc >= 0) { From 001f54878a57a95dd373a7071693173b66ba999c Mon Sep 17 00:00:00 2001 From: jcl Date: Tue, 23 Jul 2013 00:06:40 +0800 Subject: [PATCH 0331/3400] staging/lustre/mdt: add macros for fid string len add 2 macros for the length of a fid string 0xSEQ:0xOID:0xVER and it's brace version (FID_NOBRACE_LEN, and FID_LEN) Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2782 Lustre-change: http://review.whamcloud.com/5299 Signed-off-by: JC Lafoucriere Reviewed-by: Jinshan Xiong Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lustre/lustre_user.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index 7e9f57507f04..f72b2e4cbca1 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -462,6 +462,8 @@ static inline void obd_uuid2fsname(char *buf, char *uuid, int buflen) /* printf display format e.g. printf("file FID is "DFID"\n", PFID(fid)); */ +#define FID_NOBRACE_LEN 40 +#define FID_LEN (FID_NOBRACE_LEN + 2) #define DFID_NOBRACE LPX64":0x%x:0x%x" #define DFID "["DFID_NOBRACE"]" #define PFID(fid) \ From bc06a6785041fd4948bf25c5d3ac3db3c9b13bbf Mon Sep 17 00:00:00 2001 From: jcl Date: Tue, 23 Jul 2013 00:06:41 +0800 Subject: [PATCH 0332/3400] staging/lustre/llapi: add user space method for lov_user_md move lov_mds_md_size from obd_lov.h to lustre_idl.h to have it close to lov_mds_md definition. add lov_user_md_size() to compute lum size so llapi and user space utils do not use kernel internal definitions/methods Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3345 Lustre-change: http://review.whamcloud.com/6345 Signed-off-by: JC Lafoucriere Reviewed-by: Jinshan Xiong Reviewed-by: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/include/lustre/lustre_idl.h | 11 +++++++++++ .../lustre/lustre/include/lustre/lustre_user.h | 10 ++++++++++ drivers/staging/lustre/lustre/include/obd_lov.h | 10 ---------- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 30c03317fb6f..ace4e18dfae8 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -1670,6 +1670,17 @@ struct lov_mds_md_v3 { /* LOV EA mds/wire data (little-endian) */ struct lov_ost_data_v1 lmm_objects[0]; /* per-stripe data */ }; +static inline __u32 lov_mds_md_size(__u16 stripes, __u32 lmm_magic) +{ + if (lmm_magic == LOV_MAGIC_V3) + return sizeof(struct lov_mds_md_v3) + + stripes * sizeof(struct lov_ost_data_v1); + else + return sizeof(struct lov_mds_md_v1) + + stripes * sizeof(struct lov_ost_data_v1); +} + + #define OBD_MD_FLID (0x00000001ULL) /* object ID */ #define OBD_MD_FLATIME (0x00000002ULL) /* access time */ #define OBD_MD_FLMTIME (0x00000004ULL) /* data modification time */ diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h index f72b2e4cbca1..c7bd4473a1d0 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h @@ -347,6 +347,16 @@ struct lov_user_md_v3 { /* LOV EA user data (host-endian) */ struct lov_user_ost_data_v1 lmm_objects[0]; /* per-stripe data */ } __attribute__((packed)); +static inline __u32 lov_user_md_size(__u16 stripes, __u32 lmm_magic) +{ + if (lmm_magic == LOV_USER_MAGIC_V3) + return sizeof(struct lov_user_md_v3) + + stripes * sizeof(struct lov_user_ost_data_v1); + else + return sizeof(struct lov_user_md_v1) + + stripes * sizeof(struct lov_user_ost_data_v1); +} + /* Compile with -D_LARGEFILE64_SOURCE or -D_GNU_SOURCE (or #define) to * use this. It is unsafe to #define those values in this header as it * is possible the application has already #included . */ diff --git a/drivers/staging/lustre/lustre/include/obd_lov.h b/drivers/staging/lustre/lustre/include/obd_lov.h index d82f3341d0a8..235718b366dc 100644 --- a/drivers/staging/lustre/lustre/include/obd_lov.h +++ b/drivers/staging/lustre/lustre/include/obd_lov.h @@ -44,16 +44,6 @@ static inline int lov_stripe_md_size(__u16 stripes) return sizeof(struct lov_stripe_md) + stripes*sizeof(struct lov_oinfo*); } -static inline __u32 lov_mds_md_size(__u16 stripes, __u32 lmm_magic) -{ - if (lmm_magic == LOV_MAGIC_V3) - return sizeof(struct lov_mds_md_v3) + - stripes * sizeof(struct lov_ost_data_v1); - else - return sizeof(struct lov_mds_md_v1) + - stripes * sizeof(struct lov_ost_data_v1); -} - struct lov_version_size { __u32 lvs_magic; size_t lvs_lmm_size; From 353471a6bd906e3d4674b143be31ad51c2de134e Mon Sep 17 00:00:00 2001 From: Sebastien Buisson Date: Tue, 23 Jul 2013 00:06:43 +0800 Subject: [PATCH 0333/3400] staging/lustre: fix 'code maintainability' errors Fix 'code maintainability' issues found by Coverity version 6.5.1: Unused pointer value (UNUSED_VALUE) Pointer returned by function is never used. Missing varargs init or cleanup (VARARGS) va_end was not called for variable. Signed-off-by: Sebastien Buisson Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3107 Lustre-change: http://review.whamcloud.com/5944 Reviewed-by: Dmitry Eremin Reviewed-by: John Hammond Reviewed-by: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/lprocfs_jobstats.c | 2 -- drivers/staging/lustre/lustre/ptlrpc/pack_generic.c | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_jobstats.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_jobstats.c index e2d57fef0da3..7f6072c4b7f8 100644 --- a/drivers/staging/lustre/lustre/obdclass/lprocfs_jobstats.c +++ b/drivers/staging/lustre/lustre/obdclass/lprocfs_jobstats.c @@ -366,7 +366,6 @@ static int lprocfs_jobstats_seq_show(struct seq_file *p, void *v) struct job_stat *job = v; struct lprocfs_stats *s; struct lprocfs_counter ret; - struct lprocfs_counter *cntr; struct lprocfs_counter_header *cntr_header; int i; @@ -380,7 +379,6 @@ static int lprocfs_jobstats_seq_show(struct seq_file *p, void *v) s = job->js_stats; for (i = 0; i < s->ls_num; i++) { - cntr = lprocfs_stats_counter_get(s, 0, i); cntr_header = &s->ls_cnt_header[i]; lprocfs_stats_collect(s, i, &ret); diff --git a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c index be246d491886..ffff64833557 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c @@ -2462,6 +2462,7 @@ void _debug_req(struct ptlrpc_request *req, rep_ok ? lustre_msg_get_flags(req->rq_repmsg) : -1, req->rq_status, rep_ok ? lustre_msg_get_status(req->rq_repmsg) : -1); + va_end(args); } EXPORT_SYMBOL(_debug_req); From 56f4c5a8a5f84a360943b17d7cb531c161d4e9bd Mon Sep 17 00:00:00 2001 From: Liu Xuezhao Date: Tue, 23 Jul 2013 00:06:44 +0800 Subject: [PATCH 0334/3400] staging/lustre/fid: prepare FID module for client server split Split FID server from client, fid_{handler,store,lib}.c are not compliled unless server support is enabled. Generally cleanup includes in lustre/fid/ and reduce the need for client code to directly or indirectly include {dt,md}_object.h. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-1330 Lustre-change: http://review.whamcloud.com/2673 Signed-off-by: Liu Xuezhao Signed-off-by: John L. Hammond Reviewed-by: Andreas Dilger Reviewed-by: Nathaniel Clark Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/fid/Makefile | 2 +- .../staging/lustre/lustre/fid/fid_handler.c | 661 ------------------ .../staging/lustre/lustre/fid/fid_internal.h | 36 +- drivers/staging/lustre/lustre/fid/fid_lib.c | 14 +- .../staging/lustre/lustre/fid/fid_request.c | 133 +++- drivers/staging/lustre/lustre/fid/fid_store.c | 259 ------- drivers/staging/lustre/lustre/fid/lproc_fid.c | 3 - .../staging/lustre/lustre/include/lu_object.h | 5 + .../lustre/lustre/include/lustre_fid.h | 24 +- .../staging/lustre/lustre/include/md_object.h | 5 - drivers/staging/lustre/lustre/include/obd.h | 7 +- 11 files changed, 131 insertions(+), 1018 deletions(-) delete mode 100644 drivers/staging/lustre/lustre/fid/fid_handler.c delete mode 100644 drivers/staging/lustre/lustre/fid/fid_store.c diff --git a/drivers/staging/lustre/lustre/fid/Makefile b/drivers/staging/lustre/lustre/fid/Makefile index b8d6d21b39ff..ed21bea162ba 100644 --- a/drivers/staging/lustre/lustre/fid/Makefile +++ b/drivers/staging/lustre/lustre/fid/Makefile @@ -1,5 +1,5 @@ obj-$(CONFIG_LUSTRE_FS) += fid.o -fid-y := fid_handler.o fid_store.o fid_request.o lproc_fid.o fid_lib.o +fid-y := fid_request.o lproc_fid.o fid_lib.o ccflags-y := -I$(src)/../include diff --git a/drivers/staging/lustre/lustre/fid/fid_handler.c b/drivers/staging/lustre/lustre/fid/fid_handler.c deleted file mode 100644 index bbbb3cfe57b3..000000000000 --- a/drivers/staging/lustre/lustre/fid/fid_handler.c +++ /dev/null @@ -1,661 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * 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 version 2 for more details (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - * - * GPL HEADER END - */ -/* - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Use is subject to license terms. - * - * Copyright (c) 2011, 2012, Intel Corporation. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - * - * lustre/fid/fid_handler.c - * - * Lustre Sequence Manager - * - * Author: Yury Umanets - */ - -#define DEBUG_SUBSYSTEM S_FID - -# include -# include - -#include -#include -#include -#include -#include -#include -#include -#include "fid_internal.h" - -int client_fid_init(struct obd_device *obd, - struct obd_export *exp, enum lu_cli_type type) -{ - struct client_obd *cli = &obd->u.cli; - char *prefix; - int rc; - ENTRY; - - OBD_ALLOC_PTR(cli->cl_seq); - if (cli->cl_seq == NULL) - RETURN(-ENOMEM); - - OBD_ALLOC(prefix, MAX_OBD_NAME + 5); - if (prefix == NULL) - GOTO(out_free_seq, rc = -ENOMEM); - - snprintf(prefix, MAX_OBD_NAME + 5, "cli-%s", obd->obd_name); - - /* Init client side sequence-manager */ - rc = seq_client_init(cli->cl_seq, exp, type, prefix, NULL); - OBD_FREE(prefix, MAX_OBD_NAME + 5); - if (rc) - GOTO(out_free_seq, rc); - - RETURN(rc); -out_free_seq: - OBD_FREE_PTR(cli->cl_seq); - cli->cl_seq = NULL; - return rc; -} -EXPORT_SYMBOL(client_fid_init); - -int client_fid_fini(struct obd_device *obd) -{ - struct client_obd *cli = &obd->u.cli; - ENTRY; - - if (cli->cl_seq != NULL) { - seq_client_fini(cli->cl_seq); - OBD_FREE_PTR(cli->cl_seq); - cli->cl_seq = NULL; - } - - RETURN(0); -} -EXPORT_SYMBOL(client_fid_fini); - -static void seq_server_proc_fini(struct lu_server_seq *seq); - -/* Assigns client to sequence controller node. */ -int seq_server_set_cli(struct lu_server_seq *seq, - struct lu_client_seq *cli, - const struct lu_env *env) -{ - int rc = 0; - ENTRY; - - /* - * Ask client for new range, assign that range to ->seq_space and write - * seq state to backing store should be atomic. - */ - mutex_lock(&seq->lss_mutex); - - if (cli == NULL) { - CDEBUG(D_INFO, "%s: Detached sequence client %s\n", - seq->lss_name, cli->lcs_name); - seq->lss_cli = cli; - GOTO(out_up, rc = 0); - } - - if (seq->lss_cli != NULL) { - CDEBUG(D_HA, "%s: Sequence controller is already " - "assigned\n", seq->lss_name); - GOTO(out_up, rc = -EEXIST); - } - - CDEBUG(D_INFO, "%s: Attached sequence controller %s\n", - seq->lss_name, cli->lcs_name); - - seq->lss_cli = cli; - cli->lcs_space.lsr_index = seq->lss_site->ss_node_id; - EXIT; -out_up: - mutex_unlock(&seq->lss_mutex); - return rc; -} -EXPORT_SYMBOL(seq_server_set_cli); -/* - * allocate \a w units of sequence from range \a from. - */ -static inline void range_alloc(struct lu_seq_range *to, - struct lu_seq_range *from, - __u64 width) -{ - width = min(range_space(from), width); - to->lsr_start = from->lsr_start; - to->lsr_end = from->lsr_start + width; - from->lsr_start += width; -} - -/** - * On controller node, allocate new super sequence for regular sequence server. - * As this super sequence controller, this node suppose to maintain fld - * and update index. - * \a out range always has currect mds node number of requester. - */ - -static int __seq_server_alloc_super(struct lu_server_seq *seq, - struct lu_seq_range *out, - const struct lu_env *env) -{ - struct lu_seq_range *space = &seq->lss_space; - int rc; - ENTRY; - - LASSERT(range_is_sane(space)); - - if (range_is_exhausted(space)) { - CERROR("%s: Sequences space is exhausted\n", - seq->lss_name); - RETURN(-ENOSPC); - } else { - range_alloc(out, space, seq->lss_width); - } - - rc = seq_store_update(env, seq, out, 1 /* sync */); - - LCONSOLE_INFO("%s: super-sequence allocation rc = %d " DRANGE"\n", - seq->lss_name, rc, PRANGE(out)); - - RETURN(rc); -} - -int seq_server_alloc_super(struct lu_server_seq *seq, - struct lu_seq_range *out, - const struct lu_env *env) -{ - int rc; - ENTRY; - - mutex_lock(&seq->lss_mutex); - rc = __seq_server_alloc_super(seq, out, env); - mutex_unlock(&seq->lss_mutex); - - RETURN(rc); -} - -static int __seq_set_init(const struct lu_env *env, - struct lu_server_seq *seq) -{ - struct lu_seq_range *space = &seq->lss_space; - int rc; - - range_alloc(&seq->lss_lowater_set, space, seq->lss_set_width); - range_alloc(&seq->lss_hiwater_set, space, seq->lss_set_width); - - rc = seq_store_update(env, seq, NULL, 1); - - return rc; -} - -/* - * This function implements new seq allocation algorithm using async - * updates to seq file on disk. ref bug 18857 for details. - * there are four variable to keep track of this process - * - * lss_space; - available lss_space - * lss_lowater_set; - lu_seq_range for all seqs before barrier, i.e. safe to use - * lss_hiwater_set; - lu_seq_range after barrier, i.e. allocated but may be - * not yet committed - * - * when lss_lowater_set reaches the end it is replaced with hiwater one and - * a write operation is initiated to allocate new hiwater range. - * if last seq write opearion is still not commited, current operation is - * flaged as sync write op. - */ -static int range_alloc_set(const struct lu_env *env, - struct lu_seq_range *out, - struct lu_server_seq *seq) -{ - struct lu_seq_range *space = &seq->lss_space; - struct lu_seq_range *loset = &seq->lss_lowater_set; - struct lu_seq_range *hiset = &seq->lss_hiwater_set; - int rc = 0; - - if (range_is_zero(loset)) - __seq_set_init(env, seq); - - if (OBD_FAIL_CHECK(OBD_FAIL_SEQ_ALLOC)) /* exhaust set */ - loset->lsr_start = loset->lsr_end; - - if (range_is_exhausted(loset)) { - /* reached high water mark. */ - struct lu_device *dev = seq->lss_site->ss_lu->ls_top_dev; - int obd_num_clients = dev->ld_obd->obd_num_exports; - __u64 set_sz; - - /* calculate new seq width based on number of clients */ - set_sz = max(seq->lss_set_width, - obd_num_clients * seq->lss_width); - set_sz = min(range_space(space), set_sz); - - /* Switch to hiwater range now */ - *loset = *hiset; - /* allocate new hiwater range */ - range_alloc(hiset, space, set_sz); - - /* update ondisk seq with new *space */ - rc = seq_store_update(env, seq, NULL, seq->lss_need_sync); - } - - LASSERTF(!range_is_exhausted(loset) || range_is_sane(loset), - DRANGE"\n", PRANGE(loset)); - - if (rc == 0) - range_alloc(out, loset, seq->lss_width); - - RETURN(rc); -} - -static int __seq_server_alloc_meta(struct lu_server_seq *seq, - struct lu_seq_range *out, - const struct lu_env *env) -{ - struct lu_seq_range *space = &seq->lss_space; - int rc = 0; - - ENTRY; - - LASSERT(range_is_sane(space)); - - /* Check if available space ends and allocate new super seq */ - if (range_is_exhausted(space)) { - if (!seq->lss_cli) { - CERROR("%s: No sequence controller is attached.\n", - seq->lss_name); - RETURN(-ENODEV); - } - - rc = seq_client_alloc_super(seq->lss_cli, env); - if (rc) { - CERROR("%s: Can't allocate super-sequence, rc %d\n", - seq->lss_name, rc); - RETURN(rc); - } - - /* Saving new range to allocation space. */ - *space = seq->lss_cli->lcs_space; - LASSERT(range_is_sane(space)); - } - - rc = range_alloc_set(env, out, seq); - if (rc != 0) { - CERROR("%s: Allocated meta-sequence failed: rc = %d\n", - seq->lss_name, rc); - RETURN(rc); - } - - CDEBUG(D_INFO, "%s: Allocated meta-sequence " DRANGE"\n", - seq->lss_name, PRANGE(out)); - - RETURN(rc); -} - -int seq_server_alloc_meta(struct lu_server_seq *seq, - struct lu_seq_range *out, - const struct lu_env *env) -{ - int rc; - ENTRY; - - mutex_lock(&seq->lss_mutex); - rc = __seq_server_alloc_meta(seq, out, env); - mutex_unlock(&seq->lss_mutex); - - RETURN(rc); -} -EXPORT_SYMBOL(seq_server_alloc_meta); - -static int seq_server_handle(struct lu_site *site, - const struct lu_env *env, - __u32 opc, struct lu_seq_range *out) -{ - int rc; - struct seq_server_site *ss_site; - ENTRY; - - ss_site = lu_site2seq(site); - - switch (opc) { - case SEQ_ALLOC_META: - if (!ss_site->ss_server_seq) { - CERROR("Sequence server is not " - "initialized\n"); - RETURN(-EINVAL); - } - rc = seq_server_alloc_meta(ss_site->ss_server_seq, out, env); - break; - case SEQ_ALLOC_SUPER: - if (!ss_site->ss_control_seq) { - CERROR("Sequence controller is not " - "initialized\n"); - RETURN(-EINVAL); - } - rc = seq_server_alloc_super(ss_site->ss_control_seq, out, env); - break; - default: - rc = -EINVAL; - break; - } - - RETURN(rc); -} - -static int seq_req_handle(struct ptlrpc_request *req, - const struct lu_env *env, - struct seq_thread_info *info) -{ - struct lu_seq_range *out, *tmp; - struct lu_site *site; - int rc = -EPROTO; - __u32 *opc; - ENTRY; - - LASSERT(!(lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY)); - site = req->rq_export->exp_obd->obd_lu_dev->ld_site; - LASSERT(site != NULL); - - rc = req_capsule_server_pack(info->sti_pill); - if (rc) - RETURN(err_serious(rc)); - - opc = req_capsule_client_get(info->sti_pill, &RMF_SEQ_OPC); - if (opc != NULL) { - out = req_capsule_server_get(info->sti_pill, &RMF_SEQ_RANGE); - if (out == NULL) - RETURN(err_serious(-EPROTO)); - - tmp = req_capsule_client_get(info->sti_pill, &RMF_SEQ_RANGE); - - /* seq client passed mdt id, we need to pass that using out - * range parameter */ - - out->lsr_index = tmp->lsr_index; - out->lsr_flags = tmp->lsr_flags; - rc = seq_server_handle(site, env, *opc, out); - } else - rc = err_serious(-EPROTO); - - RETURN(rc); -} - -/* context key constructor/destructor: seq_key_init, seq_key_fini */ -LU_KEY_INIT_FINI(seq, struct seq_thread_info); - -/* context key: seq_thread_key */ -LU_CONTEXT_KEY_DEFINE(seq, LCT_MD_THREAD | LCT_DT_THREAD); - -static void seq_thread_info_init(struct ptlrpc_request *req, - struct seq_thread_info *info) -{ - info->sti_pill = &req->rq_pill; - /* Init request capsule */ - req_capsule_init(info->sti_pill, req, RCL_SERVER); - req_capsule_set(info->sti_pill, &RQF_SEQ_QUERY); -} - -static void seq_thread_info_fini(struct seq_thread_info *info) -{ - req_capsule_fini(info->sti_pill); -} - -int seq_handle(struct ptlrpc_request *req) -{ - const struct lu_env *env; - struct seq_thread_info *info; - int rc; - - env = req->rq_svc_thread->t_env; - LASSERT(env != NULL); - - info = lu_context_key_get(&env->le_ctx, &seq_thread_key); - LASSERT(info != NULL); - - seq_thread_info_init(req, info); - rc = seq_req_handle(req, env, info); - /* XXX: we don't need replay but MDT assign transno in any case, - * remove it manually before reply*/ - lustre_msg_set_transno(req->rq_repmsg, 0); - seq_thread_info_fini(info); - - return rc; -} -EXPORT_SYMBOL(seq_handle); - -/* - * Entry point for handling FLD RPCs called from MDT. - */ -int seq_query(struct com_thread_info *info) -{ - return seq_handle(info->cti_pill->rc_req); -} -EXPORT_SYMBOL(seq_query); - - -#ifdef LPROCFS -static int seq_server_proc_init(struct lu_server_seq *seq) -{ - int rc; - ENTRY; - - seq->lss_proc_dir = lprocfs_register(seq->lss_name, - seq_type_proc_dir, - NULL, NULL); - if (IS_ERR(seq->lss_proc_dir)) { - rc = PTR_ERR(seq->lss_proc_dir); - RETURN(rc); - } - - rc = lprocfs_add_vars(seq->lss_proc_dir, - seq_server_proc_list, seq); - if (rc) { - CERROR("%s: Can't init sequence manager " - "proc, rc %d\n", seq->lss_name, rc); - GOTO(out_cleanup, rc); - } - - RETURN(0); - -out_cleanup: - seq_server_proc_fini(seq); - return rc; -} - -static void seq_server_proc_fini(struct lu_server_seq *seq) -{ - ENTRY; - if (seq->lss_proc_dir != NULL) { - if (!IS_ERR(seq->lss_proc_dir)) - lprocfs_remove(&seq->lss_proc_dir); - seq->lss_proc_dir = NULL; - } - EXIT; -} -#else -static int seq_server_proc_init(struct lu_server_seq *seq) -{ - return 0; -} - -static void seq_server_proc_fini(struct lu_server_seq *seq) -{ - return; -} -#endif - - -int seq_server_init(struct lu_server_seq *seq, - struct dt_device *dev, - const char *prefix, - enum lu_mgr_type type, - struct seq_server_site *ss, - const struct lu_env *env) -{ - int rc, is_srv = (type == LUSTRE_SEQ_SERVER); - ENTRY; - - LASSERT(dev != NULL); - LASSERT(prefix != NULL); - LASSERT(ss != NULL); - LASSERT(ss->ss_lu != NULL); - - seq->lss_cli = NULL; - seq->lss_type = type; - seq->lss_site = ss; - range_init(&seq->lss_space); - - range_init(&seq->lss_lowater_set); - range_init(&seq->lss_hiwater_set); - seq->lss_set_width = LUSTRE_SEQ_BATCH_WIDTH; - - mutex_init(&seq->lss_mutex); - - seq->lss_width = is_srv ? - LUSTRE_SEQ_META_WIDTH : LUSTRE_SEQ_SUPER_WIDTH; - - snprintf(seq->lss_name, sizeof(seq->lss_name), - "%s-%s", (is_srv ? "srv" : "ctl"), prefix); - - rc = seq_store_init(seq, env, dev); - if (rc) - GOTO(out, rc); - /* Request backing store for saved sequence info. */ - rc = seq_store_read(seq, env); - if (rc == -ENODATA) { - - /* Nothing is read, init by default value. */ - seq->lss_space = is_srv ? - LUSTRE_SEQ_ZERO_RANGE: - LUSTRE_SEQ_SPACE_RANGE; - - LASSERT(ss != NULL); - seq->lss_space.lsr_index = ss->ss_node_id; - LCONSOLE_INFO("%s: No data found " - "on store. Initialize space\n", - seq->lss_name); - - rc = seq_store_update(env, seq, NULL, 0); - if (rc) { - CERROR("%s: Can't write space data, " - "rc %d\n", seq->lss_name, rc); - } - } else if (rc) { - CERROR("%s: Can't read space data, rc %d\n", - seq->lss_name, rc); - GOTO(out, rc); - } - - if (is_srv) { - LASSERT(range_is_sane(&seq->lss_space)); - } else { - LASSERT(!range_is_zero(&seq->lss_space) && - range_is_sane(&seq->lss_space)); - } - - rc = seq_server_proc_init(seq); - if (rc) - GOTO(out, rc); - - EXIT; -out: - if (rc) - seq_server_fini(seq, env); - return rc; -} -EXPORT_SYMBOL(seq_server_init); - -void seq_server_fini(struct lu_server_seq *seq, - const struct lu_env *env) -{ - ENTRY; - - seq_server_proc_fini(seq); - seq_store_fini(seq, env); - - EXIT; -} -EXPORT_SYMBOL(seq_server_fini); - -int seq_site_fini(const struct lu_env *env, struct seq_server_site *ss) -{ - if (ss == NULL) - RETURN(0); - - if (ss->ss_server_seq) { - seq_server_fini(ss->ss_server_seq, env); - OBD_FREE_PTR(ss->ss_server_seq); - ss->ss_server_seq = NULL; - } - - if (ss->ss_control_seq) { - seq_server_fini(ss->ss_control_seq, env); - OBD_FREE_PTR(ss->ss_control_seq); - ss->ss_control_seq = NULL; - } - - if (ss->ss_client_seq) { - seq_client_fini(ss->ss_client_seq); - OBD_FREE_PTR(ss->ss_client_seq); - ss->ss_client_seq = NULL; - } - - RETURN(0); -} -EXPORT_SYMBOL(seq_site_fini); - -proc_dir_entry_t *seq_type_proc_dir = NULL; - -static int __init fid_mod_init(void) -{ - seq_type_proc_dir = lprocfs_register(LUSTRE_SEQ_NAME, - proc_lustre_root, - NULL, NULL); - if (IS_ERR(seq_type_proc_dir)) - return PTR_ERR(seq_type_proc_dir); - - LU_CONTEXT_KEY_INIT(&seq_thread_key); - lu_context_key_register(&seq_thread_key); - return 0; -} - -static void __exit fid_mod_exit(void) -{ - lu_context_key_degister(&seq_thread_key); - if (seq_type_proc_dir != NULL && !IS_ERR(seq_type_proc_dir)) { - lprocfs_remove(&seq_type_proc_dir); - seq_type_proc_dir = NULL; - } -} - -MODULE_AUTHOR("Sun Microsystems, Inc. "); -MODULE_DESCRIPTION("Lustre FID Module"); -MODULE_LICENSE("GPL"); - -cfs_module(fid, "0.1.0", fid_mod_init, fid_mod_exit); diff --git a/drivers/staging/lustre/lustre/fid/fid_internal.h b/drivers/staging/lustre/lustre/fid/fid_internal.h index 407a7435583f..1dbe46be0f41 100644 --- a/drivers/staging/lustre/lustre/fid/fid_internal.h +++ b/drivers/staging/lustre/lustre/fid/fid_internal.h @@ -41,44 +41,16 @@ #define __FID_INTERNAL_H #include -#include - #include -struct seq_thread_info { - struct req_capsule *sti_pill; - struct lu_seq_range sti_space; - struct lu_buf sti_buf; -}; - -enum { - SEQ_TXN_STORE_CREDITS = 20 -}; - -extern struct lu_context_key seq_thread_key; - +/* Functions used internally in module. */ int seq_client_alloc_super(struct lu_client_seq *seq, const struct lu_env *env); -/* Store API functions. */ -int seq_store_init(struct lu_server_seq *seq, - const struct lu_env *env, - struct dt_device *dt); -void seq_store_fini(struct lu_server_seq *seq, - const struct lu_env *env); - -int seq_store_read(struct lu_server_seq *seq, - const struct lu_env *env); - -int seq_store_update(const struct lu_env *env, struct lu_server_seq *seq, - struct lu_seq_range *out, int sync); - -#ifdef LPROCFS -extern struct lprocfs_vars seq_server_proc_list[]; +# ifdef LPROCFS extern struct lprocfs_vars seq_client_proc_list[]; -#endif +# endif - -extern proc_dir_entry_t *seq_type_proc_dir; +extern struct proc_dir_entry *seq_type_proc_dir; #endif /* __FID_INTERNAL_H */ diff --git a/drivers/staging/lustre/lustre/fid/fid_lib.c b/drivers/staging/lustre/lustre/fid/fid_lib.c index eaff51a555fb..f03afdec027a 100644 --- a/drivers/staging/lustre/lustre/fid/fid_lib.c +++ b/drivers/staging/lustre/lustre/fid/fid_lib.c @@ -43,11 +43,9 @@ #define DEBUG_SUBSYSTEM S_FID -# include -# include - -#include -#include +#include +#include +#include #include /** @@ -56,9 +54,9 @@ * * Fid namespace: *
- * Normal FID:	seq:64 [2^33,2^64-1]      oid:32	  ver:32
- * IGIF      :	0:32, ino:32	      gen:32	  0:32
- * IDIF      :	0:31, 1:1, ost-index:16,  objd:48	 0:32
+ * Normal FID:        seq:64 [2^33,2^64-1]      oid:32          ver:32
+ * IGIF      :        0:32, ino:32              gen:32          0:32
+ * IDIF      :        0:31, 1:1, ost-index:16,  objd:48         0:32
  * 
* * The first 0x400 sequences of normal FID are reserved for special purpose. diff --git a/drivers/staging/lustre/lustre/fid/fid_request.c b/drivers/staging/lustre/lustre/fid/fid_request.c index fcaaca7e2e01..a279b5ae8e76 100644 --- a/drivers/staging/lustre/lustre/fid/fid_request.c +++ b/drivers/staging/lustre/lustre/fid/fid_request.c @@ -27,7 +27,7 @@ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. * - * Copyright (c) 2011, 2012, Intel Corporation. + * Copyright (c) 2011, 2013, Intel Corporation. */ /* * This file is part of Lustre, http://www.lustre.org/ @@ -42,15 +42,12 @@ #define DEBUG_SUBSYSTEM S_FID -# include -# include +#include +#include #include #include -#include -#include #include -#include #include /* mdc RPC locks */ #include @@ -63,9 +60,9 @@ static int seq_client_rpc(struct lu_client_seq *seq, struct obd_export *exp = seq->lcs_exp; struct ptlrpc_request *req; struct lu_seq_range *out, *in; - __u32 *op; - unsigned int debug_mask; - int rc; + __u32 *op; + unsigned int debug_mask; + int rc; ENTRY; req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp), &RQF_SEQ_QUERY, @@ -153,9 +150,7 @@ int seq_client_alloc_super(struct lu_client_seq *seq, mutex_lock(&seq->lcs_mutex); if (seq->lcs_srv) { - LASSERT(env != NULL); - rc = seq_server_alloc_super(seq->lcs_srv, &seq->lcs_space, - env); + rc = 0; } else { /* Check whether the connection to seq controller has been * setup (lcs_exp != NULL) */ @@ -179,8 +174,7 @@ static int seq_client_alloc_meta(const struct lu_env *env, ENTRY; if (seq->lcs_srv) { - LASSERT(env != NULL); - rc = seq_server_alloc_meta(seq->lcs_srv, &seq->lcs_space, env); + rc = 0; } else { do { /* If meta server return -EINPROGRESS or EAGAIN, @@ -191,6 +185,7 @@ static int seq_client_alloc_meta(const struct lu_env *env, SEQ_ALLOC_META, "meta"); } while (rc == -EINPROGRESS || rc == -EAGAIN); } + RETURN(rc); } @@ -409,11 +404,22 @@ void seq_client_flush(struct lu_client_seq *seq) } EXPORT_SYMBOL(seq_client_flush); -static void seq_client_proc_fini(struct lu_client_seq *seq); - +static void seq_client_proc_fini(struct lu_client_seq *seq) +{ #ifdef LPROCFS + ENTRY; + if (seq->lcs_proc_dir) { + if (!IS_ERR(seq->lcs_proc_dir)) + lprocfs_remove(&seq->lcs_proc_dir); + seq->lcs_proc_dir = NULL; + } + EXIT; +#endif /* LPROCFS */ +} + static int seq_client_proc_init(struct lu_client_seq *seq) { +#ifdef LPROCFS int rc; ENTRY; @@ -441,29 +447,11 @@ static int seq_client_proc_init(struct lu_client_seq *seq) out_cleanup: seq_client_proc_fini(seq); return rc; -} -static void seq_client_proc_fini(struct lu_client_seq *seq) -{ - ENTRY; - if (seq->lcs_proc_dir) { - if (!IS_ERR(seq->lcs_proc_dir)) - lprocfs_remove(&seq->lcs_proc_dir); - seq->lcs_proc_dir = NULL; - } - EXIT; -} -#else -static int seq_client_proc_init(struct lu_client_seq *seq) -{ +#else /* LPROCFS */ return 0; -} - -static void seq_client_proc_fini(struct lu_client_seq *seq) -{ - return; -} #endif +} int seq_client_init(struct lu_client_seq *seq, struct obd_export *exp, @@ -520,3 +508,76 @@ void seq_client_fini(struct lu_client_seq *seq) EXIT; } EXPORT_SYMBOL(seq_client_fini); + +int client_fid_init(struct obd_device *obd, + struct obd_export *exp, enum lu_cli_type type) +{ + struct client_obd *cli = &obd->u.cli; + char *prefix; + int rc; + ENTRY; + + OBD_ALLOC_PTR(cli->cl_seq); + if (cli->cl_seq == NULL) + RETURN(-ENOMEM); + + OBD_ALLOC(prefix, MAX_OBD_NAME + 5); + if (prefix == NULL) + GOTO(out_free_seq, rc = -ENOMEM); + + snprintf(prefix, MAX_OBD_NAME + 5, "cli-%s", obd->obd_name); + + /* Init client side sequence-manager */ + rc = seq_client_init(cli->cl_seq, exp, type, prefix, NULL); + OBD_FREE(prefix, MAX_OBD_NAME + 5); + if (rc) + GOTO(out_free_seq, rc); + + RETURN(rc); +out_free_seq: + OBD_FREE_PTR(cli->cl_seq); + cli->cl_seq = NULL; + return rc; +} +EXPORT_SYMBOL(client_fid_init); + +int client_fid_fini(struct obd_device *obd) +{ + struct client_obd *cli = &obd->u.cli; + ENTRY; + + if (cli->cl_seq != NULL) { + seq_client_fini(cli->cl_seq); + OBD_FREE_PTR(cli->cl_seq); + cli->cl_seq = NULL; + } + + RETURN(0); +} +EXPORT_SYMBOL(client_fid_fini); + +struct proc_dir_entry *seq_type_proc_dir; + +static int __init fid_mod_init(void) +{ + seq_type_proc_dir = lprocfs_register(LUSTRE_SEQ_NAME, + proc_lustre_root, + NULL, NULL); + if (IS_ERR(seq_type_proc_dir)) + return PTR_ERR(seq_type_proc_dir); + return 0; +} + +static void __exit fid_mod_exit(void) +{ + if (seq_type_proc_dir != NULL && !IS_ERR(seq_type_proc_dir)) { + lprocfs_remove(&seq_type_proc_dir); + seq_type_proc_dir = NULL; + } +} + +MODULE_AUTHOR("Sun Microsystems, Inc. "); +MODULE_DESCRIPTION("Lustre FID Module"); +MODULE_LICENSE("GPL"); + +cfs_module(fid, "0.1.0", fid_mod_init, fid_mod_exit); diff --git a/drivers/staging/lustre/lustre/fid/fid_store.c b/drivers/staging/lustre/lustre/fid/fid_store.c deleted file mode 100644 index a90e6e37d689..000000000000 --- a/drivers/staging/lustre/lustre/fid/fid_store.c +++ /dev/null @@ -1,259 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * 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 version 2 for more details (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - * - * GPL HEADER END - */ -/* - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Use is subject to license terms. - * - * Copyright (c) 2011, 2013, Intel Corporation. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - * - * lustre/fid/fid_store.c - * - * Lustre Sequence Manager - * - * Author: Yury Umanets - */ - -#define DEBUG_SUBSYSTEM S_FID - -# include -# include - -#include -#include -#include -#include -#include -#include -#include -#include "fid_internal.h" - - -static struct lu_buf *seq_store_buf(struct seq_thread_info *info) -{ - struct lu_buf *buf; - - buf = &info->sti_buf; - buf->lb_buf = &info->sti_space; - buf->lb_len = sizeof(info->sti_space); - return buf; -} - -struct seq_update_callback { - struct dt_txn_commit_cb suc_cb; - struct lu_server_seq *suc_seq; -}; - -void seq_update_cb(struct lu_env *env, struct thandle *th, - struct dt_txn_commit_cb *cb, int err) -{ - struct seq_update_callback *ccb; - - ccb = container_of0(cb, struct seq_update_callback, suc_cb); - - LASSERT(ccb->suc_seq != NULL); - - ccb->suc_seq->lss_need_sync = 0; - OBD_FREE_PTR(ccb); -} - -int seq_update_cb_add(struct thandle *th, struct lu_server_seq *seq) -{ - struct seq_update_callback *ccb; - struct dt_txn_commit_cb *dcb; - int rc; - - OBD_ALLOC_PTR(ccb); - if (ccb == NULL) - return -ENOMEM; - - ccb->suc_seq = seq; - seq->lss_need_sync = 1; - - dcb = &ccb->suc_cb; - dcb->dcb_func = seq_update_cb; - INIT_LIST_HEAD(&dcb->dcb_linkage); - strncpy(dcb->dcb_name, "seq_update_cb", MAX_COMMIT_CB_STR_LEN); - dcb->dcb_name[MAX_COMMIT_CB_STR_LEN - 1] = '\0'; - - rc = dt_trans_cb_add(th, dcb); - if (rc) - OBD_FREE_PTR(ccb); - return rc; -} - -/* This function implies that caller takes care about locking. */ -int seq_store_update(const struct lu_env *env, struct lu_server_seq *seq, - struct lu_seq_range *out, int sync) -{ - struct dt_device *dt_dev = lu2dt_dev(seq->lss_obj->do_lu.lo_dev); - struct seq_thread_info *info; - struct thandle *th; - loff_t pos = 0; - int rc; - - info = lu_context_key_get(&env->le_ctx, &seq_thread_key); - LASSERT(info != NULL); - - th = dt_trans_create(env, dt_dev); - if (IS_ERR(th)) - RETURN(PTR_ERR(th)); - - rc = dt_declare_record_write(env, seq->lss_obj, - sizeof(struct lu_seq_range), 0, th); - if (rc) - GOTO(exit, rc); - - if (out != NULL) { - rc = fld_declare_server_create(env, - seq->lss_site->ss_server_fld, - out, th); - if (rc) - GOTO(exit, rc); - } - - rc = dt_trans_start_local(env, dt_dev, th); - if (rc) - GOTO(exit, rc); - - /* Store ranges in le format. */ - range_cpu_to_le(&info->sti_space, &seq->lss_space); - - rc = dt_record_write(env, seq->lss_obj, seq_store_buf(info), &pos, th); - if (rc) { - CERROR("%s: Can't write space data, rc %d\n", - seq->lss_name, rc); - GOTO(exit, rc); - } else if (out != NULL) { - rc = fld_server_create(env, seq->lss_site->ss_server_fld, out, - th); - if (rc) { - CERROR("%s: Can't Update fld database, rc %d\n", - seq->lss_name, rc); - GOTO(exit, rc); - } - } - /* next sequence update will need sync until this update is committed - * in case of sync operation this is not needed obviously */ - if (!sync) - /* if callback can't be added then sync always */ - sync = !!seq_update_cb_add(th, seq); - - th->th_sync |= sync; -exit: - dt_trans_stop(env, dt_dev, th); - return rc; -} - -/* - * This function implies that caller takes care about locking or locking is not - * needed (init time). - */ -int seq_store_read(struct lu_server_seq *seq, - const struct lu_env *env) -{ - struct seq_thread_info *info; - loff_t pos = 0; - int rc; - ENTRY; - - info = lu_context_key_get(&env->le_ctx, &seq_thread_key); - LASSERT(info != NULL); - - rc = seq->lss_obj->do_body_ops->dbo_read(env, seq->lss_obj, - seq_store_buf(info), - &pos, BYPASS_CAPA); - - if (rc == sizeof(info->sti_space)) { - range_le_to_cpu(&seq->lss_space, &info->sti_space); - CDEBUG(D_INFO, "%s: Space - "DRANGE"\n", - seq->lss_name, PRANGE(&seq->lss_space)); - rc = 0; - } else if (rc == 0) { - rc = -ENODATA; - } else if (rc > 0) { - CERROR("%s: Read only %d bytes of %d\n", seq->lss_name, - rc, (int)sizeof(info->sti_space)); - rc = -EIO; - } - - RETURN(rc); -} - -int seq_store_init(struct lu_server_seq *seq, - const struct lu_env *env, - struct dt_device *dt) -{ - struct dt_object *dt_obj; - struct lu_fid fid; - struct lu_attr attr; - struct dt_object_format dof; - const char *name; - int rc; - ENTRY; - - name = seq->lss_type == LUSTRE_SEQ_SERVER ? - LUSTRE_SEQ_SRV_NAME : LUSTRE_SEQ_CTL_NAME; - - if (seq->lss_type == LUSTRE_SEQ_SERVER) - lu_local_obj_fid(&fid, FID_SEQ_SRV_OID); - else - lu_local_obj_fid(&fid, FID_SEQ_CTL_OID); - - memset(&attr, 0, sizeof(attr)); - attr.la_valid = LA_MODE; - attr.la_mode = S_IFREG | 0666; - dof.dof_type = DFT_REGULAR; - - dt_obj = dt_find_or_create(env, dt, &fid, &dof, &attr); - if (!IS_ERR(dt_obj)) { - seq->lss_obj = dt_obj; - rc = 0; - } else { - CERROR("%s: Can't find \"%s\" obj %d\n", - seq->lss_name, name, (int)PTR_ERR(dt_obj)); - rc = PTR_ERR(dt_obj); - } - - RETURN(rc); -} - -void seq_store_fini(struct lu_server_seq *seq, - const struct lu_env *env) -{ - ENTRY; - - if (seq->lss_obj != NULL) { - if (!IS_ERR(seq->lss_obj)) - lu_object_put(env, &seq->lss_obj->do_lu); - seq->lss_obj = NULL; - } - - EXIT; -} diff --git a/drivers/staging/lustre/lustre/fid/lproc_fid.c b/drivers/staging/lustre/lustre/fid/lproc_fid.c index af817a867f8b..20d04488c04f 100644 --- a/drivers/staging/lustre/lustre/fid/lproc_fid.c +++ b/drivers/staging/lustre/lustre/fid/lproc_fid.c @@ -204,9 +204,6 @@ lprocfs_fid_server_seq_show(struct seq_file *m, void *unused) RETURN(rc); } -struct lprocfs_vars seq_server_proc_list[] = { -}; - LPROC_SEQ_FOPS(lprocfs_fid_space); LPROC_SEQ_FOPS(lprocfs_fid_width); LPROC_SEQ_FOPS_RO(lprocfs_fid_server); diff --git a/drivers/staging/lustre/lustre/include/lu_object.h b/drivers/staging/lustre/lustre/include/lu_object.h index d40ad81b4eb2..94760481bd30 100644 --- a/drivers/staging/lustre/lustre/include/lu_object.h +++ b/drivers/staging/lustre/lustre/include/lu_object.h @@ -665,6 +665,11 @@ lu_site_bkt_from_fid(struct lu_site *site, struct lu_fid *fid) return cfs_hash_bd_extra_get(site->ls_obj_hash, &bd); } +static inline struct seq_server_site *lu_site2seq(const struct lu_site *s) +{ + return s->ld_seq_site; +} + /** \name ctors * Constructors/destructors. * @{ diff --git a/drivers/staging/lustre/lustre/include/lustre_fid.h b/drivers/staging/lustre/lustre/include/lustre_fid.h index 7523b407488e..f8f35c3fa091 100644 --- a/drivers/staging/lustre/lustre/include/lustre_fid.h +++ b/drivers/staging/lustre/lustre/include/lustre_fid.h @@ -38,8 +38,8 @@ * Author: Yury Umanets */ -#ifndef __LINUX_FID_H -#define __LINUX_FID_H +#ifndef __LUSTRE_FID_H +#define __LUSTRE_FID_H /** \defgroup fid fid * @@ -154,13 +154,12 @@ #include #include -#include -#include -#include - +struct lu_env; struct lu_site; struct lu_context; +struct obd_device; +struct obd_export; /* Whole sequences space range and zero range definitions */ extern const struct lu_seq_range LUSTRE_SEQ_SPACE_RANGE; @@ -320,6 +319,12 @@ static inline void lu_last_id_fid(struct lu_fid *fid, __u64 seq) fid->f_ver = 0; } +/* seq client type */ +enum lu_cli_type { + LUSTRE_SEQ_METADATA = 1, + LUSTRE_SEQ_DATA +}; + enum lu_mgr_type { LUSTRE_SEQ_SERVER, LUSTRE_SEQ_CONTROLLER @@ -426,10 +431,14 @@ struct lu_server_seq { struct seq_server_site *lss_site; }; +struct com_thread_info; int seq_query(struct com_thread_info *info); + +struct ptlrpc_request; int seq_handle(struct ptlrpc_request *req); /* Server methods */ + int seq_server_init(struct lu_server_seq *seq, struct dt_device *dev, const char *prefix, @@ -472,6 +481,7 @@ int seq_site_fini(const struct lu_env *env, struct seq_server_site *ss); int fid_is_local(const struct lu_env *env, struct lu_site *site, const struct lu_fid *fid); +enum lu_cli_type; int client_fid_init(struct obd_device *obd, struct obd_export *exp, enum lu_cli_type type); int client_fid_fini(struct obd_device *obd); @@ -760,4 +770,4 @@ static inline void range_be_to_cpu(struct lu_seq_range *dst, const struct lu_seq /** @} fid */ -#endif /* __LINUX_FID_H */ +#endif /* __LUSTRE_FID_H */ diff --git a/drivers/staging/lustre/lustre/include/md_object.h b/drivers/staging/lustre/lustre/include/md_object.h index 92d6420b21da..65b270a6d590 100644 --- a/drivers/staging/lustre/lustre/include/md_object.h +++ b/drivers/staging/lustre/lustre/include/md_object.h @@ -503,11 +503,6 @@ static inline struct md_device *md_obj2dev(const struct md_object *o) return container_of0(o->mo_lu.lo_dev, struct md_device, md_lu_dev); } -static inline struct seq_server_site *lu_site2seq(const struct lu_site *s) -{ - return s->ld_seq_site; -} - static inline int md_device_init(struct md_device *md, struct lu_device_type *t) { return lu_device_init(&md->md_lu_dev, t); diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 11d10fe682d0..fbf997ffa927 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -52,6 +52,7 @@ #include #include #include +#include #include #include @@ -1232,12 +1233,6 @@ typedef int (* md_enqueue_cb_t)(struct ptlrpc_request *req, struct md_enqueue_info *minfo, int rc); -/* seq client type */ -enum lu_cli_type { - LUSTRE_SEQ_METADATA = 1, - LUSTRE_SEQ_DATA -}; - struct md_enqueue_info { struct md_op_data mi_data; struct lookup_intent mi_it; From e2335e5d52b271dcc907db750b66aed6c021b594 Mon Sep 17 00:00:00 2001 From: jcl Date: Tue, 23 Jul 2013 00:06:45 +0800 Subject: [PATCH 0335/3400] staging/lustre/llite: force lvb_data update after layout change When a file is restored the layout lock is first associated with the released layout and after restore it has to be assocaited with the new layout. This patch forces lvb_data update in ll_layout_fetch() even if one is present (case for released->normal state change) Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3299 Lustre-change: http://review.whamcloud.com/6291 Signed-off-by: JC Lafoucriere Reviewed-by: Jinshan Xiong Reviewed-by: Johann Lombardi Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/file.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 549384582d49..b1df7f52ffec 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -2941,7 +2941,11 @@ static int ll_layout_fetch(struct inode *inode, struct ldlm_lock *lock) int rc; ENTRY; - if (lock->l_lvb_data != NULL) + CDEBUG(D_INODE, DFID" LVB_READY=%d l_lvb_data=%p l_lvb_len=%d\n", + PFID(ll_inode2fid(inode)), !!(lock->l_flags & LDLM_FL_LVB_READY), + lock->l_lvb_data, lock->l_lvb_len); + + if ((lock->l_lvb_data != NULL) && (lock->l_flags & LDLM_FL_LVB_READY)) RETURN(0); /* if layout lock was granted right away, the layout is returned @@ -2977,15 +2981,13 @@ static int ll_layout_fetch(struct inode *inode, struct ldlm_lock *lock) memcpy(lvbdata, lmm, lmmsize); lock_res_and_lock(lock); - if (lock->l_lvb_data == NULL) { - lock->l_lvb_data = lvbdata; - lock->l_lvb_len = lmmsize; - lvbdata = NULL; - } + if (lock->l_lvb_data != NULL) + OBD_FREE_LARGE(lock->l_lvb_data, lock->l_lvb_len); + + lock->l_lvb_data = lvbdata; + lock->l_lvb_len = lmmsize; unlock_res_and_lock(lock); - if (lvbdata != NULL) - OBD_FREE_LARGE(lvbdata, lmmsize); EXIT; out: @@ -3017,7 +3019,7 @@ static int ll_layout_lock_set(struct lustre_handle *lockh, ldlm_mode_t mode, LASSERT(ldlm_has_layout(lock)); LDLM_DEBUG(lock, "File %p/"DFID" being reconfigured: %d.\n", - inode, PFID(&lli->lli_fid), reconf); + inode, PFID(&lli->lli_fid), reconf); /* in case this is a caching lock and reinstate with new inode */ md_set_lock_data(sbi->ll_md_exp, &lockh->cookie, inode, NULL); From c6c9f60d9d537e9c05c8667f60eac88be269343a Mon Sep 17 00:00:00 2001 From: Fan Yong Date: Tue, 23 Jul 2013 00:06:46 +0800 Subject: [PATCH 0336/3400] staging/lustre/lfsck: LFSCK 1.5 technical debts (3) Original patch resolves some LFSCK 1.5 technical debts, including: 1) Check and remove repeated linkea entries. 2) Merge some "goto" branches to make the code more readable. 3) Some comments about object's nlink inconsistency processing. This patch picks the obd flags change. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2915 Lustre-change: http://review.whamcloud.com/6344 Signed-off-by: Fan Yong Reviewed-by: Alex Zhuravlev Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/obd_support.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/lustre/lustre/include/obd_support.h b/drivers/staging/lustre/lustre/include/obd_support.h index b5d40afc3599..03e6133ef50f 100644 --- a/drivers/staging/lustre/lustre/include/obd_support.h +++ b/drivers/staging/lustre/lustre/include/obd_support.h @@ -470,6 +470,7 @@ int obd_alloc_fail(const void *ptr, const char *name, const char *type, #define OBD_FAIL_LFSCK_DELAY3 0x1602 #define OBD_FAIL_LFSCK_LINKEA_CRASH 0x1603 #define OBD_FAIL_LFSCK_LINKEA_MORE 0x1604 +#define OBD_FAIL_LFSCK_LINKEA_MORE2 0x1605 #define OBD_FAIL_LFSCK_FATAL1 0x1608 #define OBD_FAIL_LFSCK_FATAL2 0x1609 #define OBD_FAIL_LFSCK_CRASH 0x160a From a55e0f44cf360a2f466b4599ec107fae4bafae64 Mon Sep 17 00:00:00 2001 From: Keith Mannthey Date: Tue, 23 Jul 2013 00:06:47 +0800 Subject: [PATCH 0337/3400] staging/lustre/osc: Check return code for lu_kmem_init lu_kmem_init can fail and returns has a return code. Check for this return code in lu_kmem_init. This issue was found during 2gb VM Racer testing Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3063 Lustre-change: http://review.whamcloud.com/6514 Signed-off-by: Keith Mannthey Reviewed-by: Mike Pershin Reviewed-by: Nathaniel Clark Reviewed-by: Bob Glossman Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/osc/osc_request.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 0c0e07b6f18e..fea04ca8ba6a 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -3681,6 +3681,8 @@ int __init osc_init(void) CDEBUG(D_INFO, "Lustre OSC module (%p).\n", &osc_caches); rc = lu_kmem_init(osc_caches); + if (rc) + RETURN(rc); lprocfs_osc_init_vars(&lvars); From 5be8e0702619eb3e77ec41c3b8825d0bbdfd8cda Mon Sep 17 00:00:00 2001 From: Hiroya Nozaki Date: Tue, 23 Jul 2013 00:06:48 +0800 Subject: [PATCH 0338/3400] staging/lustre/ptlrpc: Race between start and stop service threads When ptlrpc_start_thread fails to create a new thread, it will finalize and free a struct ptlrpc_thread created and used here. Considering this, it can be a problem when ptlrpc_svcpt_stop_thread is driven and handles the struct ptlrpc_thread right after or right before failure of cfs_create_thread. Because this situation let the both of ptlrpc_start_thread and ptlrpc_svcpt_stop_threads access the freed ptlrpc_thread and cause OS panic. Or, it may happen that ptlrpc_svcpt_stop_threads waits forever holding an already-freed waitq. This patch adds an error handling into ptlrpc_start_thread to fix this problem. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2889 Lustre-change: http://review.whamcloud.com/5552 Signed-off-by: Hiroya Nozaki Reviewed-by: Liang Zhen Reviewed-by: Nikitas Angelinas Reviewed-by: Keith Mannthey Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ptlrpc/service.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/staging/lustre/lustre/ptlrpc/service.c b/drivers/staging/lustre/lustre/ptlrpc/service.c index 687171102319..87bd63858b1c 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/service.c +++ b/drivers/staging/lustre/lustre/ptlrpc/service.c @@ -2765,11 +2765,19 @@ int ptlrpc_start_thread(struct ptlrpc_service_part *svcpt, int wait) CERROR("cannot start thread '%s': rc %d\n", thread->t_name, rc); spin_lock(&svcpt->scp_lock); - list_del(&thread->t_link); --svcpt->scp_nthrs_starting; - spin_unlock(&svcpt->scp_lock); - - OBD_FREE(thread, sizeof(*thread)); + if (thread_is_stopping(thread)) { + /* this ptlrpc_thread is being hanled + * by ptlrpc_svcpt_stop_threads now + */ + thread_add_flags(thread, SVC_STOPPED); + wake_up(&thread->t_ctl_waitq); + spin_unlock(&svcpt->scp_lock); + } else { + list_del(&thread->t_link); + spin_unlock(&svcpt->scp_lock); + OBD_FREE_PTR(thread); + } RETURN(rc); } From 7045b388be0d0d96dc30f7ad10a062feb23bc95e Mon Sep 17 00:00:00 2001 From: "Alexander.Boyko" Date: Tue, 23 Jul 2013 00:06:49 +0800 Subject: [PATCH 0339/3400] staging/lustre/crypto: add crc32c module loading to libcfs This patch add automatically module loading for crc32c when libcfs is starting. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2212 Lustre-change: http://review.whamcloud.com/4372 Signed-off-by: Alexander Boyko Reviewed-by: Andreas Dilger Reviewed-by: Shuichi Ihara Reviewed-by: James Simmons Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/libcfs/linux/linux-crypto.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto.c index 8e35777b4da5..b6c79bc177ad 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto.c @@ -274,6 +274,8 @@ static int adler32; int cfs_crypto_register(void) { + request_module("crc32c"); + adler32 = cfs_crypto_adler32_register(); /* check all algorithms and do performance test */ From ce74f92d97080b1e6cc72d3b1d06cc06d11fbe67 Mon Sep 17 00:00:00 2001 From: Andreas Dilger Date: Tue, 23 Jul 2013 00:06:50 +0800 Subject: [PATCH 0340/3400] staging/lustre/mdt: duplicate link names in directory When creating a hard link to a file, the MDT/MDD/OSD code does not verify whether the target link name already exists in the directory. The ZFS ZAP code checks for duplicate entries. The add_dirent_to_buf() function in ldiskfs only checks entries for duplicates while it is traversing the leaf block looking for free space. Even if it scanned the whole leaf block, this would not work for non-htree directories since there is no guarantee that the name is being inserted into the same leaf block. To fix this, link should check target object doesn't exist as other creat operations. Add sanity.sh test_31o with multiple threads racing to link a new name into the directory, while ensuring that there is a free entry in the leaf block that is large enough to hold the duplicate name. This needs to be racy, because otherwise the client VFS will see the existing name and not send the RPC to the MDS, hiding the bug. Add DLDLMRES/PLDLMRES macros for printing the whole lock resource name (including the name hash) in LDLM_DEBUG() messages in a format similar to DFID/PFID so they can be found in debug logs more easily. The patch pickes client side change of the original patch, which only contains the DLM printk part. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2901 Lustre-change: http://review.whamcloud.com/6591 Signed-off-by: Andreas Dilger Signed-off-by: Lai Siyao Reviewed-by: Alex Zhuravlev Reviewed-by: Mike Pershin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../lustre/lustre/include/lustre/lustre_idl.h | 4 + .../staging/lustre/lustre/ldlm/ldlm_lock.c | 145 +++++++++--------- 2 files changed, 76 insertions(+), 73 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index ace4e18dfae8..3aaa869b711f 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -2690,6 +2690,10 @@ struct ldlm_res_id { __u64 name[RES_NAME_SIZE]; }; +#define DLDLMRES "["LPX64":"LPX64":"LPX64"]."LPX64i +#define PLDLMRES(res) (res)->lr_name.name[0], (res)->lr_name.name[1], \ + (res)->lr_name.name[2], (res)->lr_name.name[3] + extern void lustre_swab_ldlm_res_id (struct ldlm_res_id *id); static inline int ldlm_res_eq(const struct ldlm_res_id *res0, diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c index c10ba9c33f42..ce1add149f52 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c @@ -2336,91 +2336,90 @@ void _ldlm_lock_debug(struct ldlm_lock *lock, switch (resource->lr_type) { case LDLM_EXTENT: libcfs_debug_vmsg2(msgdata, fmt, args, - " ns: %s lock: %p/"LPX64" lrc: %d/%d,%d mode: %s/%s " - "res: "LPU64"/"LPU64" rrc: %d type: %s ["LPU64"->"LPU64 - "] (req "LPU64"->"LPU64") flags: "LPX64" nid: %s remote:" - " "LPX64" expref: %d pid: %u timeout: %lu lvb_type: %d\n", - ldlm_lock_to_ns_name(lock), lock, - lock->l_handle.h_cookie, atomic_read(&lock->l_refc), - lock->l_readers, lock->l_writers, - ldlm_lockname[lock->l_granted_mode], - ldlm_lockname[lock->l_req_mode], - resource->lr_name.name[0], - resource->lr_name.name[1], - atomic_read(&resource->lr_refcount), - ldlm_typename[resource->lr_type], - lock->l_policy_data.l_extent.start, - lock->l_policy_data.l_extent.end, - lock->l_req_extent.start, lock->l_req_extent.end, - lock->l_flags, nid, lock->l_remote_handle.cookie, - exp ? atomic_read(&exp->exp_refcount) : -99, - lock->l_pid, lock->l_callback_timeout, lock->l_lvb_type); + " ns: %s lock: %p/"LPX64" lrc: %d/%d,%d mode: %s/%s " + "res: "DLDLMRES" rrc: %d type: %s ["LPU64"->"LPU64"] " + "(req "LPU64"->"LPU64") flags: "LPX64" nid: %s remote: " + LPX64" expref: %d pid: %u timeout: %lu lvb_type: %d\n", + ldlm_lock_to_ns_name(lock), lock, + lock->l_handle.h_cookie, atomic_read(&lock->l_refc), + lock->l_readers, lock->l_writers, + ldlm_lockname[lock->l_granted_mode], + ldlm_lockname[lock->l_req_mode], + PLDLMRES(resource), + atomic_read(&resource->lr_refcount), + ldlm_typename[resource->lr_type], + lock->l_policy_data.l_extent.start, + lock->l_policy_data.l_extent.end, + lock->l_req_extent.start, lock->l_req_extent.end, + lock->l_flags, nid, lock->l_remote_handle.cookie, + exp ? atomic_read(&exp->exp_refcount) : -99, + lock->l_pid, lock->l_callback_timeout, + lock->l_lvb_type); break; case LDLM_FLOCK: libcfs_debug_vmsg2(msgdata, fmt, args, - " ns: %s lock: %p/"LPX64" lrc: %d/%d,%d mode: %s/%s " - "res: "LPU64"/"LPU64" rrc: %d type: %s pid: %d " - "["LPU64"->"LPU64"] flags: "LPX64" nid: %s remote: "LPX64 - " expref: %d pid: %u timeout: %lu\n", - ldlm_lock_to_ns_name(lock), lock, - lock->l_handle.h_cookie, atomic_read(&lock->l_refc), - lock->l_readers, lock->l_writers, - ldlm_lockname[lock->l_granted_mode], - ldlm_lockname[lock->l_req_mode], - resource->lr_name.name[0], - resource->lr_name.name[1], - atomic_read(&resource->lr_refcount), - ldlm_typename[resource->lr_type], - lock->l_policy_data.l_flock.pid, - lock->l_policy_data.l_flock.start, - lock->l_policy_data.l_flock.end, - lock->l_flags, nid, lock->l_remote_handle.cookie, - exp ? atomic_read(&exp->exp_refcount) : -99, - lock->l_pid, lock->l_callback_timeout); + " ns: %s lock: %p/"LPX64" lrc: %d/%d,%d mode: %s/%s " + "res: "DLDLMRES" rrc: %d type: %s pid: %d " + "["LPU64"->"LPU64"] flags: "LPX64" nid: %s " + "remote: "LPX64" expref: %d pid: %u timeout: %lu\n", + ldlm_lock_to_ns_name(lock), lock, + lock->l_handle.h_cookie, atomic_read(&lock->l_refc), + lock->l_readers, lock->l_writers, + ldlm_lockname[lock->l_granted_mode], + ldlm_lockname[lock->l_req_mode], + PLDLMRES(resource), + atomic_read(&resource->lr_refcount), + ldlm_typename[resource->lr_type], + lock->l_policy_data.l_flock.pid, + lock->l_policy_data.l_flock.start, + lock->l_policy_data.l_flock.end, + lock->l_flags, nid, lock->l_remote_handle.cookie, + exp ? atomic_read(&exp->exp_refcount) : -99, + lock->l_pid, lock->l_callback_timeout); break; case LDLM_IBITS: libcfs_debug_vmsg2(msgdata, fmt, args, - " ns: %s lock: %p/"LPX64" lrc: %d/%d,%d mode: %s/%s " - "res: "LPU64"/"LPU64" bits "LPX64" rrc: %d type: %s " - "flags: "LPX64" nid: %s remote: "LPX64" expref: %d " - "pid: %u timeout: %lu lvb_type: %d\n", - ldlm_lock_to_ns_name(lock), - lock, lock->l_handle.h_cookie, - atomic_read (&lock->l_refc), - lock->l_readers, lock->l_writers, - ldlm_lockname[lock->l_granted_mode], - ldlm_lockname[lock->l_req_mode], - resource->lr_name.name[0], - resource->lr_name.name[1], - lock->l_policy_data.l_inodebits.bits, - atomic_read(&resource->lr_refcount), - ldlm_typename[resource->lr_type], - lock->l_flags, nid, lock->l_remote_handle.cookie, - exp ? atomic_read(&exp->exp_refcount) : -99, - lock->l_pid, lock->l_callback_timeout, lock->l_lvb_type); + " ns: %s lock: %p/"LPX64" lrc: %d/%d,%d mode: %s/%s " + "res: "DLDLMRES" bits "LPX64" rrc: %d type: %s " + "flags: "LPX64" nid: %s remote: "LPX64" expref: %d " + "pid: %u timeout: %lu lvb_type: %d\n", + ldlm_lock_to_ns_name(lock), + lock, lock->l_handle.h_cookie, + atomic_read(&lock->l_refc), + lock->l_readers, lock->l_writers, + ldlm_lockname[lock->l_granted_mode], + ldlm_lockname[lock->l_req_mode], + PLDLMRES(resource), + lock->l_policy_data.l_inodebits.bits, + atomic_read(&resource->lr_refcount), + ldlm_typename[resource->lr_type], + lock->l_flags, nid, lock->l_remote_handle.cookie, + exp ? atomic_read(&exp->exp_refcount) : -99, + lock->l_pid, lock->l_callback_timeout, + lock->l_lvb_type); break; default: libcfs_debug_vmsg2(msgdata, fmt, args, - " ns: %s lock: %p/"LPX64" lrc: %d/%d,%d mode: %s/%s " - "res: "LPU64"/"LPU64" rrc: %d type: %s flags: "LPX64" " - "nid: %s remote: "LPX64" expref: %d pid: %u timeout: %lu" - "lvb_type: %d\n", - ldlm_lock_to_ns_name(lock), - lock, lock->l_handle.h_cookie, - atomic_read (&lock->l_refc), - lock->l_readers, lock->l_writers, - ldlm_lockname[lock->l_granted_mode], - ldlm_lockname[lock->l_req_mode], - resource->lr_name.name[0], - resource->lr_name.name[1], - atomic_read(&resource->lr_refcount), - ldlm_typename[resource->lr_type], - lock->l_flags, nid, lock->l_remote_handle.cookie, - exp ? atomic_read(&exp->exp_refcount) : -99, - lock->l_pid, lock->l_callback_timeout, lock->l_lvb_type); + " ns: %s lock: %p/"LPX64" lrc: %d/%d,%d mode: %s/%s " + "res: "DLDLMRES" rrc: %d type: %s flags: "LPX64" " + "nid: %s remote: "LPX64" expref: %d pid: %u " + "timeout: %lu lvb_type: %d\n", + ldlm_lock_to_ns_name(lock), + lock, lock->l_handle.h_cookie, + atomic_read(&lock->l_refc), + lock->l_readers, lock->l_writers, + ldlm_lockname[lock->l_granted_mode], + ldlm_lockname[lock->l_req_mode], + PLDLMRES(resource), + atomic_read(&resource->lr_refcount), + ldlm_typename[resource->lr_type], + lock->l_flags, nid, lock->l_remote_handle.cookie, + exp ? atomic_read(&exp->exp_refcount) : -99, + lock->l_pid, lock->l_callback_timeout, + lock->l_lvb_type); break; } va_end(args); From 251c4317b3219eeacd800d167c105121ed9be188 Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Tue, 23 Jul 2013 00:06:51 +0800 Subject: [PATCH 0341/3400] staging/lustre/llite: call simple_setattr() from ll_md_setattr() This partially reverts the change from "LU-2482 layout: introduce new layout for released files" by calling simple_setattr() from ll_md_setattr() without ATTR_SIZE set. Doing so avoids failed assertions in osc_page_delete(). Disable truncates on released files and modify sanity 229 accordingly. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3448 Lustre-change: http://review.whamcloud.com/6643 Signed-off-by: John L. Hammond Reviewed-by: jacques-Charles Lafoucriere Reviewed-by: Jinshan Xiong Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/llite/llite_lib.c | 18 ++++++++---------- drivers/staging/lustre/lustre/lov/lov_io.c | 2 +- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index b9cbe9505d4a..39d519b30cb4 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -1282,6 +1282,13 @@ int ll_md_setattr(struct dentry *dentry, struct md_op_data *op_data, RETURN(rc); } + ia_valid = op_data->op_attr.ia_valid; + /* inode size will be in ll_setattr_ost, can't do it now since dirty + * cache is not cleared yet. */ + op_data->op_attr.ia_valid &= ~(TIMES_SET_FLAGS | ATTR_SIZE); + rc = simple_setattr(dentry, &op_data->op_attr); + op_data->op_attr.ia_valid = ia_valid; + /* Extract epoch data if obtained. */ op_data->op_handle = md.body->handle; op_data->op_ioepoch = md.body->ioepoch; @@ -1364,7 +1371,6 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr) struct ll_inode_info *lli = ll_i2info(inode); struct md_op_data *op_data = NULL; struct md_open_data *mod = NULL; - unsigned int valid = attr->ia_valid; int rc = 0, rc1 = 0; ENTRY; @@ -1476,13 +1482,6 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr) rc = ll_setattr_ost(inode, attr); EXIT; out: - if (rc == 0) { - /* Update inode attribute after dirty cache is cleaned - * by truncating OST objects. */ - attr->ia_valid |= ATTR_FORCE; - rc = simple_setattr(dentry, attr); - LASSERT(rc == 0); - } if (op_data) { if (op_data->op_ioepoch) { rc1 = ll_setattr_done_writing(inode, op_data, mod); @@ -1501,8 +1500,7 @@ out: ll_stats_ops_tally(ll_i2sbi(inode), (attr->ia_valid & ATTR_SIZE) ? LPROC_LL_TRUNC : LPROC_LL_SETATTR, 1); - attr->ia_valid = valid; - RETURN(rc); + return rc; } int ll_setattr(struct dentry *de, struct iattr *attr) diff --git a/drivers/staging/lustre/lustre/lov/lov_io.c b/drivers/staging/lustre/lustre/lov/lov_io.c index e78cdb7633ca..b316ce8cfeac 100644 --- a/drivers/staging/lustre/lustre/lov/lov_io.c +++ b/drivers/staging/lustre/lustre/lov/lov_io.c @@ -980,9 +980,9 @@ int lov_io_init_released(const struct lu_env *env, struct cl_object *obj, LASSERTF(0, "invalid type %d\n", io->ci_type); case CIT_MISC: case CIT_FSYNC: - case CIT_SETATTR: result = +1; break; + case CIT_SETATTR: case CIT_READ: case CIT_WRITE: case CIT_FAULT: From 3fa08ae702b15ad17b394361e53abf80b5e267fd Mon Sep 17 00:00:00 2001 From: Andriy Skulysh Date: Tue, 23 Jul 2013 00:06:52 +0800 Subject: [PATCH 0342/3400] staging/lustre/ldlm: Fix flock deadlock detection race Deadlock isn't detected if 2 threads are trying to grant 2 locks which deadlock on each other. They call ldlm_flock_deadlock() simultaneously and deadlock ins't detected. The soulition is to add lock to blocking list before calling ldlm_flock_deadlock() Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-1602 Lustre-change: http://review.whamcloud.com/3277 Signed-off-by: Andriy Skulysh Reviewed-by: Vitaly Fertman Reviewed-by: Bruce Korb Reviewed-by: Keith Mannthey Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ldlm/ldlm_flock.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c index aca1073d18b5..39973cb110a3 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c @@ -198,6 +198,7 @@ ldlm_flock_deadlock(struct ldlm_lock *req, struct ldlm_lock *bl_lock) if (lock == NULL) break; + LASSERT(req != lock); flock = &lock->l_policy_data.l_flock; LASSERT(flock->owner == bl_owner); bl_owner = flock->blocking_owner; @@ -329,18 +330,21 @@ reprocess: RETURN(LDLM_ITER_STOP); } - if (ldlm_flock_deadlock(req, lock)) { - ldlm_flock_destroy(req, mode, *flags); - *err = -EDEADLK; - RETURN(LDLM_ITER_STOP); - } - + /* add lock to blocking list before deadlock + * check to prevent race */ rc = ldlm_flock_blocking_link(req, lock); if (rc) { ldlm_flock_destroy(req, mode, *flags); *err = rc; RETURN(LDLM_ITER_STOP); } + if (ldlm_flock_deadlock(req, lock)) { + ldlm_flock_blocking_unlink(req); + ldlm_flock_destroy(req, mode, *flags); + *err = -EDEADLK; + RETURN(LDLM_ITER_STOP); + } + ldlm_resource_add_lock(res, &res->lr_waiting, req); *flags |= LDLM_FL_BLOCK_GRANTED; RETURN(LDLM_ITER_STOP); From 02524b200ca8adec61488ce23e96b6d8816778ae Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Tue, 23 Jul 2013 00:06:53 +0800 Subject: [PATCH 0343/3400] staging/lustre/lnet: remove empty file lnet/lnet/api-errno.c The file is empty. We can just remove it. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2335 Lustre-change: http://review.whamcloud.com/5880 Reviewed-by: Liang Zhen Reviewed-by: Li Wei Reviewed-by: Isaac Huang Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/lnet/Makefile | 2 +- drivers/staging/lustre/lnet/lnet/api-errno.c | 39 -------------------- 2 files changed, 1 insertion(+), 40 deletions(-) delete mode 100644 drivers/staging/lustre/lnet/lnet/api-errno.c diff --git a/drivers/staging/lustre/lnet/lnet/Makefile b/drivers/staging/lustre/lnet/lnet/Makefile index 1bd9ef774208..b815fe12b10a 100644 --- a/drivers/staging/lustre/lnet/lnet/Makefile +++ b/drivers/staging/lustre/lnet/lnet/Makefile @@ -1,6 +1,6 @@ obj-$(CONFIG_LNET) += lnet.o -lnet-y := api-errno.o api-ni.o config.o lib-me.o lib-msg.o lib-eq.o \ +lnet-y := api-ni.o config.o lib-me.o lib-msg.o lib-eq.o \ lib-md.o lib-ptl.o lib-move.o module.o lo.o router.o \ router_proc.o acceptor.o peer.o diff --git a/drivers/staging/lustre/lnet/lnet/api-errno.c b/drivers/staging/lustre/lnet/lnet/api-errno.c deleted file mode 100644 index 695b27265e23..000000000000 --- a/drivers/staging/lustre/lnet/lnet/api-errno.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * 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 version 2 for more details (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - * - * GPL HEADER END - */ -/* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. - * Use is subject to license terms. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - * - * lnet/lnet/api-errno.c - * - * Instantiate the string table of errors - */ - -/* If you change these, you must update the number table in portals/errno.h */ From e62e5d9251bf8efd08318e78bcaca86fde228383 Mon Sep 17 00:00:00 2001 From: Liu Xuezhao Date: Tue, 23 Jul 2013 00:06:54 +0800 Subject: [PATCH 0344/3400] staging/lustre/fld: prepare FLD module for client server split Split FLD server from client, fld_{handler,index}.c are not compliled unless server support is enabled. Do not include dt_object.h or lustre_mdt.h in lustre_fld.h and fix the minor breakages caused by this elsewhere. Generally cleanup includes in lustre/fld. Signed-off-by: Liu Xuezhao Signed-off-by: John L. Hammond Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-1330 Lustre-change: http://review.whamcloud.com/2675 Reviewed-by: Nathaniel Clark Reviewed-by: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/fld/Makefile | 2 +- .../staging/lustre/lustre/fld/fld_handler.c | 447 ------------------ drivers/staging/lustre/lustre/fld/fld_index.c | 426 ----------------- .../staging/lustre/lustre/fld/fld_internal.h | 29 -- .../staging/lustre/lustre/fld/fld_request.c | 40 +- drivers/staging/lustre/lustre/fld/lproc_fld.c | 205 +------- .../lustre/lustre/include/lustre_fld.h | 41 -- .../lustre/lustre/include/lustre_mdt.h | 84 ---- .../lustre/lustre/obdecho/echo_client.c | 1 + 9 files changed, 37 insertions(+), 1238 deletions(-) delete mode 100644 drivers/staging/lustre/lustre/fld/fld_handler.c delete mode 100644 drivers/staging/lustre/lustre/fld/fld_index.c delete mode 100644 drivers/staging/lustre/lustre/include/lustre_mdt.h diff --git a/drivers/staging/lustre/lustre/fld/Makefile b/drivers/staging/lustre/lustre/fld/Makefile index e7f2881a1d9e..90d46d84fbbb 100644 --- a/drivers/staging/lustre/lustre/fld/Makefile +++ b/drivers/staging/lustre/lustre/fld/Makefile @@ -1,5 +1,5 @@ obj-$(CONFIG_LUSTRE_FS) += fld.o -fld-y := fld_handler.o fld_request.o fld_cache.o fld_index.o lproc_fld.o +fld-y := fld_request.o fld_cache.o lproc_fld.o ccflags-y := -I$(src)/../include diff --git a/drivers/staging/lustre/lustre/fld/fld_handler.c b/drivers/staging/lustre/lustre/fld/fld_handler.c deleted file mode 100644 index d2707ae4ad57..000000000000 --- a/drivers/staging/lustre/lustre/fld/fld_handler.c +++ /dev/null @@ -1,447 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * 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 version 2 for more details (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - * - * GPL HEADER END - */ -/* - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Use is subject to license terms. - * - * Copyright (c) 2011, 2013, Intel Corporation. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - * - * lustre/fld/fld_handler.c - * - * FLD (Fids Location Database) - * - * Author: Yury Umanets - * Author: WangDi - * Author: Pravin Shelar - */ - -#define DEBUG_SUBSYSTEM S_FLD - -# include -# include -# include -# include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include "fld_internal.h" -#include - - -/* context key constructor/destructor: fld_key_init, fld_key_fini */ -LU_KEY_INIT_FINI(fld, struct fld_thread_info); - -/* context key: fld_thread_key */ -LU_CONTEXT_KEY_DEFINE(fld, LCT_MD_THREAD | LCT_DT_THREAD | LCT_MG_THREAD); - -proc_dir_entry_t *fld_type_proc_dir = NULL; - -static int __init fld_mod_init(void) -{ - fld_type_proc_dir = lprocfs_register(LUSTRE_FLD_NAME, - proc_lustre_root, - NULL, NULL); - if (IS_ERR(fld_type_proc_dir)) - return PTR_ERR(fld_type_proc_dir); - - LU_CONTEXT_KEY_INIT(&fld_thread_key); - lu_context_key_register(&fld_thread_key); - return 0; -} - -static void __exit fld_mod_exit(void) -{ - lu_context_key_degister(&fld_thread_key); - if (fld_type_proc_dir != NULL && !IS_ERR(fld_type_proc_dir)) { - lprocfs_remove(&fld_type_proc_dir); - fld_type_proc_dir = NULL; - } -} - -int fld_declare_server_create(const struct lu_env *env, - struct lu_server_fld *fld, - struct lu_seq_range *range, - struct thandle *th) -{ - int rc; - - rc = fld_declare_index_create(env, fld, range, th); - RETURN(rc); -} -EXPORT_SYMBOL(fld_declare_server_create); - -/** - * Insert FLD index entry and update FLD cache. - * - * This function is called from the sequence allocator when a super-sequence - * is granted to a server. - */ -int fld_server_create(const struct lu_env *env, struct lu_server_fld *fld, - struct lu_seq_range *range, struct thandle *th) -{ - int rc; - - mutex_lock(&fld->lsf_lock); - rc = fld_index_create(env, fld, range, th); - mutex_unlock(&fld->lsf_lock); - - RETURN(rc); -} -EXPORT_SYMBOL(fld_server_create); - -/** - * Lookup mds by seq, returns a range for given seq. - * - * If that entry is not cached in fld cache, request is sent to super - * sequence controller node (MDT0). All other MDT[1...N] and client - * cache fld entries, but this cache is not persistent. - */ -int fld_server_lookup(const struct lu_env *env, struct lu_server_fld *fld, - seqno_t seq, struct lu_seq_range *range) -{ - struct lu_seq_range *erange; - struct fld_thread_info *info; - int rc; - ENTRY; - - info = lu_context_key_get(&env->le_ctx, &fld_thread_key); - LASSERT(info != NULL); - erange = &info->fti_lrange; - - /* Lookup it in the cache. */ - rc = fld_cache_lookup(fld->lsf_cache, seq, erange); - if (rc == 0) { - if (unlikely(fld_range_type(erange) != fld_range_type(range) && - !fld_range_is_any(range))) { - CERROR("%s: FLD cache range "DRANGE" does not match" - "requested flag %x: rc = %d\n", fld->lsf_name, - PRANGE(erange), range->lsr_flags, -EIO); - RETURN(-EIO); - } - *range = *erange; - RETURN(0); - } - - if (fld->lsf_obj) { - /* On server side, all entries should be in cache. - * If we can not find it in cache, just return error */ - CERROR("%s: Cannot find sequence "LPX64": rc = %d\n", - fld->lsf_name, seq, -EIO); - RETURN(-EIO); - } else { - LASSERT(fld->lsf_control_exp); - /* send request to mdt0 i.e. super seq. controller. - * This is temporary solution, long term solution is fld - * replication on all mdt servers. - */ - range->lsr_start = seq; - rc = fld_client_rpc(fld->lsf_control_exp, - range, FLD_LOOKUP); - if (rc == 0) - fld_cache_insert(fld->lsf_cache, range); - } - RETURN(rc); -} -EXPORT_SYMBOL(fld_server_lookup); - -/** - * All MDT server handle fld lookup operation. But only MDT0 has fld index. - * if entry is not found in cache we need to forward lookup request to MDT0 - */ - -static int fld_server_handle(struct lu_server_fld *fld, - const struct lu_env *env, - __u32 opc, struct lu_seq_range *range, - struct fld_thread_info *info) -{ - int rc; - ENTRY; - - switch (opc) { - case FLD_LOOKUP: - rc = fld_server_lookup(env, fld, range->lsr_start, range); - break; - default: - rc = -EINVAL; - break; - } - - CDEBUG(D_INFO, "%s: FLD req handle: error %d (opc: %d, range: " - DRANGE"\n", fld->lsf_name, rc, opc, PRANGE(range)); - - RETURN(rc); - -} - -static int fld_req_handle(struct ptlrpc_request *req, - struct fld_thread_info *info) -{ - struct obd_export *exp = req->rq_export; - struct lu_site *site = exp->exp_obd->obd_lu_dev->ld_site; - struct lu_seq_range *in; - struct lu_seq_range *out; - int rc; - __u32 *opc; - ENTRY; - - rc = req_capsule_server_pack(info->fti_pill); - if (rc) - RETURN(err_serious(rc)); - - opc = req_capsule_client_get(info->fti_pill, &RMF_FLD_OPC); - if (opc != NULL) { - in = req_capsule_client_get(info->fti_pill, &RMF_FLD_MDFLD); - if (in == NULL) - RETURN(err_serious(-EPROTO)); - out = req_capsule_server_get(info->fti_pill, &RMF_FLD_MDFLD); - if (out == NULL) - RETURN(err_serious(-EPROTO)); - *out = *in; - - /* For old 2.0 client, the 'lsr_flags' is uninitialized. - * Set it as 'LU_SEQ_RANGE_MDT' by default. */ - if (!(exp_connect_flags(exp) & OBD_CONNECT_64BITHASH) && - !(exp_connect_flags(exp) & OBD_CONNECT_MDS_MDS) && - !(exp_connect_flags(exp) & OBD_CONNECT_LIGHTWEIGHT) && - !exp->exp_libclient) - fld_range_set_mdt(out); - - rc = fld_server_handle(lu_site2seq(site)->ss_server_fld, - req->rq_svc_thread->t_env, - *opc, out, info); - } else { - rc = err_serious(-EPROTO); - } - - RETURN(rc); -} - -static void fld_thread_info_init(struct ptlrpc_request *req, - struct fld_thread_info *info) -{ - info->fti_pill = &req->rq_pill; - /* Init request capsule. */ - req_capsule_init(info->fti_pill, req, RCL_SERVER); - req_capsule_set(info->fti_pill, &RQF_FLD_QUERY); -} - -static void fld_thread_info_fini(struct fld_thread_info *info) -{ - req_capsule_fini(info->fti_pill); -} - -static int fld_handle(struct ptlrpc_request *req) -{ - struct fld_thread_info *info; - const struct lu_env *env; - int rc; - - env = req->rq_svc_thread->t_env; - LASSERT(env != NULL); - - info = lu_context_key_get(&env->le_ctx, &fld_thread_key); - LASSERT(info != NULL); - - fld_thread_info_init(req, info); - rc = fld_req_handle(req, info); - fld_thread_info_fini(info); - - return rc; -} - -/* - * Entry point for handling FLD RPCs called from MDT. - */ -int fld_query(struct com_thread_info *info) -{ - return fld_handle(info->cti_pill->rc_req); -} -EXPORT_SYMBOL(fld_query); - -/* - * Returns true, if fid is local to this server node. - * - * WARNING: this function is *not* guaranteed to return false if fid is - * remote: it makes an educated conservative guess only. - * - * fid_is_local() is supposed to be used in assertion checks only. - */ -int fid_is_local(const struct lu_env *env, - struct lu_site *site, const struct lu_fid *fid) -{ - int result; - struct seq_server_site *ss_site; - struct lu_seq_range *range; - struct fld_thread_info *info; - ENTRY; - - info = lu_context_key_get(&env->le_ctx, &fld_thread_key); - range = &info->fti_lrange; - - result = 1; /* conservatively assume fid is local */ - ss_site = lu_site2seq(site); - if (ss_site->ss_client_fld != NULL) { - int rc; - - rc = fld_cache_lookup(ss_site->ss_client_fld->lcf_cache, - fid_seq(fid), range); - if (rc == 0) - result = (range->lsr_index == ss_site->ss_node_id); - } - return result; -} -EXPORT_SYMBOL(fid_is_local); - -static void fld_server_proc_fini(struct lu_server_fld *fld); - -#ifdef LPROCFS -static int fld_server_proc_init(struct lu_server_fld *fld) -{ - int rc = 0; - ENTRY; - - fld->lsf_proc_dir = lprocfs_register(fld->lsf_name, - fld_type_proc_dir, - fld_server_proc_list, fld); - if (IS_ERR(fld->lsf_proc_dir)) { - rc = PTR_ERR(fld->lsf_proc_dir); - RETURN(rc); - } - - rc = lprocfs_seq_create(fld->lsf_proc_dir, "fldb", 0444, - &fld_proc_seq_fops, fld); - if (rc) { - lprocfs_remove(&fld->lsf_proc_dir); - fld->lsf_proc_dir = NULL; - } - - RETURN(rc); -} - -static void fld_server_proc_fini(struct lu_server_fld *fld) -{ - ENTRY; - if (fld->lsf_proc_dir != NULL) { - if (!IS_ERR(fld->lsf_proc_dir)) - lprocfs_remove(&fld->lsf_proc_dir); - fld->lsf_proc_dir = NULL; - } - EXIT; -} -#else -static int fld_server_proc_init(struct lu_server_fld *fld) -{ - return 0; -} - -static void fld_server_proc_fini(struct lu_server_fld *fld) -{ - return; -} -#endif - -int fld_server_init(const struct lu_env *env, struct lu_server_fld *fld, - struct dt_device *dt, const char *prefix, int mds_node_id, - int type) -{ - int cache_size, cache_threshold; - int rc; - ENTRY; - - snprintf(fld->lsf_name, sizeof(fld->lsf_name), - "srv-%s", prefix); - - cache_size = FLD_SERVER_CACHE_SIZE / - sizeof(struct fld_cache_entry); - - cache_threshold = cache_size * - FLD_SERVER_CACHE_THRESHOLD / 100; - - mutex_init(&fld->lsf_lock); - fld->lsf_cache = fld_cache_init(fld->lsf_name, - cache_size, cache_threshold); - if (IS_ERR(fld->lsf_cache)) { - rc = PTR_ERR(fld->lsf_cache); - fld->lsf_cache = NULL; - GOTO(out, rc); - } - - if (!mds_node_id && type == LU_SEQ_RANGE_MDT) { - rc = fld_index_init(env, fld, dt); - if (rc) - GOTO(out, rc); - } else { - fld->lsf_obj = NULL; - } - - rc = fld_server_proc_init(fld); - if (rc) - GOTO(out, rc); - - fld->lsf_control_exp = NULL; - - GOTO(out, rc); - -out: - if (rc) - fld_server_fini(env, fld); - return rc; -} -EXPORT_SYMBOL(fld_server_init); - -void fld_server_fini(const struct lu_env *env, struct lu_server_fld *fld) -{ - ENTRY; - - fld_server_proc_fini(fld); - fld_index_fini(env, fld); - - if (fld->lsf_cache != NULL) { - if (!IS_ERR(fld->lsf_cache)) - fld_cache_fini(fld->lsf_cache); - fld->lsf_cache = NULL; - } - - EXIT; -} -EXPORT_SYMBOL(fld_server_fini); - -MODULE_AUTHOR("Sun Microsystems, Inc. "); -MODULE_DESCRIPTION("Lustre FLD"); -MODULE_LICENSE("GPL"); - -cfs_module(mdd, "0.1.0", fld_mod_init, fld_mod_exit); diff --git a/drivers/staging/lustre/lustre/fld/fld_index.c b/drivers/staging/lustre/lustre/fld/fld_index.c deleted file mode 100644 index ec68a54c23bd..000000000000 --- a/drivers/staging/lustre/lustre/fld/fld_index.c +++ /dev/null @@ -1,426 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * 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 version 2 for more details (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - * - * GPL HEADER END - */ -/* - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Use is subject to license terms. - * - * Copyright (c) 2011, 2013, Intel Corporation. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - * - * lustre/fld/fld_index.c - * - * Author: WangDi - * Author: Yury Umanets - */ - -#define DEBUG_SUBSYSTEM S_FLD - -# include -# include -# include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include "fld_internal.h" - -const char fld_index_name[] = "fld"; - -static const struct lu_seq_range IGIF_FLD_RANGE = { - .lsr_start = FID_SEQ_IGIF, - .lsr_end = FID_SEQ_IGIF_MAX + 1, - .lsr_index = 0, - .lsr_flags = LU_SEQ_RANGE_MDT -}; - -static const struct lu_seq_range DOT_LUSTRE_FLD_RANGE = { - .lsr_start = FID_SEQ_DOT_LUSTRE, - .lsr_end = FID_SEQ_DOT_LUSTRE + 1, - .lsr_index = 0, - .lsr_flags = LU_SEQ_RANGE_MDT -}; - -static const struct lu_seq_range ROOT_FLD_RANGE = { - .lsr_start = FID_SEQ_ROOT, - .lsr_end = FID_SEQ_ROOT + 1, - .lsr_index = 0, - .lsr_flags = LU_SEQ_RANGE_MDT -}; - -const struct dt_index_features fld_index_features = { - .dif_flags = DT_IND_UPDATE, - .dif_keysize_min = sizeof(seqno_t), - .dif_keysize_max = sizeof(seqno_t), - .dif_recsize_min = sizeof(struct lu_seq_range), - .dif_recsize_max = sizeof(struct lu_seq_range), - .dif_ptrsize = 4 -}; - -extern struct lu_context_key fld_thread_key; - -int fld_declare_index_create(const struct lu_env *env, - struct lu_server_fld *fld, - const struct lu_seq_range *new_range, - struct thandle *th) -{ - struct lu_seq_range *tmp; - struct lu_seq_range *range; - struct fld_thread_info *info; - int rc = 0; - - ENTRY; - - info = lu_context_key_get(&env->le_ctx, &fld_thread_key); - range = &info->fti_lrange; - tmp = &info->fti_irange; - memset(range, 0, sizeof(*range)); - - rc = fld_index_lookup(env, fld, new_range->lsr_start, range); - if (rc == 0) { - /* In case of duplicate entry, the location must be same */ - LASSERT((range_compare_loc(new_range, range) == 0)); - GOTO(out, rc = -EEXIST); - } - - if (rc != -ENOENT) { - CERROR("%s: lookup range "DRANGE" error: rc = %d\n", - fld->lsf_name, PRANGE(range), rc); - GOTO(out, rc); - } - - /* Check for merge case, since the fld entry can only be increamental, - * so we will only check whether it can be merged from the left. */ - if (new_range->lsr_start == range->lsr_end && range->lsr_end != 0 && - range_compare_loc(new_range, range) == 0) { - range_cpu_to_be(tmp, range); - rc = dt_declare_delete(env, fld->lsf_obj, - (struct dt_key *)&tmp->lsr_start, th); - if (rc) { - CERROR("%s: declare record "DRANGE" failed: rc = %d\n", - fld->lsf_name, PRANGE(range), rc); - GOTO(out, rc); - } - memcpy(tmp, new_range, sizeof(*new_range)); - tmp->lsr_start = range->lsr_start; - } else { - memcpy(tmp, new_range, sizeof(*new_range)); - } - - range_cpu_to_be(tmp, tmp); - rc = dt_declare_insert(env, fld->lsf_obj, (struct dt_rec *)tmp, - (struct dt_key *)&tmp->lsr_start, th); -out: - RETURN(rc); -} - -/** - * insert range in fld store. - * - * \param range range to be inserted - * \param th transaction for this operation as it could compound - * transaction. - * - * \retval 0 success - * \retval -ve error - * - * The whole fld index insertion is protected by seq->lss_mutex (see - * seq_server_alloc_super), i.e. only one thread will access fldb each - * time, so we do not need worry the fld file and cache will being - * changed between declare and create. - * Because the fld entry can only be increamental, so we will only check - * whether it can be merged from the left. - **/ -int fld_index_create(const struct lu_env *env, struct lu_server_fld *fld, - const struct lu_seq_range *new_range, struct thandle *th) -{ - struct lu_seq_range *range; - struct lu_seq_range *tmp; - struct fld_thread_info *info; - int rc = 0; - int deleted = 0; - struct fld_cache_entry *flde; - ENTRY; - - info = lu_context_key_get(&env->le_ctx, &fld_thread_key); - - LASSERT(mutex_is_locked(&fld->lsf_lock)); - - range = &info->fti_lrange; - memset(range, 0, sizeof(*range)); - tmp = &info->fti_irange; - rc = fld_index_lookup(env, fld, new_range->lsr_start, range); - if (rc != -ENOENT) { - rc = rc == 0 ? -EEXIST : rc; - GOTO(out, rc); - } - - if (new_range->lsr_start == range->lsr_end && range->lsr_end != 0 && - range_compare_loc(new_range, range) == 0) { - range_cpu_to_be(tmp, range); - rc = dt_delete(env, fld->lsf_obj, - (struct dt_key *)&tmp->lsr_start, th, - BYPASS_CAPA); - if (rc != 0) - GOTO(out, rc); - memcpy(tmp, new_range, sizeof(*new_range)); - tmp->lsr_start = range->lsr_start; - deleted = 1; - } else { - memcpy(tmp, new_range, sizeof(*new_range)); - } - - range_cpu_to_be(tmp, tmp); - rc = dt_insert(env, fld->lsf_obj, (struct dt_rec *)tmp, - (struct dt_key *)&tmp->lsr_start, th, BYPASS_CAPA, 1); - if (rc != 0) { - CERROR("%s: insert range "DRANGE" failed: rc = %d\n", - fld->lsf_name, PRANGE(new_range), rc); - GOTO(out, rc); - } - - flde = fld_cache_entry_create(new_range); - if (IS_ERR(flde)) - GOTO(out, rc = PTR_ERR(flde)); - - write_lock(&fld->lsf_cache->fci_lock); - if (deleted) - fld_cache_delete_nolock(fld->lsf_cache, new_range); - rc = fld_cache_insert_nolock(fld->lsf_cache, flde); - write_unlock(&fld->lsf_cache->fci_lock); - if (rc) - OBD_FREE_PTR(flde); -out: - RETURN(rc); -} - -/** - * lookup range for a seq passed. note here we only care about the start/end, - * caller should handle the attached location data (flags, index). - * - * \param seq seq for lookup. - * \param range result of lookup. - * - * \retval 0 found, \a range is the matched range; - * \retval -ENOENT not found, \a range is the left-side range; - * \retval -ve other error; - */ -int fld_index_lookup(const struct lu_env *env, struct lu_server_fld *fld, - seqno_t seq, struct lu_seq_range *range) -{ - struct lu_seq_range *fld_rec; - struct fld_thread_info *info; - int rc; - - ENTRY; - - info = lu_context_key_get(&env->le_ctx, &fld_thread_key); - fld_rec = &info->fti_rec; - - rc = fld_cache_lookup(fld->lsf_cache, seq, fld_rec); - if (rc == 0) { - *range = *fld_rec; - if (range_within(range, seq)) - rc = 0; - else - rc = -ENOENT; - } - - CDEBUG(D_INFO, "%s: lookup seq = "LPX64" range : "DRANGE" rc = %d\n", - fld->lsf_name, seq, PRANGE(range), rc); - - RETURN(rc); -} - -int fld_insert_entry(const struct lu_env *env, - struct lu_server_fld *fld, - const struct lu_seq_range *range) -{ - struct thandle *th; - int rc; - ENTRY; - - th = dt_trans_create(env, lu2dt_dev(fld->lsf_obj->do_lu.lo_dev)); - if (IS_ERR(th)) - RETURN(PTR_ERR(th)); - - rc = fld_declare_index_create(env, fld, range, th); - if (rc != 0) { - if (rc == -EEXIST) - rc = 0; - GOTO(out, rc); - } - - rc = dt_trans_start_local(env, lu2dt_dev(fld->lsf_obj->do_lu.lo_dev), - th); - if (rc) - GOTO(out, rc); - - rc = fld_index_create(env, fld, range, th); - if (rc == -EEXIST) - rc = 0; -out: - dt_trans_stop(env, lu2dt_dev(fld->lsf_obj->do_lu.lo_dev), th); - RETURN(rc); -} -EXPORT_SYMBOL(fld_insert_entry); - -static int fld_insert_special_entries(const struct lu_env *env, - struct lu_server_fld *fld) -{ - int rc; - - rc = fld_insert_entry(env, fld, &IGIF_FLD_RANGE); - if (rc != 0) - RETURN(rc); - - rc = fld_insert_entry(env, fld, &DOT_LUSTRE_FLD_RANGE); - if (rc != 0) - RETURN(rc); - - rc = fld_insert_entry(env, fld, &ROOT_FLD_RANGE); - - RETURN(rc); -} - -int fld_index_init(const struct lu_env *env, struct lu_server_fld *fld, - struct dt_device *dt) -{ - struct dt_object *dt_obj = NULL; - struct lu_fid fid; - struct lu_attr *attr = NULL; - struct lu_seq_range *range = NULL; - struct fld_thread_info *info; - struct dt_object_format dof; - struct dt_it *it; - const struct dt_it_ops *iops; - int rc; - ENTRY; - - info = lu_context_key_get(&env->le_ctx, &fld_thread_key); - LASSERT(info != NULL); - - lu_local_obj_fid(&fid, FLD_INDEX_OID); - OBD_ALLOC_PTR(attr); - if (attr == NULL) - RETURN(-ENOMEM); - - memset(attr, 0, sizeof(*attr)); - attr->la_valid = LA_MODE; - attr->la_mode = S_IFREG | 0666; - dof.dof_type = DFT_INDEX; - dof.u.dof_idx.di_feat = &fld_index_features; - - dt_obj = dt_find_or_create(env, dt, &fid, &dof, attr); - if (IS_ERR(dt_obj)) { - rc = PTR_ERR(dt_obj); - CERROR("%s: Can't find \"%s\" obj %d\n", fld->lsf_name, - fld_index_name, rc); - dt_obj = NULL; - GOTO(out, rc); - } - - fld->lsf_obj = dt_obj; - rc = dt_obj->do_ops->do_index_try(env, dt_obj, &fld_index_features); - if (rc != 0) { - CERROR("%s: File \"%s\" is not an index: rc = %d!\n", - fld->lsf_name, fld_index_name, rc); - GOTO(out, rc); - } - - range = &info->fti_rec; - /* Load fld entry to cache */ - iops = &dt_obj->do_index_ops->dio_it; - it = iops->init(env, dt_obj, 0, NULL); - if (IS_ERR(it)) - GOTO(out, rc = PTR_ERR(it)); - - rc = iops->load(env, it, 0); - if (rc < 0) - GOTO(out_it_fini, rc); - - if (rc > 0) { - /* Load FLD entry into server cache */ - do { - rc = iops->rec(env, it, (struct dt_rec *)range, 0); - if (rc != 0) - GOTO(out_it_put, rc); - LASSERT(range != NULL); - range_be_to_cpu(range, range); - rc = fld_cache_insert(fld->lsf_cache, range); - if (rc != 0) - GOTO(out_it_put, rc); - rc = iops->next(env, it); - } while (rc == 0); - } - - /* Note: fld_insert_entry will detect whether these - * special entries already exist inside FLDB */ - mutex_lock(&fld->lsf_lock); - rc = fld_insert_special_entries(env, fld); - mutex_unlock(&fld->lsf_lock); - if (rc != 0) { - CERROR("%s: insert special entries failed!: rc = %d\n", - fld->lsf_name, rc); - GOTO(out_it_put, rc); - } - -out_it_put: - iops->put(env, it); -out_it_fini: - iops->fini(env, it); -out: - if (attr != NULL) - OBD_FREE_PTR(attr); - - if (rc != 0) { - if (dt_obj != NULL) - lu_object_put(env, &dt_obj->do_lu); - fld->lsf_obj = NULL; - } - RETURN(rc); -} - -void fld_index_fini(const struct lu_env *env, struct lu_server_fld *fld) -{ - ENTRY; - if (fld->lsf_obj != NULL) { - if (!IS_ERR(fld->lsf_obj)) - lu_object_put(env, &fld->lsf_obj->do_lu); - fld->lsf_obj = NULL; - } - EXIT; -} diff --git a/drivers/staging/lustre/lustre/fld/fld_internal.h b/drivers/staging/lustre/lustre/fld/fld_internal.h index 9fa9e01cdb67..6e7ca9efe337 100644 --- a/drivers/staging/lustre/lustre/fld/fld_internal.h +++ b/drivers/staging/lustre/lustre/fld/fld_internal.h @@ -139,38 +139,10 @@ enum { extern struct lu_fld_hash fld_hash[]; - -struct fld_thread_info { - struct req_capsule *fti_pill; - __u64 fti_key; - struct lu_seq_range fti_rec; - struct lu_seq_range fti_lrange; - struct lu_seq_range fti_irange; -}; - -extern struct lu_context_key fld_thread_key; - -int fld_index_init(const struct lu_env *env, struct lu_server_fld *fld, - struct dt_device *dt); - -void fld_index_fini(const struct lu_env *env, struct lu_server_fld *fld); - -int fld_declare_index_create(const struct lu_env *env, - struct lu_server_fld *fld, - const struct lu_seq_range *new, - struct thandle *th); - -int fld_index_create(const struct lu_env *env, struct lu_server_fld *fld, - const struct lu_seq_range *new, struct thandle *th); - -int fld_index_lookup(const struct lu_env *env, struct lu_server_fld *fld, - seqno_t seq, struct lu_seq_range *range); - int fld_client_rpc(struct obd_export *exp, struct lu_seq_range *range, __u32 fld_op); #ifdef LPROCFS -extern struct lprocfs_vars fld_server_proc_list[]; extern struct lprocfs_vars fld_client_proc_list[]; #endif @@ -219,5 +191,4 @@ fld_target_name(struct lu_fld_target *tar) } extern proc_dir_entry_t *fld_type_proc_dir; -extern struct file_operations fld_proc_seq_fops; #endif /* __FLD_INTERNAL_H */ diff --git a/drivers/staging/lustre/lustre/fld/fld_request.c b/drivers/staging/lustre/lustre/fld/fld_request.c index e9f07398b68a..c99b945cc8ef 100644 --- a/drivers/staging/lustre/lustre/fld/fld_request.c +++ b/drivers/staging/lustre/lustre/fld/fld_request.c @@ -60,6 +60,8 @@ #include #include "fld_internal.h" +struct lu_context_key fld_thread_key; + /* TODO: these 3 functions are copies of flow-control code from mdc_lib.c * It should be common thing. The same about mdc RPC lock */ static int fld_req_avail(struct client_obd *cli, struct mdc_cache_waiter *mcw) @@ -280,6 +282,8 @@ int fld_client_del_target(struct lu_client_fld *fld, __u64 idx) EXPORT_SYMBOL(fld_client_del_target); #ifdef LPROCFS +proc_dir_entry_t *fld_type_proc_dir = NULL; + static int fld_client_proc_init(struct lu_client_fld *fld) { int rc; @@ -496,12 +500,7 @@ int fld_client_lookup(struct lu_client_fld *fld, seqno_t seq, mdsno_t *mds, res.lsr_start = seq; fld_range_set_type(&res, flags); - if (target->ft_srv != NULL) { - LASSERT(env != NULL); - rc = fld_server_lookup(env, target->ft_srv, seq, &res); - } else { - rc = fld_client_rpc(target->ft_exp, &res, FLD_LOOKUP); - } + rc = fld_client_rpc(target->ft_exp, &res, FLD_LOOKUP); if (rc == 0) { *mds = res.lsr_index; @@ -517,3 +516,32 @@ void fld_client_flush(struct lu_client_fld *fld) fld_cache_flush(fld->lcf_cache); } EXPORT_SYMBOL(fld_client_flush); + +static int __init fld_mod_init(void) +{ + fld_type_proc_dir = lprocfs_register(LUSTRE_FLD_NAME, + proc_lustre_root, + NULL, NULL); + if (IS_ERR(fld_type_proc_dir)) + return PTR_ERR(fld_type_proc_dir); + + LU_CONTEXT_KEY_INIT(&fld_thread_key); + lu_context_key_register(&fld_thread_key); + return 0; +} + +static void __exit fld_mod_exit(void) +{ + lu_context_key_degister(&fld_thread_key); + if (fld_type_proc_dir != NULL && !IS_ERR(fld_type_proc_dir)) { + lprocfs_remove(&fld_type_proc_dir); + fld_type_proc_dir = NULL; + } +} + +MODULE_AUTHOR("Sun Microsystems, Inc. "); +MODULE_DESCRIPTION("Lustre FLD"); +MODULE_LICENSE("GPL"); + +module_init(fld_mod_init) +module_exit(fld_mod_exit) diff --git a/drivers/staging/lustre/lustre/fld/lproc_fld.c b/drivers/staging/lustre/lustre/fld/lproc_fld.c index c1bd80339e67..77322ba5bf31 100644 --- a/drivers/staging/lustre/lustre/fld/lproc_fld.c +++ b/drivers/staging/lustre/lustre/fld/lproc_fld.c @@ -158,202 +158,6 @@ struct file_operations fld_proc_cache_flush_fops = { .release = fld_proc_cache_flush_release, }; -struct fld_seq_param { - struct lu_env fsp_env; - struct dt_it *fsp_it; - struct lu_server_fld *fsp_fld; - unsigned int fsp_stop:1; -}; - -static void *fldb_seq_start(struct seq_file *p, loff_t *pos) -{ - struct fld_seq_param *param = p->private; - struct lu_server_fld *fld; - struct dt_object *obj; - const struct dt_it_ops *iops; - - if (param == NULL || param->fsp_stop) - return NULL; - - fld = param->fsp_fld; - obj = fld->lsf_obj; - LASSERT(obj != NULL); - iops = &obj->do_index_ops->dio_it; - - iops->load(¶m->fsp_env, param->fsp_it, *pos); - - *pos = be64_to_cpu(*(__u64 *)iops->key(¶m->fsp_env, param->fsp_it)); - return param; -} - -static void fldb_seq_stop(struct seq_file *p, void *v) -{ - struct fld_seq_param *param = p->private; - const struct dt_it_ops *iops; - struct lu_server_fld *fld; - struct dt_object *obj; - - if (param == NULL) - return; - - fld = param->fsp_fld; - obj = fld->lsf_obj; - LASSERT(obj != NULL); - iops = &obj->do_index_ops->dio_it; - - iops->put(¶m->fsp_env, param->fsp_it); -} - -static void *fldb_seq_next(struct seq_file *p, void *v, loff_t *pos) -{ - struct fld_seq_param *param = p->private; - struct lu_server_fld *fld; - struct dt_object *obj; - const struct dt_it_ops *iops; - int rc; - - if (param == NULL || param->fsp_stop) - return NULL; - - fld = param->fsp_fld; - obj = fld->lsf_obj; - LASSERT(obj != NULL); - iops = &obj->do_index_ops->dio_it; - - rc = iops->next(¶m->fsp_env, param->fsp_it); - if (rc > 0) { - param->fsp_stop = 1; - return NULL; - } - - *pos = be64_to_cpu(*(__u64 *)iops->key(¶m->fsp_env, param->fsp_it)); - return param; -} - -static int fldb_seq_show(struct seq_file *p, void *v) -{ - struct fld_seq_param *param = p->private; - struct lu_server_fld *fld; - struct dt_object *obj; - const struct dt_it_ops *iops; - struct fld_thread_info *info; - struct lu_seq_range *fld_rec; - int rc; - - if (param == NULL || param->fsp_stop) - return 0; - - fld = param->fsp_fld; - obj = fld->lsf_obj; - LASSERT(obj != NULL); - iops = &obj->do_index_ops->dio_it; - - info = lu_context_key_get(¶m->fsp_env.le_ctx, - &fld_thread_key); - fld_rec = &info->fti_rec; - rc = iops->rec(¶m->fsp_env, param->fsp_it, - (struct dt_rec *)fld_rec, 0); - if (rc != 0) { - CERROR("%s:read record error: rc %d\n", - fld->lsf_name, rc); - } else if (fld_rec->lsr_start != 0) { - range_be_to_cpu(fld_rec, fld_rec); - rc = seq_printf(p, DRANGE"\n", PRANGE(fld_rec)); - } - - return rc; -} - -struct seq_operations fldb_sops = { - .start = fldb_seq_start, - .stop = fldb_seq_stop, - .next = fldb_seq_next, - .show = fldb_seq_show, -}; - -static int fldb_seq_open(struct inode *inode, struct file *file) -{ - struct seq_file *seq; - struct lu_server_fld *fld = (struct lu_server_fld *)PDE_DATA(inode); - struct dt_object *obj; - const struct dt_it_ops *iops; - struct fld_seq_param *param = NULL; - int env_init = 0; - int rc; - - rc = seq_open(file, &fldb_sops); - if (rc) - GOTO(out, rc); - - obj = fld->lsf_obj; - if (obj == NULL) { - seq = file->private_data; - seq->private = NULL; - return 0; - } - - OBD_ALLOC_PTR(param); - if (param == NULL) - GOTO(out, rc = -ENOMEM); - - rc = lu_env_init(¶m->fsp_env, LCT_MD_THREAD); - if (rc != 0) - GOTO(out, rc); - - env_init = 1; - iops = &obj->do_index_ops->dio_it; - param->fsp_it = iops->init(¶m->fsp_env, obj, 0, NULL); - if (IS_ERR(param->fsp_it)) - GOTO(out, rc = PTR_ERR(param->fsp_it)); - - param->fsp_fld = fld; - param->fsp_stop = 0; - - seq = file->private_data; - seq->private = param; -out: - if (rc != 0) { - if (env_init == 1) - lu_env_fini(¶m->fsp_env); - if (param != NULL) - OBD_FREE_PTR(param); - } - return rc; -} - -static int fldb_seq_release(struct inode *inode, struct file *file) -{ - struct seq_file *seq = file->private_data; - struct fld_seq_param *param; - struct lu_server_fld *fld; - struct dt_object *obj; - const struct dt_it_ops *iops; - - param = seq->private; - if (param == NULL) { - lprocfs_seq_release(inode, file); - return 0; - } - - fld = param->fsp_fld; - obj = fld->lsf_obj; - LASSERT(obj != NULL); - iops = &obj->do_index_ops->dio_it; - - LASSERT(iops != NULL); - LASSERT(obj != NULL); - LASSERT(param->fsp_it != NULL); - iops->fini(¶m->fsp_env, param->fsp_it); - lu_env_fini(¶m->fsp_env); - OBD_FREE_PTR(param); - lprocfs_seq_release(inode, file); - - return 0; -} - -struct lprocfs_vars fld_server_proc_list[] = { - { NULL }}; - LPROC_SEQ_FOPS_RO(fld_proc_targets); LPROC_SEQ_FOPS(fld_proc_hash); @@ -363,11 +167,4 @@ struct lprocfs_vars fld_client_proc_list[] = { { "cache_flush", &fld_proc_cache_flush_fops }, { NULL }}; -struct file_operations fld_proc_seq_fops = { - .owner = THIS_MODULE, - .open = fldb_seq_open, - .read = seq_read, - .release = fldb_seq_release, -}; - -#endif +#endif /* LPROCFS */ diff --git a/drivers/staging/lustre/lustre/include/lustre_fld.h b/drivers/staging/lustre/lustre/include/lustre_fld.h index 11e034a65b17..94b697dbe713 100644 --- a/drivers/staging/lustre/lustre/include/lustre_fld.h +++ b/drivers/staging/lustre/lustre/include/lustre_fld.h @@ -43,9 +43,6 @@ */ #include -#include -#include - #include struct lu_client_fld; @@ -129,47 +126,9 @@ struct lu_client_fld { * Client fld proc entry name. */ char lcf_name[80]; - const struct lu_context *lcf_ctx; - int lcf_flags; }; -/** - * number of blocks to reserve for particular operations. Should be function of - * ... something. Stub for now. - */ -enum { - /* one insert operation can involve two delete and one insert */ - FLD_TXN_INDEX_INSERT_CREDITS = 60, - FLD_TXN_INDEX_DELETE_CREDITS = 20, -}; - -int fld_query(struct com_thread_info *info); - -/* Server methods */ -int fld_server_init(const struct lu_env *env, struct lu_server_fld *fld, - struct dt_device *dt, const char *prefix, int mds_node_id, - int type); - -void fld_server_fini(const struct lu_env *env, struct lu_server_fld *fld); - -int fld_declare_server_create(const struct lu_env *env, - struct lu_server_fld *fld, - struct lu_seq_range *new, - struct thandle *th); - -int fld_server_create(const struct lu_env *env, - struct lu_server_fld *fld, - struct lu_seq_range *add_range, - struct thandle *th); - -int fld_insert_entry(const struct lu_env *env, - struct lu_server_fld *fld, - const struct lu_seq_range *range); - -int fld_server_lookup(const struct lu_env *env, struct lu_server_fld *fld, - seqno_t seq, struct lu_seq_range *range); - /* Client methods */ int fld_client_init(struct lu_client_fld *fld, const char *prefix, int hash); diff --git a/drivers/staging/lustre/lustre/include/lustre_mdt.h b/drivers/staging/lustre/lustre/include/lustre_mdt.h deleted file mode 100644 index dba26a6cfa38..000000000000 --- a/drivers/staging/lustre/lustre/include/lustre_mdt.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * 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 version 2 for more details (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - * - * GPL HEADER END - */ -/* - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Use is subject to license terms. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - */ - -#ifndef __LINUX_MDT_H -#define __LINUX_MDT_H - -/** \defgroup mdt mdt - * - * @{ - */ - -#include -#include -#include -#include -#include - -/* - * Common thread info for mdt, seq and fld - */ -struct com_thread_info { - /* - * for req-layout interface. - */ - struct req_capsule *cti_pill; -}; - -enum { - ESERIOUS = 0x0001000 -}; - -static inline int err_serious(int rc) -{ - LASSERT(rc < 0); - LASSERT(-rc < ESERIOUS); - return -(-rc | ESERIOUS); -} - -static inline int clear_serious(int rc) -{ - if (rc < 0) - rc = -(-rc & ~ESERIOUS); - return rc; -} - -static inline int is_serious(int rc) -{ - return (rc < 0 && -rc & ESERIOUS); -} - -/** @} mdt */ - -#endif diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c index ae89ea6f893c..de8f4ea7f156 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include From 5907838a44d71a446c6e418f1b9d8a66fff4cbfb Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Tue, 23 Jul 2013 00:06:58 +0800 Subject: [PATCH 0345/3400] staging/lustre/procfs: return -ENOMEM from lprocfs_register() In lprocfs_register(), if proc_mkdir() fails then return ERR_PTR(-ENOMEM) rather than NULL and hold _lprocfs_mutex for the whole function. In lprocfs_remove_nolock() return early if the entry is an error pointer. Improve error handling around lprocfs_register() in a few spots. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2650 Lustre-change: http://review.whamcloud.com/5161 Signed-off-by: John L. Hammond Reviewed-by: Emoly Liu Reviewed-by: Keith Mannthey Reviewed-by: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/ldlm/ldlm_pool.c | 1 + drivers/staging/lustre/lustre/llite/super25.c | 2 +- drivers/staging/lustre/lustre/lov/lov_obd.c | 6 ++--- .../lustre/obdclass/linux/linux-module.c | 9 ++++++- .../lustre/lustre/obdclass/lprocfs_status.c | 26 ++++++++++++------- .../lustre/lustre/ptlrpc/gss/lproc_gss.c | 6 +++-- 6 files changed, 33 insertions(+), 17 deletions(-) diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c b/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c index 3277a0dca31e..101af4be9ffb 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c @@ -750,6 +750,7 @@ static int ldlm_pool_proc_init(struct ldlm_pool *pl) if (IS_ERR(pl->pl_proc_dir)) { CERROR("LProcFS failed in ldlm-pool-init\n"); rc = PTR_ERR(pl->pl_proc_dir); + pl->pl_proc_dir = NULL; GOTO(out_free_name, rc); } diff --git a/drivers/staging/lustre/lustre/llite/super25.c b/drivers/staging/lustre/lustre/llite/super25.c index 82c14a993cca..ea06f1a18776 100644 --- a/drivers/staging/lustre/lustre/llite/super25.c +++ b/drivers/staging/lustre/lustre/llite/super25.c @@ -214,7 +214,7 @@ static void __exit exit_lustre_lite(void) ll_remote_perm_cachep = NULL; kmem_cache_destroy(ll_file_data_slab); - if (proc_lustre_fs_root) + if (proc_lustre_fs_root && !IS_ERR(proc_lustre_fs_root)) lprocfs_remove(&proc_lustre_fs_root); } diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c index 0a9e40de8fae..c7c1a8cc2592 100644 --- a/drivers/staging/lustre/lustre/lov/lov_obd.c +++ b/drivers/staging/lustre/lustre/lov/lov_obd.c @@ -836,11 +836,11 @@ int lov_setup(struct obd_device *obd, struct lustre_cfg *lcfg) lprocfs_obd_setup(obd, lvars.obd_vars); #ifdef LPROCFS { - int rc; + int rc1; - rc = lprocfs_seq_create(obd->obd_proc_entry, "target_obd", + rc1 = lprocfs_seq_create(obd->obd_proc_entry, "target_obd", 0444, &lov_proc_target_fops, obd); - if (rc) + if (rc1) CWARN("Error adding the target_obd file\n"); } #endif diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c index d2c3072541d1..2abacf206531 100644 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c +++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c @@ -385,14 +385,21 @@ struct file_operations obd_device_list_fops = { int class_procfs_init(void) { - int rc; + int rc = 0; ENTRY; obd_sysctl_init(); proc_lustre_root = lprocfs_register("fs/lustre", NULL, lprocfs_base, NULL); + if (IS_ERR(proc_lustre_root)) { + rc = PTR_ERR(proc_lustre_root); + proc_lustre_root = NULL; + goto out; + } + rc = lprocfs_seq_create(proc_lustre_root, "devices", 0444, &obd_device_list_fops, NULL); +out: if (rc) CERROR("error adding /proc/fs/lustre/devices file\n"); RETURN(0); diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c index 85163f42892e..e57a922eda59 100644 --- a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c +++ b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c @@ -179,17 +179,21 @@ struct proc_dir_entry *lprocfs_register(const char *name, struct proc_dir_entry *parent, struct lprocfs_vars *list, void *data) { - struct proc_dir_entry *newchild; + struct proc_dir_entry *entry; - newchild = proc_mkdir(name, parent); - if (newchild != NULL && list != NULL) { - int rc = lprocfs_add_vars(newchild, list, data); - if (rc) { - lprocfs_remove(&newchild); - return ERR_PTR(rc); + entry = proc_mkdir(name, parent); + if (entry == NULL) + GOTO(out, entry = ERR_PTR(-ENOMEM)); + + if (list != NULL) { + int rc = lprocfs_add_vars(entry, list, data); + if (rc != 0) { + lprocfs_remove(&entry); + entry = ERR_PTR(rc); } } - return newchild; +out: + return entry; } EXPORT_SYMBOL(lprocfs_register); @@ -1596,10 +1600,12 @@ int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid) NULL, NULL); OBD_FREE(buffer, LNET_NIDSTR_SIZE); - if (new_stat->nid_proc == NULL) { + if (IS_ERR(new_stat->nid_proc)) { CERROR("Error making export directory for nid %s\n", libcfs_nid2str(*nid)); - GOTO(destroy_new_ns, rc = -ENOMEM); + rc = PTR_ERR(new_stat->nid_proc); + new_stat->nid_proc = NULL; + GOTO(destroy_new_ns, rc); } entry = lprocfs_add_simple(new_stat->nid_proc, "uuid", diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/lproc_gss.c b/drivers/staging/lustre/lustre/ptlrpc/gss/lproc_gss.c index 340400089a5a..de100a14ab52 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/gss/lproc_gss.c +++ b/drivers/staging/lustre/lustre/ptlrpc/gss/lproc_gss.c @@ -199,15 +199,17 @@ int gss_init_lproc(void) gss_proc_root = lprocfs_register("gss", sptlrpc_proc_root, gss_lprocfs_vars, NULL); if (IS_ERR(gss_proc_root)) { + rc = PTR_ERR(gss_proc_root); gss_proc_root = NULL; - GOTO(err_out, rc = PTR_ERR(gss_proc_root)); + GOTO(err_out, rc); } gss_proc_lk = lprocfs_register("lgss_keyring", gss_proc_root, gss_lk_lprocfs_vars, NULL); if (IS_ERR(gss_proc_lk)) { + rc = PTR_ERR(gss_proc_lk); gss_proc_lk = NULL; - GOTO(err_out, rc = PTR_ERR(gss_proc_root)); + GOTO(err_out, rc); } return 0; From cdb5f7107ff8b4727e32f4921b2c5984984d24e0 Mon Sep 17 00:00:00 2001 From: Ned Bass Date: Tue, 23 Jul 2013 00:06:59 +0800 Subject: [PATCH 0346/3400] staging/lustre/lmv: fix duplicate directory entries Previously, I accidentally introduced a new way for duplicate directory entries to be returned from readdir(). That patch fails to properly decrement the nlupgs counter when breaking out of the inner-for loop. This accounting error causes an extra iteration of the inner-for loop when processing the next cfs page and a bad ldp_hash_end value is then saved in the lu_dirpage. To fix this, always decrement the nlupgs counter on entry into the inner loop. Note: this bug only affects architectures with > 4k-sized pages, e.g. PowerPC. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3182 Lustre-change: http://review.whamcloud.com/6405 Signed-off-by: Ned Bass Reviewed-by: Fan Yong Reviewed-by: Andreas Dilger Reviewed-by: Bobi Jam Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/lmv/lmv_obd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index d10f7fc553d3..5bd952a6dd65 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -1959,7 +1959,7 @@ static void lmv_adjust_dirpages(struct page **pages, int ncfspgs, int nlupgs) __u64 hash_end = dp->ldp_hash_end; __u32 flags = dp->ldp_flags; - for (; nlupgs > 1; nlupgs--) { + while (--nlupgs > 0) { ent = lu_dirent_start(dp); for (end_dirent = ent; ent != NULL; end_dirent = ent, ent = lu_dirent_next(ent)); @@ -1993,6 +1993,7 @@ static void lmv_adjust_dirpages(struct page **pages, int ncfspgs, int nlupgs) kunmap(pages[i]); } + LASSERTF(nlupgs == 0, "left = %d", nlupgs); } #else #define lmv_adjust_dirpages(pages, ncfspgs, nlupgs) do {} while (0) From f1b58c5afadb862c6daae76fe380d083cc370bc7 Mon Sep 17 00:00:00 2001 From: Nathaniel Clark Date: Tue, 23 Jul 2013 00:07:00 +0800 Subject: [PATCH 0347/3400] staging/lustre/obdclass: be more careful processing server name Because whole options line gets passed to exclude processing, don't search from end of passed in argument to determine fsname at beginning. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2200 Lustre-change: http://review.whamcloud.com/6197 Signed-off-by: Nathaniel Clark Reviewed-by: Andreas Dilger Reviewed-by: Alex Zhuravlev Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../lustre/lustre/obdclass/obd_config.c | 11 ++-- .../lustre/lustre/obdclass/obd_mount.c | 58 +++++++++++-------- 2 files changed, 40 insertions(+), 29 deletions(-) diff --git a/drivers/staging/lustre/lustre/obdclass/obd_config.c b/drivers/staging/lustre/lustre/obdclass/obd_config.c index bbf06d009fd0..8b5eb6c3b078 100644 --- a/drivers/staging/lustre/lustre/obdclass/obd_config.c +++ b/drivers/staging/lustre/lustre/obdclass/obd_config.c @@ -1426,10 +1426,13 @@ int class_config_llog_handler(const struct lu_env *env, } - if ((clli->cfg_flags & CFG_F_EXCLUDE) && - (lcfg->lcfg_command == LCFG_LOV_ADD_OBD)) - /* Add inactive instead */ - lcfg->lcfg_command = LCFG_LOV_ADD_INA; + if (clli->cfg_flags & CFG_F_EXCLUDE) { + CDEBUG(D_CONFIG, "cmd: %x marked EXCLUDED\n", + lcfg->lcfg_command); + if (lcfg->lcfg_command == LCFG_LOV_ADD_OBD) + /* Add inactive instead */ + lcfg->lcfg_command = LCFG_LOV_ADD_INA; + } lustre_cfg_bufs_init(&bufs, lcfg); diff --git a/drivers/staging/lustre/lustre/obdclass/obd_mount.c b/drivers/staging/lustre/lustre/obdclass/obd_mount.c index 99adad9793c5..f5585ccaff19 100644 --- a/drivers/staging/lustre/lustre/obdclass/obd_mount.c +++ b/drivers/staging/lustre/lustre/obdclass/obd_mount.c @@ -650,6 +650,15 @@ int lustre_put_lsi(struct super_block *sb) RETURN(0); } +/*** SERVER NAME *** + * + * FSNAME is between 1 and 8 characters (inclusive). + * Excluded characters are '/' and ':' + * SEPERATOR is either ':' or '-' + * TYPE: "OST", "MDT", etc. + * INDEX: Hex representation of the index + */ + /** Get the fsname ("lustre") from the server name ("lustre-OST003F"). * @param [in] svname server name including type and index * @param [out] fsname Buffer to copy filesystem name prefix into. @@ -659,22 +668,13 @@ int lustre_put_lsi(struct super_block *sb) */ int server_name2fsname(const char *svname, char *fsname, const char **endptr) { - const char *dash = strrchr(svname, '-'); - if (!dash) { - dash = strrchr(svname, ':'); - if (!dash) - return -EINVAL; - } + const char *dash; - /* interpret -MDTXXXXX-mdc as mdt, the better way is to pass - * in the fsname, then determine the server index */ - if (!strcmp(LUSTRE_MDC_NAME, dash + 1)) { - dash--; - for (; dash > svname && *dash != '-' && *dash != ':'; dash--) - ; - if (dash == svname) - return -EINVAL; - } + dash = svname + strnlen(svname, 8); /* max fsname length is 8 */ + for (; dash > svname && *dash != '-' && *dash != ':'; dash--) + ; + if (dash == svname) + return -EINVAL; if (fsname != NULL) { strncpy(fsname, svname, dash - svname); @@ -697,15 +697,15 @@ int server_name2svname(const char *label, char *svname, const char **endptr, size_t svsize) { int rc; - const const char *dash; + const char *dash; /* We use server_name2fsname() just for parsing */ rc = server_name2fsname(label, NULL, &dash); if (rc != 0) return rc; - if (*dash != '-') - return -1; + if (endptr != NULL) + *endptr = dash; if (strlcpy(svname, dash + 1, svsize) >= svsize) return -E2BIG; @@ -730,9 +730,6 @@ int server_name2index(const char *svname, __u32 *idx, const char **endptr) if (rc != 0) return rc; - if (*dash != '-') - return -EINVAL; - dash++; if (strncmp(dash, "MDT", 3) == 0) @@ -744,11 +741,20 @@ int server_name2index(const char *svname, __u32 *idx, const char **endptr) dash += 3; - if (strcmp(dash, "all") == 0) + if (strncmp(dash, "all", 3) == 0) { + if (endptr != NULL) + *endptr = dash + 3; return rc | LDD_F_SV_ALL; + } index = simple_strtoul(dash, (char **)endptr, 16); - *idx = index; + if (idx != NULL) + *idx = index; + + /* Account for -mdc after index that is possible when specifying mdt */ + if (endptr != NULL && strncmp(LUSTRE_MDC_NAME, *endptr + 1, + sizeof(LUSTRE_MDC_NAME)-1) == 0) + *endptr += sizeof(LUSTRE_MDC_NAME); return rc; } @@ -858,13 +864,15 @@ static int lmd_make_exclusion(struct lustre_mount_data *lmd, const char *ptr) s1++; rc = server_name2index(s1, &index, &s2); if (rc < 0) { - CERROR("Can't parse server name '%s'\n", s1); + CERROR("Can't parse server name '%s': rc = %d\n", + s1, rc); break; } if (rc == LDD_F_SV_TYPE_OST) exclude_list[lmd->lmd_exclude_count++] = index; else - CDEBUG(D_MOUNT, "ignoring exclude %.7s\n", s1); + CDEBUG(D_MOUNT, "ignoring exclude %.*s: type = %#x\n", + (uint)(s2-s1), s1, rc); s1 = s2; /* now we are pointing at ':' (next exclude) or ',' (end of excludes) */ From bd994071a9b680fd2a6ba60c640700af111b037b Mon Sep 17 00:00:00 2001 From: Fan Yong Date: Tue, 23 Jul 2013 00:07:01 +0800 Subject: [PATCH 0348/3400] staging/lustre/llite: return valid fsid for statfs Lustre uses 64-bits inode number to identify object on client side. When re-export Lustre via NFS, NFS will detect whether support fsid via statfs(). For the non-support case, it will only recognizes and packs low 32-bits inode number in nfs handle. Such handle cannot be used to locate the object properly. To avoid patch linux kernel, Lustre client should generate fsid and return it via statfs() to up layer. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2904 Lustre-change: http://review.whamcloud.com/6493 Signed-off-by: Fan Yong Reviewed-by: Andreas Dilger Reviewed-by: Lai Siyao Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/llite/llite_internal.h | 2 ++ drivers/staging/lustre/lustre/llite/llite_lib.c | 6 ++++-- drivers/staging/lustre/lustre/llite/llite_nfs.c | 16 ++++++++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 0534665df905..28aed684364f 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -505,6 +505,7 @@ struct ll_sb_info { * clustred nfs */ struct rmtacl_ctl_table ll_rct; struct eacl_table ll_et; + __kernel_fsid_t ll_fsid; }; #define LL_DEFAULT_MAX_RW_CHUNK (32 * 1024 * 1024) @@ -833,6 +834,7 @@ char *ll_get_fsname(struct super_block *sb, char *buf, int buflen); /* llite/llite_nfs.c */ extern struct export_operations lustre_export_operations; __u32 get_uuid2int(const char *name, int len); +void get_uuid2fsid(const char *name, int len, __kernel_fsid_t *fsid); struct inode *search_inode_for_lustre(struct super_block *sb, const struct lu_fid *fid); diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 39d519b30cb4..d7d87b1539b4 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -583,8 +583,10 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, /* s_dev is also used in lt_compare() to compare two fs, but that is * only a node-local comparison. */ uuid = obd_get_uuid(sbi->ll_md_exp); - if (uuid != NULL) + if (uuid != NULL) { sb->s_dev = get_uuid2int(uuid->uuid, strlen(uuid->uuid)); + get_uuid2fsid(uuid->uuid, strlen(uuid->uuid), &sbi->ll_fsid); + } if (data != NULL) OBD_FREE_PTR(data); @@ -1615,7 +1617,7 @@ int ll_statfs(struct dentry *de, struct kstatfs *sfs) sfs->f_blocks = osfs.os_blocks; sfs->f_bfree = osfs.os_bfree; sfs->f_bavail = osfs.os_bavail; - + sfs->f_fsid = ll_s2sbi(sb)->ll_fsid; return 0; } diff --git a/drivers/staging/lustre/lustre/llite/llite_nfs.c b/drivers/staging/lustre/lustre/llite/llite_nfs.c index f142a1ec3f86..b830004803e4 100644 --- a/drivers/staging/lustre/lustre/llite/llite_nfs.c +++ b/drivers/staging/lustre/lustre/llite/llite_nfs.c @@ -58,6 +58,22 @@ __u32 get_uuid2int(const char *name, int len) return (key0 << 1); } +void get_uuid2fsid(const char *name, int len, __kernel_fsid_t *fsid) +{ + __u64 key = 0, key0 = 0x12a3fe2d, key1 = 0x37abe8f9; + + while (len--) { + key = key1 + (key0 ^ (*name++ * 7152373)); + if (key & 0x8000000000000000ULL) + key -= 0x7fffffffffffffffULL; + key1 = key0; + key0 = key; + } + + fsid->val[0] = key; + fsid->val[1] = key >> 32; +} + static int ll_nfs_test_inode(struct inode *inode, void *opaque) { return lu_fid_eq(&ll_i2info(inode)->lli_fid, From cb6a2db640d94a9dc29dabb9bf58d4ff2531d42c Mon Sep 17 00:00:00 2001 From: Keith Mannthey Date: Tue, 23 Jul 2013 00:07:02 +0800 Subject: [PATCH 0349/3400] staging/lustre/llite: error of listxattr when buffer is small According to the standard, listxattr(2) should return -1 and errno should be set to ERANGE if the size of the list buffer is too small to hold the result. However ll_listxattr() will return a value bigger than the size of buffer in some cases. Let's assume listxattr(2) returns SIZE when it is called with a large enough list buffer. If it's called again with a list buffer whose size is smaller than SIZE but bigger than (SIZE - 12), then listxattr(2) will return SIZE too. This patch fixes the problem. Original patch by Li Xi Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3403 Lustre-change: http://review.whamcloud.com/6463 Signed-off-by: Keith Mannthey Reviewed-by: Li Xi Reviewed-by: Dmitry Eremin Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/xattr.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/llite/xattr.c b/drivers/staging/lustre/lustre/llite/xattr.c index 0a11902c4d2b..2e3ff6d088bc 100644 --- a/drivers/staging/lustre/lustre/llite/xattr.c +++ b/drivers/staging/lustre/lustre/llite/xattr.c @@ -564,7 +564,12 @@ ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size) const size_t name_len = sizeof("lov") - 1; const size_t total_len = prefix_len + name_len + 1; - if (buffer && (rc + total_len) <= size) { + if (((rc + total_len) > size) && (buffer != NULL)) { + ptlrpc_req_finished(request); + return -ERANGE; + } + + if (buffer != NULL) { buffer += rc; memcpy(buffer, XATTR_LUSTRE_PREFIX, prefix_len); memcpy(buffer + prefix_len, "lov", name_len); From 4c2060a8942223ee91764736439085d586538f24 Mon Sep 17 00:00:00 2001 From: Patrick Farrell Date: Tue, 23 Jul 2013 00:07:03 +0800 Subject: [PATCH 0350/3400] staging/lustre/llite: Anonymous dentry incorrectly identified as root When exporting Lustre via NFS on SLES11SP2, this check incorrectly identifies anonymous dentries as root dentries. This is due to a change in SLES11SP2 which makes the d_name.name for anonymous dentries the same as that for root dentries. (Details in LU-3484.) This changes the check to directly compare the value of the dentry pointer to the root dentry pointer found in the superblock, rather than using the name. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3484 Lustre-change: http://review.whamcloud.com/6726 Signed-off-by: Patrick Farrell Reviewed-by: Bob Glossman Reviewed-by: Andreas Dilger Reviewed-by: Peng Tao Reviewed-by: James Simmons Reviewed-by: Alexey Shvetsov Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/dcache.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/dcache.c b/drivers/staging/lustre/lustre/llite/dcache.c index a160a840d582..0d49e1bfb6bb 100644 --- a/drivers/staging/lustre/lustre/llite/dcache.c +++ b/drivers/staging/lustre/lustre/llite/dcache.c @@ -295,9 +295,10 @@ void ll_invalidate_aliases(struct inode *inode) dentry->d_name.name, dentry, dentry->d_parent, dentry->d_inode, dentry->d_flags); - if (dentry->d_name.len == 1 && dentry->d_name.name[0] == '/') { - CERROR("called on root (?) dentry=%p, inode=%p " - "ino=%lu\n", dentry, inode, inode->i_ino); + if (unlikely(dentry == dentry->d_sb->s_root)) { + CERROR("%s: called on root dentry=%p, fid="DFID"\n", + ll_get_fsname(dentry->d_sb, NULL, 0), + dentry, PFID(ll_inode2fid(inode))); lustre_dump_dentry(dentry, 1); dump_stack(); } From 73e8636e4231c3078a4a02f63702d78bf24d55af Mon Sep 17 00:00:00 2001 From: Keith Mannthey Date: Tue, 23 Jul 2013 00:07:06 +0800 Subject: [PATCH 0351/3400] staging/lustre/style: removes obsolete EXPORT_SYMTAB macros v2 EXPORT_SYMTAB is obsolete after 2.4 kernel, this patch removes EXPORT_SYMTAB from the source code again. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-1347 Lustre-change: http://review.whamcloud.com/6739 Signed-off-by: Keith Mannthey Reviewed-by: Peng Tao Reviewed-by: Liu Xuezhao Reviewed-by: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/libcfs/libcfs_cpu.c | 3 --- drivers/staging/lustre/lustre/libcfs/libcfs_lock.c | 3 --- drivers/staging/lustre/lustre/libcfs/libcfs_mem.c | 3 --- drivers/staging/lustre/lustre/obdclass/llog_osd.c | 4 ---- 4 files changed, 13 deletions(-) diff --git a/drivers/staging/lustre/lustre/libcfs/libcfs_cpu.c b/drivers/staging/lustre/lustre/libcfs/libcfs_cpu.c index 8e88eb59dd51..1fb37008cda2 100644 --- a/drivers/staging/lustre/lustre/libcfs/libcfs_cpu.c +++ b/drivers/staging/lustre/lustre/libcfs/libcfs_cpu.c @@ -33,9 +33,6 @@ * Author: liang@whamcloud.com */ -#ifndef EXPORT_SYMTAB -# define EXPORT_SYMTAB -#endif #define DEBUG_SUBSYSTEM S_LNET #include diff --git a/drivers/staging/lustre/lustre/libcfs/libcfs_lock.c b/drivers/staging/lustre/lustre/libcfs/libcfs_lock.c index 8d6c4adf2ee6..a2ce4c0eb3dc 100644 --- a/drivers/staging/lustre/lustre/libcfs/libcfs_lock.c +++ b/drivers/staging/lustre/lustre/libcfs/libcfs_lock.c @@ -30,9 +30,6 @@ * Author: liang@whamcloud.com */ -#ifndef EXPORT_SYMTAB -# define EXPORT_SYMTAB -#endif #define DEBUG_SUBSYSTEM S_LNET #include diff --git a/drivers/staging/lustre/lustre/libcfs/libcfs_mem.c b/drivers/staging/lustre/lustre/libcfs/libcfs_mem.c index 879137303482..feab537c728c 100644 --- a/drivers/staging/lustre/lustre/libcfs/libcfs_mem.c +++ b/drivers/staging/lustre/lustre/libcfs/libcfs_mem.c @@ -31,9 +31,6 @@ * Author: liang@whamcloud.com */ -#ifndef EXPORT_SYMTAB -# define EXPORT_SYMTAB -#endif #define DEBUG_SUBSYSTEM S_LNET #include diff --git a/drivers/staging/lustre/lustre/obdclass/llog_osd.c b/drivers/staging/lustre/lustre/obdclass/llog_osd.c index 6dbd21a863c2..87d5012cfc56 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog_osd.c +++ b/drivers/staging/lustre/lustre/obdclass/llog_osd.c @@ -41,10 +41,6 @@ #define DEBUG_SUBSYSTEM S_LOG -#ifndef EXPORT_SYMTAB -#define EXPORT_SYMTAB -#endif - #include #include #include From 99a92265bd61d7934542c5f398fd241c30287b70 Mon Sep 17 00:00:00 2001 From: jcl Date: Tue, 23 Jul 2013 00:07:07 +0800 Subject: [PATCH 0352/3400] staging/lustre/mdt: HSM on disk actions record HSM coordinator memorizes all actions in a llog This patch implements the methods needed to create update display these records. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3339 Lustre-change: http://review.whamcloud.com/6529 Signed-off-by: JC Lafoucriere Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../lustre/lustre/include/lprocfs_status.h | 3 - .../lustre/lustre/include/lustre/lustre_idl.h | 47 ++++++++++++++++ .../lustre/lustre/include/lustre_disk.h | 56 ++++++++++--------- drivers/staging/lustre/lustre/include/obd.h | 7 ++- .../lustre/lustre/obdclass/llog_swab.c | 17 ++++++ 5 files changed, 97 insertions(+), 33 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/lprocfs_status.h b/drivers/staging/lustre/lustre/include/lprocfs_status.h index 294fb7807c8c..7a0536436120 100644 --- a/drivers/staging/lustre/lustre/include/lprocfs_status.h +++ b/drivers/staging/lustre/lustre/include/lprocfs_status.h @@ -826,9 +826,6 @@ extern int lprocfs_quota_rd_qs_factor(char *page, char **start, loff_t off, extern int lprocfs_quota_wr_qs_factor(struct file *file, const char *buffer, unsigned long count, void *data); - - - #else /* LPROCFS is not defined */ diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 3aaa869b711f..984235ccd3a5 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -2986,6 +2986,7 @@ typedef enum { /* LLOG_JOIN_REC = LLOG_OP_MAGIC | 0x50000, obsolete 1.8.0 */ CHANGELOG_REC = LLOG_OP_MAGIC | 0x60000, CHANGELOG_USER_REC = LLOG_OP_MAGIC | 0x70000, + HSM_AGENT_REC = LLOG_OP_MAGIC | 0x80000, LLOG_HDR_MAGIC = LLOG_OP_MAGIC | 0x45539, LLOG_LOGID_MAGIC = LLOG_OP_MAGIC | 0x4553b, } llog_op_type; @@ -3105,6 +3106,52 @@ struct llog_changelog_user_rec { struct llog_rec_tail cur_tail; } __attribute__((packed)); +enum agent_req_status { + ARS_WAITING, + ARS_STARTED, + ARS_FAILED, + ARS_CANCELED, + ARS_SUCCEED, +}; + +static inline char *agent_req_status2name(enum agent_req_status ars) +{ + switch (ars) { + case ARS_WAITING: + return "WAITING"; + case ARS_STARTED: + return "STARTED"; + case ARS_FAILED: + return "FAILED"; + case ARS_CANCELED: + return "CANCELED"; + case ARS_SUCCEED: + return "SUCCEED"; + default: + return "UNKNOWN"; + } +} + +static inline bool agent_req_in_final_state(enum agent_req_status ars) +{ + return ((ars == ARS_SUCCEED) || (ars == ARS_FAILED) || + (ars == ARS_CANCELED)); +} + +struct llog_agent_req_rec { + struct llog_rec_hdr arr_hdr; /**< record header */ + __u32 arr_status; /**< status of the request */ + /* must match enum + * agent_req_status */ + __u32 arr_archive_id; /**< backend archive number */ + __u64 arr_flags; /**< req flags */ + __u64 arr_compound_id; /**< compound cookie */ + __u64 arr_req_create; /**< req. creation time */ + __u64 arr_req_change; /**< req. status change time */ + struct hsm_action_item arr_hai; /**< req. to the agent */ + struct llog_rec_tail arr_tail; /**< record tail for_sizezof_only */ +} __attribute__((packed)); + /* Old llog gen for compatibility */ struct llog_gen { __u64 mnt_cnt; diff --git a/drivers/staging/lustre/lustre/include/lustre_disk.h b/drivers/staging/lustre/lustre/include/lustre_disk.h index 8db6086ea4ea..9228b165b258 100644 --- a/drivers/staging/lustre/lustre/include/lustre_disk.h +++ b/drivers/staging/lustre/lustre/include/lustre_disk.h @@ -53,20 +53,21 @@ /****************** on-disk files *********************/ -#define MDT_LOGS_DIR "LOGS" /* COMPAT_146 */ -#define MOUNT_CONFIGS_DIR "CONFIGS" -#define CONFIGS_FILE "mountdata" +#define MDT_LOGS_DIR "LOGS" /* COMPAT_146 */ +#define MOUNT_CONFIGS_DIR "CONFIGS" +#define CONFIGS_FILE "mountdata" /** Persistent mount data are stored on the disk in this file. */ -#define MOUNT_DATA_FILE MOUNT_CONFIGS_DIR"/"CONFIGS_FILE -#define LAST_RCVD "last_rcvd" -#define LOV_OBJID "lov_objid" +#define MOUNT_DATA_FILE MOUNT_CONFIGS_DIR"/"CONFIGS_FILE +#define LAST_RCVD "last_rcvd" +#define LOV_OBJID "lov_objid" #define LOV_OBJSEQ "lov_objseq" -#define HEALTH_CHECK "health_check" -#define CAPA_KEYS "capa_keys" -#define CHANGELOG_USERS "changelog_users" -#define MGS_NIDTBL_DIR "NIDTBL_VERSIONS" -#define QMT_DIR "quota_master" -#define QSD_DIR "quota_slave" +#define HEALTH_CHECK "health_check" +#define CAPA_KEYS "capa_keys" +#define CHANGELOG_USERS "changelog_users" +#define MGS_NIDTBL_DIR "NIDTBL_VERSIONS" +#define QMT_DIR "quota_master" +#define QSD_DIR "quota_slave" +#define HSM_ACTIONS "hsm_actions" /****************** persistent mount data *********************/ @@ -226,21 +227,22 @@ struct lustre_mount_data { char *lmd_osd_type; /* OSD type */ }; -#define LMD_FLG_SERVER 0x0001 /* Mounting a server */ -#define LMD_FLG_CLIENT 0x0002 /* Mounting a client */ -#define LMD_FLG_ABORT_RECOV 0x0008 /* Abort recovery */ -#define LMD_FLG_NOSVC 0x0010 /* Only start MGS/MGC for servers, - no other services */ -#define LMD_FLG_NOMGS 0x0020 /* Only start target for servers, reusing - existing MGS services */ -#define LMD_FLG_WRITECONF 0x0040 /* Rewrite config log */ -#define LMD_FLG_NOIR 0x0080 /* NO imperative recovery */ -#define LMD_FLG_NOSCRUB 0x0100 /* Do not trigger scrub automatically */ -#define LMD_FLG_MGS 0x0200 /* Also start MGS along with server */ -#define LMD_FLG_IAM 0x0400 /* IAM dir */ -#define LMD_FLG_NO_PRIMNODE 0x0800 /* all nodes are service nodes */ -#define LMD_FLG_VIRGIN 0x1000 /* the service registers first time */ -#define LMD_FLG_UPDATE 0x2000 /* update parameters */ +#define LMD_FLG_SERVER 0x0001 /* Mounting a server */ +#define LMD_FLG_CLIENT 0x0002 /* Mounting a client */ +#define LMD_FLG_ABORT_RECOV 0x0008 /* Abort recovery */ +#define LMD_FLG_NOSVC 0x0010 /* Only start MGS/MGC for servers, + no other services */ +#define LMD_FLG_NOMGS 0x0020 /* Only start target for servers, reusing + existing MGS services */ +#define LMD_FLG_WRITECONF 0x0040 /* Rewrite config log */ +#define LMD_FLG_NOIR 0x0080 /* NO imperative recovery */ +#define LMD_FLG_NOSCRUB 0x0100 /* Do not trigger scrub automatically */ +#define LMD_FLG_MGS 0x0200 /* Also start MGS along with server */ +#define LMD_FLG_IAM 0x0400 /* IAM dir */ +#define LMD_FLG_NO_PRIMNODE 0x0800 /* all nodes are service nodes */ +#define LMD_FLG_VIRGIN 0x1000 /* the service registers first time */ +#define LMD_FLG_UPDATE 0x2000 /* update parameters */ +#define LMD_FLG_HSM 0x4000 /* Start coordinator */ #define lmd_is_client(x) ((x)->lmd_flags & LMD_FLG_CLIENT) diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index fbf997ffa927..797a6afbddaa 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -292,9 +292,10 @@ enum llog_ctxt_id { LLOG_TEST_REPL_CTXT, LLOG_LOVEA_ORIG_CTXT, LLOG_LOVEA_REPL_CTXT, - LLOG_CHANGELOG_ORIG_CTXT, /**< changelog generation on mdd */ - LLOG_CHANGELOG_REPL_CTXT, /**< changelog access on clients */ - LLOG_CHANGELOG_USER_ORIG_CTXT, /**< for multiple changelog consumers */ + LLOG_CHANGELOG_ORIG_CTXT, /**< changelog generation on mdd */ + LLOG_CHANGELOG_REPL_CTXT, /**< changelog access on clients */ + LLOG_CHANGELOG_USER_ORIG_CTXT, /**< for multiple changelog consumers */ + LLOG_AGENT_ORIG_CTXT, /**< agent requests generation on cdt */ LLOG_MAX_CTXTS }; diff --git a/drivers/staging/lustre/lustre/obdclass/llog_swab.c b/drivers/staging/lustre/lustre/obdclass/llog_swab.c index dedfecff95bc..a75b04ee5272 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog_swab.c +++ b/drivers/staging/lustre/lustre/obdclass/llog_swab.c @@ -203,6 +203,23 @@ void lustre_swab_llog_rec(struct llog_rec_hdr *rec) break; } + case HSM_AGENT_REC: { + struct llog_agent_req_rec *arr = + (struct llog_agent_req_rec *)rec; + + __swab32s(&arr->arr_hai.hai_len); + __swab32s(&arr->arr_hai.hai_action); + lustre_swab_lu_fid(&arr->arr_hai.hai_fid); + lustre_swab_lu_fid(&arr->arr_hai.hai_dfid); + __swab64s(&arr->arr_hai.hai_cookie); + __swab64s(&arr->arr_hai.hai_extent.offset); + __swab64s(&arr->arr_hai.hai_extent.length); + __swab64s(&arr->arr_hai.hai_gid); + /* no swabing for opaque data */ + /* hai_data[0]; */ + break; + } + case MDS_SETATTR64_REC: { struct llog_setattr64_rec *lsr = From 70b749d43d1654a4fda1b281ad08d194d6aada2b Mon Sep 17 00:00:00 2001 From: Fan Yong Date: Tue, 23 Jul 2013 00:07:08 +0800 Subject: [PATCH 0353/3400] staging/lustre/scrub: purge inconsistenct objects after OI scrub When OI scrub repaired the found inconsistency, it needs to purge the old object out of cache; otherwise, others may still use those cached stale information. Original patch adds functions in obdclass that is only used by server. Drop that part. Only merge in error handling change. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3335 Lustre-change: http://review.whamcloud.com/6697 Signed-off-by: Fan Yong Reviewed-by: Alex Zhuravlev Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/lu_object.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/lustre/lustre/obdclass/lu_object.c b/drivers/staging/lustre/lustre/obdclass/lu_object.c index 5559732c0437..ce0444f6911c 100644 --- a/drivers/staging/lustre/lustre/obdclass/lu_object.c +++ b/drivers/staging/lustre/lustre/obdclass/lu_object.c @@ -538,7 +538,7 @@ static struct lu_object *htable_lookup(struct lu_site *s, __u64 ver = cfs_hash_bd_version_get(bd); if (*version == ver) - return NULL; + return ERR_PTR(-ENOENT); *version = ver; bkt = cfs_hash_bd_extra_get(s->ls_obj_hash, bd); @@ -547,7 +547,7 @@ static struct lu_object *htable_lookup(struct lu_site *s, hnode = cfs_hash_bd_peek_locked(s->ls_obj_hash, bd, (void *)f); if (hnode == NULL) { lprocfs_counter_incr(s->ls_stats, LU_SS_CACHE_MISS); - return NULL; + return ERR_PTR(-ENOENT); } h = container_of0(hnode, struct lu_object_header, loh_hash); @@ -651,7 +651,7 @@ static struct lu_object *lu_object_find_try(const struct lu_env *env, cfs_hash_bd_get_and_lock(hs, (void *)f, &bd, 1); o = htable_lookup(s, &bd, f, waiter, &version); cfs_hash_bd_unlock(hs, &bd, 1); - if (o != NULL) + if (!IS_ERR(o) || PTR_ERR(o) != -ENOENT) return o; /* @@ -667,7 +667,7 @@ static struct lu_object *lu_object_find_try(const struct lu_env *env, cfs_hash_bd_lock(hs, &bd, 1); shadow = htable_lookup(s, &bd, f, waiter, &version); - if (likely(shadow == NULL)) { + if (likely(IS_ERR(shadow) && PTR_ERR(shadow) == -ENOENT)) { struct lu_site_bkt_data *bkt; bkt = cfs_hash_bd_extra_get(hs, &bd); @@ -2076,7 +2076,7 @@ void lu_object_assign_fid(const struct lu_env *env, struct lu_object *o, cfs_hash_bd_get_and_lock(hs, (void *)fid, &bd, 1); shadow = htable_lookup(s, &bd, fid, &waiter, &version); /* supposed to be unique */ - LASSERT(shadow == NULL); + LASSERT(IS_ERR(shadow) && PTR_ERR(shadow) == -ENOENT); *old = *fid; bkt = cfs_hash_bd_extra_get(hs, &bd); cfs_hash_bd_add_locked(hs, &bd, &o->lo_header->loh_hash); From cd6b328cd0c79bba866ffb60ff447b84cfaacf3b Mon Sep 17 00:00:00 2001 From: Bruno Faccini Date: Tue, 23 Jul 2013 00:07:09 +0800 Subject: [PATCH 0354/3400] staging/lustre/mdc: Keep resend FLocks FLocks requests (particulary F_UNLCKs) can't be trashed upon comm problems with Server/MDS nor upon kill/exit, thus we need to keep retry/send. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2665 Lustre-change: http://review.whamcloud.com/6415 Signed-off-by: Bruno Faccini Reviewed-by: Bobi Jam Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/mdc/mdc_locks.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/mdc/mdc_locks.c b/drivers/staging/lustre/lustre/mdc/mdc_locks.c index ab88a46c1a27..803c390e1c35 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_locks.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_locks.c @@ -823,7 +823,13 @@ resend: /* For flock requests we immediatelly return without further delay and let caller deal with the rest, since rest of this function metadata processing makes no sense for flock - requests anyway */ + requests anyway. But in case of problem during comms with + Server (ETIMEDOUT) or any signal/kill attempt (EINTR), we + can not rely on caller and this mainly for F_UNLCKs + (explicits or automatically generated by Kernel to clean + current FLocks upon exit) that can't be trashed */ + if ((rc == -EINTR) || (rc == -ETIMEDOUT)) + goto resend; RETURN(rc); } From c4f395539790680e6ab772876ddca4620e019c14 Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Sun, 21 Jul 2013 03:38:08 +0900 Subject: [PATCH 0355/3400] staging: lustre: Fix typo in printk Correct spelling typo in printk within staging/lustre Signed-off-by: Masanari Iida Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/vvp_io.c | 2 +- drivers/staging/lustre/lustre/obdclass/genops.c | 2 +- drivers/staging/lustre/lustre/obdecho/echo_client.c | 2 +- drivers/staging/lustre/lustre/ptlrpc/gss/gss_krb5_mech.c | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index 23149f96f136..50a4c9104f6d 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -970,7 +970,7 @@ static int vvp_io_commit_write(const struct lu_env *env, LINVRNT(cl_page_is_vmlocked(env, pg)); LASSERT(vmpage->mapping->host == inode); - LU_OBJECT_HEADER(D_INODE, env, &obj->co_lu, "commiting page write\n"); + LU_OBJECT_HEADER(D_INODE, env, &obj->co_lu, "committing page write\n"); CL_PAGE_HEADER(D_PAGE, env, pg, "committing: [%d, %d]\n", from, to); /* diff --git a/drivers/staging/lustre/lustre/obdclass/genops.c b/drivers/staging/lustre/lustre/obdclass/genops.c index d96876e0bc68..ea041a34f5f7 100644 --- a/drivers/staging/lustre/lustre/obdclass/genops.c +++ b/drivers/staging/lustre/lustre/obdclass/genops.c @@ -1484,7 +1484,7 @@ int obd_export_evict_by_uuid(struct obd_device *obd, const char *uuid) CERROR("%s: can't disconnect %s: no exports found\n", obd->obd_name, uuid); } else { - CWARN("%s: evicting %s at adminstrative request\n", + CWARN("%s: evicting %s at administrative request\n", obd->obd_name, doomed_exp->exp_client_uuid.uuid); class_fail_export(doomed_exp); class_export_put(doomed_exp); diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c index de8f4ea7f156..2e52ef2f92a9 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c @@ -649,7 +649,7 @@ static int echo_site_init(const struct lu_env *env, struct echo_device *ed) /* initialize site */ rc = cl_site_init(site, &ed->ed_cl); if (rc) { - CERROR("Cannot initilize site for echo client(%d)\n", rc); + CERROR("Cannot initialize site for echo client(%d)\n", rc); return rc; } diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_krb5_mech.c b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_krb5_mech.c index 4b28931bbc96..91da7637756d 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_krb5_mech.c +++ b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_krb5_mech.c @@ -341,7 +341,7 @@ __u32 import_context_rfc1964(struct krb5_ctx *kctx, char *p, char *end) if (p != end) goto out_err; - CDEBUG(D_SEC, "succesfully imported rfc1964 context\n"); + CDEBUG(D_SEC, "successfully imported rfc1964 context\n"); return 0; out_err: return GSS_S_FAILURE; @@ -403,7 +403,7 @@ __u32 import_context_rfc4121(struct krb5_ctx *kctx, char *p, char *end) if (get_keyblock(&p, end, &kctx->kc_keyc, keysize)) goto out_err; - CDEBUG(D_SEC, "succesfully imported v2 context\n"); + CDEBUG(D_SEC, "successfully imported v2 context\n"); return 0; out_err: return GSS_S_FAILURE; @@ -494,7 +494,7 @@ __u32 gss_copy_reverse_context_kerberos(struct gss_ctx *gctx, goto out_err; gctx_new->internal_ctx_id = knew; - CDEBUG(D_SEC, "succesfully copied reverse context\n"); + CDEBUG(D_SEC, "successfully copied reverse context\n"); return GSS_S_COMPLETE; out_err: From 1dc8548c307c1cbab90cb9c754effb2d030cafdd Mon Sep 17 00:00:00 2001 From: Laurent Navet Date: Fri, 5 Jul 2013 14:26:33 +0200 Subject: [PATCH 0356/3400] staging: lustre: use ERR_CAST() function use ERR_CAST() function instead of ERR_PTR() and PTR_ERR() found using coccinelle and err_cast.cocci Signed-off-by: Laurent Navet Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/llite_nfs.c | 2 +- drivers/staging/lustre/lustre/llite/rw.c | 2 +- drivers/staging/lustre/lustre/obdclass/local_storage.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/llite_nfs.c b/drivers/staging/lustre/lustre/llite/llite_nfs.c index b830004803e4..32362ece2a7b 100644 --- a/drivers/staging/lustre/lustre/llite/llite_nfs.c +++ b/drivers/staging/lustre/lustre/llite/llite_nfs.c @@ -147,7 +147,7 @@ ll_iget_for_nfs(struct super_block *sb, struct lu_fid *fid, struct lu_fid *paren inode = search_inode_for_lustre(sb, fid); if (IS_ERR(inode)) - RETURN(ERR_PTR(PTR_ERR(inode))); + RETURN(ERR_CAST(inode)); if (is_bad_inode(inode)) { /* we didn't find the right inode.. */ diff --git a/drivers/staging/lustre/lustre/llite/rw.c b/drivers/staging/lustre/lustre/llite/rw.c index f48766e6a212..43b5f0d2b72a 100644 --- a/drivers/staging/lustre/lustre/llite/rw.c +++ b/drivers/staging/lustre/lustre/llite/rw.c @@ -110,7 +110,7 @@ static struct ll_cl_context *ll_cl_init(struct file *file, env = cl_env_get(&refcheck); if (IS_ERR(env)) - return ERR_PTR(PTR_ERR(env)); + return ERR_CAST(env); lcc = &vvp_env_info(env)->vti_io_ctx; memset(lcc, 0, sizeof(*lcc)); diff --git a/drivers/staging/lustre/lustre/obdclass/local_storage.c b/drivers/staging/lustre/lustre/obdclass/local_storage.c index 3be35a83a495..e1db7abd300a 100644 --- a/drivers/staging/lustre/lustre/obdclass/local_storage.c +++ b/drivers/staging/lustre/lustre/obdclass/local_storage.c @@ -443,7 +443,7 @@ struct dt_object *local_file_find_or_create_with_fid(const struct lu_env *env, ls = ls_device_get(dt); if (IS_ERR(ls)) { - dto = ERR_PTR(PTR_ERR(ls)); + dto = ERR_CAST(ls); } else { /* create the object */ dti->dti_attr.la_valid = LA_MODE; @@ -537,7 +537,7 @@ local_index_find_or_create_with_fid(const struct lu_env *env, ls = ls_device_get(dt); if (IS_ERR(ls)) { - dto = ERR_PTR(PTR_ERR(ls)); + dto = ERR_CAST(ls); } else { /* create the object */ dti->dti_attr.la_valid = LA_MODE; From b0d67ac7771683b08a29fc21101e785a724cb7a6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 23 Jul 2013 14:02:13 -0700 Subject: [PATCH 0357/3400] staging: lustre: remove unused "helper" macros This removes a bunch of unused helper macros in the kp30.h file as they were not being used anywhere, and they better not be used in the future. Cc: Peng Tao Cc: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../lustre/include/linux/libcfs/linux/kp30.h | 42 ------------------- 1 file changed, 42 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h b/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h index 4b7ae1c5bd3b..5ba099595a99 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h @@ -74,34 +74,6 @@ #include -#define prepare_work(wq,cb,cbdata) \ -do { \ - INIT_WORK((wq), (void *)(cb)); \ -} while (0) - -#define cfs_get_work_data(type,field,data) container_of(data,type,field) - - -#define our_recalc_sigpending(current) recalc_sigpending() -#define strtok(a,b) strpbrk(a, b) -#define work_struct_t struct work_struct - -#ifdef CONFIG_SMP -#else -#endif - - -#define SEM_COUNT(sem) ((sem)->count) - - -/* ------------------------------------------------------------------- */ - -#define PORTAL_SYMBOL_REGISTER(x) -#define PORTAL_SYMBOL_UNREGISTER(x) - - - - /******************************************************************************/ /* Module parameter support */ #define CFS_MODULE_PARM(name, t, type, perm, desc) \ @@ -112,24 +84,10 @@ do { \ /******************************************************************************/ -#if (__GNUC__) -/* Use the special GNU C __attribute__ hack to have the compiler check the - * printf style argument string against the actual argument count and - * types. - */ -#ifdef printf -# warning printf has been defined as a macro... -# undef printf -#endif - -#endif /* __GNUC__ */ - # define fprintf(a, format, b...) CDEBUG(D_OTHER, format , ## b) # define printf(format, b...) CDEBUG(D_OTHER, format , ## b) # define time(a) CURRENT_TIME -# define cfs_num_present_cpus() num_present_cpus() - /******************************************************************************/ /* Light-weight trace * Support for temporary event tracing with minimal Heisenberg effect. */ From 54db996e6dab51571718e8e97c26fdc695e254ac Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 24 Jun 2013 16:55:14 -0700 Subject: [PATCH 0358/3400] staging: comedi: drivers: introduce comedi_alloc_devpriv() Introduce a helper function to allocate memory and set the comedi_device private data pointer. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedidev.h | 1 + drivers/staging/comedi/drivers.c | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index b75915f30f48..bfbe4160edf0 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -357,6 +357,7 @@ void comedi_buf_memcpy_from(struct comedi_async *async, unsigned int offset, /* drivers.c - general comedi driver functions */ +void *comedi_alloc_devpriv(struct comedi_device *, size_t); int comedi_alloc_subdevices(struct comedi_device *, int); int comedi_load_firmware(struct comedi_device *, struct device *, diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index e25eba5713c1..87df7960c96f 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -57,6 +57,18 @@ static void comedi_clear_hw_dev(struct comedi_device *dev) dev->hw_dev = NULL; } +/** + * comedi_alloc_devpriv() - Allocate memory for the device private data. + * @dev: comedi_device struct + * @size: size of the memory to allocate + */ +void *comedi_alloc_devpriv(struct comedi_device *dev, size_t size) +{ + dev->private = kzalloc(size, GFP_KERNEL); + return dev->private; +} +EXPORT_SYMBOL_GPL(comedi_alloc_devpriv); + int comedi_alloc_subdevices(struct comedi_device *dev, int num_subdevices) { struct comedi_subdevice *s; From 0bdab509bf9c6d838dc0a3b1d68bbf841fc20b5a Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 24 Jun 2013 16:55:44 -0700 Subject: [PATCH 0359/3400] staging: comedi: use comedi_alloc_devpriv() Use the helper function to allocate memory and set the comedi_device private data pointer. This removes the dependency on slab.h from most of the drivers so remove the global #include in comedidev.h and the local #include in some of the drivers. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedidev.h | 1 - drivers/staging/comedi/drivers/8255_pci.c | 3 +-- drivers/staging/comedi/drivers/addi-data/addi_common.c | 3 +-- drivers/staging/comedi/drivers/addi_apci_1032.c | 3 +-- drivers/staging/comedi/drivers/addi_apci_1516.c | 3 +-- drivers/staging/comedi/drivers/addi_apci_1710.c | 3 +-- drivers/staging/comedi/drivers/addi_apci_3120.c | 3 +-- drivers/staging/comedi/drivers/addi_apci_3501.c | 3 +-- drivers/staging/comedi/drivers/addi_apci_3xxx.c | 3 +-- drivers/staging/comedi/drivers/adl_pci6208.c | 3 +-- drivers/staging/comedi/drivers/adl_pci9111.c | 3 +-- drivers/staging/comedi/drivers/adl_pci9118.c | 6 ++---- drivers/staging/comedi/drivers/adq12b.c | 3 +-- drivers/staging/comedi/drivers/adv_pci1710.c | 3 +-- drivers/staging/comedi/drivers/adv_pci1723.c | 3 +-- drivers/staging/comedi/drivers/adv_pci1724.c | 3 +-- drivers/staging/comedi/drivers/adv_pci_dio.c | 3 +-- drivers/staging/comedi/drivers/aio_aio12_8.c | 3 +-- drivers/staging/comedi/drivers/amplc_dio200.c | 5 +---- drivers/staging/comedi/drivers/amplc_dio200_common.c | 1 - drivers/staging/comedi/drivers/amplc_dio200_pci.c | 4 +--- drivers/staging/comedi/drivers/amplc_pc236.c | 6 ++---- drivers/staging/comedi/drivers/amplc_pci224.c | 7 ++----- drivers/staging/comedi/drivers/amplc_pci230.c | 3 +-- drivers/staging/comedi/drivers/cb_das16_cs.c | 4 +--- drivers/staging/comedi/drivers/cb_pcidas.c | 3 +-- drivers/staging/comedi/drivers/cb_pcidas64.c | 3 +-- drivers/staging/comedi/drivers/cb_pcidda.c | 3 +-- drivers/staging/comedi/drivers/cb_pcimdas.c | 3 +-- drivers/staging/comedi/drivers/cb_pcimdda.c | 3 +-- drivers/staging/comedi/drivers/comedi_bond.c | 3 +-- drivers/staging/comedi/drivers/comedi_parport.c | 3 +-- drivers/staging/comedi/drivers/comedi_test.c | 3 +-- drivers/staging/comedi/drivers/daqboard2000.c | 3 +-- drivers/staging/comedi/drivers/das08_cs.c | 4 +--- drivers/staging/comedi/drivers/das08_isa.c | 3 +-- drivers/staging/comedi/drivers/das08_pci.c | 3 +-- drivers/staging/comedi/drivers/das16.c | 4 +--- drivers/staging/comedi/drivers/das16m1.c | 3 +-- drivers/staging/comedi/drivers/das1800.c | 3 +-- drivers/staging/comedi/drivers/das6402.c | 3 +-- drivers/staging/comedi/drivers/das800.c | 3 +-- drivers/staging/comedi/drivers/dmm32at.c | 3 +-- drivers/staging/comedi/drivers/dt2801.c | 3 +-- drivers/staging/comedi/drivers/dt2811.c | 3 +-- drivers/staging/comedi/drivers/dt2814.c | 3 +-- drivers/staging/comedi/drivers/dt2815.c | 3 +-- drivers/staging/comedi/drivers/dt282x.c | 3 +-- drivers/staging/comedi/drivers/dt3000.c | 3 +-- drivers/staging/comedi/drivers/dt9812.c | 4 +--- drivers/staging/comedi/drivers/dyna_pci10xx.c | 3 +-- drivers/staging/comedi/drivers/fl512.c | 3 +-- drivers/staging/comedi/drivers/gsc_hpdi.c | 3 +-- drivers/staging/comedi/drivers/icp_multi.c | 3 +-- drivers/staging/comedi/drivers/ii_pci20kc.c | 3 +-- drivers/staging/comedi/drivers/jr3_pci.c | 3 +-- drivers/staging/comedi/drivers/me4000.c | 3 +-- drivers/staging/comedi/drivers/me_daq.c | 3 +-- drivers/staging/comedi/drivers/mpc624.c | 3 +-- drivers/staging/comedi/drivers/multiq3.c | 3 +-- drivers/staging/comedi/drivers/ni_6527.c | 3 +-- drivers/staging/comedi/drivers/ni_65xx.c | 4 +--- drivers/staging/comedi/drivers/ni_660x.c | 3 +-- drivers/staging/comedi/drivers/ni_670x.c | 4 +--- drivers/staging/comedi/drivers/ni_at_a2150.c | 3 +-- drivers/staging/comedi/drivers/ni_at_ao.c | 3 +-- drivers/staging/comedi/drivers/ni_atmio16d.c | 3 +-- drivers/staging/comedi/drivers/ni_daq_700.c | 1 - drivers/staging/comedi/drivers/ni_labpc.c | 3 +-- drivers/staging/comedi/drivers/ni_labpc_cs.c | 4 +--- drivers/staging/comedi/drivers/ni_labpc_pci.c | 4 +--- drivers/staging/comedi/drivers/ni_mio_common.c | 3 +-- drivers/staging/comedi/drivers/ni_pcidio.c | 3 +-- drivers/staging/comedi/drivers/ni_tio.c | 2 ++ drivers/staging/comedi/drivers/pcl711.c | 3 +-- drivers/staging/comedi/drivers/pcl726.c | 3 +-- drivers/staging/comedi/drivers/pcl812.c | 3 +-- drivers/staging/comedi/drivers/pcl816.c | 3 +-- drivers/staging/comedi/drivers/pcl818.c | 3 +-- drivers/staging/comedi/drivers/pcm3724.c | 3 +-- drivers/staging/comedi/drivers/pcmda12.c | 3 +-- drivers/staging/comedi/drivers/pcmmio.c | 3 +-- drivers/staging/comedi/drivers/pcmuio.c | 3 +-- drivers/staging/comedi/drivers/poc.c | 3 +-- drivers/staging/comedi/drivers/quatech_daqp_cs.c | 3 +-- drivers/staging/comedi/drivers/rtd520.c | 3 +-- drivers/staging/comedi/drivers/rti800.c | 3 +-- drivers/staging/comedi/drivers/rti802.c | 3 +-- drivers/staging/comedi/drivers/s526.c | 3 +-- drivers/staging/comedi/drivers/s626.c | 3 +-- drivers/staging/comedi/drivers/s626.h | 2 -- drivers/staging/comedi/drivers/serial2002.c | 3 +-- drivers/staging/comedi/drivers/skel.c | 6 ++---- drivers/staging/comedi/drivers/unioxx5.c | 1 - drivers/staging/comedi/drivers/usbduxfast.c | 3 +-- drivers/staging/comedi/drivers/usbduxsigma.c | 3 +-- drivers/staging/comedi/drivers/vmk80xx.c | 3 +-- 97 files changed, 97 insertions(+), 208 deletions(-) diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index bfbe4160edf0..c6a7c096f625 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/staging/comedi/drivers/8255_pci.c b/drivers/staging/comedi/drivers/8255_pci.c index 3d3547c19480..b58e28bb206d 100644 --- a/drivers/staging/comedi/drivers/8255_pci.c +++ b/drivers/staging/comedi/drivers/8255_pci.c @@ -186,10 +186,9 @@ static int pci_8255_auto_attach(struct comedi_device *dev, dev->board_ptr = board; dev->board_name = board->name; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; ret = comedi_pci_enable(dev); if (ret) diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c index f25e0085219d..63dff7729ea8 100644 --- a/drivers/staging/comedi/drivers/addi-data/addi_common.c +++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c @@ -85,10 +85,9 @@ static int addi_auto_attach(struct comedi_device *dev, dev->board_name = this_board->pc_DriverName; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; ret = comedi_pci_enable(dev); if (ret) diff --git a/drivers/staging/comedi/drivers/addi_apci_1032.c b/drivers/staging/comedi/drivers/addi_apci_1032.c index 8a93542faedc..242903aac829 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1032.c +++ b/drivers/staging/comedi/drivers/addi_apci_1032.c @@ -289,10 +289,9 @@ static int apci1032_auto_attach(struct comedi_device *dev, struct comedi_subdevice *s; int ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; ret = comedi_pci_enable(dev); if (ret) diff --git a/drivers/staging/comedi/drivers/addi_apci_1516.c b/drivers/staging/comedi/drivers/addi_apci_1516.c index b626738bb73c..7523c8b0e8f7 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1516.c +++ b/drivers/staging/comedi/drivers/addi_apci_1516.c @@ -136,10 +136,9 @@ static int apci1516_auto_attach(struct comedi_device *dev, dev->board_ptr = this_board; dev->board_name = this_board->name; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; ret = comedi_pci_enable(dev); if (ret) diff --git a/drivers/staging/comedi/drivers/addi_apci_1710.c b/drivers/staging/comedi/drivers/addi_apci_1710.c index c9e6471eb06b..e533f55a1d2f 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1710.c +++ b/drivers/staging/comedi/drivers/addi_apci_1710.c @@ -35,10 +35,9 @@ static int apci1710_auto_attach(struct comedi_device *dev, struct comedi_subdevice *s; int ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; ret = comedi_pci_enable(dev); if (ret) diff --git a/drivers/staging/comedi/drivers/addi_apci_3120.c b/drivers/staging/comedi/drivers/addi_apci_3120.c index 61452848510f..a7828bb64a91 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3120.c +++ b/drivers/staging/comedi/drivers/addi_apci_3120.c @@ -65,10 +65,9 @@ static int apci3120_auto_attach(struct comedi_device *dev, dev->board_ptr = this_board; dev->board_name = this_board->pc_DriverName; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; ret = comedi_pci_enable(dev); if (ret) diff --git a/drivers/staging/comedi/drivers/addi_apci_3501.c b/drivers/staging/comedi/drivers/addi_apci_3501.c index f9b63689a12a..9b8544b43b24 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3501.c +++ b/drivers/staging/comedi/drivers/addi_apci_3501.c @@ -332,10 +332,9 @@ static int apci3501_auto_attach(struct comedi_device *dev, int ao_n_chan; int ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; ret = comedi_pci_enable(dev); if (ret) diff --git a/drivers/staging/comedi/drivers/addi_apci_3xxx.c b/drivers/staging/comedi/drivers/addi_apci_3xxx.c index 5b37cbf9228e..cf60248c726d 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3xxx.c +++ b/drivers/staging/comedi/drivers/addi_apci_3xxx.c @@ -801,10 +801,9 @@ static int apci3xxx_auto_attach(struct comedi_device *dev, dev->board_ptr = board; dev->board_name = board->name; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; ret = comedi_pci_enable(dev); if (ret) diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index b5e4e53f737f..ffd91e4f90bf 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -172,10 +172,9 @@ static int pci6208_auto_attach(struct comedi_device *dev, dev->board_ptr = boardinfo; dev->board_name = boardinfo->name; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; ret = comedi_pci_enable(dev); if (ret) diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c index af51c7460048..cf93e416dd29 100644 --- a/drivers/staging/comedi/drivers/adl_pci9111.c +++ b/drivers/staging/comedi/drivers/adl_pci9111.c @@ -855,10 +855,9 @@ static int pci9111_auto_attach(struct comedi_device *dev, struct comedi_subdevice *s; int ret; - dev_private = kzalloc(sizeof(*dev_private), GFP_KERNEL); + dev_private = comedi_alloc_devpriv(dev, sizeof(*dev_private)); if (!dev_private) return -ENOMEM; - dev->private = dev_private; ret = comedi_pci_enable(dev); if (ret) diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c index cb4ef2dcbf02..2a48f8421ca0 100644 --- a/drivers/staging/comedi/drivers/adl_pci9118.c +++ b/drivers/staging/comedi/drivers/adl_pci9118.c @@ -2140,10 +2140,9 @@ static int pci9118_attach(struct comedi_device *dev, softsshdelay = it->options[4]; hw_err_mask = it->options[5]; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; pcidev = pci9118_find_pci(dev, it); if (!pcidev) @@ -2160,10 +2159,9 @@ static int pci9118_auto_attach(struct comedi_device *dev, struct pci_dev *pcidev = comedi_to_pci_dev(dev); struct pci9118_private *devpriv; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; dev->board_ptr = pci9118_find_boardinfo(pcidev); if (dev->board_ptr == NULL) { diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c index d187a7bf0a55..72e88d8465ea 100644 --- a/drivers/staging/comedi/drivers/adq12b.c +++ b/drivers/staging/comedi/drivers/adq12b.c @@ -214,10 +214,9 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; devpriv->unipolar = it->options[1]; devpriv->differential = it->options[2]; diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index f847bbc175e7..53653d3c4937 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -1233,10 +1233,9 @@ static int pci1710_auto_attach(struct comedi_device *dev, dev->board_ptr = this_board; dev->board_name = this_board->name; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; ret = comedi_pci_enable(dev); if (ret) diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c index 8430a27ec1b5..919babae4cbe 100644 --- a/drivers/staging/comedi/drivers/adv_pci1723.c +++ b/drivers/staging/comedi/drivers/adv_pci1723.c @@ -237,10 +237,9 @@ static int pci1723_auto_attach(struct comedi_device *dev, struct comedi_subdevice *s; int ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; ret = comedi_pci_enable(dev); if (ret) diff --git a/drivers/staging/comedi/drivers/adv_pci1724.c b/drivers/staging/comedi/drivers/adv_pci1724.c index da7462e01faa..d27730e2d29f 100644 --- a/drivers/staging/comedi/drivers/adv_pci1724.c +++ b/drivers/staging/comedi/drivers/adv_pci1724.c @@ -340,10 +340,9 @@ static int adv_pci1724_auto_attach(struct comedi_device *dev, int retval; unsigned int board_id; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; /* init software copies of output values to indicate we don't know * what the output value is since it has never been written. */ diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c index 8e6ec75bd294..ff48cb30d4af 100644 --- a/drivers/staging/comedi/drivers/adv_pci_dio.c +++ b/drivers/staging/comedi/drivers/adv_pci_dio.c @@ -1107,10 +1107,9 @@ static int pci_dio_auto_attach(struct comedi_device *dev, dev->board_ptr = this_board; dev->board_name = this_board->name; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; ret = comedi_pci_enable(dev); if (ret) diff --git a/drivers/staging/comedi/drivers/aio_aio12_8.c b/drivers/staging/comedi/drivers/aio_aio12_8.c index 279dfe8951f7..ae88fe1f79d0 100644 --- a/drivers/staging/comedi/drivers/aio_aio12_8.c +++ b/drivers/staging/comedi/drivers/aio_aio12_8.c @@ -202,10 +202,9 @@ static int aio_aio12_8_attach(struct comedi_device *dev, if (ret) return ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; ret = comedi_alloc_subdevices(dev, 4); if (ret) diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c index e2478105ac1a..d1436733e913 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200.c +++ b/drivers/staging/comedi/drivers/amplc_dio200.c @@ -192,8 +192,6 @@ * order they appear in the channel list. */ -#include - #include "../comedidev.h" #include "amplc_dio200.h" @@ -272,10 +270,9 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it) irq = it->options[1]; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; ret = comedi_request_region(dev, it->options[0], thisboard->mainsize); if (ret) diff --git a/drivers/staging/comedi/drivers/amplc_dio200_common.c b/drivers/staging/comedi/drivers/amplc_dio200_common.c index 649fc69724fb..56b783642155 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200_common.c +++ b/drivers/staging/comedi/drivers/amplc_dio200_common.c @@ -20,7 +20,6 @@ */ #include -#include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/amplc_dio200_pci.c b/drivers/staging/comedi/drivers/amplc_dio200_pci.c index d7d9f5cc3ab4..25d9cc00b888 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200_pci.c +++ b/drivers/staging/comedi/drivers/amplc_dio200_pci.c @@ -222,7 +222,6 @@ #include #include -#include #include "../comedidev.h" @@ -380,10 +379,9 @@ static int dio200_pci_auto_attach(struct comedi_device *dev, dev_info(dev->class_dev, "%s: attach pci %s (%s)\n", dev->driver->driver_name, pci_name(pci_dev), dev->board_name); - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; ret = comedi_pci_enable(dev); if (ret) diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index 4e889b82cbf2..81b9b80f8a64 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -467,10 +467,9 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct pc236_private *devpriv; int ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; /* Process options according to bus type. */ if (is_isa_board(thisboard)) { @@ -510,10 +509,9 @@ static int pc236_auto_attach(struct comedi_device *dev, dev_info(dev->class_dev, PC236_DRIVER_NAME ": attach pci %s\n", pci_name(pci_dev)); - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; dev->board_ptr = pc236_find_pci_board(pci_dev); if (dev->board_ptr == NULL) { diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c index f1e36f08b103..043120448cf9 100644 --- a/drivers/staging/comedi/drivers/amplc_pci224.c +++ b/drivers/staging/comedi/drivers/amplc_pci224.c @@ -100,7 +100,6 @@ Caveats: #include #include -#include #include "../comedidev.h" @@ -1419,10 +1418,9 @@ static int pci224_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev_info(dev->class_dev, DRIVER_NAME ": attach\n"); - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; pci_dev = pci224_find_pci_dev(dev, it); if (!pci_dev) @@ -1440,10 +1438,9 @@ pci224_auto_attach(struct comedi_device *dev, unsigned long context_unused) dev_info(dev->class_dev, DRIVER_NAME ": attach pci %s\n", pci_name(pci_dev)); - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; dev->board_ptr = pci224_find_pci_board(pci_dev); if (dev->board_ptr == NULL) { diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c index 846d6448fa4d..147702b51872 100644 --- a/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -2615,10 +2615,9 @@ static int pci230_alloc_private(struct comedi_device *dev) { struct pci230_private *devpriv; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; spin_lock_init(&devpriv->isr_spinlock); spin_lock_init(&devpriv->res_spinlock); diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c index ae9a2082b5a4..ff0f8939ae78 100644 --- a/drivers/staging/comedi/drivers/cb_das16_cs.c +++ b/drivers/staging/comedi/drivers/cb_das16_cs.c @@ -35,7 +35,6 @@ Status: experimental */ #include -#include #include #include "../comedidev.h" @@ -420,10 +419,9 @@ static int das16cs_auto_attach(struct comedi_device *dev, return ret; dev->irq = link->irq; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; ret = comedi_alloc_subdevices(dev, 3); if (ret) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 58bca184bf22..d70d1dd30502 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -1444,10 +1444,9 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev, dev->board_ptr = thisboard; dev->board_name = thisboard->name; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; ret = comedi_pci_enable(dev); if (ret) diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c index 43c0bf58771a..e8222b0fe841 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas64.c +++ b/drivers/staging/comedi/drivers/cb_pcidas64.c @@ -4034,10 +4034,9 @@ static int auto_attach(struct comedi_device *dev, return -ENODEV; dev->board_ptr = thisboard; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; retval = comedi_pci_enable(dev); if (retval) diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c index 2d3e920e5987..c1f0aa59f66f 100644 --- a/drivers/staging/comedi/drivers/cb_pcidda.c +++ b/drivers/staging/comedi/drivers/cb_pcidda.c @@ -348,10 +348,9 @@ static int cb_pcidda_auto_attach(struct comedi_device *dev, dev->board_ptr = thisboard; dev->board_name = thisboard->name; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; ret = comedi_pci_enable(dev); if (ret) diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c index 8b5c198862a1..543f213c7291 100644 --- a/drivers/staging/comedi/drivers/cb_pcimdas.c +++ b/drivers/staging/comedi/drivers/cb_pcimdas.c @@ -210,10 +210,9 @@ static int cb_pcimdas_auto_attach(struct comedi_device *dev, unsigned long iobase_8255; int ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; ret = comedi_pci_enable(dev); if (ret) diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c index 406cba8cba88..b019566f6c55 100644 --- a/drivers/staging/comedi/drivers/cb_pcimdda.c +++ b/drivers/staging/comedi/drivers/cb_pcimdda.c @@ -156,10 +156,9 @@ static int cb_pcimdda_auto_attach(struct comedi_device *dev, struct comedi_subdevice *s; int ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; ret = comedi_pci_enable(dev); if (ret) diff --git a/drivers/staging/comedi/drivers/comedi_bond.c b/drivers/staging/comedi/drivers/comedi_bond.c index 1a51866be6f7..1952c62ad1fd 100644 --- a/drivers/staging/comedi/drivers/comedi_bond.c +++ b/drivers/staging/comedi/drivers/comedi_bond.c @@ -298,10 +298,9 @@ static int bonding_attach(struct comedi_device *dev, struct comedi_subdevice *s; int ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; /* * Setup our bonding from config params.. sets up our private struct.. diff --git a/drivers/staging/comedi/drivers/comedi_parport.c b/drivers/staging/comedi/drivers/comedi_parport.c index 772a8f5f0c1c..05d79cf4feff 100644 --- a/drivers/staging/comedi/drivers/comedi_parport.c +++ b/drivers/staging/comedi/drivers/comedi_parport.c @@ -279,10 +279,9 @@ static int parport_attach(struct comedi_device *dev, if (ret) return ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; s = &dev->subdevices[0]; s->type = COMEDI_SUBD_DIO; diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c index 907e7a3822f5..eb05f5e57ebc 100644 --- a/drivers/staging/comedi/drivers/comedi_test.c +++ b/drivers/staging/comedi/drivers/comedi_test.c @@ -379,10 +379,9 @@ static int waveform_attach(struct comedi_device *dev, int i; int ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; /* set default amplitude and period */ if (amplitude <= 0) diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c index 44c912b48b6e..f821b81cd3be 100644 --- a/drivers/staging/comedi/drivers/daqboard2000.c +++ b/drivers/staging/comedi/drivers/daqboard2000.c @@ -683,10 +683,9 @@ static int daqboard2000_auto_attach(struct comedi_device *dev, dev->board_ptr = board; dev->board_name = board->name; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; result = comedi_pci_enable(dev); if (result) diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c index 885fb179c9b4..24a3922ddd9a 100644 --- a/drivers/staging/comedi/drivers/das08_cs.c +++ b/drivers/staging/comedi/drivers/das08_cs.c @@ -40,7 +40,6 @@ Command support does not exist, but could be added for this board. */ #include -#include #include "../comedidev.h" @@ -78,10 +77,9 @@ static int das08_cs_auto_attach(struct comedi_device *dev, return ret; iobase = link->resource[0]->start; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; return das08_common_attach(dev, iobase); } diff --git a/drivers/staging/comedi/drivers/das08_isa.c b/drivers/staging/comedi/drivers/das08_isa.c index 21a94389b8b2..50d27aa923dd 100644 --- a/drivers/staging/comedi/drivers/das08_isa.c +++ b/drivers/staging/comedi/drivers/das08_isa.c @@ -177,10 +177,9 @@ static int das08_isa_attach(struct comedi_device *dev, struct das08_private_struct *devpriv; int ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; ret = comedi_request_region(dev, it->options[0], thisboard->iosize); if (ret) diff --git a/drivers/staging/comedi/drivers/das08_pci.c b/drivers/staging/comedi/drivers/das08_pci.c index 9c5d234e063f..2786887173a4 100644 --- a/drivers/staging/comedi/drivers/das08_pci.c +++ b/drivers/staging/comedi/drivers/das08_pci.c @@ -59,10 +59,9 @@ static int das08_pci_auto_attach(struct comedi_device *dev, struct das08_private_struct *devpriv; int ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; /* The das08 driver needs the board_ptr */ dev->board_ptr = &das08_pci_boards[0]; diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index dbec3ba99548..66be41db59ad 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -74,7 +74,6 @@ www.measurementcomputing.com */ #include -#include #include #include @@ -1102,10 +1101,9 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) } } - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; if (board->size < 0x400) { ret = comedi_request_region(dev, it->options[0], board->size); diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c index 0b33808c3a7d..ee5e1561c835 100644 --- a/drivers/staging/comedi/drivers/das16m1.c +++ b/drivers/staging/comedi/drivers/das16m1.c @@ -567,10 +567,9 @@ static int das16m1_attach(struct comedi_device *dev, int ret; unsigned int irq; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; ret = comedi_request_region(dev, it->options[0], DAS16M1_SIZE); if (ret) diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index 23b4a661eb1a..e6c852530acb 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -1511,10 +1511,9 @@ static int das1800_attach(struct comedi_device *dev, int board; int ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; ret = comedi_request_region(dev, it->options[0], DAS1800_SIZE); if (ret) diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c index f0530778bb3b..8529c9f402a1 100644 --- a/drivers/staging/comedi/drivers/das6402.c +++ b/drivers/staging/comedi/drivers/das6402.c @@ -294,10 +294,9 @@ static int das6402_attach(struct comedi_device *dev, dev->irq = irq; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; ret = comedi_alloc_subdevices(dev, 1); if (ret) diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c index 091cd911b38a..f3f4be5b3a59 100644 --- a/drivers/staging/comedi/drivers/das800.c +++ b/drivers/staging/comedi/drivers/das800.c @@ -700,10 +700,9 @@ static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it) int board; int ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; ret = comedi_request_region(dev, it->options[0], DAS800_SIZE); if (ret) diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index e29847d73b43..a8b2c64cafd9 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -753,10 +753,9 @@ static int dmm32at_attach(struct comedi_device *dev, dev->irq = irq; } - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; ret = comedi_alloc_subdevices(dev, 3); if (ret) diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c index 8f5006d70daf..2aa70d2b502d 100644 --- a/drivers/staging/comedi/drivers/dt2801.c +++ b/drivers/staging/comedi/drivers/dt2801.c @@ -627,10 +627,9 @@ havetype: if (ret) goto out; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; dev->board_name = board->name; diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c index 5348cdae408a..bbae652aa894 100644 --- a/drivers/staging/comedi/drivers/dt2811.c +++ b/drivers/staging/comedi/drivers/dt2811.c @@ -450,10 +450,9 @@ static int dt2811_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; switch (it->options[2]) { case 0: diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c index 87e9749c4be7..a46a5b32405d 100644 --- a/drivers/staging/comedi/drivers/dt2814.c +++ b/drivers/staging/comedi/drivers/dt2814.c @@ -298,10 +298,9 @@ static int dt2814_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; s = &dev->subdevices[0]; dev->read_subdev = s; diff --git a/drivers/staging/comedi/drivers/dt2815.c b/drivers/staging/comedi/drivers/dt2815.c index 0fcd4fe7acdc..e729271fcfe3 100644 --- a/drivers/staging/comedi/drivers/dt2815.c +++ b/drivers/staging/comedi/drivers/dt2815.c @@ -165,10 +165,9 @@ static int dt2815_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; s = &dev->subdevices[0]; /* ao subdevice */ diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index c1950e3b19a2..3d1ae5f3fa5f 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -1188,10 +1188,9 @@ static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it) #endif } - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; ret = dt282x_grab_dma(dev, it->options[opt_dma1], it->options[opt_dma2]); diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c index 01a2f889d5b0..c255ed1ec231 100644 --- a/drivers/staging/comedi/drivers/dt3000.c +++ b/drivers/staging/comedi/drivers/dt3000.c @@ -722,10 +722,9 @@ static int dt3000_auto_attach(struct comedi_device *dev, dev->board_ptr = this_board; dev->board_name = this_board->name; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; ret = comedi_pci_enable(dev); if (ret < 0) diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c index 6c60949d9193..07aa828365e5 100644 --- a/drivers/staging/comedi/drivers/dt9812.c +++ b/drivers/staging/comedi/drivers/dt9812.c @@ -41,7 +41,6 @@ for my needs. #include #include #include -#include #include #include #include @@ -781,10 +780,9 @@ static int dt9812_auto_attach(struct comedi_device *dev, bool is_unipolar; int ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; sema_init(&devpriv->sem, 1); usb_set_intfdata(intf, devpriv); diff --git a/drivers/staging/comedi/drivers/dyna_pci10xx.c b/drivers/staging/comedi/drivers/dyna_pci10xx.c index e14dd3ae9ec6..33398041b664 100644 --- a/drivers/staging/comedi/drivers/dyna_pci10xx.c +++ b/drivers/staging/comedi/drivers/dyna_pci10xx.c @@ -183,10 +183,9 @@ static int dyna_pci10xx_auto_attach(struct comedi_device *dev, struct comedi_subdevice *s; int ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; ret = comedi_pci_enable(dev); if (ret) diff --git a/drivers/staging/comedi/drivers/fl512.c b/drivers/staging/comedi/drivers/fl512.c index ff6f0bd7c863..77646371d80c 100644 --- a/drivers/staging/comedi/drivers/fl512.c +++ b/drivers/staging/comedi/drivers/fl512.c @@ -118,10 +118,9 @@ static int fl512_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; ret = comedi_alloc_subdevices(dev, 2); if (ret) diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c index 2fceff93867b..f130327f88d3 100644 --- a/drivers/staging/comedi/drivers/gsc_hpdi.c +++ b/drivers/staging/comedi/drivers/gsc_hpdi.c @@ -483,10 +483,9 @@ static int hpdi_auto_attach(struct comedi_device *dev, dev->board_ptr = thisboard; dev->board_name = thisboard->name; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; retval = comedi_pci_enable(dev); if (retval) diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c index a11e015dc03d..ee40233e81b3 100644 --- a/drivers/staging/comedi/drivers/icp_multi.c +++ b/drivers/staging/comedi/drivers/icp_multi.c @@ -495,10 +495,9 @@ static int icp_multi_auto_attach(struct comedi_device *dev, struct comedi_subdevice *s; int ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; ret = comedi_pci_enable(dev); if (ret) diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c index ee7537daf473..0d4de7d1094d 100644 --- a/drivers/staging/comedi/drivers/ii_pci20kc.c +++ b/drivers/staging/comedi/drivers/ii_pci20kc.c @@ -203,10 +203,9 @@ static int pci20xxx_attach(struct comedi_device *dev, if (ret) return ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; devpriv->ioaddr = (void __iomem *)(unsigned long)it->options[0]; diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c index 94609f4aa4c9..a9817c980fbc 100644 --- a/drivers/staging/comedi/drivers/jr3_pci.c +++ b/drivers/staging/comedi/drivers/jr3_pci.c @@ -638,10 +638,9 @@ static int jr3_pci_auto_attach(struct comedi_device *dev, return -EINVAL; } - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; init_timer(&devpriv->timer); switch (pcidev->device) { diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c index c2308fd24d6a..f84f0fbb6eaa 100644 --- a/drivers/staging/comedi/drivers/me4000.c +++ b/drivers/staging/comedi/drivers/me4000.c @@ -1544,10 +1544,9 @@ static int me4000_auto_attach(struct comedi_device *dev, dev->board_ptr = thisboard; dev->board_name = thisboard->name; - info = kzalloc(sizeof(*info), GFP_KERNEL); + info = comedi_alloc_devpriv(dev, sizeof(*info)); if (!info) return -ENOMEM; - dev->private = info; result = comedi_pci_enable(dev); if (result) diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c index 7533ece3670e..234332044310 100644 --- a/drivers/staging/comedi/drivers/me_daq.c +++ b/drivers/staging/comedi/drivers/me_daq.c @@ -490,10 +490,9 @@ static int me_auto_attach(struct comedi_device *dev, dev->board_ptr = board; dev->board_name = board->name; - dev_private = kzalloc(sizeof(*dev_private), GFP_KERNEL); + dev_private = comedi_alloc_devpriv(dev, sizeof(*dev_private)); if (!dev_private) return -ENOMEM; - dev->private = dev_private; ret = comedi_pci_enable(dev); if (ret) diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c index 713842ad6ff6..f24657f304fd 100644 --- a/drivers/staging/comedi/drivers/mpc624.c +++ b/drivers/staging/comedi/drivers/mpc624.c @@ -286,10 +286,9 @@ static int mpc624_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; switch (it->options[1]) { case 0: diff --git a/drivers/staging/comedi/drivers/multiq3.c b/drivers/staging/comedi/drivers/multiq3.c index 5ecd1b1666fb..8db2aad5441e 100644 --- a/drivers/staging/comedi/drivers/multiq3.c +++ b/drivers/staging/comedi/drivers/multiq3.c @@ -232,10 +232,9 @@ static int multiq3_attach(struct comedi_device *dev, if (ret) return ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; s = &dev->subdevices[0]; /* ai subdevice */ diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c index 903c2ef5dd9a..2077d6ba6d3f 100644 --- a/drivers/staging/comedi/drivers/ni_6527.c +++ b/drivers/staging/comedi/drivers/ni_6527.c @@ -335,10 +335,9 @@ static int ni6527_auto_attach(struct comedi_device *dev, if (ret) return ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; devpriv->mite = mite_alloc(pcidev); if (!devpriv->mite) diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c index 42a78de47316..1bd830023118 100644 --- a/drivers/staging/comedi/drivers/ni_65xx.c +++ b/drivers/staging/comedi/drivers/ni_65xx.c @@ -48,7 +48,6 @@ except maybe the 6514. #include #include -#include #include "../comedidev.h" @@ -591,10 +590,9 @@ static int ni_65xx_auto_attach(struct comedi_device *dev, if (ret) return ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; devpriv->mite = mite_alloc(pcidev); if (!devpriv->mite) diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index a9e000461ec7..d90d4a09ba4c 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -929,10 +929,9 @@ static int ni_660x_allocate_private(struct comedi_device *dev) struct ni_660x_private *devpriv; unsigned i; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; spin_lock_init(&devpriv->mite_channel_lock); spin_lock_init(&devpriv->interrupt_lock); diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c index 1a185b9c529f..4876f116ba92 100644 --- a/drivers/staging/comedi/drivers/ni_670x.c +++ b/drivers/staging/comedi/drivers/ni_670x.c @@ -38,7 +38,6 @@ Commands are not supported. #include #include -#include #include "../comedidev.h" @@ -205,10 +204,9 @@ static int ni_670x_auto_attach(struct comedi_device *dev, if (ret) return ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; devpriv->mite = mite_alloc(pcidev); if (!devpriv->mite) diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c index 7ea5aa32e9d2..82c5ca686300 100644 --- a/drivers/staging/comedi/drivers/ni_at_a2150.c +++ b/drivers/staging/comedi/drivers/ni_at_a2150.c @@ -719,10 +719,9 @@ static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it) int i; int ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; ret = comedi_request_region(dev, it->options[0], A2150_SIZE); if (ret) diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c index e080053c697b..639377a60c12 100644 --- a/drivers/staging/comedi/drivers/ni_at_ao.c +++ b/drivers/staging/comedi/drivers/ni_at_ao.c @@ -341,10 +341,9 @@ static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; ret = comedi_alloc_subdevices(dev, 4); if (ret) diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c index da7396f94297..d91fbc8240c0 100644 --- a/drivers/staging/comedi/drivers/ni_atmio16d.c +++ b/drivers/staging/comedi/drivers/ni_atmio16d.c @@ -645,10 +645,9 @@ static int atmio16d_attach(struct comedi_device *dev, if (ret) return ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; /* reset the atmio16d hardware */ reset_atmio16d(dev); diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c index 3c50e31ecc60..12aa15b42887 100644 --- a/drivers/staging/comedi/drivers/ni_daq_700.c +++ b/drivers/staging/comedi/drivers/ni_daq_700.c @@ -47,7 +47,6 @@ Manuals: Register level: http://www.ni.com/pdf/manuals/340698.pdf #include #include -#include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index f161e70b3a0d..4119dcfd4761 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -1697,10 +1697,9 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it) unsigned int dma_chan = it->options[2]; int ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; ret = comedi_request_region(dev, it->options[0], LABPC_SIZE); if (ret) diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c index ce67f4bbb1f5..df1de784e90b 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_cs.c +++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c @@ -56,7 +56,6 @@ NI manuals: #include "../comedidev.h" #include -#include #include "8253.h" #include "8255.h" @@ -96,10 +95,9 @@ static int labpc_auto_attach(struct comedi_device *dev, if (!link->irq) return -EINVAL; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; return labpc_common_attach(dev, link->irq, IRQF_SHARED); } diff --git a/drivers/staging/comedi/drivers/ni_labpc_pci.c b/drivers/staging/comedi/drivers/ni_labpc_pci.c index 6c79237b2b5c..203a7cef7750 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_pci.c +++ b/drivers/staging/comedi/drivers/ni_labpc_pci.c @@ -30,7 +30,6 @@ */ #include -#include #include #include "../comedidev.h" @@ -72,10 +71,9 @@ static int labpc_pci_auto_attach(struct comedi_device *dev, if (ret) return ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; devpriv->mite = mite_alloc(pcidev); if (!devpriv->mite) diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 3e9f544e67fc..458331d3fcb7 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -4363,10 +4363,9 @@ static int ni_alloc_private(struct comedi_device *dev) { struct ni_private *devpriv; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; spin_lock_init(&devpriv->window_lock); spin_lock_init(&devpriv->soft_reg_copy_lock); diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index 5b2f72e102e1..3c5275b669fc 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -1108,10 +1108,9 @@ static int nidio_auto_attach(struct comedi_device *dev, if (ret) return ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; spin_lock_init(&devpriv->mite_channel_lock); diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c index f2cf76d15d78..5b6fde08e582 100644 --- a/drivers/staging/comedi/drivers/ni_tio.c +++ b/drivers/staging/comedi/drivers/ni_tio.c @@ -44,6 +44,8 @@ TODO: Support use of both banks X and Y */ +#include + #include "ni_tio_internal.h" static uint64_t ni_tio_clock_period_ps(const struct ni_gpct *counter, diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c index 7abf3f74144e..f5ac58342a7c 100644 --- a/drivers/staging/comedi/drivers/pcl711.c +++ b/drivers/staging/comedi/drivers/pcl711.c @@ -474,10 +474,9 @@ static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; s = &dev->subdevices[0]; /* AI subdevice */ diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c index 893f012a1b7a..9bd341fedced 100644 --- a/drivers/staging/comedi/drivers/pcl726.c +++ b/drivers/staging/comedi/drivers/pcl726.c @@ -229,10 +229,9 @@ static int pcl726_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; for (i = 0; i < 12; i++) { devpriv->bipolar[i] = 0; diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index cd02786702c8..699d4558c122 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -1110,10 +1110,9 @@ static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; irq = 0; if (board->IRQbits != 0) { /* board support IRQ */ diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index 91bd2071f571..02285976177a 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -922,10 +922,9 @@ static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it) return -EIO; } - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; /* grab our IRQ */ irq = 0; diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index 91cb1bd6717f..55f10e754c76 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -1227,10 +1227,9 @@ static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it) unsigned long pages; struct comedi_subdevice *s; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; devpriv->io_range = board->io_range; if ((board->fifo) && (it->options[2] == -1)) { diff --git a/drivers/staging/comedi/drivers/pcm3724.c b/drivers/staging/comedi/drivers/pcm3724.c index 5a9cd38e15f2..87cba62c6aed 100644 --- a/drivers/staging/comedi/drivers/pcm3724.c +++ b/drivers/staging/comedi/drivers/pcm3724.c @@ -228,10 +228,9 @@ static int pcm3724_attach(struct comedi_device *dev, struct comedi_subdevice *s; int ret, i; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); + priv = comedi_alloc_devpriv(dev, sizeof(*priv)); if (!priv) return -ENOMEM; - dev->private = priv; ret = comedi_request_region(dev, it->options[0], PCM3724_SIZE); if (ret) diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c index 774a63dfe040..2839241bb35a 100644 --- a/drivers/staging/comedi/drivers/pcmda12.c +++ b/drivers/staging/comedi/drivers/pcmda12.c @@ -138,10 +138,9 @@ static int pcmda12_attach(struct comedi_device *dev, if (ret) return ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; devpriv->simultaneous_xfer_mode = it->options[1]; diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c index 9f76b1f59983..feb83caef26f 100644 --- a/drivers/staging/comedi/drivers/pcmmio.c +++ b/drivers/staging/comedi/drivers/pcmmio.c @@ -1039,10 +1039,9 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; for (asic = 0; asic < MAX_ASICS; ++asic) { devpriv->asics[asic].num = asic; diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index c43b6334ceae..30f53fb5a0ac 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -609,10 +609,9 @@ static int pcmuio_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; for (asic = 0; asic < PCMUIO_MAX_ASICS; ++asic) spin_lock_init(&devpriv->asics[asic].spinlock); diff --git a/drivers/staging/comedi/drivers/poc.c b/drivers/staging/comedi/drivers/poc.c index 005fbefae295..e50dd09a2031 100644 --- a/drivers/staging/comedi/drivers/poc.c +++ b/drivers/staging/comedi/drivers/poc.c @@ -109,10 +109,9 @@ static int poc_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; /* analog output subdevice */ s = &dev->subdevices[0]; diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c index e092ce87722e..478a97271a48 100644 --- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c +++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c @@ -715,10 +715,9 @@ static int daqp_auto_attach(struct comedi_device *dev, struct comedi_subdevice *s; int ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; link->config_flags |= CONF_AUTO_SET_IO | CONF_ENABLE_IRQ; ret = comedi_pcmcia_enable(dev, NULL); diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c index 9b93a1fc4a59..928f534ae4ec 100644 --- a/drivers/staging/comedi/drivers/rtd520.c +++ b/drivers/staging/comedi/drivers/rtd520.c @@ -1338,10 +1338,9 @@ static int rtd_auto_attach(struct comedi_device *dev, dev->board_ptr = board; dev->board_name = board->name; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; ret = comedi_pci_enable(dev); if (ret) diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c index f698c7fc5726..b95fce5d26fb 100644 --- a/drivers/staging/comedi/drivers/rti800.c +++ b/drivers/staging/comedi/drivers/rti800.c @@ -298,10 +298,9 @@ static int rti800_attach(struct comedi_device *dev, struct comedi_devconfig *it) inb(dev->iobase + RTI800_ADCHI); outb(0, dev->iobase + RTI800_CLRFLAGS); - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; devpriv->adc_2comp = (it->options[4] == 0); devpriv->dac_2comp[0] = (it->options[6] == 0); diff --git a/drivers/staging/comedi/drivers/rti802.c b/drivers/staging/comedi/drivers/rti802.c index 9e7445055482..664ad70b0501 100644 --- a/drivers/staging/comedi/drivers/rti802.c +++ b/drivers/staging/comedi/drivers/rti802.c @@ -93,10 +93,9 @@ static int rti802_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; ret = comedi_alloc_subdevices(dev, 1); if (ret) diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c index e1587e58a732..24d21eef74f8 100644 --- a/drivers/staging/comedi/drivers/s526.c +++ b/drivers/staging/comedi/drivers/s526.c @@ -553,10 +553,9 @@ static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; ret = comedi_alloc_subdevices(dev, 4); if (ret) diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c index 48c4b70b736a..f5ef91f39bbf 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c @@ -2585,10 +2585,9 @@ static int s626_auto_attach(struct comedi_device *dev, struct comedi_subdevice *s; int ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; ret = comedi_pci_enable(dev); if (ret) diff --git a/drivers/staging/comedi/drivers/s626.h b/drivers/staging/comedi/drivers/s626.h index d2756b83b62d..a85e6bdcad07 100644 --- a/drivers/staging/comedi/drivers/s626.h +++ b/drivers/staging/comedi/drivers/s626.h @@ -65,8 +65,6 @@ #define FALSE (0) #endif -#include - #define S626_SIZE 0x0200 #define DMABUF_SIZE 4096 /* 4k pages */ diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c index b4f5fe35b0fa..b6efe9b1d4d2 100644 --- a/drivers/staging/comedi/drivers/serial2002.c +++ b/drivers/staging/comedi/drivers/serial2002.c @@ -719,10 +719,9 @@ static int serial2002_attach(struct comedi_device *dev, struct comedi_subdevice *s; int ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; devpriv->port = it->options[0]; devpriv->speed = it->options[1]; diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c index 06aee302bbc2..3fc7713af5ce 100644 --- a/drivers/staging/comedi/drivers/skel.c +++ b/drivers/staging/comedi/drivers/skel.c @@ -484,10 +484,9 @@ static int skel_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* dev->board_name = thisboard->name; */ /* Allocate the private data */ - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; /* * Supported boards are usually either auto-attached via the @@ -558,10 +557,9 @@ static int skel_auto_attach(struct comedi_device *dev, dev->board_name = thisboard->name; /* Allocate the private data */ - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; /* Enable the PCI device. */ ret = comedi_pci_enable(dev); diff --git a/drivers/staging/comedi/drivers/unioxx5.c b/drivers/staging/comedi/drivers/unioxx5.c index c9201d821fbc..806285bc6ca7 100644 --- a/drivers/staging/comedi/drivers/unioxx5.c +++ b/drivers/staging/comedi/drivers/unioxx5.c @@ -42,7 +42,6 @@ Devices: [Fastwel] UNIOxx-5 (unioxx5), #include "../comedidev.h" #include -#include #define DRIVER_NAME "unioxx5" #define UNIOXX5_SIZE 0x10 diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c index 27898c44e543..9707dd1239c4 100644 --- a/drivers/staging/comedi/drivers/usbduxfast.c +++ b/drivers/staging/comedi/drivers/usbduxfast.c @@ -1061,10 +1061,9 @@ static int usbduxfast_auto_attach(struct comedi_device *dev, return -ENODEV; } - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; sema_init(&devpriv->sem, 1); usb_set_intfdata(intf, devpriv); diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index 898c3c450406..40eeb8c68306 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -1677,10 +1677,9 @@ static int usbduxsigma_auto_attach(struct comedi_device *dev, struct usbduxsigma_private *devpriv; int ret; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; sema_init(&devpriv->sem, 1); usb_set_intfdata(intf, devpriv); diff --git a/drivers/staging/comedi/drivers/vmk80xx.c b/drivers/staging/comedi/drivers/vmk80xx.c index 0ab04c0dd410..06efa16b9af2 100644 --- a/drivers/staging/comedi/drivers/vmk80xx.c +++ b/drivers/staging/comedi/drivers/vmk80xx.c @@ -875,10 +875,9 @@ static int vmk80xx_auto_attach(struct comedi_device *dev, dev->board_ptr = boardinfo; dev->board_name = boardinfo->name; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; devpriv->model = boardinfo->model; From ce157f8032bbd46d9427034c335b0afd751da25d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 24 Jun 2013 17:04:43 -0700 Subject: [PATCH 0360/3400] staging: comedi: don't rely on comedidev.h to include headers comedidev.h is the main kernel header for comedi. Every comedi driver includes this header which then includes a number of headers. All the drivers need and some of them need . The rest are not needed by any of the drivers. Remove all the includes in comedidev.h except for , which is needed to pick up the enum dma_data_direction for the comedi_subdevice definition, and "comedi.h", which is the uapi header for comedi. Add to all the comedi drivers and to the couple that need it. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedidev.h | 14 -------------- drivers/staging/comedi/drivers/8255.c | 1 + drivers/staging/comedi/drivers/8255_pci.c | 1 + .../staging/comedi/drivers/addi-data/addi_eeprom.c | 2 ++ .../comedi/drivers/addi-data/hwdrv_apci3120.c | 2 ++ drivers/staging/comedi/drivers/addi_apci_035.c | 1 + drivers/staging/comedi/drivers/addi_apci_1032.c | 1 + drivers/staging/comedi/drivers/addi_apci_1500.c | 1 + drivers/staging/comedi/drivers/addi_apci_1516.c | 1 + drivers/staging/comedi/drivers/addi_apci_1564.c | 1 + drivers/staging/comedi/drivers/addi_apci_16xx.c | 1 + drivers/staging/comedi/drivers/addi_apci_1710.c | 1 + drivers/staging/comedi/drivers/addi_apci_2032.c | 1 + drivers/staging/comedi/drivers/addi_apci_2200.c | 1 + drivers/staging/comedi/drivers/addi_apci_3120.c | 1 + drivers/staging/comedi/drivers/addi_apci_3200.c | 1 + drivers/staging/comedi/drivers/addi_apci_3501.c | 1 + drivers/staging/comedi/drivers/addi_apci_3xxx.c | 1 + drivers/staging/comedi/drivers/addi_watchdog.c | 1 + drivers/staging/comedi/drivers/adl_pci6208.c | 1 + drivers/staging/comedi/drivers/adl_pci7x3x.c | 1 + drivers/staging/comedi/drivers/adl_pci8164.c | 1 + drivers/staging/comedi/drivers/adl_pci9111.c | 1 + drivers/staging/comedi/drivers/adl_pci9118.c | 1 + drivers/staging/comedi/drivers/adq12b.c | 3 +++ drivers/staging/comedi/drivers/adv_pci1710.c | 1 + drivers/staging/comedi/drivers/adv_pci1723.c | 1 + drivers/staging/comedi/drivers/adv_pci1724.c | 2 ++ drivers/staging/comedi/drivers/adv_pci_dio.c | 1 + drivers/staging/comedi/drivers/aio_aio12_8.c | 1 + drivers/staging/comedi/drivers/aio_iiro_16.c | 1 + drivers/staging/comedi/drivers/amplc_dio200.c | 1 + .../staging/comedi/drivers/amplc_dio200_common.c | 1 + drivers/staging/comedi/drivers/amplc_dio200_pci.c | 1 + drivers/staging/comedi/drivers/amplc_pc236.c | 1 + drivers/staging/comedi/drivers/amplc_pc263.c | 1 + drivers/staging/comedi/drivers/amplc_pci224.c | 1 + drivers/staging/comedi/drivers/amplc_pci230.c | 1 + drivers/staging/comedi/drivers/amplc_pci263.c | 1 + drivers/staging/comedi/drivers/cb_das16_cs.c | 1 + drivers/staging/comedi/drivers/cb_pcidas.c | 1 + drivers/staging/comedi/drivers/cb_pcidas64.c | 1 + drivers/staging/comedi/drivers/cb_pcidda.c | 1 + drivers/staging/comedi/drivers/cb_pcimdas.c | 1 + drivers/staging/comedi/drivers/cb_pcimdda.c | 1 + drivers/staging/comedi/drivers/comedi_bond.c | 1 + drivers/staging/comedi/drivers/comedi_fc.c | 1 + drivers/staging/comedi/drivers/comedi_parport.c | 1 + drivers/staging/comedi/drivers/comedi_test.c | 1 + drivers/staging/comedi/drivers/contec_pci_dio.c | 1 + drivers/staging/comedi/drivers/daqboard2000.c | 1 + drivers/staging/comedi/drivers/das08.c | 1 + drivers/staging/comedi/drivers/das08_cs.c | 1 + drivers/staging/comedi/drivers/das08_isa.c | 1 + drivers/staging/comedi/drivers/das08_pci.c | 1 + drivers/staging/comedi/drivers/das16.c | 2 ++ drivers/staging/comedi/drivers/das16m1.c | 1 + drivers/staging/comedi/drivers/das1800.c | 1 + drivers/staging/comedi/drivers/das6402.c | 1 + drivers/staging/comedi/drivers/das800.c | 1 + drivers/staging/comedi/drivers/dmm32at.c | 2 ++ drivers/staging/comedi/drivers/dt2801.c | 1 + drivers/staging/comedi/drivers/dt2811.c | 1 + drivers/staging/comedi/drivers/dt2814.c | 1 + drivers/staging/comedi/drivers/dt2815.c | 1 + drivers/staging/comedi/drivers/dt2817.c | 1 + drivers/staging/comedi/drivers/dt282x.c | 4 ++++ drivers/staging/comedi/drivers/dt3000.c | 1 + drivers/staging/comedi/drivers/dt9812.c | 1 + drivers/staging/comedi/drivers/dyna_pci10xx.c | 2 ++ drivers/staging/comedi/drivers/fl512.c | 1 + drivers/staging/comedi/drivers/gsc_hpdi.c | 1 + drivers/staging/comedi/drivers/icp_multi.c | 1 + drivers/staging/comedi/drivers/ii_pci20kc.c | 1 + drivers/staging/comedi/drivers/jr3_pci.c | 1 + drivers/staging/comedi/drivers/ke_counter.c | 1 + drivers/staging/comedi/drivers/me4000.c | 1 + drivers/staging/comedi/drivers/me_daq.c | 1 + drivers/staging/comedi/drivers/mite.c | 1 + drivers/staging/comedi/drivers/mpc624.c | 1 + drivers/staging/comedi/drivers/multiq3.c | 1 + drivers/staging/comedi/drivers/ni_6527.c | 1 + drivers/staging/comedi/drivers/ni_65xx.c | 1 + drivers/staging/comedi/drivers/ni_660x.c | 1 + drivers/staging/comedi/drivers/ni_670x.c | 1 + drivers/staging/comedi/drivers/ni_at_a2150.c | 3 +++ drivers/staging/comedi/drivers/ni_at_ao.c | 1 + drivers/staging/comedi/drivers/ni_atmio.c | 1 + drivers/staging/comedi/drivers/ni_atmio16d.c | 1 + drivers/staging/comedi/drivers/ni_daq_700.c | 2 ++ drivers/staging/comedi/drivers/ni_daq_dio24.c | 1 + drivers/staging/comedi/drivers/ni_labpc.c | 1 + drivers/staging/comedi/drivers/ni_labpc_cs.c | 1 + drivers/staging/comedi/drivers/ni_labpc_pci.c | 1 + drivers/staging/comedi/drivers/ni_mio_cs.c | 1 + drivers/staging/comedi/drivers/ni_pcidio.c | 1 + drivers/staging/comedi/drivers/ni_pcimio.c | 1 + drivers/staging/comedi/drivers/ni_tio.c | 1 + drivers/staging/comedi/drivers/ni_tiocmd.c | 1 + drivers/staging/comedi/drivers/pcl711.c | 1 + drivers/staging/comedi/drivers/pcl724.c | 1 + drivers/staging/comedi/drivers/pcl726.c | 1 + drivers/staging/comedi/drivers/pcl730.c | 1 + drivers/staging/comedi/drivers/pcl812.c | 1 + drivers/staging/comedi/drivers/pcl816.c | 1 + drivers/staging/comedi/drivers/pcl818.c | 1 + drivers/staging/comedi/drivers/pcm3724.c | 1 + drivers/staging/comedi/drivers/pcmad.c | 1 + drivers/staging/comedi/drivers/pcmda12.c | 1 + drivers/staging/comedi/drivers/pcmmio.c | 1 + drivers/staging/comedi/drivers/pcmuio.c | 1 + drivers/staging/comedi/drivers/poc.c | 1 + drivers/staging/comedi/drivers/quatech_daqp_cs.c | 1 + drivers/staging/comedi/drivers/rtd520.c | 1 + drivers/staging/comedi/drivers/rti800.c | 2 ++ drivers/staging/comedi/drivers/rti802.c | 1 + drivers/staging/comedi/drivers/s526.c | 1 + drivers/staging/comedi/drivers/s626.c | 2 ++ drivers/staging/comedi/drivers/serial2002.c | 1 + drivers/staging/comedi/drivers/skel.c | 1 + drivers/staging/comedi/drivers/ssv_dnp.c | 1 + drivers/staging/comedi/drivers/unioxx5.c | 2 ++ 122 files changed, 138 insertions(+), 14 deletions(-) diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index c6a7c096f625..ab278942ebd1 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -19,21 +19,7 @@ #ifndef _COMEDIDEV_H #define _COMEDIDEV_H -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include #include "comedi.h" diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c index 94e17500150f..7966079a8361 100644 --- a/drivers/staging/comedi/drivers/8255.c +++ b/drivers/staging/comedi/drivers/8255.c @@ -73,6 +73,7 @@ I/O port base address can be found in the output of 'lspci -v'. will copy the latched value to a Comedi buffer. */ +#include #include "../comedidev.h" #include diff --git a/drivers/staging/comedi/drivers/8255_pci.c b/drivers/staging/comedi/drivers/8255_pci.c index b58e28bb206d..432e3f9c3301 100644 --- a/drivers/staging/comedi/drivers/8255_pci.c +++ b/drivers/staging/comedi/drivers/8255_pci.c @@ -50,6 +50,7 @@ Interrupt support for these boards is also not currently supported. Configuration Options: not applicable, uses PCI auto config */ +#include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c index dc031c494a27..aafc172f3a98 100644 --- a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c +++ b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c @@ -22,6 +22,8 @@ * for more details. */ +#include + #define NVRAM_USER_DATA_START 0x100 #define NVCMD_BEGIN_READ (0x7 << 5) /* nvRam begin read command */ diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c index a89e505c8a3a..1449b92403e2 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c @@ -40,6 +40,8 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY +----------+-----------+------------------------------------------------+ */ +#include + /* * ADDON RELATED ADDITIONS */ diff --git a/drivers/staging/comedi/drivers/addi_apci_035.c b/drivers/staging/comedi/drivers/addi_apci_035.c index 43c2c10a7c32..8d229b2f0973 100644 --- a/drivers/staging/comedi/drivers/addi_apci_035.c +++ b/drivers/staging/comedi/drivers/addi_apci_035.c @@ -1,3 +1,4 @@ +#include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/addi_apci_1032.c b/drivers/staging/comedi/drivers/addi_apci_1032.c index 242903aac829..34ab0679e992 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1032.c +++ b/drivers/staging/comedi/drivers/addi_apci_1032.c @@ -22,6 +22,7 @@ * more details. */ +#include #include #include diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c index b52cfe01e6c8..ae9ded63dcec 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1500.c +++ b/drivers/staging/comedi/drivers/addi_apci_1500.c @@ -1,3 +1,4 @@ +#include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/addi_apci_1516.c b/drivers/staging/comedi/drivers/addi_apci_1516.c index 7523c8b0e8f7..08674c18cf42 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1516.c +++ b/drivers/staging/comedi/drivers/addi_apci_1516.c @@ -22,6 +22,7 @@ * more details. */ +#include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/addi_apci_1564.c b/drivers/staging/comedi/drivers/addi_apci_1564.c index 22bace62210c..c5717d63e16a 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1564.c +++ b/drivers/staging/comedi/drivers/addi_apci_1564.c @@ -1,3 +1,4 @@ +#include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/addi_apci_16xx.c b/drivers/staging/comedi/drivers/addi_apci_16xx.c index 1f7bed9a3f7f..43296a6e7d4e 100644 --- a/drivers/staging/comedi/drivers/addi_apci_16xx.c +++ b/drivers/staging/comedi/drivers/addi_apci_16xx.c @@ -22,6 +22,7 @@ * more details. */ +#include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/addi_apci_1710.c b/drivers/staging/comedi/drivers/addi_apci_1710.c index e533f55a1d2f..e600c05c2ecc 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1710.c +++ b/drivers/staging/comedi/drivers/addi_apci_1710.c @@ -1,3 +1,4 @@ +#include #include #include diff --git a/drivers/staging/comedi/drivers/addi_apci_2032.c b/drivers/staging/comedi/drivers/addi_apci_2032.c index 89ead8eb3c70..cb5d26a567d3 100644 --- a/drivers/staging/comedi/drivers/addi_apci_2032.c +++ b/drivers/staging/comedi/drivers/addi_apci_2032.c @@ -22,6 +22,7 @@ * more details. */ +#include #include #include diff --git a/drivers/staging/comedi/drivers/addi_apci_2200.c b/drivers/staging/comedi/drivers/addi_apci_2200.c index ca1bd92ecb17..92ac8ece8494 100644 --- a/drivers/staging/comedi/drivers/addi_apci_2200.c +++ b/drivers/staging/comedi/drivers/addi_apci_2200.c @@ -22,6 +22,7 @@ * more details. */ +#include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/addi_apci_3120.c b/drivers/staging/comedi/drivers/addi_apci_3120.c index a7828bb64a91..d804957018ab 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3120.c +++ b/drivers/staging/comedi/drivers/addi_apci_3120.c @@ -1,3 +1,4 @@ +#include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/addi_apci_3200.c b/drivers/staging/comedi/drivers/addi_apci_3200.c index 17b540d3c6ae..1213d5aa6bea 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3200.c +++ b/drivers/staging/comedi/drivers/addi_apci_3200.c @@ -1,3 +1,4 @@ +#include #include #include diff --git a/drivers/staging/comedi/drivers/addi_apci_3501.c b/drivers/staging/comedi/drivers/addi_apci_3501.c index 9b8544b43b24..d9650ffb7d2f 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3501.c +++ b/drivers/staging/comedi/drivers/addi_apci_3501.c @@ -22,6 +22,7 @@ * more details. */ +#include #include #include #include diff --git a/drivers/staging/comedi/drivers/addi_apci_3xxx.c b/drivers/staging/comedi/drivers/addi_apci_3xxx.c index cf60248c726d..dbc0678027ca 100644 --- a/drivers/staging/comedi/drivers/addi_apci_3xxx.c +++ b/drivers/staging/comedi/drivers/addi_apci_3xxx.c @@ -22,6 +22,7 @@ * more details. */ +#include #include #include diff --git a/drivers/staging/comedi/drivers/addi_watchdog.c b/drivers/staging/comedi/drivers/addi_watchdog.c index 7b21acc93929..23031feaa095 100644 --- a/drivers/staging/comedi/drivers/addi_watchdog.c +++ b/drivers/staging/comedi/drivers/addi_watchdog.c @@ -18,6 +18,7 @@ * GNU General Public License for more details. */ +#include #include "../comedidev.h" #include "addi_watchdog.h" diff --git a/drivers/staging/comedi/drivers/adl_pci6208.c b/drivers/staging/comedi/drivers/adl_pci6208.c index ffd91e4f90bf..a67ad57cefcb 100644 --- a/drivers/staging/comedi/drivers/adl_pci6208.c +++ b/drivers/staging/comedi/drivers/adl_pci6208.c @@ -38,6 +38,7 @@ References: - adl_pci9118.c */ +#include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/adl_pci7x3x.c b/drivers/staging/comedi/drivers/adl_pci7x3x.c index 0d9243a5f495..81b7203f824f 100644 --- a/drivers/staging/comedi/drivers/adl_pci7x3x.c +++ b/drivers/staging/comedi/drivers/adl_pci7x3x.c @@ -44,6 +44,7 @@ driver. Configuration Options: not applicable, uses comedi PCI auto config */ +#include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/adl_pci8164.c b/drivers/staging/comedi/drivers/adl_pci8164.c index 0b591b0b5501..b3d009285ed4 100644 --- a/drivers/staging/comedi/drivers/adl_pci8164.c +++ b/drivers/staging/comedi/drivers/adl_pci8164.c @@ -27,6 +27,7 @@ */ #include +#include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c index cf93e416dd29..78cea193504f 100644 --- a/drivers/staging/comedi/drivers/adl_pci9111.c +++ b/drivers/staging/comedi/drivers/adl_pci9111.c @@ -64,6 +64,7 @@ TODO: */ +#include #include #include #include diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c index 2a48f8421ca0..22196ada0362 100644 --- a/drivers/staging/comedi/drivers/adl_pci9118.c +++ b/drivers/staging/comedi/drivers/adl_pci9118.c @@ -77,6 +77,7 @@ Configuration options: * manual attachment. */ +#include #include #include #include diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c index 72e88d8465ea..cdf5ba26c590 100644 --- a/drivers/staging/comedi/drivers/adq12b.c +++ b/drivers/staging/comedi/drivers/adq12b.c @@ -73,6 +73,9 @@ If you do not specify any options, they will default to */ +#include +#include + #include "../comedidev.h" /* address scheme (page 2.17 of the manual) */ diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 53653d3c4937..f84df46d326a 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -41,6 +41,7 @@ Configuration options: device will be used. */ +#include #include #include diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c index 919babae4cbe..f914fb1f571b 100644 --- a/drivers/staging/comedi/drivers/adv_pci1723.c +++ b/drivers/staging/comedi/drivers/adv_pci1723.c @@ -43,6 +43,7 @@ TODO: 3. Implement calibration. */ +#include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/adv_pci1724.c b/drivers/staging/comedi/drivers/adv_pci1724.c index d27730e2d29f..84907c79ca2b 100644 --- a/drivers/staging/comedi/drivers/adv_pci1724.c +++ b/drivers/staging/comedi/drivers/adv_pci1724.c @@ -52,6 +52,8 @@ supported PCI devices are configured as comedi devices automatically. */ +#include +#include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c index ff48cb30d4af..f091fa0d304d 100644 --- a/drivers/staging/comedi/drivers/adv_pci_dio.c +++ b/drivers/staging/comedi/drivers/adv_pci_dio.c @@ -29,6 +29,7 @@ Configuration options: */ +#include #include #include diff --git a/drivers/staging/comedi/drivers/aio_aio12_8.c b/drivers/staging/comedi/drivers/aio_aio12_8.c index ae88fe1f79d0..8d081076eed6 100644 --- a/drivers/staging/comedi/drivers/aio_aio12_8.c +++ b/drivers/staging/comedi/drivers/aio_aio12_8.c @@ -35,6 +35,7 @@ Notes: */ +#include #include "../comedidev.h" #include #include "8255.h" diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c index 029834d0ff1f..f066b5714941 100644 --- a/drivers/staging/comedi/drivers/aio_iiro_16.c +++ b/drivers/staging/comedi/drivers/aio_iiro_16.c @@ -30,6 +30,7 @@ Configuration Options: */ +#include #include "../comedidev.h" #include diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c index d1436733e913..dc1dee79fc16 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200.c +++ b/drivers/staging/comedi/drivers/amplc_dio200.c @@ -192,6 +192,7 @@ * order they appear in the channel list. */ +#include #include "../comedidev.h" #include "amplc_dio200.h" diff --git a/drivers/staging/comedi/drivers/amplc_dio200_common.c b/drivers/staging/comedi/drivers/amplc_dio200_common.c index 56b783642155..32c490b27b55 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200_common.c +++ b/drivers/staging/comedi/drivers/amplc_dio200_common.c @@ -19,6 +19,7 @@ GNU General Public License for more details. */ +#include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/amplc_dio200_pci.c b/drivers/staging/comedi/drivers/amplc_dio200_pci.c index 25d9cc00b888..a810a2416443 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200_pci.c +++ b/drivers/staging/comedi/drivers/amplc_dio200_pci.c @@ -220,6 +220,7 @@ * order they appear in the channel list. */ +#include #include #include diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index 81b9b80f8a64..98075f999c9f 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -47,6 +47,7 @@ the IRQ jumper. If no interrupt is connected, then subdevice 1 is unused. */ +#include #include #include diff --git a/drivers/staging/comedi/drivers/amplc_pc263.c b/drivers/staging/comedi/drivers/amplc_pc263.c index 6546095e7a45..e7108045f553 100644 --- a/drivers/staging/comedi/drivers/amplc_pc263.c +++ b/drivers/staging/comedi/drivers/amplc_pc263.c @@ -33,6 +33,7 @@ connected to a reed-relay. Relay contacts are closed when output is 1. The state of the outputs can be read. */ +#include #include "../comedidev.h" #define PC263_DRIVER_NAME "amplc_pc263" diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c index 043120448cf9..2fc56c40f5b1 100644 --- a/drivers/staging/comedi/drivers/amplc_pci224.c +++ b/drivers/staging/comedi/drivers/amplc_pci224.c @@ -98,6 +98,7 @@ Caveats: correctly. */ +#include #include #include diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c index 147702b51872..43059c25d5ea 100644 --- a/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -184,6 +184,7 @@ Support for PCI230+/260+, more triggered scan functionality, and workarounds for (or detection of) various hardware problems added by Ian Abbott. */ +#include #include #include #include diff --git a/drivers/staging/comedi/drivers/amplc_pci263.c b/drivers/staging/comedi/drivers/amplc_pci263.c index 4da900cc5845..145bb48f618e 100644 --- a/drivers/staging/comedi/drivers/amplc_pci263.c +++ b/drivers/staging/comedi/drivers/amplc_pci263.c @@ -32,6 +32,7 @@ connected to a reed-relay. Relay contacts are closed when output is 1. The state of the outputs can be read. */ +#include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c index ff0f8939ae78..05e01a3b5af6 100644 --- a/drivers/staging/comedi/drivers/cb_das16_cs.c +++ b/drivers/staging/comedi/drivers/cb_das16_cs.c @@ -34,6 +34,7 @@ Status: experimental */ +#include #include #include diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index d70d1dd30502..41d89ee7fa33 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -61,6 +61,7 @@ TODO: analog triggering on 1602 series */ +#include #include #include #include diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c index e8222b0fe841..e6e456163a29 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas64.c +++ b/drivers/staging/comedi/drivers/cb_pcidas64.c @@ -82,6 +82,7 @@ TODO: #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include #include #include #include diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c index c1f0aa59f66f..94f115820279 100644 --- a/drivers/staging/comedi/drivers/cb_pcidda.c +++ b/drivers/staging/comedi/drivers/cb_pcidda.c @@ -37,6 +37,7 @@ * Only simple analog output writing is supported. */ +#include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c index 543f213c7291..b8362a71e4bb 100644 --- a/drivers/staging/comedi/drivers/cb_pcimdas.c +++ b/drivers/staging/comedi/drivers/cb_pcimdas.c @@ -35,6 +35,7 @@ No interrupts, multi channel or FIFO AI, although the card looks like it could s See http://www.mccdaq.com/PDFs/Manuals/pcim-das1602-16.pdf for more details. */ +#include #include #include #include diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c index b019566f6c55..edf17b63096f 100644 --- a/drivers/staging/comedi/drivers/cb_pcimdda.c +++ b/drivers/staging/comedi/drivers/cb_pcimdda.c @@ -74,6 +74,7 @@ Configuration Options: not applicable, uses PCI auto config -Calin Culianu */ +#include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/comedi_bond.c b/drivers/staging/comedi/drivers/comedi_bond.c index 1952c62ad1fd..7e20bf00759c 100644 --- a/drivers/staging/comedi/drivers/comedi_bond.c +++ b/drivers/staging/comedi/drivers/comedi_bond.c @@ -45,6 +45,7 @@ Configuration Options: within each minor will be concatenated together in the order given here. */ +#include #include #include #include "../comedi.h" diff --git a/drivers/staging/comedi/drivers/comedi_fc.c b/drivers/staging/comedi/drivers/comedi_fc.c index b3d89c82d087..26d9dbcf8bd4 100644 --- a/drivers/staging/comedi/drivers/comedi_fc.c +++ b/drivers/staging/comedi/drivers/comedi_fc.c @@ -19,6 +19,7 @@ GNU General Public License for more details. */ +#include #include "../comedidev.h" #include "comedi_fc.h" diff --git a/drivers/staging/comedi/drivers/comedi_parport.c b/drivers/staging/comedi/drivers/comedi_parport.c index 05d79cf4feff..da52e514b90e 100644 --- a/drivers/staging/comedi/drivers/comedi_parport.c +++ b/drivers/staging/comedi/drivers/comedi_parport.c @@ -76,6 +76,7 @@ pin, which can be used to wake up tasks. or http://www.linux-magazin.de/ausgabe/1999/10/IO/io.html */ +#include #include "../comedidev.h" #include #include diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c index eb05f5e57ebc..16c07802107f 100644 --- a/drivers/staging/comedi/drivers/comedi_test.c +++ b/drivers/staging/comedi/drivers/comedi_test.c @@ -45,6 +45,7 @@ zero volts). */ +#include #include "../comedidev.h" #include diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c index 0fb9027dde2d..e781716bf355 100644 --- a/drivers/staging/comedi/drivers/contec_pci_dio.c +++ b/drivers/staging/comedi/drivers/contec_pci_dio.c @@ -25,6 +25,7 @@ Status: works Configuration Options: not applicable, uses comedi PCI auto config */ +#include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c index f821b81cd3be..de920ccff400 100644 --- a/drivers/staging/comedi/drivers/daqboard2000.c +++ b/drivers/staging/comedi/drivers/daqboard2000.c @@ -102,6 +102,7 @@ Configuration options: not applicable, uses PCI auto config */ +#include #include #include #include diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index 2e7e3e202390..126b4528d3cf 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -33,6 +33,7 @@ * cheap das08 hardware doesn't really support them. */ +#include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c index 24a3922ddd9a..719c978bff87 100644 --- a/drivers/staging/comedi/drivers/das08_cs.c +++ b/drivers/staging/comedi/drivers/das08_cs.c @@ -39,6 +39,7 @@ Options (for pcm-das08): Command support does not exist, but could be added for this board. */ +#include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/das08_isa.c b/drivers/staging/comedi/drivers/das08_isa.c index 50d27aa923dd..4fb03d3852d3 100644 --- a/drivers/staging/comedi/drivers/das08_isa.c +++ b/drivers/staging/comedi/drivers/das08_isa.c @@ -43,6 +43,7 @@ * [0] - base io address */ +#include #include "../comedidev.h" #include "das08.h" diff --git a/drivers/staging/comedi/drivers/das08_pci.c b/drivers/staging/comedi/drivers/das08_pci.c index 2786887173a4..3a6d3725b25f 100644 --- a/drivers/staging/comedi/drivers/das08_pci.c +++ b/drivers/staging/comedi/drivers/das08_pci.c @@ -31,6 +31,7 @@ * Configuration Options: not applicable, uses PCI auto config */ +#include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 66be41db59ad..593ec3866146 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -73,6 +73,8 @@ www.measurementcomputing.com */ +#include +#include #include #include diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c index ee5e1561c835..ede0d47aefc3 100644 --- a/drivers/staging/comedi/drivers/das16m1.c +++ b/drivers/staging/comedi/drivers/das16m1.c @@ -52,6 +52,7 @@ Options: irq can be omitted, although the cmd interface will not work without it. */ +#include #include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index e6c852530acb..f5ed55c68fa1 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -94,6 +94,7 @@ TODO: read insn for analog out */ +#include #include #include #include diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c index 8529c9f402a1..8f6dc0a44909 100644 --- a/drivers/staging/comedi/drivers/das6402.c +++ b/drivers/staging/comedi/drivers/das6402.c @@ -33,6 +33,7 @@ Devices: [Keithley Metrabyte] DAS6402 (das6402) This driver has suffered bitrot. */ +#include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c index f3f4be5b3a59..13e1cd0afd32 100644 --- a/drivers/staging/comedi/drivers/das800.c +++ b/drivers/staging/comedi/drivers/das800.c @@ -56,6 +56,7 @@ cmd triggers supported: */ +#include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index a8b2c64cafd9..1d80d7457529 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -32,6 +32,8 @@ Configuration Options: comedi_config /dev/comedi0 dmm32at baseaddr,irq */ +#include +#include #include #include "../comedidev.h" #include diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c index 2aa70d2b502d..2537696f80fc 100644 --- a/drivers/staging/comedi/drivers/dt2801.c +++ b/drivers/staging/comedi/drivers/dt2801.c @@ -29,6 +29,7 @@ Configuration options: [5] - D/A 1 range (same choices) */ +#include #include "../comedidev.h" #include #include diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c index bbae652aa894..34afa940db77 100644 --- a/drivers/staging/comedi/drivers/dt2811.c +++ b/drivers/staging/comedi/drivers/dt2811.c @@ -41,6 +41,7 @@ Configuration options: [4] - D/A 1 range (same choices) */ +#include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c index a46a5b32405d..a1076a43c294 100644 --- a/drivers/staging/comedi/drivers/dt2814.c +++ b/drivers/staging/comedi/drivers/dt2814.c @@ -34,6 +34,7 @@ a power of 10, from 1 to 10^7, of which only 3 or 4 are useful. In addition, the clock does not seem to be very accurate. */ +#include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/dt2815.c b/drivers/staging/comedi/drivers/dt2815.c index e729271fcfe3..c33708c90585 100644 --- a/drivers/staging/comedi/drivers/dt2815.c +++ b/drivers/staging/comedi/drivers/dt2815.c @@ -51,6 +51,7 @@ Configuration options: [12] - Analog output 7 range configuration (same options) */ +#include #include "../comedidev.h" #include diff --git a/drivers/staging/comedi/drivers/dt2817.c b/drivers/staging/comedi/drivers/dt2817.c index 2f46be715f79..1ba49e79ee01 100644 --- a/drivers/staging/comedi/drivers/dt2817.c +++ b/drivers/staging/comedi/drivers/dt2817.c @@ -33,6 +33,7 @@ Configuration options: [0] - I/O port base base address */ +#include #include "../comedidev.h" #include diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index 3d1ae5f3fa5f..6d3553c8a24d 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -51,13 +51,17 @@ Notes: be fixed to check for this situation and return an error. */ +#include #include "../comedidev.h" +#include #include #include #include #include + #include + #include "comedi_fc.h" #define DEBUG diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c index c255ed1ec231..e4748da1993b 100644 --- a/drivers/staging/comedi/drivers/dt3000.c +++ b/drivers/staging/comedi/drivers/dt3000.c @@ -50,6 +50,7 @@ AO commands are not supported. #define DEBUG 1 +#include #include #include #include diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c index 07aa828365e5..ffb7572b10f5 100644 --- a/drivers/staging/comedi/drivers/dt9812.c +++ b/drivers/staging/comedi/drivers/dt9812.c @@ -39,6 +39,7 @@ for my needs. */ #include +#include #include #include #include diff --git a/drivers/staging/comedi/drivers/dyna_pci10xx.c b/drivers/staging/comedi/drivers/dyna_pci10xx.c index 33398041b664..fd525f499f2a 100644 --- a/drivers/staging/comedi/drivers/dyna_pci10xx.c +++ b/drivers/staging/comedi/drivers/dyna_pci10xx.c @@ -33,6 +33,8 @@ their cards in their manuals. */ +#include +#include #include #include diff --git a/drivers/staging/comedi/drivers/fl512.c b/drivers/staging/comedi/drivers/fl512.c index 77646371d80c..13f86d5cc957 100644 --- a/drivers/staging/comedi/drivers/fl512.c +++ b/drivers/staging/comedi/drivers/fl512.c @@ -18,6 +18,7 @@ Configuration options: #define DEBUG 0 +#include #include "../comedidev.h" #include diff --git a/drivers/staging/comedi/drivers/gsc_hpdi.c b/drivers/staging/comedi/drivers/gsc_hpdi.c index f130327f88d3..cdcc8f42e209 100644 --- a/drivers/staging/comedi/drivers/gsc_hpdi.c +++ b/drivers/staging/comedi/drivers/gsc_hpdi.c @@ -42,6 +42,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include #include #include #include diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c index ee40233e81b3..3889d23292d0 100644 --- a/drivers/staging/comedi/drivers/icp_multi.c +++ b/drivers/staging/comedi/drivers/icp_multi.c @@ -42,6 +42,7 @@ There are 4 x 12-bit Analogue Outputs. Ranges : 5V, 10V, +/-5V, +/-10V Configuration options: not applicable, uses PCI auto config */ +#include #include #include #include diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c index 0d4de7d1094d..9c199a194d2b 100644 --- a/drivers/staging/comedi/drivers/ii_pci20kc.c +++ b/drivers/staging/comedi/drivers/ii_pci20kc.c @@ -77,6 +77,7 @@ options for PCI-20341M: 3 200 */ +#include #include "../comedidev.h" #define PCI20000_ID 0x1d diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c index a9817c980fbc..b52d58e5de27 100644 --- a/drivers/staging/comedi/drivers/jr3_pci.c +++ b/drivers/staging/comedi/drivers/jr3_pci.c @@ -38,6 +38,7 @@ */ #include +#include #include #include #include diff --git a/drivers/staging/comedi/drivers/ke_counter.c b/drivers/staging/comedi/drivers/ke_counter.c index f10cf10e5fe3..15589f62a619 100644 --- a/drivers/staging/comedi/drivers/ke_counter.c +++ b/drivers/staging/comedi/drivers/ke_counter.c @@ -29,6 +29,7 @@ This driver is a simple driver to read the counter values from Kolter Electronic PCI Counter Card. */ +#include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c index f84f0fbb6eaa..1eda40a9332e 100644 --- a/drivers/staging/comedi/drivers/me4000.c +++ b/drivers/staging/comedi/drivers/me4000.c @@ -40,6 +40,7 @@ broken. */ +#include #include #include #include diff --git a/drivers/staging/comedi/drivers/me_daq.c b/drivers/staging/comedi/drivers/me_daq.c index 234332044310..e8a743c2f9a1 100644 --- a/drivers/staging/comedi/drivers/me_daq.c +++ b/drivers/staging/comedi/drivers/me_daq.c @@ -30,6 +30,7 @@ * Analog Input, Analog Output, Digital I/O */ +#include #include #include #include diff --git a/drivers/staging/comedi/drivers/mite.c b/drivers/staging/comedi/drivers/mite.c index 12c34db61d63..35cb4ace7970 100644 --- a/drivers/staging/comedi/drivers/mite.c +++ b/drivers/staging/comedi/drivers/mite.c @@ -46,6 +46,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c index f24657f304fd..bfdc2d36e651 100644 --- a/drivers/staging/comedi/drivers/mpc624.c +++ b/drivers/staging/comedi/drivers/mpc624.c @@ -51,6 +51,7 @@ Configuration Options: 1 -10.1V .. +10.1V */ +#include #include "../comedidev.h" #include diff --git a/drivers/staging/comedi/drivers/multiq3.c b/drivers/staging/comedi/drivers/multiq3.c index 8db2aad5441e..088e3524e586 100644 --- a/drivers/staging/comedi/drivers/multiq3.c +++ b/drivers/staging/comedi/drivers/multiq3.c @@ -24,6 +24,7 @@ Devices: [Quanser Consulting] MultiQ-3 (multiq3) */ +#include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c index 2077d6ba6d3f..c2745f201f2c 100644 --- a/drivers/staging/comedi/drivers/ni_6527.c +++ b/drivers/staging/comedi/drivers/ni_6527.c @@ -36,6 +36,7 @@ Updated: Sat, 25 Jan 2003 13:24:40 -0800 #define DEBUG 1 #define DEBUG_FLAGS +#include #include #include diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c index 1bd830023118..3ba4c5712dff 100644 --- a/drivers/staging/comedi/drivers/ni_65xx.c +++ b/drivers/staging/comedi/drivers/ni_65xx.c @@ -46,6 +46,7 @@ except maybe the 6514. #define DEBUG 1 #define DEBUG_FLAGS +#include #include #include diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c index d90d4a09ba4c..3607336dafe2 100644 --- a/drivers/staging/comedi/drivers/ni_660x.c +++ b/drivers/staging/comedi/drivers/ni_660x.c @@ -34,6 +34,7 @@ * DAQ 6601/6602 User Manual (NI 322137B-01) */ +#include #include #include diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c index 4876f116ba92..02016258bd4e 100644 --- a/drivers/staging/comedi/drivers/ni_670x.c +++ b/drivers/staging/comedi/drivers/ni_670x.c @@ -36,6 +36,7 @@ Commands are not supported. */ +#include #include #include diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c index 82c5ca686300..e13d5c83fb48 100644 --- a/drivers/staging/comedi/drivers/ni_at_a2150.c +++ b/drivers/staging/comedi/drivers/ni_at_a2150.c @@ -58,12 +58,15 @@ TRIG_WAKE_EOS */ +#include +#include #include #include #include "../comedidev.h" #include #include + #include #include "8253.h" diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c index 639377a60c12..e19a7673ac3b 100644 --- a/drivers/staging/comedi/drivers/ni_at_ao.c +++ b/drivers/staging/comedi/drivers/ni_at_ao.c @@ -36,6 +36,7 @@ Configuration options: * document 320379.pdf. */ +#include #include "../comedidev.h" #include diff --git a/drivers/staging/comedi/drivers/ni_atmio.c b/drivers/staging/comedi/drivers/ni_atmio.c index 713edd55a91b..64f5dc7c5431 100644 --- a/drivers/staging/comedi/drivers/ni_atmio.c +++ b/drivers/staging/comedi/drivers/ni_atmio.c @@ -89,6 +89,7 @@ are not supported. */ +#include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c index d91fbc8240c0..7b28fffa4913 100644 --- a/drivers/staging/comedi/drivers/ni_atmio16d.c +++ b/drivers/staging/comedi/drivers/ni_atmio16d.c @@ -30,6 +30,7 @@ Devices: [National Instruments] AT-MIO-16 (atmio16), AT-MIO-16D (atmio16d) * */ +#include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c index 12aa15b42887..c274a14216ea 100644 --- a/drivers/staging/comedi/drivers/ni_daq_700.c +++ b/drivers/staging/comedi/drivers/ni_daq_700.c @@ -45,6 +45,8 @@ Manuals: Register level: http://www.ni.com/pdf/manuals/340698.pdf User Manual: http://www.ni.com/pdf/manuals/320676d.pdf */ +#include +#include #include #include diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c index d3d4eb9356a7..335ea34fa57c 100644 --- a/drivers/staging/comedi/drivers/ni_daq_dio24.c +++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c @@ -31,6 +31,7 @@ This is just a wrapper around the 8255.o driver to properly handle the PCMCIA interface. */ +#include #include "../comedidev.h" #include diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index 4119dcfd4761..3e95ac5402ca 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -57,6 +57,7 @@ * 320502b (lab-pc+) */ +#include #include #include #include diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c index df1de784e90b..0a8b3223f74e 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_cs.c +++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c @@ -53,6 +53,7 @@ NI manuals: */ +#include #include "../comedidev.h" #include diff --git a/drivers/staging/comedi/drivers/ni_labpc_pci.c b/drivers/staging/comedi/drivers/ni_labpc_pci.c index 203a7cef7750..8be681fca907 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_pci.c +++ b/drivers/staging/comedi/drivers/ni_labpc_pci.c @@ -29,6 +29,7 @@ * 340914a (pci-1200) */ +#include #include #include diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c index f813f5763671..229a273f2016 100644 --- a/drivers/staging/comedi/drivers/ni_mio_cs.c +++ b/drivers/staging/comedi/drivers/ni_mio_cs.c @@ -36,6 +36,7 @@ See the notes in the ni_atmio.o driver. */ +#include #include "../comedidev.h" #include diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index 3c5275b669fc..8ac7a7cce0e6 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -50,6 +50,7 @@ comedi_nonfree_firmware tarball available from http://www.comedi.org /* #define DEBUG 1 */ /* #define DEBUG_FLAGS */ +#include #include #include #include diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c index 35681ba1f369..536be83af549 100644 --- a/drivers/staging/comedi/drivers/ni_pcimio.c +++ b/drivers/staging/comedi/drivers/ni_pcimio.c @@ -106,6 +106,7 @@ Bugs: */ +#include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/ni_tio.c b/drivers/staging/comedi/drivers/ni_tio.c index 5b6fde08e582..9b120c77d83a 100644 --- a/drivers/staging/comedi/drivers/ni_tio.c +++ b/drivers/staging/comedi/drivers/ni_tio.c @@ -44,6 +44,7 @@ TODO: Support use of both banks X and Y */ +#include #include #include "ni_tio_internal.h" diff --git a/drivers/staging/comedi/drivers/ni_tiocmd.c b/drivers/staging/comedi/drivers/ni_tiocmd.c index cff50bc45bcd..45691efefd05 100644 --- a/drivers/staging/comedi/drivers/ni_tiocmd.c +++ b/drivers/staging/comedi/drivers/ni_tiocmd.c @@ -44,6 +44,7 @@ TODO: Support use of both banks X and Y */ +#include #include "comedi_fc.h" #include "ni_tio_internal.h" #include "mite.h" diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c index f5ac58342a7c..6986837edef0 100644 --- a/drivers/staging/comedi/drivers/pcl711.c +++ b/drivers/staging/comedi/drivers/pcl711.c @@ -53,6 +53,7 @@ supported. */ +#include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/pcl724.c b/drivers/staging/comedi/drivers/pcl724.c index cea657c7801d..51fe1a2740e6 100644 --- a/drivers/staging/comedi/drivers/pcl724.c +++ b/drivers/staging/comedi/drivers/pcl724.c @@ -25,6 +25,7 @@ * 1, 96: 96 DIO configuration */ +#include #include "../comedidev.h" #include diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c index 9bd341fedced..e167ea6f6760 100644 --- a/drivers/staging/comedi/drivers/pcl726.c +++ b/drivers/staging/comedi/drivers/pcl726.c @@ -62,6 +62,7 @@ Interrupts are not supported. their web page. (http://www.cir.com/) */ +#include #include "../comedidev.h" #include diff --git a/drivers/staging/comedi/drivers/pcl730.c b/drivers/staging/comedi/drivers/pcl730.c index 862e75fd68fd..6d23a9d0ddcb 100644 --- a/drivers/staging/comedi/drivers/pcl730.c +++ b/drivers/staging/comedi/drivers/pcl730.c @@ -27,6 +27,7 @@ * The ACL-7130 card has an 8254 timer/counter not supported by this driver. */ +#include #include "../comedidev.h" #include diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index 699d4558c122..c4f2f4e0a40f 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -108,6 +108,7 @@ * 3= 20V unipolar inputs */ +#include #include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index 02285976177a..dfce2a5599ce 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -32,6 +32,7 @@ Configuration Options: */ +#include #include "../comedidev.h" #include diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index 55f10e754c76..48042967065d 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -98,6 +98,7 @@ A word or two about DMA. Driver support DMA operations at two ways: */ +#include #include #include #include diff --git a/drivers/staging/comedi/drivers/pcm3724.c b/drivers/staging/comedi/drivers/pcm3724.c index 87cba62c6aed..31d398ca9ae1 100644 --- a/drivers/staging/comedi/drivers/pcm3724.c +++ b/drivers/staging/comedi/drivers/pcm3724.c @@ -28,6 +28,7 @@ Copy/pasted/hacked from pcm724.c * struct comedi_insn */ +#include #include "../comedidev.h" #include diff --git a/drivers/staging/comedi/drivers/pcmad.c b/drivers/staging/comedi/drivers/pcmad.c index d5c728dc6192..423f23676d26 100644 --- a/drivers/staging/comedi/drivers/pcmad.c +++ b/drivers/staging/comedi/drivers/pcmad.c @@ -38,6 +38,7 @@ * 1 = two's complement (+-10V input range) */ +#include #include "../comedidev.h" #define PCMAD_STATUS 0 diff --git a/drivers/staging/comedi/drivers/pcmda12.c b/drivers/staging/comedi/drivers/pcmda12.c index 2839241bb35a..1c7a135c91d6 100644 --- a/drivers/staging/comedi/drivers/pcmda12.c +++ b/drivers/staging/comedi/drivers/pcmda12.c @@ -48,6 +48,7 @@ * [1] - Do Simultaneous Xfer (see description) */ +#include #include "../comedidev.h" /* AI range is not configurable, it's set by jumpers on the board */ diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c index feb83caef26f..fab93a73651d 100644 --- a/drivers/staging/comedi/drivers/pcmmio.c +++ b/drivers/staging/comedi/drivers/pcmmio.c @@ -72,6 +72,7 @@ Configuration Options: leave out if you don't need this feature) */ +#include #include #include diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index 30f53fb5a0ac..13f1943f5b8b 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -73,6 +73,7 @@ * can be the same as first irq!) */ +#include #include #include diff --git a/drivers/staging/comedi/drivers/poc.c b/drivers/staging/comedi/drivers/poc.c index e50dd09a2031..3b51bef52ef6 100644 --- a/drivers/staging/comedi/drivers/poc.c +++ b/drivers/staging/comedi/drivers/poc.c @@ -30,6 +30,7 @@ Configuration options: [0] - I/O port base */ +#include #include "../comedidev.h" #include diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c index 478a97271a48..9775d3622a62 100644 --- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c +++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c @@ -47,6 +47,7 @@ Status: works Devices: [Quatech] DAQP-208 (daqp), DAQP-308 */ +#include #include "../comedidev.h" #include diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c index 928f534ae4ec..635c8f5cd8f6 100644 --- a/drivers/staging/comedi/drivers/rtd520.c +++ b/drivers/staging/comedi/drivers/rtd520.c @@ -95,6 +95,7 @@ * Digital-IO and Analog-Out only support instruction mode. */ +#include #include #include #include diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c index b95fce5d26fb..47a0abc88dbb 100644 --- a/drivers/staging/comedi/drivers/rti800.c +++ b/drivers/staging/comedi/drivers/rti800.c @@ -49,6 +49,8 @@ * [8] - DAC 1 encoding (same as DAC 0) */ +#include +#include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/rti802.c b/drivers/staging/comedi/drivers/rti802.c index 664ad70b0501..116687ba21ae 100644 --- a/drivers/staging/comedi/drivers/rti802.c +++ b/drivers/staging/comedi/drivers/rti802.c @@ -32,6 +32,7 @@ Configuration Options: [17] - dac#7 ... */ +#include #include "../comedidev.h" #include diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c index 24d21eef74f8..0373a45ec4e7 100644 --- a/drivers/staging/comedi/drivers/s526.c +++ b/drivers/staging/comedi/drivers/s526.c @@ -36,6 +36,7 @@ comedi_config /dev/comedi0 s526 0x2C0,0x3 */ +#include #include "../comedidev.h" #include #include diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c index f5ef91f39bbf..b0ba9b9b433b 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c @@ -59,6 +59,8 @@ INSN_CONFIG instructions: comedi_do_insn(cf,&insn); //executing configuration */ +#include +#include #include #include #include diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c index b6efe9b1d4d2..11a6da841454 100644 --- a/drivers/staging/comedi/drivers/serial2002.c +++ b/drivers/staging/comedi/drivers/serial2002.c @@ -26,6 +26,7 @@ Status: in development */ +#include #include "../comedidev.h" #include diff --git a/drivers/staging/comedi/drivers/skel.c b/drivers/staging/comedi/drivers/skel.c index 3fc7713af5ce..f76fd09e7bd3 100644 --- a/drivers/staging/comedi/drivers/skel.c +++ b/drivers/staging/comedi/drivers/skel.c @@ -67,6 +67,7 @@ Configuration Options: * options that are used with comedi_config. */ +#include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c index 45c661cbdbb9..4da4d3208fdb 100644 --- a/drivers/staging/comedi/drivers/ssv_dnp.c +++ b/drivers/staging/comedi/drivers/ssv_dnp.c @@ -26,6 +26,7 @@ Status: unknown /* include files ----------------------------------------------------------- */ +#include #include "../comedidev.h" /* Some global definitions: the registers of the DNP ----------------------- */ diff --git a/drivers/staging/comedi/drivers/unioxx5.c b/drivers/staging/comedi/drivers/unioxx5.c index 806285bc6ca7..a4cb573233e3 100644 --- a/drivers/staging/comedi/drivers/unioxx5.c +++ b/drivers/staging/comedi/drivers/unioxx5.c @@ -40,6 +40,8 @@ Devices: [Fastwel] UNIOxx-5 (unioxx5), #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include +#include #include "../comedidev.h" #include From 8e6b7915a1da703617dca28c33e150141fcec9b0 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 24 Jun 2013 17:05:07 -0700 Subject: [PATCH 0361/3400] staging: comedi: drivers do not need All the ioport resources are managed by the comedi core. None of the drivers depend on . Remove the includes. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 1 - drivers/staging/comedi/drivers/8255.c | 2 -- drivers/staging/comedi/drivers/aio_aio12_8.c | 1 - drivers/staging/comedi/drivers/aio_iiro_16.c | 1 - drivers/staging/comedi/drivers/c6xdigio.c | 1 - drivers/staging/comedi/drivers/comedi_parport.c | 1 - drivers/staging/comedi/drivers/das16m1.c | 1 - drivers/staging/comedi/drivers/das1800.c | 1 - drivers/staging/comedi/drivers/das6402.c | 2 -- drivers/staging/comedi/drivers/das800.c | 1 - drivers/staging/comedi/drivers/dmm32at.c | 1 - drivers/staging/comedi/drivers/dt2801.c | 1 - drivers/staging/comedi/drivers/dt2811.c | 2 -- drivers/staging/comedi/drivers/dt2814.c | 1 - drivers/staging/comedi/drivers/dt2815.c | 1 - drivers/staging/comedi/drivers/dt2817.c | 2 -- drivers/staging/comedi/drivers/dt282x.c | 1 - drivers/staging/comedi/drivers/fl512.c | 1 - drivers/staging/comedi/drivers/mpc624.c | 1 - drivers/staging/comedi/drivers/multiq3.c | 2 -- drivers/staging/comedi/drivers/ni_at_a2150.c | 1 - drivers/staging/comedi/drivers/ni_at_ao.c | 2 -- drivers/staging/comedi/drivers/ni_atmio16d.c | 2 -- drivers/staging/comedi/drivers/ni_daq_700.c | 1 - drivers/staging/comedi/drivers/pcl711.c | 1 - drivers/staging/comedi/drivers/pcl724.c | 1 - drivers/staging/comedi/drivers/pcl726.c | 2 -- drivers/staging/comedi/drivers/pcl730.c | 2 -- drivers/staging/comedi/drivers/pcl812.c | 1 - drivers/staging/comedi/drivers/pcl816.c | 1 - drivers/staging/comedi/drivers/pcl818.c | 1 - drivers/staging/comedi/drivers/pcm3724.c | 1 - drivers/staging/comedi/drivers/poc.c | 2 -- drivers/staging/comedi/drivers/rti800.c | 2 -- drivers/staging/comedi/drivers/rti802.c | 2 -- drivers/staging/comedi/drivers/s526.c | 1 - drivers/staging/comedi/drivers/serial2002.c | 1 - drivers/staging/comedi/drivers/unioxx5.c | 1 - drivers/staging/comedi/kcomedilib/kcomedilib_main.c | 1 - 39 files changed, 51 deletions(-) diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 8647518259f6..ad275567c09a 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c index 7966079a8361..1fa29ac4eb5d 100644 --- a/drivers/staging/comedi/drivers/8255.c +++ b/drivers/staging/comedi/drivers/8255.c @@ -76,8 +76,6 @@ I/O port base address can be found in the output of 'lspci -v'. #include #include "../comedidev.h" -#include - #include "comedi_fc.h" #include "8255.h" diff --git a/drivers/staging/comedi/drivers/aio_aio12_8.c b/drivers/staging/comedi/drivers/aio_aio12_8.c index 8d081076eed6..abb28498b58c 100644 --- a/drivers/staging/comedi/drivers/aio_aio12_8.c +++ b/drivers/staging/comedi/drivers/aio_aio12_8.c @@ -37,7 +37,6 @@ Notes: #include #include "../comedidev.h" -#include #include "8255.h" /* diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c index f066b5714941..afe87cc89761 100644 --- a/drivers/staging/comedi/drivers/aio_iiro_16.c +++ b/drivers/staging/comedi/drivers/aio_iiro_16.c @@ -32,7 +32,6 @@ Configuration Options: #include #include "../comedidev.h" -#include #define AIO_IIRO_16_SIZE 0x08 #define AIO_IIRO_16_RELAY_0_7 0x00 diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c index 929218a35975..cff23acd76ee 100644 --- a/drivers/staging/comedi/drivers/c6xdigio.c +++ b/drivers/staging/comedi/drivers/c6xdigio.c @@ -35,7 +35,6 @@ http://robot0.ge.uiuc.edu/~spong/mecha/ #include #include #include -#include #include #include #include diff --git a/drivers/staging/comedi/drivers/comedi_parport.c b/drivers/staging/comedi/drivers/comedi_parport.c index da52e514b90e..f28a15f0274e 100644 --- a/drivers/staging/comedi/drivers/comedi_parport.c +++ b/drivers/staging/comedi/drivers/comedi_parport.c @@ -79,7 +79,6 @@ pin, which can be used to wake up tasks. #include #include "../comedidev.h" #include -#include #include "comedi_fc.h" diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c index ede0d47aefc3..b943c449b691 100644 --- a/drivers/staging/comedi/drivers/das16m1.c +++ b/drivers/staging/comedi/drivers/das16m1.c @@ -53,7 +53,6 @@ irq can be omitted, although the cmd interface will not work without it. */ #include -#include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index f5ed55c68fa1..5b300294d322 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -100,7 +100,6 @@ TODO: #include #include "../comedidev.h" -#include #include #include "8253.h" diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c index 8f6dc0a44909..fb25cb847032 100644 --- a/drivers/staging/comedi/drivers/das6402.c +++ b/drivers/staging/comedi/drivers/das6402.c @@ -37,8 +37,6 @@ This driver has suffered bitrot. #include #include "../comedidev.h" -#include - #define DAS6402_SIZE 16 #define N_WORDS (3000*64) diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c index 13e1cd0afd32..11e16114e4e3 100644 --- a/drivers/staging/comedi/drivers/das800.c +++ b/drivers/staging/comedi/drivers/das800.c @@ -60,7 +60,6 @@ cmd triggers supported: #include #include "../comedidev.h" -#include #include #include "8253.h" diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index 1d80d7457529..5237f47d39ae 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -36,7 +36,6 @@ Configuration Options: #include #include #include "../comedidev.h" -#include #include "comedi_fc.h" diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c index 2537696f80fc..e0e7beab7274 100644 --- a/drivers/staging/comedi/drivers/dt2801.c +++ b/drivers/staging/comedi/drivers/dt2801.c @@ -32,7 +32,6 @@ Configuration options: #include #include "../comedidev.h" #include -#include #define DT2801_TIMEOUT 1000 diff --git a/drivers/staging/comedi/drivers/dt2811.c b/drivers/staging/comedi/drivers/dt2811.c index 34afa940db77..a41a5716f358 100644 --- a/drivers/staging/comedi/drivers/dt2811.c +++ b/drivers/staging/comedi/drivers/dt2811.c @@ -45,8 +45,6 @@ Configuration options: #include #include "../comedidev.h" -#include - static const struct comedi_lrange range_dt2811_pgh_ai_5_unipolar = { 4, { RANGE(0, 5), diff --git a/drivers/staging/comedi/drivers/dt2814.c b/drivers/staging/comedi/drivers/dt2814.c index a1076a43c294..6514b9e00552 100644 --- a/drivers/staging/comedi/drivers/dt2814.c +++ b/drivers/staging/comedi/drivers/dt2814.c @@ -38,7 +38,6 @@ addition, the clock does not seem to be very accurate. #include #include "../comedidev.h" -#include #include #include "comedi_fc.h" diff --git a/drivers/staging/comedi/drivers/dt2815.c b/drivers/staging/comedi/drivers/dt2815.c index c33708c90585..34040f0175e8 100644 --- a/drivers/staging/comedi/drivers/dt2815.c +++ b/drivers/staging/comedi/drivers/dt2815.c @@ -54,7 +54,6 @@ Configuration options: #include #include "../comedidev.h" -#include #include #define DT2815_SIZE 2 diff --git a/drivers/staging/comedi/drivers/dt2817.c b/drivers/staging/comedi/drivers/dt2817.c index 1ba49e79ee01..51cf1211f1ba 100644 --- a/drivers/staging/comedi/drivers/dt2817.c +++ b/drivers/staging/comedi/drivers/dt2817.c @@ -36,8 +36,6 @@ Configuration options: #include #include "../comedidev.h" -#include - #define DT2817_SIZE 5 #define DT2817_CR 0 diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index 6d3553c8a24d..23cb033559b3 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -56,7 +56,6 @@ Notes: #include #include -#include #include #include diff --git a/drivers/staging/comedi/drivers/fl512.c b/drivers/staging/comedi/drivers/fl512.c index 13f86d5cc957..8d70f64b1574 100644 --- a/drivers/staging/comedi/drivers/fl512.c +++ b/drivers/staging/comedi/drivers/fl512.c @@ -22,7 +22,6 @@ Configuration options: #include "../comedidev.h" #include -#include #define FL512_SIZE 16 /* the size of the used memory */ struct fl512_private { diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c index bfdc2d36e651..acbaeee6250c 100644 --- a/drivers/staging/comedi/drivers/mpc624.c +++ b/drivers/staging/comedi/drivers/mpc624.c @@ -54,7 +54,6 @@ Configuration Options: #include #include "../comedidev.h" -#include #include /* Consecutive I/O port addresses */ diff --git a/drivers/staging/comedi/drivers/multiq3.c b/drivers/staging/comedi/drivers/multiq3.c index 088e3524e586..9d75ea4e201b 100644 --- a/drivers/staging/comedi/drivers/multiq3.c +++ b/drivers/staging/comedi/drivers/multiq3.c @@ -28,8 +28,6 @@ Devices: [Quanser Consulting] MultiQ-3 (multiq3) #include #include "../comedidev.h" -#include - #define MULTIQ3_SIZE 16 /* diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c index e13d5c83fb48..2512ce8dfcaa 100644 --- a/drivers/staging/comedi/drivers/ni_at_a2150.c +++ b/drivers/staging/comedi/drivers/ni_at_a2150.c @@ -64,7 +64,6 @@ TRIG_WAKE_EOS #include #include "../comedidev.h" -#include #include #include diff --git a/drivers/staging/comedi/drivers/ni_at_ao.c b/drivers/staging/comedi/drivers/ni_at_ao.c index e19a7673ac3b..0025496bc643 100644 --- a/drivers/staging/comedi/drivers/ni_at_ao.c +++ b/drivers/staging/comedi/drivers/ni_at_ao.c @@ -39,8 +39,6 @@ Configuration options: #include #include "../comedidev.h" -#include - /* board egisters */ /* registers with _2_ are accessed when GRP2WR is set in CFG1 */ diff --git a/drivers/staging/comedi/drivers/ni_atmio16d.c b/drivers/staging/comedi/drivers/ni_atmio16d.c index 7b28fffa4913..8520d83d940f 100644 --- a/drivers/staging/comedi/drivers/ni_atmio16d.c +++ b/drivers/staging/comedi/drivers/ni_atmio16d.c @@ -34,8 +34,6 @@ Devices: [National Instruments] AT-MIO-16 (atmio16), AT-MIO-16D (atmio16d) #include #include "../comedidev.h" -#include - #include "comedi_fc.h" #include "8255.h" diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c index c274a14216ea..41659652a491 100644 --- a/drivers/staging/comedi/drivers/ni_daq_700.c +++ b/drivers/staging/comedi/drivers/ni_daq_700.c @@ -47,7 +47,6 @@ Manuals: Register level: http://www.ni.com/pdf/manuals/340698.pdf #include #include -#include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c index 6986837edef0..e859f85a8e17 100644 --- a/drivers/staging/comedi/drivers/pcl711.c +++ b/drivers/staging/comedi/drivers/pcl711.c @@ -57,7 +57,6 @@ supported. #include #include "../comedidev.h" -#include #include #include "comedi_fc.h" diff --git a/drivers/staging/comedi/drivers/pcl724.c b/drivers/staging/comedi/drivers/pcl724.c index 51fe1a2740e6..88060222baf3 100644 --- a/drivers/staging/comedi/drivers/pcl724.c +++ b/drivers/staging/comedi/drivers/pcl724.c @@ -28,7 +28,6 @@ #include #include "../comedidev.h" -#include #include #include "8255.h" diff --git a/drivers/staging/comedi/drivers/pcl726.c b/drivers/staging/comedi/drivers/pcl726.c index e167ea6f6760..a4d0bcc31e52 100644 --- a/drivers/staging/comedi/drivers/pcl726.c +++ b/drivers/staging/comedi/drivers/pcl726.c @@ -65,8 +65,6 @@ Interrupts are not supported. #include #include "../comedidev.h" -#include - #undef ACL6126_IRQ /* no interrupt support (yet) */ #define PCL726_SIZE 16 diff --git a/drivers/staging/comedi/drivers/pcl730.c b/drivers/staging/comedi/drivers/pcl730.c index 6d23a9d0ddcb..2a659f23ecda 100644 --- a/drivers/staging/comedi/drivers/pcl730.c +++ b/drivers/staging/comedi/drivers/pcl730.c @@ -30,8 +30,6 @@ #include #include "../comedidev.h" -#include - /* * Register map * diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index c4f2f4e0a40f..35251e71b7f8 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -114,7 +114,6 @@ #include "../comedidev.h" #include -#include #include #include diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index dfce2a5599ce..f03134962596 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -35,7 +35,6 @@ Configuration Options: #include #include "../comedidev.h" -#include #include #include #include diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index 48042967065d..a52ba82ff0e4 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -99,7 +99,6 @@ A word or two about DMA. Driver support DMA operations at two ways: */ #include -#include #include #include #include diff --git a/drivers/staging/comedi/drivers/pcm3724.c b/drivers/staging/comedi/drivers/pcm3724.c index 31d398ca9ae1..4c710e52e63b 100644 --- a/drivers/staging/comedi/drivers/pcm3724.c +++ b/drivers/staging/comedi/drivers/pcm3724.c @@ -31,7 +31,6 @@ Copy/pasted/hacked from pcm724.c #include #include "../comedidev.h" -#include #include #include "8255.h" diff --git a/drivers/staging/comedi/drivers/poc.c b/drivers/staging/comedi/drivers/poc.c index 3b51bef52ef6..2ae4ee15704c 100644 --- a/drivers/staging/comedi/drivers/poc.c +++ b/drivers/staging/comedi/drivers/poc.c @@ -33,8 +33,6 @@ Configuration options: #include #include "../comedidev.h" -#include - struct boarddef_struct { const char *name; unsigned int iosize; diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c index 47a0abc88dbb..cbb4ba5b852a 100644 --- a/drivers/staging/comedi/drivers/rti800.c +++ b/drivers/staging/comedi/drivers/rti800.c @@ -54,8 +54,6 @@ #include #include "../comedidev.h" -#include - /* * Register map */ diff --git a/drivers/staging/comedi/drivers/rti802.c b/drivers/staging/comedi/drivers/rti802.c index 116687ba21ae..a3fa2a4baef4 100644 --- a/drivers/staging/comedi/drivers/rti802.c +++ b/drivers/staging/comedi/drivers/rti802.c @@ -35,8 +35,6 @@ Configuration Options: #include #include "../comedidev.h" -#include - #define RTI802_SIZE 4 #define RTI802_SELECT 0 diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c index 0373a45ec4e7..6670b865256b 100644 --- a/drivers/staging/comedi/drivers/s526.c +++ b/drivers/staging/comedi/drivers/s526.c @@ -38,7 +38,6 @@ comedi_config /dev/comedi0 s526 0x2C0,0x3 #include #include "../comedidev.h" -#include #include #define S526_SIZE 64 diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c index 11a6da841454..441813ffb175 100644 --- a/drivers/staging/comedi/drivers/serial2002.c +++ b/drivers/staging/comedi/drivers/serial2002.c @@ -30,7 +30,6 @@ Status: in development #include "../comedidev.h" #include -#include #include #include diff --git a/drivers/staging/comedi/drivers/unioxx5.c b/drivers/staging/comedi/drivers/unioxx5.c index a4cb573233e3..93eec2fc254c 100644 --- a/drivers/staging/comedi/drivers/unioxx5.c +++ b/drivers/staging/comedi/drivers/unioxx5.c @@ -43,7 +43,6 @@ Devices: [Fastwel] UNIOxx-5 (unioxx5), #include #include #include "../comedidev.h" -#include #define DRIVER_NAME "unioxx5" #define UNIOXX5_SIZE 0x10 diff --git a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c index da8988c6bf50..cb3d3260a65e 100644 --- a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c +++ b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include From d92fef8d2552ffde42b6092cb467f3021ebf8b98 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 24 Jun 2013 17:05:31 -0700 Subject: [PATCH 0362/3400] staging: comedi: do not include if its not needed Some of the comedi files include this header but don't need it. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers.c | 1 - drivers/staging/comedi/drivers/c6xdigio.c | 1 - drivers/staging/comedi/drivers/cb_pcimdas.c | 1 - drivers/staging/comedi/drivers/das08.c | 1 - drivers/staging/comedi/drivers/das08_cs.c | 1 - drivers/staging/comedi/drivers/ni_atmio.c | 1 - drivers/staging/comedi/drivers/pcl724.c | 2 -- drivers/staging/comedi/drivers/pcm3724.c | 2 -- drivers/staging/comedi/kcomedilib/kcomedilib_main.c | 1 - 9 files changed, 11 deletions(-) diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index 87df7960c96f..a15934f94ab0 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c index cff23acd76ee..217aa19cdc32 100644 --- a/drivers/staging/comedi/drivers/c6xdigio.c +++ b/drivers/staging/comedi/drivers/c6xdigio.c @@ -35,7 +35,6 @@ http://robot0.ge.uiuc.edu/~spong/mecha/ #include #include #include -#include #include #include #include diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c index b8362a71e4bb..30520d4c16a6 100644 --- a/drivers/staging/comedi/drivers/cb_pcimdas.c +++ b/drivers/staging/comedi/drivers/cb_pcimdas.c @@ -37,7 +37,6 @@ See http://www.mccdaq.com/PDFs/Manuals/pcim-das1602-16.pdf for more details. #include #include -#include #include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index 126b4528d3cf..5f669709501f 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -34,7 +34,6 @@ */ #include -#include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c index 719c978bff87..f3ccc2ce6d49 100644 --- a/drivers/staging/comedi/drivers/das08_cs.c +++ b/drivers/staging/comedi/drivers/das08_cs.c @@ -40,7 +40,6 @@ Command support does not exist, but could be added for this board. */ #include -#include #include "../comedidev.h" diff --git a/drivers/staging/comedi/drivers/ni_atmio.c b/drivers/staging/comedi/drivers/ni_atmio.c index 64f5dc7c5431..856c73d8b7cd 100644 --- a/drivers/staging/comedi/drivers/ni_atmio.c +++ b/drivers/staging/comedi/drivers/ni_atmio.c @@ -93,7 +93,6 @@ are not supported. #include #include "../comedidev.h" -#include #include #include "ni_stc.h" diff --git a/drivers/staging/comedi/drivers/pcl724.c b/drivers/staging/comedi/drivers/pcl724.c index 88060222baf3..249f98b8346c 100644 --- a/drivers/staging/comedi/drivers/pcl724.c +++ b/drivers/staging/comedi/drivers/pcl724.c @@ -28,8 +28,6 @@ #include #include "../comedidev.h" -#include - #include "8255.h" #define SIZE_8255 4 diff --git a/drivers/staging/comedi/drivers/pcm3724.c b/drivers/staging/comedi/drivers/pcm3724.c index 4c710e52e63b..cca972ebd010 100644 --- a/drivers/staging/comedi/drivers/pcm3724.c +++ b/drivers/staging/comedi/drivers/pcm3724.c @@ -31,8 +31,6 @@ Copy/pasted/hacked from pcm724.c #include #include "../comedidev.h" -#include - #include "8255.h" #define PCM3724_SIZE 16 diff --git a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c index cb3d3260a65e..066083c1bceb 100644 --- a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c +++ b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include From 57d04eb131ec9df067028aef278867b4920177c3 Mon Sep 17 00:00:00 2001 From: Vikas Sajjan Date: Mon, 11 Feb 2013 12:58:00 +0200 Subject: [PATCH 0363/3400] usb: xhci: add the suspend/resume functionality Adds power management support to xHCI platform driver. This patch facilitates the transition of xHCI host controller between S0 and S3/S4 power states, during suspend/resume cycles. Signed-off-by: Abhilash Kesavan Signed-off-by: Vikas C Sajjan CC: Doug Anderson Signed-off-by: Felipe Balbi Signed-off-by: Sarah Sharp --- drivers/usb/host/xhci-plat.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 51e22bf89505..412fe8d167cf 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -186,11 +186,37 @@ static int xhci_plat_remove(struct platform_device *dev) return 0; } +#ifdef CONFIG_PM +static int xhci_plat_suspend(struct device *dev) +{ + struct usb_hcd *hcd = dev_get_drvdata(dev); + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + + return xhci_suspend(xhci); +} + +static int xhci_plat_resume(struct device *dev) +{ + struct usb_hcd *hcd = dev_get_drvdata(dev); + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + + return xhci_resume(xhci, 0); +} + +static const struct dev_pm_ops xhci_plat_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(xhci_plat_suspend, xhci_plat_resume) +}; +#define DEV_PM_OPS (&xhci_plat_pm_ops) +#else +#define DEV_PM_OPS NULL +#endif /* CONFIG_PM */ + static struct platform_driver usb_xhci_driver = { .probe = xhci_plat_probe, .remove = xhci_plat_remove, .driver = { .name = "xhci-hcd", + .pm = DEV_PM_OPS, }, }; MODULE_ALIAS("platform:xhci-hcd"); From eae5b17621d1053c81bec24e5dd5094bf50b31c6 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Tue, 2 Apr 2013 08:42:20 -0700 Subject: [PATCH 0364/3400] xhci: Refactor port status into a new function. The hub control function is *way* too long. Refactor it into a new function, and document the side effects of calling that function. Signed-off-by: Sarah Sharp --- drivers/usb/host/xhci-hub.c | 210 ++++++++++++++++++++---------------- 1 file changed, 119 insertions(+), 91 deletions(-) diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 1d3545943c50..83fc636fa254 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -534,6 +534,118 @@ void xhci_del_comp_mod_timer(struct xhci_hcd *xhci, u32 status, u16 wIndex) } } +/* + * Converts a raw xHCI port status into the format that external USB 2.0 or USB + * 3.0 hubs use. + * + * Possible side effects: + * - Mark a port as being done with device resume, + * and ring the endpoint doorbells. + * - Stop the Synopsys redriver Compliance Mode polling. + */ +static u32 xhci_get_port_status(struct usb_hcd *hcd, + struct xhci_bus_state *bus_state, + __le32 __iomem **port_array, + u16 wIndex, u32 raw_port_status) +{ + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + u32 status = 0; + int slot_id; + + /* wPortChange bits */ + if (raw_port_status & PORT_CSC) + status |= USB_PORT_STAT_C_CONNECTION << 16; + if (raw_port_status & PORT_PEC) + status |= USB_PORT_STAT_C_ENABLE << 16; + if ((raw_port_status & PORT_OCC)) + status |= USB_PORT_STAT_C_OVERCURRENT << 16; + if ((raw_port_status & PORT_RC)) + status |= USB_PORT_STAT_C_RESET << 16; + /* USB3.0 only */ + if (hcd->speed == HCD_USB3) { + if ((raw_port_status & PORT_PLC)) + status |= USB_PORT_STAT_C_LINK_STATE << 16; + if ((raw_port_status & PORT_WRC)) + status |= USB_PORT_STAT_C_BH_RESET << 16; + } + + if (hcd->speed != HCD_USB3) { + if ((raw_port_status & PORT_PLS_MASK) == XDEV_U3 + && (raw_port_status & PORT_POWER)) + status |= USB_PORT_STAT_SUSPEND; + } + if ((raw_port_status & PORT_PLS_MASK) == XDEV_RESUME && + !DEV_SUPERSPEED(raw_port_status)) { + if ((raw_port_status & PORT_RESET) || + !(raw_port_status & PORT_PE)) + return 0xffffffff; + if (time_after_eq(jiffies, + bus_state->resume_done[wIndex])) { + xhci_dbg(xhci, "Resume USB2 port %d\n", + wIndex + 1); + bus_state->resume_done[wIndex] = 0; + clear_bit(wIndex, &bus_state->resuming_ports); + xhci_set_link_state(xhci, port_array, wIndex, + XDEV_U0); + xhci_dbg(xhci, "set port %d resume\n", + wIndex + 1); + slot_id = xhci_find_slot_id_by_port(hcd, xhci, + wIndex + 1); + if (!slot_id) { + xhci_dbg(xhci, "slot_id is zero\n"); + return 0xffffffff; + } + xhci_ring_device(xhci, slot_id); + bus_state->port_c_suspend |= 1 << wIndex; + bus_state->suspended_ports &= ~(1 << wIndex); + } else { + /* + * The resume has been signaling for less than + * 20ms. Report the port status as SUSPEND, + * let the usbcore check port status again + * and clear resume signaling later. + */ + status |= USB_PORT_STAT_SUSPEND; + } + } + if ((raw_port_status & PORT_PLS_MASK) == XDEV_U0 + && (raw_port_status & PORT_POWER) + && (bus_state->suspended_ports & (1 << wIndex))) { + bus_state->suspended_ports &= ~(1 << wIndex); + if (hcd->speed != HCD_USB3) + bus_state->port_c_suspend |= 1 << wIndex; + } + if (raw_port_status & PORT_CONNECT) { + status |= USB_PORT_STAT_CONNECTION; + status |= xhci_port_speed(raw_port_status); + } + if (raw_port_status & PORT_PE) + status |= USB_PORT_STAT_ENABLE; + if (raw_port_status & PORT_OC) + status |= USB_PORT_STAT_OVERCURRENT; + if (raw_port_status & PORT_RESET) + status |= USB_PORT_STAT_RESET; + if (raw_port_status & PORT_POWER) { + if (hcd->speed == HCD_USB3) + status |= USB_SS_PORT_STAT_POWER; + else + status |= USB_PORT_STAT_POWER; + } + /* Update Port Link State for super speed ports*/ + if (hcd->speed == HCD_USB3) { + xhci_hub_report_link_state(&status, raw_port_status); + /* + * Verify if all USB3 Ports Have entered U0 already. + * Delete Compliance Mode Timer if so. + */ + xhci_del_comp_mod_timer(xhci, raw_port_status, wIndex); + } + if (bus_state->port_c_suspend & (1 << wIndex)) + status |= 1 << USB_PORT_FEAT_C_SUSPEND; + + return status; +} + int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength) { @@ -598,104 +710,20 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, if (!wIndex || wIndex > max_ports) goto error; wIndex--; - status = 0; temp = xhci_readl(xhci, port_array[wIndex]); if (temp == 0xffffffff) { retval = -ENODEV; break; } - xhci_dbg(xhci, "get port status, actual port %d status = 0x%x\n", wIndex, temp); + status = xhci_get_port_status(hcd, bus_state, port_array, + wIndex, temp); + if (status == 0xffffffff) + goto error; - /* wPortChange bits */ - if (temp & PORT_CSC) - status |= USB_PORT_STAT_C_CONNECTION << 16; - if (temp & PORT_PEC) - status |= USB_PORT_STAT_C_ENABLE << 16; - if ((temp & PORT_OCC)) - status |= USB_PORT_STAT_C_OVERCURRENT << 16; - if ((temp & PORT_RC)) - status |= USB_PORT_STAT_C_RESET << 16; - /* USB3.0 only */ - if (hcd->speed == HCD_USB3) { - if ((temp & PORT_PLC)) - status |= USB_PORT_STAT_C_LINK_STATE << 16; - if ((temp & PORT_WRC)) - status |= USB_PORT_STAT_C_BH_RESET << 16; - } - - if (hcd->speed != HCD_USB3) { - if ((temp & PORT_PLS_MASK) == XDEV_U3 - && (temp & PORT_POWER)) - status |= USB_PORT_STAT_SUSPEND; - } - if ((temp & PORT_PLS_MASK) == XDEV_RESUME && - !DEV_SUPERSPEED(temp)) { - if ((temp & PORT_RESET) || !(temp & PORT_PE)) - goto error; - if (time_after_eq(jiffies, - bus_state->resume_done[wIndex])) { - xhci_dbg(xhci, "Resume USB2 port %d\n", - wIndex + 1); - bus_state->resume_done[wIndex] = 0; - clear_bit(wIndex, &bus_state->resuming_ports); - xhci_set_link_state(xhci, port_array, wIndex, - XDEV_U0); - xhci_dbg(xhci, "set port %d resume\n", - wIndex + 1); - slot_id = xhci_find_slot_id_by_port(hcd, xhci, - wIndex + 1); - if (!slot_id) { - xhci_dbg(xhci, "slot_id is zero\n"); - goto error; - } - xhci_ring_device(xhci, slot_id); - bus_state->port_c_suspend |= 1 << wIndex; - bus_state->suspended_ports &= ~(1 << wIndex); - } else { - /* - * The resume has been signaling for less than - * 20ms. Report the port status as SUSPEND, - * let the usbcore check port status again - * and clear resume signaling later. - */ - status |= USB_PORT_STAT_SUSPEND; - } - } - if ((temp & PORT_PLS_MASK) == XDEV_U0 - && (temp & PORT_POWER) - && (bus_state->suspended_ports & (1 << wIndex))) { - bus_state->suspended_ports &= ~(1 << wIndex); - if (hcd->speed != HCD_USB3) - bus_state->port_c_suspend |= 1 << wIndex; - } - if (temp & PORT_CONNECT) { - status |= USB_PORT_STAT_CONNECTION; - status |= xhci_port_speed(temp); - } - if (temp & PORT_PE) - status |= USB_PORT_STAT_ENABLE; - if (temp & PORT_OC) - status |= USB_PORT_STAT_OVERCURRENT; - if (temp & PORT_RESET) - status |= USB_PORT_STAT_RESET; - if (temp & PORT_POWER) { - if (hcd->speed == HCD_USB3) - status |= USB_SS_PORT_STAT_POWER; - else - status |= USB_PORT_STAT_POWER; - } - /* Update Port Link State for super speed ports*/ - if (hcd->speed == HCD_USB3) { - xhci_hub_report_link_state(&status, temp); - /* - * Verify if all USB3 Ports Have entered U0 already. - * Delete Compliance Mode Timer if so. - */ - xhci_del_comp_mod_timer(xhci, temp, wIndex); - } - if (bus_state->port_c_suspend & (1 << wIndex)) - status |= 1 << USB_PORT_FEAT_C_SUSPEND; + xhci_dbg(xhci, "get port status, actual port %d status = 0x%x\n", + wIndex, temp); xhci_dbg(xhci, "Get port status returned 0x%x\n", status); + put_unaligned(cpu_to_le32(status), (__le32 *) buf); break; case SetPortFeature: From 063ebeb4335312d05bdf6fb4fc0e41500c6c0afb Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Tue, 2 Apr 2013 09:23:42 -0700 Subject: [PATCH 0365/3400] xhci: Report USB 2.1 link status for L1 USB 2.1 devices can go into a lower power link state, L1. When they are active, they are in the L0 state. The L1 transition can be purely driven by software, or some USB host controllers (including some xHCI 1.0 hosts) allow the host hardware to track idleness and automatically place a port into L1. The USB 2.1 Link Power Management ECN gives a way for USB 2.1 hubs that support LPM to report that a port is in L1. The port status bit 5 will be set when the port is in L1. The xHCI host reports the root port as being in 'U2' when the devices is in L1, and as being in 'U0' when the port is active (in L0). Translate the xHCI USB 2.1 link status into the format external hubs use, and pass the L1 status up to the USB core and tools like lsusb. Signed-off-by: Sarah Sharp --- drivers/usb/host/xhci-hub.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 83fc636fa254..93f3fdf0ff0a 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -461,8 +461,15 @@ void xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array, } } +/* Updates Link Status for USB 2.1 port */ +static void xhci_hub_report_usb2_link_state(u32 *status, u32 status_reg) +{ + if ((status_reg & PORT_PLS_MASK) == XDEV_U2) + *status |= USB_PORT_STAT_L1; +} + /* Updates Link Status for super Speed port */ -static void xhci_hub_report_link_state(u32 *status, u32 status_reg) +static void xhci_hub_report_usb3_link_state(u32 *status, u32 status_reg) { u32 pls = status_reg & PORT_PLS_MASK; @@ -631,14 +638,16 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, else status |= USB_PORT_STAT_POWER; } - /* Update Port Link State for super speed ports*/ + /* Update Port Link State */ if (hcd->speed == HCD_USB3) { - xhci_hub_report_link_state(&status, raw_port_status); + xhci_hub_report_usb3_link_state(&status, raw_port_status); /* * Verify if all USB3 Ports Have entered U0 already. * Delete Compliance Mode Timer if so. */ xhci_del_comp_mod_timer(xhci, raw_port_status, wIndex); + } else { + xhci_hub_report_usb2_link_state(&status, raw_port_status); } if (bus_state->port_c_suspend & (1 << wIndex)) status |= 1 << USB_PORT_FEAT_C_SUSPEND; From 381102be5b3e6b23d32eb54a686569ec194f55d1 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 24 Jun 2013 17:07:28 -0700 Subject: [PATCH 0366/3400] staging: comedi: ii_pci20kc: this is an ISA board not a PCI board The Intelligent Instrumentation PCI-20001C board is a legacy PC/XT/AT 8-bit ISA board not a PCI board. The "PCI" appears to mean "Personal Computer Instrumentation". Move the Kconfig option into the COMEDI_ISA group. Signed-off-by: H Hartley Sweeten Acked-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/Kconfig | 18 +++++++++--------- drivers/staging/comedi/drivers/Makefile | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index 8c8a55132257..e336ee8a8e32 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -403,6 +403,15 @@ config COMEDI_AIO_IIRO_16 To compile this driver as a module, choose M here: the module will be called aio_iiro_16. +config COMEDI_II_PCI20KC + tristate "Intelligent Instruments PCI-20001C carrier support" + ---help--- + Enable support for Intelligent Instruments PCI-20001C carrier + PCI-20001, PCI-20006 and PCI-20341 + + To compile this driver as a module, choose M here: the module will be + called ii_pci20kc. + config COMEDI_C6XDIGIO tristate "Mechatronic Systems Inc. C6x_DIGIO DSP daughter card support" ---help--- @@ -866,15 +875,6 @@ config COMEDI_ICP_MULTI To compile this driver as a module, choose M here: the module will be called icp_multi. -config COMEDI_II_PCI20KC - tristate "Intelligent Instruments PCI-20001C carrier support" - ---help--- - Enable support for Intelligent Instruments PCI-20001C carrier - PCI-20001, PCI-20006 and PCI-20341 - - To compile this driver as a module, choose M here: the module will be - called ii_pci20kc. - config COMEDI_DAQBOARD2000 tristate "IOtech DAQboard/2000 support" select COMEDI_8255 diff --git a/drivers/staging/comedi/drivers/Makefile b/drivers/staging/comedi/drivers/Makefile index dbb93e332487..643e5517cba4 100644 --- a/drivers/staging/comedi/drivers/Makefile +++ b/drivers/staging/comedi/drivers/Makefile @@ -39,6 +39,7 @@ obj-$(CONFIG_COMEDI_DMM32AT) += dmm32at.o obj-$(CONFIG_COMEDI_FL512) += fl512.o obj-$(CONFIG_COMEDI_AIO_AIO12_8) += aio_aio12_8.o obj-$(CONFIG_COMEDI_AIO_IIRO_16) += aio_iiro_16.o +obj-$(CONFIG_COMEDI_II_PCI20KC) += ii_pci20kc.o obj-$(CONFIG_COMEDI_C6XDIGIO) += c6xdigio.o obj-$(CONFIG_COMEDI_MPC624) += mpc624.o obj-$(CONFIG_COMEDI_ADQ12B) += adq12b.o @@ -89,7 +90,6 @@ obj-$(CONFIG_COMEDI_DYNA_PCI10XX) += dyna_pci10xx.o obj-$(CONFIG_COMEDI_UNIOXX5) += unioxx5.o obj-$(CONFIG_COMEDI_GSC_HPDI) += gsc_hpdi.o obj-$(CONFIG_COMEDI_ICP_MULTI) += icp_multi.o -obj-$(CONFIG_COMEDI_II_PCI20KC) += ii_pci20kc.o obj-$(CONFIG_COMEDI_DAQBOARD2000) += daqboard2000.o obj-$(CONFIG_COMEDI_JR3_PCI) += jr3_pci.o obj-$(CONFIG_COMEDI_KE_COUNTER) += ke_counter.o From ee68080d2c4c8fdb0ff4b126cb7701d05d47a719 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 24 Jun 2013 17:09:20 -0700 Subject: [PATCH 0367/3400] staging: comedi: pcl724: add support for the PCM-IO48 PC/104 board This driver can support the WinSystems PCM-IO48 PC/104 board. That board has two 8255 devices providing 48 digital I/O channels. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/Kconfig | 14 ++++++++++++-- drivers/staging/comedi/drivers/pcl724.c | 9 +++++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index e336ee8a8e32..b9dc94a8ea69 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -122,8 +122,18 @@ config COMEDI_PCL724 tristate "Advantech PCL-722/724/731 and ADlink ACL-7122/7124/PET-48DIO" select COMEDI_8255 ---help--- - Enable support for Advantech PCL-724, PCL-722, PCL-731 and - ADlink ACL-7122, ACL-7124, PET-48DIO ISA cards + Enable support for ISA and PC/104 based 8255 digital i/o boards. This + driver provides a legacy comedi driver wrapper for the generic 8255 + support driver. + + Supported boards include: + Advantech PCL-724 24 channels + Advantech PCL-722 144 (or 96) channels + Advantech PCL-731 48 channels + ADlink ACL-7122 144 (or 96) channels + ADlink ACL-7124 24 channels + ADlink PET-48DIO 48 channels + WinSystems PCM-IO48 48 channels (PC/104) To compile this driver as a module, choose M here: the module will be called pcl724. diff --git a/drivers/staging/comedi/drivers/pcl724.c b/drivers/staging/comedi/drivers/pcl724.c index 249f98b8346c..8af13e790ad1 100644 --- a/drivers/staging/comedi/drivers/pcl724.c +++ b/drivers/staging/comedi/drivers/pcl724.c @@ -1,6 +1,6 @@ /* * pcl724.c - * Comedi driver for 8255 based ISA DIO boards + * Comedi driver for 8255 based ISA and PC/104 DIO boards * * Michal Dobes */ @@ -14,6 +14,7 @@ * (ADLink) ACL-7122 [acl7122] * (ADLink) ACL-7124 [acl7124] * (ADLink) PET-48DIO [pet48dio] + * (WinSystems) PCM-IO48 [pcmio48] * Author: Michal Dobes * Status: untested * @@ -68,6 +69,10 @@ static const struct pcl724_board boardtypes[] = { .io_range = 0x02, .is_pet48 = 1, .numofports = 2, /* 48 DIO channels */ + }, { + .name = "pcmio48", + .io_range = 0x08, + .numofports = 2, /* 48 DIO channels */ }, }; @@ -146,5 +151,5 @@ static struct comedi_driver pcl724_driver = { module_comedi_driver(pcl724_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi driver for 8255 based ISA DIO boards"); +MODULE_DESCRIPTION("Comedi driver for 8255 based ISA and PC/104 DIO boards"); MODULE_LICENSE("GPL"); From 99c0e2691736d56190764bfdc59f11b090cda4ff Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Thu, 27 Jun 2013 14:50:57 +0100 Subject: [PATCH 0368/3400] staging: comedi: return void from comedi_driver_unregister() 'Unregister' functions generally return `void`. `comedi_driver_unregister()` currently returns an `int` errno value. Nothing looks at the return value. Change the return type to `void`. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedidev.h | 2 +- drivers/staging/comedi/drivers.c | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index ab278942ebd1..98058b9097e6 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -363,7 +363,7 @@ int comedi_auto_config(struct device *, struct comedi_driver *, void comedi_auto_unconfig(struct device *); int comedi_driver_register(struct comedi_driver *); -int comedi_driver_unregister(struct comedi_driver *); +void comedi_driver_unregister(struct comedi_driver *); /** * module_comedi_driver() - Helper macro for registering a comedi driver diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index a15934f94ab0..ba5d6d927a49 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -559,7 +559,7 @@ int comedi_driver_register(struct comedi_driver *driver) } EXPORT_SYMBOL_GPL(comedi_driver_register); -int comedi_driver_unregister(struct comedi_driver *driver) +void comedi_driver_unregister(struct comedi_driver *driver) { struct comedi_driver *prev; int i; @@ -584,15 +584,14 @@ int comedi_driver_unregister(struct comedi_driver *driver) if (comedi_drivers == driver) { comedi_drivers = driver->next; - return 0; + return; } for (prev = comedi_drivers; prev->next; prev = prev->next) { if (prev->next == driver) { prev->next = driver->next; - return 0; + return; } } - return -EINVAL; } EXPORT_SYMBOL_GPL(comedi_driver_unregister); From c383e2d6dacf0b6fdd40fbaf044e235cac54a20f Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Thu, 27 Jun 2013 14:50:58 +0100 Subject: [PATCH 0369/3400] staging: comedi: use a mutex when accessing driver list Low-level comedi drivers registered with the comedi core by `comedi_driver_register()` are linked together into a simple linked list headed by the `comedi_drivers` variable and chained by the `next` member of `struct comedi_driver`. A driver is removed from the list by `comedi_driver_unregister()`. The driver list is iterated through by `comedi_device_attach()` when the `COMEDI_DEVCONFIG` ioctl is used to attach a "legacy" device to a driver, and is also iterated through by `comedi_read()` in "proc.c" when reading "/proc/comedi". There is currently no protection against items being added or removed from the list while it is being iterated. Add a mutex `comedi_drivers_list_lock` to be locked while adding or removing an item on the list, or when iterating through the list. `comedi_driver_unregister()` also checks for and detaches any devices using the driver. This is currently done before unlinking the driver from the list, but it makes more sense to unlink the driver from the list first to prevent `comedi_device_attach()` attempting to use it, so move the unlinking part to the start of the function. Also, in `comedi_device_attach()` hold on to the mutex until we've finished attempting to attach the device to avoid it interfering with the detachment in `comedi_driver_unregister()`. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_internal.h | 1 + drivers/staging/comedi/drivers.c | 38 +++++++++++++++--------- drivers/staging/comedi/proc.c | 2 ++ 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/drivers/staging/comedi/comedi_internal.h b/drivers/staging/comedi/comedi_internal.h index d5e03e558b35..fda1a7ba0e16 100644 --- a/drivers/staging/comedi/comedi_internal.h +++ b/drivers/staging/comedi/comedi_internal.h @@ -24,6 +24,7 @@ extern unsigned int comedi_default_buf_maxsize_kb; /* drivers.c */ extern struct comedi_driver *comedi_drivers; +extern struct mutex comedi_drivers_list_lock; int insn_inval(struct comedi_device *, struct comedi_subdevice *, struct comedi_insn *, unsigned int *); diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index ba5d6d927a49..791a26bd5f63 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -38,6 +38,7 @@ #include "comedi_internal.h" struct comedi_driver *comedi_drivers; +DEFINE_MUTEX(comedi_drivers_list_lock); int comedi_set_hw_dev(struct comedi_device *dev, struct device *hw_dev) { @@ -453,6 +454,7 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (dev->attached) return -EBUSY; + mutex_lock(&comedi_drivers_list_lock); for (driv = comedi_drivers; driv; driv = driv->next) { if (!try_module_get(driv->module)) continue; @@ -473,7 +475,8 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it) comedi_report_boards(driv); module_put(driv->module); } - return -EIO; + ret = -EIO; + goto out; } if (driv->attach == NULL) { /* driver does not support manual configuration */ @@ -481,7 +484,8 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it) "driver '%s' does not support attach using comedi_config\n", driv->driver_name); module_put(driv->module); - return -ENOSYS; + ret = -ENOSYS; + goto out; } /* initialize dev->driver here so * comedi_error() can be called from attach */ @@ -496,6 +500,8 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it) module_put(dev->driver->module); } /* On success, the driver module count has been incremented. */ +out: + mutex_unlock(&comedi_drivers_list_lock); return ret; } @@ -552,8 +558,10 @@ EXPORT_SYMBOL_GPL(comedi_auto_unconfig); int comedi_driver_register(struct comedi_driver *driver) { + mutex_lock(&comedi_drivers_list_lock); driver->next = comedi_drivers; comedi_drivers = driver; + mutex_unlock(&comedi_drivers_list_lock); return 0; } @@ -564,6 +572,20 @@ void comedi_driver_unregister(struct comedi_driver *driver) struct comedi_driver *prev; int i; + /* unlink the driver */ + mutex_lock(&comedi_drivers_list_lock); + if (comedi_drivers == driver) { + comedi_drivers = driver->next; + } else { + for (prev = comedi_drivers; prev->next; prev = prev->next) { + if (prev->next == driver) { + prev->next = driver->next; + break; + } + } + } + mutex_unlock(&comedi_drivers_list_lock); + /* check for devices using this driver */ for (i = 0; i < COMEDI_NUM_BOARD_MINORS; i++) { struct comedi_device *dev = comedi_dev_from_minor(i); @@ -581,17 +603,5 @@ void comedi_driver_unregister(struct comedi_driver *driver) } mutex_unlock(&dev->mutex); } - - if (comedi_drivers == driver) { - comedi_drivers = driver->next; - return; - } - - for (prev = comedi_drivers; prev->next; prev = prev->next) { - if (prev->next == driver) { - prev->next = driver->next; - return; - } - } } EXPORT_SYMBOL_GPL(comedi_driver_unregister); diff --git a/drivers/staging/comedi/proc.c b/drivers/staging/comedi/proc.c index 8ee94424bc8f..ade00035d3bb 100644 --- a/drivers/staging/comedi/proc.c +++ b/drivers/staging/comedi/proc.c @@ -55,6 +55,7 @@ static int comedi_read(struct seq_file *m, void *v) if (!devices_q) seq_puts(m, "no devices\n"); + mutex_lock(&comedi_drivers_list_lock); for (driv = comedi_drivers; driv; driv = driv->next) { seq_printf(m, "%s:\n", driv->driver_name); for (i = 0; i < driv->num_names; i++) @@ -65,6 +66,7 @@ static int comedi_read(struct seq_file *m, void *v) if (!driv->num_names) seq_printf(m, " %s\n", driv->driver_name); } + mutex_unlock(&comedi_drivers_list_lock); return 0; } From 725a70d8a68ef5368652c0c49631fefb361d62cf Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 28 Jun 2013 17:09:17 +0100 Subject: [PATCH 0370/3400] staging: comedi: ni_labpc: fix possible double-free of dma_buffer If `labpc_attach()` allocates memory for `devpriv->dma_buffer` but fails to request a DMA channel, it frees `devpriv->dma_buffer` but leaves the pointer set. Later, `labpc_detach()` frees `devpriv->dma_buffer` again, which means it has been freed twice in this case. Fix it by only setting `devpriv->dma_buffer` in `labpc_attach()` if the DMA channel was requested successfully. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_labpc.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index 3e95ac5402ca..4ff1ed0c8fa8 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -1712,13 +1712,15 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it) #ifdef CONFIG_ISA_DMA_API if (dev->irq && (dma_chan == 1 || dma_chan == 3)) { - devpriv->dma_buffer = kmalloc(dma_buffer_size, - GFP_KERNEL | GFP_DMA); - if (devpriv->dma_buffer) { + void *dma_buffer = kmalloc(dma_buffer_size, + GFP_KERNEL | GFP_DMA); + + if (dma_buffer) { ret = request_dma(dma_chan, dev->board_name); if (ret == 0) { unsigned long dma_flags; + devpriv->dma_buffer = dma_buffer; devpriv->dma_chan = dma_chan; devpriv->dma_addr = virt_to_bus(devpriv->dma_buffer); @@ -1728,7 +1730,7 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it) set_dma_mode(devpriv->dma_chan, DMA_MODE_READ); release_dma_lock(dma_flags); } else { - kfree(devpriv->dma_buffer); + kfree(dma_buffer); } } } From f12a34ca0b7f02f725965f39f9ccf5d5c339d3e0 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 28 Jun 2013 17:09:18 +0100 Subject: [PATCH 0371/3400] staging: comedi: ni_labpc: don't clear cmd3 bits explicitly in labpc_ai_cmd() `labpc_ai_cmd()` calls `labpc_cancel()` which already sets `devpriv->cmd3` to 0. Remove the lines from `labpc_ai_cmd()` that clear specific bits in `devpriv->cmd3` explicitly as they have no effect. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_labpc.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index 4ff1ed0c8fa8..65ab8f6c5b69 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -976,8 +976,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) release_dma_lock(irq_flags); /* enable board's dma */ devpriv->cmd3 |= (CMD3_DMAEN | CMD3_DMATCINTEN); - } else - devpriv->cmd3 &= ~(CMD3_DMAEN | CMD3_DMATCINTEN); + } #endif /* enable error interrupts */ @@ -985,8 +984,6 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* enable fifo not empty interrupt? */ if (xfer == fifo_not_empty_transfer) devpriv->cmd3 |= CMD3_FIFOINTEN; - else - devpriv->cmd3 &= ~CMD3_FIFOINTEN; devpriv->write_byte(devpriv->cmd3, dev->iobase + CMD3_REG); /* setup any external triggering/pacing (cmd4 register) */ From 9a6386623fc8a67f792b9df56acbd8758e1aa93d Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 28 Jun 2013 17:09:19 +0100 Subject: [PATCH 0372/3400] staging: comedi: ni_labpc_isadma: new module for ISA DMA support It's just an empty module at the moment, selected by COMEDI_NI_LABPC_ISA && ISA_DMA_API && VIRT_TO_BUS, but will be populated by later patches to migrate ISA DMA support for NI Lab-PC cards out of the "ni_labpc" module. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/Kconfig | 4 ++ drivers/staging/comedi/drivers/Makefile | 1 + drivers/staging/comedi/drivers/ni_labpc.c | 1 + .../staging/comedi/drivers/ni_labpc_isadma.c | 37 +++++++++++++++++++ .../staging/comedi/drivers/ni_labpc_isadma.h | 16 ++++++++ 5 files changed, 59 insertions(+) create mode 100644 drivers/staging/comedi/drivers/ni_labpc_isadma.c create mode 100644 drivers/staging/comedi/drivers/ni_labpc_isadma.h diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index b9dc94a8ea69..b6e8faa5d777 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -492,6 +492,7 @@ config COMEDI_NI_ATMIO16D config COMEDI_NI_LABPC_ISA tristate "NI Lab-PC and compatibles ISA support" select COMEDI_NI_LABPC + select COMEDI_NI_LABPC_ISADMA if ISA_DMA_API && VIRT_TO_BUS depends on VIRT_TO_BUS ---help--- Enable support for National Instruments Lab-PC and compatibles @@ -1272,6 +1273,9 @@ config COMEDI_NI_LABPC select COMEDI_8255 select COMEDI_FC +config COMEDI_NI_LABPC_ISADMA + tristate + config COMEDI_NI_TIO tristate diff --git a/drivers/staging/comedi/drivers/Makefile b/drivers/staging/comedi/drivers/Makefile index 643e5517cba4..94cbd2618fc8 100644 --- a/drivers/staging/comedi/drivers/Makefile +++ b/drivers/staging/comedi/drivers/Makefile @@ -132,6 +132,7 @@ obj-$(CONFIG_COMEDI_MITE) += mite.o obj-$(CONFIG_COMEDI_NI_TIO) += ni_tio.o obj-$(CONFIG_COMEDI_NI_TIOCMD) += ni_tiocmd.o obj-$(CONFIG_COMEDI_NI_LABPC) += ni_labpc.o +obj-$(CONFIG_COMEDI_NI_LABPC_ISADMA) += ni_labpc_isadma.o obj-$(CONFIG_COMEDI_8255) += 8255.o obj-$(CONFIG_COMEDI_AMPLC_DIO200) += amplc_dio200_common.o diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index 65ab8f6c5b69..d1d22a19f022 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -71,6 +71,7 @@ #include "8255.h" #include "comedi_fc.h" #include "ni_labpc.h" +#include "ni_labpc_isadma.h" /* * Register map (all registers are 8-bit) diff --git a/drivers/staging/comedi/drivers/ni_labpc_isadma.c b/drivers/staging/comedi/drivers/ni_labpc_isadma.c new file mode 100644 index 000000000000..586ea54b8d79 --- /dev/null +++ b/drivers/staging/comedi/drivers/ni_labpc_isadma.c @@ -0,0 +1,37 @@ +/* + * comedi/drivers/ni_labpc_isadma.c + * ISA DMA support for National Instruments Lab-PC series boards and + * compatibles. + * + * Extracted from ni_labpc.c: + * Copyright (C) 2001-2003 Frank Mori Hess + * + * 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. + */ + +#include + +#include "ni_labpc_isadma.h" + +static int __init ni_labpc_isadma_init_module(void) +{ + return 0; +} +module_init(ni_labpc_isadma_init_module); + +static void __exit ni_labpc_isadma_cleanup_module(void) +{ +} +module_exit(ni_labpc_isadma_cleanup_module); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi NI Lab-PC ISA DMA support"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/ni_labpc_isadma.h b/drivers/staging/comedi/drivers/ni_labpc_isadma.h new file mode 100644 index 000000000000..ac644f0d9fc9 --- /dev/null +++ b/drivers/staging/comedi/drivers/ni_labpc_isadma.h @@ -0,0 +1,16 @@ +/* + * ni_labpc ISA DMA support. +*/ + +#ifndef _NI_LABPC_ISADMA_H +#define _NI_LABPC_ISADMA_H + +#define NI_LABPC_HAVE_ISA_DMA IS_ENABLED(CONFIG_COMEDI_NI_LABPC_ISADMA) + +#if NI_LABPC_HAVE_ISA_DMA + +#else + +#endif + +#endif /* _NI_LABPC_ISADMA_H */ From 86aff4bb11eb721b9be40dcd51f7571fb00edcde Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 28 Jun 2013 17:09:20 +0100 Subject: [PATCH 0373/3400] staging: comedi: ni_labpc: migrate DMA channel init & free Migrate the code for requesting an ISA DMA channel and a DMA buffer, and the code for freeing them into two new functions in the "ni_labpc_isadma" module: `labpc_init_dma_chan()` and `labpc_free_dma_chan()`. Dummy inline functions are provided in "ni_labpc_isadma.h" if the "ni_labpc_isadma" module is not being built. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_labpc.c | 35 ++---------- .../staging/comedi/drivers/ni_labpc_isadma.c | 54 +++++++++++++++++++ .../staging/comedi/drivers/ni_labpc_isadma.h | 13 +++++ 3 files changed, 72 insertions(+), 30 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index d1d22a19f022..ab1773e1fbcc 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -1708,31 +1708,8 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; -#ifdef CONFIG_ISA_DMA_API - if (dev->irq && (dma_chan == 1 || dma_chan == 3)) { - void *dma_buffer = kmalloc(dma_buffer_size, - GFP_KERNEL | GFP_DMA); - - if (dma_buffer) { - ret = request_dma(dma_chan, dev->board_name); - if (ret == 0) { - unsigned long dma_flags; - - devpriv->dma_buffer = dma_buffer; - devpriv->dma_chan = dma_chan; - devpriv->dma_addr = - virt_to_bus(devpriv->dma_buffer); - - dma_flags = claim_dma_lock(); - disable_dma(devpriv->dma_chan); - set_dma_mode(devpriv->dma_chan, DMA_MODE_READ); - release_dma_lock(dma_flags); - } else { - kfree(dma_buffer); - } - } - } -#endif + if (dev->irq) + labpc_init_dma_chan(dev, dma_chan); return 0; } @@ -1741,11 +1718,9 @@ static void labpc_detach(struct comedi_device *dev) { struct labpc_private *devpriv = dev->private; - if (devpriv) { - kfree(devpriv->dma_buffer); - if (devpriv->dma_chan) - free_dma(devpriv->dma_chan); - } + if (devpriv) + labpc_free_dma_chan(dev); + comedi_legacy_detach(dev); } diff --git a/drivers/staging/comedi/drivers/ni_labpc_isadma.c b/drivers/staging/comedi/drivers/ni_labpc_isadma.c index 586ea54b8d79..e6c8437f573c 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_isadma.c +++ b/drivers/staging/comedi/drivers/ni_labpc_isadma.c @@ -18,9 +18,63 @@ */ #include +#include +#include "../comedidev.h" +#include + +#include "ni_labpc.h" #include "ni_labpc_isadma.h" +/* size in bytes of dma buffer */ +static const int dma_buffer_size = 0xff00; + +int labpc_init_dma_chan(struct comedi_device *dev, unsigned int dma_chan) +{ + struct labpc_private *devpriv = dev->private; + void *dma_buffer; + unsigned long dma_flags; + int ret; + + if (dma_chan != 1 && dma_chan != 3) + return -EINVAL; + + dma_buffer = kmalloc(dma_buffer_size, GFP_KERNEL | GFP_DMA); + if (!dma_buffer) + return -ENOMEM; + + ret = request_dma(dma_chan, dev->board_name); + if (ret) { + kfree(dma_buffer); + return ret; + } + + devpriv->dma_buffer = dma_buffer; + devpriv->dma_chan = dma_chan; + devpriv->dma_addr = virt_to_bus(devpriv->dma_buffer); + + dma_flags = claim_dma_lock(); + disable_dma(devpriv->dma_chan); + set_dma_mode(devpriv->dma_chan, DMA_MODE_READ); + release_dma_lock(dma_flags); + + return 0; +} +EXPORT_SYMBOL_GPL(labpc_init_dma_chan); + +void labpc_free_dma_chan(struct comedi_device *dev) +{ + struct labpc_private *devpriv = dev->private; + + kfree(devpriv->dma_buffer); + devpriv->dma_buffer = NULL; + if (devpriv->dma_chan) { + free_dma(devpriv->dma_chan); + devpriv->dma_chan = 0; + } +} +EXPORT_SYMBOL_GPL(labpc_free_dma_chan); + static int __init ni_labpc_isadma_init_module(void) { return 0; diff --git a/drivers/staging/comedi/drivers/ni_labpc_isadma.h b/drivers/staging/comedi/drivers/ni_labpc_isadma.h index ac644f0d9fc9..144f4bafdbd1 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_isadma.h +++ b/drivers/staging/comedi/drivers/ni_labpc_isadma.h @@ -9,8 +9,21 @@ #if NI_LABPC_HAVE_ISA_DMA +int labpc_init_dma_chan(struct comedi_device *dev, unsigned int dma_chan); +void labpc_free_dma_chan(struct comedi_device *dev); + #else +static inline int labpc_init_dma_chan(struct comedi_device *dev, + unsigned int dma_chan) +{ + return -ENOTSUPP; +} + +static inline void labpc_free_dma_chan(struct comedi_device *dev) +{ +} + #endif #endif /* _NI_LABPC_ISADMA_H */ From c6208c2f358056d77544024373e9d73dd899a384 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 28 Jun 2013 17:09:21 +0100 Subject: [PATCH 0374/3400] staging: comedi: ni_labpc_isadma: add labpc_have_dma_chan() Add a static inline function to "ni_labpc_isadma.h" to test if a DMA channel has been set-up, in which case `devpriv->dma_chan` will be non-zero (where `devpriv` point to the private data for the comedi device). If the "ni_labpc_isadma" module is not being built, don't bother checking `devpriv->dma_chan`; just return `false` as this may help the compiler to optimize out some unreachable code. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_labpc_isadma.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/staging/comedi/drivers/ni_labpc_isadma.h b/drivers/staging/comedi/drivers/ni_labpc_isadma.h index 144f4bafdbd1..3b022ea6b564 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_isadma.h +++ b/drivers/staging/comedi/drivers/ni_labpc_isadma.h @@ -9,11 +9,23 @@ #if NI_LABPC_HAVE_ISA_DMA +static inline bool labpc_have_dma_chan(struct comedi_device *dev) +{ + struct labpc_private *devpriv = dev->private; + + return (bool)devpriv->dma_chan; +} + int labpc_init_dma_chan(struct comedi_device *dev, unsigned int dma_chan); void labpc_free_dma_chan(struct comedi_device *dev); #else +static inline bool labpc_have_dma_chan(struct comedi_device *dev) +{ + return false; +} + static inline int labpc_init_dma_chan(struct comedi_device *dev, unsigned int dma_chan) { From 5c8a138e9d33df4960e3cb497c60723c7fbdacf9 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 28 Jun 2013 17:09:22 +0100 Subject: [PATCH 0375/3400] staging: comedi: ni_labpc: use labpc_have_dma_chan() Call the new static inline function `labpc_have_dma_chan()` from `labpc_ai_cmd()` to check if the ISA DMA channel has been initialized, tidying up the surrounding code and removing an `#ifdef`. If the "ni_labpc_isadma" module is not being built, `labpc_have_dma_chan()` doesn't bother checking the DMA channel and just returns `false`, allowing the compiler to optimize out a small amount of code. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_labpc.c | 29 ++++++++++------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index ab1773e1fbcc..1f0f7f538215 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -871,25 +871,20 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) return ret; } -#ifdef CONFIG_ISA_DMA_API - /* figure out what method we will use to transfer data */ - if (devpriv->dma_chan && /* need a dma channel allocated */ - /* - * dma unsafe at RT priority, - * and too much setup time for TRIG_WAKE_EOS for - */ - (cmd->flags & (TRIG_WAKE_EOS | TRIG_RT)) == 0) { + /* figure out what method we will use to transfer data */ + if (labpc_have_dma_chan(dev) && + /* dma unsafe at RT priority, + * and too much setup time for TRIG_WAKE_EOS */ + (cmd->flags & (TRIG_WAKE_EOS | TRIG_RT)) == 0) xfer = isa_dma_transfer; - /* pc-plus has no fifo-half full interrupt */ - } else -#endif - if (board->is_labpc1200 && - /* wake-end-of-scan should interrupt on fifo not empty */ - (cmd->flags & TRIG_WAKE_EOS) == 0 && - /* make sure we are taking more than just a few points */ - (cmd->stop_src != TRIG_COUNT || devpriv->count > 256)) { + else if (/* pc-plus has no fifo-half full interrupt */ + board->is_labpc1200 && + /* wake-end-of-scan should interrupt on fifo not empty */ + (cmd->flags & TRIG_WAKE_EOS) == 0 && + /* make sure we are taking more than just a few points */ + (cmd->stop_src != TRIG_COUNT || devpriv->count > 256)) xfer = fifo_half_full_transfer; - } else + else xfer = fifo_not_empty_transfer; devpriv->current_transfer = xfer; From 50787fa99d80e86c9a22b7af16fd9827f733f3ab Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 28 Jun 2013 17:09:23 +0100 Subject: [PATCH 0376/3400] staging: comedi: ni_labpc: move register defs to new file The new "ni_labpc_isadma" module will need to access some register definitions from "ni_labpc.c", which is not part of the module's source. Move all the register definitions into a new, common header file "ni_labpc_regs.h". Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_labpc.c | 68 +---------------- .../staging/comedi/drivers/ni_labpc_isadma.c | 1 + .../staging/comedi/drivers/ni_labpc_regs.h | 75 +++++++++++++++++++ 3 files changed, 77 insertions(+), 67 deletions(-) create mode 100644 drivers/staging/comedi/drivers/ni_labpc_regs.h diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index 1f0f7f538215..dd858d58a93e 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -71,75 +71,9 @@ #include "8255.h" #include "comedi_fc.h" #include "ni_labpc.h" +#include "ni_labpc_regs.h" #include "ni_labpc_isadma.h" -/* - * Register map (all registers are 8-bit) - */ -#define STAT1_REG 0x00 /* R: Status 1 reg */ -#define STAT1_DAVAIL (1 << 0) -#define STAT1_OVERRUN (1 << 1) -#define STAT1_OVERFLOW (1 << 2) -#define STAT1_CNTINT (1 << 3) -#define STAT1_GATA0 (1 << 5) -#define STAT1_EXTGATA0 (1 << 6) -#define CMD1_REG 0x00 /* W: Command 1 reg */ -#define CMD1_MA(x) (((x) & 0x7) << 0) -#define CMD1_TWOSCMP (1 << 3) -#define CMD1_GAIN(x) (((x) & 0x7) << 4) -#define CMD1_SCANEN (1 << 7) -#define CMD2_REG 0x01 /* W: Command 2 reg */ -#define CMD2_PRETRIG (1 << 0) -#define CMD2_HWTRIG (1 << 1) -#define CMD2_SWTRIG (1 << 2) -#define CMD2_TBSEL (1 << 3) -#define CMD2_2SDAC0 (1 << 4) -#define CMD2_2SDAC1 (1 << 5) -#define CMD2_LDAC(x) (1 << (6 + (x))) -#define CMD3_REG 0x02 /* W: Command 3 reg */ -#define CMD3_DMAEN (1 << 0) -#define CMD3_DIOINTEN (1 << 1) -#define CMD3_DMATCINTEN (1 << 2) -#define CMD3_CNTINTEN (1 << 3) -#define CMD3_ERRINTEN (1 << 4) -#define CMD3_FIFOINTEN (1 << 5) -#define ADC_START_CONVERT_REG 0x03 /* W: Start Convert reg */ -#define DAC_LSB_REG(x) (0x04 + 2 * (x)) /* W: DAC0/1 LSB reg */ -#define DAC_MSB_REG(x) (0x05 + 2 * (x)) /* W: DAC0/1 MSB reg */ -#define ADC_FIFO_CLEAR_REG 0x08 /* W: A/D FIFO Clear reg */ -#define ADC_FIFO_REG 0x0a /* R: A/D FIFO reg */ -#define DMATC_CLEAR_REG 0x0a /* W: DMA Interrupt Clear reg */ -#define TIMER_CLEAR_REG 0x0c /* W: Timer Interrupt Clear reg */ -#define CMD6_REG 0x0e /* W: Command 6 reg */ -#define CMD6_NRSE (1 << 0) -#define CMD6_ADCUNI (1 << 1) -#define CMD6_DACUNI(x) (1 << (2 + (x))) -#define CMD6_HFINTEN (1 << 5) -#define CMD6_DQINTEN (1 << 6) -#define CMD6_SCANUP (1 << 7) -#define CMD4_REG 0x0f /* W: Command 3 reg */ -#define CMD4_INTSCAN (1 << 0) -#define CMD4_EOIRCV (1 << 1) -#define CMD4_ECLKDRV (1 << 2) -#define CMD4_SEDIFF (1 << 3) -#define CMD4_ECLKRCV (1 << 4) -#define DIO_BASE_REG 0x10 /* R/W: 8255 DIO base reg */ -#define COUNTER_A_BASE_REG 0x14 /* R/W: 8253 Counter A base reg */ -#define COUNTER_B_BASE_REG 0x18 /* R/W: 8253 Counter B base reg */ -#define CMD5_REG 0x1c /* W: Command 5 reg */ -#define CMD5_WRTPRT (1 << 2) -#define CMD5_DITHEREN (1 << 3) -#define CMD5_CALDACLD (1 << 4) -#define CMD5_SCLK (1 << 5) -#define CMD5_SDATA (1 << 6) -#define CMD5_EEPROMCS (1 << 7) -#define STAT2_REG 0x1d /* R: Status 2 reg */ -#define STAT2_PROMOUT (1 << 0) -#define STAT2_OUTA1 (1 << 1) -#define STAT2_FIFONHF (1 << 2) -#define INTERVAL_COUNT_REG 0x1e /* W: Interval Counter Data reg */ -#define INTERVAL_STROBE_REG 0x1f /* W: Interval Counter Strobe reg */ - #define LABPC_SIZE 0x20 /* size of ISA io region */ #define LABPC_TIMER_BASE 500 /* 2 MHz master clock */ #define LABPC_ADC_TIMEOUT 1000 diff --git a/drivers/staging/comedi/drivers/ni_labpc_isadma.c b/drivers/staging/comedi/drivers/ni_labpc_isadma.c index e6c8437f573c..a05297421bd1 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_isadma.c +++ b/drivers/staging/comedi/drivers/ni_labpc_isadma.c @@ -24,6 +24,7 @@ #include #include "ni_labpc.h" +#include "ni_labpc_regs.h" #include "ni_labpc_isadma.h" /* size in bytes of dma buffer */ diff --git a/drivers/staging/comedi/drivers/ni_labpc_regs.h b/drivers/staging/comedi/drivers/ni_labpc_regs.h new file mode 100644 index 000000000000..2a274a3e4e73 --- /dev/null +++ b/drivers/staging/comedi/drivers/ni_labpc_regs.h @@ -0,0 +1,75 @@ +/* + * ni_labpc register definitions. +*/ + +#ifndef _NI_LABPC_REGS_H +#define _NI_LABPC_REGS_H + +/* + * Register map (all registers are 8-bit) + */ +#define STAT1_REG 0x00 /* R: Status 1 reg */ +#define STAT1_DAVAIL (1 << 0) +#define STAT1_OVERRUN (1 << 1) +#define STAT1_OVERFLOW (1 << 2) +#define STAT1_CNTINT (1 << 3) +#define STAT1_GATA0 (1 << 5) +#define STAT1_EXTGATA0 (1 << 6) +#define CMD1_REG 0x00 /* W: Command 1 reg */ +#define CMD1_MA(x) (((x) & 0x7) << 0) +#define CMD1_TWOSCMP (1 << 3) +#define CMD1_GAIN(x) (((x) & 0x7) << 4) +#define CMD1_SCANEN (1 << 7) +#define CMD2_REG 0x01 /* W: Command 2 reg */ +#define CMD2_PRETRIG (1 << 0) +#define CMD2_HWTRIG (1 << 1) +#define CMD2_SWTRIG (1 << 2) +#define CMD2_TBSEL (1 << 3) +#define CMD2_2SDAC0 (1 << 4) +#define CMD2_2SDAC1 (1 << 5) +#define CMD2_LDAC(x) (1 << (6 + (x))) +#define CMD3_REG 0x02 /* W: Command 3 reg */ +#define CMD3_DMAEN (1 << 0) +#define CMD3_DIOINTEN (1 << 1) +#define CMD3_DMATCINTEN (1 << 2) +#define CMD3_CNTINTEN (1 << 3) +#define CMD3_ERRINTEN (1 << 4) +#define CMD3_FIFOINTEN (1 << 5) +#define ADC_START_CONVERT_REG 0x03 /* W: Start Convert reg */ +#define DAC_LSB_REG(x) (0x04 + 2 * (x)) /* W: DAC0/1 LSB reg */ +#define DAC_MSB_REG(x) (0x05 + 2 * (x)) /* W: DAC0/1 MSB reg */ +#define ADC_FIFO_CLEAR_REG 0x08 /* W: A/D FIFO Clear reg */ +#define ADC_FIFO_REG 0x0a /* R: A/D FIFO reg */ +#define DMATC_CLEAR_REG 0x0a /* W: DMA Interrupt Clear reg */ +#define TIMER_CLEAR_REG 0x0c /* W: Timer Interrupt Clear reg */ +#define CMD6_REG 0x0e /* W: Command 6 reg */ +#define CMD6_NRSE (1 << 0) +#define CMD6_ADCUNI (1 << 1) +#define CMD6_DACUNI(x) (1 << (2 + (x))) +#define CMD6_HFINTEN (1 << 5) +#define CMD6_DQINTEN (1 << 6) +#define CMD6_SCANUP (1 << 7) +#define CMD4_REG 0x0f /* W: Command 3 reg */ +#define CMD4_INTSCAN (1 << 0) +#define CMD4_EOIRCV (1 << 1) +#define CMD4_ECLKDRV (1 << 2) +#define CMD4_SEDIFF (1 << 3) +#define CMD4_ECLKRCV (1 << 4) +#define DIO_BASE_REG 0x10 /* R/W: 8255 DIO base reg */ +#define COUNTER_A_BASE_REG 0x14 /* R/W: 8253 Counter A base reg */ +#define COUNTER_B_BASE_REG 0x18 /* R/W: 8253 Counter B base reg */ +#define CMD5_REG 0x1c /* W: Command 5 reg */ +#define CMD5_WRTPRT (1 << 2) +#define CMD5_DITHEREN (1 << 3) +#define CMD5_CALDACLD (1 << 4) +#define CMD5_SCLK (1 << 5) +#define CMD5_SDATA (1 << 6) +#define CMD5_EEPROMCS (1 << 7) +#define STAT2_REG 0x1d /* R: Status 2 reg */ +#define STAT2_PROMOUT (1 << 0) +#define STAT2_OUTA1 (1 << 1) +#define STAT2_FIFONHF (1 << 2) +#define INTERVAL_COUNT_REG 0x1e /* W: Interval Counter Data reg */ +#define INTERVAL_STROBE_REG 0x1f /* W: Interval Counter Strobe reg */ + +#endif /* _NI_LABPC_REGS_H */ From 88dd0c0a8016d6d80ed47eb306c5b41e8af0f83a Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 28 Jun 2013 17:09:24 +0100 Subject: [PATCH 0377/3400] staging: comedi: ni_labpc: migrate DMA transfer set-up Migrate the code for setting up an ISA DMA transfer into a new function `labpc_setup_dma()` in the "ni_labpc_isadma" module. Provide a dummy inline function in "ni_labpc_isadma.h" if the "ni_labpc_isadma" module is not being built. The static function `labpc_suggest_transfer_size()` also needs to move across to the new module. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_labpc.c | 53 +------------------ .../staging/comedi/drivers/ni_labpc_isadma.c | 51 ++++++++++++++++++ .../staging/comedi/drivers/ni_labpc_isadma.h | 6 +++ 3 files changed, 59 insertions(+), 51 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index dd858d58a93e..e1b073f746fe 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -387,32 +387,6 @@ static int labpc_ai_insn_read(struct comedi_device *dev, return insn->n; } -#ifdef CONFIG_ISA_DMA_API -/* utility function that suggests a dma transfer size in bytes */ -static unsigned int labpc_suggest_transfer_size(const struct comedi_cmd *cmd) -{ - unsigned int size; - unsigned int freq; - - if (cmd->convert_src == TRIG_TIMER) - freq = 1000000000 / cmd->convert_arg; - /* return some default value */ - else - freq = 0xffffffff; - - /* make buffer fill in no more than 1/3 second */ - size = (freq / 3) * sample_size; - - /* set a minimum and maximum size allowed */ - if (size > dma_buffer_size) - size = dma_buffer_size - dma_buffer_size % sample_size; - else if (size < sample_size) - size = sample_size; - - return size; -} -#endif - static bool labpc_use_continuous_mode(const struct comedi_cmd *cmd, enum scan_mode mode) { @@ -883,31 +857,8 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) labpc_clear_adc_fifo(dev); -#ifdef CONFIG_ISA_DMA_API - /* set up dma transfer */ - if (xfer == isa_dma_transfer) { - unsigned long irq_flags; - - irq_flags = claim_dma_lock(); - disable_dma(devpriv->dma_chan); - /* clear flip-flop to make sure 2-byte registers for - * count and address get set correctly */ - clear_dma_ff(devpriv->dma_chan); - set_dma_addr(devpriv->dma_chan, devpriv->dma_addr); - /* set appropriate size of transfer */ - devpriv->dma_transfer_size = labpc_suggest_transfer_size(cmd); - if (cmd->stop_src == TRIG_COUNT && - devpriv->count * sample_size < devpriv->dma_transfer_size) { - devpriv->dma_transfer_size = - devpriv->count * sample_size; - } - set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size); - enable_dma(devpriv->dma_chan); - release_dma_lock(irq_flags); - /* enable board's dma */ - devpriv->cmd3 |= (CMD3_DMAEN | CMD3_DMATCINTEN); - } -#endif + if (xfer == isa_dma_transfer) + labpc_setup_dma(dev, s); /* enable error interrupts */ devpriv->cmd3 |= CMD3_ERRINTEN; diff --git a/drivers/staging/comedi/drivers/ni_labpc_isadma.c b/drivers/staging/comedi/drivers/ni_labpc_isadma.c index a05297421bd1..dba2be36c48d 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_isadma.c +++ b/drivers/staging/comedi/drivers/ni_labpc_isadma.c @@ -29,6 +29,57 @@ /* size in bytes of dma buffer */ static const int dma_buffer_size = 0xff00; +/* 2 bytes per sample */ +static const int sample_size = 2; + +/* utility function that suggests a dma transfer size in bytes */ +static unsigned int labpc_suggest_transfer_size(const struct comedi_cmd *cmd) +{ + unsigned int size; + unsigned int freq; + + if (cmd->convert_src == TRIG_TIMER) + freq = 1000000000 / cmd->convert_arg; + else + /* return some default value */ + freq = 0xffffffff; + + /* make buffer fill in no more than 1/3 second */ + size = (freq / 3) * sample_size; + + /* set a minimum and maximum size allowed */ + if (size > dma_buffer_size) + size = dma_buffer_size - dma_buffer_size % sample_size; + else if (size < sample_size) + size = sample_size; + + return size; +} + +void labpc_setup_dma(struct comedi_device *dev, struct comedi_subdevice *s) +{ + struct labpc_private *devpriv = dev->private; + struct comedi_cmd *cmd = &s->async->cmd; + unsigned long irq_flags; + + irq_flags = claim_dma_lock(); + disable_dma(devpriv->dma_chan); + /* clear flip-flop to make sure 2-byte registers for + * count and address get set correctly */ + clear_dma_ff(devpriv->dma_chan); + set_dma_addr(devpriv->dma_chan, devpriv->dma_addr); + /* set appropriate size of transfer */ + devpriv->dma_transfer_size = labpc_suggest_transfer_size(cmd); + if (cmd->stop_src == TRIG_COUNT && + devpriv->count * sample_size < devpriv->dma_transfer_size) + devpriv->dma_transfer_size = devpriv->count * sample_size; + set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size); + enable_dma(devpriv->dma_chan); + release_dma_lock(irq_flags); + /* set CMD3 bits for caller to enable DMA and interrupt */ + devpriv->cmd3 |= (CMD3_DMAEN | CMD3_DMATCINTEN); +} +EXPORT_SYMBOL_GPL(labpc_setup_dma); int labpc_init_dma_chan(struct comedi_device *dev, unsigned int dma_chan) { diff --git a/drivers/staging/comedi/drivers/ni_labpc_isadma.h b/drivers/staging/comedi/drivers/ni_labpc_isadma.h index 3b022ea6b564..c721f57daf0c 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_isadma.h +++ b/drivers/staging/comedi/drivers/ni_labpc_isadma.h @@ -18,6 +18,7 @@ static inline bool labpc_have_dma_chan(struct comedi_device *dev) int labpc_init_dma_chan(struct comedi_device *dev, unsigned int dma_chan); void labpc_free_dma_chan(struct comedi_device *dev); +void labpc_setup_dma(struct comedi_device *dev, struct comedi_subdevice *s); #else @@ -36,6 +37,11 @@ static inline void labpc_free_dma_chan(struct comedi_device *dev) { } +static inline void labpc_setup_dma(struct comedi_device *dev, + struct comedi_subdevice *s) +{ +} + #endif #endif /* _NI_LABPC_ISADMA_H */ From f88e8e09880d4abe3cad98ec8889e0f46eb89e4d Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 28 Jun 2013 17:09:25 +0100 Subject: [PATCH 0378/3400] staging: comedi: ni_labpc: migrate labpc_drain_dma() Move `labpc_drain_dma()` into the "ni_labpc_isadma" module. Provide a dummy inline function in "ni_labpc_isadma.h" if the module is not being built. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_labpc.c | 56 ------------------- .../staging/comedi/drivers/ni_labpc_isadma.c | 56 +++++++++++++++++++ .../staging/comedi/drivers/ni_labpc_isadma.h | 5 ++ 3 files changed, 61 insertions(+), 56 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index e1b073f746fe..818a8abe208c 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -906,60 +906,6 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) } #ifdef CONFIG_ISA_DMA_API -static void labpc_drain_dma(struct comedi_device *dev) -{ - struct labpc_private *devpriv = dev->private; - struct comedi_subdevice *s = dev->read_subdev; - struct comedi_async *async = s->async; - int status; - unsigned long flags; - unsigned int max_points, num_points, residue, leftover; - int i; - - status = devpriv->stat1; - - flags = claim_dma_lock(); - disable_dma(devpriv->dma_chan); - /* clear flip-flop to make sure 2-byte registers for - * count and address get set correctly */ - clear_dma_ff(devpriv->dma_chan); - - /* figure out how many points to read */ - max_points = devpriv->dma_transfer_size / sample_size; - /* residue is the number of points left to be done on the dma - * transfer. It should always be zero at this point unless - * the stop_src is set to external triggering. - */ - residue = get_dma_residue(devpriv->dma_chan) / sample_size; - num_points = max_points - residue; - if (devpriv->count < num_points && async->cmd.stop_src == TRIG_COUNT) - num_points = devpriv->count; - - /* figure out how many points will be stored next time */ - leftover = 0; - if (async->cmd.stop_src != TRIG_COUNT) { - leftover = devpriv->dma_transfer_size / sample_size; - } else if (devpriv->count > num_points) { - leftover = devpriv->count - num_points; - if (leftover > max_points) - leftover = max_points; - } - - /* write data to comedi buffer */ - for (i = 0; i < num_points; i++) - cfc_write_to_buffer(s, devpriv->dma_buffer[i]); - - if (async->cmd.stop_src == TRIG_COUNT) - devpriv->count -= num_points; - - /* set address and count for next transfer */ - set_dma_addr(devpriv->dma_chan, devpriv->dma_addr); - set_dma_count(devpriv->dma_chan, leftover * sample_size); - release_dma_lock(flags); - - async->events |= COMEDI_CB_BLOCK; -} - static void handle_isa_dma(struct comedi_device *dev) { struct labpc_private *devpriv = dev->private; @@ -1009,12 +955,10 @@ static int labpc_drain_fifo(struct comedi_device *dev) * when acquisition is terminated by stop_src == TRIG_EXT). */ static void labpc_drain_dregs(struct comedi_device *dev) { -#ifdef CONFIG_ISA_DMA_API struct labpc_private *devpriv = dev->private; if (devpriv->current_transfer == isa_dma_transfer) labpc_drain_dma(dev); -#endif labpc_drain_fifo(dev); } diff --git a/drivers/staging/comedi/drivers/ni_labpc_isadma.c b/drivers/staging/comedi/drivers/ni_labpc_isadma.c index dba2be36c48d..c4bfecc07b63 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_isadma.c +++ b/drivers/staging/comedi/drivers/ni_labpc_isadma.c @@ -23,6 +23,7 @@ #include +#include "comedi_fc.h" #include "ni_labpc.h" #include "ni_labpc_regs.h" #include "ni_labpc_isadma.h" @@ -81,6 +82,61 @@ void labpc_setup_dma(struct comedi_device *dev, struct comedi_subdevice *s) } EXPORT_SYMBOL_GPL(labpc_setup_dma); +void labpc_drain_dma(struct comedi_device *dev) +{ + struct labpc_private *devpriv = dev->private; + struct comedi_subdevice *s = dev->read_subdev; + struct comedi_async *async = s->async; + int status; + unsigned long flags; + unsigned int max_points, num_points, residue, leftover; + int i; + + status = devpriv->stat1; + + flags = claim_dma_lock(); + disable_dma(devpriv->dma_chan); + /* clear flip-flop to make sure 2-byte registers for + * count and address get set correctly */ + clear_dma_ff(devpriv->dma_chan); + + /* figure out how many points to read */ + max_points = devpriv->dma_transfer_size / sample_size; + /* residue is the number of points left to be done on the dma + * transfer. It should always be zero at this point unless + * the stop_src is set to external triggering. + */ + residue = get_dma_residue(devpriv->dma_chan) / sample_size; + num_points = max_points - residue; + if (devpriv->count < num_points && async->cmd.stop_src == TRIG_COUNT) + num_points = devpriv->count; + + /* figure out how many points will be stored next time */ + leftover = 0; + if (async->cmd.stop_src != TRIG_COUNT) { + leftover = devpriv->dma_transfer_size / sample_size; + } else if (devpriv->count > num_points) { + leftover = devpriv->count - num_points; + if (leftover > max_points) + leftover = max_points; + } + + /* write data to comedi buffer */ + for (i = 0; i < num_points; i++) + cfc_write_to_buffer(s, devpriv->dma_buffer[i]); + + if (async->cmd.stop_src == TRIG_COUNT) + devpriv->count -= num_points; + + /* set address and count for next transfer */ + set_dma_addr(devpriv->dma_chan, devpriv->dma_addr); + set_dma_count(devpriv->dma_chan, leftover * sample_size); + release_dma_lock(flags); + + async->events |= COMEDI_CB_BLOCK; +} +EXPORT_SYMBOL_GPL(labpc_drain_dma); + int labpc_init_dma_chan(struct comedi_device *dev, unsigned int dma_chan) { struct labpc_private *devpriv = dev->private; diff --git a/drivers/staging/comedi/drivers/ni_labpc_isadma.h b/drivers/staging/comedi/drivers/ni_labpc_isadma.h index c721f57daf0c..1f322f2bc2d9 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_isadma.h +++ b/drivers/staging/comedi/drivers/ni_labpc_isadma.h @@ -19,6 +19,7 @@ static inline bool labpc_have_dma_chan(struct comedi_device *dev) int labpc_init_dma_chan(struct comedi_device *dev, unsigned int dma_chan); void labpc_free_dma_chan(struct comedi_device *dev); void labpc_setup_dma(struct comedi_device *dev, struct comedi_subdevice *s); +void labpc_drain_dma(struct comedi_device *dev); #else @@ -42,6 +43,10 @@ static inline void labpc_setup_dma(struct comedi_device *dev, { } +static inline void labpc_drain_dma(struct comedi_device *dev) +{ +} + #endif #endif /* _NI_LABPC_ISADMA_H */ From 9bd53e0398f490707549455c00475af4923df872 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 28 Jun 2013 17:09:26 +0100 Subject: [PATCH 0379/3400] staging: comedi: ni_labpc: migrate DMA status handling Migrate the code for checking and handling the interrupt status handling for ISA DMA transfers into new a new function `labpc_handle_dma_status()` in the "ni_labpc_isadma" module. Provide a dummy inline function in "ni_labpc_isadma.h" if the "ni_labpc_isadma" module is not being built. The static function `handle_isa_dma()` also needs to move across to the new module. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_labpc.c | 29 ++----------------- .../staging/comedi/drivers/ni_labpc_isadma.c | 27 +++++++++++++++++ .../staging/comedi/drivers/ni_labpc_isadma.h | 5 ++++ 3 files changed, 35 insertions(+), 26 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index 818a8abe208c..57985a24dda4 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -905,20 +905,6 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) return 0; } -#ifdef CONFIG_ISA_DMA_API -static void handle_isa_dma(struct comedi_device *dev) -{ - struct labpc_private *devpriv = dev->private; - - labpc_drain_dma(dev); - - enable_dma(devpriv->dma_chan); - - /* clear dma tc interrupt */ - devpriv->write_byte(0x1, dev->iobase + DMATC_CLEAR_REG); -} -#endif - /* read all available samples from ai fifo */ static int labpc_drain_fifo(struct comedi_device *dev) { @@ -1003,18 +989,9 @@ static irqreturn_t labpc_interrupt(int irq, void *d) return IRQ_HANDLED; } -#ifdef CONFIG_ISA_DMA_API - if (devpriv->current_transfer == isa_dma_transfer) { - /* - * if a dma terminal count of external stop trigger - * has occurred - */ - if (devpriv->stat1 & STAT1_GATA0 || - (board->is_labpc1200 && devpriv->stat2 & STAT2_OUTA1)) { - handle_isa_dma(dev); - } - } else -#endif + if (devpriv->current_transfer == isa_dma_transfer) + labpc_handle_dma_status(dev); + else labpc_drain_fifo(dev); if (devpriv->stat1 & STAT1_CNTINT) { diff --git a/drivers/staging/comedi/drivers/ni_labpc_isadma.c b/drivers/staging/comedi/drivers/ni_labpc_isadma.c index c4bfecc07b63..2149596830af 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_isadma.c +++ b/drivers/staging/comedi/drivers/ni_labpc_isadma.c @@ -137,6 +137,33 @@ void labpc_drain_dma(struct comedi_device *dev) } EXPORT_SYMBOL_GPL(labpc_drain_dma); +static void handle_isa_dma(struct comedi_device *dev) +{ + struct labpc_private *devpriv = dev->private; + + labpc_drain_dma(dev); + + enable_dma(devpriv->dma_chan); + + /* clear dma tc interrupt */ + devpriv->write_byte(0x1, dev->iobase + DMATC_CLEAR_REG); +} + +void labpc_handle_dma_status(struct comedi_device *dev) +{ + const struct labpc_boardinfo *board = comedi_board(dev); + struct labpc_private *devpriv = dev->private; + + /* + * if a dma terminal count of external stop trigger + * has occurred + */ + if (devpriv->stat1 & STAT1_GATA0 || + (board->is_labpc1200 && devpriv->stat2 & STAT2_OUTA1)) + handle_isa_dma(dev); +} +EXPORT_SYMBOL_GPL(labpc_handle_dma_status); + int labpc_init_dma_chan(struct comedi_device *dev, unsigned int dma_chan) { struct labpc_private *devpriv = dev->private; diff --git a/drivers/staging/comedi/drivers/ni_labpc_isadma.h b/drivers/staging/comedi/drivers/ni_labpc_isadma.h index 1f322f2bc2d9..771af4bd5a76 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_isadma.h +++ b/drivers/staging/comedi/drivers/ni_labpc_isadma.h @@ -20,6 +20,7 @@ int labpc_init_dma_chan(struct comedi_device *dev, unsigned int dma_chan); void labpc_free_dma_chan(struct comedi_device *dev); void labpc_setup_dma(struct comedi_device *dev, struct comedi_subdevice *s); void labpc_drain_dma(struct comedi_device *dev); +void labpc_handle_dma_status(struct comedi_device *dev); #else @@ -47,6 +48,10 @@ static inline void labpc_drain_dma(struct comedi_device *dev) { } +static inline void labpc_handle_dma_status(struct comedi_device *dev) +{ +} + #endif #endif /* _NI_LABPC_ISADMA_H */ From 72f2baeb75ba2e6e3ffbfb64890438f576f1d931 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 28 Jun 2013 17:09:27 +0100 Subject: [PATCH 0380/3400] staging: comedi: ni_labpc: tidy up after DMA code migration After migrating the ISA DMA handling code to the "ni_labpc_isadma" module, get rid of an unneeded `#include` and a couple of unused static variables. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_labpc.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index 57985a24dda4..1add114dc0bc 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -65,8 +65,6 @@ #include "../comedidev.h" -#include - #include "8253.h" #include "8255.h" #include "comedi_fc.h" @@ -175,11 +173,6 @@ static const struct labpc_boardinfo labpc_boards[] = { }; #endif -/* size in bytes of dma buffer */ -static const int dma_buffer_size = 0xff00; -/* 2 bytes per sample */ -static const int sample_size = 2; - static int labpc_counter_load(struct comedi_device *dev, unsigned long base_address, unsigned int counter_number, From 277bef860c1bdb631c4cae385838bddd65459c07 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 28 Jun 2013 17:09:28 +0100 Subject: [PATCH 0381/3400] staging: comedi: COMEDI_NI_LABPC_ISA no longer depends on VIRT_TO_BUS After migrating ISA DMA support from the "ni_labpc" module to the new "ni_labpc_isadma" module, the `COMEDI_NI_LABPC_ISA` configuration option no longer depends on `VIRT_TO_BUS`, so remove the dependency. (The new `COMEDI_NI_LABPC_ISADMA` option does depend on `VIRT_TO_BUS` but is not configured manually and is only selected automatically if the `VIRT_TO_BUS` and `ISA_DMA_API` options are set.) Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index b6e8faa5d777..01782fccbf2a 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -493,7 +493,6 @@ config COMEDI_NI_LABPC_ISA tristate "NI Lab-PC and compatibles ISA support" select COMEDI_NI_LABPC select COMEDI_NI_LABPC_ISADMA if ISA_DMA_API && VIRT_TO_BUS - depends on VIRT_TO_BUS ---help--- Enable support for National Instruments Lab-PC and compatibles Lab-PC-1200, Lab-PC-1200AI, Lab-PC+. From 30f1e5a9abd5ea83a19e8efd71089d4204e21bd4 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 23 Jul 2013 13:44:59 +0100 Subject: [PATCH 0382/3400] staging: ozwpan: Remove extra debug logs. Remove unnecessary debug logs. Most of these logs print function name at the start of function, which are not really required. Signed-off-by: Joe Perches Signed-off-by: Rupesh Gujare Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ozwpan/ozcdev.c | 2 -- drivers/staging/ozwpan/ozhcd.c | 28 ++++++++-------------------- 2 files changed, 8 insertions(+), 22 deletions(-) diff --git a/drivers/staging/ozwpan/ozcdev.c b/drivers/staging/ozwpan/ozcdev.c index 374fdc398641..284c26da27be 100644 --- a/drivers/staging/ozwpan/ozcdev.c +++ b/drivers/staging/ozwpan/ozcdev.c @@ -73,7 +73,6 @@ static void oz_cdev_release_ctx(struct oz_serial_ctx *ctx) static int oz_cdev_open(struct inode *inode, struct file *filp) { struct oz_cdev *dev; - oz_trace("oz_cdev_open()\n"); oz_trace("major = %d minor = %d\n", imajor(inode), iminor(inode)); dev = container_of(inode->i_cdev, struct oz_cdev, cdev); filp->private_data = dev; @@ -84,7 +83,6 @@ static int oz_cdev_open(struct inode *inode, struct file *filp) */ static int oz_cdev_release(struct inode *inode, struct file *filp) { - oz_trace("oz_cdev_release()\n"); return 0; } /*------------------------------------------------------------------------------ diff --git a/drivers/staging/ozwpan/ozhcd.c b/drivers/staging/ozwpan/ozhcd.c index d68d63a2e683..9d1bd4450b8e 100644 --- a/drivers/staging/ozwpan/ozhcd.c +++ b/drivers/staging/ozwpan/ozhcd.c @@ -394,7 +394,6 @@ static void oz_complete_urb(struct usb_hcd *hcd, struct urb *urb, */ static void oz_ep_free(struct oz_port *port, struct oz_endpoint *ep) { - oz_trace("oz_ep_free()\n"); if (port) { struct list_head list; struct oz_hcd *ozhcd = port->ozhcd; @@ -631,7 +630,6 @@ void *oz_hcd_pd_arrived(void *hpd) void *hport = NULL; struct oz_hcd *ozhcd = NULL; struct oz_endpoint *ep; - oz_trace("oz_hcd_pd_arrived()\n"); ozhcd = oz_hcd_claim(); if (ozhcd == NULL) return NULL; @@ -691,7 +689,6 @@ void oz_hcd_pd_departed(void *hport) void *hpd; struct oz_endpoint *ep = NULL; - oz_trace("oz_hcd_pd_departed()\n"); if (port == NULL) { oz_trace("oz_hcd_pd_departed() port = 0\n"); return; @@ -1696,7 +1693,6 @@ static void oz_hcd_clear_orphanage(struct oz_hcd *ozhcd, int status) */ static int oz_hcd_start(struct usb_hcd *hcd) { - oz_trace("oz_hcd_start()\n"); hcd->power_budget = 200; hcd->state = HC_STATE_RUNNING; hcd->uses_new_polling = 1; @@ -1707,14 +1703,12 @@ static int oz_hcd_start(struct usb_hcd *hcd) */ static void oz_hcd_stop(struct usb_hcd *hcd) { - oz_trace("oz_hcd_stop()\n"); } /*------------------------------------------------------------------------------ * Context: unknown */ static void oz_hcd_shutdown(struct usb_hcd *hcd) { - oz_trace("oz_hcd_shutdown()\n"); } /*------------------------------------------------------------------------------ * Called to queue an urb for the device. @@ -1844,7 +1838,6 @@ static int oz_hcd_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) static void oz_hcd_endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep) { - oz_trace("oz_hcd_endpoint_disable\n"); } /*------------------------------------------------------------------------------ * Context: unknown @@ -1852,7 +1845,6 @@ static void oz_hcd_endpoint_disable(struct usb_hcd *hcd, static void oz_hcd_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep) { - oz_trace("oz_hcd_endpoint_reset\n"); } /*------------------------------------------------------------------------------ * Context: unknown @@ -1872,7 +1864,6 @@ static int oz_hcd_hub_status_data(struct usb_hcd *hcd, char *buf) struct oz_hcd *ozhcd = oz_hcd_private(hcd); int i; - oz_trace2(OZ_TRACE_HUB, "oz_hcd_hub_status_data()\n"); buf[0] = 0; spin_lock_bh(&ozhcd->hcd_lock); @@ -1892,7 +1883,6 @@ static int oz_hcd_hub_status_data(struct usb_hcd *hcd, char *buf) static void oz_get_hub_descriptor(struct usb_hcd *hcd, struct usb_hub_descriptor *desc) { - oz_trace2(OZ_TRACE_HUB, "GetHubDescriptor\n"); memset(desc, 0, sizeof(*desc)); desc->bDescriptorType = 0x29; desc->bDescLength = 9; @@ -1911,7 +1901,7 @@ static int oz_set_port_feature(struct usb_hcd *hcd, u16 wvalue, u16 windex) struct oz_hcd *ozhcd = oz_hcd_private(hcd); unsigned set_bits = 0; unsigned clear_bits = 0; - oz_trace2(OZ_TRACE_HUB, "SetPortFeature\n"); + if ((port_id < 1) || (port_id > OZ_NB_PORTS)) return -EPIPE; port = &ozhcd->ports[port_id-1]; @@ -1986,7 +1976,7 @@ static int oz_clear_port_feature(struct usb_hcd *hcd, u16 wvalue, u16 windex) u8 port_id = (u8)windex; struct oz_hcd *ozhcd = oz_hcd_private(hcd); unsigned clear_bits = 0; - oz_trace2(OZ_TRACE_HUB, "ClearPortFeature\n"); + if ((port_id < 1) || (port_id > OZ_NB_PORTS)) return -EPIPE; port = &ozhcd->ports[port_id-1]; @@ -2074,7 +2064,7 @@ static int oz_hcd_hub_control(struct usb_hcd *hcd, u16 req_type, u16 wvalue, u16 windex, char *buf, u16 wlength) { int err = 0; - oz_trace2(OZ_TRACE_HUB, "oz_hcd_hub_control()\n"); + switch (req_type) { case ClearHubFeature: oz_trace2(OZ_TRACE_HUB, "ClearHubFeature: %d\n", req_type); @@ -2111,7 +2101,7 @@ static int oz_hcd_hub_control(struct usb_hcd *hcd, u16 req_type, u16 wvalue, static int oz_hcd_bus_suspend(struct usb_hcd *hcd) { struct oz_hcd *ozhcd; - oz_trace2(OZ_TRACE_HUB, "oz_hcd_hub_suspend()\n"); + ozhcd = oz_hcd_private(hcd); spin_lock_bh(&ozhcd->hcd_lock); hcd->state = HC_STATE_SUSPENDED; @@ -2125,7 +2115,7 @@ static int oz_hcd_bus_suspend(struct usb_hcd *hcd) static int oz_hcd_bus_resume(struct usb_hcd *hcd) { struct oz_hcd *ozhcd; - oz_trace2(OZ_TRACE_HUB, "oz_hcd_hub_resume()\n"); + ozhcd = oz_hcd_private(hcd); spin_lock_bh(&ozhcd->hcd_lock); ozhcd->flags &= ~OZ_HDC_F_SUSPENDED; @@ -2137,8 +2127,8 @@ static int oz_hcd_bus_resume(struct usb_hcd *hcd) */ static void oz_plat_shutdown(struct platform_device *dev) { - oz_trace("oz_plat_shutdown()\n"); } + /*------------------------------------------------------------------------------ * Context: process */ @@ -2148,7 +2138,7 @@ static int oz_plat_probe(struct platform_device *dev) int err; struct usb_hcd *hcd; struct oz_hcd *ozhcd; - oz_trace("oz_plat_probe()\n"); + hcd = usb_create_hcd(&g_oz_hc_drv, &dev->dev, dev_name(&dev->dev)); if (hcd == NULL) { oz_trace("Failed to created hcd object OK\n"); @@ -2188,7 +2178,7 @@ static int oz_plat_remove(struct platform_device *dev) { struct usb_hcd *hcd = platform_get_drvdata(dev); struct oz_hcd *ozhcd; - oz_trace("oz_plat_remove()\n"); + if (hcd == NULL) return -1; ozhcd = oz_hcd_private(hcd); @@ -2209,7 +2199,6 @@ static int oz_plat_remove(struct platform_device *dev) */ static int oz_plat_suspend(struct platform_device *dev, pm_message_t msg) { - oz_trace("oz_plat_suspend()\n"); return 0; } /*------------------------------------------------------------------------------ @@ -2217,7 +2206,6 @@ static int oz_plat_suspend(struct platform_device *dev, pm_message_t msg) */ static int oz_plat_resume(struct platform_device *dev) { - oz_trace("oz_plat_resume()\n"); return 0; } /*------------------------------------------------------------------------------ From f724b5843431aba591a01b6988a725689cd9ebb3 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 23 Jul 2013 13:45:00 +0100 Subject: [PATCH 0383/3400] staging: ozwpan: Replace oz_trace with oz_dbg Introduce new debug macros: oz_dbg, oz_cdev_dbg, oz_pd_dbg and then replace old oz_trace & oz_trace2 with new macro. Signed-off-by: Joe Perches Signed-off-by: Rupesh Gujare Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ozwpan/ozcdev.c | 48 ++--- drivers/staging/ozwpan/ozdbg.h | 54 +++++ drivers/staging/ozwpan/ozeltbuf.c | 30 ++- drivers/staging/ozwpan/ozhcd.c | 261 ++++++++++++------------- drivers/staging/ozwpan/ozpd.c | 61 +++--- drivers/staging/ozwpan/ozproto.c | 56 +++--- drivers/staging/ozwpan/ozproto.h | 2 +- drivers/staging/ozwpan/ozurbparanoia.c | 9 +- drivers/staging/ozwpan/ozusbsvc.c | 21 +- drivers/staging/ozwpan/ozusbsvc1.c | 17 +- 10 files changed, 307 insertions(+), 252 deletions(-) create mode 100644 drivers/staging/ozwpan/ozdbg.h diff --git a/drivers/staging/ozwpan/ozcdev.c b/drivers/staging/ozwpan/ozcdev.c index 284c26da27be..87c3131f5b9f 100644 --- a/drivers/staging/ozwpan/ozcdev.c +++ b/drivers/staging/ozwpan/ozcdev.c @@ -12,6 +12,7 @@ #include #include #include "ozconfig.h" +#include "ozdbg.h" #include "ozprotocol.h" #include "oztrace.h" #include "ozappif.h" @@ -63,7 +64,7 @@ static struct oz_serial_ctx *oz_cdev_claim_ctx(struct oz_pd *pd) static void oz_cdev_release_ctx(struct oz_serial_ctx *ctx) { if (atomic_dec_and_test(&ctx->ref_count)) { - oz_trace("Dealloc serial context.\n"); + oz_dbg(ON, "Dealloc serial context\n"); kfree(ctx); } } @@ -72,9 +73,10 @@ static void oz_cdev_release_ctx(struct oz_serial_ctx *ctx) */ static int oz_cdev_open(struct inode *inode, struct file *filp) { - struct oz_cdev *dev; - oz_trace("major = %d minor = %d\n", imajor(inode), iminor(inode)); - dev = container_of(inode->i_cdev, struct oz_cdev, cdev); + struct oz_cdev *dev = container_of(inode->i_cdev, struct oz_cdev, cdev); + + oz_dbg(ON, "major = %d minor = %d\n", imajor(inode), iminor(inode)); + filp->private_data = dev; return 0; } @@ -249,7 +251,7 @@ static long oz_cdev_ioctl(struct file *filp, unsigned int cmd, switch (cmd) { case OZ_IOCTL_GET_PD_LIST: { struct oz_pd_list list; - oz_trace("OZ_IOCTL_GET_PD_LIST\n"); + oz_dbg(ON, "OZ_IOCTL_GET_PD_LIST\n"); memset(&list, 0, sizeof(list)); list.count = oz_get_pd_list(list.addr, OZ_MAX_PDS); if (copy_to_user((void __user *)arg, &list, @@ -259,7 +261,7 @@ static long oz_cdev_ioctl(struct file *filp, unsigned int cmd, break; case OZ_IOCTL_SET_ACTIVE_PD: { u8 addr[ETH_ALEN]; - oz_trace("OZ_IOCTL_SET_ACTIVE_PD\n"); + oz_dbg(ON, "OZ_IOCTL_SET_ACTIVE_PD\n"); if (copy_from_user(addr, (void __user *)arg, ETH_ALEN)) return -EFAULT; rc = oz_set_active_pd(addr); @@ -267,7 +269,7 @@ static long oz_cdev_ioctl(struct file *filp, unsigned int cmd, break; case OZ_IOCTL_GET_ACTIVE_PD: { u8 addr[ETH_ALEN]; - oz_trace("OZ_IOCTL_GET_ACTIVE_PD\n"); + oz_dbg(ON, "OZ_IOCTL_GET_ACTIVE_PD\n"); spin_lock_bh(&g_cdev.lock); memcpy(addr, g_cdev.active_addr, ETH_ALEN); spin_unlock_bh(&g_cdev.lock); @@ -300,7 +302,7 @@ static unsigned int oz_cdev_poll(struct file *filp, poll_table *wait) { unsigned int ret = 0; struct oz_cdev *dev = filp->private_data; - oz_trace("Poll called wait = %p\n", wait); + oz_dbg(ON, "Poll called wait = %p\n", wait); spin_lock_bh(&dev->lock); if (dev->active_pd) { struct oz_serial_ctx *ctx = oz_cdev_claim_ctx(dev->active_pd); @@ -337,8 +339,8 @@ int oz_cdev_register(void) err = alloc_chrdev_region(&g_cdev.devnum, 0, 1, "ozwpan"); if (err < 0) goto out3; - oz_trace("Alloc dev number %d:%d\n", MAJOR(g_cdev.devnum), - MINOR(g_cdev.devnum)); + oz_dbg(ON, "Alloc dev number %d:%d\n", + MAJOR(g_cdev.devnum), MINOR(g_cdev.devnum)); cdev_init(&g_cdev.cdev, &oz_fops); g_cdev.cdev.owner = THIS_MODULE; g_cdev.cdev.ops = &oz_fops; @@ -346,18 +348,18 @@ int oz_cdev_register(void) init_waitqueue_head(&g_cdev.rdq); err = cdev_add(&g_cdev.cdev, g_cdev.devnum, 1); if (err < 0) { - oz_trace("Failed to add cdev\n"); + oz_dbg(ON, "Failed to add cdev\n"); goto out2; } g_oz_class = class_create(THIS_MODULE, "ozmo_wpan"); if (IS_ERR(g_oz_class)) { - oz_trace("Failed to register ozmo_wpan class\n"); + oz_dbg(ON, "Failed to register ozmo_wpan class\n"); err = PTR_ERR(g_oz_class); goto out1; } dev = device_create(g_oz_class, NULL, g_cdev.devnum, NULL, "ozwpan"); if (IS_ERR(dev)) { - oz_trace("Failed to create sysfs entry for cdev\n"); + oz_dbg(ON, "Failed to create sysfs entry for cdev\n"); err = PTR_ERR(dev); goto out1; } @@ -405,7 +407,7 @@ int oz_cdev_start(struct oz_pd *pd, int resume) struct oz_serial_ctx *ctx; struct oz_serial_ctx *old_ctx; if (resume) { - oz_trace("Serial service resumed.\n"); + oz_dbg(ON, "Serial service resumed\n"); return 0; } ctx = kzalloc(sizeof(struct oz_serial_ctx), GFP_ATOMIC); @@ -427,10 +429,10 @@ int oz_cdev_start(struct oz_pd *pd, int resume) (memcmp(pd->mac_addr, g_cdev.active_addr, ETH_ALEN) == 0)) { oz_pd_get(pd); g_cdev.active_pd = pd; - oz_trace("Active PD arrived.\n"); + oz_dbg(ON, "Active PD arrived\n"); } spin_unlock(&g_cdev.lock); - oz_trace("Serial service started.\n"); + oz_dbg(ON, "Serial service started\n"); return 0; } /*------------------------------------------------------------------------------ @@ -440,7 +442,7 @@ void oz_cdev_stop(struct oz_pd *pd, int pause) { struct oz_serial_ctx *ctx; if (pause) { - oz_trace("Serial service paused.\n"); + oz_dbg(ON, "Serial service paused\n"); return; } spin_lock_bh(&pd->app_lock[OZ_APPID_SERIAL-1]); @@ -457,9 +459,9 @@ void oz_cdev_stop(struct oz_pd *pd, int pause) spin_unlock(&g_cdev.lock); if (pd) { oz_pd_put(pd); - oz_trace("Active PD departed.\n"); + oz_dbg(ON, "Active PD departed\n"); } - oz_trace("Serial service stopped.\n"); + oz_dbg(ON, "Serial service stopped\n"); } /*------------------------------------------------------------------------------ * Context: softirq-serialized @@ -476,7 +478,7 @@ void oz_cdev_rx(struct oz_pd *pd, struct oz_elt *elt) ctx = oz_cdev_claim_ctx(pd); if (ctx == NULL) { - oz_trace("Cannot claim serial context.\n"); + oz_dbg(ON, "Cannot claim serial context\n"); return; } @@ -486,8 +488,8 @@ void oz_cdev_rx(struct oz_pd *pd, struct oz_elt *elt) if (app_hdr->elt_seq_num != 0) { if (((ctx->rx_seq_num - app_hdr->elt_seq_num) & 0x80) == 0) { /* Reject duplicate element. */ - oz_trace("Duplicate element:%02x %02x\n", - app_hdr->elt_seq_num, ctx->rx_seq_num); + oz_dbg(ON, "Duplicate element:%02x %02x\n", + app_hdr->elt_seq_num, ctx->rx_seq_num); goto out; } } @@ -500,7 +502,7 @@ void oz_cdev_rx(struct oz_pd *pd, struct oz_elt *elt) if (space < 0) space += OZ_RD_BUF_SZ; if (len > space) { - oz_trace("Not enough space:%d %d\n", len, space); + oz_dbg(ON, "Not enough space:%d %d\n", len, space); len = space; } ix = ctx->rd_in; diff --git a/drivers/staging/ozwpan/ozdbg.h b/drivers/staging/ozwpan/ozdbg.h new file mode 100644 index 000000000000..b86a2b7e0178 --- /dev/null +++ b/drivers/staging/ozwpan/ozdbg.h @@ -0,0 +1,54 @@ +/* ----------------------------------------------------------------------------- + * Copyright (c) 2011 Ozmo Inc + * Released under the GNU General Public License Version 2 (GPLv2). + * ---------------------------------------------------------------------------*/ + +#ifndef _OZDBG_H +#define _OZDBG_H + +#define OZ_WANT_DBG 0 +#define OZ_WANT_VERBOSE_DBG 1 + +#define OZ_DBG_ON 0x0 +#define OZ_DBG_STREAM 0x1 +#define OZ_DBG_URB 0x2 +#define OZ_DBG_CTRL_DETAIL 0x4 +#define OZ_DBG_HUB 0x8 +#define OZ_DBG_RX_FRAMES 0x10 +#define OZ_DBG_TX_FRAMES 0x20 + +#define OZ_DEFAULT_DBG_MASK \ + ( \ + /* OZ_DBG_STREAM | */ \ + /* OZ_DBG_URB | */ \ + /* OZ_DBG_CTRL_DETAIL | */ \ + OZ_DBG_HUB | \ + /* OZ_DBG_RX_FRAMES | */ \ + /* OZ_DBG_TX_FRAMES | */ \ + 0) + +extern unsigned int oz_dbg_mask; + +#define oz_want_dbg(mask) \ + ((OZ_WANT_DBG && (OZ_DBG_##mask == OZ_DBG_ON)) || \ + (OZ_WANT_VERBOSE_DBG && (OZ_DBG_##mask & oz_dbg_mask))) + +#define oz_dbg(mask, fmt, ...) \ +do { \ + if (oz_want_dbg(mask)) \ + pr_debug(fmt, ##__VA_ARGS__); \ +} while (0) + +#define oz_cdev_dbg(cdev, mask, fmt, ...) \ +do { \ + if (oz_want_dbg(mask)) \ + netdev_dbg((cdev)->dev, fmt, ##__VA_ARGS__); \ +} while (0) + +#define oz_pd_dbg(pd, mask, fmt, ...) \ +do { \ + if (oz_want_dbg(mask)) \ + pr_debug(fmt, ##__VA_ARGS__); \ +} while (0) + +#endif /* _OZDBG_H */ diff --git a/drivers/staging/ozwpan/ozeltbuf.c b/drivers/staging/ozwpan/ozeltbuf.c index ac90fc7f5441..bf280aabe383 100644 --- a/drivers/staging/ozwpan/ozeltbuf.c +++ b/drivers/staging/ozwpan/ozeltbuf.c @@ -7,10 +7,12 @@ #include #include #include "ozconfig.h" +#include "ozdbg.h" #include "ozprotocol.h" #include "ozeltbuf.h" #include "ozpd.h" #include "oztrace.h" + /*------------------------------------------------------------------------------ */ #define OZ_ELT_INFO_MAGIC_USED 0x35791057 @@ -72,8 +74,8 @@ struct oz_elt_info *oz_elt_info_alloc(struct oz_elt_buf *buf) buf->free_elts--; spin_unlock_bh(&buf->lock); if (ei->magic != OZ_ELT_INFO_MAGIC_FREE) { - oz_trace("oz_elt_info_alloc: ei with bad magic: 0x%x\n", - ei->magic); + oz_dbg(ON, "%s: ei with bad magic: 0x%x\n", + __func__, ei->magic); } } else { spin_unlock_bh(&buf->lock); @@ -104,9 +106,8 @@ void oz_elt_info_free(struct oz_elt_buf *buf, struct oz_elt_info *ei) buf->elt_pool = &ei->link; ei->magic = OZ_ELT_INFO_MAGIC_FREE; } else { - oz_trace("oz_elt_info_free: bad magic ei: %p" - " magic: 0x%x\n", - ei, ei->magic); + oz_dbg(ON, "%s: bad magic ei: %p magic: 0x%x\n", + __func__, ei, ei->magic); } } } @@ -132,7 +133,7 @@ int oz_elt_stream_create(struct oz_elt_buf *buf, u8 id, int max_buf_count) { struct oz_elt_stream *st; - oz_trace("oz_elt_stream_create(0x%x)\n", id); + oz_dbg(ON, "%s: (0x%x)\n", __func__, id); st = kzalloc(sizeof(struct oz_elt_stream), GFP_ATOMIC | __GFP_ZERO); if (st == NULL) @@ -152,7 +153,7 @@ int oz_elt_stream_delete(struct oz_elt_buf *buf, u8 id) { struct list_head *e; struct oz_elt_stream *st = NULL; - oz_trace("oz_elt_stream_delete(0x%x)\n", id); + oz_dbg(ON, "%s: (0x%x)\n", __func__, id); spin_lock_bh(&buf->lock); e = buf->stream_list.next; while (e != &buf->stream_list) { @@ -175,9 +176,8 @@ int oz_elt_stream_delete(struct oz_elt_buf *buf, u8 id) list_del_init(&ei->link); list_del_init(&ei->link_order); st->buf_count -= ei->length; - oz_trace2(OZ_TRACE_STREAM, "Stream down: %d %d %d\n", - st->buf_count, - ei->length, atomic_read(&st->ref_count)); + oz_dbg(STREAM, "Stream down: %d %d %d\n", + st->buf_count, ei->length, atomic_read(&st->ref_count)); oz_elt_stream_put(st); oz_elt_info_free(buf, ei); } @@ -196,7 +196,7 @@ void oz_elt_stream_get(struct oz_elt_stream *st) void oz_elt_stream_put(struct oz_elt_stream *st) { if (atomic_dec_and_test(&st->ref_count)) { - oz_trace("Stream destroyed\n"); + oz_dbg(ON, "Stream destroyed\n"); kfree(st); } } @@ -242,8 +242,7 @@ int oz_queue_elt_info(struct oz_elt_buf *buf, u8 isoc, u8 id, st->buf_count += ei->length; /* Add to list in stream. */ list_add_tail(&ei->link, &st->elt_list); - oz_trace2(OZ_TRACE_STREAM, "Stream up: %d %d\n", - st->buf_count, ei->length); + oz_dbg(STREAM, "Stream up: %d %d\n", st->buf_count, ei->length); /* Check if we have too much buffered for this stream. If so * start dropping elements until we are back in bounds. */ @@ -293,9 +292,8 @@ int oz_select_elts_for_tx(struct oz_elt_buf *buf, u8 isoc, unsigned *len, list_del(&ei->link_order); if (ei->stream) { ei->stream->buf_count -= ei->length; - oz_trace2(OZ_TRACE_STREAM, - "Stream down: %d %d\n", - ei->stream->buf_count, ei->length); + oz_dbg(STREAM, "Stream down: %d %d\n", + ei->stream->buf_count, ei->length); oz_elt_stream_put(ei->stream); ei->stream = NULL; } diff --git a/drivers/staging/ozwpan/ozhcd.c b/drivers/staging/ozwpan/ozhcd.c index 9d1bd4450b8e..fece2dab3ae9 100644 --- a/drivers/staging/ozwpan/ozhcd.c +++ b/drivers/staging/ozwpan/ozhcd.c @@ -31,6 +31,7 @@ #include #include "linux/usb/hcd.h" #include +#include "ozdbg.h" #include "ozconfig.h" #include "ozusbif.h" #include "oztrace.h" @@ -371,14 +372,13 @@ static void oz_complete_urb(struct usb_hcd *hcd, struct urb *urb, */ spin_unlock(&g_tasklet_lock); if (oz_forget_urb(urb)) { - oz_trace("OZWPAN: ERROR Unknown URB %p\n", urb); + oz_dbg(ON, "ERROR Unknown URB %p\n", urb); } else { static unsigned long last_time; atomic_dec(&g_pending_urbs); - oz_trace2(OZ_TRACE_URB, - "%lu: giveback_urb(%p,%x) %lu %lu pending:%d\n", - jiffies, urb, status, jiffies-submit_jiffies, - jiffies-last_time, atomic_read(&g_pending_urbs)); + oz_dbg(URB, "%lu: giveback_urb(%p,%x) %lu %lu pending:%d\n", + jiffies, urb, status, jiffies-submit_jiffies, + jiffies-last_time, atomic_read(&g_pending_urbs)); last_time = jiffies; usb_hcd_giveback_urb(hcd, urb, status); } @@ -408,7 +408,7 @@ static void oz_ep_free(struct oz_port *port, struct oz_endpoint *ep) list_splice_tail(&list, &ozhcd->orphanage); spin_unlock_bh(&ozhcd->hcd_lock); } - oz_trace("Freeing endpoint memory\n"); + oz_dbg(ON, "Freeing endpoint memory\n"); kfree(ep); } /*------------------------------------------------------------------------------ @@ -445,8 +445,8 @@ static void oz_complete_buffered_urb(struct oz_port *port, ep->out_ix = 0; ep->buffered_units--; - oz_trace("Trying to give back buffered frame of size=%d\n", - available_space); + oz_dbg(ON, "Trying to give back buffered frame of size=%d\n", + available_space); oz_complete_urb(port->ozhcd->hcd, urb, 0, 0); } @@ -460,7 +460,7 @@ static int oz_enqueue_ep_urb(struct oz_port *port, u8 ep_addr, int in_dir, struct oz_endpoint *ep; int err = 0; if (ep_addr >= OZ_NB_ENDPOINTS) { - oz_trace("Invalid endpoint number in oz_enqueue_ep_urb().\n"); + oz_dbg(ON, "%s: Invalid endpoint number\n", __func__); return -EINVAL; } urbl = oz_alloc_urb_link(); @@ -479,7 +479,7 @@ static int oz_enqueue_ep_urb(struct oz_port *port, u8 ep_addr, int in_dir, */ if (urb->unlinked) { spin_unlock_bh(&port->ozhcd->hcd_lock); - oz_trace("urb %p unlinked so complete immediately\n", urb); + oz_dbg(ON, "urb %p unlinked so complete immediately\n", urb); oz_complete_urb(port->ozhcd->hcd, urb, 0, 0); oz_free_urb_link(urbl); return 0; @@ -640,7 +640,7 @@ void *oz_hcd_pd_arrived(void *hpd) spin_lock_bh(&ozhcd->hcd_lock); if (ozhcd->conn_port >= 0) { spin_unlock_bh(&ozhcd->hcd_lock); - oz_trace("conn_port >= 0\n"); + oz_dbg(ON, "conn_port >= 0\n"); goto out; } for (i = 0; i < OZ_NB_PORTS; i++) { @@ -654,7 +654,7 @@ void *oz_hcd_pd_arrived(void *hpd) spin_unlock(&port->port_lock); } if (i < OZ_NB_PORTS) { - oz_trace("Setting conn_port = %d\n", i); + oz_dbg(ON, "Setting conn_port = %d\n", i); ozhcd->conn_port = i; /* Attach out endpoint 0. */ @@ -663,7 +663,7 @@ void *oz_hcd_pd_arrived(void *hpd) hport = &ozhcd->ports[i]; spin_unlock_bh(&ozhcd->hcd_lock); if (ozhcd->flags & OZ_HDC_F_SUSPENDED) { - oz_trace("Resuming root hub\n"); + oz_dbg(ON, "Resuming root hub\n"); usb_hcd_resume_root_hub(ozhcd->hcd); } usb_hcd_poll_rh_status(ozhcd->hcd); @@ -690,7 +690,7 @@ void oz_hcd_pd_departed(void *hport) struct oz_endpoint *ep = NULL; if (port == NULL) { - oz_trace("oz_hcd_pd_departed() port = 0\n"); + oz_dbg(ON, "%s: port = 0\n", __func__); return; } ozhcd = port->ozhcd; @@ -701,7 +701,7 @@ void oz_hcd_pd_departed(void *hport) spin_lock_bh(&ozhcd->hcd_lock); if ((ozhcd->conn_port >= 0) && (port == &ozhcd->ports[ozhcd->conn_port])) { - oz_trace("Clearing conn_port\n"); + oz_dbg(ON, "Clearing conn_port\n"); ozhcd->conn_port = -1; } spin_lock(&port->port_lock); @@ -740,7 +740,7 @@ void oz_hcd_pd_reset(void *hpd, void *hport) */ struct oz_port *port = (struct oz_port *)hport; struct oz_hcd *ozhcd = port->ozhcd; - oz_trace("PD Reset\n"); + oz_dbg(ON, "PD Reset\n"); spin_lock_bh(&port->port_lock); port->flags |= OZ_PORT_F_CHANGED; port->status |= USB_PORT_STAT_RESET; @@ -759,8 +759,8 @@ void oz_hcd_get_desc_cnf(void *hport, u8 req_id, int status, const u8 *desc, struct urb *urb; int err = 0; - oz_trace("oz_hcd_get_desc_cnf length = %d offs = %d tot_size = %d\n", - length, offset, total_size); + oz_dbg(ON, "oz_hcd_get_desc_cnf length = %d offs = %d tot_size = %d\n", + length, offset, total_size); urb = oz_find_urb_by_id(port, 0, req_id); if (!urb) return; @@ -802,37 +802,37 @@ static void oz_display_conf_type(u8 t) { switch (t) { case USB_REQ_GET_STATUS: - oz_trace("USB_REQ_GET_STATUS - cnf\n"); + oz_dbg(ON, "USB_REQ_GET_STATUS - cnf\n"); break; case USB_REQ_CLEAR_FEATURE: - oz_trace("USB_REQ_CLEAR_FEATURE - cnf\n"); + oz_dbg(ON, "USB_REQ_CLEAR_FEATURE - cnf\n"); break; case USB_REQ_SET_FEATURE: - oz_trace("USB_REQ_SET_FEATURE - cnf\n"); + oz_dbg(ON, "USB_REQ_SET_FEATURE - cnf\n"); break; case USB_REQ_SET_ADDRESS: - oz_trace("USB_REQ_SET_ADDRESS - cnf\n"); + oz_dbg(ON, "USB_REQ_SET_ADDRESS - cnf\n"); break; case USB_REQ_GET_DESCRIPTOR: - oz_trace("USB_REQ_GET_DESCRIPTOR - cnf\n"); + oz_dbg(ON, "USB_REQ_GET_DESCRIPTOR - cnf\n"); break; case USB_REQ_SET_DESCRIPTOR: - oz_trace("USB_REQ_SET_DESCRIPTOR - cnf\n"); + oz_dbg(ON, "USB_REQ_SET_DESCRIPTOR - cnf\n"); break; case USB_REQ_GET_CONFIGURATION: - oz_trace("USB_REQ_GET_CONFIGURATION - cnf\n"); + oz_dbg(ON, "USB_REQ_GET_CONFIGURATION - cnf\n"); break; case USB_REQ_SET_CONFIGURATION: - oz_trace("USB_REQ_SET_CONFIGURATION - cnf\n"); + oz_dbg(ON, "USB_REQ_SET_CONFIGURATION - cnf\n"); break; case USB_REQ_GET_INTERFACE: - oz_trace("USB_REQ_GET_INTERFACE - cnf\n"); + oz_dbg(ON, "USB_REQ_GET_INTERFACE - cnf\n"); break; case USB_REQ_SET_INTERFACE: - oz_trace("USB_REQ_SET_INTERFACE - cnf\n"); + oz_dbg(ON, "USB_REQ_SET_INTERFACE - cnf\n"); break; case USB_REQ_SYNCH_FRAME: - oz_trace("USB_REQ_SYNCH_FRAME - cnf\n"); + oz_dbg(ON, "USB_REQ_SYNCH_FRAME - cnf\n"); break; } } @@ -870,7 +870,7 @@ static void oz_hcd_complete_set_interface(struct oz_port *port, struct urb *urb, if (rcode == 0) { struct usb_host_config *config; struct usb_host_interface *intf; - oz_trace("Set interface %d alt %d\n", if_num, alt); + oz_dbg(ON, "Set interface %d alt %d\n", if_num, alt); oz_clean_endpoints_for_interface(hcd, port, if_num); config = &urb->dev->config[port->config_num-1]; intf = &config->intf_cache[if_num]->altsetting[alt]; @@ -897,10 +897,10 @@ void oz_hcd_control_cnf(void *hport, u8 req_id, u8 rcode, const u8 *data, unsigned windex; unsigned wvalue; - oz_trace("oz_hcd_control_cnf rcode=%u len=%d\n", rcode, data_len); + oz_dbg(ON, "oz_hcd_control_cnf rcode=%u len=%d\n", rcode, data_len); urb = oz_find_urb_by_id(port, 0, req_id); if (!urb) { - oz_trace("URB not found\n"); + oz_dbg(ON, "URB not found\n"); return; } setup = (struct usb_ctrlrequest *)urb->setup_packet; @@ -924,7 +924,7 @@ void oz_hcd_control_cnf(void *hport, u8 req_id, u8 rcode, const u8 *data, } else { int copy_len; - oz_trace("VENDOR-CLASS - cnf\n"); + oz_dbg(ON, "VENDOR-CLASS - cnf\n"); if (data_len) { if (data_len <= urb->transfer_buffer_length) copy_len = data_len; @@ -950,7 +950,7 @@ static int oz_hcd_buffer_data(struct oz_endpoint *ep, const u8 *data, if (space < 0) space += ep->buffer_size; if (space < (data_len+1)) { - oz_trace("Buffer full\n"); + oz_dbg(ON, "Buffer full\n"); return -1; } ep->buffer[ep->in_ix] = (u8)data_len; @@ -1006,7 +1006,7 @@ void oz_hcd_data_ind(void *hport, u8 endpoint, const u8 *data, int data_len) oz_complete_urb(port->ozhcd->hcd, urb, 0, 0); return; } else { - oz_trace("buffering frame as URB is not available\n"); + oz_dbg(ON, "buffering frame as URB is not available\n"); oz_hcd_buffer_data(ep, data, data_len); } break; @@ -1159,8 +1159,8 @@ int oz_hcd_heartbeat(void *hport) list_for_each_safe(e, n, &ep->urb_list) { urbl = container_of(e, struct oz_urb_link, link); if (time_after(now, urbl->submit_jiffies+HZ/2)) { - oz_trace("%ld: Request 0x%p timeout\n", - now, urbl->urb); + oz_dbg(ON, "%ld: Request 0x%p timeout\n", + now, urbl->urb); urbl->submit_jiffies = now; list_move_tail(e, &xfr_list); } @@ -1172,7 +1172,7 @@ int oz_hcd_heartbeat(void *hport) while (e != &xfr_list) { urbl = container_of(e, struct oz_urb_link, link); e = e->next; - oz_trace("Resending request to PD.\n"); + oz_dbg(ON, "Resending request to PD\n"); oz_process_ep0_urb(ozhcd, urbl->urb, GFP_ATOMIC); oz_free_urb_link(urbl); } @@ -1190,7 +1190,7 @@ static int oz_build_endpoints_for_interface(struct usb_hcd *hcd, int i; int if_ix = intf->desc.bInterfaceNumber; int request_heartbeat = 0; - oz_trace("interface[%d] = %p\n", if_ix, intf); + oz_dbg(ON, "interface[%d] = %p\n", if_ix, intf); for (i = 0; i < intf->desc.bNumEndpoints; i++) { struct usb_host_endpoint *hep = &intf->endpoint[i]; u8 ep_addr = hep->desc.bEndpointAddress; @@ -1198,7 +1198,7 @@ static int oz_build_endpoints_for_interface(struct usb_hcd *hcd, struct oz_endpoint *ep; int buffer_size = 0; - oz_trace("%d bEndpointAddress = %x\n", i, ep_addr); + oz_dbg(ON, "%d bEndpointAddress = %x\n", i, ep_addr); if (ep_addr & USB_ENDPOINT_DIR_MASK) { switch (hep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { @@ -1220,8 +1220,8 @@ static int oz_build_endpoints_for_interface(struct usb_hcd *hcd, ep->ep_num = ep_num; if ((ep->attrib & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_ISOC) { - oz_trace("wMaxPacketSize = %d\n", - usb_endpoint_maxp(&hep->desc)); + oz_dbg(ON, "wMaxPacketSize = %d\n", + usb_endpoint_maxp(&hep->desc)); ep->credit_ceiling = 200; if (ep_addr & USB_ENDPOINT_DIR_MASK) { ep->flags |= OZ_F_EP_BUFFERING; @@ -1267,7 +1267,7 @@ static void oz_clean_endpoints_for_interface(struct usb_hcd *hcd, int i; struct list_head ep_list; - oz_trace("Deleting endpoints for interface %d\n", if_ix); + oz_dbg(ON, "Deleting endpoints for interface %d\n", if_ix); if (if_ix >= port->num_iface) return; INIT_LIST_HEAD(&ep_list); @@ -1343,12 +1343,12 @@ static void oz_clean_endpoints_for_config(struct usb_hcd *hcd, { struct oz_hcd *ozhcd = port->ozhcd; int i; - oz_trace("Deleting endpoints for configuration.\n"); + oz_dbg(ON, "Deleting endpoints for configuration\n"); for (i = 0; i < port->num_iface; i++) oz_clean_endpoints_for_interface(hcd, port, i); spin_lock_bh(&ozhcd->hcd_lock); if (port->iface) { - oz_trace("Freeing interfaces object.\n"); + oz_dbg(ON, "Freeing interfaces object\n"); kfree(port->iface); port->iface = NULL; } @@ -1387,7 +1387,7 @@ static void oz_process_ep0_urb(struct oz_hcd *ozhcd, struct urb *urb, int port_ix = -1; struct oz_port *port = NULL; - oz_trace2(OZ_TRACE_URB, "%lu: oz_process_ep0_urb(%p)\n", jiffies, urb); + oz_dbg(URB, "%lu: %s: (%p)\n", jiffies, __func__, urb); port_ix = oz_get_port_from_addr(ozhcd, urb->dev->devnum); if (port_ix < 0) { rc = -EPIPE; @@ -1396,8 +1396,8 @@ static void oz_process_ep0_urb(struct oz_hcd *ozhcd, struct urb *urb, port = &ozhcd->ports[port_ix]; if (((port->flags & OZ_PORT_F_PRESENT) == 0) || (port->flags & OZ_PORT_F_DYING)) { - oz_trace("Refusing URB port_ix = %d devnum = %d\n", - port_ix, urb->dev->devnum); + oz_dbg(ON, "Refusing URB port_ix = %d devnum = %d\n", + port_ix, urb->dev->devnum); rc = -EPIPE; goto out; } @@ -1408,17 +1408,16 @@ static void oz_process_ep0_urb(struct oz_hcd *ozhcd, struct urb *urb, windex = le16_to_cpu(setup->wIndex); wvalue = le16_to_cpu(setup->wValue); wlength = le16_to_cpu(setup->wLength); - oz_trace2(OZ_TRACE_CTRL_DETAIL, "bRequestType = %x\n", - setup->bRequestType); - oz_trace2(OZ_TRACE_CTRL_DETAIL, "bRequest = %x\n", setup->bRequest); - oz_trace2(OZ_TRACE_CTRL_DETAIL, "wValue = %x\n", wvalue); - oz_trace2(OZ_TRACE_CTRL_DETAIL, "wIndex = %x\n", windex); - oz_trace2(OZ_TRACE_CTRL_DETAIL, "wLength = %x\n", wlength); + oz_dbg(CTRL_DETAIL, "bRequestType = %x\n", setup->bRequestType); + oz_dbg(CTRL_DETAIL, "bRequest = %x\n", setup->bRequest); + oz_dbg(CTRL_DETAIL, "wValue = %x\n", wvalue); + oz_dbg(CTRL_DETAIL, "wIndex = %x\n", windex); + oz_dbg(CTRL_DETAIL, "wLength = %x\n", wlength); req_id = port->next_req_id++; hpd = oz_claim_hpd(port); if (hpd == NULL) { - oz_trace("Cannot claim port\n"); + oz_dbg(ON, "Cannot claim port\n"); rc = -EPIPE; goto out; } @@ -1428,30 +1427,31 @@ static void oz_process_ep0_urb(struct oz_hcd *ozhcd, struct urb *urb, */ switch (setup->bRequest) { case USB_REQ_GET_DESCRIPTOR: - oz_trace("USB_REQ_GET_DESCRIPTOR - req\n"); + oz_dbg(ON, "USB_REQ_GET_DESCRIPTOR - req\n"); break; case USB_REQ_SET_ADDRESS: - oz_trace("USB_REQ_SET_ADDRESS - req\n"); - oz_trace("Port %d address is 0x%x\n", ozhcd->conn_port, - (u8)le16_to_cpu(setup->wValue)); + oz_dbg(ON, "USB_REQ_SET_ADDRESS - req\n"); + oz_dbg(ON, "Port %d address is 0x%x\n", + ozhcd->conn_port, + (u8)le16_to_cpu(setup->wValue)); spin_lock_bh(&ozhcd->hcd_lock); if (ozhcd->conn_port >= 0) { ozhcd->ports[ozhcd->conn_port].bus_addr = (u8)le16_to_cpu(setup->wValue); - oz_trace("Clearing conn_port\n"); + oz_dbg(ON, "Clearing conn_port\n"); ozhcd->conn_port = -1; } spin_unlock_bh(&ozhcd->hcd_lock); complete = 1; break; case USB_REQ_SET_CONFIGURATION: - oz_trace("USB_REQ_SET_CONFIGURATION - req\n"); + oz_dbg(ON, "USB_REQ_SET_CONFIGURATION - req\n"); break; case USB_REQ_GET_CONFIGURATION: /* We short circuit this case and reply directly since * we have the selected configuration number cached. */ - oz_trace("USB_REQ_GET_CONFIGURATION - reply now\n"); + oz_dbg(ON, "USB_REQ_GET_CONFIGURATION - reply now\n"); if (urb->transfer_buffer_length >= 1) { urb->actual_length = 1; *((u8 *)urb->transfer_buffer) = @@ -1465,20 +1465,20 @@ static void oz_process_ep0_urb(struct oz_hcd *ozhcd, struct urb *urb, /* We short circuit this case and reply directly since * we have the selected interface alternative cached. */ - oz_trace("USB_REQ_GET_INTERFACE - reply now\n"); + oz_dbg(ON, "USB_REQ_GET_INTERFACE - reply now\n"); if (urb->transfer_buffer_length >= 1) { urb->actual_length = 1; *((u8 *)urb->transfer_buffer) = port->iface[(u8)windex].alt; - oz_trace("interface = %d alt = %d\n", - windex, port->iface[(u8)windex].alt); + oz_dbg(ON, "interface = %d alt = %d\n", + windex, port->iface[(u8)windex].alt); complete = 1; } else { rc = -EPIPE; } break; case USB_REQ_SET_INTERFACE: - oz_trace("USB_REQ_SET_INTERFACE - req\n"); + oz_dbg(ON, "USB_REQ_SET_INTERFACE - req\n"); break; } } @@ -1509,7 +1509,7 @@ static void oz_process_ep0_urb(struct oz_hcd *ozhcd, struct urb *urb, oz_usb_put(hpd); out: if (rc || complete) { - oz_trace("Completing request locally\n"); + oz_dbg(ON, "Completing request locally\n"); oz_complete_urb(ozhcd->hcd, urb, rc, 0); } else { oz_usb_request_heartbeat(port->hpd); @@ -1597,12 +1597,12 @@ static void oz_urb_cancel(struct oz_port *port, u8 ep_num, struct urb *urb) unsigned long irq_state; u8 ix; if (port == NULL) { - oz_trace("ERRORERROR: oz_urb_cancel(%p) port is null\n", urb); + oz_dbg(ON, "%s: ERROR: (%p) port is null\n", __func__, urb); return; } ozhcd = port->ozhcd; if (ozhcd == NULL) { - oz_trace("ERRORERROR: oz_urb_cancel(%p) ozhcd is null\n", urb); + oz_dbg(ON, "%s; ERROR: (%p) ozhcd is null\n", __func__, urb); return; } @@ -1627,7 +1627,7 @@ static void oz_urb_cancel(struct oz_port *port, u8 ep_num, struct urb *urb) urbl = container_of(e, struct oz_urb_link, link); if (urbl->urb == urb) { list_del(e); - oz_trace("Found urb in orphanage\n"); + oz_dbg(ON, "Found urb in orphanage\n"); goto out; } } @@ -1725,16 +1725,14 @@ static int oz_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, struct oz_port *port; unsigned long irq_state; struct oz_urb_link *urbl; - oz_trace2(OZ_TRACE_URB, "%lu: oz_hcd_urb_enqueue(%p)\n", - jiffies, urb); + oz_dbg(URB, "%lu: %s: (%p)\n", jiffies, __func__, urb); if (unlikely(ozhcd == NULL)) { - oz_trace2(OZ_TRACE_URB, "%lu: Refused urb(%p) not ozhcd.\n", - jiffies, urb); + oz_dbg(URB, "%lu: Refused urb(%p) not ozhcd\n", jiffies, urb); return -EPIPE; } if (unlikely(hcd->state != HC_STATE_RUNNING)) { - oz_trace2(OZ_TRACE_URB, "%lu: Refused urb(%p) not running.\n", - jiffies, urb); + oz_dbg(URB, "%lu: Refused urb(%p) not running\n", + jiffies, urb); return -EPIPE; } port_ix = oz_get_port_from_addr(ozhcd, urb->dev->devnum); @@ -1744,8 +1742,8 @@ static int oz_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, if (port == NULL) return -EPIPE; if ((port->flags & OZ_PORT_F_PRESENT) == 0) { - oz_trace("Refusing URB port_ix = %d devnum = %d\n", - port_ix, urb->dev->devnum); + oz_dbg(ON, "Refusing URB port_ix = %d devnum = %d\n", + port_ix, urb->dev->devnum); return -EPIPE; } urb->hcpriv = port; @@ -1802,7 +1800,7 @@ static int oz_hcd_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) struct oz_urb_link *urbl = NULL; int rc; unsigned long irq_state; - oz_trace2(OZ_TRACE_URB, "%lu: oz_hcd_urb_dequeue(%p)\n", jiffies, urb); + oz_dbg(URB, "%lu: %s: (%p)\n", jiffies, __func__, urb); urbl = oz_alloc_urb_link(); if (unlikely(urbl == NULL)) return -ENOMEM; @@ -1851,7 +1849,7 @@ static void oz_hcd_endpoint_reset(struct usb_hcd *hcd, */ static int oz_hcd_get_frame_number(struct usb_hcd *hcd) { - oz_trace("oz_hcd_get_frame_number\n"); + oz_dbg(ON, "oz_hcd_get_frame_number\n"); return oz_usb_get_frame_number(); } /*------------------------------------------------------------------------------ @@ -1869,7 +1867,7 @@ static int oz_hcd_hub_status_data(struct usb_hcd *hcd, char *buf) spin_lock_bh(&ozhcd->hcd_lock); for (i = 0; i < OZ_NB_PORTS; i++) { if (ozhcd->ports[i].flags & OZ_PORT_F_CHANGED) { - oz_trace2(OZ_TRACE_HUB, "Port %d changed\n", i); + oz_dbg(HUB, "Port %d changed\n", i); ozhcd->ports[i].flags &= ~OZ_PORT_F_CHANGED; buf[0] |= 1<<(i+1); } @@ -1907,53 +1905,53 @@ static int oz_set_port_feature(struct usb_hcd *hcd, u16 wvalue, u16 windex) port = &ozhcd->ports[port_id-1]; switch (wvalue) { case USB_PORT_FEAT_CONNECTION: - oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_CONNECTION\n"); + oz_dbg(HUB, "USB_PORT_FEAT_CONNECTION\n"); break; case USB_PORT_FEAT_ENABLE: - oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_ENABLE\n"); + oz_dbg(HUB, "USB_PORT_FEAT_ENABLE\n"); break; case USB_PORT_FEAT_SUSPEND: - oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_SUSPEND\n"); + oz_dbg(HUB, "USB_PORT_FEAT_SUSPEND\n"); break; case USB_PORT_FEAT_OVER_CURRENT: - oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_OVER_CURRENT\n"); + oz_dbg(HUB, "USB_PORT_FEAT_OVER_CURRENT\n"); break; case USB_PORT_FEAT_RESET: - oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_RESET\n"); + oz_dbg(HUB, "USB_PORT_FEAT_RESET\n"); set_bits = USB_PORT_STAT_ENABLE | (USB_PORT_STAT_C_RESET<<16); clear_bits = USB_PORT_STAT_RESET; ozhcd->ports[port_id-1].bus_addr = 0; break; case USB_PORT_FEAT_POWER: - oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_POWER\n"); + oz_dbg(HUB, "USB_PORT_FEAT_POWER\n"); set_bits |= USB_PORT_STAT_POWER; break; case USB_PORT_FEAT_LOWSPEED: - oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_LOWSPEED\n"); + oz_dbg(HUB, "USB_PORT_FEAT_LOWSPEED\n"); break; case USB_PORT_FEAT_C_CONNECTION: - oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_CONNECTION\n"); + oz_dbg(HUB, "USB_PORT_FEAT_C_CONNECTION\n"); break; case USB_PORT_FEAT_C_ENABLE: - oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_ENABLE\n"); + oz_dbg(HUB, "USB_PORT_FEAT_C_ENABLE\n"); break; case USB_PORT_FEAT_C_SUSPEND: - oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_SUSPEND\n"); + oz_dbg(HUB, "USB_PORT_FEAT_C_SUSPEND\n"); break; case USB_PORT_FEAT_C_OVER_CURRENT: - oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_OVER_CURRENT\n"); + oz_dbg(HUB, "USB_PORT_FEAT_C_OVER_CURRENT\n"); break; case USB_PORT_FEAT_C_RESET: - oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_RESET\n"); + oz_dbg(HUB, "USB_PORT_FEAT_C_RESET\n"); break; case USB_PORT_FEAT_TEST: - oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_TEST\n"); + oz_dbg(HUB, "USB_PORT_FEAT_TEST\n"); break; case USB_PORT_FEAT_INDICATOR: - oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_INDICATOR\n"); + oz_dbg(HUB, "USB_PORT_FEAT_INDICATOR\n"); break; default: - oz_trace2(OZ_TRACE_HUB, "Other %d\n", wvalue); + oz_dbg(HUB, "Other %d\n", wvalue); break; } if (set_bits || clear_bits) { @@ -1962,8 +1960,7 @@ static int oz_set_port_feature(struct usb_hcd *hcd, u16 wvalue, u16 windex) port->status |= set_bits; spin_unlock_bh(&port->port_lock); } - oz_trace2(OZ_TRACE_HUB, "Port[%d] status = 0x%x\n", port_id, - port->status); + oz_dbg(HUB, "Port[%d] status = 0x%x\n", port_id, port->status); return err; } /*------------------------------------------------------------------------------ @@ -1982,54 +1979,54 @@ static int oz_clear_port_feature(struct usb_hcd *hcd, u16 wvalue, u16 windex) port = &ozhcd->ports[port_id-1]; switch (wvalue) { case USB_PORT_FEAT_CONNECTION: - oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_CONNECTION\n"); + oz_dbg(HUB, "USB_PORT_FEAT_CONNECTION\n"); break; case USB_PORT_FEAT_ENABLE: - oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_ENABLE\n"); + oz_dbg(HUB, "USB_PORT_FEAT_ENABLE\n"); clear_bits = USB_PORT_STAT_ENABLE; break; case USB_PORT_FEAT_SUSPEND: - oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_SUSPEND\n"); + oz_dbg(HUB, "USB_PORT_FEAT_SUSPEND\n"); break; case USB_PORT_FEAT_OVER_CURRENT: - oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_OVER_CURRENT\n"); + oz_dbg(HUB, "USB_PORT_FEAT_OVER_CURRENT\n"); break; case USB_PORT_FEAT_RESET: - oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_RESET\n"); + oz_dbg(HUB, "USB_PORT_FEAT_RESET\n"); break; case USB_PORT_FEAT_POWER: - oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_POWER\n"); + oz_dbg(HUB, "USB_PORT_FEAT_POWER\n"); clear_bits |= USB_PORT_STAT_POWER; break; case USB_PORT_FEAT_LOWSPEED: - oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_LOWSPEED\n"); + oz_dbg(HUB, "USB_PORT_FEAT_LOWSPEED\n"); break; case USB_PORT_FEAT_C_CONNECTION: - oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_CONNECTION\n"); + oz_dbg(HUB, "USB_PORT_FEAT_C_CONNECTION\n"); clear_bits = (USB_PORT_STAT_C_CONNECTION << 16); break; case USB_PORT_FEAT_C_ENABLE: - oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_ENABLE\n"); + oz_dbg(HUB, "USB_PORT_FEAT_C_ENABLE\n"); clear_bits = (USB_PORT_STAT_C_ENABLE << 16); break; case USB_PORT_FEAT_C_SUSPEND: - oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_SUSPEND\n"); + oz_dbg(HUB, "USB_PORT_FEAT_C_SUSPEND\n"); break; case USB_PORT_FEAT_C_OVER_CURRENT: - oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_OVER_CURRENT\n"); + oz_dbg(HUB, "USB_PORT_FEAT_C_OVER_CURRENT\n"); break; case USB_PORT_FEAT_C_RESET: - oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_C_RESET\n"); + oz_dbg(HUB, "USB_PORT_FEAT_C_RESET\n"); clear_bits = (USB_PORT_FEAT_C_RESET << 16); break; case USB_PORT_FEAT_TEST: - oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_TEST\n"); + oz_dbg(HUB, "USB_PORT_FEAT_TEST\n"); break; case USB_PORT_FEAT_INDICATOR: - oz_trace2(OZ_TRACE_HUB, "USB_PORT_FEAT_INDICATOR\n"); + oz_dbg(HUB, "USB_PORT_FEAT_INDICATOR\n"); break; default: - oz_trace2(OZ_TRACE_HUB, "Other %d\n", wvalue); + oz_dbg(HUB, "Other %d\n", wvalue); break; } if (clear_bits) { @@ -2037,8 +2034,8 @@ static int oz_clear_port_feature(struct usb_hcd *hcd, u16 wvalue, u16 windex) port->status &= ~clear_bits; spin_unlock_bh(&port->port_lock); } - oz_trace2(OZ_TRACE_HUB, "Port[%d] status = 0x%x\n", port_id, - ozhcd->ports[port_id-1].status); + oz_dbg(HUB, "Port[%d] status = 0x%x\n", + port_id, ozhcd->ports[port_id-1].status); return err; } /*------------------------------------------------------------------------------ @@ -2051,10 +2048,10 @@ static int oz_get_port_status(struct usb_hcd *hcd, u16 windex, char *buf) if ((windex < 1) || (windex > OZ_NB_PORTS)) return -EPIPE; ozhcd = oz_hcd_private(hcd); - oz_trace2(OZ_TRACE_HUB, "GetPortStatus windex = %d\n", windex); + oz_dbg(HUB, "GetPortStatus windex = %d\n", windex); status = ozhcd->ports[windex-1].status; put_unaligned(cpu_to_le32(status), (__le32 *)buf); - oz_trace2(OZ_TRACE_HUB, "Port[%d] status = %x\n", windex, status); + oz_dbg(HUB, "Port[%d] status = %x\n", windex, status); return 0; } /*------------------------------------------------------------------------------ @@ -2067,7 +2064,7 @@ static int oz_hcd_hub_control(struct usb_hcd *hcd, u16 req_type, u16 wvalue, switch (req_type) { case ClearHubFeature: - oz_trace2(OZ_TRACE_HUB, "ClearHubFeature: %d\n", req_type); + oz_dbg(HUB, "ClearHubFeature: %d\n", req_type); break; case ClearPortFeature: err = oz_clear_port_feature(hcd, wvalue, windex); @@ -2076,21 +2073,20 @@ static int oz_hcd_hub_control(struct usb_hcd *hcd, u16 req_type, u16 wvalue, oz_get_hub_descriptor(hcd, (struct usb_hub_descriptor *)buf); break; case GetHubStatus: - oz_trace2(OZ_TRACE_HUB, "GetHubStatus: req_type = 0x%x\n", - req_type); + oz_dbg(HUB, "GetHubStatus: req_type = 0x%x\n", req_type); put_unaligned(__constant_cpu_to_le32(0), (__le32 *)buf); break; case GetPortStatus: err = oz_get_port_status(hcd, windex, buf); break; case SetHubFeature: - oz_trace2(OZ_TRACE_HUB, "SetHubFeature: %d\n", req_type); + oz_dbg(HUB, "SetHubFeature: %d\n", req_type); break; case SetPortFeature: err = oz_set_port_feature(hcd, wvalue, windex); break; default: - oz_trace2(OZ_TRACE_HUB, "Other: %d\n", req_type); + oz_dbg(HUB, "Other: %d\n", req_type); break; } return err; @@ -2141,7 +2137,7 @@ static int oz_plat_probe(struct platform_device *dev) hcd = usb_create_hcd(&g_oz_hc_drv, &dev->dev, dev_name(&dev->dev)); if (hcd == NULL) { - oz_trace("Failed to created hcd object OK\n"); + oz_dbg(ON, "Failed to created hcd object OK\n"); return -ENOMEM; } ozhcd = oz_hcd_private(hcd); @@ -2162,7 +2158,7 @@ static int oz_plat_probe(struct platform_device *dev) } err = usb_add_hcd(hcd, 0, 0); if (err) { - oz_trace("Failed to add hcd object OK\n"); + oz_dbg(ON, "Failed to add hcd object OK\n"); usb_put_hcd(hcd); return -1; } @@ -2186,14 +2182,15 @@ static int oz_plat_remove(struct platform_device *dev) if (ozhcd == g_ozhcd) g_ozhcd = NULL; spin_unlock_bh(&g_hcdlock); - oz_trace("Clearing orphanage\n"); + oz_dbg(ON, "Clearing orphanage\n"); oz_hcd_clear_orphanage(ozhcd, -EPIPE); - oz_trace("Removing hcd\n"); + oz_dbg(ON, "Removing hcd\n"); usb_remove_hcd(hcd); usb_put_hcd(hcd); oz_empty_link_pool(); return 0; } + /*------------------------------------------------------------------------------ * Context: unknown */ @@ -2201,6 +2198,7 @@ static int oz_plat_suspend(struct platform_device *dev, pm_message_t msg) { return 0; } + /*------------------------------------------------------------------------------ * Context: unknown */ @@ -2208,6 +2206,7 @@ static int oz_plat_resume(struct platform_device *dev) { return 0; } + /*------------------------------------------------------------------------------ * Context: process */ @@ -2219,7 +2218,7 @@ int oz_hcd_init(void) tasklet_init(&g_urb_process_tasklet, oz_urb_process_tasklet, 0); tasklet_init(&g_urb_cancel_tasklet, oz_urb_cancel_tasklet, 0); err = platform_driver_register(&g_oz_plat_drv); - oz_trace("platform_driver_register() returned %d\n", err); + oz_dbg(ON, "platform_driver_register() returned %d\n", err); if (err) goto error; g_plat_dev = platform_device_alloc(OZ_PLAT_DEV_NAME, -1); @@ -2227,11 +2226,11 @@ int oz_hcd_init(void) err = -ENOMEM; goto error1; } - oz_trace("platform_device_alloc() succeeded\n"); + oz_dbg(ON, "platform_device_alloc() succeeded\n"); err = platform_device_add(g_plat_dev); if (err) goto error2; - oz_trace("platform_device_add() succeeded\n"); + oz_dbg(ON, "platform_device_add() succeeded\n"); return 0; error2: platform_device_put(g_plat_dev); @@ -2240,7 +2239,7 @@ error1: error: tasklet_disable(&g_urb_process_tasklet); tasklet_disable(&g_urb_cancel_tasklet); - oz_trace("oz_hcd_init() failed %d\n", err); + oz_dbg(ON, "oz_hcd_init() failed %d\n", err); return err; } /*------------------------------------------------------------------------------ @@ -2252,5 +2251,5 @@ void oz_hcd_term(void) tasklet_kill(&g_urb_cancel_tasklet); platform_device_unregister(g_plat_dev); platform_driver_unregister(&g_oz_plat_drv); - oz_trace("Pending urbs:%d\n", atomic_read(&g_pending_urbs)); + oz_dbg(ON, "Pending urbs:%d\n", atomic_read(&g_pending_urbs)); } diff --git a/drivers/staging/ozwpan/ozpd.c b/drivers/staging/ozwpan/ozpd.c index d67dff2430ad..28adbb47764a 100644 --- a/drivers/staging/ozwpan/ozpd.c +++ b/drivers/staging/ozwpan/ozpd.c @@ -9,6 +9,7 @@ #include #include #include +#include "ozdbg.h" #include "ozconfig.h" #include "ozprotocol.h" #include "ozeltbuf.h" @@ -123,16 +124,16 @@ void oz_pd_set_state(struct oz_pd *pd, unsigned state) #ifdef WANT_TRACE switch (state) { case OZ_PD_S_IDLE: - oz_trace("PD State: OZ_PD_S_IDLE\n"); + oz_pd_dbg(pd, ON, "PD State: OZ_PD_S_IDLE\n"); break; case OZ_PD_S_CONNECTED: - oz_trace("PD State: OZ_PD_S_CONNECTED\n"); + oz_pd_dbg(pd, ON, "PD State: OZ_PD_S_CONNECTED\n"); break; case OZ_PD_S_STOPPED: - oz_trace("PD State: OZ_PD_S_STOPPED\n"); + oz_pd_dbg(pd, ON, "PD State: OZ_PD_S_STOPPED\n"); break; case OZ_PD_S_SLEEP: - oz_trace("PD State: OZ_PD_S_SLEEP\n"); + oz_pd_dbg(pd, ON, "PD State: OZ_PD_S_SLEEP\n"); break; } #endif /* WANT_TRACE */ @@ -189,7 +190,7 @@ void oz_pd_destroy(struct oz_pd *pd) struct oz_tx_frame *f; struct oz_isoc_stream *st; struct oz_farewell *fwell; - oz_trace("Destroying PD\n"); + oz_pd_dbg(pd, ON, "Destroying PD\n"); /* Delete any streams. */ e = pd->stream_list.next; @@ -235,13 +236,14 @@ int oz_services_start(struct oz_pd *pd, u16 apps, int resume) { const struct oz_app_if *ai; int rc = 0; - oz_trace("oz_services_start(0x%x) resume(%d)\n", apps, resume); + oz_pd_dbg(pd, ON, "%s: (0x%x) resume(%d)\n", __func__, apps, resume); for (ai = g_app_if; ai < &g_app_if[OZ_APPID_MAX]; ai++) { if (apps & (1<app_id)) { if (ai->start(pd, resume)) { rc = -1; - oz_trace("Unabled to start service %d\n", - ai->app_id); + oz_pd_dbg(pd, ON, + "Unable to start service %d\n", + ai->app_id); break; } oz_polling_lock_bh(); @@ -259,7 +261,7 @@ int oz_services_start(struct oz_pd *pd, u16 apps, int resume) void oz_services_stop(struct oz_pd *pd, u16 apps, int pause) { const struct oz_app_if *ai; - oz_trace("oz_stop_services(0x%x) pause(%d)\n", apps, pause); + oz_pd_dbg(pd, ON, "%s: (0x%x) pause(%d)\n", __func__, apps, pause); for (ai = g_app_if; ai < &g_app_if[OZ_APPID_MAX]; ai++) { if (apps & (1<app_id)) { oz_polling_lock_bh(); @@ -301,7 +303,7 @@ void oz_pd_heartbeat(struct oz_pd *pd, u16 apps) void oz_pd_stop(struct oz_pd *pd) { u16 stop_apps = 0; - oz_trace("oz_pd_stop() State = 0x%x\n", pd->state); + oz_dbg(ON, "oz_pd_stop() State = 0x%x\n", pd->state); oz_pd_indicate_farewells(pd); oz_polling_lock_bh(); stop_apps = pd->total_apps; @@ -314,7 +316,7 @@ void oz_pd_stop(struct oz_pd *pd) /* Remove from PD list.*/ list_del(&pd->link); oz_polling_unlock_bh(); - oz_trace("pd ref count = %d\n", atomic_read(&pd->ref_count)); + oz_dbg(ON, "pd ref count = %d\n", atomic_read(&pd->ref_count)); oz_timer_delete(pd, 0); oz_pd_put(pd); } @@ -333,8 +335,8 @@ int oz_pd_sleep(struct oz_pd *pd) if (pd->keep_alive_j && pd->session_id) { oz_pd_set_state(pd, OZ_PD_S_SLEEP); pd->pulse_time_j = jiffies + pd->keep_alive_j; - oz_trace("Sleep Now %lu until %lu\n", - jiffies, pd->pulse_time_j); + oz_dbg(ON, "Sleep Now %lu until %lu\n", + jiffies, pd->pulse_time_j); } else { do_stop = 1; } @@ -384,8 +386,8 @@ static void oz_tx_isoc_free(struct oz_pd *pd, struct oz_tx_frame *f) } else { kfree(f); } - oz_trace2(OZ_TRACE_TX_FRAMES, "Releasing ISOC Frame isoc_nb= %d\n", - pd->nb_queued_isoc_frames); + oz_dbg(TX_FRAMES, "Releasing ISOC Frame isoc_nb= %d\n", + pd->nb_queued_isoc_frames); } /*------------------------------------------------------------------------------ * Context: softirq or process @@ -540,18 +542,16 @@ static int oz_send_next_queued_frame(struct oz_pd *pd, int more_data) if ((int)atomic_read(&g_submitted_isoc) < OZ_MAX_SUBMITTED_ISOC) { if (dev_queue_xmit(skb) < 0) { - oz_trace2(OZ_TRACE_TX_FRAMES, - "Dropping ISOC Frame\n"); + oz_dbg(TX_FRAMES, "Dropping ISOC Frame\n"); return -1; } atomic_inc(&g_submitted_isoc); - oz_trace2(OZ_TRACE_TX_FRAMES, - "Sending ISOC Frame, nb_isoc= %d\n", - pd->nb_queued_isoc_frames); + oz_dbg(TX_FRAMES, "Sending ISOC Frame, nb_isoc= %d\n", + pd->nb_queued_isoc_frames); return 0; } else { kfree_skb(skb); - oz_trace2(OZ_TRACE_TX_FRAMES, "Dropping ISOC Frame>\n"); + oz_dbg(TX_FRAMES, "Dropping ISOC Frame>\n"); return -1; } } @@ -561,7 +561,7 @@ static int oz_send_next_queued_frame(struct oz_pd *pd, int more_data) spin_unlock(&pd->tx_frame_lock); if (more_data) oz_set_more_bit(skb); - oz_trace2(OZ_TRACE_TX_FRAMES, "TX frame PN=0x%x\n", f->hdr.pkt_num); + oz_dbg(TX_FRAMES, "TX frame PN=0x%x\n", f->hdr.pkt_num); if (skb) { if (dev_queue_xmit(skb) < 0) return -1; @@ -627,7 +627,7 @@ static int oz_send_isoc_frame(struct oz_pd *pd) return 0; skb = alloc_skb(total_size + OZ_ALLOCATED_SPACE(dev), GFP_ATOMIC); if (skb == NULL) { - oz_trace("Cannot alloc skb\n"); + oz_dbg(ON, "Cannot alloc skb\n"); oz_elt_info_free_chain(&pd->elt_buff, &list); return -1; } @@ -675,8 +675,8 @@ void oz_retire_tx_frames(struct oz_pd *pd, u8 lpn) diff = (lpn - (pkt_num & OZ_LAST_PN_MASK)) & OZ_LAST_PN_MASK; if ((diff > OZ_LAST_PN_HALF_CYCLE) || (pkt_num == 0)) break; - oz_trace2(OZ_TRACE_TX_FRAMES, "Releasing pkt_num= %u, nb= %d\n", - pkt_num, pd->nb_queued_frames); + oz_dbg(TX_FRAMES, "Releasing pkt_num= %u, nb= %d\n", + pkt_num, pd->nb_queued_frames); if (first == NULL) first = e; last = e; @@ -835,9 +835,8 @@ int oz_send_isoc_unit(struct oz_pd *pd, u8 ep_num, const u8 *data, int len) struct oz_tx_frame *isoc_unit = NULL; int nb = pd->nb_queued_isoc_frames; if (nb >= pd->isoc_latency) { - oz_trace2(OZ_TRACE_TX_FRAMES, - "Dropping ISOC Unit nb= %d\n", - nb); + oz_dbg(TX_FRAMES, "Dropping ISOC Unit nb= %d\n", + nb); goto out; } isoc_unit = oz_tx_frame_alloc(pd); @@ -849,9 +848,9 @@ int oz_send_isoc_unit(struct oz_pd *pd, u8 ep_num, const u8 *data, int len) list_add_tail(&isoc_unit->link, &pd->tx_queue); pd->nb_queued_isoc_frames++; spin_unlock_bh(&pd->tx_frame_lock); - oz_trace2(OZ_TRACE_TX_FRAMES, - "Added ISOC Frame to Tx Queue isoc_nb= %d, nb= %d\n", - pd->nb_queued_isoc_frames, pd->nb_queued_frames); + oz_dbg(TX_FRAMES, + "Added ISOC Frame to Tx Queue isoc_nb= %d, nb= %d\n", + pd->nb_queued_isoc_frames, pd->nb_queued_frames); return 0; } diff --git a/drivers/staging/ozwpan/ozproto.c b/drivers/staging/ozwpan/ozproto.c index 79ac7b51d5b2..494236ed4488 100644 --- a/drivers/staging/ozwpan/ozproto.c +++ b/drivers/staging/ozwpan/ozproto.c @@ -10,6 +10,7 @@ #include #include #include +#include "ozdbg.h" #include "ozconfig.h" #include "ozprotocol.h" #include "ozeltbuf.h" @@ -124,7 +125,7 @@ static void oz_send_conn_rsp(struct oz_pd *pd, u8 status) body->session_id = pd->session_id; put_unaligned(cpu_to_le16(pd->total_apps), &body->apps); } - oz_trace("TX: OZ_ELT_CONNECT_RSP %d", status); + oz_dbg(ON, "TX: OZ_ELT_CONNECT_RSP %d", status); dev_queue_xmit(skb); return; } @@ -152,7 +153,7 @@ static void pd_set_keepalive(struct oz_pd *pd, u8 kalive) default: pd->keep_alive_j = 0; } - oz_trace("Keepalive = %lu jiffies\n", pd->keep_alive_j); + oz_dbg(ON, "Keepalive = %lu jiffies\n", pd->keep_alive_j); } /*------------------------------------------------------------------------------ * Context: softirq-serialized @@ -163,7 +164,7 @@ static void pd_set_presleep(struct oz_pd *pd, u8 presleep) pd->presleep_j = oz_ms_to_jiffies(presleep*100); else pd->presleep_j = OZ_PRESLEEP_TOUT_J; - oz_trace("Presleep time = %lu jiffies\n", pd->presleep_j); + oz_dbg(ON, "Presleep time = %lu jiffies\n", pd->presleep_j); } /*------------------------------------------------------------------------------ * Context: softirq-serialized @@ -210,7 +211,7 @@ static struct oz_pd *oz_connect_req(struct oz_pd *cur_pd, struct oz_elt *elt, dev_hold(net_dev); pd->net_dev = net_dev; } - oz_trace("Host vendor: %d\n", body->host_vendor); + oz_dbg(ON, "Host vendor: %d\n", body->host_vendor); pd->max_tx_size = OZ_MAX_TX_SIZE; pd->mode = body->mode; pd->pd_info = body->pd_info; @@ -234,8 +235,8 @@ static struct oz_pd *oz_connect_req(struct oz_pd *cur_pd, struct oz_elt *elt, } if (body->max_len_div16) pd->max_tx_size = ((u16)body->max_len_div16)<<4; - oz_trace("Max frame:%u Ms per isoc:%u\n", - pd->max_tx_size, pd->ms_per_isoc); + oz_dbg(ON, "Max frame:%u Ms per isoc:%u\n", + pd->max_tx_size, pd->ms_per_isoc); pd->max_stream_buffering = 3*1024; pd->timeout_time_j = jiffies + OZ_CONNECTION_TOUT_J; pd->pulse_period_j = OZ_QUANTUM_J; @@ -272,8 +273,8 @@ done: spin_unlock_bh(&g_polling_lock); oz_pd_set_state(pd, OZ_PD_S_CONNECTED); oz_timer_delete(pd, OZ_TIMER_STOP); - oz_trace("new_apps=0x%x total_apps=0x%x paused_apps=0x%x\n", - new_apps, pd->total_apps, pd->paused_apps); + oz_dbg(ON, "new_apps=0x%x total_apps=0x%x paused_apps=0x%x\n", + new_apps, pd->total_apps, pd->paused_apps); if (start_apps) { if (oz_services_start(pd, start_apps, 0)) rsp_status = OZ_STATUS_TOO_MANY_PDS; @@ -315,7 +316,7 @@ static void oz_add_farewell(struct oz_pd *pd, u8 ep_num, u8 index, f->ep_num = ep_num; f->index = index; memcpy(f->report, report, len); - oz_trace("RX: Adding farewell report\n"); + oz_dbg(ON, "RX: Adding farewell report\n"); spin_lock(&g_polling_lock); list_for_each_entry(f2, &pd->farewell_list, link) { if ((f2->ep_num == ep_num) && (f2->index == index)) { @@ -343,17 +344,16 @@ static void oz_rx_frame(struct sk_buff *skb) int dup = 0; u32 pkt_num; - oz_trace2(OZ_TRACE_RX_FRAMES, - "RX frame PN=0x%x LPN=0x%x control=0x%x\n", - oz_hdr->pkt_num, oz_hdr->last_pkt_num, oz_hdr->control); + oz_dbg(RX_FRAMES, "RX frame PN=0x%x LPN=0x%x control=0x%x\n", + oz_hdr->pkt_num, oz_hdr->last_pkt_num, oz_hdr->control); mac_hdr = skb_mac_header(skb); src_addr = &mac_hdr[ETH_ALEN] ; length = skb->len; /* Check the version field */ if (oz_get_prot_ver(oz_hdr->control) != OZ_PROTOCOL_VERSION) { - oz_trace("Incorrect protocol version: %d\n", - oz_get_prot_ver(oz_hdr->control)); + oz_dbg(ON, "Incorrect protocol version: %d\n", + oz_get_prot_ver(oz_hdr->control)); goto done; } @@ -368,12 +368,12 @@ static void oz_rx_frame(struct sk_buff *skb) pd->last_rx_pkt_num = pkt_num; } else { dup = 1; - oz_trace("Duplicate frame\n"); + oz_dbg(ON, "Duplicate frame\n"); } } if (pd && !dup && ((pd->mode & OZ_MODE_MASK) == OZ_MODE_TRIGGERED)) { - oz_trace2(OZ_TRACE_RX_FRAMES, "Received TRIGGER Frame\n"); + oz_dbg(RX_FRAMES, "Received TRIGGER Frame\n"); pd->last_sent_frame = &pd->tx_queue; if (oz_hdr->control & OZ_F_ACK) { /* Retire completed frames */ @@ -397,18 +397,18 @@ static void oz_rx_frame(struct sk_buff *skb) break; switch (elt->type) { case OZ_ELT_CONNECT_REQ: - oz_trace("RX: OZ_ELT_CONNECT_REQ\n"); + oz_dbg(ON, "RX: OZ_ELT_CONNECT_REQ\n"); pd = oz_connect_req(pd, elt, src_addr, skb->dev); break; case OZ_ELT_DISCONNECT: - oz_trace("RX: OZ_ELT_DISCONNECT\n"); + oz_dbg(ON, "RX: OZ_ELT_DISCONNECT\n"); if (pd) oz_pd_sleep(pd); break; case OZ_ELT_UPDATE_PARAM_REQ: { struct oz_elt_update_param *body = (struct oz_elt_update_param *)(elt + 1); - oz_trace("RX: OZ_ELT_UPDATE_PARAM_REQ\n"); + oz_dbg(ON, "RX: OZ_ELT_UPDATE_PARAM_REQ\n"); if (pd && (pd->state & OZ_PD_S_CONNECTED)) { spin_lock(&g_polling_lock); pd_set_keepalive(pd, body->keepalive); @@ -420,7 +420,7 @@ static void oz_rx_frame(struct sk_buff *skb) case OZ_ELT_FAREWELL_REQ: { struct oz_elt_farewell *body = (struct oz_elt_farewell *)(elt + 1); - oz_trace("RX: OZ_ELT_FAREWELL_REQ\n"); + oz_dbg(ON, "RX: OZ_ELT_FAREWELL_REQ\n"); oz_add_farewell(pd, body->ep_num, body->index, body->report, elt->length + 1 - sizeof(*body)); @@ -436,7 +436,7 @@ static void oz_rx_frame(struct sk_buff *skb) } break; default: - oz_trace("RX: Unknown elt %02x\n", elt->type); + oz_dbg(ON, "RX: Unknown elt %02x\n", elt->type); } elt = oz_next_elt(elt); } @@ -488,7 +488,7 @@ void oz_protocol_term(void) chain = chain->next; kfree(t); } - oz_trace("Protocol stopped\n"); + oz_dbg(ON, "Protocol stopped\n"); } /*------------------------------------------------------------------------------ * Context: softirq @@ -583,7 +583,7 @@ static void oz_protocol_timer_start(void) } g_timer_state = OZ_TIMER_SET; } else { - oz_trace("No queued timers\n"); + oz_dbg(ON, "No queued timers\n"); } spin_unlock_bh(&g_polling_lock); } @@ -795,16 +795,16 @@ void oz_binding_add(char *net_dev) binding->ptype.func = oz_pkt_recv; memcpy(binding->name, net_dev, OZ_MAX_BINDING_LEN); if (net_dev && *net_dev) { - oz_trace("Adding binding: %s\n", net_dev); + oz_dbg(ON, "Adding binding: %s\n", net_dev); binding->ptype.dev = dev_get_by_name(&init_net, net_dev); if (binding->ptype.dev == NULL) { - oz_trace("Netdev %s not found\n", net_dev); + oz_dbg(ON, "Netdev %s not found\n", net_dev); kfree(binding); binding = NULL; } } else { - oz_trace("Binding to all netcards\n"); + oz_dbg(ON, "Binding to all netcards\n"); binding->ptype.dev = NULL; } if (binding) { @@ -861,13 +861,13 @@ void oz_binding_remove(char *net_dev) { struct oz_binding *binding; struct oz_binding **link; - oz_trace("Removing binding: %s\n", net_dev); + oz_dbg(ON, "Removing binding: %s\n", net_dev); spin_lock_bh(&g_binding_lock); binding = g_binding; link = &g_binding; while (binding) { if (compare_binding_name(binding->name, net_dev)) { - oz_trace("Binding '%s' found\n", net_dev); + oz_dbg(ON, "Binding '%s' found\n", net_dev); *link = binding->next; break; } else { diff --git a/drivers/staging/ozwpan/ozproto.h b/drivers/staging/ozwpan/ozproto.h index 93bb4c0172e0..9bb0a6abfc88 100644 --- a/drivers/staging/ozwpan/ozproto.h +++ b/drivers/staging/ozwpan/ozproto.h @@ -7,7 +7,7 @@ #define _OZPROTO_H #include -#include "ozconfig.h" +#include "ozdbg.h" #include "ozappif.h" #define OZ_ALLOCATED_SPACE(__x) (LL_RESERVED_SPACE(__x)+(__x)->needed_tailroom) diff --git a/drivers/staging/ozwpan/ozurbparanoia.c b/drivers/staging/ozwpan/ozurbparanoia.c index 55b9afbbe47b..387d9dac5fe0 100644 --- a/drivers/staging/ozwpan/ozurbparanoia.c +++ b/drivers/staging/ozwpan/ozurbparanoia.c @@ -4,6 +4,7 @@ * ----------------------------------------------------------------------------- */ #include +#include "ozdbg.h" #include "ozconfig.h" #ifdef WANT_URB_PARANOIA #include "ozurbparanoia.h" @@ -22,9 +23,9 @@ void oz_remember_urb(struct urb *urb) spin_lock_irqsave(&g_urb_mem_lock, irq_state); if (g_nb_urbs < OZ_MAX_URBS) { g_urb_memory[g_nb_urbs++] = urb; - oz_trace("%lu: urb up = %d %p\n", jiffies, g_nb_urbs, urb); + oz_dbg(ON, "%lu: urb up = %d %p\n", jiffies, g_nb_urbs, urb); } else { - oz_trace("ERROR urb buffer full\n"); + oz_dbg(ON, "ERROR urb buffer full\n"); } spin_unlock_irqrestore(&g_urb_mem_lock, irq_state); } @@ -42,8 +43,8 @@ int oz_forget_urb(struct urb *urb) if (--g_nb_urbs > i) memcpy(&g_urb_memory[i], &g_urb_memory[i+1], (g_nb_urbs - i) * sizeof(struct urb *)); - oz_trace("%lu: urb down = %d %p\n", - jiffies, g_nb_urbs, urb); + oz_dbg(ON, "%lu: urb down = %d %p\n", + jiffies, g_nb_urbs, urb); } } spin_unlock_irqrestore(&g_urb_mem_lock, irq_state); diff --git a/drivers/staging/ozwpan/ozusbsvc.c b/drivers/staging/ozwpan/ozusbsvc.c index 167632878249..b4aebdbd715d 100644 --- a/drivers/staging/ozwpan/ozusbsvc.c +++ b/drivers/staging/ozwpan/ozusbsvc.c @@ -18,6 +18,7 @@ #include #include #include +#include "ozdbg.h" #include "ozconfig.h" #include "ozprotocol.h" #include "ozeltbuf.h" @@ -53,10 +54,10 @@ int oz_usb_start(struct oz_pd *pd, int resume) struct oz_usb_ctx *usb_ctx; struct oz_usb_ctx *old_ctx; if (resume) { - oz_trace("USB service resumed.\n"); + oz_dbg(ON, "USB service resumed\n"); return 0; } - oz_trace("USB service started.\n"); + oz_dbg(ON, "USB service started\n"); /* Create a USB context in case we need one. If we find the PD already * has a USB context then we will destroy it. */ @@ -77,7 +78,7 @@ int oz_usb_start(struct oz_pd *pd, int resume) oz_usb_get(pd->app_ctx[OZ_APPID_USB-1]); spin_unlock_bh(&pd->app_lock[OZ_APPID_USB-1]); if (old_ctx) { - oz_trace("Already have USB context.\n"); + oz_dbg(ON, "Already have USB context\n"); kfree(usb_ctx); usb_ctx = old_ctx; } else if (usb_ctx) { @@ -95,7 +96,7 @@ int oz_usb_start(struct oz_pd *pd, int resume) } else { usb_ctx->hport = oz_hcd_pd_arrived(usb_ctx); if (usb_ctx->hport == NULL) { - oz_trace("USB hub returned null port.\n"); + oz_dbg(ON, "USB hub returned null port\n"); spin_lock_bh(&pd->app_lock[OZ_APPID_USB-1]); pd->app_ctx[OZ_APPID_USB-1] = NULL; spin_unlock_bh(&pd->app_lock[OZ_APPID_USB-1]); @@ -114,7 +115,7 @@ void oz_usb_stop(struct oz_pd *pd, int pause) { struct oz_usb_ctx *usb_ctx; if (pause) { - oz_trace("USB service paused.\n"); + oz_dbg(ON, "USB service paused\n"); return; } spin_lock_bh(&pd->app_lock[OZ_APPID_USB-1]); @@ -123,7 +124,7 @@ void oz_usb_stop(struct oz_pd *pd, int pause) spin_unlock_bh(&pd->app_lock[OZ_APPID_USB-1]); if (usb_ctx) { unsigned long tout = jiffies + HZ; - oz_trace("USB service stopping...\n"); + oz_dbg(ON, "USB service stopping...\n"); usb_ctx->stopped = 1; /* At this point the reference count on the usb context should * be 2 - one from when we created it and one from the hcd @@ -134,7 +135,7 @@ void oz_usb_stop(struct oz_pd *pd, int pause) while ((atomic_read(&usb_ctx->ref_count) > 2) && time_before(jiffies, tout)) ; - oz_trace("USB service stopped.\n"); + oz_dbg(ON, "USB service stopped\n"); oz_hcd_pd_departed(usb_ctx->hport); /* Release the reference taken in oz_usb_start. */ @@ -160,7 +161,7 @@ void oz_usb_put(void *hpd) { struct oz_usb_ctx *usb_ctx = (struct oz_usb_ctx *)hpd; if (atomic_dec_and_test(&usb_ctx->ref_count)) { - oz_trace("Dealloc USB context.\n"); + oz_dbg(ON, "Dealloc USB context\n"); oz_pd_put(usb_ctx->pd); kfree(usb_ctx); } @@ -195,7 +196,7 @@ int oz_usb_stream_create(void *hpd, u8 ep_num) { struct oz_usb_ctx *usb_ctx = (struct oz_usb_ctx *)hpd; struct oz_pd *pd = usb_ctx->pd; - oz_trace("oz_usb_stream_create(0x%x)\n", ep_num); + oz_dbg(ON, "%s: (0x%x)\n", __func__, ep_num); if (pd->mode & OZ_F_ISOC_NO_ELTS) { oz_isoc_stream_create(pd, ep_num); } else { @@ -217,7 +218,7 @@ int oz_usb_stream_delete(void *hpd, u8 ep_num) if (usb_ctx) { struct oz_pd *pd = usb_ctx->pd; if (pd) { - oz_trace("oz_usb_stream_delete(0x%x)\n", ep_num); + oz_dbg(ON, "%s: (0x%x)\n", __func__, ep_num); if (pd->mode & OZ_F_ISOC_NO_ELTS) { oz_isoc_stream_delete(pd, ep_num); } else { diff --git a/drivers/staging/ozwpan/ozusbsvc1.c b/drivers/staging/ozwpan/ozusbsvc1.c index 16e607875c38..ab2c641dffe6 100644 --- a/drivers/staging/ozwpan/ozusbsvc1.c +++ b/drivers/staging/ozwpan/ozusbsvc1.c @@ -13,6 +13,7 @@ #include #include #include +#include "ozdbg.h" #include "ozconfig.h" #include "ozprotocol.h" #include "ozeltbuf.h" @@ -62,12 +63,12 @@ int oz_usb_get_desc_req(void *hpd, u8 req_id, u8 req_type, u8 desc_type, struct oz_get_desc_req *body; struct oz_elt_buf *eb = &pd->elt_buff; struct oz_elt_info *ei = oz_elt_info_alloc(&pd->elt_buff); - oz_trace(" req_type = 0x%x\n", req_type); - oz_trace(" desc_type = 0x%x\n", desc_type); - oz_trace(" index = 0x%x\n", index); - oz_trace(" windex = 0x%x\n", windex); - oz_trace(" offset = 0x%x\n", offset); - oz_trace(" len = 0x%x\n", len); + oz_dbg(ON, " req_type = 0x%x\n", req_type); + oz_dbg(ON, " desc_type = 0x%x\n", desc_type); + oz_dbg(ON, " index = 0x%x\n", index); + oz_dbg(ON, " windex = 0x%x\n", windex); + oz_dbg(ON, " offset = 0x%x\n", offset); + oz_dbg(ON, " len = 0x%x\n", len); if (len > 200) len = 200; if (ei == NULL) @@ -376,7 +377,7 @@ void oz_usb_rx(struct oz_pd *pd, struct oz_elt *elt) u16 offs = le16_to_cpu(get_unaligned(&body->offset)); u16 total_size = le16_to_cpu(get_unaligned(&body->total_size)); - oz_trace("USB_REQ_GET_DESCRIPTOR - cnf\n"); + oz_dbg(ON, "USB_REQ_GET_DESCRIPTOR - cnf\n"); oz_hcd_get_desc_cnf(usb_ctx->hport, body->req_id, body->rcode, body->data, data_len, offs, total_size); @@ -425,7 +426,7 @@ void oz_usb_farewell(struct oz_pd *pd, u8 ep_num, u8 *data, u8 len) if (usb_ctx == NULL) return; /* Context has gone so nothing to do. */ if (!usb_ctx->stopped) { - oz_trace("Farewell indicated ep = 0x%x\n", ep_num); + oz_dbg(ON, "Farewell indicated ep = 0x%x\n", ep_num); oz_hcd_data_ind(usb_ctx->hport, ep_num, data, len); } oz_usb_put(usb_ctx); From 05f608f237dcc3c4e5188d054d9918cbfd2916c2 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 23 Jul 2013 13:45:01 +0100 Subject: [PATCH 0384/3400] staging: ozwpan: Remove old debug macro. Remove old oz_trace & oz_trace2 macro & related header files. Signed-off-by: Joe Perches Signed-off-by: Rupesh Gujare Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ozwpan/Kbuild | 6 ++--- drivers/staging/ozwpan/ozcdev.c | 2 -- drivers/staging/ozwpan/ozconfig.h | 26 ------------------- drivers/staging/ozwpan/ozeltbuf.c | 2 -- drivers/staging/ozwpan/ozhcd.c | 7 +---- drivers/staging/ozwpan/ozmain.c | 7 +++-- drivers/staging/ozwpan/ozpd.c | 6 ++--- drivers/staging/ozwpan/ozproto.c | 4 +-- drivers/staging/ozwpan/oztrace.c | 36 -------------------------- drivers/staging/ozwpan/oztrace.h | 35 ------------------------- drivers/staging/ozwpan/ozurbparanoia.c | 5 ++-- drivers/staging/ozwpan/ozusbsvc.c | 4 +-- drivers/staging/ozwpan/ozusbsvc1.c | 2 -- 13 files changed, 17 insertions(+), 125 deletions(-) delete mode 100644 drivers/staging/ozwpan/ozconfig.h delete mode 100644 drivers/staging/ozwpan/oztrace.c delete mode 100644 drivers/staging/ozwpan/oztrace.h diff --git a/drivers/staging/ozwpan/Kbuild b/drivers/staging/ozwpan/Kbuild index 1766a268d5f6..29529c1a8e3c 100644 --- a/drivers/staging/ozwpan/Kbuild +++ b/drivers/staging/ozwpan/Kbuild @@ -2,6 +2,7 @@ # Copyright (c) 2011 Ozmo Inc # Released under the GNU General Public License Version 2 (GPLv2). # ----------------------------------------------------------------------------- + obj-$(CONFIG_USB_WPAN_HCD) += ozwpan.o ozwpan-y := \ ozmain.o \ @@ -12,7 +13,4 @@ ozwpan-y := \ ozeltbuf.o \ ozproto.o \ ozcdev.o \ - ozurbparanoia.o \ - oztrace.o - - + ozurbparanoia.o diff --git a/drivers/staging/ozwpan/ozcdev.c b/drivers/staging/ozwpan/ozcdev.c index 87c3131f5b9f..3e29760ba77e 100644 --- a/drivers/staging/ozwpan/ozcdev.c +++ b/drivers/staging/ozwpan/ozcdev.c @@ -11,10 +11,8 @@ #include #include #include -#include "ozconfig.h" #include "ozdbg.h" #include "ozprotocol.h" -#include "oztrace.h" #include "ozappif.h" #include "ozeltbuf.h" #include "ozpd.h" diff --git a/drivers/staging/ozwpan/ozconfig.h b/drivers/staging/ozwpan/ozconfig.h deleted file mode 100644 index 087c322d2de0..000000000000 --- a/drivers/staging/ozwpan/ozconfig.h +++ /dev/null @@ -1,26 +0,0 @@ -/* ----------------------------------------------------------------------------- - * Copyright (c) 2011 Ozmo Inc - * Released under the GNU General Public License Version 2 (GPLv2). - * ---------------------------------------------------------------------------*/ -#ifndef _OZCONFIG_H -#define _OZCONFIG_H - -/* #define WANT_TRACE */ -#ifdef WANT_TRACE -#define WANT_VERBOSE_TRACE -#endif /* #ifdef WANT_TRACE */ -/* #define WANT_URB_PARANOIA */ - -/* #define WANT_PRE_2_6_39 */ - -/* These defines determine what verbose trace is displayed. */ -#ifdef WANT_VERBOSE_TRACE -/* #define WANT_TRACE_STREAM */ -/* #define WANT_TRACE_URB */ -/* #define WANT_TRACE_CTRL_DETAIL */ -#define WANT_TRACE_HUB -/* #define WANT_TRACE_RX_FRAMES */ -/* #define WANT_TRACE_TX_FRAMES */ -#endif /* WANT_VERBOSE_TRACE */ - -#endif /* _OZCONFIG_H */ diff --git a/drivers/staging/ozwpan/ozeltbuf.c b/drivers/staging/ozwpan/ozeltbuf.c index bf280aabe383..5e98aeb8bc6b 100644 --- a/drivers/staging/ozwpan/ozeltbuf.c +++ b/drivers/staging/ozwpan/ozeltbuf.c @@ -6,12 +6,10 @@ #include #include #include -#include "ozconfig.h" #include "ozdbg.h" #include "ozprotocol.h" #include "ozeltbuf.h" #include "ozpd.h" -#include "oztrace.h" /*------------------------------------------------------------------------------ */ diff --git a/drivers/staging/ozwpan/ozhcd.c b/drivers/staging/ozwpan/ozhcd.c index fece2dab3ae9..6b16bfc4cdd8 100644 --- a/drivers/staging/ozwpan/ozhcd.c +++ b/drivers/staging/ozwpan/ozhcd.c @@ -32,9 +32,7 @@ #include "linux/usb/hcd.h" #include #include "ozdbg.h" -#include "ozconfig.h" #include "ozusbif.h" -#include "oztrace.h" #include "ozurbparanoia.h" #include "ozhcd.h" /*------------------------------------------------------------------------------ @@ -797,7 +795,6 @@ void oz_hcd_get_desc_cnf(void *hport, u8 req_id, int status, const u8 *desc, /*------------------------------------------------------------------------------ * Context: softirq */ -#ifdef WANT_TRACE static void oz_display_conf_type(u8 t) { switch (t) { @@ -836,9 +833,7 @@ static void oz_display_conf_type(u8 t) break; } } -#else -#define oz_display_conf_type(__x) -#endif /* WANT_TRACE */ + /*------------------------------------------------------------------------------ * Context: softirq */ diff --git a/drivers/staging/ozwpan/ozmain.c b/drivers/staging/ozwpan/ozmain.c index 51fe9e98c351..e26d6bee44d2 100644 --- a/drivers/staging/ozwpan/ozmain.c +++ b/drivers/staging/ozwpan/ozmain.c @@ -3,6 +3,7 @@ * Released under the GNU General Public License Version 2 (GPLv2). * ----------------------------------------------------------------------------- */ + #include #include #include @@ -10,11 +11,13 @@ #include #include #include -#include "ozconfig.h" +#include "ozdbg.h" #include "ozpd.h" #include "ozproto.h" #include "ozcdev.h" -#include "oztrace.h" + +unsigned int oz_dbg_mask = OZ_DEFAULT_DBG_MASK; + /*------------------------------------------------------------------------------ * The name of the 802.11 mac device. Empty string is the default value but a * value can be supplied as a parameter to the module. An empty string means diff --git a/drivers/staging/ozwpan/ozpd.c b/drivers/staging/ozwpan/ozpd.c index 28adbb47764a..8a253ac07c26 100644 --- a/drivers/staging/ozwpan/ozpd.c +++ b/drivers/staging/ozwpan/ozpd.c @@ -3,6 +3,7 @@ * Released under the GNU General Public License Version 2 (GPLv2). * ----------------------------------------------------------------------------- */ + #include #include #include @@ -10,17 +11,16 @@ #include #include #include "ozdbg.h" -#include "ozconfig.h" #include "ozprotocol.h" #include "ozeltbuf.h" #include "ozpd.h" #include "ozproto.h" -#include "oztrace.h" #include "ozcdev.h" #include "ozusbsvc.h" #include #include #include + /*------------------------------------------------------------------------------ */ #define OZ_MAX_TX_POOL_SIZE 6 @@ -121,7 +121,6 @@ static void oz_def_app_rx(struct oz_pd *pd, struct oz_elt *elt) void oz_pd_set_state(struct oz_pd *pd, unsigned state) { pd->state = state; -#ifdef WANT_TRACE switch (state) { case OZ_PD_S_IDLE: oz_pd_dbg(pd, ON, "PD State: OZ_PD_S_IDLE\n"); @@ -136,7 +135,6 @@ void oz_pd_set_state(struct oz_pd *pd, unsigned state) oz_pd_dbg(pd, ON, "PD State: OZ_PD_S_SLEEP\n"); break; } -#endif /* WANT_TRACE */ } /*------------------------------------------------------------------------------ * Context: softirq or process diff --git a/drivers/staging/ozwpan/ozproto.c b/drivers/staging/ozwpan/ozproto.c index 494236ed4488..760761df3845 100644 --- a/drivers/staging/ozwpan/ozproto.c +++ b/drivers/staging/ozwpan/ozproto.c @@ -3,6 +3,7 @@ * Released under the GNU General Public License Version 2 (GPLv2). * ----------------------------------------------------------------------------- */ + #include #include #include @@ -11,13 +12,12 @@ #include #include #include "ozdbg.h" -#include "ozconfig.h" #include "ozprotocol.h" #include "ozeltbuf.h" #include "ozpd.h" #include "ozproto.h" #include "ozusbsvc.h" -#include "oztrace.h" + #include "ozappif.h" #include #include diff --git a/drivers/staging/ozwpan/oztrace.c b/drivers/staging/ozwpan/oztrace.c deleted file mode 100644 index 353ead24fd7d..000000000000 --- a/drivers/staging/ozwpan/oztrace.c +++ /dev/null @@ -1,36 +0,0 @@ -/* ----------------------------------------------------------------------------- - * Copyright (c) 2011 Ozmo Inc - * Released under the GNU General Public License Version 2 (GPLv2). - * ----------------------------------------------------------------------------- - */ -#include "ozconfig.h" -#include "oztrace.h" - -#ifdef WANT_VERBOSE_TRACE -unsigned long trace_flags = - 0 -#ifdef WANT_TRACE_STREAM - | OZ_TRACE_STREAM -#endif /* WANT_TRACE_STREAM */ -#ifdef WANT_TRACE_URB - | OZ_TRACE_URB -#endif /* WANT_TRACE_URB */ - -#ifdef WANT_TRACE_CTRL_DETAIL - | OZ_TRACE_CTRL_DETAIL -#endif /* WANT_TRACE_CTRL_DETAIL */ - -#ifdef WANT_TRACE_HUB - | OZ_TRACE_HUB -#endif /* WANT_TRACE_HUB */ - -#ifdef WANT_TRACE_RX_FRAMES - | OZ_TRACE_RX_FRAMES -#endif /* WANT_TRACE_RX_FRAMES */ - -#ifdef WANT_TRACE_TX_FRAMES - | OZ_TRACE_TX_FRAMES -#endif /* WANT_TRACE_TX_FRAMES */ - ; -#endif /* WANT_VERBOSE_TRACE */ - diff --git a/drivers/staging/ozwpan/oztrace.h b/drivers/staging/ozwpan/oztrace.h deleted file mode 100644 index 8293b24c5a77..000000000000 --- a/drivers/staging/ozwpan/oztrace.h +++ /dev/null @@ -1,35 +0,0 @@ -/* ----------------------------------------------------------------------------- - * Copyright (c) 2011 Ozmo Inc - * Released under the GNU General Public License Version 2 (GPLv2). - * ----------------------------------------------------------------------------- - */ -#ifndef _OZTRACE_H_ -#define _OZTRACE_H_ -#include "ozconfig.h" - -#define TRACE_PREFIX KERN_ALERT "OZWPAN: " - -#ifdef WANT_TRACE -#define oz_trace(...) printk(TRACE_PREFIX __VA_ARGS__) -#ifdef WANT_VERBOSE_TRACE -extern unsigned long trace_flags; -#define oz_trace2(_flag, ...) \ - do { if (trace_flags & _flag) printk(TRACE_PREFIX __VA_ARGS__); \ - } while (0) -#else -#define oz_trace2(...) -#endif /* #ifdef WANT_VERBOSE_TRACE */ -#else -#define oz_trace(...) -#define oz_trace2(...) -#endif /* #ifdef WANT_TRACE */ - -#define OZ_TRACE_STREAM 0x1 -#define OZ_TRACE_URB 0x2 -#define OZ_TRACE_CTRL_DETAIL 0x4 -#define OZ_TRACE_HUB 0x8 -#define OZ_TRACE_RX_FRAMES 0x10 -#define OZ_TRACE_TX_FRAMES 0x20 - -#endif /* Sentry */ - diff --git a/drivers/staging/ozwpan/ozurbparanoia.c b/drivers/staging/ozwpan/ozurbparanoia.c index 387d9dac5fe0..366584b75767 100644 --- a/drivers/staging/ozwpan/ozurbparanoia.c +++ b/drivers/staging/ozwpan/ozurbparanoia.c @@ -5,10 +5,11 @@ */ #include #include "ozdbg.h" -#include "ozconfig.h" + #ifdef WANT_URB_PARANOIA + #include "ozurbparanoia.h" -#include "oztrace.h" + /*----------------------------------------------------------------------------- */ #define OZ_MAX_URBS 1000 diff --git a/drivers/staging/ozwpan/ozusbsvc.c b/drivers/staging/ozwpan/ozusbsvc.c index b4aebdbd715d..816cac980586 100644 --- a/drivers/staging/ozwpan/ozusbsvc.c +++ b/drivers/staging/ozwpan/ozusbsvc.c @@ -10,6 +10,7 @@ * The implementation of this service uses ozhcd.c to implement a USB HCD. * ----------------------------------------------------------------------------- */ + #include #include #include @@ -19,15 +20,14 @@ #include #include #include "ozdbg.h" -#include "ozconfig.h" #include "ozprotocol.h" #include "ozeltbuf.h" #include "ozpd.h" #include "ozproto.h" #include "ozusbif.h" #include "ozhcd.h" -#include "oztrace.h" #include "ozusbsvc.h" + /*------------------------------------------------------------------------------ * This is called once when the driver is loaded to initialise the USB service. * Context: process diff --git a/drivers/staging/ozwpan/ozusbsvc1.c b/drivers/staging/ozwpan/ozusbsvc1.c index ab2c641dffe6..50d21bf4f927 100644 --- a/drivers/staging/ozwpan/ozusbsvc1.c +++ b/drivers/staging/ozwpan/ozusbsvc1.c @@ -14,14 +14,12 @@ #include #include #include "ozdbg.h" -#include "ozconfig.h" #include "ozprotocol.h" #include "ozeltbuf.h" #include "ozpd.h" #include "ozproto.h" #include "ozusbif.h" #include "ozhcd.h" -#include "oztrace.h" #include "ozusbsvc.h" /*------------------------------------------------------------------------------ */ From 155c71435cba5ac6761999011bc729cbd94cdac7 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 23 Jul 2013 13:45:02 +0100 Subject: [PATCH 0385/3400] staging: ozwpan: Convert macro to function. Replace macro with inline function. Signed-off-by: Joe Perches Signed-off-by: Rupesh Gujare Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ozwpan/ozurbparanoia.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/ozwpan/ozurbparanoia.h b/drivers/staging/ozwpan/ozurbparanoia.h index 00f5a3a81bc8..5080ea76f507 100644 --- a/drivers/staging/ozwpan/ozurbparanoia.h +++ b/drivers/staging/ozwpan/ozurbparanoia.h @@ -10,8 +10,8 @@ void oz_remember_urb(struct urb *urb); int oz_forget_urb(struct urb *urb); #else -#define oz_remember_urb(__x) -#define oz_forget_urb(__x) 0 +static inline void oz_remember_urb(struct urb *urb) {} +static inline int oz_forget_urb(struct urb *urb) { return 0; } #endif /* WANT_URB_PARANOIA */ From ba628ad0baec436e9c0774a8b2125a860cc7742a Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 23 Jul 2013 13:45:03 +0100 Subject: [PATCH 0386/3400] staging: ozwpan: Rename Kbuild to Makefile Rename Kbuild to usual Makefile, consistent with Kernel build structure. Signed-off-by: Joe Perches Signed-off-by: Rupesh Gujare Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ozwpan/{Kbuild => Makefile} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename drivers/staging/ozwpan/{Kbuild => Makefile} (100%) diff --git a/drivers/staging/ozwpan/Kbuild b/drivers/staging/ozwpan/Makefile similarity index 100% rename from drivers/staging/ozwpan/Kbuild rename to drivers/staging/ozwpan/Makefile From 397334fc2be6a7e2f77474bd2b24880efea007bf Mon Sep 17 00:00:00 2001 From: Serban Constantinescu Date: Thu, 4 Jul 2013 10:54:43 +0100 Subject: [PATCH 0387/3400] staging: android: binder: modify struct binder_write_read to use size_t MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change mirrors the userspace operation where struct binder_write_read members that specify the buffer size and consumed size are size_t elements. The patch also fixes the binder_thread_write() and binder_thread_read() functions prototypes to conform with the definition of binder_write_read. The changes do not affect existing 32bit ABI. Signed-off-by: Serban Constantinescu Acked-by: Arve HjønnevÃ¥g Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/binder.c | 10 +++++----- drivers/staging/android/binder.h | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index 119d486a5cf7..787fc921b1e7 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -1701,7 +1701,7 @@ err_no_context_mgr_node: } int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, - void __user *buffer, int size, signed long *consumed) + void __user *buffer, size_t size, size_t *consumed) { uint32_t cmd; void __user *ptr = buffer + *consumed; @@ -2081,8 +2081,8 @@ static int binder_has_thread_work(struct binder_thread *thread) static int binder_thread_read(struct binder_proc *proc, struct binder_thread *thread, - void __user *buffer, int size, - signed long *consumed, int non_block) + void __user *buffer, size_t size, + size_t *consumed, int non_block) { void __user *ptr = buffer + *consumed; void __user *end = buffer + size; @@ -2579,7 +2579,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) goto err; } binder_debug(BINDER_DEBUG_READ_WRITE, - "%d:%d write %ld at %08lx, read %ld at %08lx\n", + "%d:%d write %zd at %08lx, read %zd at %08lx\n", proc->pid, thread->pid, bwr.write_size, bwr.write_buffer, bwr.read_size, bwr.read_buffer); @@ -2605,7 +2605,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } } binder_debug(BINDER_DEBUG_READ_WRITE, - "%d:%d wrote %ld of %ld, read return %ld of %ld\n", + "%d:%d wrote %zd of %zd, read return %zd of %zd\n", proc->pid, thread->pid, bwr.write_consumed, bwr.write_size, bwr.read_consumed, bwr.read_size); if (copy_to_user(ubuf, &bwr, sizeof(bwr))) { diff --git a/drivers/staging/android/binder.h b/drivers/staging/android/binder.h index dbe81ceca1bd..edab2491a1b7 100644 --- a/drivers/staging/android/binder.h +++ b/drivers/staging/android/binder.h @@ -67,11 +67,11 @@ struct flat_binder_object { */ struct binder_write_read { - signed long write_size; /* bytes to write */ - signed long write_consumed; /* bytes consumed by driver */ + size_t write_size; /* bytes to write */ + size_t write_consumed; /* bytes consumed by driver */ unsigned long write_buffer; - signed long read_size; /* bytes to read */ - signed long read_consumed; /* bytes consumed by driver */ + size_t read_size; /* bytes to read */ + size_t read_consumed; /* bytes consumed by driver */ unsigned long read_buffer; }; From a9350fc859ae3f1db7f2efd55c7a3e0d09a4098d Mon Sep 17 00:00:00 2001 From: Serban Constantinescu Date: Thu, 4 Jul 2013 10:54:44 +0100 Subject: [PATCH 0388/3400] staging: android: binder: fix BINDER_SET_MAX_THREADS declaration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change will fix the BINDER_SET_MAX_THREADS ioctl to use __u32 instead of size_t for setting the max threads. Thus using the same handler for 32 and 64bit kernels. This value is stored internally in struct binder_proc and set to 15 on open_binder() in the libbinder API(thus no need for a 64bit size_t on 64bit platforms). The change does not affect existing 32bit ABI. Signed-off-by: Serban Constantinescu Acked-by: Arve HjønnevÃ¥g Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/binder.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/android/binder.h b/drivers/staging/android/binder.h index edab2491a1b7..6515dd2f3552 100644 --- a/drivers/staging/android/binder.h +++ b/drivers/staging/android/binder.h @@ -86,7 +86,7 @@ struct binder_version { #define BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read) #define BINDER_SET_IDLE_TIMEOUT _IOW('b', 3, __s64) -#define BINDER_SET_MAX_THREADS _IOW('b', 5, size_t) +#define BINDER_SET_MAX_THREADS _IOW('b', 5, __u32) #define BINDER_SET_IDLE_PRIORITY _IOW('b', 6, __s32) #define BINDER_SET_CONTEXT_MGR _IOW('b', 7, __s32) #define BINDER_THREAD_EXIT _IOW('b', 8, __s32) From fc56f2ecf091d774c18ad0d470c62c6818fa32a3 Mon Sep 17 00:00:00 2001 From: Serban Constantinescu Date: Thu, 4 Jul 2013 10:54:45 +0100 Subject: [PATCH 0389/3400] staging: android: binder: fix BC_FREE_BUFFER ioctl declaration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BinderDriverCommands mirror the ioctl usage. Thus the size of the structure passed through the interface should be used to generate the ioctl No. The change reflects the type being passed from the user space-a pointer to a binder_buffer. This change should not affect the existing 32bit user space since BC_FREE_BUFFER is computed as: #define _IOW(type,nr,size) \ ((type) << _IOC_TYPESHIFT) | \ ((nr) << _IOC_NRSHIFT) | \ ((size) << _IOC_SIZESHIFT)) and for a 32bit compiler BC_FREE_BUFFER will have the same computed value. This change will also ease our work in differentiating BC_FREE_BUFFER from COMPAT_BC_FREE_BUFFER. The change does not affect existing 32bit ABI. Signed-off-by: Serban Constantinescu Acked-by: Arve HjønnevÃ¥g Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/binder.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/android/binder.h b/drivers/staging/android/binder.h index 6515dd2f3552..b55bba9ad92b 100644 --- a/drivers/staging/android/binder.h +++ b/drivers/staging/android/binder.h @@ -265,7 +265,7 @@ enum binder_driver_command_protocol { * Else you have acquired a primary reference on the object. */ - BC_FREE_BUFFER = _IOW('c', 3, int), + BC_FREE_BUFFER = _IOW('c', 3, void *), /* * void *: ptr to transaction data received on a read */ From ec35e852dc9de9809f88ff397d7a611208880f9f Mon Sep 17 00:00:00 2001 From: Serban Constantinescu Date: Thu, 4 Jul 2013 10:54:46 +0100 Subject: [PATCH 0390/3400] staging: android: binder: fix alignment issues MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Android userspace aligns the data written to the binder buffers to 4bytes. Thus for 32bit platforms or 64bit platforms running an 32bit Android userspace we can have a buffer looking like this: platform buffer(binder_cmd pointer) size 32/32 32b 32b 8B 64/32 32b 64b 12B 64/64 32b 64b 12B Thus the kernel needs to check that the buffer size is aligned to 4bytes not to (void *) that will be 8bytes on 64bit machines. The change does not affect existing 32bit ABI. Signed-off-by: Serban Constantinescu Acked-by: Arve HjønnevÃ¥g Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/binder.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index 787fc921b1e7..c6813ea15f40 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -1248,7 +1248,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, struct flat_binder_object *fp; if (*offp > buffer->data_size - sizeof(*fp) || buffer->data_size < sizeof(*fp) || - !IS_ALIGNED(*offp, sizeof(void *))) { + !IS_ALIGNED(*offp, sizeof(u32))) { pr_err("transaction release %d bad offset %zd, size %zd\n", debug_id, *offp, buffer->data_size); continue; @@ -1497,7 +1497,7 @@ static void binder_transaction(struct binder_proc *proc, struct flat_binder_object *fp; if (*offp > t->buffer->data_size - sizeof(*fp) || t->buffer->data_size < sizeof(*fp) || - !IS_ALIGNED(*offp, sizeof(void *))) { + !IS_ALIGNED(*offp, sizeof(u32))) { binder_user_error("%d:%d got transaction with invalid offset, %zd\n", proc->pid, thread->pid, *offp); return_error = BR_FAILED_REPLY; From eecddef594f9eb159040160b929642f16a07387f Mon Sep 17 00:00:00 2001 From: Serban Constantinescu Date: Thu, 4 Jul 2013 10:54:47 +0100 Subject: [PATCH 0391/3400] staging: android: binder: replace types with portable ones MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since this driver is meant to be used on different types of processors and a portable driver should specify the size a variable expects to be this patch changes the types used throughout the binder interface. We use "userspace" types since this header will be exported and used by the Android filesystem. The patch does not change in any way the functionality of the binder driver. Signed-off-by: Serban Constantinescu Acked-by: Arve HjønnevÃ¥g Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/binder.h | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/staging/android/binder.h b/drivers/staging/android/binder.h index b55bba9ad92b..dadfce028c53 100644 --- a/drivers/staging/android/binder.h +++ b/drivers/staging/android/binder.h @@ -123,10 +123,10 @@ struct binder_transaction_data { void *ptr; /* target descriptor of return transaction */ } target; void *cookie; /* target object cookie */ - unsigned int code; /* transaction command */ + __u32 code; /* transaction command */ /* General information about the transaction. */ - unsigned int flags; + __u32 flags; pid_t sender_pid; uid_t sender_euid; size_t data_size; /* number of bytes of data */ @@ -143,7 +143,7 @@ struct binder_transaction_data { /* offsets from buffer to flat_binder_object structs */ const void __user *offsets; } ptr; - uint8_t buf[8]; + __u8 buf[8]; } data; }; @@ -153,18 +153,18 @@ struct binder_ptr_cookie { }; struct binder_pri_desc { - int priority; - int desc; + __s32 priority; + __s32 desc; }; struct binder_pri_ptr_cookie { - int priority; + __s32 priority; void *ptr; void *cookie; }; enum binder_driver_return_protocol { - BR_ERROR = _IOR('r', 0, int), + BR_ERROR = _IOR('r', 0, __s32), /* * int: error code */ @@ -178,7 +178,7 @@ enum binder_driver_return_protocol { * binder_transaction_data: the received command. */ - BR_ACQUIRE_RESULT = _IOR('r', 4, int), + BR_ACQUIRE_RESULT = _IOR('r', 4, __s32), /* * not currently supported * int: 0 if the last bcATTEMPT_ACQUIRE was not successful. @@ -258,7 +258,7 @@ enum binder_driver_command_protocol { * binder_transaction_data: the sent command. */ - BC_ACQUIRE_RESULT = _IOW('c', 2, int), + BC_ACQUIRE_RESULT = _IOW('c', 2, __s32), /* * not currently supported * int: 0 if the last BR_ATTEMPT_ACQUIRE was not successful. @@ -270,10 +270,10 @@ enum binder_driver_command_protocol { * void *: ptr to transaction data received on a read */ - BC_INCREFS = _IOW('c', 4, int), - BC_ACQUIRE = _IOW('c', 5, int), - BC_RELEASE = _IOW('c', 6, int), - BC_DECREFS = _IOW('c', 7, int), + BC_INCREFS = _IOW('c', 4, __u32), + BC_ACQUIRE = _IOW('c', 5, __u32), + BC_RELEASE = _IOW('c', 6, __u32), + BC_DECREFS = _IOW('c', 7, __u32), /* * int: descriptor */ From 64dcfe6b84d4104d93e4baf2b5a0b3e7f2e4cc30 Mon Sep 17 00:00:00 2001 From: Serban Constantinescu Date: Thu, 4 Jul 2013 10:54:48 +0100 Subject: [PATCH 0392/3400] staging: android: binder: fix binder interface for 64bit compat layer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The changes in this patch will fix the binder interface for use on 64bit machines and stand as the base of the 64bit compat support. The changes apply to the structures that are passed between the kernel and userspace. Most of the changes applied mirror the change to struct binder_version where there is no need for a 64bit wide protocol_version(on 64bit machines). The change inlines with the existing 32bit userspace(the structure has the same size) and simplifies the compat layer such that the same handler can service the BINDER_VERSION ioctl. Other changes make use of kernel types as well as user-exportable ones and fix format specifier issues. The changes do not affect existing 32bit ABI. Signed-off-by: Serban Constantinescu Acked-by: Arve HjønnevÃ¥g Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/binder.c | 20 ++++++++++---------- drivers/staging/android/binder.h | 12 ++++++------ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index c6813ea15f40..98ac020bf912 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -1272,7 +1272,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, case BINDER_TYPE_WEAK_HANDLE: { struct binder_ref *ref = binder_get_ref(proc, fp->handle); if (ref == NULL) { - pr_err("transaction release %d bad handle %ld\n", + pr_err("transaction release %d bad handle %d\n", debug_id, fp->handle); break; } @@ -1284,13 +1284,13 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, case BINDER_TYPE_FD: binder_debug(BINDER_DEBUG_TRANSACTION, - " fd %ld\n", fp->handle); + " fd %d\n", fp->handle); if (failed_at) task_close_fd(proc, fp->handle); break; default: - pr_err("transaction release %d bad object type %lx\n", + pr_err("transaction release %d bad object type %x\n", debug_id, fp->type); break; } @@ -1548,7 +1548,7 @@ static void binder_transaction(struct binder_proc *proc, case BINDER_TYPE_WEAK_HANDLE: { struct binder_ref *ref = binder_get_ref(proc, fp->handle); if (ref == NULL) { - binder_user_error("%d:%d got transaction with invalid handle, %ld\n", + binder_user_error("%d:%d got transaction with invalid handle, %d\n", proc->pid, thread->pid, fp->handle); return_error = BR_FAILED_REPLY; @@ -1591,13 +1591,13 @@ static void binder_transaction(struct binder_proc *proc, if (reply) { if (!(in_reply_to->flags & TF_ACCEPT_FDS)) { - binder_user_error("%d:%d got reply with fd, %ld, but target does not allow fds\n", + binder_user_error("%d:%d got reply with fd, %d, but target does not allow fds\n", proc->pid, thread->pid, fp->handle); return_error = BR_FAILED_REPLY; goto err_fd_not_allowed; } } else if (!target_node->accept_fds) { - binder_user_error("%d:%d got transaction with fd, %ld, but target does not allow fds\n", + binder_user_error("%d:%d got transaction with fd, %d, but target does not allow fds\n", proc->pid, thread->pid, fp->handle); return_error = BR_FAILED_REPLY; goto err_fd_not_allowed; @@ -1605,7 +1605,7 @@ static void binder_transaction(struct binder_proc *proc, file = fget(fp->handle); if (file == NULL) { - binder_user_error("%d:%d got transaction with invalid fd, %ld\n", + binder_user_error("%d:%d got transaction with invalid fd, %d\n", proc->pid, thread->pid, fp->handle); return_error = BR_FAILED_REPLY; goto err_fget_failed; @@ -1619,13 +1619,13 @@ static void binder_transaction(struct binder_proc *proc, task_fd_install(target_proc, target_fd, file); trace_binder_transaction_fd(t, fp->handle, target_fd); binder_debug(BINDER_DEBUG_TRANSACTION, - " fd %ld -> %d\n", fp->handle, target_fd); + " fd %d -> %d\n", fp->handle, target_fd); /* TODO: fput? */ fp->handle = target_fd; } break; default: - binder_user_error("%d:%d got transaction with invalid object type, %lx\n", + binder_user_error("%d:%d got transaction with invalid object type, %x\n", proc->pid, thread->pid, fp->type); return_error = BR_FAILED_REPLY; goto err_bad_object_type; @@ -2579,7 +2579,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) goto err; } binder_debug(BINDER_DEBUG_READ_WRITE, - "%d:%d write %zd at %08lx, read %zd at %08lx\n", + "%d:%d write %zd at %016lx, read %zd at %016lx\n", proc->pid, thread->pid, bwr.write_size, bwr.write_buffer, bwr.read_size, bwr.read_buffer); diff --git a/drivers/staging/android/binder.h b/drivers/staging/android/binder.h index dadfce028c53..cbe345168067 100644 --- a/drivers/staging/android/binder.h +++ b/drivers/staging/android/binder.h @@ -48,13 +48,13 @@ enum { */ struct flat_binder_object { /* 8 bytes for large_flat_header. */ - unsigned long type; - unsigned long flags; + __u32 type; + __u32 flags; /* 8 bytes of data. */ union { void __user *binder; /* local object */ - signed long handle; /* remote object */ + __u32 handle; /* remote object */ }; /* extra data associated with local object */ @@ -78,7 +78,7 @@ struct binder_write_read { /* Use with BINDER_VERSION, driver fills in fields. */ struct binder_version { /* driver protocol version -- increment with incompatible change */ - signed long protocol_version; + __s32 protocol_version; }; /* This is the current protocol version. */ @@ -119,7 +119,7 @@ struct binder_transaction_data { * identifying the target and contents of the transaction. */ union { - size_t handle; /* target descriptor of command transaction */ + __u32 handle; /* target descriptor of command transaction */ void *ptr; /* target descriptor of return transaction */ } target; void *cookie; /* target object cookie */ @@ -154,7 +154,7 @@ struct binder_ptr_cookie { struct binder_pri_desc { __s32 priority; - __s32 desc; + __u32 desc; }; struct binder_pri_ptr_cookie { From efb39e4eb3f117925d53c88c63e46131f0efc6da Mon Sep 17 00:00:00 2001 From: Chad Williamson Date: Tue, 25 Jun 2013 18:59:22 -0500 Subject: [PATCH 0393/3400] Staging: silicom: remove the bpctl_dev_t typdef Replace the bpctl_dev_t typdef in bpctl_mod.c with struct bpctl_dev for coding style compliance. Signed-off-by: Chad Williamson Signed-off-by: Greg Kroah-Hartman --- drivers/staging/silicom/bpctl_mod.c | 552 ++++++++++++++-------------- 1 file changed, 276 insertions(+), 276 deletions(-) diff --git a/drivers/staging/silicom/bpctl_mod.c b/drivers/staging/silicom/bpctl_mod.c index 48b9fb110acd..4689076fb7d1 100644 --- a/drivers/staging/silicom/bpctl_mod.c +++ b/drivers/staging/silicom/bpctl_mod.c @@ -59,7 +59,7 @@ struct bypass_pfs_sd { struct proc_dir_entry *bypass_entry; }; -typedef struct _bpctl_dev { +struct bpctl_dev { char *name; char *desc; struct pci_dev *pdev; /* PCI device */ @@ -102,26 +102,26 @@ typedef struct _bpctl_dev { char *bp_tx_data; struct bypass_pfs_sd bypass_pfs_set; -} bpctl_dev_t; +}; -static bpctl_dev_t *bpctl_dev_arr; +static struct bpctl_dev *bpctl_dev_arr; static struct semaphore bpctl_sema; static int device_num; static int get_dev_idx(int ifindex); -static bpctl_dev_t *get_master_port_fn(bpctl_dev_t *pbpctl_dev); -static int disc_status(bpctl_dev_t *pbpctl_dev); -static int bypass_status(bpctl_dev_t *pbpctl_dev); -static int wdt_timer(bpctl_dev_t *pbpctl_dev, int *time_left); -static bpctl_dev_t *get_status_port_fn(bpctl_dev_t *pbpctl_dev); +static struct bpctl_dev *get_master_port_fn(struct bpctl_dev *pbpctl_dev); +static int disc_status(struct bpctl_dev *pbpctl_dev); +static int bypass_status(struct bpctl_dev *pbpctl_dev); +static int wdt_timer(struct bpctl_dev *pbpctl_dev, int *time_left); +static struct bpctl_dev *get_status_port_fn(struct bpctl_dev *pbpctl_dev); static void if_scan_init(void); -int bypass_proc_create_dev_sd(bpctl_dev_t *pbp_device_block); -int bypass_proc_remove_dev_sd(bpctl_dev_t *pbp_device_block); +int bypass_proc_create_dev_sd(struct bpctl_dev *pbp_device_block); +int bypass_proc_remove_dev_sd(struct bpctl_dev *pbp_device_block); int bp_proc_create(void); -int is_bypass_fn(bpctl_dev_t *pbpctl_dev); +int is_bypass_fn(struct bpctl_dev *pbpctl_dev); int get_dev_idx_bsf(int bus, int slot, int func); static unsigned long str_to_hex(char *p); @@ -129,7 +129,7 @@ static int bp_device_event(struct notifier_block *unused, unsigned long event, void *ptr) { struct net_device *dev = netdev_notifier_info_to_dev(ptr); - static bpctl_dev_t *pbpctl_dev, *pbpctl_dev_m; + static struct bpctl_dev *pbpctl_dev, *pbpctl_dev_m; int dev_num = 0, ret = 0, ret_d = 0, time_left = 0; /* printk("BP_PROC_SUPPORT event =%d %s %d\n", event,dev->name, dev->ifindex ); */ /* return NOTIFY_DONE; */ @@ -284,17 +284,17 @@ static struct notifier_block bp_notifier_block = { .notifier_call = bp_device_event, }; -int is_bypass_fn(bpctl_dev_t *pbpctl_dev); -int wdt_time_left(bpctl_dev_t *pbpctl_dev); +int is_bypass_fn(struct bpctl_dev *pbpctl_dev); +int wdt_time_left(struct bpctl_dev *pbpctl_dev); -static void write_pulse(bpctl_dev_t *pbpctl_dev, +static void write_pulse(struct bpctl_dev *pbpctl_dev, unsigned int ctrl_ext, unsigned char value, unsigned char len) { unsigned char ctrl_val = 0; unsigned int i = len; unsigned int ctrl = 0; - bpctl_dev_t *pbpctl_dev_c = NULL; + struct bpctl_dev *pbpctl_dev_c = NULL; if (pbpctl_dev->bp_i80) ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); @@ -590,13 +590,13 @@ static void write_pulse(bpctl_dev_t *pbpctl_dev, } } -static int read_pulse(bpctl_dev_t *pbpctl_dev, unsigned int ctrl_ext, +static int read_pulse(struct bpctl_dev *pbpctl_dev, unsigned int ctrl_ext, unsigned char len) { unsigned char ctrl_val = 0; unsigned int i = len; unsigned int ctrl = 0; - bpctl_dev_t *pbpctl_dev_c = NULL; + struct bpctl_dev *pbpctl_dev_c = NULL; if (pbpctl_dev->bp_i80) ctrl = BPCTL_READ_REG(pbpctl_dev, CTRL_EXT); @@ -765,11 +765,11 @@ static int read_pulse(bpctl_dev_t *pbpctl_dev, unsigned int ctrl_ext, return ctrl_val; } -static void write_reg(bpctl_dev_t *pbpctl_dev, unsigned char value, +static void write_reg(struct bpctl_dev *pbpctl_dev, unsigned char value, unsigned char addr) { uint32_t ctrl_ext = 0, ctrl = 0; - bpctl_dev_t *pbpctl_dev_c = NULL; + struct bpctl_dev *pbpctl_dev_c = NULL; unsigned long flags; if (pbpctl_dev->bp_10g9) { pbpctl_dev_c = get_status_port_fn(pbpctl_dev); @@ -934,15 +934,15 @@ static void write_reg(bpctl_dev_t *pbpctl_dev, unsigned char value, } -static void write_data(bpctl_dev_t *pbpctl_dev, unsigned char value) +static void write_data(struct bpctl_dev *pbpctl_dev, unsigned char value) { write_reg(pbpctl_dev, value, CMND_REG_ADDR); } -static int read_reg(bpctl_dev_t *pbpctl_dev, unsigned char addr) +static int read_reg(struct bpctl_dev *pbpctl_dev, unsigned char addr) { uint32_t ctrl_ext = 0, ctrl = 0, ctrl_value = 0; - bpctl_dev_t *pbpctl_dev_c = NULL; + struct bpctl_dev *pbpctl_dev_c = NULL; #ifdef BP_SYNC_FLAG unsigned long flags; @@ -1208,10 +1208,10 @@ static int read_reg(bpctl_dev_t *pbpctl_dev, unsigned char addr) return ctrl_value; } -static int wdt_pulse(bpctl_dev_t *pbpctl_dev) +static int wdt_pulse(struct bpctl_dev *pbpctl_dev) { uint32_t ctrl_ext = 0, ctrl = 0; - bpctl_dev_t *pbpctl_dev_c = NULL; + struct bpctl_dev *pbpctl_dev_c = NULL; #ifdef BP_SYNC_FLAG unsigned long flags; @@ -1424,7 +1424,7 @@ static int wdt_pulse(bpctl_dev_t *pbpctl_dev) return 0; } -static void data_pulse(bpctl_dev_t *pbpctl_dev, unsigned char value) +static void data_pulse(struct bpctl_dev *pbpctl_dev, unsigned char value) { uint32_t ctrl_ext = 0; @@ -1490,7 +1490,7 @@ static void data_pulse(bpctl_dev_t *pbpctl_dev, unsigned char value) } -static int send_wdt_pulse(bpctl_dev_t *pbpctl_dev) +static int send_wdt_pulse(struct bpctl_dev *pbpctl_dev) { uint32_t ctrl_ext = 0; @@ -1524,7 +1524,7 @@ static int send_wdt_pulse(bpctl_dev_t *pbpctl_dev) return 0; } -void send_bypass_clear_pulse(bpctl_dev_t *pbpctl_dev, unsigned int value) +void send_bypass_clear_pulse(struct bpctl_dev *pbpctl_dev, unsigned int value) { uint32_t ctrl_ext = 0; @@ -1550,7 +1550,7 @@ void send_bypass_clear_pulse(bpctl_dev_t *pbpctl_dev, unsigned int value) /* #endif OLD_FW */ #ifdef BYPASS_DEBUG -int pulse_set_fn(bpctl_dev_t *pbpctl_dev, unsigned int counter) +int pulse_set_fn(struct bpctl_dev *pbpctl_dev, unsigned int counter) { uint32_t ctrl_ext = 0; @@ -1578,7 +1578,7 @@ int pulse_set_fn(bpctl_dev_t *pbpctl_dev, unsigned int counter) return 0; } -int zero_set_fn(bpctl_dev_t *pbpctl_dev) +int zero_set_fn(struct bpctl_dev *pbpctl_dev) { uint32_t ctrl_ext = 0, ctrl_value = 0; if (!pbpctl_dev) @@ -1603,7 +1603,7 @@ int zero_set_fn(bpctl_dev_t *pbpctl_dev) return ctrl_value; } -int pulse_get2_fn(bpctl_dev_t *pbpctl_dev) +int pulse_get2_fn(struct bpctl_dev *pbpctl_dev) { uint32_t ctrl_ext = 0, ctrl_value = 0; if (!pbpctl_dev) @@ -1618,7 +1618,7 @@ int pulse_get2_fn(bpctl_dev_t *pbpctl_dev) return ctrl_value; } -int pulse_get1_fn(bpctl_dev_t *pbpctl_dev) +int pulse_get1_fn(struct bpctl_dev *pbpctl_dev) { uint32_t ctrl_ext = 0, ctrl_value = 0; if (!pbpctl_dev) @@ -1635,7 +1635,7 @@ int pulse_get1_fn(bpctl_dev_t *pbpctl_dev) return ctrl_value; } -int gpio6_set_fn(bpctl_dev_t *pbpctl_dev) +int gpio6_set_fn(struct bpctl_dev *pbpctl_dev) { uint32_t ctrl_ext = 0; @@ -1646,7 +1646,7 @@ int gpio6_set_fn(bpctl_dev_t *pbpctl_dev) return 0; } -int gpio7_set_fn(bpctl_dev_t *pbpctl_dev) +int gpio7_set_fn(struct bpctl_dev *pbpctl_dev) { uint32_t ctrl_ext = 0; @@ -1657,7 +1657,7 @@ int gpio7_set_fn(bpctl_dev_t *pbpctl_dev) return 0; } -int gpio7_clear_fn(bpctl_dev_t *pbpctl_dev) +int gpio7_clear_fn(struct bpctl_dev *pbpctl_dev) { uint32_t ctrl_ext = 0; @@ -1668,7 +1668,7 @@ int gpio7_clear_fn(bpctl_dev_t *pbpctl_dev) return 0; } -int gpio6_clear_fn(bpctl_dev_t *pbpctl_dev) +int gpio6_clear_fn(struct bpctl_dev *pbpctl_dev) { uint32_t ctrl_ext = 0; @@ -1680,9 +1680,9 @@ int gpio6_clear_fn(bpctl_dev_t *pbpctl_dev) } #endif /*BYPASS_DEBUG */ -static bpctl_dev_t *lookup_port(bpctl_dev_t *dev) +static struct bpctl_dev *lookup_port(struct bpctl_dev *dev) { - bpctl_dev_t *p; + struct bpctl_dev *p; int n; for (n = 0, p = bpctl_dev_arr; n < device_num && p->pdev; n++) { if (p->bus == dev->bus @@ -1693,7 +1693,7 @@ static bpctl_dev_t *lookup_port(bpctl_dev_t *dev) return NULL; } -static bpctl_dev_t *get_status_port_fn(bpctl_dev_t *pbpctl_dev) +static struct bpctl_dev *get_status_port_fn(struct bpctl_dev *pbpctl_dev) { if (pbpctl_dev) { if (pbpctl_dev->func == 0 || pbpctl_dev->func == 2) @@ -1702,7 +1702,7 @@ static bpctl_dev_t *get_status_port_fn(bpctl_dev_t *pbpctl_dev) return NULL; } -static bpctl_dev_t *get_master_port_fn(bpctl_dev_t *pbpctl_dev) +static struct bpctl_dev *get_master_port_fn(struct bpctl_dev *pbpctl_dev) { if (pbpctl_dev) { if (pbpctl_dev->func == 1 || pbpctl_dev->func == 3) @@ -1715,7 +1715,7 @@ static bpctl_dev_t *get_master_port_fn(bpctl_dev_t *pbpctl_dev) /**************INTEL API***************/ /**************************************/ -static void write_data_port_int(bpctl_dev_t *pbpctl_dev, +static void write_data_port_int(struct bpctl_dev *pbpctl_dev, unsigned char ctrl_value) { uint32_t value; @@ -1740,9 +1740,9 @@ static void write_data_port_int(bpctl_dev_t *pbpctl_dev, } -static int write_data_int(bpctl_dev_t *pbpctl_dev, unsigned char value) +static int write_data_int(struct bpctl_dev *pbpctl_dev, unsigned char value) { - bpctl_dev_t *pbpctl_dev_b = NULL; + struct bpctl_dev *pbpctl_dev_b = NULL; pbpctl_dev_b = get_status_port_fn(pbpctl_dev); if (!pbpctl_dev_b) @@ -1755,7 +1755,7 @@ static int write_data_int(bpctl_dev_t *pbpctl_dev, unsigned char value) return 0; } -static int wdt_pulse_int(bpctl_dev_t *pbpctl_dev) +static int wdt_pulse_int(struct bpctl_dev *pbpctl_dev) { if ((atomic_read(&pbpctl_dev->wdt_busy)) == 1) @@ -1779,7 +1779,7 @@ static int wdt_pulse_int(bpctl_dev_t *pbpctl_dev) /*************************************/ /* CMND_ON 0x4 (100)*/ -int cmnd_on(bpctl_dev_t *pbpctl_dev) +int cmnd_on(struct bpctl_dev *pbpctl_dev) { int ret = BP_NOT_CAP; @@ -1796,7 +1796,7 @@ int cmnd_on(bpctl_dev_t *pbpctl_dev) } /* CMND_OFF 0x2 (10)*/ -int cmnd_off(bpctl_dev_t *pbpctl_dev) +int cmnd_off(struct bpctl_dev *pbpctl_dev) { int ret = BP_NOT_CAP; @@ -1814,7 +1814,7 @@ int cmnd_off(bpctl_dev_t *pbpctl_dev) } /* BYPASS_ON (0xa)*/ -int bypass_on(bpctl_dev_t *pbpctl_dev) +int bypass_on(struct bpctl_dev *pbpctl_dev) { int ret = BP_NOT_CAP; @@ -1835,7 +1835,7 @@ int bypass_on(bpctl_dev_t *pbpctl_dev) } /* BYPASS_OFF (0x8 111)*/ -int bypass_off(bpctl_dev_t *pbpctl_dev) +int bypass_off(struct bpctl_dev *pbpctl_dev) { int ret = BP_NOT_CAP; @@ -1858,7 +1858,7 @@ int bypass_off(bpctl_dev_t *pbpctl_dev) } /* TAP_OFF (0x9)*/ -int tap_off(bpctl_dev_t *pbpctl_dev) +int tap_off(struct bpctl_dev *pbpctl_dev) { int ret = BP_NOT_CAP; if ((pbpctl_dev->bp_caps & TAP_CAP) @@ -1871,7 +1871,7 @@ int tap_off(bpctl_dev_t *pbpctl_dev) } /* TAP_ON (0xb)*/ -int tap_on(bpctl_dev_t *pbpctl_dev) +int tap_on(struct bpctl_dev *pbpctl_dev) { int ret = BP_NOT_CAP; if ((pbpctl_dev->bp_caps & TAP_CAP) @@ -1884,7 +1884,7 @@ int tap_on(bpctl_dev_t *pbpctl_dev) } /* DISC_OFF (0x9)*/ -int disc_off(bpctl_dev_t *pbpctl_dev) +int disc_off(struct bpctl_dev *pbpctl_dev) { int ret = 0; if ((pbpctl_dev->bp_caps & DISC_CAP) && (pbpctl_dev->bp_ext_ver >= 0x8)) { @@ -1896,7 +1896,7 @@ int disc_off(bpctl_dev_t *pbpctl_dev) } /* DISC_ON (0xb)*/ -int disc_on(bpctl_dev_t *pbpctl_dev) +int disc_on(struct bpctl_dev *pbpctl_dev) { int ret = 0; if ((pbpctl_dev->bp_caps & DISC_CAP) && (pbpctl_dev->bp_ext_ver >= 0x8)) { @@ -1908,10 +1908,10 @@ int disc_on(bpctl_dev_t *pbpctl_dev) } /* DISC_PORT_ON */ -int disc_port_on(bpctl_dev_t *pbpctl_dev) +int disc_port_on(struct bpctl_dev *pbpctl_dev) { int ret = 0; - bpctl_dev_t *pbpctl_dev_m; + struct bpctl_dev *pbpctl_dev_m; if ((is_bypass_fn(pbpctl_dev)) == 1) pbpctl_dev_m = pbpctl_dev; @@ -1933,10 +1933,10 @@ int disc_port_on(bpctl_dev_t *pbpctl_dev) } /* DISC_PORT_OFF */ -int disc_port_off(bpctl_dev_t *pbpctl_dev) +int disc_port_off(struct bpctl_dev *pbpctl_dev) { int ret = 0; - bpctl_dev_t *pbpctl_dev_m; + struct bpctl_dev *pbpctl_dev_m; if ((is_bypass_fn(pbpctl_dev)) == 1) pbpctl_dev_m = pbpctl_dev; @@ -1958,10 +1958,10 @@ int disc_port_off(bpctl_dev_t *pbpctl_dev) } /*TWO_PORT_LINK_HW_EN (0xe)*/ -int tpl_hw_on(bpctl_dev_t *pbpctl_dev) +int tpl_hw_on(struct bpctl_dev *pbpctl_dev) { int ret = 0, ctrl = 0; - bpctl_dev_t *pbpctl_dev_b = NULL; + struct bpctl_dev *pbpctl_dev_b = NULL; pbpctl_dev_b = get_status_port_fn(pbpctl_dev); if (!pbpctl_dev_b) @@ -1986,10 +1986,10 @@ int tpl_hw_on(bpctl_dev_t *pbpctl_dev) } /*TWO_PORT_LINK_HW_DIS (0xc)*/ -int tpl_hw_off(bpctl_dev_t *pbpctl_dev) +int tpl_hw_off(struct bpctl_dev *pbpctl_dev) { int ret = 0, ctrl = 0; - bpctl_dev_t *pbpctl_dev_b = NULL; + struct bpctl_dev *pbpctl_dev_b = NULL; pbpctl_dev_b = get_status_port_fn(pbpctl_dev); if (!pbpctl_dev_b) @@ -2012,7 +2012,7 @@ int tpl_hw_off(bpctl_dev_t *pbpctl_dev) } /* WDT_OFF (0x6 110)*/ -int wdt_off(bpctl_dev_t *pbpctl_dev) +int wdt_off(struct bpctl_dev *pbpctl_dev) { int ret = BP_NOT_CAP; @@ -2035,7 +2035,7 @@ int wdt_off(bpctl_dev_t *pbpctl_dev) static unsigned int wdt_val_array[] = { 1000, 1500, 2000, 3000, 4000, 8000, 16000, 32000, 0 }; -int wdt_on(bpctl_dev_t *pbpctl_dev, unsigned int timeout) +int wdt_on(struct bpctl_dev *pbpctl_dev, unsigned int timeout) { if (pbpctl_dev->bp_caps & WD_CTL_CAP) { @@ -2087,7 +2087,7 @@ int wdt_on(bpctl_dev_t *pbpctl_dev, unsigned int timeout) return BP_NOT_CAP; } -void bp75_put_hw_semaphore_generic(bpctl_dev_t *pbpctl_dev) +void bp75_put_hw_semaphore_generic(struct bpctl_dev *pbpctl_dev) { u32 swsm; @@ -2098,7 +2098,7 @@ void bp75_put_hw_semaphore_generic(bpctl_dev_t *pbpctl_dev) BPCTL_WRITE_REG(pbpctl_dev, SWSM, swsm); } -s32 bp75_get_hw_semaphore_generic(bpctl_dev_t *pbpctl_dev) +s32 bp75_get_hw_semaphore_generic(struct bpctl_dev *pbpctl_dev) { u32 swsm; s32 ret_val = 0; @@ -2146,7 +2146,7 @@ s32 bp75_get_hw_semaphore_generic(bpctl_dev_t *pbpctl_dev) return ret_val; } -static void bp75_release_phy(bpctl_dev_t *pbpctl_dev) +static void bp75_release_phy(struct bpctl_dev *pbpctl_dev) { u16 mask = BPCTLI_SWFW_PHY0_SM; u32 swfw_sync; @@ -2166,7 +2166,7 @@ static void bp75_release_phy(bpctl_dev_t *pbpctl_dev) bp75_put_hw_semaphore_generic(pbpctl_dev); } -static s32 bp75_acquire_phy(bpctl_dev_t *pbpctl_dev) +static s32 bp75_acquire_phy(struct bpctl_dev *pbpctl_dev) { u16 mask = BPCTLI_SWFW_PHY0_SM; u32 swfw_sync; @@ -2212,7 +2212,7 @@ static s32 bp75_acquire_phy(bpctl_dev_t *pbpctl_dev) return ret_val; } -s32 bp75_read_phy_reg_mdic(bpctl_dev_t *pbpctl_dev, u32 offset, u16 *data) +s32 bp75_read_phy_reg_mdic(struct bpctl_dev *pbpctl_dev, u32 offset, u16 *data) { u32 i, mdic = 0; s32 ret_val = 0; @@ -2245,7 +2245,7 @@ s32 bp75_read_phy_reg_mdic(bpctl_dev_t *pbpctl_dev, u32 offset, u16 *data) return ret_val; } -s32 bp75_write_phy_reg_mdic(bpctl_dev_t *pbpctl_dev, u32 offset, u16 data) +s32 bp75_write_phy_reg_mdic(struct bpctl_dev *pbpctl_dev, u32 offset, u16 data) { u32 i, mdic = 0; s32 ret_val = 0; @@ -2278,7 +2278,7 @@ s32 bp75_write_phy_reg_mdic(bpctl_dev_t *pbpctl_dev, u32 offset, u16 data) return ret_val; } -static s32 bp75_read_phy_reg(bpctl_dev_t *pbpctl_dev, u32 offset, u16 *data) +static s32 bp75_read_phy_reg(struct bpctl_dev *pbpctl_dev, u32 offset, u16 *data) { s32 ret_val = 0; @@ -2304,7 +2304,7 @@ static s32 bp75_read_phy_reg(bpctl_dev_t *pbpctl_dev, u32 offset, u16 *data) return ret_val; } -static s32 bp75_write_phy_reg(bpctl_dev_t *pbpctl_dev, u32 offset, u16 data) +static s32 bp75_write_phy_reg(struct bpctl_dev *pbpctl_dev, u32 offset, u16 data) { s32 ret_val = 0; @@ -2332,10 +2332,10 @@ static s32 bp75_write_phy_reg(bpctl_dev_t *pbpctl_dev, u32 offset, u16 data) } /* SET_TX (non-Bypass command :)) */ -static int set_tx(bpctl_dev_t *pbpctl_dev, int tx_state) +static int set_tx(struct bpctl_dev *pbpctl_dev, int tx_state) { int ret = 0, ctrl = 0; - bpctl_dev_t *pbpctl_dev_m; + struct bpctl_dev *pbpctl_dev_m; if ((is_bypass_fn(pbpctl_dev)) == 1) pbpctl_dev_m = pbpctl_dev; else @@ -2532,7 +2532,7 @@ static int set_tx(bpctl_dev_t *pbpctl_dev, int tx_state) } /* SET_FORCE_LINK (non-Bypass command :)) */ -static int set_bp_force_link(bpctl_dev_t *pbpctl_dev, int tx_state) +static int set_bp_force_link(struct bpctl_dev *pbpctl_dev, int tx_state) { int ret = 0, ctrl = 0; @@ -2556,7 +2556,7 @@ static int set_bp_force_link(bpctl_dev_t *pbpctl_dev, int tx_state) } /*RESET_CONT 0x20 */ -int reset_cont(bpctl_dev_t *pbpctl_dev) +int reset_cont(struct bpctl_dev *pbpctl_dev) { int ret = BP_NOT_CAP; @@ -2573,7 +2573,7 @@ int reset_cont(bpctl_dev_t *pbpctl_dev) } /*DIS_BYPASS_CAP 0x22 */ -int dis_bypass_cap(bpctl_dev_t *pbpctl_dev) +int dis_bypass_cap(struct bpctl_dev *pbpctl_dev) { if (pbpctl_dev->bp_caps & BP_DIS_CAP) { @@ -2592,7 +2592,7 @@ int dis_bypass_cap(bpctl_dev_t *pbpctl_dev) } /*EN_BYPASS_CAP 0x24 */ -int en_bypass_cap(bpctl_dev_t *pbpctl_dev) +int en_bypass_cap(struct bpctl_dev *pbpctl_dev) { if (pbpctl_dev->bp_caps & BP_DIS_CAP) { if (INTEL_IF_SERIES(pbpctl_dev->subdevice)) { @@ -2608,7 +2608,7 @@ int en_bypass_cap(bpctl_dev_t *pbpctl_dev) } /* BYPASS_STATE_PWRON 0x26*/ -int bypass_state_pwron(bpctl_dev_t *pbpctl_dev) +int bypass_state_pwron(struct bpctl_dev *pbpctl_dev) { if (pbpctl_dev->bp_caps & BP_PWUP_CTL_CAP) { write_data(pbpctl_dev, BYPASS_STATE_PWRON); @@ -2622,7 +2622,7 @@ int bypass_state_pwron(bpctl_dev_t *pbpctl_dev) } /* NORMAL_STATE_PWRON 0x28*/ -int normal_state_pwron(bpctl_dev_t *pbpctl_dev) +int normal_state_pwron(struct bpctl_dev *pbpctl_dev) { if ((pbpctl_dev->bp_caps & BP_PWUP_CTL_CAP) || (pbpctl_dev->bp_caps & TAP_PWUP_CTL_CAP)) { @@ -2637,7 +2637,7 @@ int normal_state_pwron(bpctl_dev_t *pbpctl_dev) } /* BYPASS_STATE_PWROFF 0x27*/ -int bypass_state_pwroff(bpctl_dev_t *pbpctl_dev) +int bypass_state_pwroff(struct bpctl_dev *pbpctl_dev) { if (pbpctl_dev->bp_caps & BP_PWOFF_CTL_CAP) { write_data(pbpctl_dev, BYPASS_STATE_PWROFF); @@ -2648,7 +2648,7 @@ int bypass_state_pwroff(bpctl_dev_t *pbpctl_dev) } /* NORMAL_STATE_PWROFF 0x29*/ -int normal_state_pwroff(bpctl_dev_t *pbpctl_dev) +int normal_state_pwroff(struct bpctl_dev *pbpctl_dev) { if ((pbpctl_dev->bp_caps & BP_PWOFF_CTL_CAP)) { write_data(pbpctl_dev, NORMAL_STATE_PWROFF); @@ -2659,7 +2659,7 @@ int normal_state_pwroff(bpctl_dev_t *pbpctl_dev) } /*TAP_STATE_PWRON 0x2a*/ -int tap_state_pwron(bpctl_dev_t *pbpctl_dev) +int tap_state_pwron(struct bpctl_dev *pbpctl_dev) { if (pbpctl_dev->bp_caps & TAP_PWUP_CTL_CAP) { write_data(pbpctl_dev, TAP_STATE_PWRON); @@ -2670,7 +2670,7 @@ int tap_state_pwron(bpctl_dev_t *pbpctl_dev) } /*DIS_TAP_CAP 0x2c*/ -int dis_tap_cap(bpctl_dev_t *pbpctl_dev) +int dis_tap_cap(struct bpctl_dev *pbpctl_dev) { if (pbpctl_dev->bp_caps & TAP_DIS_CAP) { write_data(pbpctl_dev, DIS_TAP_CAP); @@ -2681,7 +2681,7 @@ int dis_tap_cap(bpctl_dev_t *pbpctl_dev) } /*EN_TAP_CAP 0x2e*/ -int en_tap_cap(bpctl_dev_t *pbpctl_dev) +int en_tap_cap(struct bpctl_dev *pbpctl_dev) { if (pbpctl_dev->bp_caps & TAP_DIS_CAP) { write_data(pbpctl_dev, EN_TAP_CAP); @@ -2692,7 +2692,7 @@ int en_tap_cap(bpctl_dev_t *pbpctl_dev) } /*DISC_STATE_PWRON 0x2a*/ -int disc_state_pwron(bpctl_dev_t *pbpctl_dev) +int disc_state_pwron(struct bpctl_dev *pbpctl_dev) { if (pbpctl_dev->bp_caps & DISC_PWUP_CTL_CAP) { if (pbpctl_dev->bp_ext_ver >= 0x8) { @@ -2705,7 +2705,7 @@ int disc_state_pwron(bpctl_dev_t *pbpctl_dev) } /*DIS_DISC_CAP 0x2c*/ -int dis_disc_cap(bpctl_dev_t *pbpctl_dev) +int dis_disc_cap(struct bpctl_dev *pbpctl_dev) { if (pbpctl_dev->bp_caps & DISC_DIS_CAP) { if (pbpctl_dev->bp_ext_ver >= 0x8) { @@ -2718,10 +2718,10 @@ int dis_disc_cap(bpctl_dev_t *pbpctl_dev) } /*DISC_STATE_PWRON 0x2a*/ -int disc_port_state_pwron(bpctl_dev_t *pbpctl_dev) +int disc_port_state_pwron(struct bpctl_dev *pbpctl_dev) { int ret = 0; - bpctl_dev_t *pbpctl_dev_m; + struct bpctl_dev *pbpctl_dev_m; return BP_NOT_CAP; @@ -2744,10 +2744,10 @@ int disc_port_state_pwron(bpctl_dev_t *pbpctl_dev) return ret; } -int normal_port_state_pwron(bpctl_dev_t *pbpctl_dev) +int normal_port_state_pwron(struct bpctl_dev *pbpctl_dev) { int ret = 0; - bpctl_dev_t *pbpctl_dev_m; + struct bpctl_dev *pbpctl_dev_m; return BP_NOT_CAP; if ((is_bypass_fn(pbpctl_dev)) == 1) @@ -2770,7 +2770,7 @@ int normal_port_state_pwron(bpctl_dev_t *pbpctl_dev) } /*EN_TAP_CAP 0x2e*/ -int en_disc_cap(bpctl_dev_t *pbpctl_dev) +int en_disc_cap(struct bpctl_dev *pbpctl_dev) { if (pbpctl_dev->bp_caps & DISC_DIS_CAP) { if (pbpctl_dev->bp_ext_ver >= 0x8) { @@ -2782,7 +2782,7 @@ int en_disc_cap(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -int std_nic_on(bpctl_dev_t *pbpctl_dev) +int std_nic_on(struct bpctl_dev *pbpctl_dev) { if (pbpctl_dev->bp_caps & STD_NIC_CAP) { @@ -2836,7 +2836,7 @@ int std_nic_on(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -int std_nic_off(bpctl_dev_t *pbpctl_dev) +int std_nic_off(struct bpctl_dev *pbpctl_dev) { if (pbpctl_dev->bp_caps & STD_NIC_CAP) { @@ -2888,7 +2888,7 @@ int std_nic_off(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -int wdt_time_left(bpctl_dev_t *pbpctl_dev) +int wdt_time_left(struct bpctl_dev *pbpctl_dev) { /* unsigned long curr_time=((long long)(jiffies*1000))/HZ, delta_time=0,wdt_on_time=((long long)(pbpctl_dev->bypass_wdt_on_time*1000))/HZ; */ @@ -2920,7 +2920,7 @@ int wdt_time_left(bpctl_dev_t *pbpctl_dev) return time_left; } -static int wdt_timer(bpctl_dev_t *pbpctl_dev, int *time_left) +static int wdt_timer(struct bpctl_dev *pbpctl_dev, int *time_left) { int ret = 0; if (pbpctl_dev->bp_caps & WD_CTL_CAP) { @@ -2936,7 +2936,7 @@ static int wdt_timer(bpctl_dev_t *pbpctl_dev, int *time_left) return ret; } -static int wdt_timer_reload(bpctl_dev_t *pbpctl_dev) +static int wdt_timer_reload(struct bpctl_dev *pbpctl_dev) { int ret = 0; @@ -2960,7 +2960,7 @@ static int wdt_timer_reload(bpctl_dev_t *pbpctl_dev) static void wd_reset_timer(unsigned long param) { - bpctl_dev_t *pbpctl_dev = (bpctl_dev_t *) param; + struct bpctl_dev *pbpctl_dev = (struct bpctl_dev *) param; #ifdef BP_SELF_TEST struct sk_buff *skb_tmp; #endif @@ -2999,7 +2999,7 @@ static void wd_reset_timer(unsigned long param) } /*WAIT_AT_PWRUP 0x80 */ -int bp_wait_at_pwup_en(bpctl_dev_t *pbpctl_dev) +int bp_wait_at_pwup_en(struct bpctl_dev *pbpctl_dev) { if (pbpctl_dev->bp_caps & SW_CTL_CAP) { @@ -3014,7 +3014,7 @@ int bp_wait_at_pwup_en(bpctl_dev_t *pbpctl_dev) } /*DIS_WAIT_AT_PWRUP 0x81 */ -int bp_wait_at_pwup_dis(bpctl_dev_t *pbpctl_dev) +int bp_wait_at_pwup_dis(struct bpctl_dev *pbpctl_dev) { if (pbpctl_dev->bp_caps & SW_CTL_CAP) { @@ -3031,7 +3031,7 @@ int bp_wait_at_pwup_dis(bpctl_dev_t *pbpctl_dev) /*EN_HW_RESET 0x82 */ -int bp_hw_reset_en(bpctl_dev_t *pbpctl_dev) +int bp_hw_reset_en(struct bpctl_dev *pbpctl_dev) { if (pbpctl_dev->bp_caps & SW_CTL_CAP) { @@ -3047,7 +3047,7 @@ int bp_hw_reset_en(bpctl_dev_t *pbpctl_dev) /*DIS_HW_RESET 0x83 */ -int bp_hw_reset_dis(bpctl_dev_t *pbpctl_dev) +int bp_hw_reset_dis(struct bpctl_dev *pbpctl_dev) { if (pbpctl_dev->bp_caps & SW_CTL_CAP) { @@ -3062,7 +3062,7 @@ int bp_hw_reset_dis(bpctl_dev_t *pbpctl_dev) } -int wdt_exp_mode(bpctl_dev_t *pbpctl_dev, int mode) +int wdt_exp_mode(struct bpctl_dev *pbpctl_dev, int mode) { uint32_t status_reg = 0, status_reg1 = 0; @@ -3113,7 +3113,7 @@ int wdt_exp_mode(bpctl_dev_t *pbpctl_dev, int mode) return BP_NOT_CAP; } -int bypass_fw_ver(bpctl_dev_t *pbpctl_dev) +int bypass_fw_ver(struct bpctl_dev *pbpctl_dev) { if (is_bypass_fn(pbpctl_dev)) return read_reg(pbpctl_dev, VER_REG_ADDR); @@ -3121,7 +3121,7 @@ int bypass_fw_ver(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -int bypass_sign_check(bpctl_dev_t *pbpctl_dev) +int bypass_sign_check(struct bpctl_dev *pbpctl_dev) { if (is_bypass_fn(pbpctl_dev)) @@ -3131,10 +3131,10 @@ int bypass_sign_check(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -static int tx_status(bpctl_dev_t *pbpctl_dev) +static int tx_status(struct bpctl_dev *pbpctl_dev) { uint32_t ctrl = 0; - bpctl_dev_t *pbpctl_dev_m; + struct bpctl_dev *pbpctl_dev_m; if ((is_bypass_fn(pbpctl_dev)) == 1) pbpctl_dev_m = pbpctl_dev; else @@ -3218,7 +3218,7 @@ static int tx_status(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -static int bp_force_link_status(bpctl_dev_t *pbpctl_dev) +static int bp_force_link_status(struct bpctl_dev *pbpctl_dev) { if (DBI_IF_SERIES(pbpctl_dev->subdevice)) { @@ -3232,10 +3232,10 @@ static int bp_force_link_status(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -int bypass_from_last_read(bpctl_dev_t *pbpctl_dev) +int bypass_from_last_read(struct bpctl_dev *pbpctl_dev) { uint32_t ctrl_ext = 0; - bpctl_dev_t *pbpctl_dev_b = NULL; + struct bpctl_dev *pbpctl_dev_b = NULL; if (pbpctl_dev->bp_caps & SW_CTL_CAP) { pbpctl_dev_b = get_status_port_fn(pbpctl_dev); @@ -3252,9 +3252,9 @@ int bypass_from_last_read(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -int bypass_status_clear(bpctl_dev_t *pbpctl_dev) +int bypass_status_clear(struct bpctl_dev *pbpctl_dev) { - bpctl_dev_t *pbpctl_dev_b = NULL; + struct bpctl_dev *pbpctl_dev_b = NULL; if (pbpctl_dev->bp_caps & SW_CTL_CAP) { pbpctl_dev_b = get_status_port_fn(pbpctl_dev); @@ -3266,7 +3266,7 @@ int bypass_status_clear(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -int bypass_flag_status(bpctl_dev_t *pbpctl_dev) +int bypass_flag_status(struct bpctl_dev *pbpctl_dev) { if ((pbpctl_dev->bp_caps & BP_CAP)) { @@ -3279,7 +3279,7 @@ int bypass_flag_status(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -int bypass_flag_status_clear(bpctl_dev_t *pbpctl_dev) +int bypass_flag_status_clear(struct bpctl_dev *pbpctl_dev) { if (pbpctl_dev->bp_caps & BP_CAP) { @@ -3294,7 +3294,7 @@ int bypass_flag_status_clear(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -int bypass_change_status(bpctl_dev_t *pbpctl_dev) +int bypass_change_status(struct bpctl_dev *pbpctl_dev) { int ret = BP_NOT_CAP; @@ -3313,7 +3313,7 @@ int bypass_change_status(bpctl_dev_t *pbpctl_dev) return ret; } -int bypass_off_status(bpctl_dev_t *pbpctl_dev) +int bypass_off_status(struct bpctl_dev *pbpctl_dev) { if (pbpctl_dev->bp_caps & BP_CAP) { @@ -3325,12 +3325,12 @@ int bypass_off_status(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -static int bypass_status(bpctl_dev_t *pbpctl_dev) +static int bypass_status(struct bpctl_dev *pbpctl_dev) { u32 ctrl_ext = 0; if (pbpctl_dev->bp_caps & BP_CAP) { - bpctl_dev_t *pbpctl_dev_b = NULL; + struct bpctl_dev *pbpctl_dev_b = NULL; pbpctl_dev_b = get_status_port_fn(pbpctl_dev); if (!pbpctl_dev_b) @@ -3408,7 +3408,7 @@ static int bypass_status(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -int default_pwron_status(bpctl_dev_t *pbpctl_dev) +int default_pwron_status(struct bpctl_dev *pbpctl_dev) { if (pbpctl_dev->bp_caps & SW_CTL_CAP) { @@ -3426,7 +3426,7 @@ int default_pwron_status(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -static int default_pwroff_status(bpctl_dev_t *pbpctl_dev) +static int default_pwroff_status(struct bpctl_dev *pbpctl_dev) { /*if ((!pbpctl_dev->bp_caps&BP_DIS_CAP)&& @@ -3440,7 +3440,7 @@ static int default_pwroff_status(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -int dis_bypass_cap_status(bpctl_dev_t *pbpctl_dev) +int dis_bypass_cap_status(struct bpctl_dev *pbpctl_dev) { if (pbpctl_dev->bp_caps & BP_DIS_CAP) { @@ -3453,7 +3453,7 @@ int dis_bypass_cap_status(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -int cmd_en_status(bpctl_dev_t *pbpctl_dev) +int cmd_en_status(struct bpctl_dev *pbpctl_dev) { if (pbpctl_dev->bp_caps & SW_CTL_CAP) { @@ -3465,7 +3465,7 @@ int cmd_en_status(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -int wdt_en_status(bpctl_dev_t *pbpctl_dev) +int wdt_en_status(struct bpctl_dev *pbpctl_dev) { if (pbpctl_dev->bp_caps & WD_CTL_CAP) { @@ -3477,7 +3477,7 @@ int wdt_en_status(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -int wdt_programmed(bpctl_dev_t *pbpctl_dev, int *timeout) +int wdt_programmed(struct bpctl_dev *pbpctl_dev, int *timeout) { int ret = 0; if (pbpctl_dev->bp_caps & WD_CTL_CAP) { @@ -3503,7 +3503,7 @@ int wdt_programmed(bpctl_dev_t *pbpctl_dev, int *timeout) return ret; } -int bypass_support(bpctl_dev_t *pbpctl_dev) +int bypass_support(struct bpctl_dev *pbpctl_dev) { int ret = 0; @@ -3520,7 +3520,7 @@ int bypass_support(bpctl_dev_t *pbpctl_dev) return ret; } -int tap_support(bpctl_dev_t *pbpctl_dev) +int tap_support(struct bpctl_dev *pbpctl_dev) { int ret = 0; @@ -3536,7 +3536,7 @@ int tap_support(bpctl_dev_t *pbpctl_dev) return ret; } -int normal_support(bpctl_dev_t *pbpctl_dev) +int normal_support(struct bpctl_dev *pbpctl_dev) { int ret = BP_NOT_CAP; @@ -3552,7 +3552,7 @@ int normal_support(bpctl_dev_t *pbpctl_dev) return ret; } -int get_bp_prod_caps(bpctl_dev_t *pbpctl_dev) +int get_bp_prod_caps(struct bpctl_dev *pbpctl_dev) { if ((pbpctl_dev->bp_caps & SW_CTL_CAP) && (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER)) @@ -3561,7 +3561,7 @@ int get_bp_prod_caps(bpctl_dev_t *pbpctl_dev) } -int tap_flag_status(bpctl_dev_t *pbpctl_dev) +int tap_flag_status(struct bpctl_dev *pbpctl_dev) { if (pbpctl_dev->bp_caps & TAP_STATUS_CAP) { @@ -3573,7 +3573,7 @@ int tap_flag_status(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -int tap_flag_status_clear(bpctl_dev_t *pbpctl_dev) +int tap_flag_status_clear(struct bpctl_dev *pbpctl_dev) { uint32_t status_reg = 0; if (pbpctl_dev->bp_caps & TAP_STATUS_CAP) { @@ -3587,7 +3587,7 @@ int tap_flag_status_clear(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -int tap_change_status(bpctl_dev_t *pbpctl_dev) +int tap_change_status(struct bpctl_dev *pbpctl_dev) { int ret = BP_NOT_CAP; if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER) { @@ -3604,7 +3604,7 @@ int tap_change_status(bpctl_dev_t *pbpctl_dev) return ret; } -int tap_off_status(bpctl_dev_t *pbpctl_dev) +int tap_off_status(struct bpctl_dev *pbpctl_dev) { if (pbpctl_dev->bp_caps & TAP_CAP) { if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER) @@ -3614,12 +3614,12 @@ int tap_off_status(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -int tap_status(bpctl_dev_t *pbpctl_dev) +int tap_status(struct bpctl_dev *pbpctl_dev) { u32 ctrl_ext = 0; if (pbpctl_dev->bp_caps & TAP_CAP) { - bpctl_dev_t *pbpctl_dev_b = NULL; + struct bpctl_dev *pbpctl_dev_b = NULL; pbpctl_dev_b = get_status_port_fn(pbpctl_dev); if (!pbpctl_dev_b) @@ -3653,7 +3653,7 @@ int tap_status(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -int default_pwron_tap_status(bpctl_dev_t *pbpctl_dev) +int default_pwron_tap_status(struct bpctl_dev *pbpctl_dev) { if (pbpctl_dev->bp_caps & TAP_PWUP_CTL_CAP) { if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER) @@ -3664,7 +3664,7 @@ int default_pwron_tap_status(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -int dis_tap_cap_status(bpctl_dev_t *pbpctl_dev) +int dis_tap_cap_status(struct bpctl_dev *pbpctl_dev) { if (pbpctl_dev->bp_caps & TAP_PWUP_CTL_CAP) { if (pbpctl_dev->bp_ext_ver >= PXG2TBPI_VER) @@ -3675,7 +3675,7 @@ int dis_tap_cap_status(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -int disc_flag_status(bpctl_dev_t *pbpctl_dev) +int disc_flag_status(struct bpctl_dev *pbpctl_dev) { if (pbpctl_dev->bp_caps & DISC_CAP) { @@ -3687,7 +3687,7 @@ int disc_flag_status(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -int disc_flag_status_clear(bpctl_dev_t *pbpctl_dev) +int disc_flag_status_clear(struct bpctl_dev *pbpctl_dev) { uint32_t status_reg = 0; if (pbpctl_dev->bp_caps & DISC_CAP) { @@ -3701,7 +3701,7 @@ int disc_flag_status_clear(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -int disc_change_status(bpctl_dev_t *pbpctl_dev) +int disc_change_status(struct bpctl_dev *pbpctl_dev) { int ret = BP_NOT_CAP; if (pbpctl_dev->bp_caps & DISC_CAP) { @@ -3712,9 +3712,9 @@ int disc_change_status(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -int disc_off_status(bpctl_dev_t *pbpctl_dev) +int disc_off_status(struct bpctl_dev *pbpctl_dev) { - bpctl_dev_t *pbpctl_dev_b = NULL; + struct bpctl_dev *pbpctl_dev_b = NULL; u32 ctrl_ext = 0; if (pbpctl_dev->bp_caps & DISC_CAP) { @@ -3796,7 +3796,7 @@ int disc_off_status(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -static int disc_status(bpctl_dev_t *pbpctl_dev) +static int disc_status(struct bpctl_dev *pbpctl_dev) { int ctrl = 0; if (pbpctl_dev->bp_caps & DISC_CAP) { @@ -3808,7 +3808,7 @@ static int disc_status(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -int default_pwron_disc_status(bpctl_dev_t *pbpctl_dev) +int default_pwron_disc_status(struct bpctl_dev *pbpctl_dev) { if (pbpctl_dev->bp_caps & DISC_PWUP_CTL_CAP) { if (pbpctl_dev->bp_ext_ver >= 0x8) @@ -3819,7 +3819,7 @@ int default_pwron_disc_status(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -int dis_disc_cap_status(bpctl_dev_t *pbpctl_dev) +int dis_disc_cap_status(struct bpctl_dev *pbpctl_dev) { if (pbpctl_dev->bp_caps & DIS_DISC_CAP) { if (pbpctl_dev->bp_ext_ver >= 0x8) @@ -3830,10 +3830,10 @@ int dis_disc_cap_status(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -int disc_port_status(bpctl_dev_t *pbpctl_dev) +int disc_port_status(struct bpctl_dev *pbpctl_dev) { int ret = BP_NOT_CAP; - bpctl_dev_t *pbpctl_dev_m; + struct bpctl_dev *pbpctl_dev_m; if ((is_bypass_fn(pbpctl_dev)) == 1) pbpctl_dev_m = pbpctl_dev; @@ -3854,10 +3854,10 @@ int disc_port_status(bpctl_dev_t *pbpctl_dev) return ret; } -int default_pwron_disc_port_status(bpctl_dev_t *pbpctl_dev) +int default_pwron_disc_port_status(struct bpctl_dev *pbpctl_dev) { int ret = BP_NOT_CAP; - bpctl_dev_t *pbpctl_dev_m; + struct bpctl_dev *pbpctl_dev_m; if ((is_bypass_fn(pbpctl_dev)) == 1) pbpctl_dev_m = pbpctl_dev; @@ -3878,7 +3878,7 @@ int default_pwron_disc_port_status(bpctl_dev_t *pbpctl_dev) return ret; } -int wdt_exp_mode_status(bpctl_dev_t *pbpctl_dev) +int wdt_exp_mode_status(struct bpctl_dev *pbpctl_dev) { if (pbpctl_dev->bp_caps & WD_CTL_CAP) { if (pbpctl_dev->bp_ext_ver <= PXG2BPI_VER) @@ -3901,7 +3901,7 @@ int wdt_exp_mode_status(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -int tpl2_flag_status(bpctl_dev_t *pbpctl_dev) +int tpl2_flag_status(struct bpctl_dev *pbpctl_dev) { if (pbpctl_dev->bp_caps_ex & TPL2_CAP_EX) { @@ -3912,9 +3912,9 @@ int tpl2_flag_status(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -int tpl_hw_status(bpctl_dev_t *pbpctl_dev) +int tpl_hw_status(struct bpctl_dev *pbpctl_dev) { - bpctl_dev_t *pbpctl_dev_b = NULL; + struct bpctl_dev *pbpctl_dev_b = NULL; pbpctl_dev_b = get_status_port_fn(pbpctl_dev); if (!pbpctl_dev_b) @@ -3927,7 +3927,7 @@ int tpl_hw_status(bpctl_dev_t *pbpctl_dev) } -int bp_wait_at_pwup_status(bpctl_dev_t *pbpctl_dev) +int bp_wait_at_pwup_status(struct bpctl_dev *pbpctl_dev) { if (pbpctl_dev->bp_caps & SW_CTL_CAP) { if (pbpctl_dev->bp_ext_ver >= 0x8) @@ -3938,7 +3938,7 @@ int bp_wait_at_pwup_status(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -int bp_hw_reset_status(bpctl_dev_t *pbpctl_dev) +int bp_hw_reset_status(struct bpctl_dev *pbpctl_dev) { if (pbpctl_dev->bp_caps & SW_CTL_CAP) { @@ -3952,7 +3952,7 @@ int bp_hw_reset_status(bpctl_dev_t *pbpctl_dev) } -int std_nic_status(bpctl_dev_t *pbpctl_dev) +int std_nic_status(struct bpctl_dev *pbpctl_dev) { int status_val = 0; @@ -4000,10 +4000,10 @@ int std_nic_status(bpctl_dev_t *pbpctl_dev) /******************************************************/ /**************SW_INIT*********************************/ /******************************************************/ -void bypass_caps_init(bpctl_dev_t *pbpctl_dev) +void bypass_caps_init(struct bpctl_dev *pbpctl_dev) { u_int32_t ctrl_ext = 0; - bpctl_dev_t *pbpctl_dev_m = NULL; + struct bpctl_dev *pbpctl_dev_m = NULL; #ifdef BYPASS_DEBUG int ret = 0; @@ -4218,7 +4218,7 @@ void bypass_caps_init(bpctl_dev_t *pbpctl_dev) } } -int bypass_off_init(bpctl_dev_t *pbpctl_dev) +int bypass_off_init(struct bpctl_dev *pbpctl_dev) { int ret = cmnd_on(pbpctl_dev); if (ret < 0) @@ -4234,10 +4234,10 @@ int bypass_off_init(bpctl_dev_t *pbpctl_dev) return 0; } -void remove_bypass_wd_auto(bpctl_dev_t *pbpctl_dev) +void remove_bypass_wd_auto(struct bpctl_dev *pbpctl_dev) { #ifdef BP_SELF_TEST - bpctl_dev_t *pbpctl_dev_sl = NULL; + struct bpctl_dev *pbpctl_dev_sl = NULL; #endif if (pbpctl_dev->bp_caps & WD_CTL_CAP) { @@ -4263,7 +4263,7 @@ void remove_bypass_wd_auto(bpctl_dev_t *pbpctl_dev) } -int init_bypass_wd_auto(bpctl_dev_t *pbpctl_dev) +int init_bypass_wd_auto(struct bpctl_dev *pbpctl_dev) { if (pbpctl_dev->bp_caps & WD_CTL_CAP) { init_timer(&pbpctl_dev->bp_timer); @@ -4277,7 +4277,7 @@ int init_bypass_wd_auto(bpctl_dev_t *pbpctl_dev) #ifdef BP_SELF_TEST int bp_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { - bpctl_dev_t *pbpctl_dev = NULL, *pbpctl_dev_m = NULL; + struct bpctl_dev *pbpctl_dev = NULL, *pbpctl_dev_m = NULL; int idx_dev = 0; struct ethhdr *eth = (struct ethhdr *)skb->data; @@ -4310,7 +4310,7 @@ int bp_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) } #endif -int set_bypass_wd_auto(bpctl_dev_t *pbpctl_dev, unsigned int param) +int set_bypass_wd_auto(struct bpctl_dev *pbpctl_dev, unsigned int param) { if (pbpctl_dev->bp_caps & WD_CTL_CAP) { if (pbpctl_dev->reset_time != param) { @@ -4329,7 +4329,7 @@ int set_bypass_wd_auto(bpctl_dev_t *pbpctl_dev, unsigned int param) return BP_NOT_CAP; } -int get_bypass_wd_auto(bpctl_dev_t *pbpctl_dev) +int get_bypass_wd_auto(struct bpctl_dev *pbpctl_dev) { if (pbpctl_dev->bp_caps & WD_CTL_CAP) return pbpctl_dev->reset_time; @@ -4339,9 +4339,9 @@ int get_bypass_wd_auto(bpctl_dev_t *pbpctl_dev) #ifdef BP_SELF_TEST -int set_bp_self_test(bpctl_dev_t *pbpctl_dev, unsigned int param) +int set_bp_self_test(struct bpctl_dev *pbpctl_dev, unsigned int param) { - bpctl_dev_t *pbpctl_dev_sl = NULL; + struct bpctl_dev *pbpctl_dev_sl = NULL; if (pbpctl_dev->bp_caps & WD_CTL_CAP) { pbpctl_dev->bp_self_test_flag = param == 0 ? 0 : 1; @@ -4374,7 +4374,7 @@ int set_bp_self_test(bpctl_dev_t *pbpctl_dev, unsigned int param) return BP_NOT_CAP; } -int get_bp_self_test(bpctl_dev_t *pbpctl_dev) +int get_bp_self_test(struct bpctl_dev *pbpctl_dev) { if (pbpctl_dev->bp_caps & WD_CTL_CAP) { @@ -4392,7 +4392,7 @@ int get_bp_self_test(bpctl_dev_t *pbpctl_dev) /************************* API ********************************/ /**************************************************************/ -int is_bypass_fn(bpctl_dev_t *pbpctl_dev) +int is_bypass_fn(struct bpctl_dev *pbpctl_dev) { if (!pbpctl_dev) return -1; @@ -4400,7 +4400,7 @@ int is_bypass_fn(bpctl_dev_t *pbpctl_dev) return (((pbpctl_dev->func == 0) || (pbpctl_dev->func == 2)) ? 1 : 0); } -int set_bypass_fn(bpctl_dev_t *pbpctl_dev, int bypass_mode) +int set_bypass_fn(struct bpctl_dev *pbpctl_dev, int bypass_mode) { int ret = 0; @@ -4418,12 +4418,12 @@ int set_bypass_fn(bpctl_dev_t *pbpctl_dev, int bypass_mode) return ret; } -int get_bypass_fn(bpctl_dev_t *pbpctl_dev) +int get_bypass_fn(struct bpctl_dev *pbpctl_dev) { return bypass_status(pbpctl_dev); } -int get_bypass_change_fn(bpctl_dev_t *pbpctl_dev) +int get_bypass_change_fn(struct bpctl_dev *pbpctl_dev) { if (!pbpctl_dev) return -1; @@ -4431,7 +4431,7 @@ int get_bypass_change_fn(bpctl_dev_t *pbpctl_dev) return bypass_change_status(pbpctl_dev); } -int set_dis_bypass_fn(bpctl_dev_t *pbpctl_dev, int dis_param) +int set_dis_bypass_fn(struct bpctl_dev *pbpctl_dev, int dis_param) { int ret = 0; if (!pbpctl_dev) @@ -4450,7 +4450,7 @@ int set_dis_bypass_fn(bpctl_dev_t *pbpctl_dev, int dis_param) return ret; } -int get_dis_bypass_fn(bpctl_dev_t *pbpctl_dev) +int get_dis_bypass_fn(struct bpctl_dev *pbpctl_dev) { if (!pbpctl_dev) return -1; @@ -4458,7 +4458,7 @@ int get_dis_bypass_fn(bpctl_dev_t *pbpctl_dev) return dis_bypass_cap_status(pbpctl_dev); } -int set_bypass_pwoff_fn(bpctl_dev_t *pbpctl_dev, int bypass_mode) +int set_bypass_pwoff_fn(struct bpctl_dev *pbpctl_dev, int bypass_mode) { int ret = 0; if (!pbpctl_dev) @@ -4477,7 +4477,7 @@ int set_bypass_pwoff_fn(bpctl_dev_t *pbpctl_dev, int bypass_mode) return ret; } -int get_bypass_pwoff_fn(bpctl_dev_t *pbpctl_dev) +int get_bypass_pwoff_fn(struct bpctl_dev *pbpctl_dev) { if (!pbpctl_dev) return -1; @@ -4485,7 +4485,7 @@ int get_bypass_pwoff_fn(bpctl_dev_t *pbpctl_dev) return default_pwroff_status(pbpctl_dev); } -int set_bypass_pwup_fn(bpctl_dev_t *pbpctl_dev, int bypass_mode) +int set_bypass_pwup_fn(struct bpctl_dev *pbpctl_dev, int bypass_mode) { int ret = 0; if (!pbpctl_dev) @@ -4504,7 +4504,7 @@ int set_bypass_pwup_fn(bpctl_dev_t *pbpctl_dev, int bypass_mode) return ret; } -int get_bypass_pwup_fn(bpctl_dev_t *pbpctl_dev) +int get_bypass_pwup_fn(struct bpctl_dev *pbpctl_dev) { if (!pbpctl_dev) return -1; @@ -4512,7 +4512,7 @@ int get_bypass_pwup_fn(bpctl_dev_t *pbpctl_dev) return default_pwron_status(pbpctl_dev); } -int set_bypass_wd_fn(bpctl_dev_t *pbpctl_dev, int timeout) +int set_bypass_wd_fn(struct bpctl_dev *pbpctl_dev, int timeout) { int ret = 0; if (!pbpctl_dev) @@ -4534,7 +4534,7 @@ int set_bypass_wd_fn(bpctl_dev_t *pbpctl_dev, int timeout) return ret; } -int get_bypass_wd_fn(bpctl_dev_t *pbpctl_dev, int *timeout) +int get_bypass_wd_fn(struct bpctl_dev *pbpctl_dev, int *timeout) { if (!pbpctl_dev) return -1; @@ -4542,7 +4542,7 @@ int get_bypass_wd_fn(bpctl_dev_t *pbpctl_dev, int *timeout) return wdt_programmed(pbpctl_dev, timeout); } -int get_wd_expire_time_fn(bpctl_dev_t *pbpctl_dev, int *time_left) +int get_wd_expire_time_fn(struct bpctl_dev *pbpctl_dev, int *time_left) { if (!pbpctl_dev) return -1; @@ -4550,7 +4550,7 @@ int get_wd_expire_time_fn(bpctl_dev_t *pbpctl_dev, int *time_left) return wdt_timer(pbpctl_dev, time_left); } -int reset_bypass_wd_timer_fn(bpctl_dev_t *pbpctl_dev) +int reset_bypass_wd_timer_fn(struct bpctl_dev *pbpctl_dev) { if (!pbpctl_dev) return -1; @@ -4558,7 +4558,7 @@ int reset_bypass_wd_timer_fn(bpctl_dev_t *pbpctl_dev) return wdt_timer_reload(pbpctl_dev); } -int get_wd_set_caps_fn(bpctl_dev_t *pbpctl_dev) +int get_wd_set_caps_fn(struct bpctl_dev *pbpctl_dev) { int bp_status = 0; @@ -4582,7 +4582,7 @@ int get_wd_set_caps_fn(bpctl_dev_t *pbpctl_dev) return bp_status; } -int set_std_nic_fn(bpctl_dev_t *pbpctl_dev, int nic_mode) +int set_std_nic_fn(struct bpctl_dev *pbpctl_dev, int nic_mode) { int ret = 0; if (!pbpctl_dev) @@ -4602,7 +4602,7 @@ int set_std_nic_fn(bpctl_dev_t *pbpctl_dev, int nic_mode) return ret; } -int get_std_nic_fn(bpctl_dev_t *pbpctl_dev) +int get_std_nic_fn(struct bpctl_dev *pbpctl_dev) { if (!pbpctl_dev) return -1; @@ -4610,7 +4610,7 @@ int get_std_nic_fn(bpctl_dev_t *pbpctl_dev) return std_nic_status(pbpctl_dev); } -int set_tap_fn(bpctl_dev_t *pbpctl_dev, int tap_mode) +int set_tap_fn(struct bpctl_dev *pbpctl_dev, int tap_mode) { if (!pbpctl_dev) return -1; @@ -4626,7 +4626,7 @@ int set_tap_fn(bpctl_dev_t *pbpctl_dev, int tap_mode) return BP_NOT_CAP; } -int get_tap_fn(bpctl_dev_t *pbpctl_dev) +int get_tap_fn(struct bpctl_dev *pbpctl_dev) { if (!pbpctl_dev) return -1; @@ -4634,7 +4634,7 @@ int get_tap_fn(bpctl_dev_t *pbpctl_dev) return tap_status(pbpctl_dev); } -int set_tap_pwup_fn(bpctl_dev_t *pbpctl_dev, int tap_mode) +int set_tap_pwup_fn(struct bpctl_dev *pbpctl_dev, int tap_mode) { int ret = 0; if (!pbpctl_dev) @@ -4652,7 +4652,7 @@ int set_tap_pwup_fn(bpctl_dev_t *pbpctl_dev, int tap_mode) return ret; } -int get_tap_pwup_fn(bpctl_dev_t *pbpctl_dev) +int get_tap_pwup_fn(struct bpctl_dev *pbpctl_dev) { int ret = 0; if (!pbpctl_dev) @@ -4664,7 +4664,7 @@ int get_tap_pwup_fn(bpctl_dev_t *pbpctl_dev) return ((ret == 0) ? 1 : 0); } -int get_tap_change_fn(bpctl_dev_t *pbpctl_dev) +int get_tap_change_fn(struct bpctl_dev *pbpctl_dev) { if (!pbpctl_dev) return -1; @@ -4672,7 +4672,7 @@ int get_tap_change_fn(bpctl_dev_t *pbpctl_dev) return tap_change_status(pbpctl_dev); } -int set_dis_tap_fn(bpctl_dev_t *pbpctl_dev, int dis_param) +int set_dis_tap_fn(struct bpctl_dev *pbpctl_dev, int dis_param) { int ret = 0; if (!pbpctl_dev) @@ -4689,7 +4689,7 @@ int set_dis_tap_fn(bpctl_dev_t *pbpctl_dev, int dis_param) return BP_NOT_CAP; } -int get_dis_tap_fn(bpctl_dev_t *pbpctl_dev) +int get_dis_tap_fn(struct bpctl_dev *pbpctl_dev) { if (!pbpctl_dev) return -1; @@ -4697,7 +4697,7 @@ int get_dis_tap_fn(bpctl_dev_t *pbpctl_dev) return dis_tap_cap_status(pbpctl_dev); } -int set_disc_fn(bpctl_dev_t *pbpctl_dev, int disc_mode) +int set_disc_fn(struct bpctl_dev *pbpctl_dev, int disc_mode) { if (!pbpctl_dev) return -1; @@ -4714,7 +4714,7 @@ int set_disc_fn(bpctl_dev_t *pbpctl_dev, int disc_mode) return BP_NOT_CAP; } -int get_disc_fn(bpctl_dev_t *pbpctl_dev) +int get_disc_fn(struct bpctl_dev *pbpctl_dev) { int ret = 0; if (!pbpctl_dev) @@ -4725,7 +4725,7 @@ int get_disc_fn(bpctl_dev_t *pbpctl_dev) return ret; } -int set_disc_pwup_fn(bpctl_dev_t *pbpctl_dev, int disc_mode) +int set_disc_pwup_fn(struct bpctl_dev *pbpctl_dev, int disc_mode) { int ret = 0; if (!pbpctl_dev) @@ -4743,7 +4743,7 @@ int set_disc_pwup_fn(bpctl_dev_t *pbpctl_dev, int disc_mode) return ret; } -int get_disc_pwup_fn(bpctl_dev_t *pbpctl_dev) +int get_disc_pwup_fn(struct bpctl_dev *pbpctl_dev) { int ret = 0; if (!pbpctl_dev) @@ -4753,7 +4753,7 @@ int get_disc_pwup_fn(bpctl_dev_t *pbpctl_dev) return (ret == 0 ? 1 : (ret < 0 ? BP_NOT_CAP : 0)); } -int get_disc_change_fn(bpctl_dev_t *pbpctl_dev) +int get_disc_change_fn(struct bpctl_dev *pbpctl_dev) { int ret = 0; if (!pbpctl_dev) @@ -4763,7 +4763,7 @@ int get_disc_change_fn(bpctl_dev_t *pbpctl_dev) return ret; } -int set_dis_disc_fn(bpctl_dev_t *pbpctl_dev, int dis_param) +int set_dis_disc_fn(struct bpctl_dev *pbpctl_dev, int dis_param) { int ret = 0; if (!pbpctl_dev) @@ -4781,7 +4781,7 @@ int set_dis_disc_fn(bpctl_dev_t *pbpctl_dev, int dis_param) return BP_NOT_CAP; } -int get_dis_disc_fn(bpctl_dev_t *pbpctl_dev) +int get_dis_disc_fn(struct bpctl_dev *pbpctl_dev) { int ret = 0; if (!pbpctl_dev) @@ -4792,7 +4792,7 @@ int get_dis_disc_fn(bpctl_dev_t *pbpctl_dev) return ret; } -int set_disc_port_fn(bpctl_dev_t *pbpctl_dev, int disc_mode) +int set_disc_port_fn(struct bpctl_dev *pbpctl_dev, int disc_mode) { int ret = BP_NOT_CAP; if (!pbpctl_dev) @@ -4806,7 +4806,7 @@ int set_disc_port_fn(bpctl_dev_t *pbpctl_dev, int disc_mode) return ret; } -int get_disc_port_fn(bpctl_dev_t *pbpctl_dev) +int get_disc_port_fn(struct bpctl_dev *pbpctl_dev) { if (!pbpctl_dev) return -1; @@ -4814,7 +4814,7 @@ int get_disc_port_fn(bpctl_dev_t *pbpctl_dev) return disc_port_status(pbpctl_dev); } -int set_disc_port_pwup_fn(bpctl_dev_t *pbpctl_dev, int disc_mode) +int set_disc_port_pwup_fn(struct bpctl_dev *pbpctl_dev, int disc_mode) { int ret = BP_NOT_CAP; if (!pbpctl_dev) @@ -4828,7 +4828,7 @@ int set_disc_port_pwup_fn(bpctl_dev_t *pbpctl_dev, int disc_mode) return ret; } -int get_disc_port_pwup_fn(bpctl_dev_t *pbpctl_dev) +int get_disc_port_pwup_fn(struct bpctl_dev *pbpctl_dev) { int ret = 0; if (!pbpctl_dev) @@ -4840,7 +4840,7 @@ int get_disc_port_pwup_fn(bpctl_dev_t *pbpctl_dev) return ((ret == 0) ? 1 : 0); } -int get_wd_exp_mode_fn(bpctl_dev_t *pbpctl_dev) +int get_wd_exp_mode_fn(struct bpctl_dev *pbpctl_dev) { if (!pbpctl_dev) return -1; @@ -4848,7 +4848,7 @@ int get_wd_exp_mode_fn(bpctl_dev_t *pbpctl_dev) return wdt_exp_mode_status(pbpctl_dev); } -int set_wd_exp_mode_fn(bpctl_dev_t *pbpctl_dev, int param) +int set_wd_exp_mode_fn(struct bpctl_dev *pbpctl_dev, int param) { if (!pbpctl_dev) return -1; @@ -4856,7 +4856,7 @@ int set_wd_exp_mode_fn(bpctl_dev_t *pbpctl_dev, int param) return wdt_exp_mode(pbpctl_dev, param); } -int reset_cont_fn(bpctl_dev_t *pbpctl_dev) +int reset_cont_fn(struct bpctl_dev *pbpctl_dev) { int ret = 0; if (!pbpctl_dev) @@ -4868,10 +4868,10 @@ int reset_cont_fn(bpctl_dev_t *pbpctl_dev) return reset_cont(pbpctl_dev); } -int set_tx_fn(bpctl_dev_t *pbpctl_dev, int tx_state) +int set_tx_fn(struct bpctl_dev *pbpctl_dev, int tx_state) { - bpctl_dev_t *pbpctl_dev_b = NULL; + struct bpctl_dev *pbpctl_dev_b = NULL; if (!pbpctl_dev) return -1; @@ -4891,7 +4891,7 @@ int set_tx_fn(bpctl_dev_t *pbpctl_dev, int tx_state) int set_bp_force_link_fn(int dev_num, int tx_state) { - static bpctl_dev_t *bpctl_dev_curr; + static struct bpctl_dev *bpctl_dev_curr; if ((dev_num < 0) || (dev_num > device_num) || (bpctl_dev_arr[dev_num].pdev == NULL)) @@ -4901,7 +4901,7 @@ int set_bp_force_link_fn(int dev_num, int tx_state) return set_bp_force_link(bpctl_dev_curr, tx_state); } -int set_wd_autoreset_fn(bpctl_dev_t *pbpctl_dev, int param) +int set_wd_autoreset_fn(struct bpctl_dev *pbpctl_dev, int param) { if (!pbpctl_dev) return -1; @@ -4909,7 +4909,7 @@ int set_wd_autoreset_fn(bpctl_dev_t *pbpctl_dev, int param) return set_bypass_wd_auto(pbpctl_dev, param); } -int get_wd_autoreset_fn(bpctl_dev_t *pbpctl_dev) +int get_wd_autoreset_fn(struct bpctl_dev *pbpctl_dev) { if (!pbpctl_dev) return -1; @@ -4918,7 +4918,7 @@ int get_wd_autoreset_fn(bpctl_dev_t *pbpctl_dev) } #ifdef BP_SELF_TEST -int set_bp_self_test_fn(bpctl_dev_t *pbpctl_dev, int param) +int set_bp_self_test_fn(struct bpctl_dev *pbpctl_dev, int param) { if (!pbpctl_dev) return -1; @@ -4926,7 +4926,7 @@ int set_bp_self_test_fn(bpctl_dev_t *pbpctl_dev, int param) return set_bp_self_test(pbpctl_dev, param); } -int get_bp_self_test_fn(bpctl_dev_t *pbpctl_dev) +int get_bp_self_test_fn(struct bpctl_dev *pbpctl_dev) { if (!pbpctl_dev) return -1; @@ -4936,7 +4936,7 @@ int get_bp_self_test_fn(bpctl_dev_t *pbpctl_dev) #endif -int get_bypass_caps_fn(bpctl_dev_t *pbpctl_dev) +int get_bypass_caps_fn(struct bpctl_dev *pbpctl_dev) { if (!pbpctl_dev) return -1; @@ -4945,7 +4945,7 @@ int get_bypass_caps_fn(bpctl_dev_t *pbpctl_dev) } -int get_bypass_slave_fn(bpctl_dev_t *pbpctl_dev, bpctl_dev_t **pbpctl_dev_out) +int get_bypass_slave_fn(struct bpctl_dev *pbpctl_dev, struct bpctl_dev **pbpctl_dev_out) { int idx_dev = 0; if (!pbpctl_dev) @@ -4977,7 +4977,7 @@ int get_bypass_slave_fn(bpctl_dev_t *pbpctl_dev, bpctl_dev_t **pbpctl_dev_out) return 0; } -int is_bypass(bpctl_dev_t *pbpctl_dev) +int is_bypass(struct bpctl_dev *pbpctl_dev) { if (!pbpctl_dev) return -1; @@ -4988,9 +4988,9 @@ int is_bypass(bpctl_dev_t *pbpctl_dev) return 0; } -int get_tx_fn(bpctl_dev_t *pbpctl_dev) +int get_tx_fn(struct bpctl_dev *pbpctl_dev) { - bpctl_dev_t *pbpctl_dev_b = NULL; + struct bpctl_dev *pbpctl_dev_b = NULL; if (!pbpctl_dev) return -1; @@ -5010,7 +5010,7 @@ int get_tx_fn(bpctl_dev_t *pbpctl_dev) int get_bp_force_link_fn(int dev_num) { - static bpctl_dev_t *bpctl_dev_curr; + static struct bpctl_dev *bpctl_dev_curr; if ((dev_num < 0) || (dev_num > device_num) || (bpctl_dev_arr[dev_num].pdev == NULL)) @@ -5020,7 +5020,7 @@ int get_bp_force_link_fn(int dev_num) return bp_force_link_status(bpctl_dev_curr); } -static int get_bypass_link_status(bpctl_dev_t *pbpctl_dev) +static int get_bypass_link_status(struct bpctl_dev *pbpctl_dev) { if (!pbpctl_dev) return -1; @@ -5036,9 +5036,9 @@ static int get_bypass_link_status(bpctl_dev_t *pbpctl_dev) static void bp_tpl_timer_fn(unsigned long param) { - bpctl_dev_t *pbpctl_dev = (bpctl_dev_t *) param; + struct bpctl_dev *pbpctl_dev = (struct bpctl_dev *) param; uint32_t link1, link2; - bpctl_dev_t *pbpctl_dev_b = NULL; + struct bpctl_dev *pbpctl_dev_b = NULL; pbpctl_dev_b = get_status_port_fn(pbpctl_dev); if (!pbpctl_dev_b) @@ -5071,9 +5071,9 @@ static void bp_tpl_timer_fn(unsigned long param) mod_timer(&pbpctl_dev->bp_tpl_timer, jiffies + BP_LINK_MON_DELAY * HZ); } -void remove_bypass_tpl_auto(bpctl_dev_t *pbpctl_dev) +void remove_bypass_tpl_auto(struct bpctl_dev *pbpctl_dev) { - bpctl_dev_t *pbpctl_dev_b = NULL; + struct bpctl_dev *pbpctl_dev_b = NULL; if (!pbpctl_dev) return; pbpctl_dev_b = get_status_port_fn(pbpctl_dev); @@ -5089,7 +5089,7 @@ void remove_bypass_tpl_auto(bpctl_dev_t *pbpctl_dev) return; } -int init_bypass_tpl_auto(bpctl_dev_t *pbpctl_dev) +int init_bypass_tpl_auto(struct bpctl_dev *pbpctl_dev) { if (!pbpctl_dev) return -1; @@ -5102,7 +5102,7 @@ int init_bypass_tpl_auto(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -int set_bypass_tpl_auto(bpctl_dev_t *pbpctl_dev, unsigned int param) +int set_bypass_tpl_auto(struct bpctl_dev *pbpctl_dev, unsigned int param) { if (!pbpctl_dev) return -1; @@ -5120,7 +5120,7 @@ int set_bypass_tpl_auto(bpctl_dev_t *pbpctl_dev, unsigned int param) return BP_NOT_CAP; } -int get_bypass_tpl_auto(bpctl_dev_t *pbpctl_dev) +int get_bypass_tpl_auto(struct bpctl_dev *pbpctl_dev) { if (!pbpctl_dev) return -1; @@ -5130,10 +5130,10 @@ int get_bypass_tpl_auto(bpctl_dev_t *pbpctl_dev) return BP_NOT_CAP; } -int set_tpl_fn(bpctl_dev_t *pbpctl_dev, int tpl_mode) +int set_tpl_fn(struct bpctl_dev *pbpctl_dev, int tpl_mode) { - bpctl_dev_t *pbpctl_dev_b = NULL; + struct bpctl_dev *pbpctl_dev_b = NULL; if (!pbpctl_dev) return -1; @@ -5160,7 +5160,7 @@ int set_tpl_fn(bpctl_dev_t *pbpctl_dev, int tpl_mode) return BP_NOT_CAP; } -int get_tpl_fn(bpctl_dev_t *pbpctl_dev) +int get_tpl_fn(struct bpctl_dev *pbpctl_dev) { int ret = BP_NOT_CAP; if (!pbpctl_dev) @@ -5174,7 +5174,7 @@ int get_tpl_fn(bpctl_dev_t *pbpctl_dev) return ret; } -int set_bp_wait_at_pwup_fn(bpctl_dev_t *pbpctl_dev, int tap_mode) +int set_bp_wait_at_pwup_fn(struct bpctl_dev *pbpctl_dev, int tap_mode) { if (!pbpctl_dev) return -1; @@ -5194,7 +5194,7 @@ int set_bp_wait_at_pwup_fn(bpctl_dev_t *pbpctl_dev, int tap_mode) return BP_NOT_CAP; } -int get_bp_wait_at_pwup_fn(bpctl_dev_t *pbpctl_dev) +int get_bp_wait_at_pwup_fn(struct bpctl_dev *pbpctl_dev) { int ret = 0; if (!pbpctl_dev) @@ -5207,7 +5207,7 @@ int get_bp_wait_at_pwup_fn(bpctl_dev_t *pbpctl_dev) return ret; } -int set_bp_hw_reset_fn(bpctl_dev_t *pbpctl_dev, int tap_mode) +int set_bp_hw_reset_fn(struct bpctl_dev *pbpctl_dev, int tap_mode) { if (!pbpctl_dev) return -1; @@ -5227,7 +5227,7 @@ int set_bp_hw_reset_fn(bpctl_dev_t *pbpctl_dev, int tap_mode) return BP_NOT_CAP; } -int get_bp_hw_reset_fn(bpctl_dev_t *pbpctl_dev) +int get_bp_hw_reset_fn(struct bpctl_dev *pbpctl_dev) { int ret = 0; if (!pbpctl_dev) @@ -5242,7 +5242,7 @@ int get_bp_hw_reset_fn(bpctl_dev_t *pbpctl_dev) } -int get_bypass_info_fn(bpctl_dev_t *pbpctl_dev, char *dev_name, +int get_bypass_info_fn(struct bpctl_dev *pbpctl_dev, char *dev_name, char *add_param) { if (!pbpctl_dev) @@ -5313,7 +5313,7 @@ static int get_dev_idx(int ifindex) return -1; } -static bpctl_dev_t *get_dev_idx_p(int ifindex) +static struct bpctl_dev *get_dev_idx_p(int ifindex) { int idx_dev = 0; @@ -5401,12 +5401,12 @@ static long device_ioctl(struct file *file, /* see include/linux/fs.h */ { struct bpctl_cmd bpctl_cmd; int dev_idx = 0; - bpctl_dev_t *pbpctl_dev_out; + struct bpctl_dev *pbpctl_dev_out; void __user *argp = (void __user *)ioctl_param; int ret = 0; unsigned long flags; - static bpctl_dev_t *pbpctl_dev; + static struct bpctl_dev *pbpctl_dev; /* lock_kernel(); */ if (down_interruptible(&bpctl_sema)) @@ -6623,7 +6623,7 @@ static bpmod_info_t tx_ctl_pci_tbl[] = { {0,} }; -static void find_fw(bpctl_dev_t *dev) +static void find_fw(struct bpctl_dev *dev) { unsigned long mmio_start, mmio_len; struct pci_dev *pdev1 = dev->pdev; @@ -6653,7 +6653,7 @@ static void find_fw(bpctl_dev_t *dev) printk("firmware version: 0x%x\n", dev->bp_fw_ver); } -static int init_one(bpctl_dev_t *dev, bpmod_info_t *info, struct pci_dev *pdev1) +static int init_one(struct bpctl_dev *dev, bpmod_info_t *info, struct pci_dev *pdev1) { unsigned long mmio_start, mmio_len; @@ -6744,7 +6744,7 @@ static int __init bypass_init_module(void) { int ret_val, idx, idx_dev = 0; struct pci_dev *pdev1 = NULL; - bpctl_dev_t *dev; + struct bpctl_dev *dev; printk(BP_MOD_DESCR " v" BP_MOD_VER "\n"); ret_val = register_chrdev(major_num, DEVICE_NAME, &Fops); @@ -6769,14 +6769,14 @@ static int __init bypass_init_module(void) return -1; } - bpctl_dev_arr = kmalloc((device_num) * sizeof(bpctl_dev_t), GFP_KERNEL); + bpctl_dev_arr = kmalloc((device_num) * sizeof(struct bpctl_dev), GFP_KERNEL); if (!bpctl_dev_arr) { printk("Allocation error\n"); unregister_chrdev(major_num, DEVICE_NAME); return -1; } - memset(bpctl_dev_arr, 0, ((device_num) * sizeof(bpctl_dev_t))); + memset(bpctl_dev_arr, 0, ((device_num) * sizeof(struct bpctl_dev))); pdev1 = NULL; dev = bpctl_dev_arr; @@ -6797,7 +6797,7 @@ static int __init bypass_init_module(void) spin_lock_init(&bpvm_lock); { - bpctl_dev_t *pbpctl_dev_c = NULL; + struct bpctl_dev *pbpctl_dev_c = NULL; for (idx_dev = 0, dev = bpctl_dev_arr; idx_dev < device_num && dev->pdev; idx_dev++, dev++) { @@ -7169,7 +7169,7 @@ EXPORT_SYMBOL(get_bypass_caps_sd); int get_bypass_slave_sd(int ifindex) { - bpctl_dev_t *pbpctl_dev_out; + struct bpctl_dev *pbpctl_dev_out; int ret = get_bypass_slave_fn(get_dev_idx_p(ifindex), &pbpctl_dev_out); if (ret == 1) return pbpctl_dev_out->ifindex; @@ -7229,7 +7229,7 @@ int bp_proc_create(void) } static int procfs_add(char *proc_name, const struct file_operations *fops, - bpctl_dev_t *dev) + struct bpctl_dev *dev) { struct bypass_pfs_sd *pfs = &dev->bypass_pfs_set; if (!proc_create_data(proc_name, 0644, pfs->bypass_entry, fops, dev)) @@ -7264,7 +7264,7 @@ static const struct file_operations name##_ops = { \ static int show_bypass_info(struct seq_file *m, void *v) { - bpctl_dev_t *dev = m->private; + struct bpctl_dev *dev = m->private; seq_printf(m, "Name\t\t\t%s\n", dev->name); seq_printf(m, "Firmware version\t0x%x\n", dev->bp_fw_ver); @@ -7274,8 +7274,8 @@ RO_FOPS(bypass_info) static int show_bypass_slave(struct seq_file *m, void *v) { - bpctl_dev_t *dev = m->private; - bpctl_dev_t *slave = get_status_port_fn(dev); + struct bpctl_dev *dev = m->private; + struct bpctl_dev *slave = get_status_port_fn(dev); if (!slave) slave = dev; if (!slave) @@ -7288,7 +7288,7 @@ RO_FOPS(bypass_slave) static int show_bypass_caps(struct seq_file *m, void *v) { - bpctl_dev_t *dev = m->private; + struct bpctl_dev *dev = m->private; int ret = get_bypass_caps_fn(dev); if (ret == BP_NOT_CAP) seq_puts(m, "-1\n"); @@ -7300,7 +7300,7 @@ RO_FOPS(bypass_caps) static int show_wd_set_caps(struct seq_file *m, void *v) { - bpctl_dev_t *dev = m->private; + struct bpctl_dev *dev = m->private; int ret = get_wd_set_caps_fn(dev); if (ret == BP_NOT_CAP) seq_puts(m, "-1\n"); @@ -7346,7 +7346,7 @@ static ssize_t bypass_write(struct file *file, const char __user *buffer, } static int show_bypass(struct seq_file *m, void *v) { - bpctl_dev_t *dev = m->private; + struct bpctl_dev *dev = m->private; int ret = get_bypass_fn(dev); if (ret == BP_NOT_CAP) seq_puts(m, "fail\n"); @@ -7370,7 +7370,7 @@ static ssize_t tap_write(struct file *file, const char __user *buffer, } static int show_tap(struct seq_file *m, void *v) { - bpctl_dev_t *dev = m->private; + struct bpctl_dev *dev = m->private; int ret = get_tap_fn(dev); if (ret == BP_NOT_CAP) seq_puts(m, "fail\n"); @@ -7394,7 +7394,7 @@ static ssize_t disc_write(struct file *file, const char __user *buffer, } static int show_disc(struct seq_file *m, void *v) { - bpctl_dev_t *dev = m->private; + struct bpctl_dev *dev = m->private; int ret = get_disc_fn(dev); if (ret == BP_NOT_CAP) seq_puts(m, "fail\n"); @@ -7408,7 +7408,7 @@ RW_FOPS(disc) static int show_bypass_change(struct seq_file *m, void *v) { - bpctl_dev_t *dev = m->private; + struct bpctl_dev *dev = m->private; int ret = get_bypass_change_fn(dev); if (ret == 1) seq_puts(m, "on\n"); @@ -7422,7 +7422,7 @@ RO_FOPS(bypass_change) static int show_tap_change(struct seq_file *m, void *v) { - bpctl_dev_t *dev = m->private; + struct bpctl_dev *dev = m->private; int ret = get_tap_change_fn(dev); if (ret == 1) seq_puts(m, "on\n"); @@ -7436,7 +7436,7 @@ RO_FOPS(tap_change) static int show_disc_change(struct seq_file *m, void *v) { - bpctl_dev_t *dev = m->private; + struct bpctl_dev *dev = m->private; int ret = get_disc_change_fn(dev); if (ret == 1) seq_puts(m, "on\n"); @@ -7451,7 +7451,7 @@ RO_FOPS(disc_change) static ssize_t bypass_wd_write(struct file *file, const char __user *buffer, size_t count, loff_t *pos) { - bpctl_dev_t *dev = PDE_DATA(file_inode(file)); + struct bpctl_dev *dev = PDE_DATA(file_inode(file)); int timeout; int ret = kstrtoint_from_user(buffer, count, 10, &timeout); if (ret) @@ -7461,7 +7461,7 @@ static ssize_t bypass_wd_write(struct file *file, const char __user *buffer, } static int show_bypass_wd(struct seq_file *m, void *v) { - bpctl_dev_t *dev = m->private; + struct bpctl_dev *dev = m->private; int ret = 0, timeout = 0; ret = get_bypass_wd_fn(dev, &timeout); @@ -7479,7 +7479,7 @@ RW_FOPS(bypass_wd) static int show_wd_expire_time(struct seq_file *m, void *v) { - bpctl_dev_t *dev = m->private; + struct bpctl_dev *dev = m->private; int ret = 0, timeout = 0; ret = get_wd_expire_time_fn(dev, &timeout); if (ret == BP_NOT_CAP) @@ -7497,7 +7497,7 @@ RO_FOPS(wd_expire_time) static ssize_t tpl_write(struct file *file, const char __user *buffer, size_t count, loff_t *pos) { - bpctl_dev_t *dev = PDE_DATA(file_inode(file)); + struct bpctl_dev *dev = PDE_DATA(file_inode(file)); int tpl_param = user_on_off(buffer, count); if (tpl_param < 0) return -1; @@ -7507,7 +7507,7 @@ static ssize_t tpl_write(struct file *file, const char __user *buffer, } static int show_tpl(struct seq_file *m, void *v) { - bpctl_dev_t *dev = m->private; + struct bpctl_dev *dev = m->private; int ret = get_tpl_fn(dev); if (ret == BP_NOT_CAP) seq_puts(m, "fail\n"); @@ -7523,7 +7523,7 @@ RW_FOPS(tpl) static ssize_t wait_at_pwup_write(struct file *file, const char __user *buffer, size_t count, loff_t *pos) { - bpctl_dev_t *dev = PDE_DATA(file_inode(file)); + struct bpctl_dev *dev = PDE_DATA(file_inode(file)); int tpl_param = user_on_off(buffer, count); if (tpl_param < 0) return -1; @@ -7533,7 +7533,7 @@ static ssize_t wait_at_pwup_write(struct file *file, const char __user *buffer, } static int show_wait_at_pwup(struct seq_file *m, void *v) { - bpctl_dev_t *dev = m->private; + struct bpctl_dev *dev = m->private; int ret = get_bp_wait_at_pwup_fn(dev); if (ret == BP_NOT_CAP) seq_puts(m, "fail\n"); @@ -7548,7 +7548,7 @@ RW_FOPS(wait_at_pwup) static ssize_t hw_reset_write(struct file *file, const char __user *buffer, size_t count, loff_t *pos) { - bpctl_dev_t *dev = PDE_DATA(file_inode(file)); + struct bpctl_dev *dev = PDE_DATA(file_inode(file)); int tpl_param = user_on_off(buffer, count); if (tpl_param < 0) return -1; @@ -7558,7 +7558,7 @@ static ssize_t hw_reset_write(struct file *file, const char __user *buffer, } static int show_hw_reset(struct seq_file *m, void *v) { - bpctl_dev_t *dev = m->private; + struct bpctl_dev *dev = m->private; int ret = get_bp_hw_reset_fn(dev); if (ret == BP_NOT_CAP) seq_puts(m, "fail\n"); @@ -7574,7 +7574,7 @@ RW_FOPS(hw_reset) static int show_reset_bypass_wd(struct seq_file *m, void *v) { - bpctl_dev_t *dev = m->private; + struct bpctl_dev *dev = m->private; int ret = reset_bypass_wd_timer_fn(dev); if (ret == BP_NOT_CAP) seq_puts(m, "fail\n"); @@ -7598,7 +7598,7 @@ static ssize_t dis_bypass_write(struct file *file, const char __user *buffer, } static int show_dis_bypass(struct seq_file *m, void *v) { - bpctl_dev_t *dev = m->private; + struct bpctl_dev *dev = m->private; int ret = get_dis_bypass_fn(dev); if (ret == BP_NOT_CAP) seq_puts(m, "fail\n"); @@ -7622,7 +7622,7 @@ static ssize_t dis_tap_write(struct file *file, const char __user *buffer, } static int show_dis_tap(struct seq_file *m, void *v) { - bpctl_dev_t *dev = m->private; + struct bpctl_dev *dev = m->private; int ret = get_dis_tap_fn(dev); if (ret == BP_NOT_CAP) seq_puts(m, "fail\n"); @@ -7646,7 +7646,7 @@ static ssize_t dis_disc_write(struct file *file, const char __user *buffer, } static int show_dis_disc(struct seq_file *m, void *v) { - bpctl_dev_t *dev = m->private; + struct bpctl_dev *dev = m->private; int ret = get_dis_disc_fn(dev); if (ret == BP_NOT_CAP) seq_puts(m, "fail\n"); @@ -7670,7 +7670,7 @@ static ssize_t bypass_pwup_write(struct file *file, const char __user *buffer, } static int show_bypass_pwup(struct seq_file *m, void *v) { - bpctl_dev_t *dev = m->private; + struct bpctl_dev *dev = m->private; int ret = get_bypass_pwup_fn(dev); if (ret == BP_NOT_CAP) seq_puts(m, "fail\n"); @@ -7694,7 +7694,7 @@ static ssize_t bypass_pwoff_write(struct file *file, const char __user *buffer, } static int show_bypass_pwoff(struct seq_file *m, void *v) { - bpctl_dev_t *dev = m->private; + struct bpctl_dev *dev = m->private; int ret = get_bypass_pwoff_fn(dev); if (ret == BP_NOT_CAP) seq_puts(m, "fail\n"); @@ -7718,7 +7718,7 @@ static ssize_t tap_pwup_write(struct file *file, const char __user *buffer, } static int show_tap_pwup(struct seq_file *m, void *v) { - bpctl_dev_t *dev = m->private; + struct bpctl_dev *dev = m->private; int ret = get_tap_pwup_fn(dev); if (ret == BP_NOT_CAP) seq_puts(m, "fail\n"); @@ -7742,7 +7742,7 @@ static ssize_t disc_pwup_write(struct file *file, const char __user *buffer, } static int show_disc_pwup(struct seq_file *m, void *v) { - bpctl_dev_t *dev = m->private; + struct bpctl_dev *dev = m->private; int ret = get_disc_pwup_fn(dev); if (ret == BP_NOT_CAP) seq_puts(m, "fail\n"); @@ -7766,7 +7766,7 @@ static ssize_t std_nic_write(struct file *file, const char __user *buffer, } static int show_std_nic(struct seq_file *m, void *v) { - bpctl_dev_t *dev = m->private; + struct bpctl_dev *dev = m->private; int ret = get_std_nic_fn(dev); if (ret == BP_NOT_CAP) seq_puts(m, "fail\n"); @@ -7808,7 +7808,7 @@ static ssize_t wd_exp_mode_write(struct file *file, const char __user *buffer, } static int show_wd_exp_mode(struct seq_file *m, void *v) { - bpctl_dev_t *dev = m->private; + struct bpctl_dev *dev = m->private; int ret = get_wd_exp_mode_fn(dev); if (ret == 1) seq_puts(m, "tap\n"); @@ -7834,7 +7834,7 @@ static ssize_t wd_autoreset_write(struct file *file, const char __user *buffer, } static int show_wd_autoreset(struct seq_file *m, void *v) { - bpctl_dev_t *dev = m->private; + struct bpctl_dev *dev = m->private; int ret = get_wd_autoreset_fn(dev); if (ret >= 0) seq_printf(m, "%d\n", ret); @@ -7844,7 +7844,7 @@ static int show_wd_autoreset(struct seq_file *m, void *v) } RW_FOPS(wd_autoreset) -int bypass_proc_create_dev_sd(bpctl_dev_t *pbp_device_block) +int bypass_proc_create_dev_sd(struct bpctl_dev *pbp_device_block) { struct bypass_pfs_sd *current_pfs = &(pbp_device_block->bypass_pfs_set); static struct proc_dir_entry *procfs_dir; @@ -7914,7 +7914,7 @@ int bypass_proc_create_dev_sd(bpctl_dev_t *pbp_device_block) return ret; } -int bypass_proc_remove_dev_sd(bpctl_dev_t *pbp_device_block) +int bypass_proc_remove_dev_sd(struct bpctl_dev *pbp_device_block) { struct bypass_pfs_sd *current_pfs = &pbp_device_block->bypass_pfs_set; From c014185968903c3424776cd22d0deb1a493a1df5 Mon Sep 17 00:00:00 2001 From: Chad Williamson Date: Tue, 25 Jun 2013 18:59:23 -0500 Subject: [PATCH 0394/3400] Staging: silicom: remove the typedef for bpmod_info_t Remove the bpmod_info_t typedef from bpctl_mod.c, replacing it with struct bpmod_info. Signed-off-by: Chad Williamson Signed-off-by: Greg Kroah-Hartman --- drivers/staging/silicom/bpctl_mod.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/silicom/bpctl_mod.c b/drivers/staging/silicom/bpctl_mod.c index 4689076fb7d1..91c864cf4d30 100644 --- a/drivers/staging/silicom/bpctl_mod.c +++ b/drivers/staging/silicom/bpctl_mod.c @@ -5971,7 +5971,7 @@ enum board_type { PE210G2BPi40, }; -typedef struct _bpmod_info_t { +struct bpmod_info { unsigned int vendor; unsigned int device; unsigned int subvendor; @@ -5979,7 +5979,7 @@ typedef struct _bpmod_info_t { unsigned int index; char *bp_name; -} bpmod_info_t; +}; typedef struct _dev_desc { char *name; @@ -6155,7 +6155,7 @@ dev_desc_t dev_desc[] = { {0}, }; -static bpmod_info_t tx_ctl_pci_tbl[] = { +static struct bpmod_info tx_ctl_pci_tbl[] = { {0x8086, 0x107a, SILICOM_SVID, SILICOM_PXG2BPFI_SSID, PXG2BPFI, "PXG2BPFI-SD"}, {0x8086, 0x107a, SILICOM_SVID, SILICOM_PXG2BPFIL_SSID, PXG2BPFIL, @@ -6653,7 +6653,7 @@ static void find_fw(struct bpctl_dev *dev) printk("firmware version: 0x%x\n", dev->bp_fw_ver); } -static int init_one(struct bpctl_dev *dev, bpmod_info_t *info, struct pci_dev *pdev1) +static int init_one(struct bpctl_dev *dev, struct bpmod_info *info, struct pci_dev *pdev1) { unsigned long mmio_start, mmio_len; From 11c920b0e00f9e009687bdf15c71618e91666731 Mon Sep 17 00:00:00 2001 From: Chad Williamson Date: Tue, 25 Jun 2013 18:59:24 -0500 Subject: [PATCH 0395/3400] Staging: silicom: remove typedef for dev_desc_t Remove the dev_desc_t typedef for the dev_desc struct in bpctl_mod.c, resolving a checkpatch.pl warning. In fact, we can use an anonymous struct, since it's only used in the single dev_desc array of device descriptions, whose definition follows immediately. Signed-off-by: Chad Williamson Signed-off-by: Greg Kroah-Hartman --- drivers/staging/silicom/bpctl_mod.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/staging/silicom/bpctl_mod.c b/drivers/staging/silicom/bpctl_mod.c index 91c864cf4d30..32bc530b2cfd 100644 --- a/drivers/staging/silicom/bpctl_mod.c +++ b/drivers/staging/silicom/bpctl_mod.c @@ -5981,11 +5981,9 @@ struct bpmod_info { }; -typedef struct _dev_desc { +struct { char *name; -} dev_desc_t; - -dev_desc_t dev_desc[] = { +} dev_desc[] = { {"Silicom Bypass PXG2BPFI-SD series adapter"}, {"Silicom Bypass PXG2BPFIL-SD series adapter"}, {"Silicom Bypass PXG2BPFILX-SD series adapter"}, From c429df9df06af21912741d5a3848306328564262 Mon Sep 17 00:00:00 2001 From: Vladimir Date: Fri, 12 Jul 2013 09:58:26 +0300 Subject: [PATCH 0396/3400] Staging: silicom: Remove useless unneeded semicolons Found using coccinelle tool. Signed-off-by: Vladimir Cernov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/silicom/bpctl_mod.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/staging/silicom/bpctl_mod.c b/drivers/staging/silicom/bpctl_mod.c index 32bc530b2cfd..495272d01348 100644 --- a/drivers/staging/silicom/bpctl_mod.c +++ b/drivers/staging/silicom/bpctl_mod.c @@ -1809,7 +1809,7 @@ int cmnd_off(struct bpctl_dev *pbpctl_dev) else data_pulse(pbpctl_dev, CMND_OFF); ret = 0; - }; + } return ret; } @@ -1830,7 +1830,7 @@ int bypass_on(struct bpctl_dev *pbpctl_dev) } else data_pulse(pbpctl_dev, BYPASS_ON); ret = 0; - }; + } return ret; } @@ -1866,7 +1866,7 @@ int tap_off(struct bpctl_dev *pbpctl_dev) write_data(pbpctl_dev, TAP_OFF); msec_delay_bp(LATCH_DELAY); ret = 0; - }; + } return ret; } @@ -1879,7 +1879,7 @@ int tap_on(struct bpctl_dev *pbpctl_dev) write_data(pbpctl_dev, TAP_ON); msec_delay_bp(LATCH_DELAY); ret = 0; - }; + } return ret; } @@ -2025,7 +2025,7 @@ int wdt_off(struct bpctl_dev *pbpctl_dev) data_pulse(pbpctl_dev, WDT_OFF); pbpctl_dev->wdt_status = WDT_STATUS_DIS; ret = 0; - }; + } return ret; } @@ -2568,7 +2568,7 @@ int reset_cont(struct bpctl_dev *pbpctl_dev) else data_pulse(pbpctl_dev, RESET_CONT); ret = 0; - }; + } return ret; } @@ -3497,7 +3497,7 @@ int wdt_programmed(struct bpctl_dev *pbpctl_dev, int *timeout) *timeout = curr_wdt_status == 0 ? 0 : pbpctl_dev->bypass_timer_interval; - }; + } } else ret = BP_NOT_CAP; return ret; @@ -3548,7 +3548,7 @@ int normal_support(struct bpctl_dev *pbpctl_dev) NORMAL_UNSUPPORT_MASK) ? 0 : 1); } else ret = 1; - }; + } return ret; } @@ -5111,7 +5111,7 @@ int set_bypass_tpl_auto(struct bpctl_dev *pbpctl_dev, unsigned int param) pbpctl_dev->bp_tpl_flag = param; mod_timer(&pbpctl_dev->bp_tpl_timer, jiffies + 1); return BP_OK; - }; + } if ((!param) && (pbpctl_dev->bp_tpl_flag)) remove_bypass_tpl_auto(pbpctl_dev); From f2a04351edea25eb9b380ea183ed223e4f445791 Mon Sep 17 00:00:00 2001 From: Xenia Ragiadakou Date: Wed, 26 Jun 2013 04:21:40 +0300 Subject: [PATCH 0397/3400] staging: rtl8192u: remove commented-out code in r819xU_cmdpkt.c This patch removes commented-out code and the comments that refer to it to facilitate code review. Signed-off-by: Xenia Ragiadakou Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/r819xU_cmdpkt.c | 42 ++---------------------- 1 file changed, 2 insertions(+), 40 deletions(-) diff --git a/drivers/staging/rtl8192u/r819xU_cmdpkt.c b/drivers/staging/rtl8192u/r819xU_cmdpkt.c index 6810766edfcf..5b3a3a21d4bf 100644 --- a/drivers/staging/rtl8192u/r819xU_cmdpkt.c +++ b/drivers/staging/rtl8192u/r819xU_cmdpkt.c @@ -50,9 +50,6 @@ SendTxCommandPacket( struct sk_buff *skb; cb_desc *tcb_desc; unsigned char *ptr_buf; - //bool bLastInitPacket = false; - - //PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK); //Get TCB and local buffer from common pool. (It is shared by CmdQ, MgntQ, and USB coalesce DataQ) skb = dev_alloc_skb(USB_HWDESC_HEADER_LEN + DataLen + 4); @@ -75,7 +72,6 @@ SendTxCommandPacket( priv->ieee80211->softmac_hard_start_xmit(skb,dev); } - //PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK); return rtStatus; } @@ -113,8 +109,6 @@ SendTxCommandPacket( struct r8192_priv *priv = ieee80211_priv(dev); u16 frag_threshold; u16 frag_length, frag_offset = 0; - //u16 total_size; - //int i; rt_firmware *pfirmware = priv->pFirmware; struct sk_buff *skb; @@ -310,15 +304,11 @@ cmpk_handle_tx_feedback( priv->stats.txfeedback++; - /* 0. Display received message. */ - //cmpk_Display_Message(CMPK_RX_TX_FB_SIZE, pMsg); - /* 1. Extract TX feedback info from RFD to temp structure buffer. */ /* It seems that FW use big endian(MIPS) and DRV use little endian in windows OS. So we have to read the content byte by byte or transfer endian type before copy the message copy. */ /* 2007/07/05 MH Use pointer to transfer structure memory. */ - //memcpy((UINT8 *)&rx_tx_fb, pMsg, sizeof(CMPK_TXFB_T)); memcpy((u8 *)&rx_tx_fb, pmsg, sizeof(cmpk_txfb_t)); /* 2. Use tx feedback info to count TX statistics. */ cmpk_count_txstatistic(dev, &rx_tx_fb); @@ -326,7 +316,6 @@ cmpk_handle_tx_feedback( /* Collect info TX feedback packet to fill TCB. */ /* We can not know the packet length and transmit type: broadcast or uni or multicast. */ - //CountTxStatistics( pAdapter, &tcb ); } /* cmpk_Handle_Tx_Feedback */ @@ -393,15 +382,10 @@ cmpk_handle_interrupt_status( DMESG("---> cmpk_Handle_Interrupt_Status()\n"); - /* 0. Display received message. */ - //cmpk_Display_Message(CMPK_RX_BEACON_STATE_SIZE, pMsg); - /* 1. Extract TX feedback info from RFD to temp structure buffer. */ /* It seems that FW use big endian(MIPS) and DRV use little endian in windows OS. So we have to read the content byte by byte or transfer endian type before copy the message copy. */ - //rx_bcn_state.Element_ID = pMsg[0]; - //rx_bcn_state.Length = pMsg[1]; rx_intr_status.length = pmsg[1]; if (rx_intr_status.length != (sizeof(cmpk_intr_sta_t) - 2)) { @@ -415,7 +399,6 @@ cmpk_handle_interrupt_status( { //2 maybe need endian transform? rx_intr_status.interrupt_status = *((u32 *)(pmsg + 4)); - //rx_intr_status.InterruptStatus = N2H4BYTE(*((UINT32 *)(pMsg + 4))); DMESG("interrupt status = 0x%x\n", rx_intr_status.interrupt_status); @@ -471,15 +454,11 @@ cmpk_handle_query_config_rx( { cmpk_query_cfg_t rx_query_cfg; /* */ - /* 0. Display received message. */ - //cmpk_Display_Message(CMPK_RX_BEACON_STATE_SIZE, pMsg); /* 1. Extract TX feedback info from RFD to temp structure buffer. */ /* It seems that FW use big endian(MIPS) and DRV use little endian in windows OS. So we have to read the content byte by byte or transfer endian type before copy the message copy. */ - //rx_query_cfg.Element_ID = pMsg[0]; - //rx_query_cfg.Length = pMsg[1]; rx_query_cfg.cfg_action = (pmsg[4] & 0x80000000)>>31; rx_query_cfg.cfg_type = (pmsg[4] & 0x60) >> 5; rx_query_cfg.cfg_size = (pmsg[4] & 0x18) >> 3; @@ -539,9 +518,6 @@ static void cmpk_count_tx_status( struct net_device *dev, priv->stats.txretrycount += pstx_status->txretry; priv->stats.txfeedbackretry += pstx_status->txretry; - //pAdapter->TxStats.NumTxOkBytesTotal += psTx_FB->pkt_length; - //pAdapter->TxStats.NumTxErrBytesTotal += psTx_FB->pkt_length; - //pAdapter->MgntInfo.LinkDetectInfo.NumTxOkInPeriod++; priv->stats.txmulticast += pstx_status->txmcok; priv->stats.txbroadcast += pstx_status->txbcok; @@ -613,7 +589,6 @@ cmpk_handle_tx_rate_history( u8 *pmsg) { cmpk_tx_rahis_t *ptxrate; -// RT_RF_POWER_STATE rtState; u8 i, j; u16 length = sizeof(cmpk_tx_rahis_t); u32 *ptemp; @@ -696,7 +671,6 @@ cmpk_message_handle_rx( struct net_device *dev, struct ieee80211_rx_stats *pstats) { -// u32 debug_level = DBG_LOUD; int total_length; u8 cmd_length, exe_cnt = 0; u8 element_id; @@ -704,11 +678,8 @@ cmpk_message_handle_rx( /* 0. Check inpt arguments. If is is a command queue message or pointer is null. */ - if (/*(prfd->queue_id != CMPK_RX_QUEUE_ID) || */(pstats== NULL)) + if (pstats== NULL) { - /* Print error message. */ - /*RT_TRACE(COMP_SEND, DebugLevel, - ("\n\r[CMPK]-->Err queue id or pointer"));*/ return 0; /* This is not a command packet. */ } @@ -720,8 +691,6 @@ cmpk_message_handle_rx( /* 3. Read command packet element id and length. */ element_id = pcmd_buff[0]; - /*RT_TRACE(COMP_SEND, DebugLevel, - ("\n\r[CMPK]-->element ID=%d Len=%d", element_id, total_length));*/ /* 4. Check every received command packet content according to different element type. Because FW may aggregate RX command packet to minimize @@ -757,12 +726,10 @@ cmpk_message_handle_rx( case RX_TX_PER_PKT_FEEDBACK: // You must at lease add a switch case element here, // Otherwise, we will jump to default case. - //DbgPrint("CCX Test\r\n"); cmd_length = CMPK_RX_TX_FB_SIZE; break; case RX_TX_RATE_HISTORY: - //DbgPrint(" rx tx rate history\r\n"); cmpk_handle_tx_rate_history(dev, pcmd_buff); cmd_length = CMPK_TX_RAHIS_SIZE; break; @@ -772,15 +739,10 @@ cmpk_message_handle_rx( RT_TRACE(COMP_ERR, "---->cmpk_message_handle_rx():unknow CMD Element\n"); return 1; /* This is a command packet. */ } - // 2007/01/22 MH Display received rx command packet info. - //cmpk_Display_Message(cmd_length, pcmd_buff); - - // 2007/01/22 MH Add to display tx statistic. - //cmpk_DisplayTxStatistic(pAdapter); total_length -= cmd_length; pcmd_buff += cmd_length; - } /* while (total_length > 0) */ + } return 1; /* This is a command packet. */ } /* CMPK_Message_Handle_Rx */ From 05cdf47ac3374f91a2ac438be58f216562aa9b72 Mon Sep 17 00:00:00 2001 From: Xenia Ragiadakou Date: Wed, 26 Jun 2013 04:21:41 +0300 Subject: [PATCH 0398/3400] staging: rtl8192u: fix braces in r819xU_cmdpkt.c This patch fixes the brace position according to the linux kernel coding style and removes unnecessary braces. Signed-off-by: Xenia Ragiadakou Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/r819xU_cmdpkt.c | 70 +++++------------------- 1 file changed, 15 insertions(+), 55 deletions(-) diff --git a/drivers/staging/rtl8192u/r819xU_cmdpkt.c b/drivers/staging/rtl8192u/r819xU_cmdpkt.c index 5b3a3a21d4bf..fd69da732d82 100644 --- a/drivers/staging/rtl8192u/r819xU_cmdpkt.c +++ b/drivers/staging/rtl8192u/r819xU_cmdpkt.c @@ -209,9 +209,7 @@ cmpk_count_txstatistic( // reason, ie. there may be a duration while sw switch is changed and hw // switch is being changed. 2006.12.04, by shien chang. if (rtState == eRfOff) - { return; - } #endif #ifdef TODO @@ -221,49 +219,35 @@ cmpk_count_txstatistic( /* We can not know the packet length and transmit type: broadcast or uni or multicast. So the relative statistics must be collected in tx feedback info. */ - if (pstx_fb->tok) - { + if (pstx_fb->tok) { priv->stats.txfeedbackok++; priv->stats.txoktotal++; priv->stats.txokbytestotal += pstx_fb->pkt_length; priv->stats.txokinperiod++; /* We can not make sure broadcast/multicast or unicast mode. */ - if (pstx_fb->pkt_type == PACKET_MULTICAST) - { + if (pstx_fb->pkt_type == PACKET_MULTICAST) { priv->stats.txmulticast++; priv->stats.txbytesmulticast += pstx_fb->pkt_length; - } - else if (pstx_fb->pkt_type == PACKET_BROADCAST) - { + } else if (pstx_fb->pkt_type == PACKET_BROADCAST) { priv->stats.txbroadcast++; priv->stats.txbytesbroadcast += pstx_fb->pkt_length; - } - else - { + } else { priv->stats.txunicast++; priv->stats.txbytesunicast += pstx_fb->pkt_length; } - } - else - { + } else { priv->stats.txfeedbackfail++; priv->stats.txerrtotal++; priv->stats.txerrbytestotal += pstx_fb->pkt_length; /* We can not make sure broadcast/multicast or unicast mode. */ if (pstx_fb->pkt_type == PACKET_MULTICAST) - { priv->stats.txerrmulticast++; - } else if (pstx_fb->pkt_type == PACKET_BROADCAST) - { priv->stats.txerrbroadcast++; - } else - { priv->stats.txerrunicast++; - } } priv->stats.txretrycount += pstx_fb->retry_cnt; @@ -326,26 +310,21 @@ cmdpkt_beacontimerinterrupt_819xusb( { struct r8192_priv *priv = ieee80211_priv(dev); u16 tx_rate; - { // // 070117, rcnjko: 87B have to S/W beacon for DTM encryption_cmn. // if (priv->ieee80211->current_network.mode == IEEE_A || priv->ieee80211->current_network.mode == IEEE_N_5G || - (priv->ieee80211->current_network.mode == IEEE_N_24G && (!priv->ieee80211->pHTInfo->bCurSuppCCK))) - { + (priv->ieee80211->current_network.mode == IEEE_N_24G && (!priv->ieee80211->pHTInfo->bCurSuppCCK))) { tx_rate = 60; DMESG("send beacon frame tx rate is 6Mbpm\n"); - } - else - { + } else { tx_rate =10; DMESG("send beacon frame tx rate is 1Mbpm\n"); } rtl819xusb_beacon_tx(dev,tx_rate); // HW Beacon - } } @@ -387,36 +366,29 @@ cmpk_handle_interrupt_status( windows OS. So we have to read the content byte by byte or transfer endian type before copy the message copy. */ rx_intr_status.length = pmsg[1]; - if (rx_intr_status.length != (sizeof(cmpk_intr_sta_t) - 2)) - { + if (rx_intr_status.length != (sizeof(cmpk_intr_sta_t) - 2)) { DMESG("cmpk_Handle_Interrupt_Status: wrong length!\n"); return; } // Statistics of beacon for ad-hoc mode. - if ( priv->ieee80211->iw_mode == IW_MODE_ADHOC) - { + if ( priv->ieee80211->iw_mode == IW_MODE_ADHOC) { //2 maybe need endian transform? rx_intr_status.interrupt_status = *((u32 *)(pmsg + 4)); DMESG("interrupt status = 0x%x\n", rx_intr_status.interrupt_status); - if (rx_intr_status.interrupt_status & ISR_TxBcnOk) - { + if (rx_intr_status.interrupt_status & ISR_TxBcnOk) { priv->ieee80211->bibsscoordinator = true; priv->stats.txbeaconokint++; - } - else if (rx_intr_status.interrupt_status & ISR_TxBcnErr) - { + } else if (rx_intr_status.interrupt_status & ISR_TxBcnErr) { priv->ieee80211->bibsscoordinator = false; priv->stats.txbeaconerr++; } if (rx_intr_status.interrupt_status & ISR_BcnTimerIntr) - { cmdpkt_beacontimerinterrupt_819xusb(dev); - } } @@ -504,9 +476,7 @@ static void cmpk_count_tx_status( struct net_device *dev, // reason, ie. there may be a duration while sw switch is changed and hw // switch is being changed. 2006.12.04, by shien chang. if (rtState == eRfOff) - { return; - } #endif priv->stats.txfeedbackok += pstx_status->txok; @@ -602,9 +572,7 @@ cmpk_handle_tx_rate_history( // reason, ie. there may be a duration while sw switch is changed and hw // switch is being changed. 2006.12.04, by shien chang. if (rtState == eRfOff) - { return; - } #endif ptemp = (u32 *)pmsg; @@ -613,8 +581,7 @@ cmpk_handle_tx_rate_history( // Do endian transfer to word alignment(16 bits) for windows system. // You must do different endian transfer for linux and MAC OS // - for (i = 0; i < (length/4); i++) - { + for (i = 0; i < (length/4); i++) { u16 temp1, temp2; temp1 = ptemp[i]&0x0000FFFF; @@ -625,12 +592,9 @@ cmpk_handle_tx_rate_history( ptxrate = (cmpk_tx_rahis_t *)pmsg; if (ptxrate == NULL ) - { return; - } - for (i = 0; i < 16; i++) - { + for (i = 0; i < 16; i++) { // Collect CCK rate packet num if (i < 4) priv->stats.txrate.cck[i] += ptxrate->cck[i]; @@ -679,9 +643,7 @@ cmpk_message_handle_rx( /* 0. Check inpt arguments. If is is a command queue message or pointer is null. */ if (pstats== NULL) - { return 0; /* This is not a command packet. */ - } /* 1. Read received command packet message length from RFD. */ total_length = pstats->Length; @@ -696,13 +658,11 @@ cmpk_message_handle_rx( element type. Because FW may aggregate RX command packet to minimize transmit time between DRV and FW.*/ // Add a counter to prevent the lock in the loop from being held too long - while (total_length > 0 && exe_cnt++ < 100) - { + while (total_length > 0 && exe_cnt++ < 100) { /* 2007/01/17 MH We support aggregation of different cmd in the same packet. */ element_id = pcmd_buff[0]; - switch (element_id) - { + switch (element_id) { case RX_TX_FEEDBACK: cmpk_handle_tx_feedback (dev, pcmd_buff); cmd_length = CMPK_RX_TX_FB_SIZE; From fa6b108bb17558d721c5adfa48fc309388cd0230 Mon Sep 17 00:00:00 2001 From: Xenia Ragiadakou Date: Wed, 26 Jun 2013 04:21:42 +0300 Subject: [PATCH 0399/3400] staging: rtl8192u: fix whitespace in r819xU_cmdpkt.c This patch fixes whitespaces in r819xU_cmdpkt.c to follow the kernel coding style and to improve code readability. It fixes the spaces around <,=||&&();} and adds or removes tabs to better align variables. Signed-off-by: Xenia Ragiadakou Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/r819xU_cmdpkt.c | 150 +++++++++-------------- 1 file changed, 60 insertions(+), 90 deletions(-) diff --git a/drivers/staging/rtl8192u/r819xU_cmdpkt.c b/drivers/staging/rtl8192u/r819xU_cmdpkt.c index fd69da732d82..777286beffb3 100644 --- a/drivers/staging/rtl8192u/r819xU_cmdpkt.c +++ b/drivers/staging/rtl8192u/r819xU_cmdpkt.c @@ -33,17 +33,12 @@ u32 temp[10];\ \ memcpy(temp, Address, 40);\ - for (i = 0; i <40; i+=4)\ + for (i = 0; i < 40; i += 4)\ printk("\r\n %08x", temp[i]);\ }\ /*---------------------------Define functions---------------------------------*/ -rt_status -SendTxCommandPacket( - struct net_device *dev, - void *pData, - u32 DataLen - ) +rt_status SendTxCommandPacket(struct net_device *dev, void *pData, u32 DataLen) { rt_status rtStatus = RT_STATUS_SUCCESS; struct r8192_priv *priv = ieee80211_priv(dev); @@ -53,23 +48,23 @@ SendTxCommandPacket( //Get TCB and local buffer from common pool. (It is shared by CmdQ, MgntQ, and USB coalesce DataQ) skb = dev_alloc_skb(USB_HWDESC_HEADER_LEN + DataLen + 4); - memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev)); + memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev)); tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); tcb_desc->queue_index = TXCMD_QUEUE; tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_NORMAL; tcb_desc->bLastIniPkt = 0; skb_reserve(skb, USB_HWDESC_HEADER_LEN); ptr_buf = skb_put(skb, DataLen); - memcpy(ptr_buf,pData,DataLen); - tcb_desc->txbuf_size= (u16)DataLen; + memcpy(ptr_buf, pData, DataLen); + tcb_desc->txbuf_size = (u16)DataLen; - if (!priv->ieee80211->check_nic_enough_desc(dev,tcb_desc->queue_index)|| - (!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index]))||\ - (priv->ieee80211->queue_stop) ) { - RT_TRACE(COMP_FIRMWARE,"===================NULL packet==================================> tx full!\n"); + if (!priv->ieee80211->check_nic_enough_desc(dev, tcb_desc->queue_index) || + (!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index])) ||\ + (priv->ieee80211->queue_stop)) { + RT_TRACE(COMP_FIRMWARE, "===================NULL packet==================================> tx full!\n"); skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb); } else { - priv->ieee80211->softmac_hard_start_xmit(skb,dev); + priv->ieee80211->softmac_hard_start_xmit(skb, dev); } return rtStatus; @@ -95,11 +90,9 @@ SendTxCommandPacket( * 05/06/2008 amy porting from windows code. * *---------------------------------------------------------------------------*/ - extern rt_status cmpk_message_handle_tx( - struct net_device *dev, - u8 *codevirtualaddress, - u32 packettype, - u32 buffer_len) +extern rt_status cmpk_message_handle_tx(struct net_device *dev, + u8 *codevirtualaddress, + u32 packettype, u32 buffer_len) { bool rt_status = true; @@ -121,7 +114,7 @@ SendTxCommandPacket( frag_threshold = pfirmware->cmdpacket_frag_thresold; do { if ((buffer_len - frag_offset) > frag_threshold) { - frag_length = frag_threshold ; + frag_length = frag_threshold; bLastIniPkt = 0; } else { @@ -138,7 +131,7 @@ SendTxCommandPacket( #else skb = dev_alloc_skb(frag_length + 4); #endif - memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev)); + memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev)); tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); tcb_desc->queue_index = TXCMD_QUEUE; tcb_desc->bCmdOrInit = packettype; @@ -153,23 +146,23 @@ SendTxCommandPacket( * Transform from little endian to big endian * and pending zero */ - memcpy(seg_ptr,codevirtualaddress,buffer_len); - tcb_desc->txbuf_size= (u16)buffer_len; + memcpy(seg_ptr, codevirtualaddress, buffer_len); + tcb_desc->txbuf_size = (u16)buffer_len; - if (!priv->ieee80211->check_nic_enough_desc(dev,tcb_desc->queue_index)|| - (!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index]))||\ - (priv->ieee80211->queue_stop) ) { - RT_TRACE(COMP_FIRMWARE,"=====================================================> tx full!\n"); + if (!priv->ieee80211->check_nic_enough_desc(dev, tcb_desc->queue_index) || + (!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index])) ||\ + (priv->ieee80211->queue_stop)) { + RT_TRACE(COMP_FIRMWARE, "=====================================================> tx full!\n"); skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb); } else { - priv->ieee80211->softmac_hard_start_xmit(skb,dev); + priv->ieee80211->softmac_hard_start_xmit(skb, dev); } codevirtualaddress += frag_length; frag_offset += frag_length; - }while(frag_offset < buffer_len); + } while (frag_offset < buffer_len); return rt_status; @@ -194,10 +187,7 @@ SendTxCommandPacket( * 05/12/2008 amy Create Version 0 porting from windows code. * *---------------------------------------------------------------------------*/ -static void -cmpk_count_txstatistic( - struct net_device *dev, - cmpk_txfb_t *pstx_fb) +static void cmpk_count_txstatistic(struct net_device *dev, cmpk_txfb_t *pstx_fb) { struct r8192_priv *priv = ieee80211_priv(dev); #ifdef ENABLE_PS @@ -278,10 +268,7 @@ cmpk_count_txstatistic( * 05/08/2008 amy Create Version 0 porting from windows code. * *---------------------------------------------------------------------------*/ -static void -cmpk_handle_tx_feedback( - struct net_device *dev, - u8 *pmsg) +static void cmpk_handle_tx_feedback(struct net_device *dev, u8 *pmsg) { struct r8192_priv *priv = ieee80211_priv(dev); cmpk_txfb_t rx_tx_fb; /* */ @@ -303,27 +290,24 @@ cmpk_handle_tx_feedback( } /* cmpk_Handle_Tx_Feedback */ -void -cmdpkt_beacontimerinterrupt_819xusb( - struct net_device *dev -) +void cmdpkt_beacontimerinterrupt_819xusb(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); u16 tx_rate; // // 070117, rcnjko: 87B have to S/W beacon for DTM encryption_cmn. // - if (priv->ieee80211->current_network.mode == IEEE_A || + if (priv->ieee80211->current_network.mode == IEEE_A || priv->ieee80211->current_network.mode == IEEE_N_5G || - (priv->ieee80211->current_network.mode == IEEE_N_24G && (!priv->ieee80211->pHTInfo->bCurSuppCCK))) { + (priv->ieee80211->current_network.mode == IEEE_N_24G && (!priv->ieee80211->pHTInfo->bCurSuppCCK))) { tx_rate = 60; DMESG("send beacon frame tx rate is 6Mbpm\n"); } else { - tx_rate =10; + tx_rate = 10; DMESG("send beacon frame tx rate is 1Mbpm\n"); } - rtl819xusb_beacon_tx(dev,tx_rate); // HW Beacon + rtl819xusb_beacon_tx(dev, tx_rate); // HW Beacon } @@ -351,10 +335,7 @@ cmdpkt_beacontimerinterrupt_819xusb( * 05/12/2008 amy Add this for rtl8192 porting from windows code. * *---------------------------------------------------------------------------*/ -static void -cmpk_handle_interrupt_status( - struct net_device *dev, - u8 *pmsg) +static void cmpk_handle_interrupt_status(struct net_device *dev, u8 *pmsg) { cmpk_intr_sta_t rx_intr_status; /* */ struct r8192_priv *priv = ieee80211_priv(dev); @@ -373,7 +354,7 @@ cmpk_handle_interrupt_status( // Statistics of beacon for ad-hoc mode. - if ( priv->ieee80211->iw_mode == IW_MODE_ADHOC) { + if (priv->ieee80211->iw_mode == IW_MODE_ADHOC) { //2 maybe need endian transform? rx_intr_status.interrupt_status = *((u32 *)(pmsg + 4)); @@ -419,10 +400,7 @@ cmpk_handle_interrupt_status( * 05/12/2008 amy Create Version 0 porting from windows code. * *---------------------------------------------------------------------------*/ -static void -cmpk_handle_query_config_rx( - struct net_device *dev, - u8 *pmsg) +static void cmpk_handle_query_config_rx(struct net_device *dev, u8 *pmsg) { cmpk_query_cfg_t rx_query_cfg; /* */ @@ -431,15 +409,15 @@ cmpk_handle_query_config_rx( /* It seems that FW use big endian(MIPS) and DRV use little endian in windows OS. So we have to read the content byte by byte or transfer endian type before copy the message copy. */ - rx_query_cfg.cfg_action = (pmsg[4] & 0x80000000)>>31; + rx_query_cfg.cfg_action = (pmsg[4] & 0x80000000) >> 31; rx_query_cfg.cfg_type = (pmsg[4] & 0x60) >> 5; rx_query_cfg.cfg_size = (pmsg[4] & 0x18) >> 3; rx_query_cfg.cfg_page = (pmsg[6] & 0x0F) >> 0; - rx_query_cfg.cfg_offset = pmsg[7]; - rx_query_cfg.value = (pmsg[8] << 24) | (pmsg[9] << 16) | - (pmsg[10] << 8) | (pmsg[11] << 0); - rx_query_cfg.mask = (pmsg[12] << 24) | (pmsg[13] << 16) | - (pmsg[14] << 8) | (pmsg[15] << 0); + rx_query_cfg.cfg_offset = pmsg[7]; + rx_query_cfg.value = (pmsg[8] << 24) | (pmsg[9] << 16) | + (pmsg[10] << 8) | (pmsg[11] << 0); + rx_query_cfg.mask = (pmsg[12] << 24) | (pmsg[13] << 16) | + (pmsg[14] << 8) | (pmsg[15] << 0); } /* cmpk_Handle_Query_Config_Rx */ @@ -461,8 +439,8 @@ cmpk_handle_query_config_rx( * 05/12/2008 amy Create Version 0 porting from windows code. * *---------------------------------------------------------------------------*/ -static void cmpk_count_tx_status( struct net_device *dev, - cmpk_tx_status_t *pstx_status) +static void cmpk_count_tx_status(struct net_device *dev, + cmpk_tx_status_t *pstx_status) { struct r8192_priv *priv = ieee80211_priv(dev); @@ -485,12 +463,12 @@ static void cmpk_count_tx_status( struct net_device *dev, priv->stats.txfeedbackfail += pstx_status->txfail; priv->stats.txerrtotal += pstx_status->txfail; - priv->stats.txretrycount += pstx_status->txretry; + priv->stats.txretrycount += pstx_status->txretry; priv->stats.txfeedbackretry += pstx_status->txretry; - priv->stats.txmulticast += pstx_status->txmcok; - priv->stats.txbroadcast += pstx_status->txbcok; + priv->stats.txmulticast += pstx_status->txmcok; + priv->stats.txbroadcast += pstx_status->txbcok; priv->stats.txunicast += pstx_status->txucok; priv->stats.txerrmulticast += pstx_status->txmcfail; @@ -499,9 +477,9 @@ static void cmpk_count_tx_status( struct net_device *dev, priv->stats.txbytesmulticast += pstx_status->txmclength; priv->stats.txbytesbroadcast += pstx_status->txbclength; - priv->stats.txbytesunicast += pstx_status->txuclength; + priv->stats.txbytesunicast += pstx_status->txuclength; - priv->stats.last_packet_rate = pstx_status->rate; + priv->stats.last_packet_rate = pstx_status->rate; } /* cmpk_CountTxStatus */ @@ -523,10 +501,7 @@ static void cmpk_count_tx_status( struct net_device *dev, * 05/12/2008 amy Create Version 0 porting from windows code. * *---------------------------------------------------------------------------*/ -static void -cmpk_handle_tx_status( - struct net_device *dev, - u8 *pmsg) +static void cmpk_handle_tx_status(struct net_device *dev, u8 *pmsg) { cmpk_tx_status_t rx_tx_sts; /* */ @@ -553,15 +528,12 @@ cmpk_handle_tx_status( * 05/12/2008 amy Create Version 0 porting from windows code. * *---------------------------------------------------------------------------*/ -static void -cmpk_handle_tx_rate_history( - struct net_device *dev, - u8 *pmsg) +static void cmpk_handle_tx_rate_history(struct net_device *dev, u8 *pmsg) { cmpk_tx_rahis_t *ptxrate; - u8 i, j; - u16 length = sizeof(cmpk_tx_rahis_t); - u32 *ptemp; + u8 i, j; + u16 length = sizeof(cmpk_tx_rahis_t); + u32 *ptemp; struct r8192_priv *priv = ieee80211_priv(dev); @@ -584,14 +556,14 @@ cmpk_handle_tx_rate_history( for (i = 0; i < (length/4); i++) { u16 temp1, temp2; - temp1 = ptemp[i]&0x0000FFFF; - temp2 = ptemp[i]>>16; - ptemp[i] = (temp1<<16)|temp2; + temp1 = ptemp[i] & 0x0000FFFF; + temp2 = ptemp[i] >> 16; + ptemp[i] = (temp1 << 16) | temp2; } ptxrate = (cmpk_tx_rahis_t *)pmsg; - if (ptxrate == NULL ) + if (ptxrate == NULL) return; for (i = 0; i < 16; i++) { @@ -600,7 +572,7 @@ cmpk_handle_tx_rate_history( priv->stats.txrate.cck[i] += ptxrate->cck[i]; // Collect OFDM rate packet num - if (i< 8) + if (i < 8) priv->stats.txrate.ofdm[i] += ptxrate->ofdm[i]; for (j = 0; j < 4; j++) @@ -630,10 +602,8 @@ cmpk_handle_tx_rate_history( * 05/06/2008 amy Create Version 0 porting from windows code. * *---------------------------------------------------------------------------*/ -extern u32 -cmpk_message_handle_rx( - struct net_device *dev, - struct ieee80211_rx_stats *pstats) +extern u32 cmpk_message_handle_rx(struct net_device *dev, + struct ieee80211_rx_stats *pstats) { int total_length; u8 cmd_length, exe_cnt = 0; @@ -642,7 +612,7 @@ cmpk_message_handle_rx( /* 0. Check inpt arguments. If is is a command queue message or pointer is null. */ - if (pstats== NULL) + if (pstats == NULL) return 0; /* This is not a command packet. */ /* 1. Read received command packet message length from RFD. */ @@ -664,7 +634,7 @@ cmpk_message_handle_rx( switch (element_id) { case RX_TX_FEEDBACK: - cmpk_handle_tx_feedback (dev, pcmd_buff); + cmpk_handle_tx_feedback(dev, pcmd_buff); cmd_length = CMPK_RX_TX_FB_SIZE; break; From 6df9f669de3da57e661e27e6f55799ae587fb2c9 Mon Sep 17 00:00:00 2001 From: Xenia Ragiadakou Date: Wed, 26 Jun 2013 04:21:43 +0300 Subject: [PATCH 0400/3400] staging: rtl8192u: fix comments in r819xU_cmdpkt.c This patches fixes comments by: - replacing // comments with /**/ comments - removing unnecessary comments (trailing comments with the function name, comments stating date/author when they are placed inside the function definition) - fixing internal alignment Signed-off-by: Xenia Ragiadakou Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/r819xU_cmdpkt.c | 252 +++++++++++------------ 1 file changed, 125 insertions(+), 127 deletions(-) diff --git a/drivers/staging/rtl8192u/r819xU_cmdpkt.c b/drivers/staging/rtl8192u/r819xU_cmdpkt.c index 777286beffb3..b6a6e44200a7 100644 --- a/drivers/staging/rtl8192u/r819xU_cmdpkt.c +++ b/drivers/staging/rtl8192u/r819xU_cmdpkt.c @@ -1,32 +1,34 @@ /****************************************************************************** - - (c) Copyright 2008, RealTEK Technologies Inc. All Rights Reserved. - - Module: r819xusb_cmdpkt.c (RTL8190 TX/RX command packet handler Source C File) - - Note: The module is responsible for handling TX and RX command packet. - 1. TX : Send set and query configuration command packet. - 2. RX : Receive tx feedback, beacon state, query configuration - command packet. - - Function: - - Export: - - Abbrev: - - History: - Data Who Remark - - 05/06/2008 amy Create initial version porting from windows driver. - -******************************************************************************/ + * + * (c) Copyright 2008, RealTEK Technologies Inc. All Rights Reserved. + * + * Module: r819xusb_cmdpkt.c + * (RTL8190 TX/RX command packet handler Source C File) + * + * Note: The module is responsible for handling TX and RX command packet. + * 1. TX : Send set and query configuration command packet. + * 2. RX : Receive tx feedback, beacon state, query configuration + * command packet. + * + * Function: + * + * Export: + * + * Abbrev: + * + * History: + * + * Date Who Remark + * 05/06/2008 amy Create initial version porting from + * windows driver. + * + ******************************************************************************/ #include "r8192U.h" #include "r819xU_cmdpkt.h" -/*---------------------------Define Local Constant---------------------------*/ -/* Debug constant*/ + +/* Debug constant */ #define CMPK_DEBOUNCE_CNT 1 -/* 2007/10/24 MH Add for printing a range of data. */ +/* Add for printing a range of data. */ #define CMPK_PRINT(Address)\ {\ unsigned char i;\ @@ -36,7 +38,6 @@ for (i = 0; i < 40; i += 4)\ printk("\r\n %08x", temp[i]);\ }\ -/*---------------------------Define functions---------------------------------*/ rt_status SendTxCommandPacket(struct net_device *dev, void *pData, u32 DataLen) { @@ -46,7 +47,8 @@ rt_status SendTxCommandPacket(struct net_device *dev, void *pData, u32 DataLen) cb_desc *tcb_desc; unsigned char *ptr_buf; - //Get TCB and local buffer from common pool. (It is shared by CmdQ, MgntQ, and USB coalesce DataQ) + /* Get TCB and local buffer from common pool. + (It is shared by CmdQ, MgntQ, and USB coalesce DataQ) */ skb = dev_alloc_skb(USB_HWDESC_HEADER_LEN + DataLen + 4); memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev)); tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); @@ -74,16 +76,16 @@ rt_status SendTxCommandPacket(struct net_device *dev, void *pData, u32 DataLen) * Function: cmpk_message_handle_tx() * * Overview: Driver internal module can call the API to send message to - * firmware side. For example, you can send a debug command packet. - * Or you can send a request for FW to modify RLX4181 LBUS HW bank. - * Otherwise, you can change MAC/PHT/RF register by firmware at - * run time. We do not support message more than one segment now. + * firmware side. For example, you can send a debug command packet. + * Or you can send a request for FW to modify RLX4181 LBUS HW bank. + * Otherwise, you can change MAC/PHT/RF register by firmware at + * run time. We do not support message more than one segment now. * - * Input: NONE + * Input: NONE * - * Output: NONE + * Output: NONE * - * Return: NONE + * Return: NONE * * Revised History: * When Who Remark @@ -110,7 +112,7 @@ extern rt_status cmpk_message_handle_tx(struct net_device *dev, u8 bLastIniPkt; firmware_init_param(dev); - //Fragmentation might be required + /* Fragmentation might be required */ frag_threshold = pfirmware->cmdpacket_frag_thresold; do { if ((buffer_len - frag_offset) > frag_threshold) { @@ -123,9 +125,8 @@ extern rt_status cmpk_message_handle_tx(struct net_device *dev, } - /* Allocate skb buffer to contain firmware info and tx descriptor info - * add 4 to avoid packet appending overflow. - * */ + /* Allocate skb buffer to contain firmware info and tx + descriptor info add 4 to avoid packet appending overflow. */ #ifdef RTL8192U skb = dev_alloc_skb(USB_HWDESC_HEADER_LEN + frag_length + 4); #else @@ -168,23 +169,23 @@ extern rt_status cmpk_message_handle_tx(struct net_device *dev, #endif -} /* CMPK_Message_Handle_Tx */ +} /*----------------------------------------------------------------------------- * Function: cmpk_counttxstatistic() * * Overview: * - * Input: PADAPTER pAdapter - . - * CMPK_TXFB_T *psTx_FB - . + * Input: PADAPTER pAdapter + * CMPK_TXFB_T *psTx_FB * * Output: NONE * * Return: NONE * * Revised History: - * When Who Remark - * 05/12/2008 amy Create Version 0 porting from windows code. + * When Who Remark + * 05/12/2008 amy Create Version 0 porting from windows code. * *---------------------------------------------------------------------------*/ static void cmpk_count_txstatistic(struct net_device *dev, cmpk_txfb_t *pstx_fb) @@ -195,9 +196,9 @@ static void cmpk_count_txstatistic(struct net_device *dev, cmpk_txfb_t *pstx_fb) pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE, (pu1Byte)(&rtState)); - // When RF is off, we should not count the packet for hw/sw synchronize - // reason, ie. there may be a duration while sw switch is changed and hw - // switch is being changed. 2006.12.04, by shien chang. + /* When RF is off, we should not count the packet for hw/sw synchronize + reason, ie. there may be a duration while sw switch is changed and + hw switch is being changed. */ if (rtState == eRfOff) return; #endif @@ -206,9 +207,9 @@ static void cmpk_count_txstatistic(struct net_device *dev, cmpk_txfb_t *pstx_fb) if (pAdapter->bInHctTest) return; #endif - /* We can not know the packet length and transmit type: broadcast or uni - or multicast. So the relative statistics must be collected in tx - feedback info. */ + /* We can not know the packet length and transmit type: + broadcast or uni or multicast. So the relative statistics + must be collected in tx feedback info. */ if (pstx_fb->tok) { priv->stats.txfeedbackok++; priv->stats.txoktotal++; @@ -243,7 +244,7 @@ static void cmpk_count_txstatistic(struct net_device *dev, cmpk_txfb_t *pstx_fb) priv->stats.txretrycount += pstx_fb->retry_cnt; priv->stats.txfeedbackretry += pstx_fb->retry_cnt; -} /* cmpk_CountTxStatistic */ +} @@ -251,27 +252,27 @@ static void cmpk_count_txstatistic(struct net_device *dev, cmpk_txfb_t *pstx_fb) * Function: cmpk_handle_tx_feedback() * * Overview: The function is responsible for extract the message inside TX - * feedbck message from firmware. It will contain dedicated info in - * ws-06-0063-rtl8190-command-packet-specification. Please - * refer to chapter "TX Feedback Element". We have to read 20 bytes - * in the command packet. + * feedbck message from firmware. It will contain dedicated info in + * ws-06-0063-rtl8190-command-packet-specification. + * Please refer to chapter "TX Feedback Element". + * We have to read 20 bytes in the command packet. * - * Input: struct net_device * dev - * u8 * pmsg - Msg Ptr of the command packet. + * Input: struct net_device *dev + * u8 *pmsg - Msg Ptr of the command packet. * * Output: NONE * * Return: NONE * * Revised History: - * When Who Remark - * 05/08/2008 amy Create Version 0 porting from windows code. + * When Who Remark + * 05/08/2008 amy Create Version 0 porting from windows code. * *---------------------------------------------------------------------------*/ static void cmpk_handle_tx_feedback(struct net_device *dev, u8 *pmsg) { struct r8192_priv *priv = ieee80211_priv(dev); - cmpk_txfb_t rx_tx_fb; /* */ + cmpk_txfb_t rx_tx_fb; priv->stats.txfeedback++; @@ -279,24 +280,22 @@ static void cmpk_handle_tx_feedback(struct net_device *dev, u8 *pmsg) /* It seems that FW use big endian(MIPS) and DRV use little endian in windows OS. So we have to read the content byte by byte or transfer endian type before copy the message copy. */ - /* 2007/07/05 MH Use pointer to transfer structure memory. */ + /* Use pointer to transfer structure memory. */ memcpy((u8 *)&rx_tx_fb, pmsg, sizeof(cmpk_txfb_t)); /* 2. Use tx feedback info to count TX statistics. */ cmpk_count_txstatistic(dev, &rx_tx_fb); - /* 2007/01/17 MH Comment previous method for TX statistic function. */ + /* Comment previous method for TX statistic function. */ /* Collect info TX feedback packet to fill TCB. */ /* We can not know the packet length and transmit type: broadcast or uni or multicast. */ -} /* cmpk_Handle_Tx_Feedback */ +} void cmdpkt_beacontimerinterrupt_819xusb(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); u16 tx_rate; - // - // 070117, rcnjko: 87B have to S/W beacon for DTM encryption_cmn. - // + /* 87B have to S/W beacon for DTM encryption_cmn. */ if (priv->ieee80211->current_network.mode == IEEE_A || priv->ieee80211->current_network.mode == IEEE_N_5G || (priv->ieee80211->current_network.mode == IEEE_N_24G && (!priv->ieee80211->pHTInfo->bCurSuppCCK))) { @@ -307,7 +306,7 @@ void cmdpkt_beacontimerinterrupt_819xusb(struct net_device *dev) DMESG("send beacon frame tx rate is 1Mbpm\n"); } - rtl819xusb_beacon_tx(dev, tx_rate); // HW Beacon + rtl819xusb_beacon_tx(dev, tx_rate); /* HW Beacon */ } @@ -319,20 +318,20 @@ void cmdpkt_beacontimerinterrupt_819xusb(struct net_device *dev) * Function: cmpk_handle_interrupt_status() * * Overview: The function is responsible for extract the message from - * firmware. It will contain dedicated info in - * ws-07-0063-v06-rtl819x-command-packet-specification-070315.doc. - * Please refer to chapter "Interrupt Status Element". + * firmware. It will contain dedicated info in + * ws-07-0063-v06-rtl819x-command-packet-specification-070315.doc. + * Please refer to chapter "Interrupt Status Element". * - * Input: struct net_device *dev, - * u8* pmsg - Message Pointer of the command packet. + * Input: struct net_device *dev + * u8 *pmsg - Message Pointer of the command packet. * * Output: NONE * * Return: NONE * * Revised History: - * When Who Remark - * 05/12/2008 amy Add this for rtl8192 porting from windows code. + * When Who Remark + * 05/12/2008 amy Add this for rtl8192 porting from windows code. * *---------------------------------------------------------------------------*/ static void cmpk_handle_interrupt_status(struct net_device *dev, u8 *pmsg) @@ -353,9 +352,9 @@ static void cmpk_handle_interrupt_status(struct net_device *dev, u8 *pmsg) } - // Statistics of beacon for ad-hoc mode. + /* Statistics of beacon for ad-hoc mode. */ if (priv->ieee80211->iw_mode == IW_MODE_ADHOC) { - //2 maybe need endian transform? + /* 2 maybe need endian transform? */ rx_intr_status.interrupt_status = *((u32 *)(pmsg + 4)); DMESG("interrupt status = 0x%x\n", rx_intr_status.interrupt_status); @@ -373,36 +372,36 @@ static void cmpk_handle_interrupt_status(struct net_device *dev, u8 *pmsg) } - // Other informations in interrupt status we need? + /* Other informations in interrupt status we need? */ DMESG("<---- cmpk_handle_interrupt_status()\n"); -} /* cmpk_handle_interrupt_status */ +} /*----------------------------------------------------------------------------- * Function: cmpk_handle_query_config_rx() * * Overview: The function is responsible for extract the message from - * firmware. It will contain dedicated info in - * ws-06-0063-rtl8190-command-packet-specification. Please - * refer to chapter "Beacon State Element". + * firmware. It will contain dedicated info in + * ws-06-0063-rtl8190-command-packet-specification. Please + * refer to chapter "Beacon State Element". * - * Input: u8 * pmsg - Message Pointer of the command packet. + * Input: u8 *pmsg - Message Pointer of the command packet. * * Output: NONE * * Return: NONE * * Revised History: - * When Who Remark - * 05/12/2008 amy Create Version 0 porting from windows code. + * When Who Remark + * 05/12/2008 amy Create Version 0 porting from windows code. * *---------------------------------------------------------------------------*/ static void cmpk_handle_query_config_rx(struct net_device *dev, u8 *pmsg) { - cmpk_query_cfg_t rx_query_cfg; /* */ + cmpk_query_cfg_t rx_query_cfg; /* 1. Extract TX feedback info from RFD to temp structure buffer. */ @@ -419,24 +418,24 @@ static void cmpk_handle_query_config_rx(struct net_device *dev, u8 *pmsg) rx_query_cfg.mask = (pmsg[12] << 24) | (pmsg[13] << 16) | (pmsg[14] << 8) | (pmsg[15] << 0); -} /* cmpk_Handle_Query_Config_Rx */ +} /*----------------------------------------------------------------------------- * Function: cmpk_count_tx_status() * * Overview: Count aggregated tx status from firmwar of one type rx command - * packet element id = RX_TX_STATUS. + * packet element id = RX_TX_STATUS. * - * Input: NONE + * Input: NONE * - * Output: NONE + * Output: NONE * - * Return: NONE + * Return: NONE * * Revised History: - * When Who Remark - * 05/12/2008 amy Create Version 0 porting from windows code. + * When Who Remark + * 05/12/2008 amy Create Version 0 porting from windows code. * *---------------------------------------------------------------------------*/ static void cmpk_count_tx_status(struct net_device *dev, @@ -450,9 +449,9 @@ static void cmpk_count_tx_status(struct net_device *dev, pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE, (pu1Byte)(&rtState)); - // When RF is off, we should not count the packet for hw/sw synchronize - // reason, ie. there may be a duration while sw switch is changed and hw - // switch is being changed. 2006.12.04, by shien chang. + /* When RF is off, we should not count the packet for hw/sw synchronize + reason, ie. there may be a duration while sw switch is changed and + hw switch is being changed. */ if (rtState == eRfOff) return; #endif @@ -480,7 +479,7 @@ static void cmpk_count_tx_status(struct net_device *dev, priv->stats.txbytesunicast += pstx_status->txuclength; priv->stats.last_packet_rate = pstx_status->rate; -} /* cmpk_CountTxStatus */ +} @@ -488,7 +487,7 @@ static void cmpk_count_tx_status(struct net_device *dev, * Function: cmpk_handle_tx_status() * * Overview: Firmware add a new tx feedback status to reduce rx command - * packet buffer operation load. + * packet buffer operation load. * * Input: NONE * @@ -497,19 +496,19 @@ static void cmpk_count_tx_status(struct net_device *dev, * Return: NONE * * Revised History: - * When Who Remark - * 05/12/2008 amy Create Version 0 porting from windows code. + * When Who Remark + * 05/12/2008 amy Create Version 0 porting from windows code. * *---------------------------------------------------------------------------*/ static void cmpk_handle_tx_status(struct net_device *dev, u8 *pmsg) { - cmpk_tx_status_t rx_tx_sts; /* */ + cmpk_tx_status_t rx_tx_sts; memcpy((void *)&rx_tx_sts, (void *)pmsg, sizeof(cmpk_tx_status_t)); /* 2. Use tx feedback info to count TX statistics. */ cmpk_count_tx_status(dev, &rx_tx_sts); -} /* cmpk_Handle_Tx_Status */ +} /*----------------------------------------------------------------------------- @@ -524,8 +523,8 @@ static void cmpk_handle_tx_status(struct net_device *dev, u8 *pmsg) * Return: NONE * * Revised History: - * When Who Remark - * 05/12/2008 amy Create Version 0 porting from windows code. + * When Who Remark + * 05/12/2008 amy Create Version 0 porting from windows code. * *---------------------------------------------------------------------------*/ static void cmpk_handle_tx_rate_history(struct net_device *dev, u8 *pmsg) @@ -540,19 +539,17 @@ static void cmpk_handle_tx_rate_history(struct net_device *dev, u8 *pmsg) #ifdef ENABLE_PS pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE, (pu1Byte)(&rtState)); - // When RF is off, we should not count the packet for hw/sw synchronize - // reason, ie. there may be a duration while sw switch is changed and hw - // switch is being changed. 2006.12.04, by shien chang. + /* When RF is off, we should not count the packet for hw/sw synchronize + reason, ie. there may be a duration while sw switch is changed and + hw switch is being changed. */ if (rtState == eRfOff) return; #endif ptemp = (u32 *)pmsg; - // - // Do endian transfer to word alignment(16 bits) for windows system. - // You must do different endian transfer for linux and MAC OS - // + /* Do endian transfer to word alignment(16 bits) for windows system. + You must do different endian transfer for linux and MAC OS */ for (i = 0; i < (length/4); i++) { u16 temp1, temp2; @@ -567,11 +564,11 @@ static void cmpk_handle_tx_rate_history(struct net_device *dev, u8 *pmsg) return; for (i = 0; i < 16; i++) { - // Collect CCK rate packet num + /* Collect CCK rate packet num */ if (i < 4) priv->stats.txrate.cck[i] += ptxrate->cck[i]; - // Collect OFDM rate packet num + /* Collect OFDM rate packet num */ if (i < 8) priv->stats.txrate.ofdm[i] += ptxrate->ofdm[i]; @@ -579,17 +576,17 @@ static void cmpk_handle_tx_rate_history(struct net_device *dev, u8 *pmsg) priv->stats.txrate.ht_mcs[j][i] += ptxrate->ht_mcs[j][i]; } -} /* cmpk_Handle_Tx_Rate_History */ +} /*----------------------------------------------------------------------------- * Function: cmpk_message_handle_rx() * * Overview: In the function, we will capture different RX command packet - * info. Every RX command packet element has different message - * length and meaning in content. We only support three type of RX - * command packet now. Please refer to document - * ws-06-0063-rtl8190-command-packet-specification. + * info. Every RX command packet element has different message + * length and meaning in content. We only support three type of RX + * command packet now. Please refer to document + * ws-06-0063-rtl8190-command-packet-specification. * * Input: NONE * @@ -598,8 +595,8 @@ static void cmpk_handle_tx_rate_history(struct net_device *dev, u8 *pmsg) * Return: NONE * * Revised History: - * When Who Remark - * 05/06/2008 amy Create Version 0 porting from windows code. + * When Who Remark + * 05/06/2008 amy Create Version 0 porting from windows code. * *---------------------------------------------------------------------------*/ extern u32 cmpk_message_handle_rx(struct net_device *dev, @@ -610,8 +607,8 @@ extern u32 cmpk_message_handle_rx(struct net_device *dev, u8 element_id; u8 *pcmd_buff; - /* 0. Check inpt arguments. If is is a command queue message or pointer is - null. */ + /* 0. Check inpt arguments. If is is a command queue message or + pointer is null. */ if (pstats == NULL) return 0; /* This is not a command packet. */ @@ -625,11 +622,12 @@ extern u32 cmpk_message_handle_rx(struct net_device *dev, element_id = pcmd_buff[0]; /* 4. Check every received command packet content according to different - element type. Because FW may aggregate RX command packet to minimize - transmit time between DRV and FW.*/ - // Add a counter to prevent the lock in the loop from being held too long + element type. Because FW may aggregate RX command packet to + minimize transmit time between DRV and FW.*/ + /* Add a counter to prevent the lock in the loop from being held too + long */ while (total_length > 0 && exe_cnt++ < 100) { - /* 2007/01/17 MH We support aggregation of different cmd in the same packet. */ + /* We support aggregation of different cmd in the same packet */ element_id = pcmd_buff[0]; switch (element_id) { @@ -654,8 +652,8 @@ extern u32 cmpk_message_handle_rx(struct net_device *dev, break; case RX_TX_PER_PKT_FEEDBACK: - // You must at lease add a switch case element here, - // Otherwise, we will jump to default case. + /* You must at lease add a switch case element here, + Otherwise, we will jump to default case. */ cmd_length = CMPK_RX_TX_FB_SIZE; break; @@ -675,4 +673,4 @@ extern u32 cmpk_message_handle_rx(struct net_device *dev, } return 1; /* This is a command packet. */ -} /* CMPK_Message_Handle_Rx */ +} From bdcd57fa210646738c7fd6ecc927fc87065b5bbd Mon Sep 17 00:00:00 2001 From: Xenia Ragiadakou Date: Wed, 26 Jun 2013 04:21:44 +0300 Subject: [PATCH 0401/3400] staging: rtl8192u: remove unnecessary line continuations in r819xU_cmdpkt.c This patch fixes the following checkpatch warning: WARNING: Avoid unnecessary line continuations Signed-off-by: Xenia Ragiadakou Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/r819xU_cmdpkt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/rtl8192u/r819xU_cmdpkt.c b/drivers/staging/rtl8192u/r819xU_cmdpkt.c index b6a6e44200a7..469b12bf2d97 100644 --- a/drivers/staging/rtl8192u/r819xU_cmdpkt.c +++ b/drivers/staging/rtl8192u/r819xU_cmdpkt.c @@ -61,7 +61,7 @@ rt_status SendTxCommandPacket(struct net_device *dev, void *pData, u32 DataLen) tcb_desc->txbuf_size = (u16)DataLen; if (!priv->ieee80211->check_nic_enough_desc(dev, tcb_desc->queue_index) || - (!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index])) ||\ + (!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index])) || (priv->ieee80211->queue_stop)) { RT_TRACE(COMP_FIRMWARE, "===================NULL packet==================================> tx full!\n"); skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb); @@ -152,7 +152,7 @@ extern rt_status cmpk_message_handle_tx(struct net_device *dev, if (!priv->ieee80211->check_nic_enough_desc(dev, tcb_desc->queue_index) || - (!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index])) ||\ + (!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index])) || (priv->ieee80211->queue_stop)) { RT_TRACE(COMP_FIRMWARE, "=====================================================> tx full!\n"); skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb); From f70edb9f1c62e4367068f263bfb596767675477b Mon Sep 17 00:00:00 2001 From: Xenia Ragiadakou Date: Wed, 26 Jun 2013 04:21:45 +0300 Subject: [PATCH 0402/3400] staging: rtl8192u: fix line size and identation in r819xU_cmdpkt.c This patch limits the line size below 80 characters, when possible, and fixes identation to meet kernel coding style convetions. Signed-off-by: Xenia Ragiadakou Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/r819xU_cmdpkt.c | 102 ++++++++++++----------- 1 file changed, 54 insertions(+), 48 deletions(-) diff --git a/drivers/staging/rtl8192u/r819xU_cmdpkt.c b/drivers/staging/rtl8192u/r819xU_cmdpkt.c index 469b12bf2d97..8c56598b5eac 100644 --- a/drivers/staging/rtl8192u/r819xU_cmdpkt.c +++ b/drivers/staging/rtl8192u/r819xU_cmdpkt.c @@ -61,13 +61,13 @@ rt_status SendTxCommandPacket(struct net_device *dev, void *pData, u32 DataLen) tcb_desc->txbuf_size = (u16)DataLen; if (!priv->ieee80211->check_nic_enough_desc(dev, tcb_desc->queue_index) || - (!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index])) || - (priv->ieee80211->queue_stop)) { - RT_TRACE(COMP_FIRMWARE, "===================NULL packet==================================> tx full!\n"); - skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb); - } else { - priv->ieee80211->softmac_hard_start_xmit(skb, dev); - } + (!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index])) || + (priv->ieee80211->queue_stop)) { + RT_TRACE(COMP_FIRMWARE, "=== NULL packet ======> tx full!\n"); + skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb); + } else { + priv->ieee80211->softmac_hard_start_xmit(skb, dev); + } return rtStatus; } @@ -127,20 +127,20 @@ extern rt_status cmpk_message_handle_tx(struct net_device *dev, /* Allocate skb buffer to contain firmware info and tx descriptor info add 4 to avoid packet appending overflow. */ - #ifdef RTL8192U +#ifdef RTL8192U skb = dev_alloc_skb(USB_HWDESC_HEADER_LEN + frag_length + 4); - #else +#else skb = dev_alloc_skb(frag_length + 4); - #endif +#endif memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev)); tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); tcb_desc->queue_index = TXCMD_QUEUE; tcb_desc->bCmdOrInit = packettype; tcb_desc->bLastIniPkt = bLastIniPkt; - #ifdef RTL8192U +#ifdef RTL8192U skb_reserve(skb, USB_HWDESC_HEADER_LEN); - #endif +#endif seg_ptr = skb_put(skb, buffer_len); /* @@ -152,9 +152,9 @@ extern rt_status cmpk_message_handle_tx(struct net_device *dev, if (!priv->ieee80211->check_nic_enough_desc(dev, tcb_desc->queue_index) || - (!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index])) || - (priv->ieee80211->queue_stop)) { - RT_TRACE(COMP_FIRMWARE, "=====================================================> tx full!\n"); + (!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index])) || + (priv->ieee80211->queue_stop)) { + RT_TRACE(COMP_FIRMWARE, "======> tx full!\n"); skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb); } else { priv->ieee80211->softmac_hard_start_xmit(skb, dev); @@ -194,7 +194,8 @@ static void cmpk_count_txstatistic(struct net_device *dev, cmpk_txfb_t *pstx_fb) #ifdef ENABLE_PS RT_RF_POWER_STATE rtState; - pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE, (pu1Byte)(&rtState)); + pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE, + (pu1Byte)(&rtState)); /* When RF is off, we should not count the packet for hw/sw synchronize reason, ie. there may be a duration while sw switch is changed and @@ -298,7 +299,8 @@ void cmdpkt_beacontimerinterrupt_819xusb(struct net_device *dev) /* 87B have to S/W beacon for DTM encryption_cmn. */ if (priv->ieee80211->current_network.mode == IEEE_A || priv->ieee80211->current_network.mode == IEEE_N_5G || - (priv->ieee80211->current_network.mode == IEEE_N_24G && (!priv->ieee80211->pHTInfo->bCurSuppCCK))) { + (priv->ieee80211->current_network.mode == IEEE_N_24G && + (!priv->ieee80211->pHTInfo->bCurSuppCCK))) { tx_rate = 60; DMESG("send beacon frame tx rate is 6Mbpm\n"); } else { @@ -357,7 +359,8 @@ static void cmpk_handle_interrupt_status(struct net_device *dev, u8 *pmsg) /* 2 maybe need endian transform? */ rx_intr_status.interrupt_status = *((u32 *)(pmsg + 4)); - DMESG("interrupt status = 0x%x\n", rx_intr_status.interrupt_status); + DMESG("interrupt status = 0x%x\n", + rx_intr_status.interrupt_status); if (rx_intr_status.interrupt_status & ISR_TxBcnOk) { priv->ieee80211->bibsscoordinator = true; @@ -447,7 +450,8 @@ static void cmpk_count_tx_status(struct net_device *dev, RT_RF_POWER_STATE rtstate; - pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE, (pu1Byte)(&rtState)); + pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE, + (pu1Byte)(&rtState)); /* When RF is off, we should not count the packet for hw/sw synchronize reason, ie. there may be a duration while sw switch is changed and @@ -537,7 +541,8 @@ static void cmpk_handle_tx_rate_history(struct net_device *dev, u8 *pmsg) #ifdef ENABLE_PS - pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE, (pu1Byte)(&rtState)); + pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE, + (pu1Byte)(&rtState)); /* When RF is off, we should not count the packet for hw/sw synchronize reason, ie. there may be a duration while sw switch is changed and @@ -631,41 +636,42 @@ extern u32 cmpk_message_handle_rx(struct net_device *dev, element_id = pcmd_buff[0]; switch (element_id) { - case RX_TX_FEEDBACK: - cmpk_handle_tx_feedback(dev, pcmd_buff); - cmd_length = CMPK_RX_TX_FB_SIZE; - break; + case RX_TX_FEEDBACK: + cmpk_handle_tx_feedback(dev, pcmd_buff); + cmd_length = CMPK_RX_TX_FB_SIZE; + break; - case RX_INTERRUPT_STATUS: - cmpk_handle_interrupt_status(dev, pcmd_buff); - cmd_length = sizeof(cmpk_intr_sta_t); - break; + case RX_INTERRUPT_STATUS: + cmpk_handle_interrupt_status(dev, pcmd_buff); + cmd_length = sizeof(cmpk_intr_sta_t); + break; - case BOTH_QUERY_CONFIG: - cmpk_handle_query_config_rx(dev, pcmd_buff); - cmd_length = CMPK_BOTH_QUERY_CONFIG_SIZE; - break; + case BOTH_QUERY_CONFIG: + cmpk_handle_query_config_rx(dev, pcmd_buff); + cmd_length = CMPK_BOTH_QUERY_CONFIG_SIZE; + break; - case RX_TX_STATUS: - cmpk_handle_tx_status(dev, pcmd_buff); - cmd_length = CMPK_RX_TX_STS_SIZE; - break; + case RX_TX_STATUS: + cmpk_handle_tx_status(dev, pcmd_buff); + cmd_length = CMPK_RX_TX_STS_SIZE; + break; - case RX_TX_PER_PKT_FEEDBACK: - /* You must at lease add a switch case element here, - Otherwise, we will jump to default case. */ - cmd_length = CMPK_RX_TX_FB_SIZE; - break; + case RX_TX_PER_PKT_FEEDBACK: + /* You must at lease add a switch case element here, + Otherwise, we will jump to default case. */ + cmd_length = CMPK_RX_TX_FB_SIZE; + break; - case RX_TX_RATE_HISTORY: - cmpk_handle_tx_rate_history(dev, pcmd_buff); - cmd_length = CMPK_TX_RAHIS_SIZE; - break; + case RX_TX_RATE_HISTORY: + cmpk_handle_tx_rate_history(dev, pcmd_buff); + cmd_length = CMPK_TX_RAHIS_SIZE; + break; - default: + default: - RT_TRACE(COMP_ERR, "---->cmpk_message_handle_rx():unknow CMD Element\n"); - return 1; /* This is a command packet. */ + RT_TRACE(COMP_ERR, "---->%s():unknown CMD Element\n", + __func__); + return 1; /* This is a command packet. */ } total_length -= cmd_length; From bdc7cb1994d5df7f14e42cd61b332e8eb12cac3e Mon Sep 17 00:00:00 2001 From: Xenia Ragiadakou Date: Wed, 26 Jun 2013 04:21:46 +0300 Subject: [PATCH 0403/3400] staging: rtl8192u: remove unused macros r819xU_cmdpkt.c This patch removes CMPK_DEBOUNCE_CNT and CMPK_PRINT() because they are not used anywhere in the driver. Signed-off-by: Xenia Ragiadakou Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/r819xU_cmdpkt.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/drivers/staging/rtl8192u/r819xU_cmdpkt.c b/drivers/staging/rtl8192u/r819xU_cmdpkt.c index 8c56598b5eac..5bc361b16d4c 100644 --- a/drivers/staging/rtl8192u/r819xU_cmdpkt.c +++ b/drivers/staging/rtl8192u/r819xU_cmdpkt.c @@ -26,19 +26,6 @@ #include "r8192U.h" #include "r819xU_cmdpkt.h" -/* Debug constant */ -#define CMPK_DEBOUNCE_CNT 1 -/* Add for printing a range of data. */ -#define CMPK_PRINT(Address)\ -{\ - unsigned char i;\ - u32 temp[10];\ - \ - memcpy(temp, Address, 40);\ - for (i = 0; i < 40; i += 4)\ - printk("\r\n %08x", temp[i]);\ -}\ - rt_status SendTxCommandPacket(struct net_device *dev, void *pData, u32 DataLen) { rt_status rtStatus = RT_STATUS_SUCCESS; From 977da7f0a5012b994f03af7be983f458edcd0644 Mon Sep 17 00:00:00 2001 From: Lilis Iskandar Date: Tue, 23 Jul 2013 19:51:02 +0800 Subject: [PATCH 0404/3400] Staging: bcm: Qos: Fix some coding style issues Fixed spacing/tabs issues that were found using checkpatch. Signed-off-by: Lilis Iskandar Reviewed-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/Qos.c | 526 +++++++++++++++++++------------------- 1 file changed, 263 insertions(+), 263 deletions(-) diff --git a/drivers/staging/bcm/Qos.c b/drivers/staging/bcm/Qos.c index 8d142a547e7f..2d4a77cca915 100644 --- a/drivers/staging/bcm/Qos.c +++ b/drivers/staging/bcm/Qos.c @@ -4,11 +4,11 @@ This file contains the routines related to Quality of Service. */ #include "headers.h" -static void EThCSGetPktInfo(struct bcm_mini_adapter *Adapter,PVOID pvEthPayload, struct bcm_eth_packet_info *pstEthCsPktInfo); -static BOOLEAN EThCSClassifyPkt(struct bcm_mini_adapter *Adapter,struct sk_buff* skb, struct bcm_eth_packet_info *pstEthCsPktInfo,struct bcm_classifier_rule *pstClassifierRule, B_UINT8 EthCSCupport); +static void EThCSGetPktInfo(struct bcm_mini_adapter *Adapter, PVOID pvEthPayload, struct bcm_eth_packet_info *pstEthCsPktInfo); +static BOOLEAN EThCSClassifyPkt(struct bcm_mini_adapter *Adapter, struct sk_buff* skb, struct bcm_eth_packet_info *pstEthCsPktInfo, struct bcm_classifier_rule *pstClassifierRule, B_UINT8 EthCSCupport); static USHORT IpVersion4(struct bcm_mini_adapter *Adapter, struct iphdr *iphd, - struct bcm_classifier_rule *pstClassifierRule ); + struct bcm_classifier_rule *pstClassifierRule); static VOID PruneQueue(struct bcm_mini_adapter *Adapter, INT iIndex); @@ -20,30 +20,30 @@ static VOID PruneQueue(struct bcm_mini_adapter *Adapter, INT iIndex); * matches with that of Queue. * * Parameters - pstClassifierRule: Pointer to the packet info structure. -* - ulSrcIP : Source IP address from the packet. +* - ulSrcIP : Source IP address from the packet. * * Returns - TRUE(If address matches) else FAIL . *********************************************************************/ -BOOLEAN MatchSrcIpAddress(struct bcm_classifier_rule *pstClassifierRule,ULONG ulSrcIP) +BOOLEAN MatchSrcIpAddress(struct bcm_classifier_rule *pstClassifierRule, ULONG ulSrcIP) { - UCHAR ucLoopIndex=0; + UCHAR ucLoopIndex = 0; - struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); + struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); - ulSrcIP=ntohl(ulSrcIP); - if(0 == pstClassifierRule->ucIPSourceAddressLength) - return TRUE; - for(ucLoopIndex=0; ucLoopIndex < (pstClassifierRule->ucIPSourceAddressLength);ucLoopIndex++) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Ip Address Mask:0x%x PacketIp:0x%x and Classification:0x%x", (UINT)pstClassifierRule->stSrcIpAddress.ulIpv4Mask[ucLoopIndex], (UINT)ulSrcIP, (UINT)pstClassifierRule->stSrcIpAddress.ulIpv6Addr[ucLoopIndex]); - if((pstClassifierRule->stSrcIpAddress.ulIpv4Mask[ucLoopIndex] & ulSrcIP)== - (pstClassifierRule->stSrcIpAddress.ulIpv4Addr[ucLoopIndex] & pstClassifierRule->stSrcIpAddress.ulIpv4Mask[ucLoopIndex] )) - { - return TRUE; - } - } - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Ip Address Not Matched"); - return FALSE; + ulSrcIP = ntohl(ulSrcIP); + if (0 == pstClassifierRule->ucIPSourceAddressLength) + return TRUE; + for (ucLoopIndex = 0; ucLoopIndex < (pstClassifierRule->ucIPSourceAddressLength); ucLoopIndex++) + { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Ip Address Mask:0x%x PacketIp:0x%x and Classification:0x%x", (UINT)pstClassifierRule->stSrcIpAddress.ulIpv4Mask[ucLoopIndex], (UINT)ulSrcIP, (UINT)pstClassifierRule->stSrcIpAddress.ulIpv6Addr[ucLoopIndex]); + if ((pstClassifierRule->stSrcIpAddress.ulIpv4Mask[ucLoopIndex] & ulSrcIP) == + (pstClassifierRule->stSrcIpAddress.ulIpv4Addr[ucLoopIndex] & pstClassifierRule->stSrcIpAddress.ulIpv4Mask[ucLoopIndex])) + { + return TRUE; + } + } + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Ip Address Not Matched"); + return FALSE; } @@ -54,30 +54,30 @@ BOOLEAN MatchSrcIpAddress(struct bcm_classifier_rule *pstClassifierRule,ULONG ul * matches with that of Queue. * * Parameters - pstClassifierRule: Pointer to the packet info structure. -* - ulDestIP : Destination IP address from the packet. +* - ulDestIP : Destination IP address from the packet. * * Returns - TRUE(If address matches) else FAIL . *********************************************************************/ -BOOLEAN MatchDestIpAddress(struct bcm_classifier_rule *pstClassifierRule,ULONG ulDestIP) +BOOLEAN MatchDestIpAddress(struct bcm_classifier_rule *pstClassifierRule, ULONG ulDestIP) { - UCHAR ucLoopIndex=0; + UCHAR ucLoopIndex = 0; struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); - ulDestIP=ntohl(ulDestIP); - if(0 == pstClassifierRule->ucIPDestinationAddressLength) - return TRUE; - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination Ip Address 0x%x 0x%x 0x%x ", (UINT)ulDestIP, (UINT)pstClassifierRule->stDestIpAddress.ulIpv4Mask[ucLoopIndex], (UINT)pstClassifierRule->stDestIpAddress.ulIpv4Addr[ucLoopIndex]); + ulDestIP = ntohl(ulDestIP); + if (0 == pstClassifierRule->ucIPDestinationAddressLength) + return TRUE; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination Ip Address 0x%x 0x%x 0x%x ", (UINT)ulDestIP, (UINT)pstClassifierRule->stDestIpAddress.ulIpv4Mask[ucLoopIndex], (UINT)pstClassifierRule->stDestIpAddress.ulIpv4Addr[ucLoopIndex]); - for(ucLoopIndex=0;ucLoopIndex<(pstClassifierRule->ucIPDestinationAddressLength);ucLoopIndex++) - { - if((pstClassifierRule->stDestIpAddress.ulIpv4Mask[ucLoopIndex] & ulDestIP)== - (pstClassifierRule->stDestIpAddress.ulIpv4Addr[ucLoopIndex] & pstClassifierRule->stDestIpAddress.ulIpv4Mask[ucLoopIndex])) - { - return TRUE; - } - } - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination Ip Address Not Matched"); - return FALSE; + for (ucLoopIndex = 0; ucLoopIndex < (pstClassifierRule->ucIPDestinationAddressLength); ucLoopIndex++) + { + if ((pstClassifierRule->stDestIpAddress.ulIpv4Mask[ucLoopIndex] & ulDestIP) == + (pstClassifierRule->stDestIpAddress.ulIpv4Addr[ucLoopIndex] & pstClassifierRule->stDestIpAddress.ulIpv4Mask[ucLoopIndex])) + { + return TRUE; + } + } + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination Ip Address Not Matched"); + return FALSE; } @@ -87,23 +87,23 @@ BOOLEAN MatchDestIpAddress(struct bcm_classifier_rule *pstClassifierRule,ULONG u * Description - Checks the TOS from the packet matches with that of queue. * * Parameters - pstClassifierRule : Pointer to the packet info structure. -* - ucTypeOfService: TOS from the packet. +* - ucTypeOfService: TOS from the packet. * * Returns - TRUE(If address matches) else FAIL. **************************************************************************/ -BOOLEAN MatchTos(struct bcm_classifier_rule *pstClassifierRule,UCHAR ucTypeOfService) +BOOLEAN MatchTos(struct bcm_classifier_rule *pstClassifierRule, UCHAR ucTypeOfService) { struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); - if( 3 != pstClassifierRule->ucIPTypeOfServiceLength ) - return TRUE; + if (3 != pstClassifierRule->ucIPTypeOfServiceLength) + return TRUE; - if(((pstClassifierRule->ucTosMask & ucTypeOfService)<=pstClassifierRule->ucTosHigh) && ((pstClassifierRule->ucTosMask & ucTypeOfService)>=pstClassifierRule->ucTosLow)) - { - return TRUE; - } - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Type Of Service Not Matched"); - return FALSE; + if (((pstClassifierRule->ucTosMask & ucTypeOfService) <= pstClassifierRule->ucTosHigh) && ((pstClassifierRule->ucTosMask & ucTypeOfService) >= pstClassifierRule->ucTosLow)) + { + return TRUE; + } + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Type Of Service Not Matched"); + return FALSE; } @@ -113,26 +113,26 @@ BOOLEAN MatchTos(struct bcm_classifier_rule *pstClassifierRule,UCHAR ucTypeOfSer * Description - Checks the protocol from the packet matches with that of queue. * * Parameters - pstClassifierRule: Pointer to the packet info structure. -* - ucProtocol : Protocol from the packet. +* - ucProtocol : Protocol from the packet. * * Returns - TRUE(If address matches) else FAIL. ****************************************************************************/ -bool MatchProtocol(struct bcm_classifier_rule *pstClassifierRule,UCHAR ucProtocol) +bool MatchProtocol(struct bcm_classifier_rule *pstClassifierRule, UCHAR ucProtocol) { - UCHAR ucLoopIndex=0; + UCHAR ucLoopIndex = 0; struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); - if(0 == pstClassifierRule->ucProtocolLength) - return TRUE; - for(ucLoopIndex=0;ucLoopIndexucProtocolLength;ucLoopIndex++) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Protocol:0x%X Classification Protocol:0x%X",ucProtocol,pstClassifierRule->ucProtocol[ucLoopIndex]); - if(pstClassifierRule->ucProtocol[ucLoopIndex]==ucProtocol) - { - return TRUE; - } - } - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Protocol Not Matched"); - return FALSE; + if (0 == pstClassifierRule->ucProtocolLength) + return TRUE; + for (ucLoopIndex = 0; ucLoopIndex < pstClassifierRule->ucProtocolLength; ucLoopIndex++) + { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Protocol:0x%X Classification Protocol:0x%X", ucProtocol, pstClassifierRule->ucProtocol[ucLoopIndex]); + if (pstClassifierRule->ucProtocol[ucLoopIndex] == ucProtocol) + { + return TRUE; + } + } + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Protocol Not Matched"); + return FALSE; } @@ -142,29 +142,29 @@ bool MatchProtocol(struct bcm_classifier_rule *pstClassifierRule,UCHAR ucProtoco * Description - Checks, Source port from the packet matches with that of queue. * * Parameters - pstClassifierRule: Pointer to the packet info structure. -* - ushSrcPort : Source port from the packet. +* - ushSrcPort : Source port from the packet. * * Returns - TRUE(If address matches) else FAIL. ***************************************************************************/ -bool MatchSrcPort(struct bcm_classifier_rule *pstClassifierRule,USHORT ushSrcPort) +bool MatchSrcPort(struct bcm_classifier_rule *pstClassifierRule, USHORT ushSrcPort) { - UCHAR ucLoopIndex=0; + UCHAR ucLoopIndex = 0; struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); - if(0 == pstClassifierRule->ucSrcPortRangeLength) - return TRUE; - for(ucLoopIndex=0;ucLoopIndexucSrcPortRangeLength;ucLoopIndex++) - { - if(ushSrcPort <= pstClassifierRule->usSrcPortRangeHi[ucLoopIndex] && - ushSrcPort >= pstClassifierRule->usSrcPortRangeLo[ucLoopIndex]) - { - return TRUE; - } - } - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Port: %x Not Matched ",ushSrcPort); - return FALSE; + if (0 == pstClassifierRule->ucSrcPortRangeLength) + return TRUE; + for (ucLoopIndex = 0; ucLoopIndex < pstClassifierRule->ucSrcPortRangeLength; ucLoopIndex++) + { + if (ushSrcPort <= pstClassifierRule->usSrcPortRangeHi[ucLoopIndex] && + ushSrcPort >= pstClassifierRule->usSrcPortRangeLo[ucLoopIndex]) + { + return TRUE; + } + } + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Port: %x Not Matched ", ushSrcPort); + return FALSE; } @@ -174,30 +174,30 @@ bool MatchSrcPort(struct bcm_classifier_rule *pstClassifierRule,USHORT ushSrcPor * Description - Checks, Destination port from packet matches with that of queue. * * Parameters - pstClassifierRule: Pointer to the packet info structure. -* - ushDestPort : Destination port from the packet. +* - ushDestPort : Destination port from the packet. * * Returns - TRUE(If address matches) else FAIL. ***************************************************************************/ -bool MatchDestPort(struct bcm_classifier_rule *pstClassifierRule,USHORT ushDestPort) +bool MatchDestPort(struct bcm_classifier_rule *pstClassifierRule, USHORT ushDestPort) { - UCHAR ucLoopIndex=0; + UCHAR ucLoopIndex = 0; struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); - if(0 == pstClassifierRule->ucDestPortRangeLength) - return TRUE; + if (0 == pstClassifierRule->ucDestPortRangeLength) + return TRUE; - for(ucLoopIndex=0;ucLoopIndexucDestPortRangeLength;ucLoopIndex++) - { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Matching Port:0x%X 0x%X 0x%X",ushDestPort,pstClassifierRule->usDestPortRangeLo[ucLoopIndex],pstClassifierRule->usDestPortRangeHi[ucLoopIndex]); + for (ucLoopIndex = 0; ucLoopIndex < pstClassifierRule->ucDestPortRangeLength; ucLoopIndex++) + { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Matching Port:0x%X 0x%X 0x%X", ushDestPort, pstClassifierRule->usDestPortRangeLo[ucLoopIndex], pstClassifierRule->usDestPortRangeHi[ucLoopIndex]); - if(ushDestPort <= pstClassifierRule->usDestPortRangeHi[ucLoopIndex] && - ushDestPort >= pstClassifierRule->usDestPortRangeLo[ucLoopIndex]) - { - return TRUE; - } - } - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Dest Port: %x Not Matched",ushDestPort); - return FALSE; + if (ushDestPort <= pstClassifierRule->usDestPortRangeHi[ucLoopIndex] && + ushDestPort >= pstClassifierRule->usDestPortRangeLo[ucLoopIndex]) + { + return TRUE; + } + } + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Dest Port: %x Not Matched", ushDestPort); + return FALSE; } /** @ingroup tx_functions @@ -209,95 +209,95 @@ static USHORT IpVersion4(struct bcm_mini_adapter *Adapter, struct bcm_classifier_rule *pstClassifierRule) { struct bcm_transport_header *xprt_hdr = NULL; - BOOLEAN bClassificationSucceed=FALSE; + BOOLEAN bClassificationSucceed = FALSE; - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "========>"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "========>"); - xprt_hdr=(struct bcm_transport_header *)((PUCHAR)iphd + sizeof(struct iphdr)); + xprt_hdr = (struct bcm_transport_header *)((PUCHAR)iphd + sizeof(struct iphdr)); do { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Trying to see Direction = %d %d", + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Trying to see Direction = %d %d", pstClassifierRule->ucDirection, pstClassifierRule->usVCID_Value); //Checking classifier validity - if(!pstClassifierRule->bUsed || pstClassifierRule->ucDirection == DOWNLINK_DIR) + if (!pstClassifierRule->bUsed || pstClassifierRule->ucDirection == DOWNLINK_DIR) { bClassificationSucceed = FALSE; break; } - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "is IPv6 check!"); - if(pstClassifierRule->bIpv6Protocol) + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "is IPv6 check!"); + if (pstClassifierRule->bIpv6Protocol) break; //**************Checking IP header parameter**************************// - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Trying to match Source IP Address"); - if(FALSE == (bClassificationSucceed = + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Trying to match Source IP Address"); + if (FALSE == (bClassificationSucceed = MatchSrcIpAddress(pstClassifierRule, iphd->saddr))) break; - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Source IP Address Matched"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Source IP Address Matched"); - if(FALSE == (bClassificationSucceed = + if (FALSE == (bClassificationSucceed = MatchDestIpAddress(pstClassifierRule, iphd->daddr))) break; - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination IP Address Matched"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination IP Address Matched"); - if(FALSE == (bClassificationSucceed = + if (FALSE == (bClassificationSucceed = MatchTos(pstClassifierRule, iphd->tos))) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "TOS Match failed\n"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "TOS Match failed\n"); break; } - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "TOS Matched"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "TOS Matched"); - if(FALSE == (bClassificationSucceed = - MatchProtocol(pstClassifierRule,iphd->protocol))) + if (FALSE == (bClassificationSucceed = + MatchProtocol(pstClassifierRule, iphd->protocol))) break; - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Protocol Matched"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Protocol Matched"); //if protocol is not TCP or UDP then no need of comparing source port and destination port - if(iphd->protocol!=TCP && iphd->protocol!=UDP) + if (iphd->protocol != TCP && iphd->protocol != UDP) break; //******************Checking Transport Layer Header field if present *****************// - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Source Port %04x", - (iphd->protocol==UDP)?xprt_hdr->uhdr.source:xprt_hdr->thdr.source); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Source Port %04x", + (iphd->protocol == UDP) ? xprt_hdr->uhdr.source : xprt_hdr->thdr.source); - if(FALSE == (bClassificationSucceed = + if (FALSE == (bClassificationSucceed = MatchSrcPort(pstClassifierRule, - ntohs((iphd->protocol == UDP)? - xprt_hdr->uhdr.source:xprt_hdr->thdr.source)))) + ntohs((iphd->protocol == UDP) ? + xprt_hdr->uhdr.source : xprt_hdr->thdr.source)))) break; - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Port Matched"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Port Matched"); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination Port %04x", - (iphd->protocol==UDP)?xprt_hdr->uhdr.dest: + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination Port %04x", + (iphd->protocol == UDP) ? xprt_hdr->uhdr.dest : xprt_hdr->thdr.dest); - if(FALSE == (bClassificationSucceed = + if (FALSE == (bClassificationSucceed = MatchDestPort(pstClassifierRule, - ntohs((iphd->protocol == UDP)? - xprt_hdr->uhdr.dest:xprt_hdr->thdr.dest)))) + ntohs((iphd->protocol == UDP) ? + xprt_hdr->uhdr.dest : xprt_hdr->thdr.dest)))) break; - } while(0); + } while (0); - if(TRUE==bClassificationSucceed) + if (TRUE == bClassificationSucceed) { INT iMatchedSFQueueIndex = 0; - iMatchedSFQueueIndex = SearchSfid(Adapter,pstClassifierRule->ulSFID); - if(iMatchedSFQueueIndex >= NO_OF_QUEUES) + iMatchedSFQueueIndex = SearchSfid(Adapter, pstClassifierRule->ulSFID); + if (iMatchedSFQueueIndex >= NO_OF_QUEUES) { bClassificationSucceed = FALSE; } else { - if(FALSE == Adapter->PackInfo[iMatchedSFQueueIndex].bActive) + if (FALSE == Adapter->PackInfo[iMatchedSFQueueIndex].bActive) { bClassificationSucceed = FALSE; } } } - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "IpVersion4 <=========="); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "IpVersion4 <=========="); return bClassificationSucceed; } @@ -306,9 +306,9 @@ VOID PruneQueueAllSF(struct bcm_mini_adapter *Adapter) { UINT iIndex = 0; - for(iIndex = 0; iIndex < HiPriority; iIndex++) + for (iIndex = 0; iIndex < HiPriority; iIndex++) { - if(!Adapter->PackInfo[iIndex].bValid) + if (!Adapter->PackInfo[iIndex].bValid) continue; PruneQueue(Adapter, iIndex); @@ -325,15 +325,15 @@ less than or equal to max queue size for the queue. */ static VOID PruneQueue(struct bcm_mini_adapter *Adapter, INT iIndex) { - struct sk_buff* PacketToDrop=NULL; + struct sk_buff* PacketToDrop = NULL; struct net_device_stats *netstats; - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, PRUNE_QUEUE, DBG_LVL_ALL, "=====> Index %d",iIndex); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, PRUNE_QUEUE, DBG_LVL_ALL, "=====> Index %d", iIndex); - if(iIndex == HiPriority) + if (iIndex == HiPriority) return; - if(!Adapter || (iIndex < 0) || (iIndex > HiPriority)) + if (!Adapter || (iIndex < 0) || (iIndex > HiPriority)) return; /* To Store the netdevice statistic */ @@ -341,26 +341,26 @@ static VOID PruneQueue(struct bcm_mini_adapter *Adapter, INT iIndex) spin_lock_bh(&Adapter->PackInfo[iIndex].SFQueueLock); - while(1) + while (1) // while((UINT)Adapter->PackInfo[iIndex].uiCurrentPacketsOnHost > // SF_MAX_ALLOWED_PACKETS_TO_BACKUP) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, PRUNE_QUEUE, DBG_LVL_ALL, "uiCurrentBytesOnHost:%x uiMaxBucketSize :%x", + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, PRUNE_QUEUE, DBG_LVL_ALL, "uiCurrentBytesOnHost:%x uiMaxBucketSize :%x", Adapter->PackInfo[iIndex].uiCurrentBytesOnHost, Adapter->PackInfo[iIndex].uiMaxBucketSize); PacketToDrop = Adapter->PackInfo[iIndex].FirstTxQueue; - if(PacketToDrop == NULL) + if (PacketToDrop == NULL) break; - if((Adapter->PackInfo[iIndex].uiCurrentPacketsOnHost < SF_MAX_ALLOWED_PACKETS_TO_BACKUP) && + if ((Adapter->PackInfo[iIndex].uiCurrentPacketsOnHost < SF_MAX_ALLOWED_PACKETS_TO_BACKUP) && ((1000*(jiffies - *((B_UINT32 *)(PacketToDrop->cb)+SKB_CB_LATENCY_OFFSET))/HZ) <= Adapter->PackInfo[iIndex].uiMaxLatency)) break; - if(PacketToDrop) + if (PacketToDrop) { if (netif_msg_tx_err(Adapter)) - pr_info(PFX "%s: tx queue %d overlimit\n", + pr_info(PFX "%s: tx queue %d overlimit\n", Adapter->dev->name, iIndex); netstats->tx_dropped++; @@ -378,7 +378,7 @@ static VOID PruneQueue(struct bcm_mini_adapter *Adapter, INT iIndex) } - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, PRUNE_QUEUE, DBG_LVL_ALL, "Dropped Bytes:%x Dropped Packets:%x", + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, PRUNE_QUEUE, DBG_LVL_ALL, "Dropped Bytes:%x Dropped Packets:%x", Adapter->PackInfo[iIndex].uiDroppedCountBytes, Adapter->PackInfo[iIndex].uiDroppedCountPackets); @@ -387,29 +387,29 @@ static VOID PruneQueue(struct bcm_mini_adapter *Adapter, INT iIndex) spin_unlock_bh(&Adapter->PackInfo[iIndex].SFQueueLock); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, PRUNE_QUEUE, DBG_LVL_ALL, "TotalPacketCount:%x", + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, PRUNE_QUEUE, DBG_LVL_ALL, "TotalPacketCount:%x", atomic_read(&Adapter->TotalPacketCount)); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, PRUNE_QUEUE, DBG_LVL_ALL, "<====="); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, PRUNE_QUEUE, DBG_LVL_ALL, "<====="); } VOID flush_all_queues(struct bcm_mini_adapter *Adapter) { INT iQIndex; UINT uiTotalPacketLength; - struct sk_buff* PacketToDrop=NULL; + struct sk_buff* PacketToDrop = NULL; - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "=====>"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "=====>"); // down(&Adapter->data_packet_queue_lock); - for(iQIndex=LowPriority; iQIndexdev->stats; spin_lock_bh(&Adapter->PackInfo[iQIndex].SFQueueLock); - while(Adapter->PackInfo[iQIndex].FirstTxQueue) + while (Adapter->PackInfo[iQIndex].FirstTxQueue) { PacketToDrop = Adapter->PackInfo[iQIndex].FirstTxQueue; - if(PacketToDrop) + if (PacketToDrop) { uiTotalPacketLength = PacketToDrop->len; netstats->tx_dropped++; @@ -431,7 +431,7 @@ VOID flush_all_queues(struct bcm_mini_adapter *Adapter) Adapter->PackInfo[iQIndex].uiDroppedCountBytes += uiTotalPacketLength; Adapter->PackInfo[iQIndex].uiDroppedCountPackets++; - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Dropped Bytes:%x Dropped Packets:%x", + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Dropped Bytes:%x Dropped Packets:%x", Adapter->PackInfo[iQIndex].uiDroppedCountBytes, Adapter->PackInfo[iQIndex].uiDroppedCountPackets); atomic_dec(&Adapter->TotalPacketCount); @@ -439,30 +439,30 @@ VOID flush_all_queues(struct bcm_mini_adapter *Adapter) spin_unlock_bh(&Adapter->PackInfo[iQIndex].SFQueueLock); } // up(&Adapter->data_packet_queue_lock); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "<====="); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "<====="); } -USHORT ClassifyPacket(struct bcm_mini_adapter *Adapter,struct sk_buff* skb) +USHORT ClassifyPacket(struct bcm_mini_adapter *Adapter, struct sk_buff* skb) { - INT uiLoopIndex=0; + INT uiLoopIndex = 0; struct bcm_classifier_rule *pstClassifierRule = NULL; struct bcm_eth_packet_info stEthCsPktInfo; PVOID pvEThPayload = NULL; - struct iphdr *pIpHeader = NULL; - INT uiSfIndex=0; - USHORT usIndex=Adapter->usBestEffortQueueIndex; - BOOLEAN bFragmentedPkt=FALSE,bClassificationSucceed=FALSE; - USHORT usCurrFragment =0; + struct iphdr *pIpHeader = NULL; + INT uiSfIndex = 0; + USHORT usIndex = Adapter->usBestEffortQueueIndex; + BOOLEAN bFragmentedPkt = FALSE, bClassificationSucceed = FALSE; + USHORT usCurrFragment = 0; struct bcm_tcp_header *pTcpHeader; UCHAR IpHeaderLength; UCHAR TcpHeaderLength; pvEThPayload = skb->data; - *((UINT32*) (skb->cb) +SKB_CB_TCPACK_OFFSET ) = 0; - EThCSGetPktInfo(Adapter,pvEThPayload,&stEthCsPktInfo); + *((UINT32*) (skb->cb) +SKB_CB_TCPACK_OFFSET) = 0; + EThCSGetPktInfo(Adapter, pvEThPayload, &stEthCsPktInfo); - switch(stEthCsPktInfo.eNwpktEthFrameType) + switch (stEthCsPktInfo.eNwpktEthFrameType) { case eEth802LLCFrame: { @@ -497,75 +497,75 @@ USHORT ClassifyPacket(struct bcm_mini_adapter *Adapter,struct sk_buff* skb) } } - if(stEthCsPktInfo.eNwpktIPFrameType == eIPv4Packet) + if (stEthCsPktInfo.eNwpktIPFrameType == eIPv4Packet) { usCurrFragment = (ntohs(pIpHeader->frag_off) & IP_OFFSET); - if((ntohs(pIpHeader->frag_off) & IP_MF) || usCurrFragment) + if ((ntohs(pIpHeader->frag_off) & IP_MF) || usCurrFragment) bFragmentedPkt = TRUE; - if(bFragmentedPkt) + if (bFragmentedPkt) { //Fragmented Packet. Get Frag Classifier Entry. - pstClassifierRule = GetFragIPClsEntry(Adapter,pIpHeader->id, pIpHeader->saddr); - if(pstClassifierRule) + pstClassifierRule = GetFragIPClsEntry(Adapter, pIpHeader->id, pIpHeader->saddr); + if (pstClassifierRule) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,"It is next Fragmented pkt"); - bClassificationSucceed=TRUE; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "It is next Fragmented pkt"); + bClassificationSucceed = TRUE; } - if(!(ntohs(pIpHeader->frag_off) & IP_MF)) + if (!(ntohs(pIpHeader->frag_off) & IP_MF)) { //Fragmented Last packet . Remove Frag Classifier Entry - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,"This is the last fragmented Pkt"); - DelFragIPClsEntry(Adapter,pIpHeader->id, pIpHeader->saddr); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "This is the last fragmented Pkt"); + DelFragIPClsEntry(Adapter, pIpHeader->id, pIpHeader->saddr); } } } - for(uiLoopIndex = MAX_CLASSIFIERS - 1; uiLoopIndex >= 0; uiLoopIndex--) + for (uiLoopIndex = MAX_CLASSIFIERS - 1; uiLoopIndex >= 0; uiLoopIndex--) { - if(bClassificationSucceed) + if (bClassificationSucceed) break; //Iterate through all classifiers which are already in order of priority //to classify the packet until match found do { - if(FALSE==Adapter->astClassifierTable[uiLoopIndex].bUsed) + if (FALSE == Adapter->astClassifierTable[uiLoopIndex].bUsed) { - bClassificationSucceed=FALSE; + bClassificationSucceed = FALSE; break; } - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Adapter->PackInfo[%d].bvalid=True\n",uiLoopIndex); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Adapter->PackInfo[%d].bvalid=True\n", uiLoopIndex); - if(0 == Adapter->astClassifierTable[uiLoopIndex].ucDirection) + if (0 == Adapter->astClassifierTable[uiLoopIndex].ucDirection) { - bClassificationSucceed=FALSE;//cannot be processed for classification. + bClassificationSucceed = FALSE;//cannot be processed for classification. break; // it is a down link connection } pstClassifierRule = &Adapter->astClassifierTable[uiLoopIndex]; - uiSfIndex = SearchSfid(Adapter,pstClassifierRule->ulSFID); + uiSfIndex = SearchSfid(Adapter, pstClassifierRule->ulSFID); if (uiSfIndex >= NO_OF_QUEUES) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Queue Not Valid. SearchSfid for this classifier Failed\n"); break; } - if(Adapter->PackInfo[uiSfIndex].bEthCSSupport) + if (Adapter->PackInfo[uiSfIndex].bEthCSSupport) { - if(eEthUnsupportedFrame==stEthCsPktInfo.eNwpktEthFrameType) + if (eEthUnsupportedFrame == stEthCsPktInfo.eNwpktEthFrameType) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, " ClassifyPacket : Packet Not a Valid Supported Ethernet Frame \n"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, " ClassifyPacket : Packet Not a Valid Supported Ethernet Frame\n"); bClassificationSucceed = FALSE; break; } - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Performing ETH CS Classification on Classifier Rule ID : %x Service Flow ID : %lx\n",pstClassifierRule->uiClassifierRuleIndex,Adapter->PackInfo[uiSfIndex].ulSFID); - bClassificationSucceed = EThCSClassifyPkt(Adapter,skb,&stEthCsPktInfo,pstClassifierRule, Adapter->PackInfo[uiSfIndex].bEthCSSupport); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Performing ETH CS Classification on Classifier Rule ID : %x Service Flow ID : %lx\n", pstClassifierRule->uiClassifierRuleIndex, Adapter->PackInfo[uiSfIndex].ulSFID); + bClassificationSucceed = EThCSClassifyPkt(Adapter, skb, &stEthCsPktInfo, pstClassifierRule, Adapter->PackInfo[uiSfIndex].bEthCSSupport); - if(!bClassificationSucceed) + if (!bClassificationSucceed) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : Ethernet CS Classification Failed\n"); break; @@ -574,9 +574,9 @@ USHORT ClassifyPacket(struct bcm_mini_adapter *Adapter,struct sk_buff* skb) else // No ETH Supported on this SF { - if(eEthOtherFrame != stEthCsPktInfo.eNwpktEthFrameType) + if (eEthOtherFrame != stEthCsPktInfo.eNwpktEthFrameType) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, " ClassifyPacket : Packet Not a 802.3 Ethernet Frame... hence not allowed over non-ETH CS SF \n"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, " ClassifyPacket : Packet Not a 802.3 Ethernet Frame... hence not allowed over non-ETH CS SF\n"); bClassificationSucceed = FALSE; break; } @@ -584,51 +584,51 @@ USHORT ClassifyPacket(struct bcm_mini_adapter *Adapter,struct sk_buff* skb) BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Proceeding to IP CS Clasification"); - if(Adapter->PackInfo[uiSfIndex].bIPCSSupport) + if (Adapter->PackInfo[uiSfIndex].bIPCSSupport) { - if(stEthCsPktInfo.eNwpktIPFrameType == eNonIPPacket) + if (stEthCsPktInfo.eNwpktIPFrameType == eNonIPPacket) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, " ClassifyPacket : Packet is Not an IP Packet \n"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, " ClassifyPacket : Packet is Not an IP Packet\n"); bClassificationSucceed = FALSE; break; } - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Dump IP Header : \n"); - DumpFullPacket((PUCHAR)pIpHeader,20); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Dump IP Header :\n"); + DumpFullPacket((PUCHAR)pIpHeader, 20); - if(stEthCsPktInfo.eNwpktIPFrameType == eIPv4Packet) - bClassificationSucceed = IpVersion4(Adapter,pIpHeader,pstClassifierRule); - else if(stEthCsPktInfo.eNwpktIPFrameType == eIPv6Packet) - bClassificationSucceed = IpVersion6(Adapter,pIpHeader,pstClassifierRule); + if (stEthCsPktInfo.eNwpktIPFrameType == eIPv4Packet) + bClassificationSucceed = IpVersion4(Adapter, pIpHeader, pstClassifierRule); + else if (stEthCsPktInfo.eNwpktIPFrameType == eIPv6Packet) + bClassificationSucceed = IpVersion6(Adapter, pIpHeader, pstClassifierRule); } - }while(0); + } while (0); } - if(bClassificationSucceed == TRUE) + if (bClassificationSucceed == TRUE) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "CF id : %d, SF ID is =%lu",pstClassifierRule->uiClassifierRuleIndex, pstClassifierRule->ulSFID); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "CF id : %d, SF ID is =%lu", pstClassifierRule->uiClassifierRuleIndex, pstClassifierRule->ulSFID); //Store The matched Classifier in SKB *((UINT32*)(skb->cb)+SKB_CB_CLASSIFICATION_OFFSET) = pstClassifierRule->uiClassifierRuleIndex; - if((TCP == pIpHeader->protocol ) && !bFragmentedPkt && (ETH_AND_IP_HEADER_LEN + TCP_HEADER_LEN <= skb->len) ) + if ((TCP == pIpHeader->protocol) && !bFragmentedPkt && (ETH_AND_IP_HEADER_LEN + TCP_HEADER_LEN <= skb->len)) { IpHeaderLength = pIpHeader->ihl; pTcpHeader = (struct bcm_tcp_header *)(((PUCHAR)pIpHeader)+(IpHeaderLength*4)); TcpHeaderLength = GET_TCP_HEADER_LEN(pTcpHeader->HeaderLength); - if((pTcpHeader->ucFlags & TCP_ACK) && + if ((pTcpHeader->ucFlags & TCP_ACK) && (ntohs(pIpHeader->tot_len) == (IpHeaderLength*4)+(TcpHeaderLength*4))) { - *((UINT32*) (skb->cb) +SKB_CB_TCPACK_OFFSET ) = TCP_ACK; + *((UINT32*) (skb->cb) + SKB_CB_TCPACK_OFFSET) = TCP_ACK; } } usIndex = SearchSfid(Adapter, pstClassifierRule->ulSFID); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "index is =%d", usIndex); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "index is =%d", usIndex); //If this is the first fragment of a Fragmented pkt, add this CF. Only This CF should be used for all other fragment of this Pkt. - if(bFragmentedPkt && (usCurrFragment == 0)) + if (bFragmentedPkt && (usCurrFragment == 0)) { //First Fragment of Fragmented Packet. Create Frag CLS Entry struct bcm_fragmented_packet_info stFragPktInfo; @@ -637,77 +637,77 @@ USHORT ClassifyPacket(struct bcm_mini_adapter *Adapter,struct sk_buff* skb) stFragPktInfo.usIpIdentification = pIpHeader->id; stFragPktInfo.pstMatchedClassifierEntry = pstClassifierRule; stFragPktInfo.bOutOfOrderFragment = FALSE; - AddFragIPClsEntry(Adapter,&stFragPktInfo); + AddFragIPClsEntry(Adapter, &stFragPktInfo); } } - if(bClassificationSucceed) + if (bClassificationSucceed) return usIndex; else return INVALID_QUEUE_INDEX; } -static BOOLEAN EthCSMatchSrcMACAddress(struct bcm_classifier_rule *pstClassifierRule,PUCHAR Mac) +static BOOLEAN EthCSMatchSrcMACAddress(struct bcm_classifier_rule *pstClassifierRule, PUCHAR Mac) { - UINT i=0; + UINT i = 0; struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); - if(pstClassifierRule->ucEthCSSrcMACLen==0) + if (pstClassifierRule->ucEthCSSrcMACLen == 0) return TRUE; - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s \n",__FUNCTION__); - for(i=0;iau8EThCSSrcMAC[i],pstClassifierRule->au8EThCSSrcMACMask[i]); - if((pstClassifierRule->au8EThCSSrcMAC[i] & pstClassifierRule->au8EThCSSrcMACMask[i])!= + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "SRC MAC[%x] = %x ClassifierRuleSrcMAC = %x Mask : %x\n", i, Mac[i], pstClassifierRule->au8EThCSSrcMAC[i], pstClassifierRule->au8EThCSSrcMACMask[i]); + if ((pstClassifierRule->au8EThCSSrcMAC[i] & pstClassifierRule->au8EThCSSrcMACMask[i]) != (Mac[i] & pstClassifierRule->au8EThCSSrcMACMask[i])) return FALSE; } return TRUE; } -static BOOLEAN EthCSMatchDestMACAddress(struct bcm_classifier_rule *pstClassifierRule,PUCHAR Mac) +static BOOLEAN EthCSMatchDestMACAddress(struct bcm_classifier_rule *pstClassifierRule, PUCHAR Mac) { - UINT i=0; + UINT i = 0; struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); - if(pstClassifierRule->ucEthCSDestMACLen==0) + if (pstClassifierRule->ucEthCSDestMACLen == 0) return TRUE; - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s \n",__FUNCTION__); - for(i=0;iau8EThCSDestMAC[i],pstClassifierRule->au8EThCSDestMACMask[i]); - if((pstClassifierRule->au8EThCSDestMAC[i] & pstClassifierRule->au8EThCSDestMACMask[i])!= + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "SRC MAC[%x] = %x ClassifierRuleSrcMAC = %x Mask : %x\n", i, Mac[i], pstClassifierRule->au8EThCSDestMAC[i], pstClassifierRule->au8EThCSDestMACMask[i]); + if ((pstClassifierRule->au8EThCSDestMAC[i] & pstClassifierRule->au8EThCSDestMACMask[i]) != (Mac[i] & pstClassifierRule->au8EThCSDestMACMask[i])) return FALSE; } return TRUE; } -static BOOLEAN EthCSMatchEThTypeSAP(struct bcm_classifier_rule *pstClassifierRule,struct sk_buff* skb, struct bcm_eth_packet_info *pstEthCsPktInfo) +static BOOLEAN EthCSMatchEThTypeSAP(struct bcm_classifier_rule *pstClassifierRule, struct sk_buff* skb, struct bcm_eth_packet_info *pstEthCsPktInfo) { struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); - if((pstClassifierRule->ucEtherTypeLen==0)|| + if ((pstClassifierRule->ucEtherTypeLen == 0) || (pstClassifierRule->au8EthCSEtherType[0] == 0)) return TRUE; - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s SrcEtherType:%x CLS EtherType[0]:%x\n",__FUNCTION__,pstEthCsPktInfo->usEtherType,pstClassifierRule->au8EthCSEtherType[0]); - if(pstClassifierRule->au8EthCSEtherType[0] == 1) + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s SrcEtherType:%x CLS EtherType[0]:%x\n", __FUNCTION__, pstEthCsPktInfo->usEtherType, pstClassifierRule->au8EthCSEtherType[0]); + if (pstClassifierRule->au8EthCSEtherType[0] == 1) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s CLS EtherType[1]:%x EtherType[2]:%x\n",__FUNCTION__,pstClassifierRule->au8EthCSEtherType[1],pstClassifierRule->au8EthCSEtherType[2]); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s CLS EtherType[1]:%x EtherType[2]:%x\n", __FUNCTION__, pstClassifierRule->au8EthCSEtherType[1], pstClassifierRule->au8EthCSEtherType[2]); - if(memcmp(&pstEthCsPktInfo->usEtherType,&pstClassifierRule->au8EthCSEtherType[1],2)==0) + if (memcmp(&pstEthCsPktInfo->usEtherType, &pstClassifierRule->au8EthCSEtherType[1], 2) == 0) return TRUE; else return FALSE; } - if(pstClassifierRule->au8EthCSEtherType[0] == 2) + if (pstClassifierRule->au8EthCSEtherType[0] == 2) { - if(eEth802LLCFrame != pstEthCsPktInfo->eNwpktEthFrameType) + if (eEth802LLCFrame != pstEthCsPktInfo->eNwpktEthFrameType) return FALSE; - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s EthCS DSAP:%x EtherType[2]:%x\n",__FUNCTION__,pstEthCsPktInfo->ucDSAP,pstClassifierRule->au8EthCSEtherType[2]); - if(pstEthCsPktInfo->ucDSAP == pstClassifierRule->au8EthCSEtherType[2]) + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s EthCS DSAP:%x EtherType[2]:%x\n", __FUNCTION__, pstEthCsPktInfo->ucDSAP, pstClassifierRule->au8EthCSEtherType[2]); + if (pstEthCsPktInfo->ucDSAP == pstClassifierRule->au8EthCSEtherType[2]) return TRUE; else return FALSE; @@ -718,27 +718,27 @@ static BOOLEAN EthCSMatchEThTypeSAP(struct bcm_classifier_rule *pstClassifierRul } -static BOOLEAN EthCSMatchVLANRules(struct bcm_classifier_rule *pstClassifierRule,struct sk_buff* skb, struct bcm_eth_packet_info *pstEthCsPktInfo) +static BOOLEAN EthCSMatchVLANRules(struct bcm_classifier_rule *pstClassifierRule, struct sk_buff* skb, struct bcm_eth_packet_info *pstEthCsPktInfo) { BOOLEAN bClassificationSucceed = FALSE; USHORT usVLANID; B_UINT8 uPriority = 0; struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s CLS UserPrio:%x CLS VLANID:%x\n",__FUNCTION__,ntohs(*((USHORT *)pstClassifierRule->usUserPriority)),pstClassifierRule->usVLANID); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s CLS UserPrio:%x CLS VLANID:%x\n", __FUNCTION__, ntohs(*((USHORT *)pstClassifierRule->usUserPriority)), pstClassifierRule->usVLANID); /* In case FW didn't receive the TLV, the priority field should be ignored */ - if(pstClassifierRule->usValidityBitMap & (1<usValidityBitMap & (1<eNwpktEthFrameType!=eEth802QVLANFrame) + if (pstEthCsPktInfo->eNwpktEthFrameType != eEth802QVLANFrame) return FALSE; uPriority = (ntohs(*(USHORT *)(skb->data + sizeof(struct bcm_eth_header))) & 0xF000) >> 13; - if((uPriority >= pstClassifierRule->usUserPriority[0]) && (uPriority <= pstClassifierRule->usUserPriority[1])) + if ((uPriority >= pstClassifierRule->usUserPriority[0]) && (uPriority <= pstClassifierRule->usUserPriority[1])) bClassificationSucceed = TRUE; - if(!bClassificationSucceed) + if (!bClassificationSucceed) return FALSE; } @@ -746,19 +746,19 @@ static BOOLEAN EthCSMatchVLANRules(struct bcm_classifier_rule *pstClassifierRule bClassificationSucceed = FALSE; - if(pstClassifierRule->usValidityBitMap & (1<usValidityBitMap & (1<eNwpktEthFrameType!=eEth802QVLANFrame) + if (pstEthCsPktInfo->eNwpktEthFrameType != eEth802QVLANFrame) return FALSE; usVLANID = ntohs(*(USHORT *)(skb->data + sizeof(struct bcm_eth_header))) & 0xFFF; - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s Pkt VLANID %x Priority: %d\n",__FUNCTION__,usVLANID, uPriority); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s Pkt VLANID %x Priority: %d\n", __FUNCTION__, usVLANID, uPriority); - if(usVLANID == ((pstClassifierRule->usVLANID & 0xFFF0) >> 4)) + if (usVLANID == ((pstClassifierRule->usVLANID & 0xFFF0) >> 4)) bClassificationSucceed = TRUE; - if(!bClassificationSucceed) + if (!bClassificationSucceed) return FALSE; } @@ -768,50 +768,50 @@ static BOOLEAN EthCSMatchVLANRules(struct bcm_classifier_rule *pstClassifierRule } -static BOOLEAN EThCSClassifyPkt(struct bcm_mini_adapter *Adapter,struct sk_buff* skb, +static BOOLEAN EThCSClassifyPkt(struct bcm_mini_adapter *Adapter, struct sk_buff* skb, struct bcm_eth_packet_info *pstEthCsPktInfo, struct bcm_classifier_rule *pstClassifierRule, B_UINT8 EthCSCupport) { BOOLEAN bClassificationSucceed = FALSE; - bClassificationSucceed = EthCSMatchSrcMACAddress(pstClassifierRule,((struct bcm_eth_header *)(skb->data))->au8SourceAddress); - if(!bClassificationSucceed) + bClassificationSucceed = EthCSMatchSrcMACAddress(pstClassifierRule, ((struct bcm_eth_header *)(skb->data))->au8SourceAddress); + if (!bClassificationSucceed) return FALSE; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ETH CS SrcMAC Matched\n"); - bClassificationSucceed = EthCSMatchDestMACAddress(pstClassifierRule,((struct bcm_eth_header *)(skb->data))->au8DestinationAddress); - if(!bClassificationSucceed) + bClassificationSucceed = EthCSMatchDestMACAddress(pstClassifierRule, ((struct bcm_eth_header *)(skb->data))->au8DestinationAddress); + if (!bClassificationSucceed) return FALSE; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ETH CS DestMAC Matched\n"); //classify on ETHType/802.2SAP TLV - bClassificationSucceed = EthCSMatchEThTypeSAP(pstClassifierRule,skb,pstEthCsPktInfo); - if(!bClassificationSucceed) + bClassificationSucceed = EthCSMatchEThTypeSAP(pstClassifierRule, skb, pstEthCsPktInfo); + if (!bClassificationSucceed) return FALSE; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ETH CS EthType/802.2SAP Matched\n"); //classify on 802.1VLAN Header Parameters - bClassificationSucceed = EthCSMatchVLANRules(pstClassifierRule,skb,pstEthCsPktInfo); - if(!bClassificationSucceed) + bClassificationSucceed = EthCSMatchVLANRules(pstClassifierRule, skb, pstEthCsPktInfo); + if (!bClassificationSucceed) return FALSE; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ETH CS 802.1 VLAN Rules Matched\n"); return bClassificationSucceed; } -static void EThCSGetPktInfo(struct bcm_mini_adapter *Adapter,PVOID pvEthPayload, +static void EThCSGetPktInfo(struct bcm_mini_adapter *Adapter, PVOID pvEthPayload, struct bcm_eth_packet_info *pstEthCsPktInfo) { USHORT u16Etype = ntohs(((struct bcm_eth_header *)pvEthPayload)->u16Etype); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "EthCSGetPktInfo : Eth Hdr Type : %X\n",u16Etype); - if(u16Etype > 0x5dc) + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "EthCSGetPktInfo : Eth Hdr Type : %X\n", u16Etype); + if (u16Etype > 0x5dc) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "EthCSGetPktInfo : ETH2 Frame \n"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "EthCSGetPktInfo : ETH2 Frame\n"); //ETH2 Frame - if(u16Etype == ETHERNET_FRAMETYPE_802QVLAN) + if (u16Etype == ETHERNET_FRAMETYPE_802QVLAN) { //802.1Q VLAN Header pstEthCsPktInfo->eNwpktEthFrameType = eEth802QVLANFrame; @@ -828,27 +828,27 @@ static void EThCSGetPktInfo(struct bcm_mini_adapter *Adapter,PVOID pvEthPayload, else { //802.2 LLC - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "802.2 LLC Frame \n"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "802.2 LLC Frame\n"); pstEthCsPktInfo->eNwpktEthFrameType = eEth802LLCFrame; pstEthCsPktInfo->ucDSAP = ((struct bcm_eth_llc_frame *)pvEthPayload)->DSAP; - if(pstEthCsPktInfo->ucDSAP == 0xAA && ((struct bcm_eth_llc_frame *)pvEthPayload)->SSAP == 0xAA) + if (pstEthCsPktInfo->ucDSAP == 0xAA && ((struct bcm_eth_llc_frame *)pvEthPayload)->SSAP == 0xAA) { //SNAP Frame pstEthCsPktInfo->eNwpktEthFrameType = eEth802LLCSNAPFrame; u16Etype = ((struct bcm_eth_llc_snap_frame *)pvEthPayload)->usEtherType; } } - if(u16Etype == ETHERNET_FRAMETYPE_IPV4) + if (u16Etype == ETHERNET_FRAMETYPE_IPV4) pstEthCsPktInfo->eNwpktIPFrameType = eIPv4Packet; - else if(u16Etype == ETHERNET_FRAMETYPE_IPV6) + else if (u16Etype == ETHERNET_FRAMETYPE_IPV6) pstEthCsPktInfo->eNwpktIPFrameType = eIPv6Packet; else pstEthCsPktInfo->eNwpktIPFrameType = eNonIPPacket; pstEthCsPktInfo->usEtherType = ((struct bcm_eth_header *)pvEthPayload)->u16Etype; - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "EthCsPktInfo->eNwpktIPFrameType : %x\n",pstEthCsPktInfo->eNwpktIPFrameType); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "EthCsPktInfo->eNwpktEthFrameType : %x\n",pstEthCsPktInfo->eNwpktEthFrameType); - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "EthCsPktInfo->usEtherType : %x\n",pstEthCsPktInfo->usEtherType); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "EthCsPktInfo->eNwpktIPFrameType : %x\n", pstEthCsPktInfo->eNwpktIPFrameType); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "EthCsPktInfo->eNwpktEthFrameType : %x\n", pstEthCsPktInfo->eNwpktEthFrameType); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "EthCsPktInfo->usEtherType : %x\n", pstEthCsPktInfo->usEtherType); } From 26b76798e0507429506b93cd49f8c4cfdab06896 Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Tue, 23 Jul 2013 11:35:47 +0300 Subject: [PATCH 0405/3400] Intel xhci: refactor EHCI/xHCI port switching Make the Linux xHCI driver automatically try to switchover the EHCI ports to xHCI when an Intel xHCI host is detected, and it also finds an Intel EHCI host. This means we will no longer have to add Intel xHCI hosts to a quirks list when the PCI device IDs change. Simply continuing to add new Intel xHCI PCI device IDs to the quirks list is not sustainable. During suspend ports may be swicthed back to EHCI by BIOS and not properly restored to xHCI at resume. Previously both EHCI and xHCI resume functions switched ports back to XHCI, but it's enough to do it in xHCI only because the hub driver doesn't start running again until after both hosts are resumed. Signed-off-by: Mathias Nyman Signed-off-by: Sarah Sharp --- drivers/usb/host/ehci-pci.c | 42 ------------------------------ drivers/usb/host/pci-quirks.c | 48 +++++++++++++---------------------- drivers/usb/host/pci-quirks.h | 3 +-- drivers/usb/host/xhci-pci.c | 14 +++++----- 4 files changed, 27 insertions(+), 80 deletions(-) diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 595d210655b6..6bd299e61f58 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -315,53 +315,11 @@ done: * Also they depend on separate root hub suspend/resume. */ -static bool usb_is_intel_switchable_ehci(struct pci_dev *pdev) -{ - return pdev->class == PCI_CLASS_SERIAL_USB_EHCI && - pdev->vendor == PCI_VENDOR_ID_INTEL && - (pdev->device == 0x1E26 || - pdev->device == 0x8C2D || - pdev->device == 0x8C26 || - pdev->device == 0x9C26); -} - -static void ehci_enable_xhci_companion(void) -{ - struct pci_dev *companion = NULL; - - /* The xHCI and EHCI controllers are not on the same PCI slot */ - for_each_pci_dev(companion) { - if (!usb_is_intel_switchable_xhci(companion)) - continue; - usb_enable_xhci_ports(companion); - return; - } -} - static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); struct pci_dev *pdev = to_pci_dev(hcd->self.controller); - /* The BIOS on systems with the Intel Panther Point chipset may or may - * not support xHCI natively. That means that during system resume, it - * may switch the ports back to EHCI so that users can use their - * keyboard to select a kernel from GRUB after resume from hibernate. - * - * The BIOS is supposed to remember whether the OS had xHCI ports - * enabled before resume, and switch the ports back to xHCI when the - * BIOS/OS semaphore is written, but we all know we can't trust BIOS - * writers. - * - * Unconditionally switch the ports back to xHCI after a system resume. - * We can't tell whether the EHCI or xHCI controller will be resumed - * first, so we have to do the port switchover in both drivers. Writing - * a '1' to the port switchover registers should have no effect if the - * port was already switched over. - */ - if (usb_is_intel_switchable_ehci(pdev)) - ehci_enable_xhci_companion(); - if (ehci_resume(hcd, hibernated) != 0) (void) ehci_pci_reinit(ehci, pdev); return 0; diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index b9848e4d3d44..2c76ef1320ea 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -735,32 +735,6 @@ static int handshake(void __iomem *ptr, u32 mask, u32 done, return -ETIMEDOUT; } -#define PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI 0x8C31 -#define PCI_DEVICE_ID_INTEL_LYNX_POINT_LP_XHCI 0x9C31 - -bool usb_is_intel_ppt_switchable_xhci(struct pci_dev *pdev) -{ - return pdev->class == PCI_CLASS_SERIAL_USB_XHCI && - pdev->vendor == PCI_VENDOR_ID_INTEL && - pdev->device == PCI_DEVICE_ID_INTEL_PANTHERPOINT_XHCI; -} - -/* The Intel Lynx Point chipset also has switchable ports. */ -bool usb_is_intel_lpt_switchable_xhci(struct pci_dev *pdev) -{ - return pdev->class == PCI_CLASS_SERIAL_USB_XHCI && - pdev->vendor == PCI_VENDOR_ID_INTEL && - (pdev->device == PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI || - pdev->device == PCI_DEVICE_ID_INTEL_LYNX_POINT_LP_XHCI); -} - -bool usb_is_intel_switchable_xhci(struct pci_dev *pdev) -{ - return usb_is_intel_ppt_switchable_xhci(pdev) || - usb_is_intel_lpt_switchable_xhci(pdev); -} -EXPORT_SYMBOL_GPL(usb_is_intel_switchable_xhci); - /* * Intel's Panther Point chipset has two host controllers (EHCI and xHCI) that * share some number of ports. These ports can be switched between either @@ -779,9 +753,23 @@ EXPORT_SYMBOL_GPL(usb_is_intel_switchable_xhci); * terminations before switching the USB 2.0 wires over, so that USB 3.0 * devices connect at SuperSpeed, rather than at USB 2.0 speeds. */ -void usb_enable_xhci_ports(struct pci_dev *xhci_pdev) +void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev) { u32 ports_available; + bool ehci_found = false; + struct pci_dev *companion = NULL; + + /* make sure an intel EHCI controller exists */ + for_each_pci_dev(companion) { + if (companion->class == PCI_CLASS_SERIAL_USB_EHCI && + companion->vendor == PCI_VENDOR_ID_INTEL) { + ehci_found = true; + break; + } + } + + if (!ehci_found) + return; /* Don't switchover the ports if the user hasn't compiled the xHCI * driver. Otherwise they will see "dead" USB ports that don't power @@ -840,7 +828,7 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev) dev_dbg(&xhci_pdev->dev, "USB 2.0 ports that are now switched over " "to xHCI: 0x%x\n", ports_available); } -EXPORT_SYMBOL_GPL(usb_enable_xhci_ports); +EXPORT_SYMBOL_GPL(usb_enable_intel_xhci_ports); void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) { @@ -921,8 +909,8 @@ static void quirk_usb_handoff_xhci(struct pci_dev *pdev) writel(val, base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET); hc_init: - if (usb_is_intel_switchable_xhci(pdev)) - usb_enable_xhci_ports(pdev); + if (pdev->vendor == PCI_VENDOR_ID_INTEL) + usb_enable_intel_xhci_ports(pdev); op_reg_base = base + XHCI_HC_LENGTH(readl(base)); diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h index 4b8a2092432f..0a5e0fb8f466 100644 --- a/drivers/usb/host/pci-quirks.h +++ b/drivers/usb/host/pci-quirks.h @@ -8,8 +8,7 @@ int usb_amd_find_chipset_info(void); void usb_amd_dev_put(void); void usb_amd_quirk_pll_disable(void); void usb_amd_quirk_pll_enable(void); -bool usb_is_intel_switchable_xhci(struct pci_dev *pdev); -void usb_enable_xhci_ports(struct pci_dev *xhci_pdev); +void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev); void usb_disable_xhci_ports(struct pci_dev *xhci_pdev); void sb800_prefetch(struct device *dev, int on); #else diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index cc24e39b97d5..475e06e10a77 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -250,13 +250,15 @@ static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated) * writers. * * Unconditionally switch the ports back to xHCI after a system resume. - * We can't tell whether the EHCI or xHCI controller will be resumed - * first, so we have to do the port switchover in both drivers. Writing - * a '1' to the port switchover registers should have no effect if the - * port was already switched over. + * It should not matter whether the EHCI or xHCI controller is + * resumed first. It's enough to do the switchover in xHCI because + * USB core won't notice anything as the hub driver doesn't start + * running again until after all the devices (including both EHCI and + * xHCI host controllers) have been resumed. */ - if (usb_is_intel_switchable_xhci(pdev)) - usb_enable_xhci_ports(pdev); + + if (pdev->vendor == PCI_VENDOR_ID_INTEL) + usb_enable_intel_xhci_ports(pdev); retval = xhci_resume(xhci, hibernated); return retval; From 03e64e967180181510de06eecae3be44e648b692 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 16 Jul 2013 19:25:59 -0700 Subject: [PATCH 0406/3400] xhci: Correct misplaced newlines Logging messages end in newlines, not have them put in the middle of messages. Signed-off-by: Joe Perches Signed-off-by: Sarah Sharp --- drivers/usb/host/xhci.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 2c49f00260ca..87b5e6581359 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -3075,8 +3075,8 @@ static u32 xhci_calculate_no_streams_bitmask(struct xhci_hcd *xhci, /* Are streams already being freed for the endpoint? */ if (ep_state & EP_GETTING_NO_STREAMS) { xhci_warn(xhci, "WARN Can't disable streams for " - "endpoint 0x%x\n, " - "streams are being disabled already.", + "endpoint 0x%x, " + "streams are being disabled already\n", eps[i]->desc.bEndpointAddress); return 0; } @@ -3084,8 +3084,8 @@ static u32 xhci_calculate_no_streams_bitmask(struct xhci_hcd *xhci, if (!(ep_state & EP_HAS_STREAMS) && !(ep_state & EP_GETTING_STREAMS)) { xhci_warn(xhci, "WARN Can't disable streams for " - "endpoint 0x%x\n, " - "streams are already disabled!", + "endpoint 0x%x, " + "streams are already disabled!\n", eps[i]->desc.bEndpointAddress); xhci_warn(xhci, "WARN xhci_free_streams() called " "with non-streams endpoint\n"); @@ -4353,7 +4353,7 @@ static u16 xhci_get_timeout_no_hub_lpm(struct usb_device *udev, state_name, sel); else dev_dbg(&udev->dev, "Device-initiated %s disabled " - "due to long PEL %llu\n ms", + "due to long PEL %llu ms\n", state_name, pel); return USB3_LPM_DISABLED; } From 4599934de2cd1c028efcfb8dd643f47bc999d4ff Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Wed, 24 Jul 2013 01:05:07 +0900 Subject: [PATCH 0407/3400] staging: imx-drm: Fix typo in staging/imx-drm Correct spelling typo in staging/imx-drm Singed-off-by: Masanari Iida Acked-by: Sascha Hauer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/imx-drm/Kconfig | 2 +- drivers/staging/imx-drm/imx-ldb.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/imx-drm/Kconfig b/drivers/staging/imx-drm/Kconfig index 22339059837f..6156e3f2a3e7 100644 --- a/drivers/staging/imx-drm/Kconfig +++ b/drivers/staging/imx-drm/Kconfig @@ -15,7 +15,7 @@ config DRM_IMX_FB_HELPER help The DRM framework can provide a legacy /dev/fb0 framebuffer for your device. This is necessary to get a framebuffer console - and also for appplications using the legacy framebuffer API + and also for applications using the legacy framebuffer API config DRM_IMX_PARALLEL_DISPLAY tristate "Support for parallel displays" diff --git a/drivers/staging/imx-drm/imx-ldb.c b/drivers/staging/imx-drm/imx-ldb.c index 8af7f3b40bae..bb7da0e4dc03 100644 --- a/drivers/staging/imx-drm/imx-ldb.c +++ b/drivers/staging/imx-drm/imx-ldb.c @@ -497,7 +497,7 @@ static int imx_ldb_probe(struct platform_device *pdev) imx_ldb->ldb_ctrl |= LDB_SPLIT_MODE_EN; /* - * There are three diferent possible clock mux configurations: + * There are three different possible clock mux configurations: * i.MX53: ipu1_di0_sel, ipu1_di1_sel * i.MX6q: ipu1_di0_sel, ipu1_di1_sel, ipu2_di0_sel, ipu2_di1_sel * i.MX6dl: ipu1_di0_sel, ipu1_di1_sel, lcdif_sel From 87fa05e8ab38149c1e69324c96ade9d47f6d27b9 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 10 Jul 2013 17:27:21 +0300 Subject: [PATCH 0408/3400] staging: rtl8712: return MAC in standard form MAC respresentation should follow standard form. Signed-off-by: Andy Shevchenko Acked-by: Larry Finger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_ioctl_linux.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c index f034567122d9..d58aa7e3b15c 100644 --- a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c +++ b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c @@ -1000,12 +1000,8 @@ static int r871x_wx_set_priv(struct net_device *dev, sprintf(ext, "LINKSPEED %d", mbps); } else if (0 == strcasecmp(ext, "MACADDR")) { /*Return mac address of the station */ - /*Macaddr = xx.xx.xx.xx.xx.xx */ - sprintf(ext, - "MACADDR = %02x.%02x.%02x.%02x.%02x.%02x", - *(dev->dev_addr), *(dev->dev_addr+1), - *(dev->dev_addr+2), *(dev->dev_addr+3), - *(dev->dev_addr+4), *(dev->dev_addr+5)); + /* Macaddr = xx:xx:xx:xx:xx:xx */ + sprintf(ext, "MACADDR = %pM", dev->dev_addr); } else if (0 == strcasecmp(ext, "SCAN-ACTIVE")) { /*Set scan type to active */ /*OK if successful */ From e842b976a88a39b447fc34bd0fcb3c0be0a1d9d9 Mon Sep 17 00:00:00 2001 From: Sunghan Suh Date: Fri, 12 Jul 2013 16:08:13 +0900 Subject: [PATCH 0409/3400] staging: zsmalloc: access page->private by using page_private macro Signed-off-by: Sunghan Suh Signed-off-by: Greg Kroah-Hartman --- drivers/staging/zsmalloc/zsmalloc-main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/zsmalloc/zsmalloc-main.c b/drivers/staging/zsmalloc/zsmalloc-main.c index 4bb275b2d98f..1a67537dbc56 100644 --- a/drivers/staging/zsmalloc/zsmalloc-main.c +++ b/drivers/staging/zsmalloc/zsmalloc-main.c @@ -423,7 +423,7 @@ static struct page *get_next_page(struct page *page) if (is_last_page(page)) next = NULL; else if (is_first_page(page)) - next = (struct page *)page->private; + next = (struct page *)page_private(page); else next = list_entry(page->lru.next, struct page, lru); @@ -581,7 +581,7 @@ static struct page *alloc_zspage(struct size_class *class, gfp_t flags) first_page->inuse = 0; } if (i == 1) - first_page->private = (unsigned long)page; + set_page_private(first_page, (unsigned long)page); if (i >= 1) page->first_page = first_page; if (i >= 2) From 0d012b98662495f1fe5c4aa8acc7e6ed121c1254 Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Sat, 13 Jul 2013 14:53:48 -0700 Subject: [PATCH 0410/3400] staging: dwc2: refactor dwc2_host_complete() The parameters to dwc2_host_complete() didn't make much sense. The 'context' parameter always came from the ->priv member of the 'dwc2_urb' parameter, and both of those always came from a struct dwc2_qtd. So just pass in the struct dwc2_qtd instead. This also allows us to null out the dwc2_qtd->urb member after it is freed, which the calling code forgot to do in several places, causing random driver crashes from dereferencing the freed pointer. This also requires the calls to dwc2_hc_handle_tt_clear() to be moved before the calls to dwc2_host_complete(), otherwise that routine would do nothing because dwc2_qtd->urb has already been freed. Signed-off-by: Paul Zimmerman Tested-by: Stephen Warren Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dwc2/hcd.c | 46 ++++++++++++++----------- drivers/staging/dwc2/hcd.h | 4 +-- drivers/staging/dwc2/hcd_ddma.c | 23 +++++++++---- drivers/staging/dwc2/hcd_intr.c | 59 +++++++++++++++------------------ 4 files changed, 70 insertions(+), 62 deletions(-) diff --git a/drivers/staging/dwc2/hcd.c b/drivers/staging/dwc2/hcd.c index 2ed54b172a3b..e8fb84f53dd9 100644 --- a/drivers/staging/dwc2/hcd.c +++ b/drivers/staging/dwc2/hcd.c @@ -134,11 +134,8 @@ static void dwc2_kill_urbs_in_qh_list(struct dwc2_hsotg *hsotg, list_for_each_entry_safe(qh, qh_tmp, qh_list, qh_list_entry) { list_for_each_entry_safe(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) { - if (qtd->urb != NULL) { - dwc2_host_complete(hsotg, qtd->urb->priv, - qtd->urb, -ETIMEDOUT); - dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh); - } + dwc2_host_complete(hsotg, qtd, -ETIMEDOUT); + dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh); } } } @@ -421,6 +418,8 @@ static int dwc2_hcd_urb_dequeue(struct dwc2_hsotg *hsotg, return -EINVAL; } + urb->priv = NULL; + if (urb_qtd->in_process && qh->channel) { dwc2_dump_channel_info(hsotg, qh->channel); @@ -2088,23 +2087,29 @@ static void dwc2_free_bus_bandwidth(struct usb_hcd *hcd, u16 bw, * * Must be called with interrupt disabled and spinlock held */ -void dwc2_host_complete(struct dwc2_hsotg *hsotg, void *context, - struct dwc2_hcd_urb *dwc2_urb, int status) +void dwc2_host_complete(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd, + int status) { - struct urb *urb = context; + struct urb *urb; int i; + if (!qtd) { + dev_dbg(hsotg->dev, "## %s: qtd is NULL ##\n", __func__); + return; + } + + if (!qtd->urb) { + dev_dbg(hsotg->dev, "## %s: qtd->urb is NULL ##\n", __func__); + return; + } + + urb = qtd->urb->priv; if (!urb) { - dev_dbg(hsotg->dev, "## %s: context is NULL ##\n", __func__); + dev_dbg(hsotg->dev, "## %s: urb->priv is NULL ##\n", __func__); return; } - if (!dwc2_urb) { - dev_dbg(hsotg->dev, "## %s: dwc2_urb is NULL ##\n", __func__); - return; - } - - urb->actual_length = dwc2_hcd_urb_get_actual_length(dwc2_urb); + urb->actual_length = dwc2_hcd_urb_get_actual_length(qtd->urb); if (dbg_urb(urb)) dev_vdbg(hsotg->dev, @@ -2121,18 +2126,17 @@ void dwc2_host_complete(struct dwc2_hsotg *hsotg, void *context, } if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { - urb->error_count = dwc2_hcd_urb_get_error_count(dwc2_urb); + urb->error_count = dwc2_hcd_urb_get_error_count(qtd->urb); for (i = 0; i < urb->number_of_packets; ++i) { urb->iso_frame_desc[i].actual_length = dwc2_hcd_urb_get_iso_desc_actual_length( - dwc2_urb, i); + qtd->urb, i); urb->iso_frame_desc[i].status = - dwc2_hcd_urb_get_iso_desc_status(dwc2_urb, i); + dwc2_hcd_urb_get_iso_desc_status(qtd->urb, i); } } urb->status = status; - urb->hcpriv = NULL; if (!status) { if ((urb->transfer_flags & URB_SHORT_NOT_OK) && urb->actual_length < urb->transfer_buffer_length) @@ -2149,7 +2153,9 @@ void dwc2_host_complete(struct dwc2_hsotg *hsotg, void *context, urb); } - kfree(dwc2_urb); + urb->hcpriv = NULL; + kfree(qtd->urb); + qtd->urb = NULL; spin_unlock(&hsotg->lock); usb_hcd_giveback_urb(dwc2_hsotg_to_hcd(hsotg), urb, status); diff --git a/drivers/staging/dwc2/hcd.h b/drivers/staging/dwc2/hcd.h index cf6c055aec8d..933e8d1999bf 100644 --- a/drivers/staging/dwc2/hcd.h +++ b/drivers/staging/dwc2/hcd.h @@ -716,8 +716,8 @@ extern void dwc2_host_disconnect(struct dwc2_hsotg *hsotg); extern void dwc2_host_hub_info(struct dwc2_hsotg *hsotg, void *context, int *hub_addr, int *hub_port); extern int dwc2_host_get_speed(struct dwc2_hsotg *hsotg, void *context); -extern void dwc2_host_complete(struct dwc2_hsotg *hsotg, void *context, - struct dwc2_hcd_urb *dwc2_urb, int status); +extern void dwc2_host_complete(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd, + int status); #ifdef DEBUG /* diff --git a/drivers/staging/dwc2/hcd_ddma.c b/drivers/staging/dwc2/hcd_ddma.c index 5c0fd273a7bf..de5af1b9b5d9 100644 --- a/drivers/staging/dwc2/hcd_ddma.c +++ b/drivers/staging/dwc2/hcd_ddma.c @@ -800,6 +800,9 @@ static int dwc2_cmpl_host_isoc_dma_desc(struct dwc2_hsotg *hsotg, u16 remain = 0; int rc = 0; + if (!qtd->urb) + return -EINVAL; + frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index_last]; dma_desc->buf = (u32)(qtd->urb->dma + frame_desc->offset); if (chan->ep_is_in) @@ -826,7 +829,7 @@ static int dwc2_cmpl_host_isoc_dma_desc(struct dwc2_hsotg *hsotg, * urb->status is not used for isoc transfers here. The * individual frame_desc status are used instead. */ - dwc2_host_complete(hsotg, qtd->urb->priv, qtd->urb, 0); + dwc2_host_complete(hsotg, qtd, 0); dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh); /* @@ -884,13 +887,16 @@ static void dwc2_complete_isoc_xfer_ddma(struct dwc2_hsotg *hsotg, list_for_each_entry_safe(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) { - for (idx = 0; idx < qtd->urb->packet_count; idx++) { - frame_desc = &qtd->urb->iso_descs[idx]; - frame_desc->status = err; + if (qtd->urb) { + for (idx = 0; idx < qtd->urb->packet_count; + idx++) { + frame_desc = &qtd->urb->iso_descs[idx]; + frame_desc->status = err; + } + + dwc2_host_complete(hsotg, qtd, err); } - dwc2_host_complete(hsotg, qtd->urb->priv, qtd->urb, - err); dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh); } @@ -1015,6 +1021,9 @@ static int dwc2_process_non_isoc_desc(struct dwc2_hsotg *hsotg, dev_vdbg(hsotg->dev, "%s()\n", __func__); + if (!urb) + return -EINVAL; + dma_desc = &qh->desc_list[desc_num]; n_bytes = qh->n_bytes[desc_num]; dev_vdbg(hsotg->dev, @@ -1024,7 +1033,7 @@ static int dwc2_process_non_isoc_desc(struct dwc2_hsotg *hsotg, halt_status, n_bytes, xfer_done); if (failed || (*xfer_done && urb->status != -EINPROGRESS)) { - dwc2_host_complete(hsotg, urb->priv, urb, urb->status); + dwc2_host_complete(hsotg, qtd, urb->status); dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh); dev_vdbg(hsotg->dev, "failed=%1x xfer_done=%1x status=%08x\n", failed, *xfer_done, urb->status); diff --git a/drivers/staging/dwc2/hcd_intr.c b/drivers/staging/dwc2/hcd_intr.c index e75dccb3b80b..22836f5f7ff6 100644 --- a/drivers/staging/dwc2/hcd_intr.c +++ b/drivers/staging/dwc2/hcd_intr.c @@ -623,7 +623,7 @@ static enum dwc2_halt_status dwc2_update_isoc_urb_state( * urb->status is not used for isoc transfers. The individual * frame_desc statuses are used instead. */ - dwc2_host_complete(hsotg, urb->priv, urb, 0); + dwc2_host_complete(hsotg, qtd, 0); halt_status = DWC2_HC_XFER_URB_COMPLETE; } else { halt_status = DWC2_HC_XFER_COMPLETE; @@ -714,11 +714,7 @@ static void dwc2_release_channel(struct dwc2_hsotg *hsotg, dev_vdbg(hsotg->dev, " Complete URB with transaction error\n"); free_qtd = 1; - if (qtd->urb) { - qtd->urb->status = -EPROTO; - dwc2_host_complete(hsotg, qtd->urb->priv, - qtd->urb, -EPROTO); - } + dwc2_host_complete(hsotg, qtd, -EPROTO); } break; case DWC2_HC_XFER_URB_DEQUEUE: @@ -731,11 +727,7 @@ static void dwc2_release_channel(struct dwc2_hsotg *hsotg, case DWC2_HC_XFER_PERIODIC_INCOMPLETE: dev_vdbg(hsotg->dev, " Complete URB with I/O error\n"); free_qtd = 1; - if (qtd && qtd->urb) { - qtd->urb->status = -EIO; - dwc2_host_complete(hsotg, qtd->urb->priv, qtd->urb, - -EIO); - } + dwc2_host_complete(hsotg, qtd, -EIO); break; case DWC2_HC_XFER_NO_HALT_STATUS: default: @@ -957,7 +949,7 @@ static int dwc2_xfercomp_isoc_split_in(struct dwc2_hsotg *hsotg, } if (qtd->isoc_frame_index == qtd->urb->packet_count) { - dwc2_host_complete(hsotg, qtd->urb->priv, qtd->urb, 0); + dwc2_host_complete(hsotg, qtd, 0); dwc2_release_channel(hsotg, chan, qtd, DWC2_HC_XFER_URB_COMPLETE); } else { @@ -1040,7 +1032,7 @@ static void dwc2_hc_xfercomp_intr(struct dwc2_hsotg *hsotg, dev_vdbg(hsotg->dev, " Control transfer complete\n"); if (urb->status == -EINPROGRESS) urb->status = 0; - dwc2_host_complete(hsotg, urb->priv, urb, urb->status); + dwc2_host_complete(hsotg, qtd, urb->status); halt_status = DWC2_HC_XFER_URB_COMPLETE; break; } @@ -1053,7 +1045,7 @@ static void dwc2_hc_xfercomp_intr(struct dwc2_hsotg *hsotg, urb_xfer_done = dwc2_update_urb_state(hsotg, chan, chnum, urb, qtd); if (urb_xfer_done) { - dwc2_host_complete(hsotg, urb->priv, urb, urb->status); + dwc2_host_complete(hsotg, qtd, urb->status); halt_status = DWC2_HC_XFER_URB_COMPLETE; } else { halt_status = DWC2_HC_XFER_COMPLETE; @@ -1073,11 +1065,10 @@ static void dwc2_hc_xfercomp_intr(struct dwc2_hsotg *hsotg, * interrupt */ if (urb_xfer_done) { - dwc2_host_complete(hsotg, urb->priv, urb, - urb->status); - halt_status = DWC2_HC_XFER_URB_COMPLETE; + dwc2_host_complete(hsotg, qtd, urb->status); + halt_status = DWC2_HC_XFER_URB_COMPLETE; } else { - halt_status = DWC2_HC_XFER_COMPLETE; + halt_status = DWC2_HC_XFER_COMPLETE; } dwc2_hcd_save_data_toggle(hsotg, chan, chnum, qtd); @@ -1123,11 +1114,11 @@ static void dwc2_hc_stall_intr(struct dwc2_hsotg *hsotg, goto handle_stall_halt; if (pipe_type == USB_ENDPOINT_XFER_CONTROL) - dwc2_host_complete(hsotg, urb->priv, urb, -EPIPE); + dwc2_host_complete(hsotg, qtd, -EPIPE); if (pipe_type == USB_ENDPOINT_XFER_BULK || pipe_type == USB_ENDPOINT_XFER_INT) { - dwc2_host_complete(hsotg, urb->priv, urb, -EPIPE); + dwc2_host_complete(hsotg, qtd, -EPIPE); /* * USB protocol requires resetting the data toggle for bulk * and interrupt endpoints when a CLEAR_FEATURE(ENDPOINT_HALT) @@ -1372,10 +1363,10 @@ static void dwc2_hc_nyet_intr(struct dwc2_hsotg *hsotg, hsotg->core_params->dma_enable > 0) { qtd->complete_split = 0; qtd->isoc_split_offset = 0; + qtd->isoc_frame_index++; if (qtd->urb && - ++qtd->isoc_frame_index == qtd->urb->packet_count) { - dwc2_host_complete(hsotg, qtd->urb->priv, - qtd->urb, 0); + qtd->isoc_frame_index == qtd->urb->packet_count) { + dwc2_host_complete(hsotg, qtd, 0); dwc2_release_channel(hsotg, chan, qtd, DWC2_HC_XFER_URB_COMPLETE); } else { @@ -1445,16 +1436,16 @@ static void dwc2_hc_babble_intr(struct dwc2_hsotg *hsotg, dev_dbg(hsotg->dev, "--Host Channel %d Interrupt: Babble Error--\n", chnum); + dwc2_hc_handle_tt_clear(hsotg, chan, qtd); + if (hsotg->core_params->dma_desc_enable > 0) { dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum, DWC2_HC_XFER_BABBLE_ERR); - goto handle_babble_done; + goto disable_int; } if (chan->ep_type != USB_ENDPOINT_XFER_ISOC) { - if (qtd->urb) - dwc2_host_complete(hsotg, qtd->urb->priv, qtd->urb, - -EOVERFLOW); + dwc2_host_complete(hsotg, qtd, -EOVERFLOW); dwc2_halt_channel(hsotg, chan, qtd, DWC2_HC_XFER_BABBLE_ERR); } else { enum dwc2_halt_status halt_status; @@ -1464,8 +1455,7 @@ static void dwc2_hc_babble_intr(struct dwc2_hsotg *hsotg, dwc2_halt_channel(hsotg, chan, qtd, halt_status); } -handle_babble_done: - dwc2_hc_handle_tt_clear(hsotg, chan, qtd); +disable_int: disable_hc_int(hsotg, chnum, HCINTMSK_BBLERR); } @@ -1490,6 +1480,8 @@ static void dwc2_hc_ahberr_intr(struct dwc2_hsotg *hsotg, if (!urb) goto handle_ahberr_halt; + dwc2_hc_handle_tt_clear(hsotg, chan, qtd); + hcchar = readl(hsotg->regs + HCCHAR(chnum)); hcsplt = readl(hsotg->regs + HCSPLT(chnum)); hctsiz = readl(hsotg->regs + HCTSIZ(chnum)); @@ -1557,7 +1549,7 @@ static void dwc2_hc_ahberr_intr(struct dwc2_hsotg *hsotg, goto handle_ahberr_done; } - dwc2_host_complete(hsotg, urb->priv, urb, -EIO); + dwc2_host_complete(hsotg, qtd, -EIO); handle_ahberr_halt: /* @@ -1567,7 +1559,6 @@ handle_ahberr_halt: dwc2_hc_halt(hsotg, chan, DWC2_HC_XFER_AHB_ERR); handle_ahberr_done: - dwc2_hc_handle_tt_clear(hsotg, chan, qtd); disable_hc_int(hsotg, chnum, HCINTMSK_AHBERR); } @@ -1582,6 +1573,8 @@ static void dwc2_hc_xacterr_intr(struct dwc2_hsotg *hsotg, dev_dbg(hsotg->dev, "--Host Channel %d Interrupt: Transaction Error--\n", chnum); + dwc2_hc_handle_tt_clear(hsotg, chan, qtd); + if (hsotg->core_params->dma_desc_enable > 0) { dwc2_hcd_complete_xfer_ddma(hsotg, chan, chnum, DWC2_HC_XFER_XACT_ERR); @@ -1625,7 +1618,6 @@ static void dwc2_hc_xacterr_intr(struct dwc2_hsotg *hsotg, } handle_xacterr_done: - dwc2_hc_handle_tt_clear(hsotg, chan, qtd); disable_hc_int(hsotg, chnum, HCINTMSK_XACTERR); } @@ -1643,6 +1635,8 @@ static void dwc2_hc_frmovrun_intr(struct dwc2_hsotg *hsotg, dev_dbg(hsotg->dev, "--Host Channel %d Interrupt: Frame Overrun--\n", chnum); + dwc2_hc_handle_tt_clear(hsotg, chan, qtd); + switch (dwc2_hcd_get_pipe_type(&qtd->urb->pipe_info)) { case USB_ENDPOINT_XFER_CONTROL: case USB_ENDPOINT_XFER_BULK: @@ -1657,7 +1651,6 @@ static void dwc2_hc_frmovrun_intr(struct dwc2_hsotg *hsotg, break; } - dwc2_hc_handle_tt_clear(hsotg, chan, qtd); disable_hc_int(hsotg, chnum, HCINTMSK_FRMOVRUN); } From c9e1c907ff520bdc01170a8d6461d262094ed6f8 Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Sat, 13 Jul 2013 14:53:49 -0700 Subject: [PATCH 0411/3400] staging: dwc2: add calls to usb_hcd_link_urb_to_ep() and friends The driver was lacking calls to usb_hcd_link_urb_to_ep(), usb_hcd_unlink_urb_from_ep(), and usb_hcd_check_unlink_urb(). Add those now. Signed-off-by: Paul Zimmerman Tested-by: Stephen Warren Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dwc2/hcd.c | 52 +++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 15 deletions(-) diff --git a/drivers/staging/dwc2/hcd.c b/drivers/staging/dwc2/hcd.c index e8fb84f53dd9..d72daf179148 100644 --- a/drivers/staging/dwc2/hcd.c +++ b/drivers/staging/dwc2/hcd.c @@ -2153,6 +2153,7 @@ void dwc2_host_complete(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd, urb); } + usb_hcd_unlink_urb_from_ep(dwc2_hsotg_to_hcd(hsotg), urb); urb->hcpriv = NULL; kfree(qtd->urb); qtd->urb = NULL; @@ -2343,8 +2344,8 @@ static int _dwc2_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, struct usb_host_endpoint *ep = urb->ep; struct dwc2_hcd_urb *dwc2_urb; int i; + int retval; int alloc_bandwidth = 0; - int retval = 0; u8 ep_type = 0; u32 tflags = 0; void *buf; @@ -2426,21 +2427,36 @@ static int _dwc2_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, urb->iso_frame_desc[i].length); urb->hcpriv = dwc2_urb; - retval = dwc2_hcd_urb_enqueue(hsotg, dwc2_urb, &ep->hcpriv, - mem_flags); - if (retval) { - urb->hcpriv = NULL; - kfree(dwc2_urb); - } else { - if (alloc_bandwidth) { - spin_lock_irqsave(&hsotg->lock, flags); - dwc2_allocate_bus_bandwidth(hcd, - dwc2_hcd_get_ep_bandwidth(hsotg, ep), - urb); - spin_unlock_irqrestore(&hsotg->lock, flags); - } + + spin_lock_irqsave(&hsotg->lock, flags); + retval = usb_hcd_link_urb_to_ep(hcd, urb); + spin_unlock_irqrestore(&hsotg->lock, flags); + if (retval) + goto fail1; + + retval = dwc2_hcd_urb_enqueue(hsotg, dwc2_urb, &ep->hcpriv, mem_flags); + if (retval) + goto fail2; + + if (alloc_bandwidth) { + spin_lock_irqsave(&hsotg->lock, flags); + dwc2_allocate_bus_bandwidth(hcd, + dwc2_hcd_get_ep_bandwidth(hsotg, ep), + urb); + spin_unlock_irqrestore(&hsotg->lock, flags); } + return 0; + +fail2: + spin_lock_irqsave(&hsotg->lock, flags); + dwc2_urb->priv = NULL; + usb_hcd_unlink_urb_from_ep(hcd, urb); + spin_unlock_irqrestore(&hsotg->lock, flags); +fail1: + urb->hcpriv = NULL; + kfree(dwc2_urb); + return retval; } @@ -2451,7 +2467,7 @@ static int _dwc2_hcd_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) { struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); - int rc = 0; + int rc; unsigned long flags; dev_dbg(hsotg->dev, "DWC OTG HCD URB Dequeue\n"); @@ -2459,6 +2475,10 @@ static int _dwc2_hcd_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, spin_lock_irqsave(&hsotg->lock, flags); + rc = usb_hcd_check_unlink_urb(hcd, urb, status); + if (rc) + goto out; + if (!urb->hcpriv) { dev_dbg(hsotg->dev, "## urb->hcpriv is NULL ##\n"); goto out; @@ -2466,6 +2486,8 @@ static int _dwc2_hcd_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, rc = dwc2_hcd_urb_dequeue(hsotg, urb->hcpriv); + usb_hcd_unlink_urb_from_ep(hcd, urb); + kfree(urb->hcpriv); urb->hcpriv = NULL; From 399fdf9e57457444bbb5ab33eefa1f8723e9ea05 Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Sat, 13 Jul 2013 14:53:50 -0700 Subject: [PATCH 0412/3400] staging: dwc2: optimize dwc2_hc_handle_tt_clear() a bit Make dwc2_hc_handle_tt_clear() return early if the device is hi-speed. Signed-off-by: Paul Zimmerman Tested-by: Stephen Warren Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dwc2/hcd_intr.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/staging/dwc2/hcd_intr.c b/drivers/staging/dwc2/hcd_intr.c index 22836f5f7ff6..093a75c3d0db 100644 --- a/drivers/staging/dwc2/hcd_intr.c +++ b/drivers/staging/dwc2/hcd_intr.c @@ -89,15 +89,20 @@ static void dwc2_hc_handle_tt_clear(struct dwc2_hsotg *hsotg, { struct urb *usb_urb; - if (!chan->qh || !qtd->urb) + if (!chan->qh) + return; + + if (chan->qh->dev_speed == USB_SPEED_HIGH) + return; + + if (!qtd->urb) return; usb_urb = qtd->urb->priv; - if (!usb_urb || !usb_urb->dev) + if (!usb_urb || !usb_urb->dev || !usb_urb->dev->tt) return; - if (chan->qh->dev_speed != USB_SPEED_HIGH && - qtd->urb->status != -EPIPE && qtd->urb->status != -EREMOTEIO) { + if (qtd->urb->status != -EPIPE && qtd->urb->status != -EREMOTEIO) { chan->qh->tt_buffer_dirty = 1; if (usb_hub_clear_tt_buffer(usb_urb)) /* Clear failed; let's hope things work anyway */ From b2d6cb55183b93d65dfc4a71c2706c4e13fa19c5 Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Sat, 13 Jul 2013 14:53:51 -0700 Subject: [PATCH 0413/3400] staging: dwc2: fix dwc2_hcd_qtd_add() The logic in dwc2_hcd_qtd_add() was a bit messy, and one of the error exit paths was broken. Fix it up. Signed-off-by: Paul Zimmerman Tested-by: Stephen Warren Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dwc2/hcd_queue.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/drivers/staging/dwc2/hcd_queue.c b/drivers/staging/dwc2/hcd_queue.c index b36f783dd3e9..5461e3b86ae9 100644 --- a/drivers/staging/dwc2/hcd_queue.c +++ b/drivers/staging/dwc2/hcd_queue.c @@ -197,6 +197,9 @@ static struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg, { struct dwc2_qh *qh; + if (!urb->priv) + return NULL; + /* Allocate memory */ qh = kzalloc(sizeof(*qh), mem_flags); if (!qh) @@ -638,7 +641,7 @@ int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd, struct dwc2_hcd_urb *urb = qtd->urb; unsigned long flags; int allocated = 0; - int retval = 0; + int retval; /* * Get the QH which holds the QTD-list to insert to. Create QH if it @@ -652,8 +655,19 @@ int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd, } spin_lock_irqsave(&hsotg->lock, flags); + retval = dwc2_hcd_qh_add(hsotg, *qh); - if (retval && allocated) { + if (retval) + goto fail; + + qtd->qh = *qh; + list_add_tail(&qtd->qtd_list_entry, &(*qh)->qtd_list); + spin_unlock_irqrestore(&hsotg->lock, flags); + + return 0; + +fail: + if (allocated) { struct dwc2_qtd *qtd2, *qtd2_tmp; struct dwc2_qh *qh_tmp = *qh; @@ -668,8 +682,6 @@ int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd, spin_unlock_irqrestore(&hsotg->lock, flags); dwc2_hcd_qh_free(hsotg, qh_tmp); } else { - qtd->qh = *qh; - list_add_tail(&qtd->qtd_list_entry, &(*qh)->qtd_list); spin_unlock_irqrestore(&hsotg->lock, flags); } From 0cf31f8629bf50efe0651ef878a8ddd29a722cac Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Sat, 13 Jul 2013 14:53:52 -0700 Subject: [PATCH 0414/3400] staging: dwc2: reduce noisy debug messages Change the non-aligned buffer debug messages to dev_vdbg(). Also remove some duplicated debug output when the driver is loaded. Signed-off-by: Paul Zimmerman Tested-by: Stephen Warren Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dwc2/hcd.c | 2 -- drivers/staging/dwc2/hcd_intr.c | 14 +++++++------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/drivers/staging/dwc2/hcd.c b/drivers/staging/dwc2/hcd.c index d72daf179148..26392090e2f8 100644 --- a/drivers/staging/dwc2/hcd.c +++ b/drivers/staging/dwc2/hcd.c @@ -2950,8 +2950,6 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq, if (retval < 0) goto error3; - dwc2_dump_global_registers(hsotg); - dwc2_dump_host_registers(hsotg); dwc2_hcd_dump_state(hsotg); dwc2_enable_global_interrupts(hsotg); diff --git a/drivers/staging/dwc2/hcd_intr.c b/drivers/staging/dwc2/hcd_intr.c index 093a75c3d0db..9e68ef1d5998 100644 --- a/drivers/staging/dwc2/hcd_intr.c +++ b/drivers/staging/dwc2/hcd_intr.c @@ -467,7 +467,7 @@ static int dwc2_update_urb_state(struct dwc2_hsotg *hsotg, /* Non DWORD-aligned buffer case handling */ if (chan->align_buf && xfer_length && chan->ep_is_in) { - dev_dbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__); + dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__); dma_sync_single_for_cpu(hsotg->dev, urb->dma, urb->length, DMA_FROM_DEVICE); memcpy(urb->buf + urb->actual_length, chan->qh->dw_align_buf, @@ -562,8 +562,8 @@ static enum dwc2_halt_status dwc2_update_isoc_urb_state( /* Non DWORD-aligned buffer case handling */ if (chan->align_buf && frame_desc->actual_length && chan->ep_is_in) { - dev_dbg(hsotg->dev, "%s(): non-aligned buffer\n", - __func__); + dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", + __func__); dma_sync_single_for_cpu(hsotg->dev, urb->dma, urb->length, DMA_FROM_DEVICE); memcpy(urb->buf + frame_desc->offset + @@ -596,8 +596,8 @@ static enum dwc2_halt_status dwc2_update_isoc_urb_state( /* Non DWORD-aligned buffer case handling */ if (chan->align_buf && frame_desc->actual_length && chan->ep_is_in) { - dev_dbg(hsotg->dev, "%s(): non-aligned buffer\n", - __func__); + dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", + __func__); dma_sync_single_for_cpu(hsotg->dev, urb->dma, urb->length, DMA_FROM_DEVICE); memcpy(urb->buf + frame_desc->offset + @@ -935,7 +935,7 @@ static int dwc2_xfercomp_isoc_split_in(struct dwc2_hsotg *hsotg, frame_desc->actual_length += len; if (chan->align_buf && len) { - dev_dbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__); + dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__); dma_sync_single_for_cpu(hsotg->dev, qtd->urb->dma, qtd->urb->length, DMA_FROM_DEVICE); memcpy(qtd->urb->buf + frame_desc->offset + @@ -1164,7 +1164,7 @@ static void dwc2_update_urb_state_abn(struct dwc2_hsotg *hsotg, /* Non DWORD-aligned buffer case handling */ if (chan->align_buf && xfer_length && chan->ep_is_in) { - dev_dbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__); + dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__); dma_sync_single_for_cpu(hsotg->dev, urb->dma, urb->length, DMA_FROM_DEVICE); memcpy(urb->buf + urb->actual_length, chan->qh->dw_align_buf, From 25a494457c2bfc9e1d92be9067e235524fad96ee Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Sat, 13 Jul 2013 14:53:53 -0700 Subject: [PATCH 0415/3400] staging: dwc2: remove use of bus_to_virt() Remove the use of bus_to_virt() and just fail the transfer if an unaligned buffer with no virtual address is found. AFAIK that can't happen anyway. Also change setting of coherent DMA mask to the normal 32 bits. 31 bits was only needed when calling bus_to_virt() AFAICR. Signed-off-by: Paul Zimmerman Tested-by: Stephen Warren Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dwc2/Kconfig | 1 - drivers/staging/dwc2/hcd.c | 20 ++++++++++---------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/staging/dwc2/Kconfig b/drivers/staging/dwc2/Kconfig index d15d9d58e5ac..be947d673844 100644 --- a/drivers/staging/dwc2/Kconfig +++ b/drivers/staging/dwc2/Kconfig @@ -1,7 +1,6 @@ config USB_DWC2 tristate "DesignWare USB2 DRD Core Support" depends on USB - depends on VIRT_TO_BUS help Say Y or M here if your system has a Dual Role HighSpeed USB controller based on the DesignWare HSOTG IP Core. diff --git a/drivers/staging/dwc2/hcd.c b/drivers/staging/dwc2/hcd.c index 26392090e2f8..962468f06716 100644 --- a/drivers/staging/dwc2/hcd.c +++ b/drivers/staging/dwc2/hcd.c @@ -2396,14 +2396,15 @@ static int _dwc2_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, !(usb_pipein(urb->pipe)))); buf = urb->transfer_buffer; + if (hcd->self.uses_dma) { - /* - * Calculate virtual address from physical address, because - * some class driver may not fill transfer_buffer. - * In Buffer DMA mode virtual address is used, when handling - * non-DWORD aligned buffers. - */ - buf = bus_to_virt(urb->transfer_dma); + if (!buf && (urb->transfer_dma & 3)) { + dev_err(hsotg->dev, + "%s: unaligned transfer with no transfer_buffer", + __func__); + retval = -EINVAL; + goto fail1; + } } if (!(urb->transfer_flags & URB_NO_INTERRUPT)) @@ -2833,9 +2834,8 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq, if (hsotg->core_params->dma_enable > 0) { if (dma_set_mask(hsotg->dev, DMA_BIT_MASK(32)) < 0) dev_warn(hsotg->dev, "can't set DMA mask\n"); - if (dma_set_coherent_mask(hsotg->dev, DMA_BIT_MASK(31)) < 0) - dev_warn(hsotg->dev, - "can't enable workaround for >2GB RAM\n"); + if (dma_set_coherent_mask(hsotg->dev, DMA_BIT_MASK(32)) < 0) + dev_warn(hsotg->dev, "can't set coherent DMA mask\n"); } else { dma_set_mask(hsotg->dev, 0); dma_set_coherent_mask(hsotg->dev, 0); From b39ed5c7b480f720d549987c9b3acd0833eafc8e Mon Sep 17 00:00:00 2001 From: Julien Delacou Date: Thu, 11 Jul 2013 14:24:10 +0200 Subject: [PATCH 0416/3400] staging: dwc2: fix value used in dwc2_set_all_params This fix uses 'value' parameter as it should be instead of hardcoded -1. Signed-off-by: Julien Delacou Acked-by: Paul Zimmerman Reviewed-by: Matthijs Kooijman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dwc2/hcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/dwc2/hcd.c b/drivers/staging/dwc2/hcd.c index 962468f06716..d4ef5f34c2a0 100644 --- a/drivers/staging/dwc2/hcd.c +++ b/drivers/staging/dwc2/hcd.c @@ -2719,7 +2719,7 @@ void dwc2_set_all_params(struct dwc2_core_params *params, int value) int i; for (i = 0; i < size; i++) - p[i] = -1; + p[i] = value; } EXPORT_SYMBOL_GPL(dwc2_set_all_params); From 4d3190e1f84f08692f4b87461108f72e9a0b452c Mon Sep 17 00:00:00 2001 From: Paul Zimmerman Date: Tue, 16 Jul 2013 12:22:12 -0700 Subject: [PATCH 0417/3400] staging: dwc2: add driver parameter to set AHB config register value The dwc2 driver sets the value of the DWC2 GAHBCFG register to 0x6, which is GAHBCFG_HBSTLEN_INCR4. But different platforms may require different values. In particular, the Broadcom 2835 SOC used in the Raspberry Pi needs a value of 0x10, otherwise the DWC2 controller stops working after a short period of heavy USB traffic. So this patch adds another driver parameter named 'ahbcfg'. The default value is 0x6. Any platform needing a different value should add a DT attribute to set it. This patch also removes the 'ahb_single' driver parameter, since that bit can now be set using 'ahbcfg'. This patch does not add DT support to platform.c, I will leave that to whoever owns the first platform that needs a non-default value. (Stephen?) Signed-off-by: Paul Zimmerman Tested-by: Stephen Warren Reviewed-by: Matthijs Kooijman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dwc2/core.c | 51 ++++++++++--------------------------- drivers/staging/dwc2/core.h | 13 +++++----- drivers/staging/dwc2/hw.h | 4 +++ drivers/staging/dwc2/pci.c | 2 +- 4 files changed, 25 insertions(+), 45 deletions(-) diff --git a/drivers/staging/dwc2/core.c b/drivers/staging/dwc2/core.c index e3a0e770301d..a090f79bb5f5 100644 --- a/drivers/staging/dwc2/core.c +++ b/drivers/staging/dwc2/core.c @@ -277,7 +277,7 @@ static void dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) static int dwc2_gahbcfg_init(struct dwc2_hsotg *hsotg) { - u32 ahbcfg = 0; + u32 ahbcfg = readl(hsotg->regs + GAHBCFG); switch (hsotg->hwcfg2 & GHWCFG2_ARCHITECTURE_MASK) { case GHWCFG2_EXT_DMA_ARCH: @@ -286,11 +286,11 @@ static int dwc2_gahbcfg_init(struct dwc2_hsotg *hsotg) case GHWCFG2_INT_DMA_ARCH: dev_dbg(hsotg->dev, "Internal DMA Mode\n"); - /* - * Old value was GAHBCFG_HBSTLEN_INCR - done for - * Host mode ISOC in issue fix - vahrama - */ - ahbcfg |= GAHBCFG_HBSTLEN_INCR4; + if (hsotg->core_params->ahbcfg != -1) { + ahbcfg &= GAHBCFG_CTRL_MASK; + ahbcfg |= hsotg->core_params->ahbcfg & + ~GAHBCFG_CTRL_MASK; + } break; case GHWCFG2_SLAVE_ONLY_ARCH: @@ -313,9 +313,6 @@ static int dwc2_gahbcfg_init(struct dwc2_hsotg *hsotg) hsotg->core_params->dma_desc_enable = 0; } - if (hsotg->core_params->ahb_single > 0) - ahbcfg |= GAHBCFG_AHB_SINGLE; - if (hsotg->core_params->dma_enable > 0) ahbcfg |= GAHBCFG_DMA_EN; @@ -2586,35 +2583,13 @@ int dwc2_set_param_reload_ctl(struct dwc2_hsotg *hsotg, int val) return retval; } -int dwc2_set_param_ahb_single(struct dwc2_hsotg *hsotg, int val) +int dwc2_set_param_ahbcfg(struct dwc2_hsotg *hsotg, int val) { - int valid = 1; - int retval = 0; - - if (DWC2_PARAM_TEST(val, 0, 1)) { - if (val >= 0) { - dev_err(hsotg->dev, - "'%d' invalid for parameter ahb_single\n", val); - dev_err(hsotg->dev, "ahb_single must be 0 or 1\n"); - } - valid = 0; - } - - if (val > 0 && hsotg->snpsid < DWC2_CORE_REV_2_94a) - valid = 0; - - if (!valid) { - if (val >= 0) - dev_err(hsotg->dev, - "%d invalid for parameter ahb_single. Check HW configuration.\n", - val); - val = 0; - dev_dbg(hsotg->dev, "Setting ahb_single to %d\n", val); - retval = -EINVAL; - } - - hsotg->core_params->ahb_single = val; - return retval; + if (val != -1) + hsotg->core_params->ahbcfg = val; + else + hsotg->core_params->ahbcfg = GAHBCFG_HBSTLEN_INCR4; + return 0; } int dwc2_set_param_otg_ver(struct dwc2_hsotg *hsotg, int val) @@ -2681,7 +2656,7 @@ int dwc2_set_parameters(struct dwc2_hsotg *hsotg, retval |= dwc2_set_param_en_multiple_tx_fifo(hsotg, params->en_multiple_tx_fifo); retval |= dwc2_set_param_reload_ctl(hsotg, params->reload_ctl); - retval |= dwc2_set_param_ahb_single(hsotg, params->ahb_single); + retval |= dwc2_set_param_ahbcfg(hsotg, params->ahbcfg); retval |= dwc2_set_param_otg_ver(hsotg, params->otg_ver); return retval; diff --git a/drivers/staging/dwc2/core.h b/drivers/staging/dwc2/core.h index fc075a7c1de5..e771e405453f 100644 --- a/drivers/staging/dwc2/core.h +++ b/drivers/staging/dwc2/core.h @@ -150,10 +150,11 @@ enum dwc2_lx_state { * are enabled * @reload_ctl: True to allow dynamic reloading of HFIR register during * runtime - * @ahb_single: This bit enables SINGLE transfers for remainder data in - * a transfer for DMA mode of operation. - * 0 - remainder data will be sent using INCR burst size - * 1 - remainder data will be sent using SINGLE burst size + * @ahbcfg: This field allows the default value of the GAHBCFG + * register to be overridden + * -1 - GAHBCFG value will not be overridden + * all others - GAHBCFG value will be overridden with + * this value * @otg_ver: OTG version supported * 0 - 1.3 * 1 - 2.0 @@ -189,7 +190,7 @@ struct dwc2_core_params { int host_ls_low_power_phy_clk; int ts_dline; int reload_ctl; - int ahb_single; + int ahbcfg; }; /** @@ -643,7 +644,7 @@ extern int dwc2_set_param_en_multiple_tx_fifo(struct dwc2_hsotg *hsotg, extern int dwc2_set_param_reload_ctl(struct dwc2_hsotg *hsotg, int val); -extern int dwc2_set_param_ahb_single(struct dwc2_hsotg *hsotg, int val); +extern int dwc2_set_param_ahbcfg(struct dwc2_hsotg *hsotg, int val); extern int dwc2_set_param_otg_ver(struct dwc2_hsotg *hsotg, int val); diff --git a/drivers/staging/dwc2/hw.h b/drivers/staging/dwc2/hw.h index 382a1d74865d..cf0dc97d5520 100644 --- a/drivers/staging/dwc2/hw.h +++ b/drivers/staging/dwc2/hw.h @@ -78,6 +78,10 @@ #define GAHBCFG_HBSTLEN_INCR8 (5 << 1) #define GAHBCFG_HBSTLEN_INCR16 (7 << 1) #define GAHBCFG_GLBL_INTR_EN (1 << 0) +#define GAHBCFG_CTRL_MASK (GAHBCFG_P_TXF_EMP_LVL | \ + GAHBCFG_NP_TXF_EMP_LVL | \ + GAHBCFG_DMA_EN | \ + GAHBCFG_GLBL_INTR_EN) #define GUSBCFG HSOTG_REG(0x00C) #define GUSBCFG_FORCEDEVMODE (1 << 30) diff --git a/drivers/staging/dwc2/pci.c b/drivers/staging/dwc2/pci.c index 3ca54d6782fd..fdfbc719663c 100644 --- a/drivers/staging/dwc2/pci.c +++ b/drivers/staging/dwc2/pci.c @@ -83,7 +83,7 @@ static const struct dwc2_core_params dwc2_module_params = { .host_ls_low_power_phy_clk = -1, .ts_dline = -1, .reload_ctl = -1, - .ahb_single = -1, + .ahbcfg = -1, }; /** From a0112f487180bd243aec86b5a8c4b5e2d45e8404 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Fri, 19 Jul 2013 11:34:22 +0200 Subject: [PATCH 0418/3400] staging: dwc2: disable dma when no dma_mask was setup If the platform or bus driver failed to setup a dma_mask, but the hardware advertises support for DMA, before DMA would be enabled in dwc2, but disabled in the usb core, making all connectivity break. With this commit, the dwc2 driver will emit a warning and fall back to slave mode in this case. Note that since commit 642f2ec (staging: dwc2: Fix dma-enabled platform devices using a default dma_mask) the platform bindings make sure a DMA mask is always present, but having this check here anyway is probably a good from a defensive programming standpoint (in case of changes to platform.c or addition of new glue layers). Signed-off-by: Matthijs Kooijman Acked-by: Paul Zimmerman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dwc2/hcd.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/staging/dwc2/hcd.c b/drivers/staging/dwc2/hcd.c index d4ef5f34c2a0..f77e66333ac7 100644 --- a/drivers/staging/dwc2/hcd.c +++ b/drivers/staging/dwc2/hcd.c @@ -2830,6 +2830,15 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq, /* Validate parameter values */ dwc2_set_parameters(hsotg, params); + /* Check if the bus driver or platform code has setup a dma_mask */ + if (hsotg->core_params->dma_enable > 0 && + hsotg->dev->dma_mask == NULL) { + dev_warn(hsotg->dev, + "dma_mask not set, disabling DMA\n"); + hsotg->core_params->dma_enable = 0; + hsotg->core_params->dma_desc_enable = 0; + } + /* Set device flags indicating whether the HCD supports DMA */ if (hsotg->core_params->dma_enable > 0) { if (dma_set_mask(hsotg->dev, DMA_BIT_MASK(32)) < 0) From 7de76ee118ce013bb17c924515cb45464d8a059b Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Fri, 19 Jul 2013 11:34:23 +0200 Subject: [PATCH 0419/3400] staging: dwc2: when dma is disabled, clear hcd->self.uses_dma When dma is disabled inside dwc2 (because the hardware does not support it, or the code was changed to disable it for testing), let the usb core know about this by clearing hcd->self.uses_dma. By default, the usb core assumes that dma is used when a dma_mask is set, but this might not always match the dma_enable value in dwc2. To prevent problems resulting from a mismatch, better to explicitely disable dma in this case (though everything seemed to work with the wrong value of uses_dma as well, probably only resulted in some unneeded work). Signed-off-by: Matthijs Kooijman Acked-by: Paul Zimmerman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dwc2/hcd.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/staging/dwc2/hcd.c b/drivers/staging/dwc2/hcd.c index f77e66333ac7..fbacf6a9f72e 100644 --- a/drivers/staging/dwc2/hcd.c +++ b/drivers/staging/dwc2/hcd.c @@ -2854,6 +2854,9 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq, if (!hcd) goto error1; + if (hsotg->core_params->dma_enable <= 0) + hcd->self.uses_dma = 0; + hcd->has_tt = 1; spin_lock_init(&hsotg->lock); From f3ac47cf7910f5b8414c1d8fc247399791a968b8 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 16 Jul 2013 23:13:25 +0300 Subject: [PATCH 0420/3400] staging: xgifb: delete unused "rateindex" parameters Delete unused "rateindex" parameters from internal functions. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/XGI_main_26.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index 801ac4053a7a..015d7bbccf86 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -60,7 +60,7 @@ static inline void dumpVGAReg(void) static int XGIfb_mode_rate_to_dclock(struct vb_device_info *XGI_Pr, struct xgi_hw_device_info *HwDeviceExtension, - unsigned char modeno, unsigned char rateindex) + unsigned char modeno) { unsigned short ModeNo = modeno; unsigned short ModeIdIndex = 0, ClockIndex = 0; @@ -82,7 +82,7 @@ static int XGIfb_mode_rate_to_dclock(struct vb_device_info *XGI_Pr, static int XGIfb_mode_rate_to_ddata(struct vb_device_info *XGI_Pr, struct xgi_hw_device_info *HwDeviceExtension, - unsigned char modeno, unsigned char rateindex, + unsigned char modeno, u32 *left_margin, u32 *right_margin, u32 *upper_margin, u32 *lower_margin, u32 *hsync_len, u32 *vsync_len, u32 *sync, u32 *vmode) @@ -1980,12 +1980,10 @@ static int xgifb_probe(struct pci_dev *pdev, fb_info->var.pixclock = (u32) (1000000000 / XGIfb_mode_rate_to_dclock(&xgifb_info->dev_info, hw_info, - XGIbios_mode[xgifb_info->mode_idx].mode_no, - xgifb_info->rate_idx)); + XGIbios_mode[xgifb_info->mode_idx].mode_no)); if (XGIfb_mode_rate_to_ddata(&xgifb_info->dev_info, hw_info, XGIbios_mode[xgifb_info->mode_idx].mode_no, - xgifb_info->rate_idx, &fb_info->var.left_margin, &fb_info->var.right_margin, &fb_info->var.upper_margin, From 3d05f66f76487536513f461e9f005a11851102ec Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 16 Jul 2013 23:13:26 +0300 Subject: [PATCH 0421/3400] staging: xgifb: delete unused "ModeNo" parameters Delete unused "ModeNo" parameters from internal functions. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/vb_setmode.c | 241 +++++++++++++---------------- 1 file changed, 107 insertions(+), 134 deletions(-) diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index fcefe5b36cdd..84cc48612e15 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -63,8 +63,7 @@ void InitTo330Pointer(unsigned char ChipType, struct vb_device_info *pVBInfo) } -static void XGI_SetSeqRegs(unsigned short ModeNo, - unsigned short ModeIdIndex, +static void XGI_SetSeqRegs(unsigned short ModeIdIndex, struct vb_device_info *pVBInfo) { unsigned char SRdata, i; @@ -96,8 +95,7 @@ static void XGI_SetCRTCRegs(struct xgi_hw_device_info *HwDeviceExtension, } } -static void XGI_SetATTRegs(unsigned short ModeNo, - unsigned short ModeIdIndex, +static void XGI_SetATTRegs(unsigned short ModeIdIndex, struct vb_device_info *pVBInfo) { unsigned char ARdata; @@ -171,8 +169,7 @@ static unsigned char XGI_SetDefaultVCLK(struct vb_device_info *pVBInfo) return 0; } -static unsigned char XGI_AjustCRT2Rate(unsigned short ModeNo, - unsigned short ModeIdIndex, +static unsigned char XGI_AjustCRT2Rate(unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, unsigned short *i, struct vb_device_info *pVBInfo) { @@ -322,7 +319,6 @@ static void XGI_SetCRT1Timing_H(struct vb_device_info *pVBInfo, } static void XGI_SetCRT1Timing_V(unsigned short ModeIdIndex, - unsigned short ModeNo, struct vb_device_info *pVBInfo) { unsigned char data; @@ -365,7 +361,7 @@ static void XGI_SetCRT1Timing_V(unsigned short ModeIdIndex, xgifb_reg_set(pVBInfo->P3d4, 0x09, data); } -static void XGI_SetCRT1CRTC(unsigned short ModeNo, unsigned short ModeIdIndex, +static void XGI_SetCRT1CRTC(unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo, struct xgi_hw_device_info *HwDeviceExtension) @@ -391,7 +387,7 @@ static void XGI_SetCRT1CRTC(unsigned short ModeNo, unsigned short ModeIdIndex, XGI_SetCRT1Timing_H(pVBInfo, HwDeviceExtension); - XGI_SetCRT1Timing_V(ModeIdIndex, ModeNo, pVBInfo); + XGI_SetCRT1Timing_V(ModeIdIndex, pVBInfo); if (pVBInfo->ModeType > 0x03) xgifb_reg_set(pVBInfo->P3d4, 0x14, 0x4F); @@ -403,7 +399,7 @@ static void XGI_SetCRT1CRTC(unsigned short ModeNo, unsigned short ModeIdIndex, /* Output : Fill CRT Hsync/Vsync to SR2E/SR2F/SR30/SR33/SR34/SR3F */ /* Description : Set LCD timing */ /* --------------------------------------------------------------------- */ -static void XGI_SetXG21CRTC(unsigned short ModeNo, unsigned short ModeIdIndex, +static void XGI_SetXG21CRTC(unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo) { @@ -500,8 +496,7 @@ static void XGI_SetXG21CRTC(unsigned short ModeNo, unsigned short ModeIdIndex, xgifb_reg_set(pVBInfo->P3c4, 0x3F, Tempax); } -static void XGI_SetXG27CRTC(unsigned short ModeNo, - unsigned short ModeIdIndex, +static void XGI_SetXG27CRTC(unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo) { @@ -605,8 +600,7 @@ static void XGI_SetXG27FPBits(struct vb_device_info *pVBInfo) static void xgifb_set_lcd(int chip_id, struct vb_device_info *pVBInfo, - unsigned short RefreshRateTableIndex, - unsigned short ModeNo) + unsigned short RefreshRateTableIndex) { unsigned short temp; @@ -688,7 +682,7 @@ static void XGI_UpdateXG21CRTC(unsigned short ModeNo, } static void XGI_SetCRT1DE(struct xgi_hw_device_info *HwDeviceExtension, - unsigned short ModeNo, unsigned short ModeIdIndex, + unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo) { @@ -834,8 +828,7 @@ static void XGI_SetCRT1Offset(unsigned short ModeNo, xgifb_reg_set(pVBInfo->P3c4, 0x10, ah); } -static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo, - unsigned short ModeIdIndex, +static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo) @@ -886,8 +879,7 @@ static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo, return VCLKIndex; } -static void XGI_SetCRT1VCLK(unsigned short ModeNo, - unsigned short ModeIdIndex, +static void XGI_SetCRT1VCLK(unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo) @@ -899,9 +891,8 @@ static void XGI_SetCRT1VCLK(unsigned short ModeNo, (pVBInfo->VBType & (VB_SIS301B | VB_SIS302B | VB_SIS301LV | VB_SIS302LV | VB_XGI301C)) && (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)) { - vclkindex = XGI_GetVCLK2Ptr(ModeNo, ModeIdIndex, - RefreshRateTableIndex, HwDeviceExtension, - pVBInfo); + vclkindex = XGI_GetVCLK2Ptr(ModeIdIndex, RefreshRateTableIndex, + HwDeviceExtension, pVBInfo); data = xgifb_reg_get(pVBInfo->P3c4, 0x31) & 0xCF; xgifb_reg_set(pVBInfo->P3c4, 0x31, data); data = XGI_VBVCLKData[vclkindex].Part4_A; @@ -948,9 +939,8 @@ static void XGI_SetXG21FPBits(struct vb_device_info *pVBInfo) } -static void XGI_SetCRT1FIFO(unsigned short ModeNo, - struct xgi_hw_device_info *HwDeviceExtension, - struct vb_device_info *pVBInfo) +static void XGI_SetCRT1FIFO(struct xgi_hw_device_info *HwDeviceExtension, + struct vb_device_info *pVBInfo) { unsigned short data; @@ -971,7 +961,7 @@ static void XGI_SetCRT1FIFO(unsigned short ModeNo, } static void XGI_SetVCLKState(struct xgi_hw_device_info *HwDeviceExtension, - unsigned short ModeNo, unsigned short RefreshRateTableIndex, + unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo) { unsigned short data, data2 = 0; @@ -1010,7 +1000,7 @@ static void XGI_SetVCLKState(struct xgi_hw_device_info *HwDeviceExtension, } static void XGI_SetCRT1ModeRegs(struct xgi_hw_device_info *HwDeviceExtension, - unsigned short ModeNo, unsigned short ModeIdIndex, + unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo) { @@ -1063,8 +1053,7 @@ static void XGI_SetCRT1ModeRegs(struct xgi_hw_device_info *HwDeviceExtension, data = data ^ 0xA0; xgifb_reg_and_or(pVBInfo->P3c4, 0x21, 0x1F, data); - XGI_SetVCLKState(HwDeviceExtension, ModeNo, RefreshRateTableIndex, - pVBInfo); + XGI_SetVCLKState(HwDeviceExtension, RefreshRateTableIndex, pVBInfo); data = xgifb_reg_get(pVBInfo->P3d4, 0x31); @@ -1122,7 +1111,7 @@ static void XGI_WriteDAC(unsigned short dl, outb((unsigned short) bl, pVBInfo->P3c9); } -static void XGI_LoadDAC(unsigned short ModeNo, unsigned short ModeIdIndex, +static void XGI_LoadDAC(unsigned short ModeIdIndex, struct vb_device_info *pVBInfo) { unsigned short data, data2, i, k, m, n, o, si, di, bx, dl, al, ah, dh; @@ -1188,8 +1177,7 @@ static void XGI_LoadDAC(unsigned short ModeNo, unsigned short ModeIdIndex, } } -static void XGI_GetLVDSResInfo(unsigned short ModeNo, - unsigned short ModeIdIndex, +static void XGI_GetLVDSResInfo(unsigned short ModeIdIndex, struct vb_device_info *pVBInfo) { unsigned short resindex, xres, yres, modeflag; @@ -1219,7 +1207,6 @@ static void XGI_GetLVDSResInfo(unsigned short ModeNo, } static void const *XGI_GetLcdPtr(struct XGI330_LCDDataTablStruct const *table, - unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo) @@ -1259,8 +1246,7 @@ static void const *XGI_GetLcdPtr(struct XGI330_LCDDataTablStruct const *table, return table[i].DATAPTR; } -static struct SiS_TVData const *XGI_GetTVPtr(unsigned short ModeNo, - unsigned short ModeIdIndex, +static struct SiS_TVData const *XGI_GetTVPtr(unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo) { @@ -1289,7 +1275,7 @@ static struct SiS_TVData const *XGI_GetTVPtr(unsigned short ModeNo, return &XGI_TVDataTable[i].DATAPTR[tempal]; } -static void XGI_GetLVDSData(unsigned short ModeNo, unsigned short ModeIdIndex, +static void XGI_GetLVDSData(unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo) { @@ -1298,7 +1284,7 @@ static void XGI_GetLVDSData(unsigned short ModeNo, unsigned short ModeIdIndex, if (!(pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA))) return; - LCDPtr = XGI_GetLcdPtr(XGI_EPLLCDDataPtr, ModeNo, ModeIdIndex, + LCDPtr = XGI_GetLcdPtr(XGI_EPLLCDDataPtr, ModeIdIndex, RefreshRateTableIndex, pVBInfo); pVBInfo->VGAHT = LCDPtr->VGAHT; pVBInfo->VGAVT = LCDPtr->VGAVT; @@ -1325,7 +1311,7 @@ static void XGI_GetLVDSData(unsigned short ModeNo, unsigned short ModeIdIndex, } } -static void XGI_ModCRT1Regs(unsigned short ModeNo, unsigned short ModeIdIndex, +static void XGI_ModCRT1Regs(unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo) @@ -1335,7 +1321,7 @@ static void XGI_ModCRT1Regs(unsigned short ModeNo, unsigned short ModeIdIndex, struct XGI_LVDSCRT1VDataStruct const *LCDPtr1 = NULL; if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) { - LCDPtr = XGI_GetLcdPtr(xgifb_epllcd_crt1_h, ModeNo, ModeIdIndex, + LCDPtr = XGI_GetLcdPtr(xgifb_epllcd_crt1_h, ModeIdIndex, RefreshRateTableIndex, pVBInfo); for (i = 0; i < 8; i++) @@ -1345,14 +1331,13 @@ static void XGI_ModCRT1Regs(unsigned short ModeNo, unsigned short ModeIdIndex, XGI_SetCRT1Timing_H(pVBInfo, HwDeviceExtension); if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) { - LCDPtr1 = XGI_GetLcdPtr(xgifb_epllcd_crt1_v, ModeNo, - ModeIdIndex, RefreshRateTableIndex, - pVBInfo); + LCDPtr1 = XGI_GetLcdPtr(xgifb_epllcd_crt1_v, ModeIdIndex, + RefreshRateTableIndex, pVBInfo); for (i = 0; i < 7; i++) pVBInfo->TimingV.data[i] = LCDPtr1[0].Reg[i]; } - XGI_SetCRT1Timing_V(ModeIdIndex, ModeNo, pVBInfo); + XGI_SetCRT1Timing_V(ModeIdIndex, pVBInfo); } static unsigned short XGI_GetLCDCapPtr(struct vb_device_info *pVBInfo) @@ -1425,7 +1410,7 @@ static void XGI_GetLCDSync(unsigned short *HSyncWidth, *VSyncWidth = pVBInfo->LCDCapList[Index].LCD_VSyncWidth; } -static void XGI_SetLVDSRegs(unsigned short ModeNo, unsigned short ModeIdIndex, +static void XGI_SetLVDSRegs(unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo) { @@ -1434,8 +1419,8 @@ static void XGI_SetLVDSRegs(unsigned short ModeNo, unsigned short ModeIdIndex, struct XGI330_LCDDataDesStruct2 const *LCDPtr1 = NULL; modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag; - LCDPtr1 = XGI_GetLcdPtr(XGI_EPLLCDDesDataPtr, ModeNo, ModeIdIndex, - RefreshRateTableIndex, pVBInfo); + LCDPtr1 = XGI_GetLcdPtr(XGI_EPLLCDDesDataPtr, ModeIdIndex, + RefreshRateTableIndex, pVBInfo); XGI_GetLCDSync(&tempax, &tempbx, pVBInfo); push1 = tempbx; @@ -1686,8 +1671,7 @@ static void XGI_GetLCDVCLKPtr(unsigned char *di_0, unsigned char *di_1, } static unsigned char XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex, - unsigned short ModeNo, unsigned short ModeIdIndex, - struct vb_device_info *pVBInfo) + unsigned short ModeIdIndex, struct vb_device_info *pVBInfo) { unsigned short index, modeflag; @@ -1769,15 +1753,14 @@ static void XGI_GetVCLKLen(unsigned char tempal, unsigned char *di_0, } } -static void XGI_SetCRT2ECLK(unsigned short ModeNo, unsigned short ModeIdIndex, +static void XGI_SetCRT2ECLK(unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo) { unsigned char di_0, di_1, tempal; int i; - tempal = XGI_GetVCLKPtr(RefreshRateTableIndex, ModeNo, ModeIdIndex, - pVBInfo); + tempal = XGI_GetVCLKPtr(RefreshRateTableIndex, ModeIdIndex, pVBInfo); XGI_GetVCLKLen(tempal, &di_0, &di_1, pVBInfo); XGI_GetLCDVCLKPtr(&di_0, &di_1, pVBInfo); @@ -1922,7 +1905,7 @@ finish: pVBInfo->VBType = tempbx; } -static void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, +static void XGI_GetVBInfo(unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo) { @@ -2048,7 +2031,7 @@ static void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, pVBInfo->VBInfo = tempbx; } -static void XGI_GetTVInfo(unsigned short ModeNo, unsigned short ModeIdIndex, +static void XGI_GetTVInfo(unsigned short ModeIdIndex, struct vb_device_info *pVBInfo) { unsigned short tempbx = 0, resinfo = 0, modeflag, index1; @@ -2115,8 +2098,8 @@ static void XGI_GetTVInfo(unsigned short ModeNo, unsigned short ModeIdIndex, pVBInfo->TVInfo = tempbx; } -static unsigned char XGI_GetLCDInfo(unsigned short ModeNo, - unsigned short ModeIdIndex, struct vb_device_info *pVBInfo) +static unsigned char XGI_GetLCDInfo(unsigned short ModeIdIndex, + struct vb_device_info *pVBInfo) { unsigned short temp, tempax, tempbx, resinfo = 0, LCDIdIndex; @@ -2435,8 +2418,7 @@ static void XGI_SaveCRT2Info(unsigned short ModeNo, xgifb_reg_and_or(pVBInfo->P3d4, 0x31, temp2, temp1); } -static void XGI_GetCRT2ResInfo(unsigned short ModeNo, - unsigned short ModeIdIndex, +static void XGI_GetCRT2ResInfo(unsigned short ModeIdIndex, struct vb_device_info *pVBInfo) { unsigned short xres, yres, modeflag, resindex; @@ -2508,8 +2490,7 @@ static unsigned char XGI_IsLCDDualLink(struct vb_device_info *pVBInfo) return 0; } -static void XGI_GetRAMDAC2DATA(unsigned short ModeNo, - unsigned short ModeIdIndex, +static void XGI_GetRAMDAC2DATA(unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo) { @@ -2551,7 +2532,7 @@ static void XGI_GetRAMDAC2DATA(unsigned short ModeNo, pVBInfo->VT = tempbx; } -static void XGI_GetCRT2Data(unsigned short ModeNo, unsigned short ModeIdIndex, +static void XGI_GetCRT2Data(unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo) { @@ -2566,13 +2547,12 @@ static void XGI_GetCRT2Data(unsigned short ModeNo, unsigned short ModeIdIndex, pVBInfo->RVBHRS = 50; if (pVBInfo->VBInfo & SetCRT2ToRAMDAC) { - XGI_GetRAMDAC2DATA(ModeNo, ModeIdIndex, RefreshRateTableIndex, - pVBInfo); + XGI_GetRAMDAC2DATA(ModeIdIndex, RefreshRateTableIndex, pVBInfo); return; } if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) { - LCDPtr = XGI_GetLcdPtr(XGI_LCDDataTable, ModeNo, ModeIdIndex, + LCDPtr = XGI_GetLcdPtr(XGI_LCDDataTable, ModeIdIndex, RefreshRateTableIndex, pVBInfo); pVBInfo->RVBHCMAX = LCDPtr->RVBHCMAX; @@ -2654,7 +2634,7 @@ static void XGI_GetCRT2Data(unsigned short ModeNo, unsigned short ModeIdIndex, if (pVBInfo->VBInfo & (SetCRT2ToTV)) { struct SiS_TVData const *TVPtr; - TVPtr = XGI_GetTVPtr(ModeNo, ModeIdIndex, RefreshRateTableIndex, + TVPtr = XGI_GetTVPtr(ModeIdIndex, RefreshRateTableIndex, pVBInfo); pVBInfo->RVBHCMAX = TVPtr->RVBHCMAX; @@ -2722,14 +2702,13 @@ static void XGI_GetCRT2Data(unsigned short ModeNo, unsigned short ModeIdIndex, } } -static void XGI_SetCRT2VCLK(unsigned short ModeNo, unsigned short ModeIdIndex, +static void XGI_SetCRT2VCLK(unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo) { unsigned char di_0, di_1, tempal; - tempal = XGI_GetVCLKPtr(RefreshRateTableIndex, ModeNo, ModeIdIndex, - pVBInfo); + tempal = XGI_GetVCLKPtr(RefreshRateTableIndex, ModeIdIndex, pVBInfo); XGI_GetVCLKLen(tempal, &di_0, &di_1, pVBInfo); XGI_GetLCDVCLKPtr(&di_0, &di_1, pVBInfo); @@ -2751,8 +2730,8 @@ static void XGI_SetCRT2VCLK(unsigned short ModeNo, unsigned short ModeIdIndex, xgifb_reg_or(pVBInfo->Part4Port, 0x12, 0x08); } -static unsigned short XGI_GetColorDepth(unsigned short ModeNo, - unsigned short ModeIdIndex, struct vb_device_info *pVBInfo) +static unsigned short XGI_GetColorDepth(unsigned short ModeIdIndex, + struct vb_device_info *pVBInfo) { unsigned short ColorDepth[6] = { 1, 2, 4, 4, 6, 8 }; short index; @@ -2786,7 +2765,7 @@ static unsigned short XGI_GetOffset(unsigned short ModeNo, if (infoflag & InterlaceMode) temp = temp << 1; - colordepth = XGI_GetColorDepth(ModeNo, ModeIdIndex, pVBInfo); + colordepth = XGI_GetColorDepth(ModeIdIndex, pVBInfo); if ((ModeNo >= 0x7C) && (ModeNo <= 0x7E)) { temp = ModeNo - 0x7C; @@ -2846,7 +2825,7 @@ static void XGI_PreSetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex, xgifb_reg_set(pVBInfo->Part1Port, 0x02, 0x44); /* temp 0206 */ } -static void XGI_SetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex, +static void XGI_SetGroup1(unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo) @@ -3724,7 +3703,7 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, } } -static void XGI_SetLCDRegs(unsigned short ModeNo, unsigned short ModeIdIndex, +static void XGI_SetLCDRegs(unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo) @@ -3772,12 +3751,11 @@ static void XGI_SetLCDRegs(unsigned short ModeNo, unsigned short ModeIdIndex, /* Customized LCDB Does not add */ if ((pVBInfo->VBType & VB_SIS301LV) || (pVBInfo->VBType & VB_SIS302LV)) - LCDBDesPtr = XGI_GetLcdPtr(xgifb_lcddldes, ModeNo, ModeIdIndex, + LCDBDesPtr = XGI_GetLcdPtr(xgifb_lcddldes, ModeIdIndex, RefreshRateTableIndex, pVBInfo); else - LCDBDesPtr = XGI_GetLcdPtr(XGI_LCDDesDataTable, ModeNo, - ModeIdIndex, RefreshRateTableIndex, - pVBInfo); + LCDBDesPtr = XGI_GetLcdPtr(XGI_LCDDesDataTable, ModeIdIndex, + RefreshRateTableIndex, pVBInfo); tempah = pVBInfo->LCDResInfo; tempah &= PanelResInfo; @@ -4003,8 +3981,8 @@ static void XGI_SetTap4Regs(struct vb_device_info *pVBInfo) xgifb_reg_and_or(pVBInfo->Part2Port, 0x4E, ~0x14, 0x10); } -static void XGI_SetGroup3(unsigned short ModeNo, unsigned short ModeIdIndex, - struct vb_device_info *pVBInfo) +static void XGI_SetGroup3(unsigned short ModeIdIndex, + struct vb_device_info *pVBInfo) { unsigned short i; unsigned char const *tempdi; @@ -4059,7 +4037,7 @@ static void XGI_SetGroup3(unsigned short ModeNo, unsigned short ModeIdIndex, } } -static void XGI_SetGroup4(unsigned short ModeNo, unsigned short ModeIdIndex, +static void XGI_SetGroup4(unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo) @@ -4224,7 +4202,7 @@ static void XGI_SetGroup4(unsigned short ModeNo, unsigned short ModeIdIndex, } /* end 301b */ - XGI_SetCRT2VCLK(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo); + XGI_SetCRT2VCLK(ModeIdIndex, RefreshRateTableIndex, pVBInfo); } static void XGINew_EnableCRT2(struct vb_device_info *pVBInfo) @@ -4232,8 +4210,8 @@ static void XGINew_EnableCRT2(struct vb_device_info *pVBInfo) xgifb_reg_and_or(pVBInfo->P3c4, 0x1E, 0xFF, 0x20); } -static void XGI_SetGroup5(unsigned short ModeNo, unsigned short ModeIdIndex, - struct vb_device_info *pVBInfo) +static void XGI_SetGroup5(unsigned short ModeIdIndex, + struct vb_device_info *pVBInfo) { if (pVBInfo->ModeType == ModeVGA) { if (!(pVBInfo->VBInfo & (SetInSlaveMode | LoadDACFlag @@ -4281,7 +4259,7 @@ static unsigned char XGI_XG21CheckLVDSMode(struct xgifb_video_info *xgifb_info, if (xres != xgifb_info->lvds_data.LVDSHDE || yres != xgifb_info->lvds_data.LVDSVDE) { - colordepth = XGI_GetColorDepth(ModeNo, ModeIdIndex, pVBInfo); + colordepth = XGI_GetColorDepth(ModeIdIndex, pVBInfo); if (colordepth > 2) return 0; } @@ -4290,7 +4268,6 @@ static unsigned char XGI_XG21CheckLVDSMode(struct xgifb_video_info *xgifb_info, static void xgifb_set_lvds(struct xgifb_video_info *xgifb_info, int chip_id, - unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo) { @@ -4831,8 +4808,7 @@ static void XGI_SetLCDCap(struct vb_device_info *pVBInfo) /* Output : */ /* Description : Set TV Customized Param. */ /* --------------------------------------------------------------------- */ -static void XGI_SetAntiFlicker(unsigned short ModeNo, - unsigned short ModeIdIndex, +static void XGI_SetAntiFlicker(unsigned short ModeIdIndex, struct vb_device_info *pVBInfo) { unsigned short tempbx; @@ -4850,8 +4826,7 @@ static void XGI_SetAntiFlicker(unsigned short ModeNo, xgifb_reg_and_or(pVBInfo->Part2Port, 0x0A, 0x8F, tempah); } -static void XGI_SetEdgeEnhance(unsigned short ModeNo, - unsigned short ModeIdIndex, +static void XGI_SetEdgeEnhance(unsigned short ModeIdIndex, struct vb_device_info *pVBInfo) { unsigned short tempbx; @@ -4887,8 +4862,8 @@ static void XGI_SetPhaseIncr(struct vb_device_info *pVBInfo) & 0xFF000000) >> 24)); } -static void XGI_SetYFilter(unsigned short ModeNo, unsigned short ModeIdIndex, - struct vb_device_info *pVBInfo) +static void XGI_SetYFilter(unsigned short ModeIdIndex, + struct vb_device_info *pVBInfo) { unsigned short tempbx, index; unsigned char const *filterPtr; @@ -4957,8 +4932,7 @@ static void XGI_SetYFilter(unsigned short ModeNo, unsigned short ModeIdIndex, /* Output : */ /* Description : Customized Param. for 301 */ /* --------------------------------------------------------------------- */ -static void XGI_OEM310Setting(unsigned short ModeNo, - unsigned short ModeIdIndex, +static void XGI_OEM310Setting(unsigned short ModeIdIndex, struct vb_device_info *pVBInfo) { XGI_SetDelayComp(pVBInfo); @@ -4968,11 +4942,11 @@ static void XGI_OEM310Setting(unsigned short ModeNo, if (pVBInfo->VBInfo & SetCRT2ToTV) { XGI_SetPhaseIncr(pVBInfo); - XGI_SetYFilter(ModeNo, ModeIdIndex, pVBInfo); - XGI_SetAntiFlicker(ModeNo, ModeIdIndex, pVBInfo); + XGI_SetYFilter(ModeIdIndex, pVBInfo); + XGI_SetAntiFlicker(ModeIdIndex, pVBInfo); if (pVBInfo->VBType & VB_SIS301) - XGI_SetEdgeEnhance(ModeNo, ModeIdIndex, pVBInfo); + XGI_SetEdgeEnhance(ModeIdIndex, pVBInfo); } } @@ -4982,8 +4956,7 @@ static void XGI_OEM310Setting(unsigned short ModeNo, /* Output : */ /* Description : Origin code for crt2group */ /* --------------------------------------------------------------------- */ -static void XGI_SetCRT2ModeRegs(unsigned short ModeNo, - struct xgi_hw_device_info *HwDeviceExtension, +static void XGI_SetCRT2ModeRegs(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo) { unsigned short tempbl; @@ -5231,8 +5204,8 @@ unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE, } i--; if ((pVBInfo->SetFlag & ProgrammingCRT2)) { - temp = XGI_AjustCRT2Rate(ModeNo, ModeIdIndex, - RefreshRateTableIndex, &i, pVBInfo); + temp = XGI_AjustCRT2Rate(ModeIdIndex, RefreshRateTableIndex, + &i, pVBInfo); } return RefreshRateTableIndex + i; } @@ -5246,12 +5219,12 @@ static void XGI_SetLCDAGroup(unsigned short ModeNo, unsigned short ModeIdIndex, pVBInfo->SetFlag |= ProgrammingCRT2; RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo, ModeIdIndex, pVBInfo); - XGI_GetLVDSResInfo(ModeNo, ModeIdIndex, pVBInfo); - XGI_GetLVDSData(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo); - XGI_ModCRT1Regs(ModeNo, ModeIdIndex, RefreshRateTableIndex, - HwDeviceExtension, pVBInfo); - XGI_SetLVDSRegs(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo); - XGI_SetCRT2ECLK(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo); + XGI_GetLVDSResInfo(ModeIdIndex, pVBInfo); + XGI_GetLVDSData(ModeIdIndex, RefreshRateTableIndex, pVBInfo); + XGI_ModCRT1Regs(ModeIdIndex, RefreshRateTableIndex, HwDeviceExtension, + pVBInfo); + XGI_SetLVDSRegs(ModeIdIndex, RefreshRateTableIndex, pVBInfo); + XGI_SetCRT2ECLK(ModeIdIndex, RefreshRateTableIndex, pVBInfo); } static unsigned char XGI_SetCRT2Group301(unsigned short ModeNo, @@ -5266,24 +5239,24 @@ static unsigned char XGI_SetCRT2Group301(unsigned short ModeNo, RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo, ModeIdIndex, pVBInfo); XGI_SaveCRT2Info(ModeNo, pVBInfo); - XGI_GetCRT2ResInfo(ModeNo, ModeIdIndex, pVBInfo); - XGI_GetCRT2Data(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo); + XGI_GetCRT2ResInfo(ModeIdIndex, pVBInfo); + XGI_GetCRT2Data(ModeIdIndex, RefreshRateTableIndex, pVBInfo); XGI_PreSetGroup1(ModeNo, ModeIdIndex, HwDeviceExtension, RefreshRateTableIndex, pVBInfo); - XGI_SetGroup1(ModeNo, ModeIdIndex, HwDeviceExtension, - RefreshRateTableIndex, pVBInfo); + XGI_SetGroup1(ModeIdIndex, HwDeviceExtension, RefreshRateTableIndex, + pVBInfo); XGI_SetLockRegs(ModeNo, ModeIdIndex, HwDeviceExtension, RefreshRateTableIndex, pVBInfo); XGI_SetGroup2(ModeNo, ModeIdIndex, RefreshRateTableIndex, HwDeviceExtension, pVBInfo); - XGI_SetLCDRegs(ModeNo, ModeIdIndex, HwDeviceExtension, - RefreshRateTableIndex, pVBInfo); + XGI_SetLCDRegs(ModeIdIndex, HwDeviceExtension, RefreshRateTableIndex, + pVBInfo); XGI_SetTap4Regs(pVBInfo); - XGI_SetGroup3(ModeNo, ModeIdIndex, pVBInfo); - XGI_SetGroup4(ModeNo, ModeIdIndex, RefreshRateTableIndex, - HwDeviceExtension, pVBInfo); - XGI_SetCRT2VCLK(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo); - XGI_SetGroup5(ModeNo, ModeIdIndex, pVBInfo); + XGI_SetGroup3(ModeIdIndex, pVBInfo); + XGI_SetGroup4(ModeIdIndex, RefreshRateTableIndex, HwDeviceExtension, + pVBInfo); + XGI_SetCRT2VCLK(ModeIdIndex, RefreshRateTableIndex, pVBInfo); + XGI_SetGroup5(ModeIdIndex, pVBInfo); XGI_AutoThreshold(pVBInfo); return 1; } @@ -5467,10 +5440,10 @@ static void XGI_SetCRT1Group(struct xgifb_video_info *xgifb_info, { unsigned short RefreshRateTableIndex, temp; - XGI_SetSeqRegs(ModeNo, ModeIdIndex, pVBInfo); + XGI_SetSeqRegs(ModeIdIndex, pVBInfo); outb(XGI330_StandTable.MISC, pVBInfo->P3c2); XGI_SetCRTCRegs(HwDeviceExtension, pVBInfo); - XGI_SetATTRegs(ModeNo, ModeIdIndex, pVBInfo); + XGI_SetATTRegs(ModeIdIndex, pVBInfo); XGI_SetGRCRegs(pVBInfo); XGI_ClearExt1Regs(pVBInfo); @@ -5495,13 +5468,13 @@ static void XGI_SetCRT1Group(struct xgifb_video_info *xgifb_info, ModeIdIndex, pVBInfo); if (RefreshRateTableIndex != 0xFFFF) { XGI_SetSync(RefreshRateTableIndex, pVBInfo); - XGI_SetCRT1CRTC(ModeNo, ModeIdIndex, RefreshRateTableIndex, + XGI_SetCRT1CRTC(ModeIdIndex, RefreshRateTableIndex, pVBInfo, HwDeviceExtension); - XGI_SetCRT1DE(HwDeviceExtension, ModeNo, ModeIdIndex, + XGI_SetCRT1DE(HwDeviceExtension, ModeIdIndex, RefreshRateTableIndex, pVBInfo); XGI_SetCRT1Offset(ModeNo, ModeIdIndex, RefreshRateTableIndex, HwDeviceExtension, pVBInfo); - XGI_SetCRT1VCLK(ModeNo, ModeIdIndex, HwDeviceExtension, + XGI_SetCRT1VCLK(ModeIdIndex, HwDeviceExtension, RefreshRateTableIndex, pVBInfo); } @@ -5510,30 +5483,30 @@ static void XGI_SetCRT1Group(struct xgifb_video_info *xgifb_info, if (temp & 0xA0) { if (HwDeviceExtension->jChipType == XG27) - XGI_SetXG27CRTC(ModeNo, ModeIdIndex, + XGI_SetXG27CRTC(ModeIdIndex, RefreshRateTableIndex, pVBInfo); else - XGI_SetXG21CRTC(ModeNo, ModeIdIndex, + XGI_SetXG21CRTC(ModeIdIndex, RefreshRateTableIndex, pVBInfo); XGI_UpdateXG21CRTC(ModeNo, pVBInfo, RefreshRateTableIndex); xgifb_set_lcd(HwDeviceExtension->jChipType, - pVBInfo, RefreshRateTableIndex, ModeNo); + pVBInfo, RefreshRateTableIndex); if (pVBInfo->IF_DEF_LVDS == 1) xgifb_set_lvds(xgifb_info, HwDeviceExtension->jChipType, - ModeNo, ModeIdIndex, pVBInfo); + ModeIdIndex, pVBInfo); } } pVBInfo->SetFlag &= (~ProgrammingCRT2); - XGI_SetCRT1FIFO(ModeNo, HwDeviceExtension, pVBInfo); - XGI_SetCRT1ModeRegs(HwDeviceExtension, ModeNo, ModeIdIndex, - RefreshRateTableIndex, pVBInfo); - XGI_LoadDAC(ModeNo, ModeIdIndex, pVBInfo); + XGI_SetCRT1FIFO(HwDeviceExtension, pVBInfo); + XGI_SetCRT1ModeRegs(HwDeviceExtension, ModeIdIndex, + RefreshRateTableIndex, pVBInfo); + XGI_LoadDAC(ModeIdIndex, pVBInfo); } unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info, @@ -5573,9 +5546,9 @@ unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info, XGI_SearchModeID(ModeNo, &ModeIdIndex, pVBInfo); if (HwDeviceExtension->jChipType < XG20) { - XGI_GetVBInfo(ModeNo, ModeIdIndex, HwDeviceExtension, pVBInfo); - XGI_GetTVInfo(ModeNo, ModeIdIndex, pVBInfo); - XGI_GetLCDInfo(ModeNo, ModeIdIndex, pVBInfo); + XGI_GetVBInfo(ModeIdIndex, HwDeviceExtension, pVBInfo); + XGI_GetTVInfo(ModeIdIndex, pVBInfo); + XGI_GetLCDInfo(ModeIdIndex, pVBInfo); XGI_DisableBridge(xgifb_info, HwDeviceExtension, pVBInfo); if (pVBInfo->VBInfo & (SetSimuScanMode | XGI_SetCRT2ToLCDA) || @@ -5602,8 +5575,8 @@ unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info, } } - XGI_SetCRT2ModeRegs(ModeNo, HwDeviceExtension, pVBInfo); - XGI_OEM310Setting(ModeNo, ModeIdIndex, pVBInfo); /*0212*/ + XGI_SetCRT2ModeRegs(HwDeviceExtension, pVBInfo); + XGI_OEM310Setting(ModeIdIndex, pVBInfo); /*0212*/ XGI_EnableBridge(xgifb_info, HwDeviceExtension, pVBInfo); } /* !XG20 */ else { From 6b6e6a3995435d2cf8c8c30dbfc75953ead64c35 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 16 Jul 2013 23:13:27 +0300 Subject: [PATCH 0422/3400] staging: xgifb: delete unused "ModeIdIndex" parameters Delete unused "ModeIdIndex" parameters from internal functions. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/vb_setmode.c | 37 +++++++++++------------------- 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index 84cc48612e15..36be17bfa5a8 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -63,8 +63,7 @@ void InitTo330Pointer(unsigned char ChipType, struct vb_device_info *pVBInfo) } -static void XGI_SetSeqRegs(unsigned short ModeIdIndex, - struct vb_device_info *pVBInfo) +static void XGI_SetSeqRegs(struct vb_device_info *pVBInfo) { unsigned char SRdata, i; @@ -399,8 +398,7 @@ static void XGI_SetCRT1CRTC(unsigned short ModeIdIndex, /* Output : Fill CRT Hsync/Vsync to SR2E/SR2F/SR30/SR33/SR34/SR3F */ /* Description : Set LCD timing */ /* --------------------------------------------------------------------- */ -static void XGI_SetXG21CRTC(unsigned short ModeIdIndex, - unsigned short RefreshRateTableIndex, +static void XGI_SetXG21CRTC(unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo) { unsigned char index, Tempax, Tempbx, Tempcx, Tempdx; @@ -496,8 +494,7 @@ static void XGI_SetXG21CRTC(unsigned short ModeIdIndex, xgifb_reg_set(pVBInfo->P3c4, 0x3F, Tempax); } -static void XGI_SetXG27CRTC(unsigned short ModeIdIndex, - unsigned short RefreshRateTableIndex, +static void XGI_SetXG27CRTC(unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo) { unsigned short index, Tempax, Tempbx, Tempcx; @@ -1111,8 +1108,7 @@ static void XGI_WriteDAC(unsigned short dl, outb((unsigned short) bl, pVBInfo->P3c9); } -static void XGI_LoadDAC(unsigned short ModeIdIndex, - struct vb_device_info *pVBInfo) +static void XGI_LoadDAC(struct vb_device_info *pVBInfo) { unsigned short data, data2, i, k, m, n, o, si, di, bx, dl, al, ah, dh; const unsigned short *table = XGINew_VGA_DAC; @@ -4210,8 +4206,7 @@ static void XGINew_EnableCRT2(struct vb_device_info *pVBInfo) xgifb_reg_and_or(pVBInfo->P3c4, 0x1E, 0xFF, 0x20); } -static void XGI_SetGroup5(unsigned short ModeIdIndex, - struct vb_device_info *pVBInfo) +static void XGI_SetGroup5(struct vb_device_info *pVBInfo) { if (pVBInfo->ModeType == ModeVGA) { if (!(pVBInfo->VBInfo & (SetInSlaveMode | LoadDACFlag @@ -4808,8 +4803,7 @@ static void XGI_SetLCDCap(struct vb_device_info *pVBInfo) /* Output : */ /* Description : Set TV Customized Param. */ /* --------------------------------------------------------------------- */ -static void XGI_SetAntiFlicker(unsigned short ModeIdIndex, - struct vb_device_info *pVBInfo) +static void XGI_SetAntiFlicker(struct vb_device_info *pVBInfo) { unsigned short tempbx; @@ -4826,8 +4820,7 @@ static void XGI_SetAntiFlicker(unsigned short ModeIdIndex, xgifb_reg_and_or(pVBInfo->Part2Port, 0x0A, 0x8F, tempah); } -static void XGI_SetEdgeEnhance(unsigned short ModeIdIndex, - struct vb_device_info *pVBInfo) +static void XGI_SetEdgeEnhance(struct vb_device_info *pVBInfo) { unsigned short tempbx; @@ -4943,10 +4936,10 @@ static void XGI_OEM310Setting(unsigned short ModeIdIndex, if (pVBInfo->VBInfo & SetCRT2ToTV) { XGI_SetPhaseIncr(pVBInfo); XGI_SetYFilter(ModeIdIndex, pVBInfo); - XGI_SetAntiFlicker(ModeIdIndex, pVBInfo); + XGI_SetAntiFlicker(pVBInfo); if (pVBInfo->VBType & VB_SIS301) - XGI_SetEdgeEnhance(ModeIdIndex, pVBInfo); + XGI_SetEdgeEnhance(pVBInfo); } } @@ -5256,7 +5249,7 @@ static unsigned char XGI_SetCRT2Group301(unsigned short ModeNo, XGI_SetGroup4(ModeIdIndex, RefreshRateTableIndex, HwDeviceExtension, pVBInfo); XGI_SetCRT2VCLK(ModeIdIndex, RefreshRateTableIndex, pVBInfo); - XGI_SetGroup5(ModeIdIndex, pVBInfo); + XGI_SetGroup5(pVBInfo); XGI_AutoThreshold(pVBInfo); return 1; } @@ -5440,7 +5433,7 @@ static void XGI_SetCRT1Group(struct xgifb_video_info *xgifb_info, { unsigned short RefreshRateTableIndex, temp; - XGI_SetSeqRegs(ModeIdIndex, pVBInfo); + XGI_SetSeqRegs(pVBInfo); outb(XGI330_StandTable.MISC, pVBInfo->P3c2); XGI_SetCRTCRegs(HwDeviceExtension, pVBInfo); XGI_SetATTRegs(ModeIdIndex, pVBInfo); @@ -5483,11 +5476,9 @@ static void XGI_SetCRT1Group(struct xgifb_video_info *xgifb_info, if (temp & 0xA0) { if (HwDeviceExtension->jChipType == XG27) - XGI_SetXG27CRTC(ModeIdIndex, - RefreshRateTableIndex, pVBInfo); + XGI_SetXG27CRTC(RefreshRateTableIndex, pVBInfo); else - XGI_SetXG21CRTC(ModeIdIndex, - RefreshRateTableIndex, pVBInfo); + XGI_SetXG21CRTC(RefreshRateTableIndex, pVBInfo); XGI_UpdateXG21CRTC(ModeNo, pVBInfo, RefreshRateTableIndex); @@ -5506,7 +5497,7 @@ static void XGI_SetCRT1Group(struct xgifb_video_info *xgifb_info, XGI_SetCRT1FIFO(HwDeviceExtension, pVBInfo); XGI_SetCRT1ModeRegs(HwDeviceExtension, ModeIdIndex, RefreshRateTableIndex, pVBInfo); - XGI_LoadDAC(ModeIdIndex, pVBInfo); + XGI_LoadDAC(pVBInfo); } unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info, From b053af16885fb5f4ebd720433271abb63ea4c7fa Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 16 Jul 2013 23:13:28 +0300 Subject: [PATCH 0423/3400] staging: xgifb: delete unused "HwDeviceExtension" parameters Delete unused "HwDeviceExtension" parameters from internal functions. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/vb_init.c | 31 +++++------- drivers/staging/xgifb/vb_setmode.c | 78 +++++++++--------------------- drivers/staging/xgifb/vb_setmode.h | 6 +-- 3 files changed, 39 insertions(+), 76 deletions(-) diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c index 5f1c41ed778b..506b7fe9c20d 100644 --- a/drivers/staging/xgifb/vb_init.c +++ b/drivers/staging/xgifb/vb_init.c @@ -102,10 +102,8 @@ static void XGINew_DDR1x_MRS_340(unsigned long P3c4, xgifb_reg_set(P3c4, 0x1B, 0x00); } -static void XGINew_SetMemoryClock(struct xgi_hw_device_info *HwDeviceExtension, - struct vb_device_info *pVBInfo) +static void XGINew_SetMemoryClock(struct vb_device_info *pVBInfo) { - xgifb_reg_set(pVBInfo->P3c4, 0x28, pVBInfo->MCLKData[pVBInfo->ram_type].SR28); @@ -133,7 +131,7 @@ static void XGINew_DDRII_Bootup_XG27( { unsigned long P3d4 = P3c4 + 0x10; pVBInfo->ram_type = XGINew_GetXG20DRAMType(HwDeviceExtension, pVBInfo); - XGINew_SetMemoryClock(HwDeviceExtension, pVBInfo); + XGINew_SetMemoryClock(pVBInfo); /* Set Double Frequency */ xgifb_reg_set(P3d4, 0x97, pVBInfo->XGINew_CR97); /* CR97 */ @@ -206,7 +204,7 @@ static void XGINew_DDR2_MRS_XG20(struct xgi_hw_device_info *HwDeviceExtension, unsigned long P3d4 = P3c4 + 0x10; pVBInfo->ram_type = XGINew_GetXG20DRAMType(HwDeviceExtension, pVBInfo); - XGINew_SetMemoryClock(HwDeviceExtension, pVBInfo); + XGINew_SetMemoryClock(pVBInfo); xgifb_reg_set(P3d4, 0x97, 0x11); /* CR97 */ @@ -280,7 +278,7 @@ static void XGINew_DDR1x_DefaultRegister( unsigned long P3d4 = Port, P3c4 = Port - 0x10; if (HwDeviceExtension->jChipType >= XG20) { - XGINew_SetMemoryClock(HwDeviceExtension, pVBInfo); + XGINew_SetMemoryClock(pVBInfo); xgifb_reg_set(P3d4, 0x82, pVBInfo->CR40[11][pVBInfo->ram_type]); /* CR82 */ @@ -296,7 +294,7 @@ static void XGINew_DDR1x_DefaultRegister( XGINew_DDR1x_MRS_XG20(P3c4, pVBInfo); } else { - XGINew_SetMemoryClock(HwDeviceExtension, pVBInfo); + XGINew_SetMemoryClock(pVBInfo); switch (HwDeviceExtension->jChipType) { case XG42: @@ -948,8 +946,7 @@ error: return false; } -static void XGINew_ChkSenseStatus(struct xgi_hw_device_info *HwDeviceExtension, - struct vb_device_info *pVBInfo) +static void XGINew_ChkSenseStatus(struct vb_device_info *pVBInfo) { unsigned short tempbx = 0, temp, tempcx, CR3CData; @@ -991,8 +988,7 @@ static void XGINew_ChkSenseStatus(struct xgi_hw_device_info *HwDeviceExtension, xgifb_reg_set(pVBInfo->P3d4, 0x3e, ((tempbx & 0xFF00) >> 8)); } -static void XGINew_SetModeScratch(struct xgi_hw_device_info *HwDeviceExtension, - struct vb_device_info *pVBInfo) +static void XGINew_SetModeScratch(struct vb_device_info *pVBInfo) { unsigned short temp, tempcl = 0, tempch = 0, CR31Data, CR38Data; @@ -1126,8 +1122,7 @@ static void XGINew_GetXG21Sense(struct pci_dev *pdev, } } -static void XGINew_GetXG27Sense(struct xgi_hw_device_info *HwDeviceExtension, - struct vb_device_info *pVBInfo) +static void XGINew_GetXG27Sense(struct vb_device_info *pVBInfo) { unsigned char Temp, bCR4A; @@ -1222,7 +1217,7 @@ unsigned char XGIInitNew(struct pci_dev *pdev) XGINew_GetXG21Sense(pdev, pVBInfo); if (HwDeviceExtension->jChipType == XG27) - XGINew_GetXG27Sense(HwDeviceExtension, pVBInfo); + XGINew_GetXG27Sense(pVBInfo); /* Reset Extended register */ @@ -1294,7 +1289,7 @@ unsigned char XGIInitNew(struct pci_dev *pdev) if (HwDeviceExtension->jChipType < XG20) { /* Set VB */ - XGI_UnLockCRT2(HwDeviceExtension, pVBInfo); + XGI_UnLockCRT2(pVBInfo); /* disable VideoCapture */ xgifb_reg_and_or(pVBInfo->Part0Port, 0x3F, 0xEF, 0x00); xgifb_reg_set(pVBInfo->Part1Port, 0x00, 0x00); @@ -1334,7 +1329,7 @@ unsigned char XGIInitNew(struct pci_dev *pdev) xgifb_reg_set(pVBInfo->Part4Port, 0x10, XGI330_CRT2Data_4_10); xgifb_reg_set(pVBInfo->Part4Port, 0x0F, 0x3F); - XGI_LockCRT2(HwDeviceExtension, pVBInfo); + XGI_LockCRT2(pVBInfo); } } /* != XG20 */ @@ -1370,8 +1365,8 @@ unsigned char XGIInitNew(struct pci_dev *pdev) xgifb_reg_set(pVBInfo->P3c4, 0x22, 0xfa); xgifb_reg_set(pVBInfo->P3c4, 0x21, 0xa3); - XGINew_ChkSenseStatus(HwDeviceExtension, pVBInfo); - XGINew_SetModeScratch(HwDeviceExtension, pVBInfo); + XGINew_ChkSenseStatus(pVBInfo); + XGINew_SetModeScratch(pVBInfo); xgifb_reg_set(pVBInfo->P3d4, 0x8c, 0x87); diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index 36be17bfa5a8..729203803b1b 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -77,8 +77,7 @@ static void XGI_SetSeqRegs(struct vb_device_info *pVBInfo) } } -static void XGI_SetCRTCRegs(struct xgi_hw_device_info *HwDeviceExtension, - struct vb_device_info *pVBInfo) +static void XGI_SetCRTCRegs(struct vb_device_info *pVBInfo) { unsigned char CRTCdata; unsigned short i; @@ -678,8 +677,7 @@ static void XGI_UpdateXG21CRTC(unsigned short ModeNo, } } -static void XGI_SetCRT1DE(struct xgi_hw_device_info *HwDeviceExtension, - unsigned short ModeIdIndex, +static void XGI_SetCRT1DE(unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo) { @@ -827,7 +825,6 @@ static void XGI_SetCRT1Offset(unsigned short ModeNo, static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, - struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo) { unsigned short VCLKIndex, modeflag; @@ -889,7 +886,7 @@ static void XGI_SetCRT1VCLK(unsigned short ModeIdIndex, VB_SIS302LV | VB_XGI301C)) && (pVBInfo->VBInfo & XGI_SetCRT2ToLCDA)) { vclkindex = XGI_GetVCLK2Ptr(ModeIdIndex, RefreshRateTableIndex, - HwDeviceExtension, pVBInfo); + pVBInfo); data = xgifb_reg_get(pVBInfo->P3c4, 0x31) & 0xCF; xgifb_reg_set(pVBInfo->P3c4, 0x31, data); data = XGI_VBVCLKData[vclkindex].Part4_A; @@ -1774,8 +1771,7 @@ static void XGI_SetCRT2ECLK(unsigned short ModeIdIndex, } } -static void XGI_UpdateModeInfo(struct xgi_hw_device_info *HwDeviceExtension, - struct vb_device_info *pVBInfo) +static void XGI_UpdateModeInfo(struct vb_device_info *pVBInfo) { unsigned short tempcl, tempch, temp, tempbl, tempax; @@ -1902,7 +1898,6 @@ finish: } static void XGI_GetVBInfo(unsigned short ModeIdIndex, - struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo) { unsigned short tempax, push, tempbx, temp, modeflag; @@ -2745,7 +2740,6 @@ static unsigned short XGI_GetColorDepth(unsigned short ModeIdIndex, static unsigned short XGI_GetOffset(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, - struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo) { unsigned short temp, colordepth, modeinfo, index, infoflag, @@ -2776,7 +2770,6 @@ static unsigned short XGI_GetOffset(unsigned short ModeNo, static void XGI_SetCRT2Offset(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, - struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo) { unsigned short offset; @@ -2786,7 +2779,7 @@ static void XGI_SetCRT2Offset(unsigned short ModeNo, return; offset = XGI_GetOffset(ModeNo, ModeIdIndex, RefreshRateTableIndex, - HwDeviceExtension, pVBInfo); + pVBInfo); temp = (unsigned char) (offset & 0xFF); xgifb_reg_set(pVBInfo->Part1Port, 0x07, temp); temp = (unsigned char) ((offset & 0xFF00) >> 8); @@ -2804,14 +2797,12 @@ static void XGI_SetCRT2FIFO(struct vb_device_info *pVBInfo) } static void XGI_PreSetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex, - struct xgi_hw_device_info *HwDeviceExtension, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo) { u8 tempcx; - XGI_SetCRT2Offset(ModeNo, ModeIdIndex, RefreshRateTableIndex, - HwDeviceExtension, pVBInfo); + XGI_SetCRT2Offset(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo); XGI_SetCRT2FIFO(pVBInfo); for (tempcx = 4; tempcx < 7; tempcx++) @@ -2822,7 +2813,6 @@ static void XGI_PreSetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex, } static void XGI_SetGroup1(unsigned short ModeIdIndex, - struct xgi_hw_device_info *HwDeviceExtension, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo) { @@ -2977,7 +2967,6 @@ static unsigned short XGI_GetVGAHT2(struct vb_device_info *pVBInfo) } static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex, - struct xgi_hw_device_info *HwDeviceExtension, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo) { @@ -3270,7 +3259,6 @@ static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex, static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, - struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo) { unsigned short i, j, tempax, tempbx, tempcx, temp, push1, push2, @@ -3700,7 +3688,6 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, } static void XGI_SetLCDRegs(unsigned short ModeIdIndex, - struct xgi_hw_device_info *HwDeviceExtension, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo) { @@ -4035,7 +4022,6 @@ static void XGI_SetGroup3(unsigned short ModeIdIndex, static void XGI_SetGroup4(unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, - struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo) { unsigned short tempax, tempcx, tempbx, modeflag, temp, temp2; @@ -4216,10 +4202,8 @@ static void XGI_SetGroup5(struct vb_device_info *pVBInfo) } } -static void XGI_DisableGatingCRT(struct xgi_hw_device_info *HwDeviceExtension, - struct vb_device_info *pVBInfo) +static void XGI_DisableGatingCRT(struct vb_device_info *pVBInfo) { - xgifb_reg_and_or(pVBInfo->P3d4, 0x63, 0xBF, 0x00); } @@ -4949,8 +4933,7 @@ static void XGI_OEM310Setting(unsigned short ModeIdIndex, /* Output : */ /* Description : Origin code for crt2group */ /* --------------------------------------------------------------------- */ -static void XGI_SetCRT2ModeRegs(struct xgi_hw_device_info *HwDeviceExtension, - struct vb_device_info *pVBInfo) +static void XGI_SetCRT2ModeRegs(struct vb_device_info *pVBInfo) { unsigned short tempbl; short tempcl; @@ -5112,20 +5095,14 @@ reg_and_or: } -void XGI_UnLockCRT2(struct xgi_hw_device_info *HwDeviceExtension, - struct vb_device_info *pVBInfo) +void XGI_UnLockCRT2(struct vb_device_info *pVBInfo) { - xgifb_reg_and_or(pVBInfo->Part1Port, 0x2f, 0xFF, 0x01); - } -void XGI_LockCRT2(struct xgi_hw_device_info *HwDeviceExtension, - struct vb_device_info *pVBInfo) +void XGI_LockCRT2(struct vb_device_info *pVBInfo) { - xgifb_reg_and_or(pVBInfo->Part1Port, 0x2F, 0xFE, 0x00); - } unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE, @@ -5234,20 +5211,14 @@ static unsigned char XGI_SetCRT2Group301(unsigned short ModeNo, XGI_SaveCRT2Info(ModeNo, pVBInfo); XGI_GetCRT2ResInfo(ModeIdIndex, pVBInfo); XGI_GetCRT2Data(ModeIdIndex, RefreshRateTableIndex, pVBInfo); - XGI_PreSetGroup1(ModeNo, ModeIdIndex, HwDeviceExtension, - RefreshRateTableIndex, pVBInfo); - XGI_SetGroup1(ModeIdIndex, HwDeviceExtension, RefreshRateTableIndex, - pVBInfo); - XGI_SetLockRegs(ModeNo, ModeIdIndex, HwDeviceExtension, - RefreshRateTableIndex, pVBInfo); - XGI_SetGroup2(ModeNo, ModeIdIndex, RefreshRateTableIndex, - HwDeviceExtension, pVBInfo); - XGI_SetLCDRegs(ModeIdIndex, HwDeviceExtension, RefreshRateTableIndex, - pVBInfo); + XGI_PreSetGroup1(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo); + XGI_SetGroup1(ModeIdIndex, RefreshRateTableIndex, pVBInfo); + XGI_SetLockRegs(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo); + XGI_SetGroup2(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo); + XGI_SetLCDRegs(ModeIdIndex, RefreshRateTableIndex, pVBInfo); XGI_SetTap4Regs(pVBInfo); XGI_SetGroup3(ModeIdIndex, pVBInfo); - XGI_SetGroup4(ModeIdIndex, RefreshRateTableIndex, HwDeviceExtension, - pVBInfo); + XGI_SetGroup4(ModeIdIndex, RefreshRateTableIndex, pVBInfo); XGI_SetCRT2VCLK(ModeIdIndex, RefreshRateTableIndex, pVBInfo); XGI_SetGroup5(pVBInfo); XGI_AutoThreshold(pVBInfo); @@ -5408,7 +5379,7 @@ static void XGI_EnableBridge(struct xgifb_video_info *xgifb_info, /* EnablePart4_1F */ xgifb_reg_or(pVBInfo->Part4Port, 0x1F, tempah); - XGI_DisableGatingCRT(HwDeviceExtension, pVBInfo); + XGI_DisableGatingCRT(pVBInfo); XGI_DisplayOn(xgifb_info, HwDeviceExtension, pVBInfo); } /* 301 */ else { /* LVDS */ @@ -5435,7 +5406,7 @@ static void XGI_SetCRT1Group(struct xgifb_video_info *xgifb_info, XGI_SetSeqRegs(pVBInfo); outb(XGI330_StandTable.MISC, pVBInfo->P3c2); - XGI_SetCRTCRegs(HwDeviceExtension, pVBInfo); + XGI_SetCRTCRegs(pVBInfo); XGI_SetATTRegs(ModeIdIndex, pVBInfo); XGI_SetGRCRegs(pVBInfo); XGI_ClearExt1Regs(pVBInfo); @@ -5463,8 +5434,7 @@ static void XGI_SetCRT1Group(struct xgifb_video_info *xgifb_info, XGI_SetSync(RefreshRateTableIndex, pVBInfo); XGI_SetCRT1CRTC(ModeIdIndex, RefreshRateTableIndex, pVBInfo, HwDeviceExtension); - XGI_SetCRT1DE(HwDeviceExtension, ModeIdIndex, - RefreshRateTableIndex, pVBInfo); + XGI_SetCRT1DE(ModeIdIndex, RefreshRateTableIndex, pVBInfo); XGI_SetCRT1Offset(ModeNo, ModeIdIndex, RefreshRateTableIndex, HwDeviceExtension, pVBInfo); XGI_SetCRT1VCLK(ModeIdIndex, HwDeviceExtension, @@ -5532,12 +5502,12 @@ unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info, xgifb_reg_set(pVBInfo->P3c4, 0x05, 0x86); if (HwDeviceExtension->jChipType < XG20) - XGI_UnLockCRT2(HwDeviceExtension, pVBInfo); + XGI_UnLockCRT2(pVBInfo); XGI_SearchModeID(ModeNo, &ModeIdIndex, pVBInfo); if (HwDeviceExtension->jChipType < XG20) { - XGI_GetVBInfo(ModeIdIndex, HwDeviceExtension, pVBInfo); + XGI_GetVBInfo(ModeIdIndex, pVBInfo); XGI_GetTVInfo(ModeIdIndex, pVBInfo); XGI_GetLCDInfo(ModeIdIndex, pVBInfo); XGI_DisableBridge(xgifb_info, HwDeviceExtension, pVBInfo); @@ -5566,7 +5536,7 @@ unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info, } } - XGI_SetCRT2ModeRegs(HwDeviceExtension, pVBInfo); + XGI_SetCRT2ModeRegs(pVBInfo); XGI_OEM310Setting(ModeIdIndex, pVBInfo); /*0212*/ XGI_EnableBridge(xgifb_info, HwDeviceExtension, pVBInfo); } /* !XG20 */ @@ -5591,10 +5561,10 @@ unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info, XGI_DisplayOn(xgifb_info, HwDeviceExtension, pVBInfo); } - XGI_UpdateModeInfo(HwDeviceExtension, pVBInfo); + XGI_UpdateModeInfo(pVBInfo); if (HwDeviceExtension->jChipType < XG20) - XGI_LockCRT2(HwDeviceExtension, pVBInfo); + XGI_LockCRT2(pVBInfo); return 1; } diff --git a/drivers/staging/xgifb/vb_setmode.h b/drivers/staging/xgifb/vb_setmode.h index 2c0a31c8dfd5..3170dd384392 100644 --- a/drivers/staging/xgifb/vb_setmode.h +++ b/drivers/staging/xgifb/vb_setmode.h @@ -2,10 +2,8 @@ #define _VBSETMODE_ extern void InitTo330Pointer(unsigned char, struct vb_device_info *); -extern void XGI_UnLockCRT2(struct xgi_hw_device_info *HwDeviceExtension, - struct vb_device_info *); -extern void XGI_LockCRT2(struct xgi_hw_device_info *HwDeviceExtension, - struct vb_device_info *); +extern void XGI_UnLockCRT2(struct vb_device_info *); +extern void XGI_LockCRT2(struct vb_device_info *); extern void XGI_DisplayOff(struct xgifb_video_info *, struct xgi_hw_device_info *, struct vb_device_info *); From 88a3dfdd93ab1f1ac4a92defd17fadcbc1c0e812 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 16 Jul 2013 23:13:29 +0300 Subject: [PATCH 0424/3400] staging: xgifb: delete unused "RefreshRateTableIndex" parameters Delete unused "RefreshRateTableIndex" parameters from internal functions. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/vb_setmode.c | 44 ++++++++++++------------------ 1 file changed, 17 insertions(+), 27 deletions(-) diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index 729203803b1b..7228d171d31e 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -1201,7 +1201,6 @@ static void XGI_GetLVDSResInfo(unsigned short ModeIdIndex, static void const *XGI_GetLcdPtr(struct XGI330_LCDDataTablStruct const *table, unsigned short ModeIdIndex, - unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo) { unsigned short i, tempdx, tempbx, modeflag; @@ -1269,16 +1268,14 @@ static struct SiS_TVData const *XGI_GetTVPtr(unsigned short ModeIdIndex, } static void XGI_GetLVDSData(unsigned short ModeIdIndex, - unsigned short RefreshRateTableIndex, - struct vb_device_info *pVBInfo) + struct vb_device_info *pVBInfo) { struct SiS_LVDSData const *LCDPtr; if (!(pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA))) return; - LCDPtr = XGI_GetLcdPtr(XGI_EPLLCDDataPtr, ModeIdIndex, - RefreshRateTableIndex, pVBInfo); + LCDPtr = XGI_GetLcdPtr(XGI_EPLLCDDataPtr, ModeIdIndex, pVBInfo); pVBInfo->VGAHT = LCDPtr->VGAHT; pVBInfo->VGAVT = LCDPtr->VGAVT; pVBInfo->HT = LCDPtr->LCDHT; @@ -1305,9 +1302,8 @@ static void XGI_GetLVDSData(unsigned short ModeIdIndex, } static void XGI_ModCRT1Regs(unsigned short ModeIdIndex, - unsigned short RefreshRateTableIndex, - struct xgi_hw_device_info *HwDeviceExtension, - struct vb_device_info *pVBInfo) + struct xgi_hw_device_info *HwDeviceExtension, + struct vb_device_info *pVBInfo) { unsigned short i; struct XGI_LVDSCRT1HDataStruct const *LCDPtr = NULL; @@ -1315,7 +1311,7 @@ static void XGI_ModCRT1Regs(unsigned short ModeIdIndex, if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) { LCDPtr = XGI_GetLcdPtr(xgifb_epllcd_crt1_h, ModeIdIndex, - RefreshRateTableIndex, pVBInfo); + pVBInfo); for (i = 0; i < 8; i++) pVBInfo->TimingH.data[i] = LCDPtr[0].Reg[i]; @@ -1325,7 +1321,7 @@ static void XGI_ModCRT1Regs(unsigned short ModeIdIndex, if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) { LCDPtr1 = XGI_GetLcdPtr(xgifb_epllcd_crt1_v, ModeIdIndex, - RefreshRateTableIndex, pVBInfo); + pVBInfo); for (i = 0; i < 7; i++) pVBInfo->TimingV.data[i] = LCDPtr1[0].Reg[i]; } @@ -1404,16 +1400,14 @@ static void XGI_GetLCDSync(unsigned short *HSyncWidth, } static void XGI_SetLVDSRegs(unsigned short ModeIdIndex, - unsigned short RefreshRateTableIndex, - struct vb_device_info *pVBInfo) + struct vb_device_info *pVBInfo) { unsigned short tempbx, tempax, tempcx, tempdx, push1, push2, modeflag; unsigned long temp, temp1, temp2, temp3, push3; struct XGI330_LCDDataDesStruct2 const *LCDPtr1 = NULL; modeflag = XGI330_EModeIDTable[ModeIdIndex].Ext_ModeFlag; - LCDPtr1 = XGI_GetLcdPtr(XGI_EPLLCDDesDataPtr, ModeIdIndex, - RefreshRateTableIndex, pVBInfo); + LCDPtr1 = XGI_GetLcdPtr(XGI_EPLLCDDesDataPtr, ModeIdIndex, pVBInfo); XGI_GetLCDSync(&tempax, &tempbx, pVBInfo); push1 = tempbx; @@ -2544,7 +2538,7 @@ static void XGI_GetCRT2Data(unsigned short ModeIdIndex, if (pVBInfo->VBInfo & (SetCRT2ToLCD | XGI_SetCRT2ToLCDA)) { LCDPtr = XGI_GetLcdPtr(XGI_LCDDataTable, ModeIdIndex, - RefreshRateTableIndex, pVBInfo); + pVBInfo); pVBInfo->RVBHCMAX = LCDPtr->RVBHCMAX; pVBInfo->RVBHCFACT = LCDPtr->RVBHCFACT; @@ -2967,7 +2961,6 @@ static unsigned short XGI_GetVGAHT2(struct vb_device_info *pVBInfo) } static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex, - unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo) { unsigned short push1, push2, tempax, tempbx = 0, tempcx, temp, resinfo, @@ -3258,7 +3251,6 @@ static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex, } static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, - unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo) { unsigned short i, j, tempax, tempbx, tempcx, temp, push1, push2, @@ -3688,7 +3680,6 @@ static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, } static void XGI_SetLCDRegs(unsigned short ModeIdIndex, - unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo) { unsigned short pushbx, tempax, tempbx, tempcx, temp, tempah, @@ -3735,10 +3726,10 @@ static void XGI_SetLCDRegs(unsigned short ModeIdIndex, /* Customized LCDB Does not add */ if ((pVBInfo->VBType & VB_SIS301LV) || (pVBInfo->VBType & VB_SIS302LV)) LCDBDesPtr = XGI_GetLcdPtr(xgifb_lcddldes, ModeIdIndex, - RefreshRateTableIndex, pVBInfo); + pVBInfo); else LCDBDesPtr = XGI_GetLcdPtr(XGI_LCDDesDataTable, ModeIdIndex, - RefreshRateTableIndex, pVBInfo); + pVBInfo); tempah = pVBInfo->LCDResInfo; tempah &= PanelResInfo; @@ -5190,10 +5181,9 @@ static void XGI_SetLCDAGroup(unsigned short ModeNo, unsigned short ModeIdIndex, RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo, ModeIdIndex, pVBInfo); XGI_GetLVDSResInfo(ModeIdIndex, pVBInfo); - XGI_GetLVDSData(ModeIdIndex, RefreshRateTableIndex, pVBInfo); - XGI_ModCRT1Regs(ModeIdIndex, RefreshRateTableIndex, HwDeviceExtension, - pVBInfo); - XGI_SetLVDSRegs(ModeIdIndex, RefreshRateTableIndex, pVBInfo); + XGI_GetLVDSData(ModeIdIndex, pVBInfo); + XGI_ModCRT1Regs(ModeIdIndex, HwDeviceExtension, pVBInfo); + XGI_SetLVDSRegs(ModeIdIndex, pVBInfo); XGI_SetCRT2ECLK(ModeIdIndex, RefreshRateTableIndex, pVBInfo); } @@ -5213,9 +5203,9 @@ static unsigned char XGI_SetCRT2Group301(unsigned short ModeNo, XGI_GetCRT2Data(ModeIdIndex, RefreshRateTableIndex, pVBInfo); XGI_PreSetGroup1(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo); XGI_SetGroup1(ModeIdIndex, RefreshRateTableIndex, pVBInfo); - XGI_SetLockRegs(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo); - XGI_SetGroup2(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo); - XGI_SetLCDRegs(ModeIdIndex, RefreshRateTableIndex, pVBInfo); + XGI_SetLockRegs(ModeNo, ModeIdIndex, pVBInfo); + XGI_SetGroup2(ModeNo, ModeIdIndex, pVBInfo); + XGI_SetLCDRegs(ModeIdIndex, pVBInfo); XGI_SetTap4Regs(pVBInfo); XGI_SetGroup3(ModeIdIndex, pVBInfo); XGI_SetGroup4(ModeIdIndex, RefreshRateTableIndex, pVBInfo); From 334ab0728d7b6e333a07a7c28d6b7bb25ad8b220 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 16 Jul 2013 23:13:30 +0300 Subject: [PATCH 0425/3400] staging: xgifb: delete unused "pVBInfo" parameters Delete unused "pVBInfo" parameters from internal functions. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/XGI_main_26.c | 4 ++-- drivers/staging/xgifb/vb_init.c | 5 ++--- drivers/staging/xgifb/vb_setmode.c | 25 ++++++++++--------------- drivers/staging/xgifb/vb_setmode.h | 3 +-- 4 files changed, 15 insertions(+), 22 deletions(-) diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index 015d7bbccf86..3b3e17d3f6f5 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -68,7 +68,7 @@ static int XGIfb_mode_rate_to_dclock(struct vb_device_info *XGI_Pr, int Clock; InitTo330Pointer(HwDeviceExtension->jChipType, XGI_Pr); - XGI_SearchModeID(ModeNo, &ModeIdIndex, XGI_Pr); + XGI_SearchModeID(ModeNo, &ModeIdIndex); RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo, ModeIdIndex, XGI_Pr); @@ -96,7 +96,7 @@ static int XGIfb_mode_rate_to_ddata(struct vb_device_info *XGI_Pr, unsigned char sr_data, cr_data, cr_data2; int B, C, D, F, temp, j; InitTo330Pointer(HwDeviceExtension->jChipType, XGI_Pr); - if (!XGI_SearchModeID(ModeNo, &ModeIdIndex, XGI_Pr)) + if (!XGI_SearchModeID(ModeNo, &ModeIdIndex)) return 0; RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo, ModeIdIndex, XGI_Pr); diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c index 506b7fe9c20d..21541720e05c 100644 --- a/drivers/staging/xgifb/vb_init.c +++ b/drivers/staging/xgifb/vb_init.c @@ -874,8 +874,7 @@ done: return rom_copy; } -static bool xgifb_read_vbios(struct pci_dev *pdev, - struct vb_device_info *pVBInfo) +static bool xgifb_read_vbios(struct pci_dev *pdev) { struct xgifb_video_info *xgifb_info = pci_get_drvdata(pdev); u8 *vbios; @@ -1098,7 +1097,7 @@ static void XGINew_GetXG21Sense(struct pci_dev *pdev, struct xgifb_video_info *xgifb_info = pci_get_drvdata(pdev); unsigned char Temp; - if (xgifb_read_vbios(pdev, pVBInfo)) { /* For XG21 LVDS */ + if (xgifb_read_vbios(pdev)) { /* For XG21 LVDS */ xgifb_reg_or(pVBInfo->P3d4, 0x32, LCDSense); /* LVDS on chip */ xgifb_reg_and_or(pVBInfo->P3d4, 0x38, ~0xE0, 0xC0); diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index 7228d171d31e..46dea3f10888 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -2164,7 +2164,7 @@ static unsigned char XGI_GetLCDInfo(unsigned short ModeIdIndex, } unsigned char XGI_SearchModeID(unsigned short ModeNo, - unsigned short *ModeIdIndex, struct vb_device_info *pVBInfo) + unsigned short *ModeIdIndex) { for (*ModeIdIndex = 0;; (*ModeIdIndex)++) { if (XGI330_EModeIDTable[*ModeIdIndex].Ext_ModeID == ModeNo) @@ -2715,8 +2715,7 @@ static void XGI_SetCRT2VCLK(unsigned short ModeIdIndex, xgifb_reg_or(pVBInfo->Part4Port, 0x12, 0x08); } -static unsigned short XGI_GetColorDepth(unsigned short ModeIdIndex, - struct vb_device_info *pVBInfo) +static unsigned short XGI_GetColorDepth(unsigned short ModeIdIndex) { unsigned short ColorDepth[6] = { 1, 2, 4, 4, 6, 8 }; short index; @@ -2733,8 +2732,7 @@ static unsigned short XGI_GetColorDepth(unsigned short ModeIdIndex, static unsigned short XGI_GetOffset(unsigned short ModeNo, unsigned short ModeIdIndex, - unsigned short RefreshRateTableIndex, - struct vb_device_info *pVBInfo) + unsigned short RefreshRateTableIndex) { unsigned short temp, colordepth, modeinfo, index, infoflag, ColorDepth[] = { 0x01, 0x02, 0x04 }; @@ -2749,7 +2747,7 @@ static unsigned short XGI_GetOffset(unsigned short ModeNo, if (infoflag & InterlaceMode) temp = temp << 1; - colordepth = XGI_GetColorDepth(ModeIdIndex, pVBInfo); + colordepth = XGI_GetColorDepth(ModeIdIndex); if ((ModeNo >= 0x7C) && (ModeNo <= 0x7E)) { temp = ModeNo - 0x7C; @@ -2772,8 +2770,7 @@ static void XGI_SetCRT2Offset(unsigned short ModeNo, if (pVBInfo->VBInfo & SetInSlaveMode) return; - offset = XGI_GetOffset(ModeNo, ModeIdIndex, RefreshRateTableIndex, - pVBInfo); + offset = XGI_GetOffset(ModeNo, ModeIdIndex, RefreshRateTableIndex); temp = (unsigned char) (offset & 0xFF); xgifb_reg_set(pVBInfo->Part1Port, 0x07, temp); temp = (unsigned char) ((offset & 0xFF00) >> 8); @@ -4199,8 +4196,7 @@ static void XGI_DisableGatingCRT(struct vb_device_info *pVBInfo) } static unsigned char XGI_XG21CheckLVDSMode(struct xgifb_video_info *xgifb_info, - unsigned short ModeNo, unsigned short ModeIdIndex, - struct vb_device_info *pVBInfo) + unsigned short ModeNo, unsigned short ModeIdIndex) { unsigned short xres, yres, colordepth, modeflag, resindex; @@ -4229,7 +4225,7 @@ static unsigned char XGI_XG21CheckLVDSMode(struct xgifb_video_info *xgifb_info, if (xres != xgifb_info->lvds_data.LVDSHDE || yres != xgifb_info->lvds_data.LVDSVDE) { - colordepth = XGI_GetColorDepth(ModeIdIndex, pVBInfo); + colordepth = XGI_GetColorDepth(ModeIdIndex); if (colordepth > 2) return 0; } @@ -5194,7 +5190,7 @@ static unsigned char XGI_SetCRT2Group301(unsigned short ModeNo, unsigned short ModeIdIndex, RefreshRateTableIndex; pVBInfo->SetFlag |= ProgrammingCRT2; - XGI_SearchModeID(ModeNo, &ModeIdIndex, pVBInfo); + XGI_SearchModeID(ModeNo, &ModeIdIndex); pVBInfo->SelectCRT2Rate = 4; RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo, ModeIdIndex, pVBInfo); @@ -5494,7 +5490,7 @@ unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info, if (HwDeviceExtension->jChipType < XG20) XGI_UnLockCRT2(pVBInfo); - XGI_SearchModeID(ModeNo, &ModeIdIndex, pVBInfo); + XGI_SearchModeID(ModeNo, &ModeIdIndex); if (HwDeviceExtension->jChipType < XG20) { XGI_GetVBInfo(ModeIdIndex, pVBInfo); @@ -5533,8 +5529,7 @@ unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info, else { if (pVBInfo->IF_DEF_LVDS == 1) if (!XGI_XG21CheckLVDSMode(xgifb_info, ModeNo, - ModeIdIndex, - pVBInfo)) + ModeIdIndex)) return 0; pVBInfo->ModeType = XGI330_EModeIDTable[ModeIdIndex]. diff --git a/drivers/staging/xgifb/vb_setmode.h b/drivers/staging/xgifb/vb_setmode.h index 3170dd384392..f67d9478f768 100644 --- a/drivers/staging/xgifb/vb_setmode.h +++ b/drivers/staging/xgifb/vb_setmode.h @@ -14,8 +14,7 @@ extern unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info, unsigned short ModeNo) ; extern unsigned char XGI_SearchModeID(unsigned short ModeNo, - unsigned short *ModeIdIndex, - struct vb_device_info *); + unsigned short *ModeIdIndex); extern unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE, unsigned short ModeNo, unsigned short ModeIdIndex, From 04948a34698ddfa8823148b3a357cf3438e1433b Mon Sep 17 00:00:00 2001 From: Anthony Foiani Date: Mon, 8 Jul 2013 00:52:40 -0600 Subject: [PATCH 0426/3400] staging: usbip: clean up checkpatch warnings in usbipd.c A few whitespace changes allows the file to pass checkpatch --strict (other than ignoring the CamelCase derived from the USB standard.) Signed-Off-By: Anthony Foiani Signed-off-by: Greg Kroah-Hartman --- drivers/staging/usbip/userspace/src/usbipd.c | 31 ++++++++++---------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/drivers/staging/usbip/userspace/src/usbipd.c b/drivers/staging/usbip/userspace/src/usbipd.c index 3e913b861dc2..9d3824133e85 100644 --- a/drivers/staging/usbip/userspace/src/usbipd.c +++ b/drivers/staging/usbip/userspace/src/usbipd.c @@ -53,18 +53,18 @@ static const char usbip_version_string[] = PACKAGE_STRING; static const char usbipd_help_string[] = - "usage: usbipd [options] \n" - " -D, --daemon \n" - " Run as a daemon process. \n" - " \n" - " -d, --debug \n" - " Print debugging information. \n" - " \n" - " -h, --help \n" - " Print this help. \n" - " \n" - " -v, --version \n" - " Show version. \n"; + "usage: usbipd [options]\n" + " -D, --daemon\n" + " Run as a daemon process.\n" + "\n" + " -d, --debug\n" + " Print debugging information.\n" + "\n" + " -h, --help\n" + " Print this help.\n" + "\n" + " -v, --version\n" + " Show version.\n"; static void usbipd_help(void) { @@ -286,13 +286,13 @@ static int do_accept(int listenfd) memset(&ss, 0, sizeof(ss)); - connfd = accept(listenfd, (struct sockaddr *) &ss, &len); + connfd = accept(listenfd, (struct sockaddr *)&ss, &len); if (connfd < 0) { err("failed to accept connection"); return -1; } - rc = getnameinfo((struct sockaddr *) &ss, len, host, sizeof(host), + rc = getnameinfo((struct sockaddr *)&ss, len, host, sizeof(host), port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV); if (rc) err("getnameinfo: %s", gai_strerror(rc)); @@ -496,8 +496,9 @@ static int do_standalone_mode(int daemonize) process_request(sockfdlist[i]); } } - } else + } else { dbg("heartbeat timeout on ppoll()"); + } } info("shutting down " PROGNAME); From 2568dd1b6b800dd0fdff5aa997cf7d0c46c19ffe Mon Sep 17 00:00:00 2001 From: Anthony Foiani Date: Mon, 8 Jul 2013 00:52:41 -0600 Subject: [PATCH 0427/3400] staging: usbip: use local variable while setting up socket Using a simple integer makes the code easier to read and removes the need to blank out array elements in case of errors. Signed-Off-By: Anthony Foiani Signed-off-by: Greg Kroah-Hartman --- drivers/staging/usbip/userspace/src/usbipd.c | 27 +++++++++----------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/drivers/staging/usbip/userspace/src/usbipd.c b/drivers/staging/usbip/userspace/src/usbipd.c index 9d3824133e85..d833e7b5fdf9 100644 --- a/drivers/staging/usbip/userspace/src/usbipd.c +++ b/drivers/staging/usbip/userspace/src/usbipd.c @@ -348,36 +348,33 @@ static int listen_all_addrinfo(struct addrinfo *ai_head, int sockfdlist[]) int ret, nsockfd = 0; for (ai = ai_head; ai && nsockfd < MAXSOCKFD; ai = ai->ai_next) { - sockfdlist[nsockfd] = socket(ai->ai_family, ai->ai_socktype, - ai->ai_protocol); - if (sockfdlist[nsockfd] < 0) + int sock = socket(ai->ai_family, ai->ai_socktype, + ai->ai_protocol); + if (sock < 0) continue; - usbip_net_set_reuseaddr(sockfdlist[nsockfd]); - usbip_net_set_nodelay(sockfdlist[nsockfd]); + usbip_net_set_reuseaddr(sock); + usbip_net_set_nodelay(sock); - if (sockfdlist[nsockfd] >= FD_SETSIZE) { - close(sockfdlist[nsockfd]); - sockfdlist[nsockfd] = -1; + if (sock >= FD_SETSIZE) { + close(sock); continue; } - ret = bind(sockfdlist[nsockfd], ai->ai_addr, ai->ai_addrlen); + ret = bind(sock, ai->ai_addr, ai->ai_addrlen); if (ret < 0) { - close(sockfdlist[nsockfd]); - sockfdlist[nsockfd] = -1; + close(sock); continue; } - ret = listen(sockfdlist[nsockfd], SOMAXCONN); + ret = listen(sock, SOMAXCONN); if (ret < 0) { - close(sockfdlist[nsockfd]); - sockfdlist[nsockfd] = -1; + close(sock); continue; } log_addrinfo(ai); - nsockfd++; + sockfdlist[nsockfd++] = sock; } if (nsockfd == 0) From a159d620b0d9a2095616be4e98d10654ad386c11 Mon Sep 17 00:00:00 2001 From: Anthony Foiani Date: Mon, 8 Jul 2013 00:52:42 -0600 Subject: [PATCH 0428/3400] staging: usbip: improve error reporting Give useful error messages when we can't create server sockets. Signed-Off-By: Anthony Foiani Signed-off-by: Greg Kroah-Hartman --- drivers/staging/usbip/userspace/src/usbipd.c | 28 +++++++++++++++----- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/drivers/staging/usbip/userspace/src/usbipd.c b/drivers/staging/usbip/userspace/src/usbipd.c index d833e7b5fdf9..1ecca9dd9945 100644 --- a/drivers/staging/usbip/userspace/src/usbipd.c +++ b/drivers/staging/usbip/userspace/src/usbipd.c @@ -328,52 +328,68 @@ int process_request(int listenfd) return 0; } -static void log_addrinfo(struct addrinfo *ai) +static void addrinfo_to_text(struct addrinfo *ai, char buf[], + const size_t buf_size) { char hbuf[NI_MAXHOST]; char sbuf[NI_MAXSERV]; int rc; + buf[0] = '\0'; + rc = getnameinfo(ai->ai_addr, ai->ai_addrlen, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV); if (rc) err("getnameinfo: %s", gai_strerror(rc)); - info("listening on %s:%s", hbuf, sbuf); + snprintf(buf, buf_size, "%s:%s", hbuf, sbuf); } static int listen_all_addrinfo(struct addrinfo *ai_head, int sockfdlist[]) { struct addrinfo *ai; int ret, nsockfd = 0; + const size_t ai_buf_size = NI_MAXHOST + NI_MAXSERV + 2; + char ai_buf[ai_buf_size]; for (ai = ai_head; ai && nsockfd < MAXSOCKFD; ai = ai->ai_next) { - int sock = socket(ai->ai_family, ai->ai_socktype, - ai->ai_protocol); - if (sock < 0) + int sock; + addrinfo_to_text(ai, ai_buf, ai_buf_size); + dbg("opening %s", ai_buf); + sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + if (sock < 0) { + err("socket: %s: %d (%s)", + ai_buf, errno, strerror(errno)); continue; + } usbip_net_set_reuseaddr(sock); usbip_net_set_nodelay(sock); if (sock >= FD_SETSIZE) { + err("FD_SETSIZE: %s: sock=%d, max=%d", + ai_buf, sock, FD_SETSIZE); close(sock); continue; } ret = bind(sock, ai->ai_addr, ai->ai_addrlen); if (ret < 0) { + err("bind: %s: %d (%s)", + ai_buf, errno, strerror(errno)); close(sock); continue; } ret = listen(sock, SOMAXCONN); if (ret < 0) { + err("listen: %s: %d (%s)", + ai_buf, errno, strerror(errno)); close(sock); continue; } - log_addrinfo(ai); + info("listening on %s", ai_buf); sockfdlist[nsockfd++] = sock; } From 457163c4c7c69ee7f92c31bd48be332316824a14 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 26 Jun 2013 16:30:38 -0700 Subject: [PATCH 0429/3400] USB: ldusb: remove custom dbg_info() macro We want to get rid of CONFIG_USB_DEBUG, so remove the reliance of the ldusb driver on it. Don't use the custom macro, or a special module parameter, instead, rely on the in-kernel dynamic debugging infrastructure, which is much easier to use, and consistant across the whole kernel. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/ldusb.c | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c index ac762299eaa8..b1d59532ac22 100644 --- a/drivers/usb/misc/ldusb.c +++ b/drivers/usb/misc/ldusb.c @@ -129,19 +129,6 @@ MODULE_DESCRIPTION("LD USB Driver"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("LD USB Devices"); -#ifdef CONFIG_USB_DEBUG - static int debug = 1; -#else - static int debug = 0; -#endif - -/* Use our own dbg macro */ -#define dbg_info(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0) - -/* Module parameters */ -module_param(debug, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); - /* All interrupt in transfers are collected in a ring buffer to * avoid racing conditions and get better performance of the driver. */ @@ -256,8 +243,9 @@ static void ld_usb_interrupt_in_callback(struct urb *urb) status == -ESHUTDOWN) { goto exit; } else { - dbg_info(&dev->intf->dev, "%s: nonzero status received: %d\n", - __func__, status); + dev_dbg(&dev->intf->dev, + "%s: nonzero status received: %d\n", __func__, + status); spin_lock(&dev->rbsl); goto resubmit; /* maybe we can recover */ } @@ -272,8 +260,8 @@ static void ld_usb_interrupt_in_callback(struct urb *urb) *actual_buffer = urb->actual_length; memcpy(actual_buffer+1, dev->interrupt_in_buffer, urb->actual_length); dev->ring_head = next_ring_head; - dbg_info(&dev->intf->dev, "%s: received %d bytes\n", - __func__, urb->actual_length); + dev_dbg(&dev->intf->dev, "%s: received %d bytes\n", + __func__, urb->actual_length); } else { dev_warn(&dev->intf->dev, "Ring buffer overflow, %d bytes dropped\n", @@ -310,9 +298,9 @@ static void ld_usb_interrupt_out_callback(struct urb *urb) if (status && !(status == -ENOENT || status == -ECONNRESET || status == -ESHUTDOWN)) - dbg_info(&dev->intf->dev, - "%s - nonzero write interrupt status received: %d\n", - __func__, status); + dev_dbg(&dev->intf->dev, + "%s - nonzero write interrupt status received: %d\n", + __func__, status); dev->interrupt_out_busy = 0; wake_up_interruptible(&dev->write_wait); @@ -585,7 +573,8 @@ static ssize_t ld_usb_write(struct file *file, const char __user *buffer, bytes_to_write = min(count, write_buffer_size*dev->interrupt_out_endpoint_size); if (bytes_to_write < count) dev_warn(&dev->intf->dev, "Write buffer overflow, %zd bytes dropped\n",count-bytes_to_write); - dbg_info(&dev->intf->dev, "%s: count = %zd, bytes_to_write = %zd\n", __func__, count, bytes_to_write); + dev_dbg(&dev->intf->dev, "%s: count = %zd, bytes_to_write = %zd\n", + __func__, count, bytes_to_write); if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write)) { retval = -EFAULT; From d26f6e57e71169bab907bdf716021b2d19bd09f0 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 26 Jun 2013 16:30:39 -0700 Subject: [PATCH 0430/3400] USB: legotower: remove unneeded tracing macros Remove the unneeded tracing macros in this driver. The kernel has a built-in trace function that can be used if this is really still needed. Cc: Juergen Stuber Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/legousbtower.c | 42 +-------------------------------- 1 file changed, 1 insertion(+), 41 deletions(-) diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index 80894791c020..93c95d09f04e 100644 --- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c @@ -318,8 +318,6 @@ static inline void lego_usb_tower_debug_data (int level, const char *function, i */ static inline void tower_delete (struct lego_usb_tower *dev) { - dbg(2, "%s: enter", __func__); - tower_abort_transfers (dev); /* free data structures */ @@ -329,8 +327,6 @@ static inline void tower_delete (struct lego_usb_tower *dev) kfree (dev->interrupt_in_buffer); kfree (dev->interrupt_out_buffer); kfree (dev); - - dbg(2, "%s: leave", __func__); } @@ -346,8 +342,6 @@ static int tower_open (struct inode *inode, struct file *file) struct tower_reset_reply reset_reply; int result; - dbg(2, "%s: enter", __func__); - nonseekable_open(inode, file); subminor = iminor(inode); @@ -435,8 +429,6 @@ unlock_exit: mutex_unlock(&dev->lock); exit: - dbg(2, "%s: leave, return value %d ", __func__, retval); - return retval; } @@ -448,8 +440,6 @@ static int tower_release (struct inode *inode, struct file *file) struct lego_usb_tower *dev; int retval = 0; - dbg(2, "%s: enter", __func__); - dev = file->private_data; if (dev == NULL) { @@ -491,7 +481,6 @@ unlock_exit: exit: mutex_unlock(&open_disc_mutex); exit_nolock: - dbg(2, "%s: leave, return value %d", __func__, retval); return retval; } @@ -502,11 +491,9 @@ exit_nolock: */ static void tower_abort_transfers (struct lego_usb_tower *dev) { - dbg(2, "%s: enter", __func__); - if (dev == NULL) { dbg(1, "%s: dev is null", __func__); - goto exit; + return; } /* shutdown transfer */ @@ -518,9 +505,6 @@ static void tower_abort_transfers (struct lego_usb_tower *dev) } if (dev->interrupt_out_busy && dev->udev) usb_kill_urb(dev->interrupt_out_urb); - -exit: - dbg(2, "%s: leave", __func__); } @@ -553,8 +537,6 @@ static unsigned int tower_poll (struct file *file, poll_table *wait) struct lego_usb_tower *dev; unsigned int mask = 0; - dbg(2, "%s: enter", __func__); - dev = file->private_data; if (!dev->udev) @@ -571,8 +553,6 @@ static unsigned int tower_poll (struct file *file, poll_table *wait) mask |= POLLOUT | POLLWRNORM; } - dbg(2, "%s: leave, mask = %d", __func__, mask); - return mask; } @@ -597,8 +577,6 @@ static ssize_t tower_read (struct file *file, char __user *buffer, size_t count, int retval = 0; unsigned long timeout = 0; - dbg(2, "%s: enter, count = %Zd", __func__, count); - dev = file->private_data; /* lock this object */ @@ -672,7 +650,6 @@ unlock_exit: mutex_unlock(&dev->lock); exit: - dbg(2, "%s: leave, return value %d", __func__, retval); return retval; } @@ -686,8 +663,6 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t size_t bytes_to_write; int retval = 0; - dbg(2, "%s: enter, count = %Zd", __func__, count); - dev = file->private_data; /* lock this object */ @@ -757,8 +732,6 @@ unlock_exit: mutex_unlock(&dev->lock); exit: - dbg(2, "%s: leave, return value %d", __func__, retval); - return retval; } @@ -772,8 +745,6 @@ static void tower_interrupt_in_callback (struct urb *urb) int status = urb->status; int retval; - dbg(4, "%s: enter, status %d", __func__, status); - lego_usb_tower_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer); if (status) { @@ -817,7 +788,6 @@ exit: wake_up_interruptible (&dev->read_wait); lego_usb_tower_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer); - dbg(4, "%s: leave, status %d", __func__, status); } @@ -829,7 +799,6 @@ static void tower_interrupt_out_callback (struct urb *urb) struct lego_usb_tower *dev = urb->context; int status = urb->status; - dbg(4, "%s: enter, status %d", __func__, status); lego_usb_tower_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer); /* sync/async unlink faults aren't errors */ @@ -844,7 +813,6 @@ static void tower_interrupt_out_callback (struct urb *urb) wake_up_interruptible(&dev->write_wait); lego_usb_tower_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer); - dbg(4, "%s: leave, status %d", __func__, status); } @@ -866,8 +834,6 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device int retval = -ENOMEM; int result; - dbg(2, "%s: enter", __func__); - /* allocate memory for our device state and initialize it */ dev = kmalloc (sizeof(struct lego_usb_tower), GFP_KERNEL); @@ -993,8 +959,6 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device exit: - dbg(2, "%s: leave, return value 0x%.8lx (dev)", __func__, (long) dev); - return retval; error: @@ -1013,8 +977,6 @@ static void tower_disconnect (struct usb_interface *interface) struct lego_usb_tower *dev; int minor; - dbg(2, "%s: enter", __func__); - dev = usb_get_intfdata (interface); mutex_lock(&open_disc_mutex); usb_set_intfdata (interface, NULL); @@ -1041,8 +1003,6 @@ static void tower_disconnect (struct usb_interface *interface) dev_info(&interface->dev, "LEGO USB Tower #%d now disconnected\n", (minor - LEGO_USB_TOWER_MINOR_BASE)); - - dbg(2, "%s: leave", __func__); } module_usb_driver(tower_driver); From fef526cae700471ba37279e41b88e1c3bfdda1b9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 26 Jun 2013 16:30:40 -0700 Subject: [PATCH 0431/3400] USB: legousbtower: remove custom debug macro Don't use a custom debug macro for just one driver, instead rely on the in-kernel dynamic debugging logic, which can handle this much better. Cc: Juergen Stuber Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/legousbtower.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index 93c95d09f04e..4a5a8b16d7b5 100644 --- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c @@ -443,7 +443,6 @@ static int tower_release (struct inode *inode, struct file *file) dev = file->private_data; if (dev == NULL) { - dbg(1, "%s: object is NULL", __func__); retval = -ENODEV; goto exit_nolock; } @@ -455,7 +454,8 @@ static int tower_release (struct inode *inode, struct file *file) } if (dev->open_count != 1) { - dbg(1, "%s: device not opened exactly once", __func__); + dev_dbg(&dev->udev->dev, "%s: device not opened exactly once\n", + __func__); retval = -ENODEV; goto unlock_exit; } @@ -491,10 +491,8 @@ exit_nolock: */ static void tower_abort_transfers (struct lego_usb_tower *dev) { - if (dev == NULL) { - dbg(1, "%s: dev is null", __func__); + if (dev == NULL) return; - } /* shutdown transfer */ if (dev->interrupt_in_running) { @@ -594,7 +592,7 @@ static ssize_t tower_read (struct file *file, char __user *buffer, size_t count, /* verify that we actually have some data to read */ if (count == 0) { - dbg(1, "%s: read request of 0 bytes", __func__); + dev_dbg(&dev->udev->dev, "read request of 0 bytes\n"); goto unlock_exit; } @@ -680,7 +678,7 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t /* verify that we actually have some data to write */ if (count == 0) { - dbg(1, "%s: write request of 0 bytes", __func__); + dev_dbg(&dev->udev->dev, "write request of 0 bytes\n"); goto unlock_exit; } @@ -698,7 +696,8 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t /* write the data into interrupt_out_buffer from userspace */ bytes_to_write = min_t(int, count, write_buffer_size); - dbg(4, "%s: count = %Zd, bytes_to_write = %Zd", __func__, count, bytes_to_write); + dev_dbg(&dev->udev->dev, "%s: count = %Zd, bytes_to_write = %Zd\n", + __func__, count, bytes_to_write); if (copy_from_user (dev->interrupt_out_buffer, buffer, bytes_to_write)) { retval = -EFAULT; @@ -753,7 +752,9 @@ static void tower_interrupt_in_callback (struct urb *urb) status == -ESHUTDOWN) { goto exit; } else { - dbg(1, "%s: nonzero status received: %d", __func__, status); + dev_dbg(&dev->udev->dev, + "%s: nonzero status received: %d\n", __func__, + status); goto resubmit; /* maybe we can recover */ } } @@ -766,7 +767,8 @@ static void tower_interrupt_in_callback (struct urb *urb) urb->actual_length); dev->read_buffer_length += urb->actual_length; dev->read_last_arrival = jiffies; - dbg(3, "%s: received %d bytes", __func__, urb->actual_length); + dev_dbg(&dev->udev->dev, "%s: received %d bytes\n", + __func__, urb->actual_length); } else { printk(KERN_WARNING "%s: read_buffer overflow, %d bytes dropped", __func__, urb->actual_length); } @@ -805,8 +807,9 @@ static void tower_interrupt_out_callback (struct urb *urb) if (status && !(status == -ENOENT || status == -ECONNRESET || status == -ESHUTDOWN)) { - dbg(1, "%s - nonzero write bulk status received: %d", - __func__, status); + dev_dbg(&dev->udev->dev, + "%s: nonzero write bulk status received: %d\n", __func__, + status); } dev->interrupt_out_busy = 0; From 4dae99638097b254c863c541368598f5a80e41bf Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 26 Jun 2013 16:30:41 -0700 Subject: [PATCH 0432/3400] USB: legotower: remove custom debug macro and module parameter Now that we don't use the dbg() macro, remove it, and the module parameter. Also fix up the "dump_data" function to properly use the dynamic debug core and the correct printk options, and don't call it twice per function, as the data doesn't change from the beginning and the end of the call. Cc: Juergen Stuber Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/legousbtower.c | 43 +++++++-------------------------- 1 file changed, 9 insertions(+), 34 deletions(-) diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index 4a5a8b16d7b5..6df99dc4fe87 100644 --- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c @@ -87,28 +87,11 @@ #include -#ifdef CONFIG_USB_DEBUG - static int debug = 4; -#else - static int debug = 0; -#endif - -/* Use our own dbg macro */ -#undef dbg -#define dbg(lvl, format, arg...) \ -do { \ - if (debug >= lvl) \ - printk(KERN_DEBUG "%s: " format "\n", __FILE__, ##arg); \ -} while (0) - /* Version Information */ #define DRIVER_VERSION "v0.96" #define DRIVER_AUTHOR "Juergen Stuber " #define DRIVER_DESC "LEGO USB Tower Driver" -/* Module parameters */ -module_param(debug, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); /* The defaults are chosen to work with the latest versions of leJOS and NQC. */ @@ -298,18 +281,12 @@ static struct usb_driver tower_driver = { /** * lego_usb_tower_debug_data */ -static inline void lego_usb_tower_debug_data (int level, const char *function, int size, const unsigned char *data) +static inline void lego_usb_tower_debug_data(struct device *dev, + const char *function, int size, + const unsigned char *data) { - int i; - - if (debug < level) - return; - - printk (KERN_DEBUG "%s: %s - length = %d, data = ", __FILE__, function, size); - for (i = 0; i < size; ++i) { - printk ("%.2x ", data[i]); - } - printk ("\n"); + dev_dbg(dev, "%s - length = %d, data = %*ph\n", + function, size, size, data); } @@ -744,7 +721,8 @@ static void tower_interrupt_in_callback (struct urb *urb) int status = urb->status; int retval; - lego_usb_tower_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer); + lego_usb_tower_debug_data(&dev->udev->dev, __func__, + urb->actual_length, urb->transfer_buffer); if (status) { if (status == -ENOENT || @@ -788,8 +766,6 @@ resubmit: exit: dev->interrupt_in_done = 1; wake_up_interruptible (&dev->read_wait); - - lego_usb_tower_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer); } @@ -801,7 +777,8 @@ static void tower_interrupt_out_callback (struct urb *urb) struct lego_usb_tower *dev = urb->context; int status = urb->status; - lego_usb_tower_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer); + lego_usb_tower_debug_data(&dev->udev->dev, __func__, + urb->actual_length, urb->transfer_buffer); /* sync/async unlink faults aren't errors */ if (status && !(status == -ENOENT || @@ -814,8 +791,6 @@ static void tower_interrupt_out_callback (struct urb *urb) dev->interrupt_out_busy = 0; wake_up_interruptible(&dev->write_wait); - - lego_usb_tower_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer); } From 38726bf5417972ff51b8f047ab4e79f0333f2cf0 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 26 Jun 2013 16:30:42 -0700 Subject: [PATCH 0433/3400] USB: legotower: remove direct calls to printk() Use the pr_* calls instead, which are much more descriptive. Cc: Juergen Stuber Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/legousbtower.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index 6df99dc4fe87..eb37c9542052 100644 --- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c @@ -75,6 +75,8 @@ * - move reset into open to clean out spurious data */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -325,8 +327,7 @@ static int tower_open (struct inode *inode, struct file *file) interface = usb_find_interface (&tower_driver, subminor); if (!interface) { - printk(KERN_ERR "%s - error, can't find device for minor %d\n", - __func__, subminor); + pr_err("error, can't find device for minor %d\n", subminor); retval = -ENODEV; goto exit; } @@ -563,7 +564,7 @@ static ssize_t tower_read (struct file *file, char __user *buffer, size_t count, /* verify that the device wasn't unplugged */ if (dev->udev == NULL) { retval = -ENODEV; - printk(KERN_ERR "legousbtower: No device or device unplugged %d\n", retval); + pr_err("No device or device unplugged %d\n", retval); goto unlock_exit; } @@ -649,7 +650,7 @@ static ssize_t tower_write (struct file *file, const char __user *buffer, size_t /* verify that the device wasn't unplugged */ if (dev->udev == NULL) { retval = -ENODEV; - printk(KERN_ERR "legousbtower: No device or device unplugged %d\n", retval); + pr_err("No device or device unplugged %d\n", retval); goto unlock_exit; } @@ -748,7 +749,8 @@ static void tower_interrupt_in_callback (struct urb *urb) dev_dbg(&dev->udev->dev, "%s: received %d bytes\n", __func__, urb->actual_length); } else { - printk(KERN_WARNING "%s: read_buffer overflow, %d bytes dropped", __func__, urb->actual_length); + pr_warn("read_buffer overflow, %d bytes dropped\n", + urb->actual_length); } spin_unlock (&dev->read_buffer_lock); } From 6e42a15803ddbeb3a6f8f64bf599398a0ef5912b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 26 Jun 2013 16:30:43 -0700 Subject: [PATCH 0434/3400] USB: adutux: remove unneeded tracing macros Remove the unneeded tracing macros in this driver. The kernel has a built-in trace function that can be used if this is really still needed. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/adutux.c | 41 +-------------------------------------- 1 file changed, 1 insertion(+), 40 deletions(-) diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c index eb3c8c142fa9..e8a9e16789f5 100644 --- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c @@ -147,11 +147,9 @@ static void adu_abort_transfers(struct adu_device *dev) { unsigned long flags; - dbg(2, " %s : enter", __func__); - if (dev->udev == NULL) { dbg(1, " %s : udev is null", __func__); - goto exit; + return; } /* shutdown transfer */ @@ -170,15 +168,10 @@ static void adu_abort_transfers(struct adu_device *dev) usb_kill_urb(dev->interrupt_out_urb); } else spin_unlock_irqrestore(&dev->buflock, flags); - -exit: - dbg(2, " %s : leave", __func__); } static void adu_delete(struct adu_device *dev) { - dbg(2, "%s enter", __func__); - /* free data structures */ usb_free_urb(dev->interrupt_in_urb); usb_free_urb(dev->interrupt_out_urb); @@ -187,8 +180,6 @@ static void adu_delete(struct adu_device *dev) kfree(dev->interrupt_in_buffer); kfree(dev->interrupt_out_buffer); kfree(dev); - - dbg(2, "%s : leave", __func__); } static void adu_interrupt_in_callback(struct urb *urb) @@ -196,7 +187,6 @@ static void adu_interrupt_in_callback(struct urb *urb) struct adu_device *dev = urb->context; int status = urb->status; - dbg(4, " %s : enter, status %d", __func__, status); adu_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer); @@ -234,7 +224,6 @@ exit: wake_up_interruptible(&dev->read_wait); adu_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer); - dbg(4, " %s : leave, status %d", __func__, status); } static void adu_interrupt_out_callback(struct urb *urb) @@ -242,7 +231,6 @@ static void adu_interrupt_out_callback(struct urb *urb) struct adu_device *dev = urb->context; int status = urb->status; - dbg(4, " %s : enter, status %d", __func__, status); adu_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer); if (status != 0) { @@ -262,7 +250,6 @@ exit: adu_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer); - dbg(4, " %s : leave, status %d", __func__, status); } static int adu_open(struct inode *inode, struct file *file) @@ -272,8 +259,6 @@ static int adu_open(struct inode *inode, struct file *file) int subminor; int retval; - dbg(2, "%s : enter", __func__); - subminor = iminor(inode); retval = mutex_lock_interruptible(&adutux_mutex); @@ -333,14 +318,11 @@ static int adu_open(struct inode *inode, struct file *file) exit_no_device: mutex_unlock(&adutux_mutex); exit_no_lock: - dbg(2, "%s : leave, return value %d ", __func__, retval); return retval; } static void adu_release_internal(struct adu_device *dev) { - dbg(2, " %s : enter", __func__); - /* decrement our usage count for the device */ --dev->open_count; dbg(2, " %s : open count %d", __func__, dev->open_count); @@ -348,8 +330,6 @@ static void adu_release_internal(struct adu_device *dev) adu_abort_transfers(dev); dev->open_count = 0; } - - dbg(2, " %s : leave", __func__); } static int adu_release(struct inode *inode, struct file *file) @@ -357,8 +337,6 @@ static int adu_release(struct inode *inode, struct file *file) struct adu_device *dev; int retval = 0; - dbg(2, " %s : enter", __func__); - if (file == NULL) { dbg(1, " %s : file is NULL", __func__); retval = -ENODEV; @@ -389,7 +367,6 @@ static int adu_release(struct inode *inode, struct file *file) unlock: mutex_unlock(&adutux_mutex); exit: - dbg(2, " %s : leave, return value %d", __func__, retval); return retval; } @@ -406,11 +383,7 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, unsigned long flags; DECLARE_WAITQUEUE(wait, current); - dbg(2, " %s : enter, count = %Zd, file=%p", __func__, count, file); - dev = file->private_data; - dbg(2, " %s : dev=%p", __func__, dev); - if (mutex_lock_interruptible(&dev->mtx)) return -ERESTARTSYS; @@ -552,7 +525,6 @@ exit: /* unlock the device */ mutex_unlock(&dev->mtx); - dbg(2, " %s : leave, return value %d", __func__, retval); return retval; } @@ -567,8 +539,6 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, unsigned long flags; int retval; - dbg(2, " %s : enter, count = %Zd", __func__, count); - dev = file->private_data; retval = mutex_lock_interruptible(&dev->mtx); @@ -665,7 +635,6 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, exit: mutex_unlock(&dev->mtx); exit_nolock: - dbg(2, " %s : leave, return value %d", __func__, retval); return retval; exit_onqueue: @@ -711,8 +680,6 @@ static int adu_probe(struct usb_interface *interface, int out_end_size; int i; - dbg(2, " %s : enter", __func__); - if (udev == NULL) { dev_err(&interface->dev, "udev is NULL.\n"); goto exit; @@ -833,8 +800,6 @@ static int adu_probe(struct usb_interface *interface, udev->descriptor.idProduct, dev->serial_number, (dev->minor - ADU_MINOR_BASE)); exit: - dbg(2, " %s : leave, return value %p (dev)", __func__, dev); - return retval; error: @@ -852,8 +817,6 @@ static void adu_disconnect(struct usb_interface *interface) struct adu_device *dev; int minor; - dbg(2, " %s : enter", __func__); - dev = usb_get_intfdata(interface); mutex_lock(&dev->mtx); /* not interruptible */ @@ -874,8 +837,6 @@ static void adu_disconnect(struct usb_interface *interface) dev_info(&interface->dev, "ADU device adutux%d now disconnected\n", (minor - ADU_MINOR_BASE)); - - dbg(2, " %s : leave", __func__); } /* usb specific object needed to register this driver with the usb subsystem */ From 66d4bc30d128e7c7ac4cf64aa78cb76e971cec5b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 26 Jun 2013 16:30:44 -0700 Subject: [PATCH 0435/3400] USB: adutux: remove custom debug macro Don't use a custom debug macro for just one driver, instead rely on the in-kernel dynamic debugging logic, which can handle this much better. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/adutux.c | 97 +++++++++++++++++++++++---------------- 1 file changed, 58 insertions(+), 39 deletions(-) diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c index e8a9e16789f5..885f99322a84 100644 --- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c @@ -147,10 +147,8 @@ static void adu_abort_transfers(struct adu_device *dev) { unsigned long flags; - if (dev->udev == NULL) { - dbg(1, " %s : udev is null", __func__); + if (dev->udev == NULL) return; - } /* shutdown transfer */ @@ -195,8 +193,9 @@ static void adu_interrupt_in_callback(struct urb *urb) if (status != 0) { if ((status != -ENOENT) && (status != -ECONNRESET) && (status != -ESHUTDOWN)) { - dbg(1, " %s : nonzero status received: %d", - __func__, status); + dev_dbg(&dev->udev->dev, + "%s : nonzero status received: %d\n", + __func__, status); } goto exit; } @@ -210,10 +209,11 @@ static void adu_interrupt_in_callback(struct urb *urb) dev->interrupt_in_buffer, urb->actual_length); dev->read_buffer_length += urb->actual_length; - dbg(2, " %s reading %d ", __func__, - urb->actual_length); + dev_dbg(&dev->udev->dev,"%s reading %d\n", __func__, + urb->actual_length); } else { - dbg(1, " %s : read_buffer overflow", __func__); + dev_dbg(&dev->udev->dev,"%s : read_buffer overflow\n", + __func__); } } @@ -236,8 +236,9 @@ static void adu_interrupt_out_callback(struct urb *urb) if (status != 0) { if ((status != -ENOENT) && (status != -ECONNRESET)) { - dbg(1, " %s :nonzero status received: %d", - __func__, status); + dev_dbg(&dev->udev->dev, + "%s :nonzero status received: %d\n", __func__, + status); } goto exit; } @@ -262,10 +263,8 @@ static int adu_open(struct inode *inode, struct file *file) subminor = iminor(inode); retval = mutex_lock_interruptible(&adutux_mutex); - if (retval) { - dbg(2, "%s : mutex lock failed", __func__); + if (retval) goto exit_no_lock; - } interface = usb_find_interface(&adu_driver, subminor); if (!interface) { @@ -288,7 +287,8 @@ static int adu_open(struct inode *inode, struct file *file) } ++dev->open_count; - dbg(2, "%s : open count %d", __func__, dev->open_count); + dev_dbg(&dev->udev->dev, "%s: open count %d\n", __func__, + dev->open_count); /* save device in the file's private structure */ file->private_data = dev; @@ -325,7 +325,8 @@ static void adu_release_internal(struct adu_device *dev) { /* decrement our usage count for the device */ --dev->open_count; - dbg(2, " %s : open count %d", __func__, dev->open_count); + dev_dbg(&dev->udev->dev, "%s : open count %d\n", __func__, + dev->open_count); if (dev->open_count <= 0) { adu_abort_transfers(dev); dev->open_count = 0; @@ -338,14 +339,12 @@ static int adu_release(struct inode *inode, struct file *file) int retval = 0; if (file == NULL) { - dbg(1, " %s : file is NULL", __func__); retval = -ENODEV; goto exit; } dev = file->private_data; if (dev == NULL) { - dbg(1, " %s : object is NULL", __func__); retval = -ENODEV; goto exit; } @@ -353,7 +352,7 @@ static int adu_release(struct inode *inode, struct file *file) mutex_lock(&adutux_mutex); /* not interruptible */ if (dev->open_count <= 0) { - dbg(1, " %s : device not opened", __func__); + dev_dbg(&dev->udev->dev, "%s : device not opened\n", __func__); retval = -ENODEV; goto unlock; } @@ -397,17 +396,19 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, /* verify that some data was requested */ if (count == 0) { - dbg(1, " %s : read request of 0 bytes", __func__); + dev_dbg(&dev->udev->dev, "%s : read request of 0 bytes\n", + __func__); goto exit; } timeout = COMMAND_TIMEOUT; - dbg(2, " %s : about to start looping", __func__); + dev_dbg(&dev->udev->dev, "%s : about to start looping\n", __func__); while (bytes_to_read) { int data_in_secondary = dev->secondary_tail - dev->secondary_head; - dbg(2, " %s : while, data_in_secondary=%d, status=%d", - __func__, data_in_secondary, - dev->interrupt_in_urb->status); + dev_dbg(&dev->udev->dev, + "%s : while, data_in_secondary=%d, status=%d\n", + __func__, data_in_secondary, + dev->interrupt_in_urb->status); if (data_in_secondary) { /* drain secondary buffer */ @@ -430,8 +431,9 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, if (dev->read_buffer_length) { /* we secure access to the primary */ char *tmp; - dbg(2, " %s : swap, read_buffer_length = %d", - __func__, dev->read_buffer_length); + dev_dbg(&dev->udev->dev, + "%s : swap, read_buffer_length = %d\n", + __func__, dev->read_buffer_length); tmp = dev->read_buffer_secondary; dev->read_buffer_secondary = dev->read_buffer_primary; dev->read_buffer_primary = tmp; @@ -446,10 +448,14 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, if (!dev->read_urb_finished) { /* somebody is doing IO */ spin_unlock_irqrestore(&dev->buflock, flags); - dbg(2, " %s : submitted already", __func__); + dev_dbg(&dev->udev->dev, + "%s : submitted already\n", + __func__); } else { /* we must initiate input */ - dbg(2, " %s : initiate input", __func__); + dev_dbg(&dev->udev->dev, + "%s : initiate input\n", + __func__); dev->read_urb_finished = 0; spin_unlock_irqrestore(&dev->buflock, flags); @@ -467,7 +473,9 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, if (retval == -ENOMEM) { retval = bytes_read ? bytes_read : -ENOMEM; } - dbg(2, " %s : submit failed", __func__); + dev_dbg(&dev->udev->dev, + "%s : submit failed\n", + __func__); goto exit; } } @@ -486,13 +494,16 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, remove_wait_queue(&dev->read_wait, &wait); if (timeout <= 0) { - dbg(2, " %s : timeout", __func__); + dev_dbg(&dev->udev->dev, + "%s : timeout\n", __func__); retval = bytes_read ? bytes_read : -ETIMEDOUT; goto exit; } if (signal_pending(current)) { - dbg(2, " %s : signal pending", __func__); + dev_dbg(&dev->udev->dev, + "%s : signal pending\n", + __func__); retval = bytes_read ? bytes_read : -EINTR; goto exit; } @@ -555,7 +566,8 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, /* verify that we actually have some data to write */ if (count == 0) { - dbg(1, " %s : write request of 0 bytes", __func__); + dev_dbg(&dev->udev->dev, "%s : write request of 0 bytes\n", + __func__); goto exit; } @@ -568,13 +580,15 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, mutex_unlock(&dev->mtx); if (signal_pending(current)) { - dbg(1, " %s : interrupted", __func__); + dev_dbg(&dev->udev->dev, "%s : interrupted\n", + __func__); set_current_state(TASK_RUNNING); retval = -EINTR; goto exit_onqueue; } if (schedule_timeout(COMMAND_TIMEOUT) == 0) { - dbg(1, "%s - command timed out.", __func__); + dev_dbg(&dev->udev->dev, + "%s - command timed out.\n", __func__); retval = -ETIMEDOUT; goto exit_onqueue; } @@ -585,18 +599,22 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, goto exit_nolock; } - dbg(4, " %s : in progress, count = %Zd", __func__, count); + dev_dbg(&dev->udev->dev, + "%s : in progress, count = %Zd\n", + __func__, count); } else { spin_unlock_irqrestore(&dev->buflock, flags); set_current_state(TASK_RUNNING); remove_wait_queue(&dev->write_wait, &waita); - dbg(4, " %s : sending, count = %Zd", __func__, count); + dev_dbg(&dev->udev->dev, "%s : sending, count = %Zd\n", + __func__, count); /* write the data into interrupt_out_buffer from userspace */ buffer_size = usb_endpoint_maxp(dev->interrupt_out_endpoint); bytes_to_write = count > buffer_size ? buffer_size : count; - dbg(4, " %s : buffer_size = %Zd, count = %Zd, bytes_to_write = %Zd", - __func__, buffer_size, count, bytes_to_write); + dev_dbg(&dev->udev->dev, + "%s : buffer_size = %Zd, count = %Zd, bytes_to_write = %Zd\n", + __func__, buffer_size, count, bytes_to_write); if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write) != 0) { retval = -EFAULT; @@ -779,7 +797,7 @@ static int adu_probe(struct usb_interface *interface, dev_err(&interface->dev, "Could not retrieve serial number\n"); goto error; } - dbg(2, " %s : serial_number=%s", __func__, dev->serial_number); + dev_dbg(&interface->dev,"serial_number=%s", dev->serial_number); /* we can register the device now, as it is ready */ usb_set_intfdata(interface, dev); @@ -829,7 +847,8 @@ static void adu_disconnect(struct usb_interface *interface) usb_set_intfdata(interface, NULL); /* if the device is not opened, then we clean up right now */ - dbg(2, " %s : open count %d", __func__, dev->open_count); + dev_dbg(&dev->udev->dev, "%s : open count %d\n", + __func__, dev->open_count); if (!dev->open_count) adu_delete(dev); From 1ef37c6047fef8b65d62aa908d9795101b5244d6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 26 Jun 2013 16:30:45 -0700 Subject: [PATCH 0436/3400] USB: adutux: remove custom debug macro and module parameter Now that we don't use the dbg() macro, remove it, and the module parameter. Also fix up the "dump_data" function to properly use the dynamic debug core and the correct printk options, and don't call it twice per function, as the data doesn't change from the beginning and the end of the call. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/adutux.c | 50 +++++++-------------------------------- 1 file changed, 9 insertions(+), 41 deletions(-) diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c index 885f99322a84..2a4793647580 100644 --- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c @@ -27,30 +27,11 @@ #include #include -#ifdef CONFIG_USB_DEBUG -static int debug = 5; -#else -static int debug = 1; -#endif - -/* Use our own dbg macro */ -#undef dbg -#define dbg(lvl, format, arg...) \ -do { \ - if (debug >= lvl) \ - printk(KERN_DEBUG "%s: " format "\n", __FILE__, ##arg); \ -} while (0) - - /* Version Information */ #define DRIVER_VERSION "v0.0.13" #define DRIVER_AUTHOR "John Homppi" #define DRIVER_DESC "adutux (see www.ontrak.net)" -/* Module parameters */ -module_param(debug, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); - /* Define these values to match your device */ #define ADU_VENDOR_ID 0x0a07 #define ADU_PRODUCT_ID 0x0064 @@ -124,19 +105,11 @@ static DEFINE_MUTEX(adutux_mutex); static struct usb_driver adu_driver; -static void adu_debug_data(int level, const char *function, int size, - const unsigned char *data) +static inline void adu_debug_data(struct device *dev, const char *function, + int size, const unsigned char *data) { - int i; - - if (debug < level) - return; - - printk(KERN_DEBUG "%s: %s - length = %d, data = ", - __FILE__, function, size); - for (i = 0; i < size; ++i) - printk("%.2x ", data[i]); - printk("\n"); + dev_dbg(dev, "%s - length = %d, data = %*ph\n", + function, size, size, data); } /** @@ -185,8 +158,8 @@ static void adu_interrupt_in_callback(struct urb *urb) struct adu_device *dev = urb->context; int status = urb->status; - adu_debug_data(5, __func__, urb->actual_length, - urb->transfer_buffer); + adu_debug_data(&dev->udev->dev, __func__, + urb->actual_length, urb->transfer_buffer); spin_lock(&dev->buflock); @@ -222,8 +195,6 @@ exit: spin_unlock(&dev->buflock); /* always wake up so we recover from errors */ wake_up_interruptible(&dev->read_wait); - adu_debug_data(5, __func__, urb->actual_length, - urb->transfer_buffer); } static void adu_interrupt_out_callback(struct urb *urb) @@ -231,7 +202,8 @@ static void adu_interrupt_out_callback(struct urb *urb) struct adu_device *dev = urb->context; int status = urb->status; - adu_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer); + adu_debug_data(&dev->udev->dev, __func__, + urb->actual_length, urb->transfer_buffer); if (status != 0) { if ((status != -ENOENT) && @@ -240,17 +212,13 @@ static void adu_interrupt_out_callback(struct urb *urb) "%s :nonzero status received: %d\n", __func__, status); } - goto exit; + return; } spin_lock(&dev->buflock); dev->out_urb_finished = 1; wake_up(&dev->write_wait); spin_unlock(&dev->buflock); -exit: - - adu_debug_data(5, __func__, urb->actual_length, - urb->transfer_buffer); } static int adu_open(struct inode *inode, struct file *file) From 28f47c34c75222abefac95a5740b246e065de35f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 26 Jun 2013 16:30:46 -0700 Subject: [PATCH 0437/3400] USB: adutux: remove direct calls to printk() Use the pr_* calls instead, which are much more descriptive. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/adutux.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c index 2a4793647580..7078e9bf0fc0 100644 --- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c @@ -18,6 +18,8 @@ * */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -236,8 +238,8 @@ static int adu_open(struct inode *inode, struct file *file) interface = usb_find_interface(&adu_driver, subminor); if (!interface) { - printk(KERN_ERR "adutux: %s - error, can't find device for " - "minor %d\n", __func__, subminor); + pr_err("%s - error, can't find device for minor %d\n", + __func__, subminor); retval = -ENODEV; goto exit_no_device; } @@ -357,8 +359,7 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, /* verify that the device wasn't unplugged */ if (dev->udev == NULL) { retval = -ENODEV; - printk(KERN_ERR "adutux: No device or device unplugged %d\n", - retval); + pr_err("No device or device unplugged %d\n", retval); goto exit; } @@ -527,8 +528,7 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, /* verify that the device wasn't unplugged */ if (dev->udev == NULL) { retval = -ENODEV; - printk(KERN_ERR "adutux: No device or device unplugged %d\n", - retval); + pr_err("No device or device unplugged %d\n", retval); goto exit; } From 4ce10417e840ab58717d2c91986d8684c6858c3f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 26 Jun 2013 16:30:47 -0700 Subject: [PATCH 0438/3400] USB: misc: remove CONFIG_USB_DEBUG from Makefile Now that no usb misc driver is looking for CONFIG_USB_DEBUG, or DEBUG, don't enable it in the Makefile, as that's pointless. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/Makefile | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile index 3e1bd70b06ea..5a896f319118 100644 --- a/drivers/usb/misc/Makefile +++ b/drivers/usb/misc/Makefile @@ -2,9 +2,6 @@ # Makefile for the rest of the USB drivers # (the ones that don't fit into any other categories) # - -ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG - obj-$(CONFIG_USB_ADUTUX) += adutux.o obj-$(CONFIG_USB_APPLEDISPLAY) += appledisplay.o obj-$(CONFIG_USB_CYPRESS_CY7C63) += cypress_cy7c63.o From a0b9281e29fb8942baddf2ce4067eb611f4f9c01 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 26 Jun 2013 16:47:20 +0200 Subject: [PATCH 0439/3400] USB: serial: remove defensive test from set_termios Remove defensive test from set_termios which is never called with a NULL tty. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp210x.c | 3 --- drivers/usb/serial/oti6858.c | 3 --- 2 files changed, 6 deletions(-) diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index d6ef2f8da37d..5627058964d5 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -666,9 +666,6 @@ static void cp210x_set_termios(struct tty_struct *tty, unsigned int bits; unsigned int modem_ctl[4]; - if (!tty) - return; - cflag = tty->termios.c_cflag; old_cflag = old_termios->c_cflag; diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index 7e3e0782e51f..cf509c8c1aa1 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c @@ -411,9 +411,6 @@ static void oti6858_set_termios(struct tty_struct *tty, __le16 divisor; int br; - if (!tty) - return; - cflag = tty->termios.c_cflag; spin_lock_irqsave(&priv->lock, flags); From 91c4211c394996df485184b7308c8868be1b2055 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 26 Jun 2013 16:47:21 +0200 Subject: [PATCH 0440/3400] USB: serial: remove hupping check from tiocmiwait Since commit 31ca020b ("TTY: wake up processes last at hangup") there no longer any need to check the hupping flag in the generic tiocmiwait implementation, so remove it. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/generic.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index ba45170c78e5..1f31e6b4c251 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -460,12 +460,7 @@ static bool usb_serial_generic_msr_changed(struct tty_struct *tty, /* * Use tty-port initialised flag to detect all hangups including the * one generated at USB-device disconnect. - * - * FIXME: Remove hupping check once tty_port_hangup calls shutdown - * (which clears the initialised flag) before wake up. */ - if (test_bit(TTY_HUPPING, &tty->flags)) - return true; if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags)) return true; @@ -496,12 +491,8 @@ int usb_serial_generic_tiocmiwait(struct tty_struct *tty, unsigned long arg) ret = wait_event_interruptible(port->port.delta_msr_wait, usb_serial_generic_msr_changed(tty, arg, &cnow)); - if (!ret) { - if (test_bit(TTY_HUPPING, &tty->flags)) - ret = -EIO; - if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags)) - ret = -EIO; - } + if (!ret && !test_bit(ASYNCB_INITIALIZED, &port->port.flags)) + ret = -EIO; return ret; } From f5f45304512fa167883dbf7cc23ff92008b173e7 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 26 Jun 2013 16:47:22 +0200 Subject: [PATCH 0441/3400] USB: serial: clean up dtr_rts Since commit 957dacae ("TTY: fix DTR not being dropped on hang up") dtr_rts is no longer called for uninitialised ports (e.g. after a disconnect), which removes the need to grab the disconnect mutex. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index cb27fcb2fc90..6091bd5a1f4f 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -681,20 +681,10 @@ static int serial_port_carrier_raised(struct tty_port *port) static void serial_port_dtr_rts(struct tty_port *port, int on) { struct usb_serial_port *p = container_of(port, struct usb_serial_port, port); - struct usb_serial *serial = p->serial; - struct usb_serial_driver *drv = serial->type; + struct usb_serial_driver *drv = p->serial->type; - if (!drv->dtr_rts) - return; - /* - * Work-around bug in the tty-layer which can result in dtr_rts - * being called after a disconnect (and tty_unregister_device - * has returned). Remove once bug has been squashed. - */ - mutex_lock(&serial->disc_mutex); - if (!serial->disconnected) + if (drv->dtr_rts) drv->dtr_rts(p, on); - mutex_unlock(&serial->disc_mutex); } static const struct tty_port_operations serial_port_ops = { From d7be62211125c85fa1dd796e92aadce84961a502 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 26 Jun 2013 16:47:23 +0200 Subject: [PATCH 0442/3400] USB: serial: set drain delay at port probe The port drain delay is constant and should be set at port probe rather than open. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cypress_m8.c | 4 +++- drivers/usb/serial/f81232.c | 3 ++- drivers/usb/serial/io_ti.c | 3 +-- drivers/usb/serial/oti6858.c | 4 +++- drivers/usb/serial/pl2303.c | 3 ++- drivers/usb/serial/spcp8x5.c | 4 ++-- drivers/usb/serial/ti_usb_3410_5052.c | 4 ++-- 7 files changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index e948dc02795d..558605d646f3 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -495,6 +495,8 @@ static int cypress_generic_port_probe(struct usb_serial_port *port) } usb_set_serial_port_data(port, priv); + port->port.drain_delay = 256; + return 0; } @@ -625,7 +627,7 @@ static int cypress_open(struct tty_struct *tty, struct usb_serial_port *port) __func__, result); cypress_set_dead(port); } - port->port.drain_delay = 256; + return result; } /* cypress_open */ diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c index 75e85cbf9e8b..639a18fb67e6 100644 --- a/drivers/usb/serial/f81232.c +++ b/drivers/usb/serial/f81232.c @@ -207,7 +207,6 @@ static int f81232_open(struct tty_struct *tty, struct usb_serial_port *port) return result; } - port->port.drain_delay = 256; return 0; } @@ -322,6 +321,8 @@ static int f81232_port_probe(struct usb_serial_port *port) usb_set_serial_port_data(port, priv); + port->port.drain_delay = 256; + return 0; } diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 60054e72b75b..d43adc08283c 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -1872,8 +1872,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port) ++edge_serial->num_ports_open; - port->port.drain_delay = 1; - goto release_es_lock; unlink_int_urb: @@ -2473,6 +2471,7 @@ static int edge_port_probe(struct usb_serial_port *port) } port->port.closing_wait = msecs_to_jiffies(closing_wait * 10); + port->port.drain_delay = 1; return 0; } diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index cf509c8c1aa1..baa2ea59b921 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c @@ -343,6 +343,8 @@ static int oti6858_port_probe(struct usb_serial_port *port) usb_set_serial_port_data(port, priv); + port->port.drain_delay = 256; /* FIXME: check the FIFO length */ + return 0; } @@ -558,7 +560,7 @@ static int oti6858_open(struct tty_struct *tty, struct usb_serial_port *port) /* setup termios */ if (tty) oti6858_set_termios(tty, port, &tmp_termios); - port->port.drain_delay = 256; /* FIXME: check the FIFO length */ + return 0; } diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index cb6bbed374f2..ed9edb2e1849 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -235,6 +235,8 @@ static int pl2303_port_probe(struct usb_serial_port *port) usb_set_serial_port_data(port, priv); + port->port.drain_delay = 256; + return 0; } @@ -521,7 +523,6 @@ static int pl2303_open(struct tty_struct *tty, struct usb_serial_port *port) return result; } - port->port.drain_delay = 256; return 0; } diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index ddf6c47137dc..4abac28b5992 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -169,6 +169,8 @@ static int spcp8x5_port_probe(struct usb_serial_port *port) usb_set_serial_port_data(port, priv); + port->port.drain_delay = 256; + return 0; } @@ -411,8 +413,6 @@ static int spcp8x5_open(struct tty_struct *tty, struct usb_serial_port *port) if (tty) spcp8x5_set_termios(tty, port, NULL); - port->port.drain_delay = 256; - return usb_serial_generic_open(tty, port); } diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 7182bb774b79..18db7b3e52b7 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -441,6 +441,8 @@ static int ti_port_probe(struct usb_serial_port *port) usb_set_serial_port_data(port, tport); + port->port.drain_delay = 3; + return 0; } @@ -582,8 +584,6 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port) tport->tp_is_open = 1; ++tdev->td_open_port_count; - port->port.drain_delay = 3; - goto release_lock; unlink_int_urb: From 7b94cae47cbfaa1a64cd51b3735eba3abe6af827 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 26 Jun 2013 16:47:25 +0200 Subject: [PATCH 0443/3400] USB: console: use dev_dbg Use dev_dbg for debugging. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/console.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index afb50eab2049..bfad2cd39bf3 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c @@ -210,10 +210,10 @@ static void usb_console_write(struct console *co, if (count == 0) return; - pr_debug("%s - minor %d, %d byte(s)\n", __func__, port->minor, count); + dev_dbg(&port->dev, "%s - %d byte(s)\n", __func__, count); if (!port->port.console) { - pr_debug("%s - port not opened\n", __func__); + dev_dbg(&port->dev, "%s - port not opened\n", __func__); return; } @@ -234,7 +234,7 @@ static void usb_console_write(struct console *co, retval = serial->type->write(NULL, port, buf, i); else retval = usb_serial_generic_write(NULL, port, buf, i); - pr_debug("%s - return value : %d\n", __func__, retval); + dev_dbg(&port->dev, "%s - write: %d\n", __func__, retval); if (lf) { /* append CR after LF */ unsigned char cr = 13; @@ -244,7 +244,8 @@ static void usb_console_write(struct console *co, else retval = usb_serial_generic_write(NULL, port, &cr, 1); - pr_debug("%s - return value : %d\n", __func__, retval); + dev_dbg(&port->dev, "%s - write cr: %d\n", + __func__, retval); } buf += i; count -= i; From c7b13475b4466adcdcd8378f12b4ee416ef9b98b Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 26 Jun 2013 16:47:26 +0200 Subject: [PATCH 0444/3400] USB: console: remove unnecessary operations test Remove unnecessary tests for open and write operations as these are set to the generic implementations by usb-serial core if left unset by a subdriver. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/console.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index bfad2cd39bf3..c69bb50d4663 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c @@ -151,11 +151,7 @@ static int usb_console_setup(struct console *co, char *options) /* only call the device specific open if this * is the first time the port is opened */ - if (serial->type->open) - retval = serial->type->open(NULL, port); - else - retval = usb_serial_generic_open(NULL, port); - + retval = serial->type->open(NULL, port); if (retval) { dev_err(&port->dev, "could not open USB console port\n"); goto fail; @@ -230,20 +226,12 @@ static void usb_console_write(struct console *co, } /* pass on to the driver specific version of this function if it is available */ - if (serial->type->write) - retval = serial->type->write(NULL, port, buf, i); - else - retval = usb_serial_generic_write(NULL, port, buf, i); + retval = serial->type->write(NULL, port, buf, i); dev_dbg(&port->dev, "%s - write: %d\n", __func__, retval); if (lf) { /* append CR after LF */ unsigned char cr = 13; - if (serial->type->write) - retval = serial->type->write(NULL, - port, &cr, 1); - else - retval = usb_serial_generic_write(NULL, - port, &cr, 1); + retval = serial->type->write(NULL, port, &cr, 1); dev_dbg(&port->dev, "%s - write cr: %d\n", __func__, retval); } From 15e7cead1ed89d445cf86c75a72368e98a7a9039 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 26 Jun 2013 16:47:27 +0200 Subject: [PATCH 0445/3400] USB: pl2303: refactor baud-rate handling Break out baud-rate handling from set_termios. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/pl2303.c | 127 ++++++++++++++++++++---------------- 1 file changed, 69 insertions(+), 58 deletions(-) diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index ed9edb2e1849..c15d64d6e1e7 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -263,68 +263,21 @@ static int pl2303_set_control_lines(struct usb_serial_port *port, u8 value) return retval; } -static void pl2303_set_termios(struct tty_struct *tty, - struct usb_serial_port *port, struct ktermios *old_termios) +static void pl2303_encode_baudrate(struct tty_struct *tty, + struct usb_serial_port *port, + u8 buf[4]) { - struct usb_serial *serial = port->serial; - struct pl2303_serial_private *spriv = usb_get_serial_data(serial); - struct pl2303_private *priv = usb_get_serial_port_data(port); - unsigned long flags; - unsigned int cflag; - unsigned char *buf; - int baud; - int i; - u8 control; const int baud_sup[] = { 75, 150, 300, 600, 1200, 1800, 2400, 3600, 4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200, 230400, 460800, 500000, 614400, 921600, 1228800, 2457600, 3000000, 6000000 }; + + struct usb_serial *serial = port->serial; + struct pl2303_serial_private *spriv = usb_get_serial_data(serial); + int baud; int baud_floor, baud_ceil; int k; - /* The PL2303 is reported to lose bytes if you change - serial settings even to the same values as before. Thus - we actually need to filter in this specific case */ - - if (old_termios && !tty_termios_hw_change(&tty->termios, old_termios)) - return; - - cflag = tty->termios.c_cflag; - - buf = kzalloc(7, GFP_KERNEL); - if (!buf) { - dev_err(&port->dev, "%s - out of memory.\n", __func__); - /* Report back no change occurred */ - if (old_termios) - tty->termios = *old_termios; - return; - } - - i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), - GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE, - 0, 0, buf, 7, 100); - dev_dbg(&port->dev, "0xa1:0x21:0:0 %d - %7ph\n", i, buf); - - if (cflag & CSIZE) { - switch (cflag & CSIZE) { - case CS5: - buf[6] = 5; - break; - case CS6: - buf[6] = 6; - break; - case CS7: - buf[6] = 7; - break; - default: - case CS8: - buf[6] = 8; - break; - } - dev_dbg(&port->dev, "data bits = %d\n", buf[6]); - } - - /* For reference buf[0]:buf[3] baud rate value */ /* NOTE: Only the values defined in baud_sup are supported ! * => if unsupported values are set, the PL2303 seems to use * 9600 baud (at least my PL2303X always does) @@ -378,6 +331,68 @@ static void pl2303_set_termios(struct tty_struct *tty, } } + /* Save resulting baud rate */ + if (baud) + tty_encode_baud_rate(tty, baud, baud); +} + +static void pl2303_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios) +{ + struct usb_serial *serial = port->serial; + struct pl2303_serial_private *spriv = usb_get_serial_data(serial); + struct pl2303_private *priv = usb_get_serial_port_data(port); + unsigned long flags; + unsigned int cflag; + unsigned char *buf; + int i; + u8 control; + + /* The PL2303 is reported to lose bytes if you change + serial settings even to the same values as before. Thus + we actually need to filter in this specific case */ + + if (old_termios && !tty_termios_hw_change(&tty->termios, old_termios)) + return; + + cflag = tty->termios.c_cflag; + + buf = kzalloc(7, GFP_KERNEL); + if (!buf) { + dev_err(&port->dev, "%s - out of memory.\n", __func__); + /* Report back no change occurred */ + if (old_termios) + tty->termios = *old_termios; + return; + } + + i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), + GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE, + 0, 0, buf, 7, 100); + dev_dbg(&port->dev, "0xa1:0x21:0:0 %d - %7ph\n", i, buf); + + if (cflag & CSIZE) { + switch (cflag & CSIZE) { + case CS5: + buf[6] = 5; + break; + case CS6: + buf[6] = 6; + break; + case CS7: + buf[6] = 7; + break; + default: + case CS8: + buf[6] = 8; + break; + } + dev_dbg(&port->dev, "data bits = %d\n", buf[6]); + } + + /* For reference buf[0]:buf[3] baud rate value */ + pl2303_encode_baudrate(tty, port, &buf[0]); + /* For reference buf[4]=0 is 1 stop bits */ /* For reference buf[4]=1 is 1.5 stop bits */ /* For reference buf[4]=2 is 2 stop bits */ @@ -461,10 +476,6 @@ static void pl2303_set_termios(struct tty_struct *tty, pl2303_vendor_write(0x0, 0x0, serial); } - /* Save resulting baud rate */ - if (baud) - tty_encode_baud_rate(tty, baud, baud); - kfree(buf); } From b2d6d98fc71bb94ada78d433f26a93498802d3f8 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 26 Jun 2013 16:47:28 +0200 Subject: [PATCH 0446/3400] USB: pl2303: clean up baud-rate handling Clean up baud-rate handling somewhat. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/pl2303.c | 90 +++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 49 deletions(-) diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index c15d64d6e1e7..dd59c640edcc 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "pl2303.h" /* @@ -275,65 +276,56 @@ static void pl2303_encode_baudrate(struct tty_struct *tty, struct usb_serial *serial = port->serial; struct pl2303_serial_private *spriv = usb_get_serial_data(serial); int baud; - int baud_floor, baud_ceil; - int k; + int i; - /* NOTE: Only the values defined in baud_sup are supported ! + /* + * NOTE: Only the values defined in baud_sup are supported! * => if unsupported values are set, the PL2303 seems to use * 9600 baud (at least my PL2303X always does) */ baud = tty_get_baud_rate(tty); dev_dbg(&port->dev, "baud requested = %d\n", baud); - if (baud) { - /* Set baudrate to nearest supported value */ - for (k=0; k (baud % baud_floor)) - baud = baud_floor; - else - baud = baud_ceil; - } - break; - } - } - if (baud > 1228800) { - /* type_0, type_1 only support up to 1228800 baud */ - if (spriv->type != HX) - baud = 1228800; - else if (baud > 6000000) - baud = 6000000; - } - dev_dbg(&port->dev, "baud set = %d\n", baud); - if (baud <= 115200) { - buf[0] = baud & 0xff; - buf[1] = (baud >> 8) & 0xff; - buf[2] = (baud >> 16) & 0xff; - buf[3] = (baud >> 24) & 0xff; - } else { - /* apparently the formula for higher speeds is: - * baudrate = 12M * 32 / (2^buf[1]) / buf[0] - */ - unsigned tmp = 12*1000*1000*32 / baud; - buf[3] = 0x80; - buf[2] = 0; - buf[1] = (tmp >= 256); - while (tmp >= 256) { - tmp >>= 2; - buf[1] <<= 1; - } - buf[0] = tmp; + if (!baud) + return; + + /* Set baudrate to nearest supported value */ + for (i = 0; i < ARRAY_SIZE(baud_sup); ++i) { + if (baud_sup[i] > baud) + break; + } + + if (i == ARRAY_SIZE(baud_sup)) + baud = baud_sup[i - 1]; + else if (i > 0 && (baud_sup[i] - baud) > (baud - baud_sup[i - 1])) + baud = baud_sup[i - 1]; + else + baud = baud_sup[i]; + + /* type_0, type_1 only support up to 1228800 baud */ + if (spriv->type != HX) + baud = max_t(int, baud, 1228800); + + if (baud <= 115200) { + put_unaligned_le32(baud, buf); + } else { + /* + * Apparently the formula for higher speeds is: + * baudrate = 12M * 32 / (2^buf[1]) / buf[0] + */ + unsigned tmp = 12000000 * 32 / baud; + buf[3] = 0x80; + buf[2] = 0; + buf[1] = (tmp >= 256); + while (tmp >= 256) { + tmp >>= 2; + buf[1] <<= 1; } + buf[0] = tmp; } /* Save resulting baud rate */ - if (baud) - tty_encode_baud_rate(tty, baud, baud); + tty_encode_baud_rate(tty, baud, baud); + dev_dbg(&port->dev, "baud set = %d\n", baud); } static void pl2303_set_termios(struct tty_struct *tty, From 87265b4514f5a0b79efdccdcb1c6331285652640 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 26 Jun 2013 16:47:29 +0200 Subject: [PATCH 0447/3400] USB: pl2303: clean up set_termios Clean up set_termios somewhat. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/pl2303.c | 39 +++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index dd59c640edcc..91f14c6950f9 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -335,20 +335,18 @@ static void pl2303_set_termios(struct tty_struct *tty, struct pl2303_serial_private *spriv = usb_get_serial_data(serial); struct pl2303_private *priv = usb_get_serial_port_data(port); unsigned long flags; - unsigned int cflag; unsigned char *buf; int i; u8 control; - /* The PL2303 is reported to lose bytes if you change - serial settings even to the same values as before. Thus - we actually need to filter in this specific case */ - + /* + * The PL2303 is reported to lose bytes if you change serial settings + * even to the same values as before. Thus we actually need to filter + * in this specific case. + */ if (old_termios && !tty_termios_hw_change(&tty->termios, old_termios)) return; - cflag = tty->termios.c_cflag; - buf = kzalloc(7, GFP_KERNEL); if (!buf) { dev_err(&port->dev, "%s - out of memory.\n", __func__); @@ -363,8 +361,8 @@ static void pl2303_set_termios(struct tty_struct *tty, 0, 0, buf, 7, 100); dev_dbg(&port->dev, "0xa1:0x21:0:0 %d - %7ph\n", i, buf); - if (cflag & CSIZE) { - switch (cflag & CSIZE) { + if (C_CSIZE(tty)) { + switch (C_CSIZE(tty)) { case CS5: buf[6] = 5; break; @@ -377,7 +375,6 @@ static void pl2303_set_termios(struct tty_struct *tty, default: case CS8: buf[6] = 8; - break; } dev_dbg(&port->dev, "data bits = %d\n", buf[6]); } @@ -388,11 +385,12 @@ static void pl2303_set_termios(struct tty_struct *tty, /* For reference buf[4]=0 is 1 stop bits */ /* For reference buf[4]=1 is 1.5 stop bits */ /* For reference buf[4]=2 is 2 stop bits */ - if (cflag & CSTOPB) { - /* NOTE: Comply with "real" UARTs / RS232: + if (C_CSTOPB(tty)) { + /* + * NOTE: Comply with "real" UARTs / RS232: * use 1.5 instead of 2 stop bits with 5 data bits */ - if ((cflag & CSIZE) == CS5) { + if (C_CSIZE(tty) == CS5) { buf[4] = 1; dev_dbg(&port->dev, "stop bits = 1.5\n"); } else { @@ -404,14 +402,14 @@ static void pl2303_set_termios(struct tty_struct *tty, dev_dbg(&port->dev, "stop bits = 1\n"); } - if (cflag & PARENB) { + if (C_PARENB(tty)) { /* For reference buf[5]=0 is none parity */ /* For reference buf[5]=1 is odd parity */ /* For reference buf[5]=2 is even parity */ /* For reference buf[5]=3 is mark parity */ /* For reference buf[5]=4 is space parity */ - if (cflag & PARODD) { - if (cflag & CMSPAR) { + if (C_PARODD(tty)) { + if (tty->termios.c_cflag & CMSPAR) { buf[5] = 3; dev_dbg(&port->dev, "parity = mark\n"); } else { @@ -419,7 +417,7 @@ static void pl2303_set_termios(struct tty_struct *tty, dev_dbg(&port->dev, "parity = odd\n"); } } else { - if (cflag & CMSPAR) { + if (tty->termios.c_cflag & CMSPAR) { buf[5] = 4; dev_dbg(&port->dev, "parity = space\n"); } else { @@ -440,7 +438,7 @@ static void pl2303_set_termios(struct tty_struct *tty, /* change control lines if we are switching to or from B0 */ spin_lock_irqsave(&priv->lock, flags); control = priv->line_control; - if ((cflag & CBAUD) == B0) + if (C_BAUD(tty) == B0) priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS); else if (old_termios && (old_termios->c_cflag & CBAUD) == B0) priv->line_control |= (CONTROL_DTR | CONTROL_RTS); @@ -452,14 +450,13 @@ static void pl2303_set_termios(struct tty_struct *tty, spin_unlock_irqrestore(&priv->lock, flags); } - buf[0] = buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0; - + memset(buf, 0, 7); i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE, 0, 0, buf, 7, 100); dev_dbg(&port->dev, "0xa1:0x21:0:0 %d - %7ph\n", i, buf); - if (cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { if (spriv->type == HX) pl2303_vendor_write(0x0, 0x61, serial); else From 3ba19fe31b726371b45f91a8de9341f5625e75e4 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 26 Jun 2013 16:47:30 +0200 Subject: [PATCH 0448/3400] USB: pl2303: remove debugging noise Only log the tty_flags in process_read_urb on errors. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/pl2303.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 91f14c6950f9..299a0ffcb165 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -790,8 +790,10 @@ static void pl2303_process_read_urb(struct urb *urb) tty_flag = TTY_PARITY; else if (line_status & UART_FRAME_ERROR) tty_flag = TTY_FRAME; - dev_dbg(&port->dev, "%s - tty_flag = %d\n", __func__, tty_flag); + if (tty_flag != TTY_NORMAL) + dev_dbg(&port->dev, "%s - tty_flag = %d\n", __func__, + tty_flag); /* overrun is special, not associated with a char */ if (line_status & UART_OVERRUN_ERROR) tty_insert_flip_char(&port->port, 0, TTY_OVERRUN); From dc43ff924d0d29e53e3f4d26db2c4265b1aa5a2a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 26 Jun 2013 16:47:31 +0200 Subject: [PATCH 0449/3400] USB: oti6858: do not call set_termios with uninitialised data Make sure set_termios is not called with uninitialised data at open. The old termios struct is currently not used, but pass NULL instead to avoid future problems (e.g. stack data leak). Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/oti6858.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index baa2ea59b921..a2080ac7b7e5 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c @@ -508,7 +508,6 @@ static void oti6858_set_termios(struct tty_struct *tty, static int oti6858_open(struct tty_struct *tty, struct usb_serial_port *port) { struct oti6858_private *priv = usb_get_serial_port_data(port); - struct ktermios tmp_termios; struct usb_serial *serial = port->serial; struct oti6858_control_pkt *buf; unsigned long flags; @@ -559,7 +558,7 @@ static int oti6858_open(struct tty_struct *tty, struct usb_serial_port *port) /* setup termios */ if (tty) - oti6858_set_termios(tty, port, &tmp_termios); + oti6858_set_termios(tty, port, NULL); return 0; } From be0278ccf3c05e7048cc6c7906e41bba0b41b8c7 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 26 Jun 2013 16:47:32 +0200 Subject: [PATCH 0450/3400] USB: ftdi_sio: clean up device initialisation Do not use zeroed termios data to determine when to unconditionally configure the device at open. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 7260ec660347..abcaeafa525f 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1842,7 +1842,6 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port) static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port) { - struct ktermios dummy; struct usb_device *dev = port->serial->dev; struct ftdi_private *priv = usb_get_serial_port_data(port); @@ -1858,10 +1857,8 @@ static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port) This is same behaviour as serial.c/rs_open() - Kuba */ /* ftdi_set_termios will send usb control messages */ - if (tty) { - memset(&dummy, 0, sizeof(dummy)); - ftdi_set_termios(tty, port, &dummy); - } + if (tty) + ftdi_set_termios(tty, port, NULL); return usb_serial_generic_open(tty, port); } From 3177130fd7827fcf792036eaa54d12156172ed5f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 26 Jun 2013 16:47:33 +0200 Subject: [PATCH 0451/3400] USB: ftdi_sio: remove redundant raise of DTR/RTS at open Do not raise DTR/RTS a second time in set_termios at open -- this has already been taken care of by the tty layer. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index abcaeafa525f..86f6dfe87f86 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -2187,7 +2187,7 @@ no_data_parity_stop_changes: dev_err(ddev, "%s urb failed to set baudrate\n", __func__); mutex_unlock(&priv->cfg_lock); /* Ensure RTS and DTR are raised when baudrate changed from 0 */ - if (!old_termios || (old_termios->c_cflag & CBAUD) == B0) + if (old_termios && (old_termios->c_cflag & CBAUD) == B0) set_mctrl(port, TIOCM_DTR | TIOCM_RTS); } From e17c1aa2e165556018169ed4dfcc5713167bdb35 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 26 Jun 2013 16:47:34 +0200 Subject: [PATCH 0452/3400] USB: ftdi_sio: remove vendor/product module parameters Remove the vendor and product module parameters which were added a long time ago when we did not have the dynamic sysfs interface to add new device ids (and which isn't limited to a single new vid/pid pair). A vid/pid pair can be added dynamically using sysfs, for example: echo 0403 1234 >/sys/bus/usb-serial/drivers/ftdi_sio/new_id Also fix up the in-code comment that got the sysfs path wrong. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 36 +++-------------------------------- 1 file changed, 3 insertions(+), 33 deletions(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 86f6dfe87f86..9bd1f6f1ea80 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -51,8 +51,6 @@ #define DRIVER_AUTHOR "Greg Kroah-Hartman , Bill Ryder , Kuba Ober , Andreas Mohr, Johan Hovold " #define DRIVER_DESC "USB FTDI Serial Converters Driver" -static __u16 vendor = FTDI_VID; -static __u16 product; struct ftdi_private { enum ftdi_chip_type chip_type; @@ -144,8 +142,8 @@ static struct ftdi_sio_quirk ftdi_8u2232c_quirk = { /* - * Device ID not listed? Test via module params product/vendor or - * /sys/bus/usb/ftdi_sio/new_id, then send patch/report! + * Device ID not listed? Test it using + * /sys/bus/usb-serial/drivers/ftdi_sio/new_id and send a patch or report. */ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_ZEITCONTROL_TAGTRACE_MIFARE_PID) }, @@ -881,7 +879,6 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_LUMEL_PD12_PID) }, /* Crucible Devices */ { USB_DEVICE(FTDI_VID, FTDI_CT_COMET_PID) }, - { }, /* Optional parameter entry */ { } /* Terminating entry */ }; @@ -2377,38 +2374,11 @@ static int ftdi_ioctl(struct tty_struct *tty, return -ENOIOCTLCMD; } -static int __init ftdi_init(void) -{ - if (vendor > 0 && product > 0) { - /* Add user specified VID/PID to reserved element of table. */ - int i; - for (i = 0; id_table_combined[i].idVendor; i++) - ; - id_table_combined[i].match_flags = USB_DEVICE_ID_MATCH_DEVICE; - id_table_combined[i].idVendor = vendor; - id_table_combined[i].idProduct = product; - } - return usb_serial_register_drivers(serial_drivers, KBUILD_MODNAME, id_table_combined); -} - -static void __exit ftdi_exit(void) -{ - usb_serial_deregister_drivers(serial_drivers); -} - - -module_init(ftdi_init); -module_exit(ftdi_exit); +module_usb_serial_driver(serial_drivers, id_table_combined); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -module_param(vendor, ushort, 0); -MODULE_PARM_DESC(vendor, "User specified vendor ID (default=" - __MODULE_STRING(FTDI_VID)")"); -module_param(product, ushort, 0); -MODULE_PARM_DESC(product, "User specified product ID"); - module_param(ndi_latency_timer, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(ndi_latency_timer, "NDI device latency timer override"); From 2843988299bc503d8a4dc72e032c6be6cd79e28e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 26 Jun 2013 16:47:35 +0200 Subject: [PATCH 0453/3400] USB: ftdi_sio: remove unused defines Remove some unused defines. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 9bd1f6f1ea80..bebf3ef7927e 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -902,9 +902,6 @@ static const char *ftdi_chip_name[] = { #define FTDI_STATUS_B1_MASK (FTDI_RS_BI) /* End TIOCMIWAIT */ -#define FTDI_IMPL_ASYNC_FLAGS = (ASYNC_SPD_HI | ASYNC_SPD_VHI \ - | ASYNC_SPD_CUST | ASYNC_SPD_SHI | ASYNC_SPD_WARP) - /* function prototypes for a FTDI serial converter */ static int ftdi_sio_probe(struct usb_serial *serial, const struct usb_device_id *id); @@ -971,10 +968,6 @@ static struct usb_serial_driver * const serial_drivers[] = { #define WDR_TIMEOUT 5000 /* default urb timeout */ #define WDR_SHORT_TIMEOUT 1000 /* shorter urb timeout */ -/* High and low are for DTR, RTS etc etc */ -#define HIGH 1 -#define LOW 0 - /* * *************************************************************************** * Utility functions From 421ae6e3db690a5679192aca2463662bc0c1a1da Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 26 Jun 2013 16:47:36 +0200 Subject: [PATCH 0454/3400] USB: io_edgeport: remove unused defines Remove unused timeout defines. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/io_edgeport.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index dc2803b5eb09..c91481d74a14 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -56,9 +56,7 @@ #define MAX_NAME_LEN 64 -#define CHASE_TIMEOUT (5*HZ) /* 5 seconds */ #define OPEN_TIMEOUT (5*HZ) /* 5 seconds */ -#define COMMAND_TIMEOUT (5*HZ) /* 5 seconds */ /* receive port state */ enum RXSTATE { From ddca16e4f10ac83d4d3f02065b3886f85961f7ec Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 26 Jun 2013 16:47:37 +0200 Subject: [PATCH 0455/3400] USB: io_ti: kill private fifo Kill private write fifo and use the already allocated port write fifo instead. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/io_ti.c | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index d43adc08283c..f48e90a222e8 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -64,8 +64,6 @@ #define EDGE_CLOSING_WAIT 4000 /* in .01 sec */ -#define EDGE_OUT_BUF_SIZE 1024 - /* Product information read from the Edgeport */ struct product_info { @@ -93,7 +91,6 @@ struct edgeport_port { spinlock_t ep_lock; int ep_read_urb_state; int ep_write_urb_in_use; - struct kfifo write_fifo; }; struct edgeport_serial { @@ -1903,7 +1900,7 @@ static void edge_close(struct usb_serial_port *port) usb_kill_urb(port->write_urb); edge_port->ep_write_urb_in_use = 0; spin_lock_irqsave(&edge_port->ep_lock, flags); - kfifo_reset_out(&edge_port->write_fifo); + kfifo_reset_out(&port->write_fifo); spin_unlock_irqrestore(&edge_port->ep_lock, flags); dev_dbg(&port->dev, "%s - send umpc_close_port\n", __func__); @@ -1937,7 +1934,7 @@ static int edge_write(struct tty_struct *tty, struct usb_serial_port *port, if (edge_port->close_pending == 1) return -ENODEV; - count = kfifo_in_locked(&edge_port->write_fifo, data, count, + count = kfifo_in_locked(&port->write_fifo, data, count, &edge_port->ep_lock); edge_send(port, tty); @@ -1957,7 +1954,7 @@ static void edge_send(struct usb_serial_port *port, struct tty_struct *tty) return; } - count = kfifo_out(&edge_port->write_fifo, + count = kfifo_out(&port->write_fifo, port->write_urb->transfer_buffer, port->bulk_out_size); @@ -2005,7 +2002,7 @@ static int edge_write_room(struct tty_struct *tty) return 0; spin_lock_irqsave(&edge_port->ep_lock, flags); - room = kfifo_avail(&edge_port->write_fifo); + room = kfifo_avail(&port->write_fifo); spin_unlock_irqrestore(&edge_port->ep_lock, flags); dev_dbg(&port->dev, "%s - returns %d\n", __func__, room); @@ -2022,7 +2019,7 @@ static int edge_chars_in_buffer(struct tty_struct *tty) return 0; spin_lock_irqsave(&edge_port->ep_lock, flags); - chars = kfifo_len(&edge_port->write_fifo); + chars = kfifo_len(&port->write_fifo); spin_unlock_irqrestore(&edge_port->ep_lock, flags); dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars); @@ -2449,13 +2446,6 @@ static int edge_port_probe(struct usb_serial_port *port) if (!edge_port) return -ENOMEM; - ret = kfifo_alloc(&edge_port->write_fifo, EDGE_OUT_BUF_SIZE, - GFP_KERNEL); - if (ret) { - kfree(edge_port); - return -ENOMEM; - } - spin_lock_init(&edge_port->ep_lock); edge_port->port = port; edge_port->edge_serial = usb_get_serial_data(port->serial); @@ -2465,7 +2455,6 @@ static int edge_port_probe(struct usb_serial_port *port) ret = edge_create_sysfs_attrs(port); if (ret) { - kfifo_free(&edge_port->write_fifo); kfree(edge_port); return ret; } @@ -2482,7 +2471,6 @@ static int edge_port_remove(struct usb_serial_port *port) edge_port = usb_get_serial_port_data(port); edge_remove_sysfs_attrs(port); - kfifo_free(&edge_port->write_fifo); kfree(edge_port); return 0; From 0fce06da6bb49a3973b7c2ab174761fbc848ca6c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 26 Jun 2013 16:47:38 +0200 Subject: [PATCH 0456/3400] USB: io_ti: move port initialisation to probe Move port initialisation code from open to probe where it belongs. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/io_ti.c | 46 +++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index f48e90a222e8..9c18f5985c8d 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -1729,22 +1729,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port) return -ENODEV; port_number = port->port_number; - switch (port_number) { - case 0: - edge_port->uart_base = UMPMEM_BASE_UART1; - edge_port->dma_address = UMPD_OEDB1_ADDRESS; - break; - case 1: - edge_port->uart_base = UMPMEM_BASE_UART2; - edge_port->dma_address = UMPD_OEDB2_ADDRESS; - break; - default: - dev_err(&port->dev, "Unknown port number!!!\n"); - return -ENODEV; - } - - dev_dbg(&port->dev, "%s - port_number = %d, uart_base = %04x, dma_address = %04x\n", - __func__, port_number, edge_port->uart_base, edge_port->dma_address); dev = port->serial->dev; @@ -2451,18 +2435,40 @@ static int edge_port_probe(struct usb_serial_port *port) edge_port->edge_serial = usb_get_serial_data(port->serial); edge_port->bUartMode = default_uart_mode; + switch (port->port_number) { + case 0: + edge_port->uart_base = UMPMEM_BASE_UART1; + edge_port->dma_address = UMPD_OEDB1_ADDRESS; + break; + case 1: + edge_port->uart_base = UMPMEM_BASE_UART2; + edge_port->dma_address = UMPD_OEDB2_ADDRESS; + break; + default: + dev_err(&port->dev, "unknown port number\n"); + ret = -ENODEV; + goto err; + } + + dev_dbg(&port->dev, + "%s - port_number = %d, uart_base = %04x, dma_address = %04x\n", + __func__, port->port_number, edge_port->uart_base, + edge_port->dma_address); + usb_set_serial_port_data(port, edge_port); ret = edge_create_sysfs_attrs(port); - if (ret) { - kfree(edge_port); - return ret; - } + if (ret) + goto err; port->port.closing_wait = msecs_to_jiffies(closing_wait * 10); port->port.drain_delay = 1; return 0; +err: + kfree(edge_port); + + return ret; } static int edge_port_remove(struct usb_serial_port *port) From 4833960e503549cd73aadc89be5b0c9da0563b5c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 26 Jun 2013 16:47:39 +0200 Subject: [PATCH 0457/3400] USB: mos7840: remove broken chase implementation Remove broken "chase" implementation which was supposed to be used to drain the write buffers at break. The chase implementation slept on a wait queue which was never woken up (i.e. no hardware buffers were queried), and thus amounted to nothing more than polling chars_in_buffer, something which has already been taken care of by the tty layer. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7840.c | 48 ------------------------------------ 1 file changed, 48 deletions(-) diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 0a818b238508..dff27e6b677a 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -218,7 +218,6 @@ struct moschip_port { __u8 shadowMCR; /* last MCR value received */ char open; char open_ports; - wait_queue_head_t wait_chase; /* for handling sleeping while waiting for chase to finish */ struct usb_serial_port *port; /* loop back to the owner of this object */ /* Offsets */ @@ -1092,9 +1091,6 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port) mos7840_port->read_urb_busy = false; } - /* initialize our wait queues */ - init_waitqueue_head(&mos7840_port->wait_chase); - /* initialize our port settings */ /* Must set to enable ints! */ mos7840_port->shadowMCR = MCR_MASTER_IE; @@ -1211,47 +1207,6 @@ static void mos7840_close(struct usb_serial_port *port) mos7840_port->open = 0; } -/************************************************************************ - * - * mos7840_block_until_chase_response - * - * This function will block the close until one of the following: - * 1. Response to our Chase comes from mos7840 - * 2. A timeout of 10 seconds without activity has expired - * (1K of mos7840 data @ 2400 baud ==> 4 sec to empty) - * - ************************************************************************/ - -static void mos7840_block_until_chase_response(struct tty_struct *tty, - struct moschip_port *mos7840_port) -{ - int timeout = msecs_to_jiffies(1000); - int wait = 10; - int count; - - while (1) { - count = mos7840_chars_in_buffer(tty); - - /* Check for Buffer status */ - if (count <= 0) - return; - - /* Block the thread for a while */ - interruptible_sleep_on_timeout(&mos7840_port->wait_chase, - timeout); - /* No activity.. count down section */ - wait--; - if (wait == 0) { - dev_dbg(&mos7840_port->port->dev, "%s - TIMEOUT\n", __func__); - return; - } else { - /* Reset timeout value back to seconds */ - wait = 10; - } - } - -} - /***************************************************************************** * mos7840_break * this function sends a break to the port @@ -1275,9 +1230,6 @@ static void mos7840_break(struct tty_struct *tty, int break_state) if (mos7840_port == NULL) return; - /* flush and block until tx is empty */ - mos7840_block_until_chase_response(tty, mos7840_port); - if (break_state == -1) data = mos7840_port->shadowLCR | LCR_SET_BREAK; else From 8b61d927beb2479ebff654aef686be4df2d84fc0 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 26 Jun 2013 16:47:40 +0200 Subject: [PATCH 0458/3400] USB: safe_serial: remove vendor/product module parameters Remove the vendor and product module parameters which were added a long time ago when we did not have the dynamic sysfs interface to add new device ids (and which isn't limited to a single new vid/pid pair). A vid/pid pair can be added dynamically using sysfs, for example: echo 04dd 1234 >/sys/bus/usb-serial/drivers/safe_serial/new_id Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/safe_serial.c | 51 +++++++++----------------------- 1 file changed, 14 insertions(+), 37 deletions(-) diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c index 21cd7bf2a8cc..ba895989d8c4 100644 --- a/drivers/usb/serial/safe_serial.c +++ b/drivers/usb/serial/safe_serial.c @@ -92,13 +92,6 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -static __u16 vendor; /* no default */ -static __u16 product; /* no default */ -module_param(vendor, ushort, 0); -MODULE_PARM_DESC(vendor, "User specified USB idVendor (required)"); -module_param(product, ushort, 0); -MODULE_PARM_DESC(product, "User specified USB idProduct (required)"); - module_param(safe, bool, 0); MODULE_PARM_DESC(safe, "Turn Safe Encapsulation On/Off"); @@ -140,8 +133,6 @@ static struct usb_device_id id_table[] = { {MY_USB_DEVICE(0x4dd, 0x8003, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, /* Collie */ {MY_USB_DEVICE(0x4dd, 0x8004, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, /* Collie */ {MY_USB_DEVICE(0x5f9, 0xffff, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, /* Sharp tmp */ - /* extra null entry for module vendor/produc parameters */ - {MY_USB_DEVICE(0, 0, CDC_DEVICE_CLASS, LINEO_INTERFACE_CLASS, LINEO_INTERFACE_SUBCLASS_SAFESERIAL)}, {} /* terminating entry */ }; @@ -272,7 +263,19 @@ static int safe_prepare_write_buffer(struct usb_serial_port *port, static int safe_startup(struct usb_serial *serial) { - switch (serial->interface->cur_altsetting->desc.bInterfaceProtocol) { + struct usb_interface_descriptor *desc; + + if (serial->dev->descriptor.bDeviceClass != CDC_DEVICE_CLASS) + return -ENODEV; + + desc = &serial->interface->cur_altsetting->desc; + + if (desc->bInterfaceClass != LINEO_INTERFACE_CLASS) + return -ENODEV; + if (desc->bInterfaceSubClass != LINEO_INTERFACE_SUBCLASS_SAFESERIAL) + return -ENODEV; + + switch (desc->bInterfaceProtocol) { case LINEO_SAFESERIAL_CRC: break; case LINEO_SAFESERIAL_CRC_PADDED: @@ -300,30 +303,4 @@ static struct usb_serial_driver * const serial_drivers[] = { &safe_device, NULL }; -static int __init safe_init(void) -{ - int i; - - /* if we have vendor / product parameters patch them into id list */ - if (vendor || product) { - pr_info("vendor: %x product: %x\n", vendor, product); - - for (i = 0; i < ARRAY_SIZE(id_table); i++) { - if (!id_table[i].idVendor && !id_table[i].idProduct) { - id_table[i].idVendor = vendor; - id_table[i].idProduct = product; - break; - } - } - } - - return usb_serial_register_drivers(serial_drivers, KBUILD_MODNAME, id_table); -} - -static void __exit safe_exit(void) -{ - usb_serial_deregister_drivers(serial_drivers); -} - -module_init(safe_init); -module_exit(safe_exit); +module_usb_serial_driver(serial_drivers, id_table); From cd1e098b5a57f218322c34d6bf0e2dbea26dc85e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 26 Jun 2013 16:47:41 +0200 Subject: [PATCH 0459/3400] USB: ti_usb_3410_5052: kill private fifo Kill private write fifo and use the already allocated port write fifo instead. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ti_usb_3410_5052.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 18db7b3e52b7..d2c6196ca46e 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -45,8 +45,6 @@ #define TI_FIRMWARE_BUF_SIZE 16284 -#define TI_WRITE_BUF_SIZE 1024 - #define TI_TRANSFER_TIMEOUT 2 #define TI_DEFAULT_CLOSING_WAIT 4000 /* in .01 secs */ @@ -77,7 +75,6 @@ struct ti_port { spinlock_t tp_lock; int tp_read_urb_state; int tp_write_urb_in_use; - struct kfifo write_fifo; }; struct ti_device { @@ -431,10 +428,6 @@ static int ti_port_probe(struct usb_serial_port *port) tport->tp_uart_base_addr = TI_UART2_BASE_ADDR; port->port.closing_wait = msecs_to_jiffies(10 * closing_wait); init_waitqueue_head(&tport->tp_write_wait); - if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE, GFP_KERNEL)) { - kfree(tport); - return -ENOMEM; - } tport->tp_port = port; tport->tp_tdev = usb_get_serial_data(port->serial); tport->tp_uart_mode = 0; /* default is RS232 */ @@ -451,7 +444,6 @@ static int ti_port_remove(struct usb_serial_port *port) struct ti_port *tport; tport = usb_get_serial_port_data(port); - kfifo_free(&tport->write_fifo); kfree(tport); return 0; @@ -616,7 +608,7 @@ static void ti_close(struct usb_serial_port *port) usb_kill_urb(port->write_urb); tport->tp_write_urb_in_use = 0; spin_lock_irqsave(&tport->tp_lock, flags); - kfifo_reset_out(&tport->write_fifo); + kfifo_reset_out(&port->write_fifo); spin_unlock_irqrestore(&tport->tp_lock, flags); port_number = port->port_number; @@ -655,7 +647,7 @@ static int ti_write(struct tty_struct *tty, struct usb_serial_port *port, if (tport == NULL || !tport->tp_is_open) return -ENODEV; - count = kfifo_in_locked(&tport->write_fifo, data, count, + count = kfifo_in_locked(&port->write_fifo, data, count, &tport->tp_lock); ti_send(tport); @@ -674,7 +666,7 @@ static int ti_write_room(struct tty_struct *tty) return 0; spin_lock_irqsave(&tport->tp_lock, flags); - room = kfifo_avail(&tport->write_fifo); + room = kfifo_avail(&port->write_fifo); spin_unlock_irqrestore(&tport->tp_lock, flags); dev_dbg(&port->dev, "%s - returns %d\n", __func__, room); @@ -693,7 +685,7 @@ static int ti_chars_in_buffer(struct tty_struct *tty) return 0; spin_lock_irqsave(&tport->tp_lock, flags); - chars = kfifo_len(&tport->write_fifo); + chars = kfifo_len(&port->write_fifo); spin_unlock_irqrestore(&tport->tp_lock, flags); dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars); @@ -1197,7 +1189,7 @@ static void ti_send(struct ti_port *tport) if (tport->tp_write_urb_in_use) goto unlock; - count = kfifo_out(&tport->write_fifo, + count = kfifo_out(&port->write_fifo, port->write_urb->transfer_buffer, port->bulk_out_size); @@ -1312,7 +1304,7 @@ static int ti_get_serial_info(struct ti_port *tport, ret_serial.line = port->minor; ret_serial.port = port->port_number; ret_serial.flags = tport->tp_flags; - ret_serial.xmit_fifo_size = TI_WRITE_BUF_SIZE; + ret_serial.xmit_fifo_size = kfifo_size(&port->write_fifo); ret_serial.baud_base = tport->tp_tdev->td_is_3410 ? 921600 : 460800; ret_serial.closing_wait = cwait; From 5df08c8d3fe7ec91b12882b9d49ca50918039e9f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 26 Jun 2013 16:47:42 +0200 Subject: [PATCH 0460/3400] USB: ti_usb_3410_5052: remove unused wait queue The write wait queue is never added to since commit f1175daa5 ("USB: ti_usb_3410_5052: kill custom closing_wait"). Remove it completely. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ti_usb_3410_5052.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index d2c6196ca46e..f3e21f5f48f2 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -69,7 +69,6 @@ struct ti_port { __u8 tp_uart_mode; /* 232 or 485 modes */ unsigned int tp_uart_base_addr; int tp_flags; - wait_queue_head_t tp_write_wait; struct ti_device *tp_tdev; struct usb_serial_port *tp_port; spinlock_t tp_lock; @@ -427,7 +426,6 @@ static int ti_port_probe(struct usb_serial_port *port) else tport->tp_uart_base_addr = TI_UART2_BASE_ADDR; port->port.closing_wait = msecs_to_jiffies(10 * closing_wait); - init_waitqueue_head(&tport->tp_write_wait); tport->tp_port = port; tport->tp_tdev = usb_get_serial_data(port->serial); tport->tp_uart_mode = 0; /* default is RS232 */ @@ -1082,13 +1080,11 @@ static void ti_bulk_in_callback(struct urb *urb) case -ESHUTDOWN: dev_dbg(dev, "%s - urb shutting down, %d\n", __func__, status); tport->tp_tdev->td_urb_error = 1; - wake_up_interruptible(&tport->tp_write_wait); return; default: dev_err(dev, "%s - nonzero urb status, %d\n", __func__, status); tport->tp_tdev->td_urb_error = 1; - wake_up_interruptible(&tport->tp_write_wait); } if (status == -EPIPE) @@ -1144,13 +1140,11 @@ static void ti_bulk_out_callback(struct urb *urb) case -ESHUTDOWN: dev_dbg(&port->dev, "%s - urb shutting down, %d\n", __func__, status); tport->tp_tdev->td_urb_error = 1; - wake_up_interruptible(&tport->tp_write_wait); return; default: dev_err_console(port, "%s - nonzero urb status, %d\n", __func__, status); tport->tp_tdev->td_urb_error = 1; - wake_up_interruptible(&tport->tp_write_wait); } /* send any buffered data */ @@ -1224,7 +1218,6 @@ static void ti_send(struct ti_port *tport) /* more room in the buffer for new writes, wakeup */ tty_port_tty_wakeup(&port->port); - wake_up_interruptible(&tport->tp_write_wait); return; unlock: spin_unlock_irqrestore(&tport->tp_lock, flags); From d7ece6515e129a419e6603d49362517a1511425e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 26 Jun 2013 16:47:43 +0200 Subject: [PATCH 0461/3400] USB: ti_usb_3410_5052: remove vendor/product module parameters Remove the vendor and product module parameters which were added a long time ago when we did not have the dynamic sysfs interface to add new device ids (and which isn't limited to five new vid/pid pair). A vid/pid pair can be added dynamically using sysfs, for example: echo 0451 1234 >/sys/bus/usb-serial/drivers/ti_usb_3410_5052_1/new_id for 1-port adapters, or echo 0451 1234 >/sys/bus/usb-serial/drivers/ti_usb_3410_5052_2/new_id for 2-port adapters. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ti_usb_3410_5052.c | 72 +++------------------------ 1 file changed, 7 insertions(+), 65 deletions(-) diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index f3e21f5f48f2..5585b20397fb 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -141,20 +141,9 @@ static int ti_download_firmware(struct ti_device *tdev); /* module parameters */ static int closing_wait = TI_DEFAULT_CLOSING_WAIT; -static ushort vendor_3410[TI_EXTRA_VID_PID_COUNT]; -static unsigned int vendor_3410_count; -static ushort product_3410[TI_EXTRA_VID_PID_COUNT]; -static unsigned int product_3410_count; -static ushort vendor_5052[TI_EXTRA_VID_PID_COUNT]; -static unsigned int vendor_5052_count; -static ushort product_5052[TI_EXTRA_VID_PID_COUNT]; -static unsigned int product_5052_count; /* supported devices */ -/* the array dimension is the number of default entries plus */ -/* TI_EXTRA_VID_PID_COUNT user defined entries plus 1 terminating */ -/* null entry */ -static struct usb_device_id ti_id_table_3410[15+TI_EXTRA_VID_PID_COUNT+1] = { +static struct usb_device_id ti_id_table_3410[] = { { USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) }, { USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) }, { USB_DEVICE(MTS_VENDOR_ID, MTS_GSM_NO_FW_PRODUCT_ID) }, @@ -171,16 +160,18 @@ static struct usb_device_id ti_id_table_3410[15+TI_EXTRA_VID_PID_COUNT+1] = { { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_STEREO_PLUG_ID) }, { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_STRIP_PORT_ID) }, { USB_DEVICE(TI_VENDOR_ID, FRI2_PRODUCT_ID) }, + { } /* terminator */ }; -static struct usb_device_id ti_id_table_5052[5+TI_EXTRA_VID_PID_COUNT+1] = { +static struct usb_device_id ti_id_table_5052[] = { { USB_DEVICE(TI_VENDOR_ID, TI_5052_BOOT_PRODUCT_ID) }, { USB_DEVICE(TI_VENDOR_ID, TI_5152_BOOT_PRODUCT_ID) }, { USB_DEVICE(TI_VENDOR_ID, TI_5052_EEPROM_PRODUCT_ID) }, { USB_DEVICE(TI_VENDOR_ID, TI_5052_FIRMWARE_PRODUCT_ID) }, + { } /* terminator */ }; -static struct usb_device_id ti_id_table_combined[19+2*TI_EXTRA_VID_PID_COUNT+1] = { +static struct usb_device_id ti_id_table_combined[] = { { USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) }, { USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) }, { USB_DEVICE(MTS_VENDOR_ID, MTS_GSM_NO_FW_PRODUCT_ID) }, @@ -200,7 +191,7 @@ static struct usb_device_id ti_id_table_combined[19+2*TI_EXTRA_VID_PID_COUNT+1] { USB_DEVICE(IBM_VENDOR_ID, IBM_454C_PRODUCT_ID) }, { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_PRODUCT_ID) }, { USB_DEVICE(TI_VENDOR_ID, FRI2_PRODUCT_ID) }, - { } + { } /* terminator */ }; static struct usb_serial_driver ti_1port_device = { @@ -289,61 +280,12 @@ module_param(closing_wait, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(closing_wait, "Maximum wait for data to drain in close, in .01 secs, default is 4000"); -module_param_array(vendor_3410, ushort, &vendor_3410_count, S_IRUGO); -MODULE_PARM_DESC(vendor_3410, - "Vendor ids for 3410 based devices, 1-5 short integers"); -module_param_array(product_3410, ushort, &product_3410_count, S_IRUGO); -MODULE_PARM_DESC(product_3410, - "Product ids for 3410 based devices, 1-5 short integers"); -module_param_array(vendor_5052, ushort, &vendor_5052_count, S_IRUGO); -MODULE_PARM_DESC(vendor_5052, - "Vendor ids for 5052 based devices, 1-5 short integers"); -module_param_array(product_5052, ushort, &product_5052_count, S_IRUGO); -MODULE_PARM_DESC(product_5052, - "Product ids for 5052 based devices, 1-5 short integers"); - MODULE_DEVICE_TABLE(usb, ti_id_table_combined); +module_usb_serial_driver(serial_drivers, ti_id_table_combined); /* Functions */ -static int __init ti_init(void) -{ - int i, j, c; - - /* insert extra vendor and product ids */ - c = ARRAY_SIZE(ti_id_table_combined) - 2 * TI_EXTRA_VID_PID_COUNT - 1; - j = ARRAY_SIZE(ti_id_table_3410) - TI_EXTRA_VID_PID_COUNT - 1; - for (i = 0; i < min(vendor_3410_count, product_3410_count); i++, j++, c++) { - ti_id_table_3410[j].idVendor = vendor_3410[i]; - ti_id_table_3410[j].idProduct = product_3410[i]; - ti_id_table_3410[j].match_flags = USB_DEVICE_ID_MATCH_DEVICE; - ti_id_table_combined[c].idVendor = vendor_3410[i]; - ti_id_table_combined[c].idProduct = product_3410[i]; - ti_id_table_combined[c].match_flags = USB_DEVICE_ID_MATCH_DEVICE; - } - j = ARRAY_SIZE(ti_id_table_5052) - TI_EXTRA_VID_PID_COUNT - 1; - for (i = 0; i < min(vendor_5052_count, product_5052_count); i++, j++, c++) { - ti_id_table_5052[j].idVendor = vendor_5052[i]; - ti_id_table_5052[j].idProduct = product_5052[i]; - ti_id_table_5052[j].match_flags = USB_DEVICE_ID_MATCH_DEVICE; - ti_id_table_combined[c].idVendor = vendor_5052[i]; - ti_id_table_combined[c].idProduct = product_5052[i]; - ti_id_table_combined[c].match_flags = USB_DEVICE_ID_MATCH_DEVICE; - } - - return usb_serial_register_drivers(serial_drivers, KBUILD_MODNAME, ti_id_table_combined); -} - -static void __exit ti_exit(void) -{ - usb_serial_deregister_drivers(serial_drivers); -} - -module_init(ti_init); -module_exit(ti_exit); - - static int ti_startup(struct usb_serial *serial) { struct ti_device *tdev; From f55876dec74edb4d4b3eeaaf1278c2835a4c20f0 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 28 Jun 2013 11:32:50 -0700 Subject: [PATCH 0462/3400] USB: usbatm: remove unused UDSL_ASSERT macro If this code isn't triggering this assert by now, it never will, so just remove it, it's pointless. Cc: Duncan Sands Acked-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/usbatm.c | 8 -------- drivers/usb/atm/usbatm.h | 12 ------------ 2 files changed, 20 deletions(-) diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c index 5e0d33a7da58..c76739c60568 100644 --- a/drivers/usb/atm/usbatm.c +++ b/drivers/usb/atm/usbatm.c @@ -344,7 +344,6 @@ static void usbatm_extract_one_cell(struct usbatm_data *instance, unsigned char __func__, sarb->len, vcc); /* discard cells already received */ skb_trim(sarb, 0); - UDSL_ASSERT(instance, sarb->tail + ATM_CELL_PAYLOAD <= sarb->end); } memcpy(skb_tail_pointer(sarb), source + ATM_CELL_HEADER, ATM_CELL_PAYLOAD); @@ -437,8 +436,6 @@ static void usbatm_extract_cells(struct usbatm_data *instance, unsigned char *cell_buf = instance->cell_buf; unsigned int space_left = stride - buf_usage; - UDSL_ASSERT(instance, buf_usage <= stride); - if (avail_data >= space_left) { /* add new data and process cell */ memcpy(cell_buf + buf_usage, source, space_left); @@ -481,7 +478,6 @@ static unsigned int usbatm_write_cells(struct usbatm_data *instance, vdbg(&instance->usb_intf->dev, "%s: skb->len=%d, avail_space=%u", __func__, skb->len, avail_space); - UDSL_ASSERT(instance, !(avail_space % stride)); for (bytes_written = 0; bytes_written < avail_space && ctrl->len; bytes_written += stride, target += stride) { @@ -553,8 +549,6 @@ static void usbatm_rx_process(unsigned long data) if (!urb->iso_frame_desc[i].status) { unsigned int actual_length = urb->iso_frame_desc[i].actual_length; - UDSL_ASSERT(instance, actual_length <= packet_size); - if (!merge_length) merge_start = (unsigned char *)urb->transfer_buffer + urb->iso_frame_desc[i].offset; merge_length += actual_length; @@ -1176,8 +1170,6 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id, struct urb *urb; unsigned int iso_packets = usb_pipeisoc(channel->endpoint) ? channel->buf_size / channel->packet_size : 0; - UDSL_ASSERT(instance, !usb_pipeisoc(channel->endpoint) || usb_pipein(channel->endpoint)); - urb = usb_alloc_urb(iso_packets, GFP_KERNEL); if (!urb) { dev_err(dev, "%s: no memory for urb %d!\n", __func__, i); diff --git a/drivers/usb/atm/usbatm.h b/drivers/usb/atm/usbatm.h index 5fc489405217..a2955b117e88 100644 --- a/drivers/usb/atm/usbatm.h +++ b/drivers/usb/atm/usbatm.h @@ -39,18 +39,6 @@ #define VERBOSE_DEBUG */ -#ifdef DEBUG -#define UDSL_ASSERT(instance, x) BUG_ON(!(x)) -#else -#define UDSL_ASSERT(instance, x) \ - do { \ - if (!(x)) \ - dev_warn(&(instance)->usb_intf->dev, \ - "failed assertion '%s' at line %d", \ - __stringify(x), __LINE__); \ - } while (0) -#endif - #define usb_err(instance, format, arg...) \ dev_err(&(instance)->usb_intf->dev , format , ## arg) #define usb_info(instance, format, arg...) \ From 0fef59d338a7e3384698084dd34d94b295708990 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 28 Jun 2013 11:32:51 -0700 Subject: [PATCH 0463/3400] USB: usbatm: remove unneeded trace printk calls We have an in-kernel trace subsystem, so use that instead of printk for trying to figure out what functions are being called. Cc: Duncan Sands Acked-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/usbatm.c | 34 ---------------------------------- 1 file changed, 34 deletions(-) diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c index c76739c60568..231ef4712e84 100644 --- a/drivers/usb/atm/usbatm.c +++ b/drivers/usb/atm/usbatm.c @@ -311,8 +311,6 @@ static void usbatm_extract_one_cell(struct usbatm_data *instance, unsigned char int vci = ((source[1] & 0x0f) << 12) | (source[2] << 4) | (source[3] >> 4); u8 pti = ((source[3] & 0xe) >> 1); - vdbg(&instance->usb_intf->dev, "%s: vpi %hd, vci %d, pti %d", __func__, vpi, vci, pti); - if ((vci != instance->cached_vci) || (vpi != instance->cached_vpi)) { instance->cached_vpi = vpi; instance->cached_vci = vci; @@ -476,9 +474,6 @@ static unsigned int usbatm_write_cells(struct usbatm_data *instance, unsigned int bytes_written; unsigned int stride = instance->tx_channel.stride; - vdbg(&instance->usb_intf->dev, "%s: skb->len=%d, avail_space=%u", - __func__, skb->len, avail_space); - for (bytes_written = 0; bytes_written < avail_space && ctrl->len; bytes_written += stride, target += stride) { unsigned int data_len = min_t(unsigned int, skb->len, ATM_CELL_PAYLOAD); @@ -639,7 +634,6 @@ static void usbatm_cancel_send(struct usbatm_data *instance, { struct sk_buff *skb, *n; - atm_dbg(instance, "%s entered\n", __func__); spin_lock_irq(&instance->sndqueue.lock); skb_queue_walk_safe(&instance->sndqueue, skb, n) { if (UDSL_SKB(skb)->atm.vcc == vcc) { @@ -657,7 +651,6 @@ static void usbatm_cancel_send(struct usbatm_data *instance, usbatm_pop(vcc, skb); } tasklet_enable(&instance->tx_channel.tasklet); - atm_dbg(instance, "%s done\n", __func__); } static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) @@ -675,9 +668,6 @@ static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) goto fail; } - vdbg(&instance->usb_intf->dev, "%s called (skb 0x%p, len %u)", __func__, - skb, skb->len); - if (vcc->qos.aal != ATM_AAL5) { atm_rldbg(instance, "%s: unsupported ATM type %d!\n", __func__, vcc->qos.aal); err = -EINVAL; @@ -717,8 +707,6 @@ static void usbatm_destroy_instance(struct kref *kref) { struct usbatm_data *instance = container_of(kref, struct usbatm_data, refcount); - usb_dbg(instance, "%s\n", __func__); - tasklet_kill(&instance->rx_channel.tasklet); tasklet_kill(&instance->tx_channel.tasklet); usb_put_dev(instance->usb_dev); @@ -727,15 +715,11 @@ static void usbatm_destroy_instance(struct kref *kref) static void usbatm_get_instance(struct usbatm_data *instance) { - usb_dbg(instance, "%s\n", __func__); - kref_get(&instance->refcount); } static void usbatm_put_instance(struct usbatm_data *instance) { - usb_dbg(instance, "%s\n", __func__); - kref_put(&instance->refcount, usbatm_destroy_instance); } @@ -751,7 +735,6 @@ static void usbatm_atm_dev_close(struct atm_dev *atm_dev) if (!instance) return; - usb_dbg(instance, "%s\n", __func__); atm_dev->dev_data = NULL; /* catch bugs */ usbatm_put_instance(instance); /* taken in usbatm_atm_init */ } @@ -807,8 +790,6 @@ static int usbatm_atm_open(struct atm_vcc *vcc) if (!instance) return -ENODEV; - atm_dbg(instance, "%s: vpi %hd, vci %d\n", __func__, vpi, vci); - /* only support AAL5 */ if ((vcc->qos.aal != ATM_AAL5)) { atm_warn(instance, "%s: unsupported ATM type %d!\n", __func__, vcc->qos.aal); @@ -885,11 +866,6 @@ static void usbatm_atm_close(struct atm_vcc *vcc) if (!instance || !vcc_data) return; - atm_dbg(instance, "%s entered\n", __func__); - - atm_dbg(instance, "%s: deallocating vcc 0x%p with vpi %d vci %d\n", - __func__, vcc_data, vcc_data->vpi, vcc_data->vci); - usbatm_cancel_send(instance, vcc); mutex_lock(&instance->serialize); /* vs self, usbatm_atm_open, usbatm_usb_disconnect */ @@ -916,8 +892,6 @@ static void usbatm_atm_close(struct atm_vcc *vcc) clear_bit(ATM_VF_ADDR, &vcc->flags); mutex_unlock(&instance->serialize); - - atm_dbg(instance, "%s successful\n", __func__); } static int usbatm_atm_ioctl(struct atm_dev *atm_dev, unsigned int cmd, @@ -1054,12 +1028,6 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id, int i, length; unsigned int maxpacket, num_packets; - dev_dbg(dev, "%s: trying driver %s with vendor=%04x, product=%04x, ifnum %2d\n", - __func__, driver->driver_name, - le16_to_cpu(usb_dev->descriptor.idVendor), - le16_to_cpu(usb_dev->descriptor.idProduct), - intf->altsetting->desc.bInterfaceNumber); - /* instance init */ instance = kzalloc(sizeof(*instance) + sizeof(struct urb *) * (num_rcv_urbs + num_snd_urbs), GFP_KERNEL); if (!instance) { @@ -1258,8 +1226,6 @@ void usbatm_usb_disconnect(struct usb_interface *intf) struct usbatm_vcc_data *vcc_data; int i; - dev_dbg(dev, "%s entered\n", __func__); - if (!instance) { dev_dbg(dev, "%s: NULL instance!\n", __func__); return; From ca4d701323f8450b1bf80359a41af8cbccc7731a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 28 Jun 2013 11:32:52 -0700 Subject: [PATCH 0464/3400] USB: usbatm: don't rely on CONFIG_USB_DEBUG Enable the USB atm drivers to use the dynamic debugging subsystem, and not rely on if CONFIG_USB_DEBUG is enabled or not for debugging messages. This also provides a saner debug message, pointing out the exact device the message is coming from. This also means the drivers do not have to be rebuilt to get debugging messages, important for getting information from users who can not rebuild their kernels. Cc: Duncan Sands Acked-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/usbatm.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/usb/atm/usbatm.h b/drivers/usb/atm/usbatm.h index a2955b117e88..71dd13994bbe 100644 --- a/drivers/usb/atm/usbatm.h +++ b/drivers/usb/atm/usbatm.h @@ -45,13 +45,8 @@ dev_info(&(instance)->usb_intf->dev , format , ## arg) #define usb_warn(instance, format, arg...) \ dev_warn(&(instance)->usb_intf->dev , format , ## arg) -#ifdef DEBUG #define usb_dbg(instance, format, arg...) \ - dev_printk(KERN_DEBUG , &(instance)->usb_intf->dev , format , ## arg) -#else -#define usb_dbg(instance, format, arg...) \ - do {} while (0) -#endif + dev_dbg(&(instance)->usb_intf->dev , format , ## arg) /* FIXME: move to dev_* once ATM is driver model aware */ #define atm_printk(level, instance, format, arg...) \ From 2d6401cf4ca3861692a4779745e0049cac769d10 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 28 Jun 2013 11:32:53 -0700 Subject: [PATCH 0465/3400] USB: usbatm: move the atm_dbg() call to use dynamic debug Move the atm_dbg() call to use the dynamic debug subsystem, and not rely on CONFIG_USB_DEBUG for if things should be printed out or not. This also means the drivers do not have to be rebuilt to get debugging messages, important for getting information from users who can not rebuild their kernels. Acked-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/usbatm.h | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/usb/atm/usbatm.h b/drivers/usb/atm/usbatm.h index 71dd13994bbe..5651231a7437 100644 --- a/drivers/usb/atm/usbatm.h +++ b/drivers/usb/atm/usbatm.h @@ -59,18 +59,12 @@ atm_printk(KERN_INFO, instance , format , ## arg) #define atm_warn(instance, format, arg...) \ atm_printk(KERN_WARNING, instance , format , ## arg) -#ifdef DEBUG -#define atm_dbg(instance, format, arg...) \ - atm_printk(KERN_DEBUG, instance , format , ## arg) -#define atm_rldbg(instance, format, arg...) \ +#define atm_dbg(instance, format, arg...) \ + dynamic_pr_debug("ATM dev %d: " format , \ + (instance)->atm_dev->number , ## arg) +#define atm_rldbg(instance, format, arg...) \ if (printk_ratelimit()) \ - atm_printk(KERN_DEBUG, instance , format , ## arg) -#else -#define atm_dbg(instance, format, arg...) \ - do {} while (0) -#define atm_rldbg(instance, format, arg...) \ - do {} while (0) -#endif + atm_dbg(instance , format , ## arg) /* flags, set by mini-driver in bind() */ From 2c21c985f1bc9f9b19ce258f38bb400ced3c7309 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 28 Jun 2013 11:32:54 -0700 Subject: [PATCH 0466/3400] USB: usbatm: remove CONFIG_USB_DEBUG dependancy Now that no USB atm driver is relying on the CONFIG_USB_DEBUG option (well, really the DEBUG option, thanks to some Makefile fun), remove it from the Makefile. Also remove two last vestiges of DEBUG in the usbatm.c driver, moving one to VERBOSE_DEBUG, which no one ever really cares about, and the other to use the dynamic debug subsystem. Cc: Duncan Sands Acked-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/Makefile | 3 --- drivers/usb/atm/usbatm.c | 7 +++---- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/usb/atm/Makefile b/drivers/usb/atm/Makefile index a5d792ec3ad5..ac278946b06c 100644 --- a/drivers/usb/atm/Makefile +++ b/drivers/usb/atm/Makefile @@ -1,9 +1,6 @@ # # Makefile for USB ATM/xDSL drivers # - -ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG - obj-$(CONFIG_USB_CXACRU) += cxacru.o obj-$(CONFIG_USB_SPEEDTOUCH) += speedtch.o obj-$(CONFIG_USB_UEAGLEATM) += ueagle-atm.o diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c index 231ef4712e84..25a7bfcf666c 100644 --- a/drivers/usb/atm/usbatm.c +++ b/drivers/usb/atm/usbatm.c @@ -661,7 +661,7 @@ static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) /* racy disconnection check - fine */ if (!instance || instance->disconnected) { -#ifdef DEBUG +#ifdef VERBOSE_DEBUG printk_ratelimited(KERN_DEBUG "%s: %s!\n", __func__, instance ? "disconnected" : "NULL instance"); #endif err = -ENODEV; @@ -1120,14 +1120,13 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id, instance->rx_channel.buf_size = num_packets * maxpacket; instance->rx_channel.packet_size = maxpacket; -#ifdef DEBUG for (i = 0; i < 2; i++) { struct usbatm_channel *channel = i ? &instance->tx_channel : &instance->rx_channel; - dev_dbg(dev, "%s: using %d byte buffer for %s channel 0x%p\n", __func__, channel->buf_size, i ? "tx" : "rx", channel); + dev_dbg(dev, "%s: using %d byte buffer for %s channel 0x%p\n", + __func__, channel->buf_size, i ? "tx" : "rx", channel); } -#endif /* initialize urbs */ From 523e531ea694eadf2957ee207bb4e0681e837057 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 28 Jun 2013 11:32:55 -0700 Subject: [PATCH 0467/3400] USB: phy: remove custom DBG macro Use the in-kernel pr_debug() calls instead of trying to roll your own DBG macro. This means the dynamic debugging calls now work here, and there is no dependency on CONFIG_USB_DEBUG for the phy code anymore. Acked-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/phy/phy-fsl-usb.c | 6 +++--- drivers/usb/phy/phy-fsm-usb.h | 11 ++--------- drivers/usb/phy/phy-isp1301-omap.c | 6 +----- 3 files changed, 6 insertions(+), 17 deletions(-) diff --git a/drivers/usb/phy/phy-fsl-usb.c b/drivers/usb/phy/phy-fsl-usb.c index e771bafb9f1d..181bfb10a57a 100644 --- a/drivers/usb/phy/phy-fsl-usb.c +++ b/drivers/usb/phy/phy-fsl-usb.c @@ -611,7 +611,7 @@ static int fsl_otg_set_peripheral(struct usb_otg *otg, otg_dev->fsm.b_bus_req = 1; /* start the gadget right away if the ID pin says Mini-B */ - DBG("ID pin=%d\n", otg_dev->fsm.id); + pr_debug("ID pin=%d\n", otg_dev->fsm.id); if (otg_dev->fsm.id == 1) { fsl_otg_start_host(&otg_dev->fsm, 0); otg_drv_vbus(&otg_dev->fsm, 0); @@ -684,7 +684,7 @@ static int fsl_otg_start_hnp(struct usb_otg *otg) if (otg_dev != fsl_otg_dev) return -ENODEV; - DBG("start_hnp...n"); + pr_debug("start_hnp...\n"); /* clear a_bus_req to enter a_suspend state */ otg_dev->fsm.a_bus_req = 0; @@ -941,7 +941,7 @@ int usb_otg_start(struct platform_device *pdev) p_otg->fsm.id = 0; } - DBG("initial ID pin=%d\n", p_otg->fsm.id); + pr_debug("initial ID pin=%d\n", p_otg->fsm.id); /* enable OTG ID pin interrupt */ temp = fsl_readl(&p_otg->dr_mem_map->otgsc); diff --git a/drivers/usb/phy/phy-fsm-usb.h b/drivers/usb/phy/phy-fsm-usb.h index c30a2e1d9e46..fbe586206f33 100644 --- a/drivers/usb/phy/phy-fsm-usb.h +++ b/drivers/usb/phy/phy-fsm-usb.h @@ -15,18 +15,11 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ -#undef DEBUG #undef VERBOSE -#ifdef DEBUG -#define DBG(fmt, args...) printk(KERN_DEBUG "[%s] " fmt , \ - __func__, ## args) -#else -#define DBG(fmt, args...) do {} while (0) -#endif - #ifdef VERBOSE -#define VDBG DBG +#define VDBG(fmt, args...) pr_debug("[%s] " fmt , \ + __func__, ## args) #else #define VDBG(stuff...) do {} while (0) #endif diff --git a/drivers/usb/phy/phy-isp1301-omap.c b/drivers/usb/phy/phy-isp1301-omap.c index ae481afcb3ec..d3a5160e4cc7 100644 --- a/drivers/usb/phy/phy-isp1301-omap.c +++ b/drivers/usb/phy/phy-isp1301-omap.c @@ -40,9 +40,7 @@ #include -#ifndef DEBUG -#undef VERBOSE -#endif +#undef VERBOSE #define DRIVER_VERSION "24 August 2004" @@ -387,7 +385,6 @@ static void b_idle(struct isp1301 *isp, const char *tag) static void dump_regs(struct isp1301 *isp, const char *label) { -#ifdef DEBUG u8 ctrl = isp1301_get_u8(isp, ISP1301_OTG_CONTROL_1); u8 status = isp1301_get_u8(isp, ISP1301_OTG_STATUS); u8 src = isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE); @@ -396,7 +393,6 @@ dump_regs(struct isp1301 *isp, const char *label) omap_readl(OTG_CTRL), label, state_name(isp), ctrl, status, src); /* mode control and irq enables don't change much */ -#endif } /*-------------------------------------------------------------------------*/ From 8fb822c5077c30258f27308d55f0eda5e398f3b6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 28 Jun 2013 11:32:56 -0700 Subject: [PATCH 0468/3400] USB: phy: remove CONFIG_USB_DEBUG usage Now that no USB phy driver is using CONFIG_USB_DEBUG, remove it from the Makefile. Acked-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/phy/Makefile | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index 070eca3af18b..98730ca1d5d3 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -1,9 +1,6 @@ # # Makefile for physical layer USB drivers # - -ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG - obj-$(CONFIG_USB_PHY) += phy.o obj-$(CONFIG_OF) += of.o From 0667fe76764927d986265e7405d8f4a4025f7d23 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 28 Jun 2013 11:32:57 -0700 Subject: [PATCH 0469/3400] USB: gadget: fix up comment This endif is for CONFIG_USB_GADGET_DEBUG_FILES, not CONFIG_USB_DEBUG, so document it properly. Acked-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/storage_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c index dbce3a9074e6..8c71212a8c52 100644 --- a/drivers/usb/gadget/storage_common.c +++ b/drivers/usb/gadget/storage_common.c @@ -172,7 +172,7 @@ MODULE_PARM_DESC(num_buffers, "Number of pipeline buffers"); */ #define fsg_num_buffers CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS -#endif /* CONFIG_USB_DEBUG */ +#endif /* CONFIG_USB_GADGET_DEBUG_FILES */ /* check if fsg_num_buffers is within a valid range */ static inline int fsg_num_buffers_validate(void) From 051a0689d64348264fb6e32736be283398b3f0c3 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 28 Jun 2013 11:32:58 -0700 Subject: [PATCH 0470/3400] USB: isp1362: remove unused _BUG_ON() calls We shouldn't ever panic in a driver, and these calls were never being used, so just delete them, as obviously the driver is working properly now (right?) Acked-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/isp1362-hcd.c | 2 -- drivers/usb/host/isp1362.h | 20 -------------------- 2 files changed, 22 deletions(-) diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c index b04e8ece4d35..c747ba35f731 100644 --- a/drivers/usb/host/isp1362-hcd.c +++ b/drivers/usb/host/isp1362-hcd.c @@ -350,8 +350,6 @@ static void isp1362_write_ptd(struct isp1362_hcd *isp1362_hcd, struct isp1362_ep struct ptd *ptd = &ep->ptd; int len = PTD_GET_DIR(ptd) == PTD_DIR_IN ? 0 : ep->length; - _BUG_ON(ep->ptd_offset < 0); - prefetch(ptd); isp1362_write_buffer(isp1362_hcd, ptd, ep->ptd_offset, PTD_HEADER_SIZE); if (len) diff --git a/drivers/usb/host/isp1362.h b/drivers/usb/host/isp1362.h index 0f97820e65be..4ef746dcef85 100644 --- a/drivers/usb/host/isp1362.h +++ b/drivers/usb/host/isp1362.h @@ -91,7 +91,6 @@ typedef const unsigned int isp1362_reg_t; #define ISP1362_REG_NO(r) ((r) & REG_NO_MASK) -#define _BUG_ON(x) BUG_ON(x) #define _WARN_ON(x) WARN_ON(x) #define ISP1362_REG(name, addr, width, rw) \ @@ -102,7 +101,6 @@ static isp1362_reg_t ISP1362_REG_##name = ((addr) | (width) | (rw)) #else typedef const unsigned char isp1362_reg_t; #define ISP1362_REG_NO(r) (r) -#define _BUG_ON(x) do {} while (0) #define _WARN_ON(x) do {} while (0) #define ISP1362_REG(name, addr, width, rw) \ @@ -645,9 +643,7 @@ static inline struct usb_hcd *isp1362_hcd_to_hcd(struct isp1362_hcd *isp1362_hcd */ static void isp1362_write_addr(struct isp1362_hcd *isp1362_hcd, isp1362_reg_t reg) { - /*_BUG_ON((reg & ISP1362_REG_WRITE_OFFSET) && !(reg & REG_ACCESS_W));*/ REG_ACCESS_TEST(reg); - _BUG_ON(!irqs_disabled()); DUMMY_DELAY_ACCESS; writew(ISP1362_REG_NO(reg), isp1362_hcd->addr_reg); DUMMY_DELAY_ACCESS; @@ -656,7 +652,6 @@ static void isp1362_write_addr(struct isp1362_hcd *isp1362_hcd, isp1362_reg_t re static void isp1362_write_data16(struct isp1362_hcd *isp1362_hcd, u16 val) { - _BUG_ON(!irqs_disabled()); DUMMY_DELAY_ACCESS; writew(val, isp1362_hcd->data_reg); } @@ -665,7 +660,6 @@ static u16 isp1362_read_data16(struct isp1362_hcd *isp1362_hcd) { u16 val; - _BUG_ON(!irqs_disabled()); DUMMY_DELAY_ACCESS; val = readw(isp1362_hcd->data_reg); @@ -674,7 +668,6 @@ static u16 isp1362_read_data16(struct isp1362_hcd *isp1362_hcd) static void isp1362_write_data32(struct isp1362_hcd *isp1362_hcd, u32 val) { - _BUG_ON(!irqs_disabled()); #if USE_32BIT DUMMY_DELAY_ACCESS; writel(val, isp1362_hcd->data_reg); @@ -690,7 +683,6 @@ static u32 isp1362_read_data32(struct isp1362_hcd *isp1362_hcd) { u32 val; - _BUG_ON(!irqs_disabled()); #if USE_32BIT DUMMY_DELAY_ACCESS; val = readl(isp1362_hcd->data_reg); @@ -713,8 +705,6 @@ static void isp1362_read_fifo(struct isp1362_hcd *isp1362_hcd, void *buf, u16 le if (!len) return; - _BUG_ON(!irqs_disabled()); - RDBG("%s: Reading %d byte from fifo to mem @ %p\n", __func__, len, buf); #if USE_32BIT if (len >= 4) { @@ -760,8 +750,6 @@ static void isp1362_write_fifo(struct isp1362_hcd *isp1362_hcd, void *buf, u16 l return; } - _BUG_ON(!irqs_disabled()); - RDBG("%s: Writing %d byte to fifo from memory @%p\n", __func__, len, buf); #if USE_32BIT if (len >= 4) { @@ -923,10 +911,6 @@ static void __attribute__((__unused__)) isp1362_show_regs(struct isp1362_hcd *is static void isp1362_write_diraddr(struct isp1362_hcd *isp1362_hcd, u16 offset, u16 len) { - _BUG_ON(offset & 1); - _BUG_ON(offset >= ISP1362_BUF_SIZE); - _BUG_ON(len > ISP1362_BUF_SIZE); - _BUG_ON(offset + len > ISP1362_BUF_SIZE); len = (len + 1) & ~1; isp1362_clr_mask16(isp1362_hcd, HCDMACFG, HCDMACFG_CTR_ENABLE); @@ -936,8 +920,6 @@ static void isp1362_write_diraddr(struct isp1362_hcd *isp1362_hcd, u16 offset, u static void isp1362_read_buffer(struct isp1362_hcd *isp1362_hcd, void *buf, u16 offset, int len) { - _BUG_ON(offset & 1); - isp1362_write_diraddr(isp1362_hcd, offset, len); DBG(3, "%s: Reading %d byte from buffer @%04x to memory @ %p\n", @@ -956,8 +938,6 @@ static void isp1362_read_buffer(struct isp1362_hcd *isp1362_hcd, void *buf, u16 static void isp1362_write_buffer(struct isp1362_hcd *isp1362_hcd, void *buf, u16 offset, int len) { - _BUG_ON(offset & 1); - isp1362_write_diraddr(isp1362_hcd, offset, len); DBG(3, "%s: Writing %d byte to buffer @%04x from memory @ %p\n", From 2809508d3b63c9fedf8daf23d08dd61f40a761f4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 28 Jun 2013 11:32:59 -0700 Subject: [PATCH 0471/3400] USB: isp1362: remove unused _WARN_ON() calls Like _BUG_ON(), _WARN_ON() wasn't ever being used, so just delete it, as obviously things are working properly now (if not, we have bigger problems...) Acked-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/isp1362.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/usb/host/isp1362.h b/drivers/usb/host/isp1362.h index 4ef746dcef85..e0f6f922052d 100644 --- a/drivers/usb/host/isp1362.h +++ b/drivers/usb/host/isp1362.h @@ -91,8 +91,6 @@ typedef const unsigned int isp1362_reg_t; #define ISP1362_REG_NO(r) ((r) & REG_NO_MASK) -#define _WARN_ON(x) WARN_ON(x) - #define ISP1362_REG(name, addr, width, rw) \ static isp1362_reg_t ISP1362_REG_##name = ((addr) | (width) | (rw)) @@ -101,7 +99,6 @@ static isp1362_reg_t ISP1362_REG_##name = ((addr) | (width) | (rw)) #else typedef const unsigned char isp1362_reg_t; #define ISP1362_REG_NO(r) (r) -#define _WARN_ON(x) do {} while (0) #define ISP1362_REG(name, addr, width, rw) \ static isp1362_reg_t ISP1362_REG_##name = addr @@ -926,14 +923,11 @@ static void isp1362_read_buffer(struct isp1362_hcd *isp1362_hcd, void *buf, u16 __func__, len, offset, buf); isp1362_write_reg16(isp1362_hcd, HCuPINT, HCuPINT_EOT); - _WARN_ON((isp1362_read_reg16(isp1362_hcd, HCuPINT) & HCuPINT_EOT)); isp1362_write_addr(isp1362_hcd, ISP1362_REG_HCDIRDATA); isp1362_read_fifo(isp1362_hcd, buf, len); - _WARN_ON(!(isp1362_read_reg16(isp1362_hcd, HCuPINT) & HCuPINT_EOT)); isp1362_write_reg16(isp1362_hcd, HCuPINT, HCuPINT_EOT); - _WARN_ON((isp1362_read_reg16(isp1362_hcd, HCuPINT) & HCuPINT_EOT)); } static void isp1362_write_buffer(struct isp1362_hcd *isp1362_hcd, void *buf, u16 offset, int len) @@ -944,14 +938,11 @@ static void isp1362_write_buffer(struct isp1362_hcd *isp1362_hcd, void *buf, u16 __func__, len, offset, buf); isp1362_write_reg16(isp1362_hcd, HCuPINT, HCuPINT_EOT); - _WARN_ON((isp1362_read_reg16(isp1362_hcd, HCuPINT) & HCuPINT_EOT)); isp1362_write_addr(isp1362_hcd, ISP1362_REG_HCDIRDATA | ISP1362_REG_WRITE_OFFSET); isp1362_write_fifo(isp1362_hcd, buf, len); - _WARN_ON(!(isp1362_read_reg16(isp1362_hcd, HCuPINT) & HCuPINT_EOT)); isp1362_write_reg16(isp1362_hcd, HCuPINT, HCuPINT_EOT); - _WARN_ON((isp1362_read_reg16(isp1362_hcd, HCuPINT) & HCuPINT_EOT)); } static void __attribute__((unused)) dump_data(char *buf, int len) From 374f4bfdf5b6a37a641c13ef22e0bbb42e0b3ac7 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 28 Jun 2013 11:33:00 -0700 Subject: [PATCH 0472/3400] USB: isp1362: remove _DBG() usage If you want a debug call, just make it, so move to using the already-there DBG() call. No need to make things more complex than they really need to be. Acked-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/isp1362-hcd.c | 30 +++++++++++++++--------------- drivers/usb/host/isp1362.h | 6 ------ 2 files changed, 15 insertions(+), 21 deletions(-) diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c index c747ba35f731..428d184ceb33 100644 --- a/drivers/usb/host/isp1362-hcd.c +++ b/drivers/usb/host/isp1362-hcd.c @@ -1573,12 +1573,12 @@ static int isp1362_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, DBG(0, "ClearHubFeature: "); switch (wValue) { case C_HUB_OVER_CURRENT: - _DBG(0, "C_HUB_OVER_CURRENT\n"); + DBG(0, "C_HUB_OVER_CURRENT\n"); spin_lock_irqsave(&isp1362_hcd->lock, flags); isp1362_write_reg32(isp1362_hcd, HCRHSTATUS, RH_HS_OCIC); spin_unlock_irqrestore(&isp1362_hcd->lock, flags); case C_HUB_LOCAL_POWER: - _DBG(0, "C_HUB_LOCAL_POWER\n"); + DBG(0, "C_HUB_LOCAL_POWER\n"); break; default: goto error; @@ -1589,7 +1589,7 @@ static int isp1362_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, switch (wValue) { case C_HUB_OVER_CURRENT: case C_HUB_LOCAL_POWER: - _DBG(0, "C_HUB_OVER_CURRENT or C_HUB_LOCAL_POWER\n"); + DBG(0, "C_HUB_OVER_CURRENT or C_HUB_LOCAL_POWER\n"); break; default: goto error; @@ -1620,36 +1620,36 @@ static int isp1362_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, switch (wValue) { case USB_PORT_FEAT_ENABLE: - _DBG(0, "USB_PORT_FEAT_ENABLE\n"); + DBG(0, "USB_PORT_FEAT_ENABLE\n"); tmp = RH_PS_CCS; break; case USB_PORT_FEAT_C_ENABLE: - _DBG(0, "USB_PORT_FEAT_C_ENABLE\n"); + DBG(0, "USB_PORT_FEAT_C_ENABLE\n"); tmp = RH_PS_PESC; break; case USB_PORT_FEAT_SUSPEND: - _DBG(0, "USB_PORT_FEAT_SUSPEND\n"); + DBG(0, "USB_PORT_FEAT_SUSPEND\n"); tmp = RH_PS_POCI; break; case USB_PORT_FEAT_C_SUSPEND: - _DBG(0, "USB_PORT_FEAT_C_SUSPEND\n"); + DBG(0, "USB_PORT_FEAT_C_SUSPEND\n"); tmp = RH_PS_PSSC; break; case USB_PORT_FEAT_POWER: - _DBG(0, "USB_PORT_FEAT_POWER\n"); + DBG(0, "USB_PORT_FEAT_POWER\n"); tmp = RH_PS_LSDA; break; case USB_PORT_FEAT_C_CONNECTION: - _DBG(0, "USB_PORT_FEAT_C_CONNECTION\n"); + DBG(0, "USB_PORT_FEAT_C_CONNECTION\n"); tmp = RH_PS_CSC; break; case USB_PORT_FEAT_C_OVER_CURRENT: - _DBG(0, "USB_PORT_FEAT_C_OVER_CURRENT\n"); + DBG(0, "USB_PORT_FEAT_C_OVER_CURRENT\n"); tmp = RH_PS_OCIC; break; case USB_PORT_FEAT_C_RESET: - _DBG(0, "USB_PORT_FEAT_C_RESET\n"); + DBG(0, "USB_PORT_FEAT_C_RESET\n"); tmp = RH_PS_PRSC; break; default: @@ -1669,7 +1669,7 @@ static int isp1362_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, wIndex--; switch (wValue) { case USB_PORT_FEAT_SUSPEND: - _DBG(0, "USB_PORT_FEAT_SUSPEND\n"); + DBG(0, "USB_PORT_FEAT_SUSPEND\n"); spin_lock_irqsave(&isp1362_hcd->lock, flags); isp1362_write_reg32(isp1362_hcd, HCRHPORT1 + wIndex, RH_PS_PSS); isp1362_hcd->rhport[wIndex] = @@ -1677,7 +1677,7 @@ static int isp1362_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, spin_unlock_irqrestore(&isp1362_hcd->lock, flags); break; case USB_PORT_FEAT_POWER: - _DBG(0, "USB_PORT_FEAT_POWER\n"); + DBG(0, "USB_PORT_FEAT_POWER\n"); spin_lock_irqsave(&isp1362_hcd->lock, flags); isp1362_write_reg32(isp1362_hcd, HCRHPORT1 + wIndex, RH_PS_PPS); isp1362_hcd->rhport[wIndex] = @@ -1685,7 +1685,7 @@ static int isp1362_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, spin_unlock_irqrestore(&isp1362_hcd->lock, flags); break; case USB_PORT_FEAT_RESET: - _DBG(0, "USB_PORT_FEAT_RESET\n"); + DBG(0, "USB_PORT_FEAT_RESET\n"); spin_lock_irqsave(&isp1362_hcd->lock, flags); t1 = jiffies + msecs_to_jiffies(USB_RESET_WIDTH); @@ -1719,7 +1719,7 @@ static int isp1362_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, default: error: /* "protocol stall" on error */ - _DBG(0, "PROTOCOL STALL\n"); + DBG(0, "PROTOCOL STALL\n"); retval = -EPIPE; } diff --git a/drivers/usb/host/isp1362.h b/drivers/usb/host/isp1362.h index e0f6f922052d..d36a90868900 100644 --- a/drivers/usb/host/isp1362.h +++ b/drivers/usb/host/isp1362.h @@ -588,14 +588,8 @@ static inline struct usb_hcd *isp1362_hcd_to_hcd(struct isp1362_hcd *isp1362_hcd if (dbg_level > level) \ pr_debug(fmt); \ } while (0) -#define _DBG(level, fmt...) \ - do { \ - if (dbg_level > level) \ - printk(fmt); \ - } while (0) #else #define DBG(fmt...) do {} while (0) -#define _DBG DBG #endif #ifdef VERBOSE From 641c86cd1cc6cb42233500a20e85ae5027826cfa Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 28 Jun 2013 11:33:01 -0700 Subject: [PATCH 0473/3400] USB: isp1362: remove CONFIG_USB_DEBUG dependency Now that the debugging macros are cleaned up, just rely on the dynamic debug code in the kernel to do the debug messages for the driver. This lets debugging be enabled without having to rebuild the driver, an important thing for users that can not do it. Acked-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/isp1362-hcd.c | 6 +----- drivers/usb/host/isp1362.h | 16 ++++------------ 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c index 428d184ceb33..fd76256c7e74 100644 --- a/drivers/usb/host/isp1362-hcd.c +++ b/drivers/usb/host/isp1362-hcd.c @@ -37,11 +37,7 @@ * recovery time (MSCx = 0x7f8c) with a memory clock of 99.53 MHz. */ -#ifdef CONFIG_USB_DEBUG -# define ISP1362_DEBUG -#else -# undef ISP1362_DEBUG -#endif +#undef ISP1362_DEBUG /* * The PXA255 UDC apparently doesn't handle GET_STATUS, GET_CONFIG and diff --git a/drivers/usb/host/isp1362.h b/drivers/usb/host/isp1362.h index d36a90868900..7b34699f5a65 100644 --- a/drivers/usb/host/isp1362.h +++ b/drivers/usb/host/isp1362.h @@ -76,14 +76,14 @@ static inline void delayed_insw(unsigned int addr, void *buf, int len) #define ISP1362_REG_WRITE_OFFSET 0x80 -#ifdef ISP1362_DEBUG -typedef const unsigned int isp1362_reg_t; - #define REG_WIDTH_16 0x000 #define REG_WIDTH_32 0x100 #define REG_WIDTH_MASK 0x100 #define REG_NO_MASK 0x0ff +#ifdef ISP1362_DEBUG +typedef const unsigned int isp1362_reg_t; + #define REG_ACCESS_R 0x200 #define REG_ACCESS_W 0x400 #define REG_ACCESS_RW 0x600 @@ -582,15 +582,11 @@ static inline struct usb_hcd *isp1362_hcd_to_hcd(struct isp1362_hcd *isp1362_hcd * ISP1362 HW Interface */ -#ifdef ISP1362_DEBUG #define DBG(level, fmt...) \ do { \ if (dbg_level > level) \ pr_debug(fmt); \ } while (0) -#else -#define DBG(fmt...) do {} while (0) -#endif #ifdef VERBOSE # define VDBG(fmt...) DBG(3, fmt) @@ -833,7 +829,6 @@ static void isp1362_write_fifo(struct isp1362_hcd *isp1362_hcd, void *buf, u16 l isp1362_write_reg32(d, r, __v & ~m); \ } -#ifdef ISP1362_DEBUG #define isp1362_show_reg(d, r) { \ if ((ISP1362_REG_##r & REG_WIDTH_MASK) == REG_WIDTH_32) \ DBG(0, "%-12s[%02x]: %08x\n", #r, \ @@ -842,9 +837,6 @@ static void isp1362_write_fifo(struct isp1362_hcd *isp1362_hcd, void *buf, u16 l DBG(0, "%-12s[%02x]: %04x\n", #r, \ ISP1362_REG_NO(ISP1362_REG_##r), isp1362_read_reg16(d, r)); \ } -#else -#define isp1362_show_reg(d, r) do {} while (0) -#endif static void __attribute__((__unused__)) isp1362_show_regs(struct isp1362_hcd *isp1362_hcd) { @@ -967,7 +959,7 @@ static void __attribute__((unused)) dump_data(char *buf, int len) } } -#if defined(ISP1362_DEBUG) && defined(PTD_TRACE) +#if defined(PTD_TRACE) static void dump_ptd(struct ptd *ptd) { From 1d896ceae46d61412a575a4fc269f5eb4b0397d6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 28 Jun 2013 11:33:02 -0700 Subject: [PATCH 0474/3400] USB: isp116x: remove dependency on CONFIG_USB_DEBUG Move all debugging messages in the driver to use the dynamic debug subsystem, and not rely on CONFIG_USB_DEBUG to turn them on or off. This lets debugging be enabled without having to rebuild the driver, an important thing for users that can not do it. It also removes the pointless IRQ_TEST() macro, as that was totally useless and obviously never used. Cc: Olav Kongas Acked-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/isp116x.h | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/usb/host/isp116x.h b/drivers/usb/host/isp116x.h index 9a2c400e6090..dd34b7a33965 100644 --- a/drivers/usb/host/isp116x.h +++ b/drivers/usb/host/isp116x.h @@ -325,11 +325,7 @@ struct isp116x_ep { /*-------------------------------------------------------------------------*/ -#ifdef DEBUG -#define DBG(stuff...) printk(KERN_DEBUG "116x: " stuff) -#else -#define DBG(stuff...) do{}while(0) -#endif +#define DBG(stuff...) pr_debug("116x: " stuff) #ifdef VERBOSE # define VDBG DBG @@ -358,15 +354,8 @@ struct isp116x_ep { #define isp116x_check_platform_delay(h) 0 #endif -#if defined(DEBUG) -#define IRQ_TEST() BUG_ON(!irqs_disabled()) -#else -#define IRQ_TEST() do{}while(0) -#endif - static inline void isp116x_write_addr(struct isp116x *isp116x, unsigned reg) { - IRQ_TEST(); writew(reg & 0xff, isp116x->addr_reg); isp116x_delay(isp116x, 300); } From e45282829a814a7f1e857427f218b21aef012e52 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 28 Jun 2013 11:33:03 -0700 Subject: [PATCH 0475/3400] USB: sl811: remove CONFIG_USB_DEBUG dependency This removes the dependency of the driver on CONFIG_USB_DEBUG and moves it to us the dynamic debug subsystem instead. Bonus is the fact that we can now properly determine the exact hardware that is spitting out the messages. This lets debugging be enabled without having to rebuild the driver, an important thing for users that can not do it. Acked-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/sl811-hcd.c | 69 +++++++++++++++++++++--------------- drivers/usb/host/sl811.h | 19 +--------- 2 files changed, 42 insertions(+), 46 deletions(-) diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index b2ec7fe758dd..c11c5d8f94e0 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c @@ -100,7 +100,8 @@ static void port_power(struct sl811 *sl811, int is_on) if (sl811->board && sl811->board->port_power) { /* switch VBUS, at 500mA unless hub power budget gets set */ - DBG("power %s\n", is_on ? "on" : "off"); + dev_dbg(hcd->self.controller, "power %s\n", + is_on ? "on" : "off"); sl811->board->port_power(hcd->self.controller, is_on); } @@ -282,7 +283,7 @@ static inline void sofirq_on(struct sl811 *sl811) { if (sl811->irq_enable & SL11H_INTMASK_SOFINTR) return; - VDBG("sof irq on\n"); + dev_dbg(sl811_to_hcd(sl811)->self.controller, "sof irq on\n"); sl811->irq_enable |= SL11H_INTMASK_SOFINTR; } @@ -290,7 +291,7 @@ static inline void sofirq_off(struct sl811 *sl811) { if (!(sl811->irq_enable & SL11H_INTMASK_SOFINTR)) return; - VDBG("sof irq off\n"); + dev_dbg(sl811_to_hcd(sl811)->self.controller, "sof irq off\n"); sl811->irq_enable &= ~SL11H_INTMASK_SOFINTR; } @@ -338,7 +339,8 @@ static struct sl811h_ep *start(struct sl811 *sl811, u8 bank) } if (unlikely(list_empty(&ep->hep->urb_list))) { - DBG("empty %p queue?\n", ep); + dev_dbg(sl811_to_hcd(sl811)->self.controller, + "empty %p queue?\n", ep); return NULL; } @@ -391,7 +393,8 @@ static struct sl811h_ep *start(struct sl811 *sl811, u8 bank) status_packet(sl811, ep, urb, bank, control); break; default: - DBG("bad ep%p pid %02x\n", ep, ep->nextpid); + dev_dbg(sl811_to_hcd(sl811)->self.controller, + "bad ep%p pid %02x\n", ep, ep->nextpid); ep = NULL; } return ep; @@ -447,7 +450,8 @@ static void finish_request( } /* periodic deschedule */ - DBG("deschedule qh%d/%p branch %d\n", ep->period, ep, ep->branch); + dev_dbg(sl811_to_hcd(sl811)->self.controller, + "deschedule qh%d/%p branch %d\n", ep->period, ep, ep->branch); for (i = ep->branch; i < PERIODIC_SIZE; i += ep->period) { struct sl811h_ep *temp; struct sl811h_ep **prev = &sl811->periodic[i]; @@ -593,7 +597,8 @@ static inline u8 checkdone(struct sl811 *sl811) ctl = sl811_read(sl811, SL811_EP_A(SL11H_HOSTCTLREG)); if (ctl & SL11H_HCTLMASK_ARM) sl811_write(sl811, SL811_EP_A(SL11H_HOSTCTLREG), 0); - DBG("%s DONE_A: ctrl %02x sts %02x\n", + dev_dbg(sl811_to_hcd(sl811)->self.controller, + "%s DONE_A: ctrl %02x sts %02x\n", (ctl & SL11H_HCTLMASK_ARM) ? "timeout" : "lost", ctl, sl811_read(sl811, SL811_EP_A(SL11H_PKTSTATREG))); @@ -604,7 +609,8 @@ static inline u8 checkdone(struct sl811 *sl811) ctl = sl811_read(sl811, SL811_EP_B(SL11H_HOSTCTLREG)); if (ctl & SL11H_HCTLMASK_ARM) sl811_write(sl811, SL811_EP_B(SL11H_HOSTCTLREG), 0); - DBG("%s DONE_B: ctrl %02x sts %02x\n", + dev_dbg(sl811_to_hcd(sl811)->self.controller, + "%s DONE_B: ctrl %02x sts %02x\n", (ctl & SL11H_HCTLMASK_ARM) ? "timeout" : "lost", ctl, sl811_read(sl811, SL811_EP_B(SL11H_PKTSTATREG))); @@ -665,7 +671,7 @@ retry: * this one has nothing scheduled. */ if (sl811->next_periodic) { - // ERR("overrun to slot %d\n", index); + // dev_err(hcd->self.controller, "overrun to slot %d\n", index); sl811->stat_overrun++; } if (sl811->periodic[index]) @@ -723,7 +729,7 @@ retry: } else if (irqstat & SL11H_INTMASK_RD) { if (sl811->port1 & USB_PORT_STAT_SUSPEND) { - DBG("wakeup\n"); + dev_dbg(hcd->self.controller, "wakeup\n"); sl811->port1 |= USB_PORT_STAT_C_SUSPEND << 16; sl811->stat_wake++; } else @@ -852,8 +858,9 @@ static int sl811h_urb_enqueue( if (ep->maxpacket > H_MAXPACKET) { /* iso packets up to 240 bytes could work... */ - DBG("dev %d ep%d maxpacket %d\n", - udev->devnum, epnum, ep->maxpacket); + dev_dbg(hcd->self.controller, + "dev %d ep%d maxpacket %d\n", udev->devnum, + epnum, ep->maxpacket); retval = -EINVAL; kfree(ep); goto fail; @@ -917,7 +924,8 @@ static int sl811h_urb_enqueue( * to share the faster parts of the tree without needing * dummy/placeholder nodes */ - DBG("schedule qh%d/%p branch %d\n", ep->period, ep, ep->branch); + dev_dbg(hcd->self.controller, "schedule qh%d/%p branch %d\n", + ep->period, ep, ep->branch); for (i = ep->branch; i < PERIODIC_SIZE; i += ep->period) { struct sl811h_ep **prev = &sl811->periodic[i]; struct sl811h_ep *here = *prev; @@ -976,7 +984,8 @@ static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) } else if (sl811->active_a == ep) { if (time_before_eq(sl811->jiffies_a, jiffies)) { /* happens a lot with lowspeed?? */ - DBG("giveup on DONE_A: ctrl %02x sts %02x\n", + dev_dbg(hcd->self.controller, + "giveup on DONE_A: ctrl %02x sts %02x\n", sl811_read(sl811, SL811_EP_A(SL11H_HOSTCTLREG)), sl811_read(sl811, @@ -990,7 +999,8 @@ static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) } else if (sl811->active_b == ep) { if (time_before_eq(sl811->jiffies_a, jiffies)) { /* happens a lot with lowspeed?? */ - DBG("giveup on DONE_B: ctrl %02x sts %02x\n", + dev_dbg(hcd->self.controller, + "giveup on DONE_B: ctrl %02x sts %02x\n", sl811_read(sl811, SL811_EP_B(SL11H_HOSTCTLREG)), sl811_read(sl811, @@ -1008,7 +1018,8 @@ static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) if (urb) finish_request(sl811, ep, urb, 0); else - VDBG("dequeue, urb %p active %s; wait4irq\n", urb, + dev_dbg(sl811_to_hcd(sl811)->self.controller, + "dequeue, urb %p active %s; wait4irq\n", urb, (sl811->active_a == ep) ? "A" : "B"); } else retval = -EINVAL; @@ -1029,7 +1040,7 @@ sl811h_endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep) if (!list_empty(&hep->urb_list)) msleep(3); if (!list_empty(&hep->urb_list)) - WARNING("ep %p not empty?\n", ep); + dev_warn(hcd->self.controller, "ep %p not empty?\n", ep); kfree(ep); hep->hcpriv = NULL; @@ -1132,7 +1143,7 @@ sl811h_timer(unsigned long _sl811) switch (signaling) { case SL11H_CTL1MASK_SE0: - DBG("end reset\n"); + dev_dbg(sl811_to_hcd(sl811)->self.controller, "end reset\n"); sl811->port1 = (USB_PORT_STAT_C_RESET << 16) | USB_PORT_STAT_POWER; sl811->ctrl1 = 0; @@ -1141,11 +1152,12 @@ sl811h_timer(unsigned long _sl811) irqstat &= ~SL11H_INTMASK_RD; break; case SL11H_CTL1MASK_K: - DBG("end resume\n"); + dev_dbg(sl811_to_hcd(sl811)->self.controller, "end resume\n"); sl811->port1 &= ~USB_PORT_STAT_SUSPEND; break; default: - DBG("odd timer signaling: %02x\n", signaling); + dev_dbg(sl811_to_hcd(sl811)->self.controller, + "odd timer signaling: %02x\n", signaling); break; } sl811_write(sl811, SL11H_IRQ_STATUS, irqstat); @@ -1243,7 +1255,7 @@ sl811h_hub_control( break; /* 20 msec of resume/K signaling, other irqs blocked */ - DBG("start resume...\n"); + dev_dbg(hcd->self.controller, "start resume...\n"); sl811->irq_enable = 0; sl811_write(sl811, SL11H_IRQ_ENABLE, sl811->irq_enable); @@ -1281,7 +1293,8 @@ sl811h_hub_control( #ifndef VERBOSE if (*(u16*)(buf+2)) /* only if wPortChange is interesting */ #endif - DBG("GetPortStatus %08x\n", sl811->port1); + dev_dbg(hcd->self.controller, "GetPortStatus %08x\n", + sl811->port1); break; case SetPortFeature: if (wIndex != 1 || wLength != 0) @@ -1293,7 +1306,7 @@ sl811h_hub_control( if (!(sl811->port1 & USB_PORT_STAT_ENABLE)) goto error; - DBG("suspend...\n"); + dev_dbg(hcd->self.controller,"suspend...\n"); sl811->ctrl1 &= ~SL11H_CTL1MASK_SOF_ENA; sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1); break; @@ -1338,7 +1351,7 @@ static int sl811h_bus_suspend(struct usb_hcd *hcd) { // SOFs off - DBG("%s\n", __func__); + dev_dbg(hcd->self.controller, "%s\n", __func__); return 0; } @@ -1346,7 +1359,7 @@ static int sl811h_bus_resume(struct usb_hcd *hcd) { // SOFs on - DBG("%s\n", __func__); + dev_dbg(hcd->self.controller, "%s\n", __func__); return 0; } @@ -1648,7 +1661,7 @@ sl811h_probe(struct platform_device *dev) /* refuse to confuse usbcore */ if (dev->dev.dma_mask) { - DBG("no we won't dma\n"); + dev_dbg(&dev->dev, "no we won't dma\n"); return -EINVAL; } @@ -1716,7 +1729,7 @@ sl811h_probe(struct platform_device *dev) break; default: /* reject case 0, SL11S is less functional */ - DBG("chiprev %02x\n", tmp); + dev_dbg(&dev->dev, "chiprev %02x\n", tmp); retval = -ENXIO; goto err6; } @@ -1747,7 +1760,7 @@ sl811h_probe(struct platform_device *dev) if (!ioaddr) iounmap(addr_reg); err2: - DBG("init error, %d\n", retval); + dev_dbg(&dev->dev, "init error, %d\n", retval); return retval; } diff --git a/drivers/usb/host/sl811.h b/drivers/usb/host/sl811.h index b6b8c1f233dd..7ac5c5ee4a3e 100644 --- a/drivers/usb/host/sl811.h +++ b/drivers/usb/host/sl811.h @@ -242,25 +242,8 @@ sl811_read_buf(struct sl811 *sl811, int addr, void *buf, size_t count) /*-------------------------------------------------------------------------*/ -#ifdef DEBUG -#define DBG(stuff...) printk(KERN_DEBUG "sl811: " stuff) -#else -#define DBG(stuff...) do{}while(0) -#endif - -#ifdef VERBOSE -# define VDBG DBG -#else -# define VDBG(stuff...) do{}while(0) -#endif - #ifdef PACKET_TRACE -# define PACKET VDBG +# define PACKET pr_debug("sl811: "stuff) #else # define PACKET(stuff...) do{}while(0) #endif - -#define ERR(stuff...) printk(KERN_ERR "sl811: " stuff) -#define WARNING(stuff...) printk(KERN_WARNING "sl811: " stuff) -#define INFO(stuff...) printk(KERN_INFO "sl811: " stuff) - From 137084bbaddf4f6dde948ef3a14e18ba0754cc0d Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 07:04:46 -0400 Subject: [PATCH 0476/3400] tty: Fix tty_ldisc_lock name collision The file scope spinlock identifier, tty_ldisc_lock, will collide with the file scope lock function tty_ldisc_lock() so rename it. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 4 ++-- drivers/tty/tty_ldisc.c | 46 ++++++++++++++++++++--------------------- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 366af832794b..fa80af3656a3 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -603,7 +603,7 @@ static int tty_signal_session_leader(struct tty_struct *tty, int exit_session) * BTM * redirect lock for undoing redirection * file list lock for manipulating list of ttys - * tty_ldisc_lock from called functions + * tty_ldiscs_lock from called functions * termios_mutex resetting termios data * tasklist_lock to walk task list for hangup event * ->siglock to protect ->signal/->sighand @@ -2202,7 +2202,7 @@ static int tty_fasync(int fd, struct file *filp, int on) * FIXME: does not honour flow control ?? * * Locking: - * Called functions take tty_ldisc_lock + * Called functions take tty_ldiscs_lock * current->signal->tty check is safe without locks * * FIXME: may race normal receive processing diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 1afe192bef6a..8166260aa839 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -37,7 +37,7 @@ * callers who will do ldisc lookups and cannot sleep. */ -static DEFINE_RAW_SPINLOCK(tty_ldisc_lock); +static DEFINE_RAW_SPINLOCK(tty_ldiscs_lock); static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait); /* Line disc dispatch table */ static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS]; @@ -52,7 +52,7 @@ static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS]; * from this point onwards. * * Locking: - * takes tty_ldisc_lock to guard against ldisc races + * takes tty_ldiscs_lock to guard against ldisc races */ int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc) @@ -63,11 +63,11 @@ int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc) if (disc < N_TTY || disc >= NR_LDISCS) return -EINVAL; - raw_spin_lock_irqsave(&tty_ldisc_lock, flags); + raw_spin_lock_irqsave(&tty_ldiscs_lock, flags); tty_ldiscs[disc] = new_ldisc; new_ldisc->num = disc; new_ldisc->refcount = 0; - raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags); + raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags); return ret; } @@ -82,7 +82,7 @@ EXPORT_SYMBOL(tty_register_ldisc); * currently in use. * * Locking: - * takes tty_ldisc_lock to guard against ldisc races + * takes tty_ldiscs_lock to guard against ldisc races */ int tty_unregister_ldisc(int disc) @@ -93,12 +93,12 @@ int tty_unregister_ldisc(int disc) if (disc < N_TTY || disc >= NR_LDISCS) return -EINVAL; - raw_spin_lock_irqsave(&tty_ldisc_lock, flags); + raw_spin_lock_irqsave(&tty_ldiscs_lock, flags); if (tty_ldiscs[disc]->refcount) ret = -EBUSY; else tty_ldiscs[disc] = NULL; - raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags); + raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags); return ret; } @@ -109,7 +109,7 @@ static struct tty_ldisc_ops *get_ldops(int disc) unsigned long flags; struct tty_ldisc_ops *ldops, *ret; - raw_spin_lock_irqsave(&tty_ldisc_lock, flags); + raw_spin_lock_irqsave(&tty_ldiscs_lock, flags); ret = ERR_PTR(-EINVAL); ldops = tty_ldiscs[disc]; if (ldops) { @@ -119,7 +119,7 @@ static struct tty_ldisc_ops *get_ldops(int disc) ret = ldops; } } - raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags); + raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags); return ret; } @@ -127,10 +127,10 @@ static void put_ldops(struct tty_ldisc_ops *ldops) { unsigned long flags; - raw_spin_lock_irqsave(&tty_ldisc_lock, flags); + raw_spin_lock_irqsave(&tty_ldiscs_lock, flags); ldops->refcount--; module_put(ldops->owner); - raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags); + raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags); } /** @@ -143,7 +143,7 @@ static void put_ldops(struct tty_ldisc_ops *ldops) * available * * Locking: - * takes tty_ldisc_lock to guard against ldisc races + * takes tty_ldiscs_lock to guard against ldisc races */ static struct tty_ldisc *tty_ldisc_get(int disc) @@ -191,7 +191,7 @@ static inline void tty_ldisc_put(struct tty_ldisc *ld) if (WARN_ON_ONCE(!ld)) return; - raw_spin_lock_irqsave(&tty_ldisc_lock, flags); + raw_spin_lock_irqsave(&tty_ldiscs_lock, flags); /* unreleased reader reference(s) will cause this WARN */ WARN_ON(!atomic_dec_and_test(&ld->users)); @@ -199,7 +199,7 @@ static inline void tty_ldisc_put(struct tty_ldisc *ld) ld->ops->refcount--; module_put(ld->ops->owner); kfree(ld); - raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags); + raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags); } static void *tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos) @@ -259,7 +259,7 @@ const struct file_operations tty_ldiscs_proc_fops = { * used to implement both the waiting and non waiting versions * of tty_ldisc_ref * - * Locking: takes tty_ldisc_lock + * Locking: takes tty_ldiscs_lock */ static struct tty_ldisc *tty_ldisc_try(struct tty_struct *tty) @@ -268,13 +268,13 @@ static struct tty_ldisc *tty_ldisc_try(struct tty_struct *tty) struct tty_ldisc *ld; /* FIXME: this allows reference acquire after TTY_LDISC is cleared */ - raw_spin_lock_irqsave(&tty_ldisc_lock, flags); + raw_spin_lock_irqsave(&tty_ldiscs_lock, flags); ld = NULL; if (test_bit(TTY_LDISC, &tty->flags) && tty->ldisc) { ld = tty->ldisc; atomic_inc(&ld->users); } - raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags); + raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags); return ld; } @@ -291,7 +291,7 @@ static struct tty_ldisc *tty_ldisc_try(struct tty_struct *tty) * against a discipline change, such as an existing ldisc reference * (which we check for) * - * Locking: call functions take tty_ldisc_lock + * Locking: call functions take tty_ldiscs_lock */ struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty) @@ -312,7 +312,7 @@ EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait); * reference to it. If the line discipline is in flux then * return NULL. Can be called from IRQ and timer functions. * - * Locking: called functions take tty_ldisc_lock + * Locking: called functions take tty_ldiscs_lock */ struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty) @@ -328,7 +328,7 @@ EXPORT_SYMBOL_GPL(tty_ldisc_ref); * Undoes the effect of tty_ldisc_ref or tty_ldisc_ref_wait. May * be called in IRQ context. * - * Locking: takes tty_ldisc_lock + * Locking: takes tty_ldiscs_lock */ void tty_ldisc_deref(struct tty_ldisc *ld) @@ -338,13 +338,13 @@ void tty_ldisc_deref(struct tty_ldisc *ld) if (WARN_ON_ONCE(!ld)) return; - raw_spin_lock_irqsave(&tty_ldisc_lock, flags); + raw_spin_lock_irqsave(&tty_ldiscs_lock, flags); /* * WARNs if one-too-many reader references were released * - the last reference must be released with tty_ldisc_put */ WARN_ON(atomic_dec_and_test(&ld->users)); - raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags); + raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags); if (waitqueue_active(&ld->wq_idle)) wake_up(&ld->wq_idle); @@ -593,7 +593,7 @@ static bool tty_ldisc_hangup_halt(struct tty_struct *tty) * overlapping ldisc change (including on the other end of pty pairs), * the close of one side of a tty/pty pair, and eventually hangup. * - * Locking: takes tty_ldisc_lock, termios_mutex + * Locking: takes tty_ldiscs_lock, termios_mutex */ int tty_set_ldisc(struct tty_struct *tty, int ldisc) From d2c438905f9f718b3d9f5d89ce163fc22bd33995 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 07:04:47 -0400 Subject: [PATCH 0477/3400] tty: Add lock/unlock ldisc pair functions Just as the tty pair must be locked in a stable sequence (ie, independent of which is consider the 'other' tty), so must the ldisc pair be locked in a stable sequence as well. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_ldisc.c | 87 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 8166260aa839..418c9f64a9fd 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -31,6 +31,13 @@ #define tty_ldisc_debug(tty, f, args...) #endif +/* lockdep nested classes for tty->ldisc_sem */ +enum { + LDISC_SEM_NORMAL, + LDISC_SEM_OTHER, +}; + + /* * This guards the refcounted line discipline lists. The lock * must be taken with irqs off because there are hangup path @@ -351,6 +358,86 @@ void tty_ldisc_deref(struct tty_ldisc *ld) } EXPORT_SYMBOL_GPL(tty_ldisc_deref); + +static inline int __lockfunc +tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout) +{ + return ldsem_down_write(&tty->ldisc_sem, timeout); +} + +static inline int __lockfunc +tty_ldisc_lock_nested(struct tty_struct *tty, unsigned long timeout) +{ + return ldsem_down_write_nested(&tty->ldisc_sem, + LDISC_SEM_OTHER, timeout); +} + +static inline void tty_ldisc_unlock(struct tty_struct *tty) +{ + return ldsem_up_write(&tty->ldisc_sem); +} + +static int __lockfunc +tty_ldisc_lock_pair_timeout(struct tty_struct *tty, struct tty_struct *tty2, + unsigned long timeout) +{ + int ret; + + if (tty < tty2) { + ret = tty_ldisc_lock(tty, timeout); + if (ret) { + ret = tty_ldisc_lock_nested(tty2, timeout); + if (!ret) + tty_ldisc_unlock(tty); + } + } else { + /* if this is possible, it has lots of implications */ + WARN_ON_ONCE(tty == tty2); + if (tty2 && tty != tty2) { + ret = tty_ldisc_lock(tty2, timeout); + if (ret) { + ret = tty_ldisc_lock_nested(tty, timeout); + if (!ret) + tty_ldisc_unlock(tty2); + } + } else + ret = tty_ldisc_lock(tty, timeout); + } + + if (!ret) + return -EBUSY; + + set_bit(TTY_LDISC_HALTED, &tty->flags); + if (tty2) + set_bit(TTY_LDISC_HALTED, &tty2->flags); + return 0; +} + +static void __lockfunc +tty_ldisc_lock_pair(struct tty_struct *tty, struct tty_struct *tty2) +{ + tty_ldisc_lock_pair_timeout(tty, tty2, MAX_SCHEDULE_TIMEOUT); +} + +static void __lockfunc tty_ldisc_unlock_pair(struct tty_struct *tty, + struct tty_struct *tty2) +{ + tty_ldisc_unlock(tty); + if (tty2) + tty_ldisc_unlock(tty2); +} + +static void __lockfunc tty_ldisc_enable_pair(struct tty_struct *tty, + struct tty_struct *tty2) +{ + clear_bit(TTY_LDISC_HALTED, &tty->flags); + if (tty2) + clear_bit(TTY_LDISC_HALTED, &tty2->flags); + + tty_ldisc_unlock_pair(tty, tty2); +} + + /** * tty_ldisc_enable - allow ldisc use * @tty: terminal to activate ldisc on From 36697529b5bbe36911e39a6309e7a7c9250d280a Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 07:04:48 -0400 Subject: [PATCH 0478/3400] tty: Replace ldisc locking with ldisc_sem Line discipline locking was performed with a combination of a mutex, a status bit, a count, and a waitqueue -- basically, a rw semaphore. Replace the existing combination with an ld_semaphore. Fixes: 1) the 'reference acquire after ldisc locked' bug 2) the over-complicated halt mechanism 3) lock order wrt. tty_lock() 4) dropping locks while changing ldisc 5) previously unidentified deadlock while locking ldisc from both linked ttys concurrently 6) previously unidentified recursive deadlocks Adds much-needed lockdep diagnostics. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_buffer.c | 2 +- drivers/tty/tty_io.c | 7 +- drivers/tty/tty_ldisc.c | 329 ++++++-------------------------------- include/linux/tty.h | 4 +- include/linux/tty_ldisc.h | 3 +- 5 files changed, 52 insertions(+), 293 deletions(-) diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index 9121c1f7aeef..a42a028a9d4e 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -429,7 +429,7 @@ static void flush_to_ldisc(struct work_struct *work) return; disc = tty_ldisc_ref(tty); - if (disc == NULL) /* !TTY_LDISC */ + if (disc == NULL) return; spin_lock_irqsave(&buf->lock, flags); diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index fa80af3656a3..0fa5db4c7a7a 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -1388,8 +1388,7 @@ static int tty_reopen(struct tty_struct *tty) struct tty_driver *driver = tty->driver; if (test_bit(TTY_CLOSING, &tty->flags) || - test_bit(TTY_HUPPING, &tty->flags) || - test_bit(TTY_LDISC_CHANGING, &tty->flags)) + test_bit(TTY_HUPPING, &tty->flags)) return -EIO; if (driver->type == TTY_DRIVER_TYPE_PTY && @@ -1405,7 +1404,7 @@ static int tty_reopen(struct tty_struct *tty) } tty->count++; - WARN_ON(!test_bit(TTY_LDISC, &tty->flags)); + WARN_ON(!tty->ldisc); return 0; } @@ -3017,7 +3016,7 @@ void initialize_tty_struct(struct tty_struct *tty, tty->pgrp = NULL; mutex_init(&tty->legacy_mutex); mutex_init(&tty->termios_mutex); - mutex_init(&tty->ldisc_mutex); + init_ldsem(&tty->ldisc_sem); init_waitqueue_head(&tty->write_wait); init_waitqueue_head(&tty->read_wait); INIT_WORK(&tty->hangup_work, do_tty_hangup); diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 418c9f64a9fd..b7b8048f1253 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -45,7 +45,6 @@ enum { */ static DEFINE_RAW_SPINLOCK(tty_ldiscs_lock); -static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait); /* Line disc dispatch table */ static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS]; @@ -153,7 +152,7 @@ static void put_ldops(struct tty_ldisc_ops *ldops) * takes tty_ldiscs_lock to guard against ldisc races */ -static struct tty_ldisc *tty_ldisc_get(int disc) +static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc) { struct tty_ldisc *ld; struct tty_ldisc_ops *ldops; @@ -180,8 +179,7 @@ static struct tty_ldisc *tty_ldisc_get(int disc) } ld->ops = ldops; - atomic_set(&ld->users, 1); - init_waitqueue_head(&ld->wq_idle); + ld->tty = tty; return ld; } @@ -193,20 +191,11 @@ static struct tty_ldisc *tty_ldisc_get(int disc) */ static inline void tty_ldisc_put(struct tty_ldisc *ld) { - unsigned long flags; - if (WARN_ON_ONCE(!ld)) return; - raw_spin_lock_irqsave(&tty_ldiscs_lock, flags); - - /* unreleased reader reference(s) will cause this WARN */ - WARN_ON(!atomic_dec_and_test(&ld->users)); - - ld->ops->refcount--; - module_put(ld->ops->owner); + put_ldops(ld->ops); kfree(ld); - raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags); } static void *tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos) @@ -257,34 +246,6 @@ const struct file_operations tty_ldiscs_proc_fops = { .release = seq_release, }; -/** - * tty_ldisc_try - internal helper - * @tty: the tty - * - * Make a single attempt to grab and bump the refcount on - * the tty ldisc. Return 0 on failure or 1 on success. This is - * used to implement both the waiting and non waiting versions - * of tty_ldisc_ref - * - * Locking: takes tty_ldiscs_lock - */ - -static struct tty_ldisc *tty_ldisc_try(struct tty_struct *tty) -{ - unsigned long flags; - struct tty_ldisc *ld; - - /* FIXME: this allows reference acquire after TTY_LDISC is cleared */ - raw_spin_lock_irqsave(&tty_ldiscs_lock, flags); - ld = NULL; - if (test_bit(TTY_LDISC, &tty->flags) && tty->ldisc) { - ld = tty->ldisc; - atomic_inc(&ld->users); - } - raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags); - return ld; -} - /** * tty_ldisc_ref_wait - wait for the tty ldisc * @tty: tty device @@ -298,16 +259,15 @@ static struct tty_ldisc *tty_ldisc_try(struct tty_struct *tty) * against a discipline change, such as an existing ldisc reference * (which we check for) * - * Locking: call functions take tty_ldiscs_lock + * Note: only callable from a file_operations routine (which + * guarantees tty->ldisc != NULL when the lock is acquired). */ struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty) { - struct tty_ldisc *ld; - - /* wait_event is a macro */ - wait_event(tty_ldisc_wait, (ld = tty_ldisc_try(tty)) != NULL); - return ld; + ldsem_down_read(&tty->ldisc_sem, MAX_SCHEDULE_TIMEOUT); + WARN_ON(!tty->ldisc); + return tty->ldisc; } EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait); @@ -318,13 +278,18 @@ EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait); * Dereference the line discipline for the terminal and take a * reference to it. If the line discipline is in flux then * return NULL. Can be called from IRQ and timer functions. - * - * Locking: called functions take tty_ldiscs_lock */ struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty) { - return tty_ldisc_try(tty); + struct tty_ldisc *ld = NULL; + + if (ldsem_down_read_trylock(&tty->ldisc_sem)) { + ld = tty->ldisc; + if (!ld) + ldsem_up_read(&tty->ldisc_sem); + } + return ld; } EXPORT_SYMBOL_GPL(tty_ldisc_ref); @@ -334,27 +299,11 @@ EXPORT_SYMBOL_GPL(tty_ldisc_ref); * * Undoes the effect of tty_ldisc_ref or tty_ldisc_ref_wait. May * be called in IRQ context. - * - * Locking: takes tty_ldiscs_lock */ void tty_ldisc_deref(struct tty_ldisc *ld) { - unsigned long flags; - - if (WARN_ON_ONCE(!ld)) - return; - - raw_spin_lock_irqsave(&tty_ldiscs_lock, flags); - /* - * WARNs if one-too-many reader references were released - * - the last reference must be released with tty_ldisc_put - */ - WARN_ON(atomic_dec_and_test(&ld->users)); - raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags); - - if (waitqueue_active(&ld->wq_idle)) - wake_up(&ld->wq_idle); + ldsem_up_read(&ld->tty->ldisc_sem); } EXPORT_SYMBOL_GPL(tty_ldisc_deref); @@ -437,27 +386,6 @@ static void __lockfunc tty_ldisc_enable_pair(struct tty_struct *tty, tty_ldisc_unlock_pair(tty, tty2); } - -/** - * tty_ldisc_enable - allow ldisc use - * @tty: terminal to activate ldisc on - * - * Set the TTY_LDISC flag when the line discipline can be called - * again. Do necessary wakeups for existing sleepers. Clear the LDISC - * changing flag to indicate any ldisc change is now over. - * - * Note: nobody should set the TTY_LDISC bit except via this function. - * Clearing directly is allowed. - */ - -static void tty_ldisc_enable(struct tty_struct *tty) -{ - clear_bit(TTY_LDISC_HALTED, &tty->flags); - set_bit(TTY_LDISC, &tty->flags); - clear_bit(TTY_LDISC_CHANGING, &tty->flags); - wake_up(&tty_ldisc_wait); -} - /** * tty_ldisc_flush - flush line discipline queue * @tty: tty @@ -555,14 +483,14 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old) int r; /* There is an outstanding reference here so this is safe */ - old = tty_ldisc_get(old->ops->num); + old = tty_ldisc_get(tty, old->ops->num); WARN_ON(IS_ERR(old)); tty->ldisc = old; tty_set_termios_ldisc(tty, old->ops->num); if (tty_ldisc_open(tty, old) < 0) { tty_ldisc_put(old); /* This driver is always present */ - new_ldisc = tty_ldisc_get(N_TTY); + new_ldisc = tty_ldisc_get(tty, N_TTY); if (IS_ERR(new_ldisc)) panic("n_tty: get"); tty->ldisc = new_ldisc; @@ -575,101 +503,6 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old) } } -/** - * tty_ldisc_wait_idle - wait for the ldisc to become idle - * @tty: tty to wait for - * @timeout: for how long to wait at most - * - * Wait for the line discipline to become idle. The discipline must - * have been halted for this to guarantee it remains idle. - */ -static int tty_ldisc_wait_idle(struct tty_struct *tty, long timeout) -{ - long ret; - ret = wait_event_timeout(tty->ldisc->wq_idle, - atomic_read(&tty->ldisc->users) == 1, timeout); - return ret > 0 ? 0 : -EBUSY; -} - -/** - * tty_ldisc_halt - shut down the line discipline - * @tty: tty device - * @o_tty: paired pty device (can be NULL) - * @timeout: # of jiffies to wait for ldisc refs to be released - * - * Shut down the line discipline and work queue for this tty device and - * its paired pty (if exists). Clearing the TTY_LDISC flag ensures - * no further references can be obtained, while waiting for existing - * references to be released ensures no more data is fed to the ldisc. - * - * You need to do a 'flush_scheduled_work()' (outside the ldisc_mutex) - * in order to make sure any currently executing ldisc work is also - * flushed. - */ - -static int tty_ldisc_halt(struct tty_struct *tty, struct tty_struct *o_tty, - long timeout) -{ - int retval; - - clear_bit(TTY_LDISC, &tty->flags); - if (o_tty) - clear_bit(TTY_LDISC, &o_tty->flags); - - retval = tty_ldisc_wait_idle(tty, timeout); - if (!retval && o_tty) - retval = tty_ldisc_wait_idle(o_tty, timeout); - if (retval) - return retval; - - set_bit(TTY_LDISC_HALTED, &tty->flags); - if (o_tty) - set_bit(TTY_LDISC_HALTED, &o_tty->flags); - - return 0; -} - -/** - * tty_ldisc_hangup_halt - halt the line discipline for hangup - * @tty: tty being hung up - * - * Shut down the line discipline and work queue for the tty device - * being hungup. Clear the TTY_LDISC flag to ensure no further - * references can be obtained and wait for remaining references to be - * released to ensure no more data is fed to this ldisc. - * Caller must hold legacy and ->ldisc_mutex. - * - * NB: tty_set_ldisc() is prevented from changing the ldisc concurrently - * with this function by checking the TTY_HUPPING flag. - */ -static bool tty_ldisc_hangup_halt(struct tty_struct *tty) -{ - char cur_n[TASK_COMM_LEN], tty_n[64]; - long timeout = 3 * HZ; - - clear_bit(TTY_LDISC, &tty->flags); - - if (tty->ldisc) { /* Not yet closed */ - tty_unlock(tty); - - while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) { - timeout = MAX_SCHEDULE_TIMEOUT; - printk_ratelimited(KERN_WARNING - "%s: waiting (%s) for %s took too long, but we keep waiting...\n", - __func__, get_task_comm(cur_n, current), - tty_name(tty, tty_n)); - } - - set_bit(TTY_LDISC_HALTED, &tty->flags); - - /* must reacquire both locks and preserve lock order */ - mutex_unlock(&tty->ldisc_mutex); - tty_lock(tty); - mutex_lock(&tty->ldisc_mutex); - } - return !!tty->ldisc; -} - /** * tty_set_ldisc - set line discipline * @tty: the terminal to set @@ -679,103 +512,47 @@ static bool tty_ldisc_hangup_halt(struct tty_struct *tty) * context. The ldisc change logic has to protect itself against any * overlapping ldisc change (including on the other end of pty pairs), * the close of one side of a tty/pty pair, and eventually hangup. - * - * Locking: takes tty_ldiscs_lock, termios_mutex */ int tty_set_ldisc(struct tty_struct *tty, int ldisc) { int retval; struct tty_ldisc *o_ldisc, *new_ldisc; - struct tty_struct *o_tty; + struct tty_struct *o_tty = tty->link; - new_ldisc = tty_ldisc_get(ldisc); + new_ldisc = tty_ldisc_get(tty, ldisc); if (IS_ERR(new_ldisc)) return PTR_ERR(new_ldisc); - tty_lock(tty); - /* - * We need to look at the tty locking here for pty/tty pairs - * when both sides try to change in parallel. - */ - - o_tty = tty->link; /* o_tty is the pty side or NULL */ - + retval = tty_ldisc_lock_pair_timeout(tty, o_tty, 5 * HZ); + if (retval) { + tty_ldisc_put(new_ldisc); + return retval; + } /* * Check the no-op case */ if (tty->ldisc->ops->num == ldisc) { - tty_unlock(tty); + tty_ldisc_enable_pair(tty, o_tty); tty_ldisc_put(new_ldisc); return 0; } - mutex_lock(&tty->ldisc_mutex); - - /* - * We could be midstream of another ldisc change which has - * dropped the lock during processing. If so we need to wait. - */ - - while (test_bit(TTY_LDISC_CHANGING, &tty->flags)) { - mutex_unlock(&tty->ldisc_mutex); - tty_unlock(tty); - wait_event(tty_ldisc_wait, - test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0); - tty_lock(tty); - mutex_lock(&tty->ldisc_mutex); - } - - set_bit(TTY_LDISC_CHANGING, &tty->flags); - - /* - * No more input please, we are switching. The new ldisc - * will update this value in the ldisc open function - */ - + /* FIXME: why 'shutoff' input if the ldisc is locked? */ tty->receive_room = 0; o_ldisc = tty->ldisc; - - tty_unlock(tty); - /* - * Make sure we don't change while someone holds a - * reference to the line discipline. The TTY_LDISC bit - * prevents anyone taking a reference once it is clear. - * We need the lock to avoid racing reference takers. - * - * We must clear the TTY_LDISC bit here to avoid a livelock - * with a userspace app continually trying to use the tty in - * parallel to the change and re-referencing the tty. - */ - - retval = tty_ldisc_halt(tty, o_tty, 5 * HZ); - - /* - * Wait for hangup to complete, if pending. - * We must drop the mutex here in case a hangup is also in process. - */ - - mutex_unlock(&tty->ldisc_mutex); - - flush_work(&tty->hangup_work); - tty_lock(tty); - mutex_lock(&tty->ldisc_mutex); - /* handle wait idle failure locked */ - if (retval) { - tty_ldisc_put(new_ldisc); - goto enable; - } + /* FIXME: for testing only */ + WARN_ON(test_bit(TTY_HUPPED, &tty->flags)); if (test_bit(TTY_HUPPING, &tty->flags)) { /* We were raced by the hangup method. It will have stomped the ldisc data and closed the ldisc down */ - clear_bit(TTY_LDISC_CHANGING, &tty->flags); - mutex_unlock(&tty->ldisc_mutex); + tty_ldisc_enable_pair(tty, o_tty); tty_ldisc_put(new_ldisc); tty_unlock(tty); return -EIO; @@ -804,14 +581,10 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) tty_ldisc_put(o_ldisc); -enable: /* * Allow ldisc referencing to occur again */ - - tty_ldisc_enable(tty); - if (o_tty) - tty_ldisc_enable(o_tty); + tty_ldisc_enable_pair(tty, o_tty); /* Restart the work queue in case no characters kick it off. Safe if already running */ @@ -819,7 +592,6 @@ enable: if (o_tty) schedule_work(&o_tty->port->buf.work); - mutex_unlock(&tty->ldisc_mutex); tty_unlock(tty); return retval; } @@ -852,7 +624,7 @@ static void tty_reset_termios(struct tty_struct *tty) static int tty_ldisc_reinit(struct tty_struct *tty, int ldisc) { - struct tty_ldisc *ld = tty_ldisc_get(ldisc); + struct tty_ldisc *ld = tty_ldisc_get(tty, ldisc); if (IS_ERR(ld)) return -1; @@ -891,14 +663,8 @@ void tty_ldisc_hangup(struct tty_struct *tty) tty_ldisc_debug(tty, "closing ldisc: %p\n", tty->ldisc); - /* - * FIXME! What are the locking issues here? This may me overdoing - * things... This question is especially important now that we've - * removed the irqlock. - */ ld = tty_ldisc_ref(tty); if (ld != NULL) { - /* We may have no line discipline at this point */ if (ld->ops->flush_buffer) ld->ops->flush_buffer(tty); tty_driver_flush_buffer(tty); @@ -909,21 +675,22 @@ void tty_ldisc_hangup(struct tty_struct *tty) ld->ops->hangup(tty); tty_ldisc_deref(ld); } - /* - * FIXME: Once we trust the LDISC code better we can wait here for - * ldisc completion and fix the driver call race - */ + wake_up_interruptible_poll(&tty->write_wait, POLLOUT); wake_up_interruptible_poll(&tty->read_wait, POLLIN); + + tty_unlock(tty); + /* * Shutdown the current line discipline, and reset it to * N_TTY if need be. * * Avoid racing set_ldisc or tty_ldisc_release */ - mutex_lock(&tty->ldisc_mutex); + tty_ldisc_lock_pair(tty, tty->link); + tty_lock(tty); - if (tty_ldisc_hangup_halt(tty)) { + if (tty->ldisc) { /* At this point we have a halted ldisc; we want to close it and reopen a new ldisc. We could defer the reopen to the next @@ -942,9 +709,8 @@ void tty_ldisc_hangup(struct tty_struct *tty) BUG_ON(tty_ldisc_reinit(tty, N_TTY)); WARN_ON(tty_ldisc_open(tty, tty->ldisc)); } - tty_ldisc_enable(tty); } - mutex_unlock(&tty->ldisc_mutex); + tty_ldisc_enable_pair(tty, tty->link); if (reset) tty_reset_termios(tty); @@ -976,15 +742,12 @@ int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty) tty_ldisc_close(tty, ld); return retval; } - tty_ldisc_enable(o_tty); } - tty_ldisc_enable(tty); return 0; } static void tty_ldisc_kill(struct tty_struct *tty) { - mutex_lock(&tty->ldisc_mutex); /* * Now kill off the ldisc */ @@ -995,7 +758,6 @@ static void tty_ldisc_kill(struct tty_struct *tty) /* Ensure the next open requests the N_TTY ldisc */ tty_set_termios_ldisc(tty, N_TTY); - mutex_unlock(&tty->ldisc_mutex); } /** @@ -1017,15 +779,16 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty) tty_ldisc_debug(tty, "closing ldisc: %p\n", tty->ldisc); - tty_ldisc_halt(tty, o_tty, MAX_SCHEDULE_TIMEOUT); - + tty_ldisc_lock_pair(tty, o_tty); tty_lock_pair(tty, o_tty); - /* This will need doing differently if we need to lock */ + tty_ldisc_kill(tty); if (o_tty) tty_ldisc_kill(o_tty); tty_unlock_pair(tty, o_tty); + tty_ldisc_unlock_pair(tty, o_tty); + /* And the memory resources remaining (buffers, termios) will be disposed of when the kref hits zero */ @@ -1042,7 +805,7 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty) void tty_ldisc_init(struct tty_struct *tty) { - struct tty_ldisc *ld = tty_ldisc_get(N_TTY); + struct tty_ldisc *ld = tty_ldisc_get(tty, N_TTY); if (IS_ERR(ld)) panic("n_tty: init_tty"); tty->ldisc = ld; diff --git a/include/linux/tty.h b/include/linux/tty.h index 01ac30efd6a6..7269daf7632b 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -238,7 +238,7 @@ struct tty_struct { int index; /* Protects ldisc changes: Lock tty not pty */ - struct mutex ldisc_mutex; + struct ld_semaphore ldisc_sem; struct tty_ldisc *ldisc; struct mutex atomic_write_lock; @@ -305,8 +305,6 @@ struct tty_file_private { #define TTY_DO_WRITE_WAKEUP 5 /* Call write_wakeup after queuing new */ #define TTY_PUSH 6 /* n_tty private */ #define TTY_CLOSING 7 /* ->close() in progress */ -#define TTY_LDISC 9 /* Line discipline attached */ -#define TTY_LDISC_CHANGING 10 /* Line discipline changing */ #define TTY_LDISC_OPEN 11 /* Line discipline is open */ #define TTY_PTY_LOCK 16 /* pty private */ #define TTY_NO_WRITE_SPLIT 17 /* Preserve write boundaries to driver */ diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h index a1b048999821..23bdd9debb84 100644 --- a/include/linux/tty_ldisc.h +++ b/include/linux/tty_ldisc.h @@ -203,8 +203,7 @@ struct tty_ldisc_ops { struct tty_ldisc { struct tty_ldisc_ops *ops; - atomic_t users; - wait_queue_head_t wq_idle; + struct tty_struct *tty; }; #define TTY_LDISC_MAGIC 0x5403 From 9fbfa34c18b31978bf6bab26148f84d7a4b3ccea Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 07:04:49 -0400 Subject: [PATCH 0479/3400] tty: Clarify ldisc variable Rename o_ldisc to avoid confusion with the ldisc of the 'other' tty. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_ldisc.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index b7b8048f1253..31bd45a2d16b 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -517,7 +517,7 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old) int tty_set_ldisc(struct tty_struct *tty, int ldisc) { int retval; - struct tty_ldisc *o_ldisc, *new_ldisc; + struct tty_ldisc *old_ldisc, *new_ldisc; struct tty_struct *o_tty = tty->link; new_ldisc = tty_ldisc_get(tty, ldisc); @@ -543,7 +543,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) /* FIXME: why 'shutoff' input if the ldisc is locked? */ tty->receive_room = 0; - o_ldisc = tty->ldisc; + old_ldisc = tty->ldisc; tty_lock(tty); /* FIXME: for testing only */ @@ -558,8 +558,8 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) return -EIO; } - /* Shutdown the current discipline. */ - tty_ldisc_close(tty, o_ldisc); + /* Shutdown the old discipline. */ + tty_ldisc_close(tty, old_ldisc); /* Now set up the new line discipline. */ tty->ldisc = new_ldisc; @@ -569,17 +569,17 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) if (retval < 0) { /* Back to the old one or N_TTY if we can't */ tty_ldisc_put(new_ldisc); - tty_ldisc_restore(tty, o_ldisc); + tty_ldisc_restore(tty, old_ldisc); } /* At this point we hold a reference to the new ldisc and a a reference to the old ldisc. If we ended up flipping back to the existing ldisc we have two references to it */ - if (tty->ldisc->ops->num != o_ldisc->ops->num && tty->ops->set_ldisc) + if (tty->ldisc->ops->num != old_ldisc->ops->num && tty->ops->set_ldisc) tty->ops->set_ldisc(tty); - tty_ldisc_put(o_ldisc); + tty_ldisc_put(old_ldisc); /* * Allow ldisc referencing to occur again From e97733ca677878d0ecf08af17f4661eb83e268bc Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 07:04:50 -0400 Subject: [PATCH 0480/3400] tty: Fix hangup race with TIOCSETD ioctl The hangup may already have happened; check for that state also. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_ldisc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 31bd45a2d16b..5819667f5bdb 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -546,10 +546,8 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) old_ldisc = tty->ldisc; tty_lock(tty); - /* FIXME: for testing only */ - WARN_ON(test_bit(TTY_HUPPED, &tty->flags)); - - if (test_bit(TTY_HUPPING, &tty->flags)) { + if (test_bit(TTY_HUPPING, &tty->flags) || + test_bit(TTY_HUPPED, &tty->flags)) { /* We were raced by the hangup method. It will have stomped the ldisc data and closed the ldisc down */ tty_ldisc_enable_pair(tty, o_tty); From b0e95858238d95f32edf00ff4a0375165129d0c6 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 07:04:51 -0400 Subject: [PATCH 0481/3400] tty: Clarify multiple-references comment in TIOCSETD ioctl Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_ldisc.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 5819667f5bdb..75fa99978348 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -570,13 +570,15 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) tty_ldisc_restore(tty, old_ldisc); } - /* At this point we hold a reference to the new ldisc and a - a reference to the old ldisc. If we ended up flipping back - to the existing ldisc we have two references to it */ - if (tty->ldisc->ops->num != old_ldisc->ops->num && tty->ops->set_ldisc) tty->ops->set_ldisc(tty); + /* At this point we hold a reference to the new ldisc and a + reference to the old ldisc, or we hold two references to + the old ldisc (if it was restored as part of error cleanup + above). In either case, releasing a single reference from + the old ldisc is correct. */ + tty_ldisc_put(old_ldisc); /* From 3b80df7ca7e2fec76be2eda304cc7e0eb90f911d Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:14:13 -0400 Subject: [PATCH 0482/3400] tty: Don't change receive_room for ioctl(TIOCSETD) tty_set_ldisc() is guaranteed exclusive use of the line discipline by tty_ldisc_lock_pair_timeout(); shutting off input by resetting receive_room is unnecessary. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_ldisc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 75fa99978348..e52d61573553 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -540,9 +540,6 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) return 0; } - /* FIXME: why 'shutoff' input if the ldisc is locked? */ - tty->receive_room = 0; - old_ldisc = tty->ldisc; tty_lock(tty); From da261e7fe7b0e23a0d4d46039d20dc60fa197b49 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:14:14 -0400 Subject: [PATCH 0483/3400] tty: Simplify tty buffer/ldisc interface with helper function Ldisc interface functions must be called with interrupts enabled. Separating the ldisc calls into a helper function simplies the eventual removal of the spinlock. Note that access to the buf->head ptr outside the spinlock is safe here because; * __tty_buffer_flush() is prevented from running while buffer work performs i/o, * tty_buffer_find() only assigns buf->head if the flip buffer list is empty (which is never the case in flush_to_ldisc() since at least one buffer is always left in the list after use) Access to the read index outside the spinlock is safe here for the same reasons. Update the buffer's read index _after_ the data has been received by the ldisc. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_buffer.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index a42a028a9d4e..6c7a1d043c76 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -403,6 +403,18 @@ int tty_prepare_flip_string_flags(struct tty_port *port, EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags); +static int +receive_buf(struct tty_struct *tty, struct tty_buffer *head, int count) +{ + struct tty_ldisc *disc = tty->ldisc; + + count = min_t(int, count, tty->receive_room); + if (count) + disc->ops->receive_buf(tty, head->char_buf_ptr + head->read, + head->flag_buf_ptr + head->read, count); + head->read += count; + return count; +} /** * flush_to_ldisc @@ -438,8 +450,6 @@ static void flush_to_ldisc(struct work_struct *work) struct tty_buffer *head; while ((head = buf->head) != NULL) { int count; - char *char_buf; - unsigned char *flag_buf; count = head->commit - head->read; if (!count) { @@ -449,16 +459,10 @@ static void flush_to_ldisc(struct work_struct *work) tty_buffer_free(port, head); continue; } - if (!tty->receive_room) - break; - if (count > tty->receive_room) - count = tty->receive_room; - char_buf = head->char_buf_ptr + head->read; - flag_buf = head->flag_buf_ptr + head->read; - head->read += count; spin_unlock_irqrestore(&buf->lock, flags); - disc->ops->receive_buf(tty, char_buf, - flag_buf, count); + + count = receive_buf(tty, head, count); + spin_lock_irqsave(&buf->lock, flags); /* Ldisc or user is trying to flush the buffers. We may have a deferred request to flush the @@ -469,7 +473,8 @@ static void flush_to_ldisc(struct work_struct *work) clear_bit(TTYP_FLUSHPENDING, &port->iflags); wake_up(&tty->read_wait); break; - } + } else if (!count) + break; } clear_bit(TTYP_FLUSHING, &port->iflags); } From 24a89d1cb69b6c488cf16d98dd02e7820f62b40c Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:14:15 -0400 Subject: [PATCH 0484/3400] tty: Make ldisc input flow control concurrency-friendly Although line discipline receiving is single-producer/single-consumer, using tty->receive_room to manage flow control creates unnecessary critical regions requiring additional lock use. Instead, introduce the optional .receive_buf2() ldisc method which returns the # of bytes actually received. Serialization is guaranteed by the caller. In turn, the line discipline should schedule the buffer work item whenever space becomes available; ie., when there is room to receive data and receive_room() previously returned 0 (the buffer work item stops processing if receive_buf2() returns 0). Note the 'no room' state need not be atomic despite concurrent use by two threads because only the buffer work thread can set the state and only the read() thread can clear the state. Add n_tty_receive_buf2() as the receive_buf2() method for N_TTY. Provide a public helper function, tty_ldisc_receive_buf(), to use when directly accessing the receive_buf() methods. Line disciplines not using input flow control can continue to set tty->receive_room to a fixed value and only provide the receive_buf() method. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 72 ++++++++++++++++++++++++-------------- drivers/tty/tty_buffer.c | 13 ++++--- drivers/tty/vt/selection.c | 4 +-- include/linux/tty.h | 13 +++++++ include/linux/tty_ldisc.h | 13 +++++++ 5 files changed, 82 insertions(+), 33 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 4bf0fc0843d7..eddeb7889e62 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -79,6 +79,9 @@ struct n_tty_data { unsigned long overrun_time; int num_overrun; + /* non-atomic */ + bool no_room; + unsigned char lnext:1, erasing:1, raw:1, real_raw:1, icanon:1; unsigned char echo_overrun:1; @@ -114,25 +117,10 @@ static inline int tty_put_user(struct tty_struct *tty, unsigned char x, return put_user(x, ptr); } -/** - * n_tty_set_room - receive space - * @tty: terminal - * - * Updates tty->receive_room to reflect the currently available space - * in the input buffer, and re-schedules the flip buffer work if space - * just became available. - * - * Locks: Concurrent update is protected with read_lock - */ - -static int set_room(struct tty_struct *tty) +static int receive_room(struct tty_struct *tty) { struct n_tty_data *ldata = tty->disc_data; int left; - int old_left; - unsigned long flags; - - raw_spin_lock_irqsave(&ldata->read_lock, flags); if (I_PARMRK(tty)) { /* Multiply read_cnt by 3, since each byte might take up to @@ -150,18 +138,27 @@ static int set_room(struct tty_struct *tty) */ if (left <= 0) left = ldata->icanon && !ldata->canon_data; - old_left = tty->receive_room; - tty->receive_room = left; - raw_spin_unlock_irqrestore(&ldata->read_lock, flags); - - return left && !old_left; + return left; } +/** + * n_tty_set_room - receive space + * @tty: terminal + * + * Re-schedules the flip buffer work if space just became available. + * + * Locks: Concurrent update is protected with read_lock + */ + static void n_tty_set_room(struct tty_struct *tty) { + struct n_tty_data *ldata = tty->disc_data; + /* Did this open up the receive buffer? We may need to flip */ - if (set_room(tty)) { + if (unlikely(ldata->no_room) && receive_room(tty)) { + ldata->no_room = 0; + WARN_RATELIMIT(tty->port->itty == NULL, "scheduling with invalid itty\n"); /* see if ldisc has been killed - if so, this means that @@ -1408,8 +1405,8 @@ static void n_tty_write_wakeup(struct tty_struct *tty) * calls one at a time and in order (or using flush_to_ldisc) */ -static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count) +static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, + char *fp, int count) { struct n_tty_data *ldata = tty->disc_data; const unsigned char *p; @@ -1464,8 +1461,6 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, tty->ops->flush_chars(tty); } - set_room(tty); - if ((!ldata->icanon && (ldata->read_cnt >= ldata->minimum_to_wake)) || L_EXTPROC(tty)) { kill_fasync(&tty->fasync, SIGIO, POLL_IN); @@ -1480,7 +1475,7 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, */ while (1) { tty_set_flow_change(tty, TTY_THROTTLE_SAFE); - if (tty->receive_room >= TTY_THRESHOLD_THROTTLE) + if (receive_room(tty) >= TTY_THRESHOLD_THROTTLE) break; if (!tty_throttle_safe(tty)) break; @@ -1488,6 +1483,28 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, __tty_set_flow_change(tty, 0); } +static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, + char *fp, int count) +{ + __receive_buf(tty, cp, fp, count); +} + +static int n_tty_receive_buf2(struct tty_struct *tty, const unsigned char *cp, + char *fp, int count) +{ + struct n_tty_data *ldata = tty->disc_data; + int room; + + tty->receive_room = room = receive_room(tty); + if (!room) + ldata->no_room = 1; + count = min(count, room); + if (count) + __receive_buf(tty, cp, fp, count); + + return count; +} + int is_ignored(int sig) { return (sigismember(¤t->blocked, sig) || @@ -2203,6 +2220,7 @@ struct tty_ldisc_ops tty_ldisc_N_TTY = { .receive_buf = n_tty_receive_buf, .write_wakeup = n_tty_write_wakeup, .fasync = n_tty_fasync, + .receive_buf2 = n_tty_receive_buf2, }; /** diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index 6c7a1d043c76..ff1b2e37c3ca 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -407,11 +407,16 @@ static int receive_buf(struct tty_struct *tty, struct tty_buffer *head, int count) { struct tty_ldisc *disc = tty->ldisc; + char *p = head->char_buf_ptr + head->read; + unsigned char *f = head->flag_buf_ptr + head->read; - count = min_t(int, count, tty->receive_room); - if (count) - disc->ops->receive_buf(tty, head->char_buf_ptr + head->read, - head->flag_buf_ptr + head->read, count); + if (disc->ops->receive_buf2) + count = disc->ops->receive_buf2(tty, p, f, count); + else { + count = min_t(int, count, tty->receive_room); + if (count) + disc->ops->receive_buf(tty, p, f, count); + } head->read += count; return count; } diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c index 60b7b6926059..2ca8d6b6514c 100644 --- a/drivers/tty/vt/selection.c +++ b/drivers/tty/vt/selection.c @@ -356,8 +356,8 @@ int paste_selection(struct tty_struct *tty) continue; } count = sel_buffer_lth - pasted; - count = min(count, tty->receive_room); - ld->ops->receive_buf(tty, sel_buffer + pasted, NULL, count); + count = tty_ldisc_receive_buf(ld, sel_buffer + pasted, NULL, + count); pasted += count; } remove_wait_queue(&vc->paste_wait, &wait); diff --git a/include/linux/tty.h b/include/linux/tty.h index 7269daf7632b..8323ee4f95b9 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -557,6 +557,19 @@ extern void tty_ldisc_init(struct tty_struct *tty); extern void tty_ldisc_deinit(struct tty_struct *tty); extern void tty_ldisc_begin(void); +static inline int tty_ldisc_receive_buf(struct tty_ldisc *ld, unsigned char *p, + char *f, int count) +{ + if (ld->ops->receive_buf2) + count = ld->ops->receive_buf2(ld->tty, p, f, count); + else { + count = min_t(int, count, ld->tty->receive_room); + if (count) + ld->ops->receive_buf(ld->tty, p, f, count); + } + return count; +} + /* n_tty.c */ extern struct tty_ldisc_ops tty_ldisc_N_TTY; diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h index 23bdd9debb84..f15c898ff462 100644 --- a/include/linux/tty_ldisc.h +++ b/include/linux/tty_ldisc.h @@ -109,6 +109,17 @@ * * Tells the discipline that the DCD pin has changed its status. * Used exclusively by the N_PPS (Pulse-Per-Second) line discipline. + * + * int (*receive_buf2)(struct tty_struct *, const unsigned char *cp, + * char *fp, int count); + * + * This function is called by the low-level tty driver to send + * characters received by the hardware to the line discpline for + * processing. is a pointer to the buffer of input + * character received by the device. is a pointer to a + * pointer of flag bytes which indicate whether a character was + * received with a parity error, etc. + * If assigned, prefer this function for automatic flow control. */ #include @@ -195,6 +206,8 @@ struct tty_ldisc_ops { void (*write_wakeup)(struct tty_struct *); void (*dcd_change)(struct tty_struct *, unsigned int); void (*fasync)(struct tty_struct *tty, int on); + int (*receive_buf2)(struct tty_struct *, const unsigned char *cp, + char *fp, int count); struct module *owner; From 88bb0de389a464521034e87816e5d6c7c489a664 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:14:16 -0400 Subject: [PATCH 0485/3400] n_tty: Factor canonical mode copy from n_tty_read() Simplify n_tty_read(); extract complex copy algorithm into separate function, canon_copy_to_user(). Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 95 +++++++++++++++++++++++++++------------------ 1 file changed, 57 insertions(+), 38 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index eddeb7889e62..7fd77746f2d0 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1747,6 +1747,62 @@ static int copy_from_read_buf(struct tty_struct *tty, return retval; } +/** + * canon_copy_to_user - copy read data in canonical mode + * @tty: terminal device + * @b: user data + * @nr: size of data + * + * Helper function for n_tty_read. It is only called when ICANON is on; + * it copies characters one at a time from the read buffer to the user + * space buffer. + * + * Called under the atomic_read_lock mutex + */ + +static int canon_copy_to_user(struct tty_struct *tty, + unsigned char __user **b, + size_t *nr) +{ + struct n_tty_data *ldata = tty->disc_data; + unsigned long flags; + int eol, c; + + /* N.B. avoid overrun if nr == 0 */ + raw_spin_lock_irqsave(&ldata->read_lock, flags); + while (*nr && ldata->read_cnt) { + + eol = test_and_clear_bit(ldata->read_tail, ldata->read_flags); + c = ldata->read_buf[ldata->read_tail]; + ldata->read_tail = (ldata->read_tail+1) & (N_TTY_BUF_SIZE-1); + ldata->read_cnt--; + if (eol) { + /* this test should be redundant: + * we shouldn't be reading data if + * canon_data is 0 + */ + if (--ldata->canon_data < 0) + ldata->canon_data = 0; + } + raw_spin_unlock_irqrestore(&ldata->read_lock, flags); + + if (!eol || (c != __DISABLED_CHAR)) { + if (tty_put_user(tty, c, *b)) + return -EFAULT; + *b += 1; + *nr -= 1; + } + if (eol) { + tty_audit_push(tty); + return 0; + } + raw_spin_lock_irqsave(&ldata->read_lock, flags); + } + raw_spin_unlock_irqrestore(&ldata->read_lock, flags); + + return 0; +} + extern ssize_t redirected_tty_write(struct file *, const char __user *, size_t, loff_t *); @@ -1916,44 +1972,7 @@ do_it_again: } if (ldata->icanon && !L_EXTPROC(tty)) { - /* N.B. avoid overrun if nr == 0 */ - raw_spin_lock_irqsave(&ldata->read_lock, flags); - while (nr && ldata->read_cnt) { - int eol; - - eol = test_and_clear_bit(ldata->read_tail, - ldata->read_flags); - c = ldata->read_buf[ldata->read_tail]; - ldata->read_tail = ((ldata->read_tail+1) & - (N_TTY_BUF_SIZE-1)); - ldata->read_cnt--; - if (eol) { - /* this test should be redundant: - * we shouldn't be reading data if - * canon_data is 0 - */ - if (--ldata->canon_data < 0) - ldata->canon_data = 0; - } - raw_spin_unlock_irqrestore(&ldata->read_lock, flags); - - if (!eol || (c != __DISABLED_CHAR)) { - if (tty_put_user(tty, c, b++)) { - retval = -EFAULT; - b--; - raw_spin_lock_irqsave(&ldata->read_lock, flags); - break; - } - nr--; - } - if (eol) { - tty_audit_push(tty); - raw_spin_lock_irqsave(&ldata->read_lock, flags); - break; - } - raw_spin_lock_irqsave(&ldata->read_lock, flags); - } - raw_spin_unlock_irqrestore(&ldata->read_lock, flags); + retval = canon_copy_to_user(tty, &b, &nr); if (retval) break; } else { From 32f13521ca68bc624ff6effc77f308a52b038bf0 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:14:17 -0400 Subject: [PATCH 0486/3400] n_tty: Line copy to user buffer in canonical mode Instead of pushing one char per loop, pre-compute the data length to copy and copy all at once. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 108 +++++++++++++++++++++++++++++++------------- 1 file changed, 76 insertions(+), 32 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 7fd77746f2d0..74dcedd06a8b 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -74,6 +74,13 @@ #define ECHO_OP_SET_CANON_COL 0x81 #define ECHO_OP_ERASE_TAB 0x82 +#undef N_TTY_TRACE +#ifdef N_TTY_TRACE +# define n_tty_trace(f, args...) trace_printk(f, ##args) +#else +# define n_tty_trace(f, args...) +#endif + struct n_tty_data { unsigned int column; unsigned long overrun_time; @@ -1748,58 +1755,95 @@ static int copy_from_read_buf(struct tty_struct *tty, } /** - * canon_copy_to_user - copy read data in canonical mode + * canon_copy_from_read_buf - copy read data in canonical mode * @tty: terminal device * @b: user data * @nr: size of data * * Helper function for n_tty_read. It is only called when ICANON is on; - * it copies characters one at a time from the read buffer to the user - * space buffer. + * it copies one line of input up to and including the line-delimiting + * character into the user-space buffer. * * Called under the atomic_read_lock mutex */ -static int canon_copy_to_user(struct tty_struct *tty, - unsigned char __user **b, - size_t *nr) +static int canon_copy_from_read_buf(struct tty_struct *tty, + unsigned char __user **b, + size_t *nr) { struct n_tty_data *ldata = tty->disc_data; unsigned long flags; - int eol, c; + size_t n, size, more, c; + unsigned long eol; + int ret, tail, found = 0; /* N.B. avoid overrun if nr == 0 */ + raw_spin_lock_irqsave(&ldata->read_lock, flags); - while (*nr && ldata->read_cnt) { - eol = test_and_clear_bit(ldata->read_tail, ldata->read_flags); - c = ldata->read_buf[ldata->read_tail]; - ldata->read_tail = (ldata->read_tail+1) & (N_TTY_BUF_SIZE-1); - ldata->read_cnt--; - if (eol) { - /* this test should be redundant: - * we shouldn't be reading data if - * canon_data is 0 - */ - if (--ldata->canon_data < 0) - ldata->canon_data = 0; - } + n = min_t(size_t, *nr, ldata->read_cnt); + if (!n) { raw_spin_unlock_irqrestore(&ldata->read_lock, flags); + return 0; + } - if (!eol || (c != __DISABLED_CHAR)) { - if (tty_put_user(tty, c, *b)) - return -EFAULT; - *b += 1; - *nr -= 1; - } - if (eol) { - tty_audit_push(tty); - return 0; - } - raw_spin_lock_irqsave(&ldata->read_lock, flags); + tail = ldata->read_tail; + size = min_t(size_t, tail + n, N_TTY_BUF_SIZE); + + n_tty_trace("%s: nr:%zu tail:%d n:%zu size:%zu\n", + __func__, *nr, tail, n, size); + + eol = find_next_bit(ldata->read_flags, size, tail); + more = n - (size - tail); + if (eol == N_TTY_BUF_SIZE && more) { + /* scan wrapped without finding set bit */ + eol = find_next_bit(ldata->read_flags, more, 0); + if (eol != more) + found = 1; + } else if (eol != size) + found = 1; + + size = N_TTY_BUF_SIZE - tail; + n = (found + eol + size) & (N_TTY_BUF_SIZE - 1); + c = n; + + if (found && ldata->read_buf[eol] == __DISABLED_CHAR) + n--; + + n_tty_trace("%s: eol:%lu found:%d n:%zu c:%zu size:%zu more:%zu\n", + __func__, eol, found, n, c, size, more); + + raw_spin_unlock_irqrestore(&ldata->read_lock, flags); + + if (n > size) { + ret = copy_to_user(*b, &ldata->read_buf[tail], size); + if (ret) + return -EFAULT; + ret = copy_to_user(*b + size, ldata->read_buf, n - size); + } else + ret = copy_to_user(*b, &ldata->read_buf[tail], n); + + if (ret) + return -EFAULT; + *b += n; + *nr -= n; + + raw_spin_lock_irqsave(&ldata->read_lock, flags); + ldata->read_tail = (ldata->read_tail + c) & (N_TTY_BUF_SIZE - 1); + ldata->read_cnt -= c; + if (found) { + __clear_bit(eol, ldata->read_flags); + /* this test should be redundant: + * we shouldn't be reading data if + * canon_data is 0 + */ + if (--ldata->canon_data < 0) + ldata->canon_data = 0; } raw_spin_unlock_irqrestore(&ldata->read_lock, flags); + if (found) + tty_audit_push(tty); return 0; } @@ -1972,7 +2016,7 @@ do_it_again: } if (ldata->icanon && !L_EXTPROC(tty)) { - retval = canon_copy_to_user(tty, &b, &nr); + retval = canon_copy_from_read_buf(tty, &b, &nr); if (retval) break; } else { From a19d0c6a9166fe3d8bb1575b64f28590206148d9 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:14:18 -0400 Subject: [PATCH 0487/3400] n_tty: Split n_tty_chars_in_buffer() for reader-only interface N_TTY .chars_in_buffer() method requires serialized access if the current thread is not the single-consumer, n_tty_read(). Separate the internal interface; prepare for lockless read-side. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 74dcedd06a8b..594a3c19882b 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -277,7 +277,7 @@ static void n_tty_flush_buffer(struct tty_struct *tty) * Locking: read_lock */ -static ssize_t n_tty_chars_in_buffer(struct tty_struct *tty) +static ssize_t chars_in_buffer(struct tty_struct *tty) { struct n_tty_data *ldata = tty->disc_data; unsigned long flags; @@ -295,6 +295,11 @@ static ssize_t n_tty_chars_in_buffer(struct tty_struct *tty) return n; } +static ssize_t n_tty_chars_in_buffer(struct tty_struct *tty) +{ + return chars_in_buffer(tty); +} + /** * is_utf8_continuation - utf8 multibyte check * @c: byte to check @@ -2032,7 +2037,7 @@ do_it_again: } /* If there is enough space in the read buffer now, let the - * low-level driver know. We use n_tty_chars_in_buffer() to + * low-level driver know. We use chars_in_buffer() to * check the buffer, as it now knows about canonical mode. * Otherwise, if the driver is throttled and the line is * longer than TTY_THRESHOLD_UNTHROTTLE in canonical mode, @@ -2040,7 +2045,7 @@ do_it_again: */ while (1) { tty_set_flow_change(tty, TTY_UNTHROTTLE_SAFE); - if (n_tty_chars_in_buffer(tty) > TTY_THRESHOLD_UNTHROTTLE) + if (chars_in_buffer(tty) > TTY_THRESHOLD_UNTHROTTLE) break; if (!tty->count) break; From 475340846f4c9c307f2de03cb4fcc486e267e974 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:14:19 -0400 Subject: [PATCH 0488/3400] tty: Deprecate ldisc .chars_in_buffer() method Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 594a3c19882b..290769c67a8d 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -297,6 +297,7 @@ static ssize_t chars_in_buffer(struct tty_struct *tty) static ssize_t n_tty_chars_in_buffer(struct tty_struct *tty) { + WARN_ONCE(1, "%s is deprecated and scheduled for removal.", __func__); return chars_in_buffer(tty); } From ce74117a1823431c86f5cb620fa852d21310feac Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:14:20 -0400 Subject: [PATCH 0489/3400] n_tty: Get read_cnt through accessor Prepare for replacing read_cnt field with computed value. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 290769c67a8d..371612b42238 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -115,6 +115,11 @@ struct n_tty_data { raw_spinlock_t read_lock; }; +static inline size_t read_cnt(struct n_tty_data *ldata) +{ + return ldata->read_cnt; +} + static inline int tty_put_user(struct tty_struct *tty, unsigned char x, unsigned char __user *ptr) { @@ -133,9 +138,9 @@ static int receive_room(struct tty_struct *tty) /* Multiply read_cnt by 3, since each byte might take up to * three times as many spaces when PARMRK is set (depending on * its flags, e.g. parity error). */ - left = N_TTY_BUF_SIZE - ldata->read_cnt * 3 - 1; + left = N_TTY_BUF_SIZE - read_cnt(ldata) * 3 - 1; } else - left = N_TTY_BUF_SIZE - ldata->read_cnt - 1; + left = N_TTY_BUF_SIZE - read_cnt(ldata) - 1; /* * If we are doing input canonicalization, and there are no @@ -180,7 +185,7 @@ static void n_tty_set_room(struct tty_struct *tty) static void put_tty_queue_nolock(unsigned char c, struct n_tty_data *ldata) { - if (ldata->read_cnt < N_TTY_BUF_SIZE) { + if (read_cnt(ldata) < N_TTY_BUF_SIZE) { ldata->read_buf[ldata->read_head] = c; ldata->read_head = (ldata->read_head + 1) & (N_TTY_BUF_SIZE-1); ldata->read_cnt++; @@ -285,7 +290,7 @@ static ssize_t chars_in_buffer(struct tty_struct *tty) raw_spin_lock_irqsave(&ldata->read_lock, flags); if (!ldata->icanon) { - n = ldata->read_cnt; + n = read_cnt(ldata); } else if (ldata->canon_data) { n = (ldata->canon_head > ldata->read_tail) ? ldata->canon_head - ldata->read_tail : @@ -1204,7 +1209,7 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) if (!test_bit(c, ldata->process_char_map) || ldata->lnext) { ldata->lnext = 0; parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0; - if (ldata->read_cnt >= (N_TTY_BUF_SIZE - parmrk - 1)) { + if (read_cnt(ldata) >= (N_TTY_BUF_SIZE - parmrk - 1)) { /* beep if no space */ if (L_ECHO(tty)) process_output('\a', tty); @@ -1304,7 +1309,7 @@ send_signal: return; } if (c == '\n') { - if (ldata->read_cnt >= N_TTY_BUF_SIZE) { + if (read_cnt(ldata) >= N_TTY_BUF_SIZE) { if (L_ECHO(tty)) process_output('\a', tty); return; @@ -1316,7 +1321,7 @@ send_signal: goto handle_newline; } if (c == EOF_CHAR(tty)) { - if (ldata->read_cnt >= N_TTY_BUF_SIZE) + if (read_cnt(ldata) >= N_TTY_BUF_SIZE) return; if (ldata->canon_head != ldata->read_head) set_bit(TTY_PUSH, &tty->flags); @@ -1327,7 +1332,7 @@ send_signal: (c == EOL2_CHAR(tty) && L_IEXTEN(tty))) { parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0; - if (ldata->read_cnt >= (N_TTY_BUF_SIZE - parmrk)) { + if (read_cnt(ldata) >= (N_TTY_BUF_SIZE - parmrk)) { if (L_ECHO(tty)) process_output('\a', tty); return; @@ -1364,7 +1369,7 @@ handle_newline: } parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0; - if (ldata->read_cnt >= (N_TTY_BUF_SIZE - parmrk - 1)) { + if (read_cnt(ldata) >= (N_TTY_BUF_SIZE - parmrk - 1)) { /* beep if no space */ if (L_ECHO(tty)) process_output('\a', tty); @@ -1430,7 +1435,7 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, if (ldata->real_raw) { raw_spin_lock_irqsave(&ldata->read_lock, cpuflags); - i = min(N_TTY_BUF_SIZE - ldata->read_cnt, + i = min(N_TTY_BUF_SIZE - read_cnt(ldata), N_TTY_BUF_SIZE - ldata->read_head); i = min(count, i); memcpy(ldata->read_buf + ldata->read_head, cp, i); @@ -1439,7 +1444,7 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, cp += i; count -= i; - i = min(N_TTY_BUF_SIZE - ldata->read_cnt, + i = min(N_TTY_BUF_SIZE - read_cnt(ldata), N_TTY_BUF_SIZE - ldata->read_head); i = min(count, i); memcpy(ldata->read_buf + ldata->read_head, cp, i); @@ -1474,7 +1479,7 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, tty->ops->flush_chars(tty); } - if ((!ldata->icanon && (ldata->read_cnt >= ldata->minimum_to_wake)) || + if ((!ldata->icanon && (read_cnt(ldata) >= ldata->minimum_to_wake)) || L_EXTPROC(tty)) { kill_fasync(&tty->fasync, SIGIO, POLL_IN); if (waitqueue_active(&tty->read_wait)) @@ -1552,7 +1557,7 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old) ldata->erasing = 0; } - if (canon_change && !L_ICANON(tty) && ldata->read_cnt) + if (canon_change && !L_ICANON(tty) && read_cnt(ldata)) wake_up_interruptible(&tty->read_wait); ldata->icanon = (L_ICANON(tty) != 0); @@ -1701,7 +1706,7 @@ static inline int input_available_p(struct tty_struct *tty, int amt) if (ldata->icanon && !L_EXTPROC(tty)) { if (ldata->canon_data) return 1; - } else if (ldata->read_cnt >= (amt ? amt : 1)) + } else if (read_cnt(ldata) >= (amt ? amt : 1)) return 1; return 0; @@ -1737,7 +1742,7 @@ static int copy_from_read_buf(struct tty_struct *tty, retval = 0; raw_spin_lock_irqsave(&ldata->read_lock, flags); - n = min(ldata->read_cnt, N_TTY_BUF_SIZE - ldata->read_tail); + n = min(read_cnt(ldata), N_TTY_BUF_SIZE - ldata->read_tail); n = min(*nr, n); raw_spin_unlock_irqrestore(&ldata->read_lock, flags); if (n) { @@ -1751,7 +1756,7 @@ static int copy_from_read_buf(struct tty_struct *tty, ldata->read_tail = (ldata->read_tail + n) & (N_TTY_BUF_SIZE-1); ldata->read_cnt -= n; /* Turn single EOF into zero-length read */ - if (L_EXTPROC(tty) && ldata->icanon && is_eof && !ldata->read_cnt) + if (L_EXTPROC(tty) && ldata->icanon && is_eof && !read_cnt(ldata)) n = 0; raw_spin_unlock_irqrestore(&ldata->read_lock, flags); *b += n; @@ -1787,7 +1792,7 @@ static int canon_copy_from_read_buf(struct tty_struct *tty, raw_spin_lock_irqsave(&ldata->read_lock, flags); - n = min_t(size_t, *nr, ldata->read_cnt); + n = min(*nr, read_cnt(ldata)); if (!n) { raw_spin_unlock_irqrestore(&ldata->read_lock, flags); return 0; @@ -2253,7 +2258,7 @@ static int n_tty_ioctl(struct tty_struct *tty, struct file *file, return put_user(tty_chars_in_buffer(tty), (int __user *) arg); case TIOCINQ: /* FIXME: Locking */ - retval = ldata->read_cnt; + retval = read_cnt(ldata); if (L_ICANON(tty)) retval = inq_canon(ldata); return put_user(retval, (unsigned int __user *) arg); From bc5a5e3f45d047844830233fb95b19a95c864a0f Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:14:21 -0400 Subject: [PATCH 0490/3400] n_tty: Don't wrap input buffer indices at buffer size Wrap read_buf indices (read_head, read_tail, canon_head) at max representable value, instead of at the N_TTY_BUF_SIZE. This step is necessary to allow lockless reads of these shared variables (by updating the variables atomically). Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 111 ++++++++++++++++++++++++-------------------- 1 file changed, 60 insertions(+), 51 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 371612b42238..b2fef10a0c62 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -96,8 +96,8 @@ struct n_tty_data { DECLARE_BITMAP(read_flags, N_TTY_BUF_SIZE); char *read_buf; - int read_head; - int read_tail; + size_t read_head; + size_t read_tail; int read_cnt; int minimum_to_wake; @@ -106,7 +106,7 @@ struct n_tty_data { unsigned int echo_cnt; int canon_data; - unsigned long canon_head; + size_t canon_head; unsigned int canon_column; struct mutex atomic_read_lock; @@ -120,6 +120,16 @@ static inline size_t read_cnt(struct n_tty_data *ldata) return ldata->read_cnt; } +static inline unsigned char read_buf(struct n_tty_data *ldata, size_t i) +{ + return ldata->read_buf[i & (N_TTY_BUF_SIZE - 1)]; +} + +static inline unsigned char *read_buf_addr(struct n_tty_data *ldata, size_t i) +{ + return &ldata->read_buf[i & (N_TTY_BUF_SIZE - 1)]; +} + static inline int tty_put_user(struct tty_struct *tty, unsigned char x, unsigned char __user *ptr) { @@ -186,8 +196,8 @@ static void n_tty_set_room(struct tty_struct *tty) static void put_tty_queue_nolock(unsigned char c, struct n_tty_data *ldata) { if (read_cnt(ldata) < N_TTY_BUF_SIZE) { - ldata->read_buf[ldata->read_head] = c; - ldata->read_head = (ldata->read_head + 1) & (N_TTY_BUF_SIZE-1); + *read_buf_addr(ldata, ldata->read_head) = c; + ldata->read_head++; ldata->read_cnt++; } } @@ -289,13 +299,10 @@ static ssize_t chars_in_buffer(struct tty_struct *tty) ssize_t n = 0; raw_spin_lock_irqsave(&ldata->read_lock, flags); - if (!ldata->icanon) { + if (!ldata->icanon) n = read_cnt(ldata); - } else if (ldata->canon_data) { - n = (ldata->canon_head > ldata->read_tail) ? - ldata->canon_head - ldata->read_tail : - ldata->canon_head + (N_TTY_BUF_SIZE - ldata->read_tail); - } + else + n = ldata->canon_head - ldata->read_tail; raw_spin_unlock_irqrestore(&ldata->read_lock, flags); return n; } @@ -918,7 +925,9 @@ static void eraser(unsigned char c, struct tty_struct *tty) { struct n_tty_data *ldata = tty->disc_data; enum { ERASE, WERASE, KILL } kill_type; - int head, seen_alnums, cnt; + size_t head; + size_t cnt; + int seen_alnums; unsigned long flags; /* FIXME: locking needed ? */ @@ -962,8 +971,8 @@ static void eraser(unsigned char c, struct tty_struct *tty) /* erase a single possibly multibyte character */ do { - head = (head - 1) & (N_TTY_BUF_SIZE-1); - c = ldata->read_buf[head]; + head--; + c = read_buf(ldata, head); } while (is_continuation(c, tty) && head != ldata->canon_head); /* do not partially erase */ @@ -977,7 +986,7 @@ static void eraser(unsigned char c, struct tty_struct *tty) else if (seen_alnums) break; } - cnt = (ldata->read_head - head) & (N_TTY_BUF_SIZE-1); + cnt = ldata->read_head - head; raw_spin_lock_irqsave(&ldata->read_lock, flags); ldata->read_head = head; ldata->read_cnt -= cnt; @@ -991,9 +1000,8 @@ static void eraser(unsigned char c, struct tty_struct *tty) /* if cnt > 1, output a multi-byte character */ echo_char(c, tty); while (--cnt > 0) { - head = (head+1) & (N_TTY_BUF_SIZE-1); - echo_char_raw(ldata->read_buf[head], - ldata); + head++; + echo_char_raw(read_buf(ldata, head), ldata); echo_move_back_col(ldata); } } else if (kill_type == ERASE && !L_ECHOE(tty)) { @@ -1001,7 +1009,7 @@ static void eraser(unsigned char c, struct tty_struct *tty) } else if (c == '\t') { unsigned int num_chars = 0; int after_tab = 0; - unsigned long tail = ldata->read_head; + size_t tail = ldata->read_head; /* * Count the columns used for characters @@ -1011,8 +1019,8 @@ static void eraser(unsigned char c, struct tty_struct *tty) * number of columns. */ while (tail != ldata->canon_head) { - tail = (tail-1) & (N_TTY_BUF_SIZE-1); - c = ldata->read_buf[tail]; + tail--; + c = read_buf(ldata, tail); if (c == '\t') { after_tab = 1; break; @@ -1296,14 +1304,14 @@ send_signal: } if (c == REPRINT_CHAR(tty) && L_ECHO(tty) && L_IEXTEN(tty)) { - unsigned long tail = ldata->canon_head; + size_t tail = ldata->canon_head; finish_erasing(ldata); echo_char(c, tty); echo_char_raw('\n', ldata); while (tail != ldata->read_head) { - echo_char(ldata->read_buf[tail], tty); - tail = (tail+1) & (N_TTY_BUF_SIZE-1); + echo_char(read_buf(ldata, tail), tty); + tail++; } process_echoes(tty); return; @@ -1356,7 +1364,7 @@ send_signal: handle_newline: raw_spin_lock_irqsave(&ldata->read_lock, flags); - set_bit(ldata->read_head, ldata->read_flags); + set_bit(ldata->read_head & (N_TTY_BUF_SIZE - 1), ldata->read_flags); put_tty_queue_nolock(c, ldata); ldata->canon_head = ldata->read_head; ldata->canon_data++; @@ -1436,19 +1444,19 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, if (ldata->real_raw) { raw_spin_lock_irqsave(&ldata->read_lock, cpuflags); i = min(N_TTY_BUF_SIZE - read_cnt(ldata), - N_TTY_BUF_SIZE - ldata->read_head); + N_TTY_BUF_SIZE - (ldata->read_head & (N_TTY_BUF_SIZE - 1))); i = min(count, i); - memcpy(ldata->read_buf + ldata->read_head, cp, i); - ldata->read_head = (ldata->read_head + i) & (N_TTY_BUF_SIZE-1); + memcpy(read_buf_addr(ldata, ldata->read_head), cp, i); + ldata->read_head += i; ldata->read_cnt += i; cp += i; count -= i; i = min(N_TTY_BUF_SIZE - read_cnt(ldata), - N_TTY_BUF_SIZE - ldata->read_head); + N_TTY_BUF_SIZE - (ldata->read_head & (N_TTY_BUF_SIZE - 1))); i = min(count, i); - memcpy(ldata->read_buf + ldata->read_head, cp, i); - ldata->read_head = (ldata->read_head + i) & (N_TTY_BUF_SIZE-1); + memcpy(read_buf_addr(ldata, ldata->read_head), cp, i); + ldata->read_head += i; ldata->read_cnt += i; raw_spin_unlock_irqrestore(&ldata->read_lock, cpuflags); } else { @@ -1739,21 +1747,21 @@ static int copy_from_read_buf(struct tty_struct *tty, size_t n; unsigned long flags; bool is_eof; + size_t tail = ldata->read_tail & (N_TTY_BUF_SIZE - 1); retval = 0; raw_spin_lock_irqsave(&ldata->read_lock, flags); - n = min(read_cnt(ldata), N_TTY_BUF_SIZE - ldata->read_tail); + n = min(read_cnt(ldata), N_TTY_BUF_SIZE - tail); n = min(*nr, n); raw_spin_unlock_irqrestore(&ldata->read_lock, flags); if (n) { - retval = copy_to_user(*b, &ldata->read_buf[ldata->read_tail], n); + retval = copy_to_user(*b, read_buf_addr(ldata, tail), n); n -= retval; - is_eof = n == 1 && - ldata->read_buf[ldata->read_tail] == EOF_CHAR(tty); - tty_audit_add_data(tty, &ldata->read_buf[ldata->read_tail], n, + is_eof = n == 1 && read_buf(ldata, tail) == EOF_CHAR(tty); + tty_audit_add_data(tty, read_buf_addr(ldata, tail), n, ldata->icanon); raw_spin_lock_irqsave(&ldata->read_lock, flags); - ldata->read_tail = (ldata->read_tail + n) & (N_TTY_BUF_SIZE-1); + ldata->read_tail += n; ldata->read_cnt -= n; /* Turn single EOF into zero-length read */ if (L_EXTPROC(tty) && ldata->icanon && is_eof && !read_cnt(ldata)) @@ -1785,8 +1793,9 @@ static int canon_copy_from_read_buf(struct tty_struct *tty, struct n_tty_data *ldata = tty->disc_data; unsigned long flags; size_t n, size, more, c; - unsigned long eol; - int ret, tail, found = 0; + size_t eol; + size_t tail; + int ret, found = 0; /* N.B. avoid overrun if nr == 0 */ @@ -1798,10 +1807,10 @@ static int canon_copy_from_read_buf(struct tty_struct *tty, return 0; } - tail = ldata->read_tail; + tail = ldata->read_tail & (N_TTY_BUF_SIZE - 1); size = min_t(size_t, tail + n, N_TTY_BUF_SIZE); - n_tty_trace("%s: nr:%zu tail:%d n:%zu size:%zu\n", + n_tty_trace("%s: nr:%zu tail:%zu n:%zu size:%zu\n", __func__, *nr, tail, n, size); eol = find_next_bit(ldata->read_flags, size, tail); @@ -1818,21 +1827,21 @@ static int canon_copy_from_read_buf(struct tty_struct *tty, n = (found + eol + size) & (N_TTY_BUF_SIZE - 1); c = n; - if (found && ldata->read_buf[eol] == __DISABLED_CHAR) + if (found && read_buf(ldata, eol) == __DISABLED_CHAR) n--; - n_tty_trace("%s: eol:%lu found:%d n:%zu c:%zu size:%zu more:%zu\n", + n_tty_trace("%s: eol:%zu found:%d n:%zu c:%zu size:%zu more:%zu\n", __func__, eol, found, n, c, size, more); raw_spin_unlock_irqrestore(&ldata->read_lock, flags); if (n > size) { - ret = copy_to_user(*b, &ldata->read_buf[tail], size); + ret = copy_to_user(*b, read_buf_addr(ldata, tail), size); if (ret) return -EFAULT; ret = copy_to_user(*b + size, ldata->read_buf, n - size); } else - ret = copy_to_user(*b, &ldata->read_buf[tail], n); + ret = copy_to_user(*b, read_buf_addr(ldata, tail), n); if (ret) return -EFAULT; @@ -1840,7 +1849,7 @@ static int canon_copy_from_read_buf(struct tty_struct *tty, *nr -= n; raw_spin_lock_irqsave(&ldata->read_lock, flags); - ldata->read_tail = (ldata->read_tail + c) & (N_TTY_BUF_SIZE - 1); + ldata->read_tail += c; ldata->read_cnt -= c; if (found) { __clear_bit(eol, ldata->read_flags); @@ -2230,19 +2239,19 @@ static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file, static unsigned long inq_canon(struct n_tty_data *ldata) { - int nr, head, tail; + size_t nr, head, tail; if (!ldata->canon_data) return 0; head = ldata->canon_head; tail = ldata->read_tail; - nr = (head - tail) & (N_TTY_BUF_SIZE-1); + nr = head - tail; /* Skip EOF-chars.. */ while (head != tail) { - if (test_bit(tail, ldata->read_flags) && - ldata->read_buf[tail] == __DISABLED_CHAR) + if (test_bit(tail & (N_TTY_BUF_SIZE - 1), ldata->read_flags) && + read_buf(ldata, tail) == __DISABLED_CHAR) nr--; - tail = (tail+1) & (N_TTY_BUF_SIZE-1); + tail++; } return nr; } From a2f73be8ee36e48f11f89ab705beb3c587a2f320 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:14:22 -0400 Subject: [PATCH 0491/3400] n_tty: Remove read_cnt Storing the read_cnt creates an unnecessary shared variable between the single-producer (n_tty_receive_buf()) and the single-consumer (n_tty_read()). Compute read_cnt from head & tail instead of storing. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index b2fef10a0c62..d159059560e8 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -98,7 +98,6 @@ struct n_tty_data { char *read_buf; size_t read_head; size_t read_tail; - int read_cnt; int minimum_to_wake; unsigned char *echo_buf; @@ -117,7 +116,7 @@ struct n_tty_data { static inline size_t read_cnt(struct n_tty_data *ldata) { - return ldata->read_cnt; + return ldata->read_head - ldata->read_tail; } static inline unsigned char read_buf(struct n_tty_data *ldata, size_t i) @@ -198,7 +197,6 @@ static void put_tty_queue_nolock(unsigned char c, struct n_tty_data *ldata) if (read_cnt(ldata) < N_TTY_BUF_SIZE) { *read_buf_addr(ldata, ldata->read_head) = c; ldata->read_head++; - ldata->read_cnt++; } } @@ -239,7 +237,7 @@ static void reset_buffer_flags(struct n_tty_data *ldata) unsigned long flags; raw_spin_lock_irqsave(&ldata->read_lock, flags); - ldata->read_head = ldata->read_tail = ldata->read_cnt = 0; + ldata->read_head = ldata->read_tail = 0; raw_spin_unlock_irqrestore(&ldata->read_lock, flags); mutex_lock(&ldata->echo_lock); @@ -942,16 +940,12 @@ static void eraser(unsigned char c, struct tty_struct *tty) else { if (!L_ECHO(tty)) { raw_spin_lock_irqsave(&ldata->read_lock, flags); - ldata->read_cnt -= ((ldata->read_head - ldata->canon_head) & - (N_TTY_BUF_SIZE - 1)); ldata->read_head = ldata->canon_head; raw_spin_unlock_irqrestore(&ldata->read_lock, flags); return; } if (!L_ECHOK(tty) || !L_ECHOKE(tty) || !L_ECHOE(tty)) { raw_spin_lock_irqsave(&ldata->read_lock, flags); - ldata->read_cnt -= ((ldata->read_head - ldata->canon_head) & - (N_TTY_BUF_SIZE - 1)); ldata->read_head = ldata->canon_head; raw_spin_unlock_irqrestore(&ldata->read_lock, flags); finish_erasing(ldata); @@ -989,7 +983,6 @@ static void eraser(unsigned char c, struct tty_struct *tty) cnt = ldata->read_head - head; raw_spin_lock_irqsave(&ldata->read_lock, flags); ldata->read_head = head; - ldata->read_cnt -= cnt; raw_spin_unlock_irqrestore(&ldata->read_lock, flags); if (L_ECHO(tty)) { if (L_ECHOPRT(tty)) { @@ -1448,7 +1441,6 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, i = min(count, i); memcpy(read_buf_addr(ldata, ldata->read_head), cp, i); ldata->read_head += i; - ldata->read_cnt += i; cp += i; count -= i; @@ -1457,7 +1449,6 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, i = min(count, i); memcpy(read_buf_addr(ldata, ldata->read_head), cp, i); ldata->read_head += i; - ldata->read_cnt += i; raw_spin_unlock_irqrestore(&ldata->read_lock, cpuflags); } else { for (i = count, p = cp, f = fp; i; i--, p++) { @@ -1762,7 +1753,6 @@ static int copy_from_read_buf(struct tty_struct *tty, ldata->icanon); raw_spin_lock_irqsave(&ldata->read_lock, flags); ldata->read_tail += n; - ldata->read_cnt -= n; /* Turn single EOF into zero-length read */ if (L_EXTPROC(tty) && ldata->icanon && is_eof && !read_cnt(ldata)) n = 0; @@ -1850,7 +1840,6 @@ static int canon_copy_from_read_buf(struct tty_struct *tty, raw_spin_lock_irqsave(&ldata->read_lock, flags); ldata->read_tail += c; - ldata->read_cnt -= c; if (found) { __clear_bit(eol, ldata->read_flags); /* this test should be redundant: From 6a1c0680cf3ba94356ecd58833e1540c93472a57 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:14:23 -0400 Subject: [PATCH 0492/3400] tty: Convert termios_mutex to termios_rwsem termios is commonly accessed unsafely (especially by N_TTY) because the existing mutex forces exclusive access. Convert existing usage. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/net/irda/irtty-sir.c | 8 ++-- drivers/tty/n_tty.c | 2 +- drivers/tty/pty.c | 4 +- drivers/tty/tty_io.c | 14 +++--- drivers/tty/tty_ioctl.c | 90 ++++++++++++++++++------------------ drivers/tty/tty_ldisc.c | 10 ++-- drivers/tty/vt/vt.c | 4 +- include/linux/tty.h | 7 +-- 8 files changed, 70 insertions(+), 69 deletions(-) diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c index a41267197839..177441afeb96 100644 --- a/drivers/net/irda/irtty-sir.c +++ b/drivers/net/irda/irtty-sir.c @@ -123,14 +123,14 @@ static int irtty_change_speed(struct sir_dev *dev, unsigned speed) tty = priv->tty; - mutex_lock(&tty->termios_mutex); + down_write(&tty->termios_rwsem); old_termios = tty->termios; cflag = tty->termios.c_cflag; tty_encode_baud_rate(tty, speed, speed); if (tty->ops->set_termios) tty->ops->set_termios(tty, &old_termios); priv->io.speed = speed; - mutex_unlock(&tty->termios_mutex); + up_write(&tty->termios_rwsem); return 0; } @@ -280,7 +280,7 @@ static inline void irtty_stop_receiver(struct tty_struct *tty, int stop) struct ktermios old_termios; int cflag; - mutex_lock(&tty->termios_mutex); + down_write(&tty->termios_rwsem); old_termios = tty->termios; cflag = tty->termios.c_cflag; @@ -292,7 +292,7 @@ static inline void irtty_stop_receiver(struct tty_struct *tty, int stop) tty->termios.c_cflag = cflag; if (tty->ops->set_termios) tty->ops->set_termios(tty, &old_termios); - mutex_unlock(&tty->termios_mutex); + up_write(&tty->termios_rwsem); } /*****************************************************************/ diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index d159059560e8..ab923bb2b262 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1539,7 +1539,7 @@ int is_ignored(int sig) * guaranteed that this function will not be re-entered or in progress * when the ldisc is closed. * - * Locking: Caller holds tty->termios_mutex + * Locking: Caller holds tty->termios_rwsem */ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old) diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index abfd99089781..1b39dd639ee9 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -287,7 +287,7 @@ static int pty_resize(struct tty_struct *tty, struct winsize *ws) struct tty_struct *pty = tty->link; /* For a PTY we need to lock the tty side */ - mutex_lock(&tty->termios_mutex); + down_write(&tty->termios_rwsem); if (!memcmp(ws, &tty->winsize, sizeof(*ws))) goto done; @@ -314,7 +314,7 @@ static int pty_resize(struct tty_struct *tty, struct winsize *ws) tty->winsize = *ws; pty->winsize = *ws; /* Never used so will go away soon */ done: - mutex_unlock(&tty->termios_mutex); + up_write(&tty->termios_rwsem); return 0; } diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 0fa5db4c7a7a..639e24ade9bf 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -604,7 +604,7 @@ static int tty_signal_session_leader(struct tty_struct *tty, int exit_session) * redirect lock for undoing redirection * file list lock for manipulating list of ttys * tty_ldiscs_lock from called functions - * termios_mutex resetting termios data + * termios_rwsem resetting termios data * tasklist_lock to walk task list for hangup event * ->siglock to protect ->signal/->sighand */ @@ -2230,7 +2230,7 @@ static int tiocsti(struct tty_struct *tty, char __user *p) * * Copies the kernel idea of the window size into the user buffer. * - * Locking: tty->termios_mutex is taken to ensure the winsize data + * Locking: tty->termios_rwsem is taken to ensure the winsize data * is consistent. */ @@ -2238,9 +2238,9 @@ static int tiocgwinsz(struct tty_struct *tty, struct winsize __user *arg) { int err; - mutex_lock(&tty->termios_mutex); + down_read(&tty->termios_rwsem); err = copy_to_user(arg, &tty->winsize, sizeof(*arg)); - mutex_unlock(&tty->termios_mutex); + up_read(&tty->termios_rwsem); return err ? -EFAULT: 0; } @@ -2261,7 +2261,7 @@ int tty_do_resize(struct tty_struct *tty, struct winsize *ws) unsigned long flags; /* Lock the tty */ - mutex_lock(&tty->termios_mutex); + down_write(&tty->termios_rwsem); if (!memcmp(ws, &tty->winsize, sizeof(*ws))) goto done; /* Get the PID values and reference them so we can @@ -2276,7 +2276,7 @@ int tty_do_resize(struct tty_struct *tty, struct winsize *ws) tty->winsize = *ws; done: - mutex_unlock(&tty->termios_mutex); + up_write(&tty->termios_rwsem); return 0; } EXPORT_SYMBOL(tty_do_resize); @@ -3015,7 +3015,7 @@ void initialize_tty_struct(struct tty_struct *tty, tty->session = NULL; tty->pgrp = NULL; mutex_init(&tty->legacy_mutex); - mutex_init(&tty->termios_mutex); + init_rwsem(&tty->termios_rwsem); init_ldsem(&tty->ldisc_sem); init_waitqueue_head(&tty->write_wait); init_waitqueue_head(&tty->read_wait); diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c index 3500d4114147..9ce20df8a2c8 100644 --- a/drivers/tty/tty_ioctl.c +++ b/drivers/tty/tty_ioctl.c @@ -94,20 +94,20 @@ EXPORT_SYMBOL(tty_driver_flush_buffer); * @tty: terminal * * Indicate that a tty should stop transmitting data down the stack. - * Takes the termios mutex to protect against parallel throttle/unthrottle + * Takes the termios rwsem to protect against parallel throttle/unthrottle * and also to ensure the driver can consistently reference its own * termios data at this point when implementing software flow control. */ void tty_throttle(struct tty_struct *tty) { - mutex_lock(&tty->termios_mutex); + down_write(&tty->termios_rwsem); /* check TTY_THROTTLED first so it indicates our state */ if (!test_and_set_bit(TTY_THROTTLED, &tty->flags) && tty->ops->throttle) tty->ops->throttle(tty); tty->flow_change = 0; - mutex_unlock(&tty->termios_mutex); + up_write(&tty->termios_rwsem); } EXPORT_SYMBOL(tty_throttle); @@ -116,7 +116,7 @@ EXPORT_SYMBOL(tty_throttle); * @tty: terminal * * Indicate that a tty may continue transmitting data down the stack. - * Takes the termios mutex to protect against parallel throttle/unthrottle + * Takes the termios rwsem to protect against parallel throttle/unthrottle * and also to ensure the driver can consistently reference its own * termios data at this point when implementing software flow control. * @@ -126,12 +126,12 @@ EXPORT_SYMBOL(tty_throttle); void tty_unthrottle(struct tty_struct *tty) { - mutex_lock(&tty->termios_mutex); + down_write(&tty->termios_rwsem); if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) && tty->ops->unthrottle) tty->ops->unthrottle(tty); tty->flow_change = 0; - mutex_unlock(&tty->termios_mutex); + up_write(&tty->termios_rwsem); } EXPORT_SYMBOL(tty_unthrottle); @@ -151,7 +151,7 @@ int tty_throttle_safe(struct tty_struct *tty) { int ret = 0; - mutex_lock(&tty->termios_mutex); + down_write(&tty->termios_rwsem); if (!test_bit(TTY_THROTTLED, &tty->flags)) { if (tty->flow_change != TTY_THROTTLE_SAFE) ret = 1; @@ -161,7 +161,7 @@ int tty_throttle_safe(struct tty_struct *tty) tty->ops->throttle(tty); } } - mutex_unlock(&tty->termios_mutex); + up_write(&tty->termios_rwsem); return ret; } @@ -182,7 +182,7 @@ int tty_unthrottle_safe(struct tty_struct *tty) { int ret = 0; - mutex_lock(&tty->termios_mutex); + down_write(&tty->termios_rwsem); if (test_bit(TTY_THROTTLED, &tty->flags)) { if (tty->flow_change != TTY_UNTHROTTLE_SAFE) ret = 1; @@ -192,7 +192,7 @@ int tty_unthrottle_safe(struct tty_struct *tty) tty->ops->unthrottle(tty); } } - mutex_unlock(&tty->termios_mutex); + up_write(&tty->termios_rwsem); return ret; } @@ -468,7 +468,7 @@ EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate); * @obad: output baud rate * * Update the current termios data for the tty with the new speed - * settings. The caller must hold the termios_mutex for the tty in + * settings. The caller must hold the termios_rwsem for the tty in * question. */ @@ -528,7 +528,7 @@ EXPORT_SYMBOL(tty_termios_hw_change); * is a bit of layering violation here with n_tty in terms of the * internal knowledge of this function. * - * Locking: termios_mutex + * Locking: termios_rwsem */ int tty_set_termios(struct tty_struct *tty, struct ktermios *new_termios) @@ -544,7 +544,7 @@ int tty_set_termios(struct tty_struct *tty, struct ktermios *new_termios) /* FIXME: we need to decide on some locking/ordering semantics for the set_termios notification eventually */ - mutex_lock(&tty->termios_mutex); + down_write(&tty->termios_rwsem); old_termios = tty->termios; tty->termios = *new_termios; unset_locked_termios(&tty->termios, &old_termios, &tty->termios_locked); @@ -586,7 +586,7 @@ int tty_set_termios(struct tty_struct *tty, struct ktermios *new_termios) (ld->ops->set_termios)(tty, &old_termios); tty_ldisc_deref(ld); } - mutex_unlock(&tty->termios_mutex); + up_write(&tty->termios_rwsem); return 0; } EXPORT_SYMBOL_GPL(tty_set_termios); @@ -601,7 +601,7 @@ EXPORT_SYMBOL_GPL(tty_set_termios); * functions before using tty_set_termios to do the actual changes. * * Locking: - * Called functions take ldisc and termios_mutex locks + * Called functions take ldisc and termios_rwsem locks */ static int set_termios(struct tty_struct *tty, void __user *arg, int opt) @@ -613,9 +613,9 @@ static int set_termios(struct tty_struct *tty, void __user *arg, int opt) if (retval) return retval; - mutex_lock(&tty->termios_mutex); + down_read(&tty->termios_rwsem); tmp_termios = tty->termios; - mutex_unlock(&tty->termios_mutex); + up_read(&tty->termios_rwsem); if (opt & TERMIOS_TERMIO) { if (user_termio_to_kernel_termios(&tmp_termios, @@ -667,16 +667,16 @@ static int set_termios(struct tty_struct *tty, void __user *arg, int opt) static void copy_termios(struct tty_struct *tty, struct ktermios *kterm) { - mutex_lock(&tty->termios_mutex); + down_read(&tty->termios_rwsem); *kterm = tty->termios; - mutex_unlock(&tty->termios_mutex); + up_read(&tty->termios_rwsem); } static void copy_termios_locked(struct tty_struct *tty, struct ktermios *kterm) { - mutex_lock(&tty->termios_mutex); + down_read(&tty->termios_rwsem); *kterm = tty->termios_locked; - mutex_unlock(&tty->termios_mutex); + up_read(&tty->termios_rwsem); } static int get_termio(struct tty_struct *tty, struct termio __user *termio) @@ -723,10 +723,10 @@ static int set_termiox(struct tty_struct *tty, void __user *arg, int opt) return -ERESTARTSYS; } - mutex_lock(&tty->termios_mutex); + down_write(&tty->termios_rwsem); if (tty->ops->set_termiox) tty->ops->set_termiox(tty, &tnew); - mutex_unlock(&tty->termios_mutex); + up_write(&tty->termios_rwsem); return 0; } @@ -761,13 +761,13 @@ static int get_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb) { struct sgttyb tmp; - mutex_lock(&tty->termios_mutex); + down_read(&tty->termios_rwsem); tmp.sg_ispeed = tty->termios.c_ispeed; tmp.sg_ospeed = tty->termios.c_ospeed; tmp.sg_erase = tty->termios.c_cc[VERASE]; tmp.sg_kill = tty->termios.c_cc[VKILL]; tmp.sg_flags = get_sgflags(tty); - mutex_unlock(&tty->termios_mutex); + up_read(&tty->termios_rwsem); return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0; } @@ -806,7 +806,7 @@ static void set_sgflags(struct ktermios *termios, int flags) * Updates a terminal from the legacy BSD style terminal information * structure. * - * Locking: termios_mutex + * Locking: termios_rwsem */ static int set_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb) @@ -822,7 +822,7 @@ static int set_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb) if (copy_from_user(&tmp, sgttyb, sizeof(tmp))) return -EFAULT; - mutex_lock(&tty->termios_mutex); + down_write(&tty->termios_rwsem); termios = tty->termios; termios.c_cc[VERASE] = tmp.sg_erase; termios.c_cc[VKILL] = tmp.sg_kill; @@ -832,7 +832,7 @@ static int set_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb) tty_termios_encode_baud_rate(&termios, termios.c_ispeed, termios.c_ospeed); #endif - mutex_unlock(&tty->termios_mutex); + up_write(&tty->termios_rwsem); tty_set_termios(tty, &termios); return 0; } @@ -843,14 +843,14 @@ static int get_tchars(struct tty_struct *tty, struct tchars __user *tchars) { struct tchars tmp; - mutex_lock(&tty->termios_mutex); + down_read(&tty->termios_rwsem); tmp.t_intrc = tty->termios.c_cc[VINTR]; tmp.t_quitc = tty->termios.c_cc[VQUIT]; tmp.t_startc = tty->termios.c_cc[VSTART]; tmp.t_stopc = tty->termios.c_cc[VSTOP]; tmp.t_eofc = tty->termios.c_cc[VEOF]; tmp.t_brkc = tty->termios.c_cc[VEOL2]; /* what is brkc anyway? */ - mutex_unlock(&tty->termios_mutex); + up_read(&tty->termios_rwsem); return copy_to_user(tchars, &tmp, sizeof(tmp)) ? -EFAULT : 0; } @@ -860,14 +860,14 @@ static int set_tchars(struct tty_struct *tty, struct tchars __user *tchars) if (copy_from_user(&tmp, tchars, sizeof(tmp))) return -EFAULT; - mutex_lock(&tty->termios_mutex); + down_write(&tty->termios_rwsem); tty->termios.c_cc[VINTR] = tmp.t_intrc; tty->termios.c_cc[VQUIT] = tmp.t_quitc; tty->termios.c_cc[VSTART] = tmp.t_startc; tty->termios.c_cc[VSTOP] = tmp.t_stopc; tty->termios.c_cc[VEOF] = tmp.t_eofc; tty->termios.c_cc[VEOL2] = tmp.t_brkc; /* what is brkc anyway? */ - mutex_unlock(&tty->termios_mutex); + up_write(&tty->termios_rwsem); return 0; } #endif @@ -877,7 +877,7 @@ static int get_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars) { struct ltchars tmp; - mutex_lock(&tty->termios_mutex); + down_read(&tty->termios_rwsem); tmp.t_suspc = tty->termios.c_cc[VSUSP]; /* what is dsuspc anyway? */ tmp.t_dsuspc = tty->termios.c_cc[VSUSP]; @@ -886,7 +886,7 @@ static int get_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars) tmp.t_flushc = tty->termios.c_cc[VEOL2]; tmp.t_werasc = tty->termios.c_cc[VWERASE]; tmp.t_lnextc = tty->termios.c_cc[VLNEXT]; - mutex_unlock(&tty->termios_mutex); + up_read(&tty->termios_rwsem); return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0; } @@ -897,7 +897,7 @@ static int set_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars) if (copy_from_user(&tmp, ltchars, sizeof(tmp))) return -EFAULT; - mutex_lock(&tty->termios_mutex); + down_write(&tty->termios_rwsem); tty->termios.c_cc[VSUSP] = tmp.t_suspc; /* what is dsuspc anyway? */ tty->termios.c_cc[VEOL2] = tmp.t_dsuspc; @@ -906,7 +906,7 @@ static int set_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars) tty->termios.c_cc[VEOL2] = tmp.t_flushc; tty->termios.c_cc[VWERASE] = tmp.t_werasc; tty->termios.c_cc[VLNEXT] = tmp.t_lnextc; - mutex_unlock(&tty->termios_mutex); + up_write(&tty->termios_rwsem); return 0; } #endif @@ -946,7 +946,7 @@ static int send_prio_char(struct tty_struct *tty, char ch) * @arg: enable/disable CLOCAL * * Perform a change to the CLOCAL state and call into the driver - * layer to make it visible. All done with the termios mutex + * layer to make it visible. All done with the termios rwsem */ static int tty_change_softcar(struct tty_struct *tty, int arg) @@ -955,7 +955,7 @@ static int tty_change_softcar(struct tty_struct *tty, int arg) int bit = arg ? CLOCAL : 0; struct ktermios old; - mutex_lock(&tty->termios_mutex); + down_write(&tty->termios_rwsem); old = tty->termios; tty->termios.c_cflag &= ~CLOCAL; tty->termios.c_cflag |= bit; @@ -963,7 +963,7 @@ static int tty_change_softcar(struct tty_struct *tty, int arg) tty->ops->set_termios(tty, &old); if ((tty->termios.c_cflag & CLOCAL) != bit) ret = -EINVAL; - mutex_unlock(&tty->termios_mutex); + up_write(&tty->termios_rwsem); return ret; } @@ -1066,9 +1066,9 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file, if (user_termios_to_kernel_termios(&kterm, (struct termios __user *) arg)) return -EFAULT; - mutex_lock(&real_tty->termios_mutex); + down_write(&real_tty->termios_rwsem); real_tty->termios_locked = kterm; - mutex_unlock(&real_tty->termios_mutex); + up_write(&real_tty->termios_rwsem); return 0; #else case TIOCGLCKTRMIOS: @@ -1083,9 +1083,9 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file, if (user_termios_to_kernel_termios_1(&kterm, (struct termios __user *) arg)) return -EFAULT; - mutex_lock(&real_tty->termios_mutex); + down_write(&real_tty->termios_rwsem); real_tty->termios_locked = kterm; - mutex_unlock(&real_tty->termios_mutex); + up_write(&real_tty->termios_rwsem); return ret; #endif #ifdef TCGETX @@ -1093,9 +1093,9 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file, struct termiox ktermx; if (real_tty->termiox == NULL) return -EINVAL; - mutex_lock(&real_tty->termios_mutex); + down_read(&real_tty->termios_rwsem); memcpy(&ktermx, real_tty->termiox, sizeof(struct termiox)); - mutex_unlock(&real_tty->termios_mutex); + up_read(&real_tty->termios_rwsem); if (copy_to_user(p, &ktermx, sizeof(struct termiox))) ret = -EFAULT; return ret; diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index e52d61573553..6458e11e8e9d 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -415,14 +415,14 @@ EXPORT_SYMBOL_GPL(tty_ldisc_flush); * they are not on hot paths so a little discipline won't do * any harm. * - * Locking: takes termios_mutex + * Locking: takes termios_rwsem */ static void tty_set_termios_ldisc(struct tty_struct *tty, int num) { - mutex_lock(&tty->termios_mutex); + down_write(&tty->termios_rwsem); tty->termios.c_line = num; - mutex_unlock(&tty->termios_mutex); + up_write(&tty->termios_rwsem); } /** @@ -602,11 +602,11 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) static void tty_reset_termios(struct tty_struct *tty) { - mutex_lock(&tty->termios_mutex); + down_write(&tty->termios_rwsem); tty->termios = tty->driver->init_termios; tty->termios.c_ispeed = tty_termios_input_baud_rate(&tty->termios); tty->termios.c_ospeed = tty_termios_baud_rate(&tty->termios); - mutex_unlock(&tty->termios_mutex); + up_write(&tty->termios_rwsem); } diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index c677829baa8b..02af6ccefe6a 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -828,7 +828,7 @@ static inline int resize_screen(struct vc_data *vc, int width, int height, * If the caller passes a tty structure then update the termios winsize * information and perform any necessary signal handling. * - * Caller must hold the console semaphore. Takes the termios mutex and + * Caller must hold the console semaphore. Takes the termios rwsem and * ctrl_lock of the tty IFF a tty is passed. */ @@ -972,7 +972,7 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows) * the actual work. * * Takes the console sem and the called methods then take the tty - * termios_mutex and the tty ctrl_lock in that order. + * termios_rwsem and the tty ctrl_lock in that order. */ static int vt_resize(struct tty_struct *tty, struct winsize *ws) { diff --git a/include/linux/tty.h b/include/linux/tty.h index 8323ee4f95b9..d3042076d163 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -10,6 +10,7 @@ #include #include #include +#include @@ -243,9 +244,9 @@ struct tty_struct { struct mutex atomic_write_lock; struct mutex legacy_mutex; - struct mutex termios_mutex; + struct rw_semaphore termios_rwsem; spinlock_t ctrl_lock; - /* Termios values are protected by the termios mutex */ + /* Termios values are protected by the termios rwsem */ struct ktermios termios, termios_locked; struct termiox *termiox; /* May be NULL for unsupported */ char name[64]; @@ -253,7 +254,7 @@ struct tty_struct { struct pid *session; unsigned long flags; int count; - struct winsize winsize; /* termios mutex */ + struct winsize winsize; /* termios rwsem */ unsigned char stopped:1, hw_stopped:1, flow_stopped:1, packet:1; unsigned char ctrl_status; /* ctrl_lock */ unsigned int receive_room; /* Bytes free for queue */ From 9356b535fcb71db494fc434acceb79f56d15bda2 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:14:24 -0400 Subject: [PATCH 0493/3400] n_tty: Access termios values safely Use termios_rwsem to guarantee safe access to the termios values. This is particularly important for N_TTY as changing certain termios settings alters the mode of operation. termios_rwsem must be dropped across throttle/unthrottle since those functions claim the termios_rwsem exclusively (to guarantee safe access to the termios and for mutual exclusion). Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 44 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index ab923bb2b262..0599b583d21e 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1491,10 +1491,14 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, * canonical mode and don't have a newline yet! */ while (1) { + int throttled; tty_set_flow_change(tty, TTY_THROTTLE_SAFE); if (receive_room(tty) >= TTY_THRESHOLD_THROTTLE) break; - if (!tty_throttle_safe(tty)) + up_read(&tty->termios_rwsem); + throttled = tty_throttle_safe(tty); + down_read(&tty->termios_rwsem); + if (!throttled) break; } __tty_set_flow_change(tty, 0); @@ -1503,7 +1507,9 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) { + down_read(&tty->termios_rwsem); __receive_buf(tty, cp, fp, count); + up_read(&tty->termios_rwsem); } static int n_tty_receive_buf2(struct tty_struct *tty, const unsigned char *cp, @@ -1512,6 +1518,8 @@ static int n_tty_receive_buf2(struct tty_struct *tty, const unsigned char *cp, struct n_tty_data *ldata = tty->disc_data; int room; + down_read(&tty->termios_rwsem); + tty->receive_room = room = receive_room(tty); if (!room) ldata->no_room = 1; @@ -1519,6 +1527,8 @@ static int n_tty_receive_buf2(struct tty_struct *tty, const unsigned char *cp, if (count) __receive_buf(tty, cp, fp, count); + up_read(&tty->termios_rwsem); + return count; } @@ -1934,6 +1944,8 @@ do_it_again: if (c < 0) return c; + down_read(&tty->termios_rwsem); + minimum = time = 0; timeout = MAX_SCHEDULE_TIMEOUT; if (!ldata->icanon) { @@ -1955,11 +1967,15 @@ do_it_again: * Internal serialization of reads. */ if (file->f_flags & O_NONBLOCK) { - if (!mutex_trylock(&ldata->atomic_read_lock)) + if (!mutex_trylock(&ldata->atomic_read_lock)) { + up_read(&tty->termios_rwsem); return -EAGAIN; + } } else { - if (mutex_lock_interruptible(&ldata->atomic_read_lock)) + if (mutex_lock_interruptible(&ldata->atomic_read_lock)) { + up_read(&tty->termios_rwsem); return -ERESTARTSYS; + } } packet = tty->packet; @@ -2009,7 +2025,11 @@ do_it_again: break; } n_tty_set_room(tty); + up_read(&tty->termios_rwsem); + timeout = schedule_timeout(timeout); + + down_read(&tty->termios_rwsem); continue; } __set_current_state(TASK_RUNNING); @@ -2048,13 +2068,17 @@ do_it_again: * we won't get any more characters. */ while (1) { + int unthrottled; tty_set_flow_change(tty, TTY_UNTHROTTLE_SAFE); if (chars_in_buffer(tty) > TTY_THRESHOLD_UNTHROTTLE) break; if (!tty->count) break; n_tty_set_room(tty); - if (!tty_unthrottle_safe(tty)) + up_read(&tty->termios_rwsem); + unthrottled = tty_unthrottle_safe(tty); + down_read(&tty->termios_rwsem); + if (!unthrottled) break; } __tty_set_flow_change(tty, 0); @@ -2076,10 +2100,13 @@ do_it_again: retval = size; if (nr) clear_bit(TTY_PUSH, &tty->flags); - } else if (test_and_clear_bit(TTY_PUSH, &tty->flags)) + } else if (test_and_clear_bit(TTY_PUSH, &tty->flags)) { + up_read(&tty->termios_rwsem); goto do_it_again; + } n_tty_set_room(tty); + up_read(&tty->termios_rwsem); return retval; } @@ -2120,6 +2147,8 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, return retval; } + down_read(&tty->termios_rwsem); + /* Write out any echoed characters that are still pending */ process_echoes(tty); @@ -2173,13 +2202,18 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, retval = -EAGAIN; break; } + up_read(&tty->termios_rwsem); + schedule(); + + down_read(&tty->termios_rwsem); } break_out: __set_current_state(TASK_RUNNING); remove_wait_queue(&tty->write_wait, &wait); if (b - buf != nr && tty->fasync) set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); + up_read(&tty->termios_rwsem); return (b - buf) ? b - buf : retval; } From a73d3d6987e4e60d442b7cdf4f7c38400b454bf5 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:14:25 -0400 Subject: [PATCH 0494/3400] n_tty: Replace canon_data with index comparison canon_data represented the # of lines which had been copied to the receive buffer but not yet copied to the user buffer. The value was tested to determine if input was available in canonical mode (and also to force input overrun if the receive buffer was full but a newline had not been received). However, the actual count was irrelevent; only whether it was non-zero (meaning 'is there any input to transfer?'). This shared count is unnecessary and unsafe with a lockless algorithm. The same check is made by comparing canon_head with read_tail instead. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 0599b583d21e..1098dd73a4f7 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -104,7 +104,6 @@ struct n_tty_data { unsigned int echo_pos; unsigned int echo_cnt; - int canon_data; size_t canon_head; unsigned int canon_column; @@ -158,7 +157,7 @@ static int receive_room(struct tty_struct *tty) * characters will be beeped. */ if (left <= 0) - left = ldata->icanon && !ldata->canon_data; + left = ldata->icanon && ldata->canon_head == ldata->read_tail; return left; } @@ -237,14 +236,14 @@ static void reset_buffer_flags(struct n_tty_data *ldata) unsigned long flags; raw_spin_lock_irqsave(&ldata->read_lock, flags); - ldata->read_head = ldata->read_tail = 0; + ldata->read_head = ldata->canon_head = ldata->read_tail = 0; raw_spin_unlock_irqrestore(&ldata->read_lock, flags); mutex_lock(&ldata->echo_lock); ldata->echo_pos = ldata->echo_cnt = ldata->echo_overrun = 0; mutex_unlock(&ldata->echo_lock); - ldata->canon_head = ldata->canon_data = ldata->erasing = 0; + ldata->erasing = 0; bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE); } @@ -1360,7 +1359,6 @@ handle_newline: set_bit(ldata->read_head & (N_TTY_BUF_SIZE - 1), ldata->read_flags); put_tty_queue_nolock(c, ldata); ldata->canon_head = ldata->read_head; - ldata->canon_data++; raw_spin_unlock_irqrestore(&ldata->read_lock, flags); kill_fasync(&tty->fasync, SIGIO, POLL_IN); if (waitqueue_active(&tty->read_wait)) @@ -1562,7 +1560,6 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old) if (canon_change) { bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE); ldata->canon_head = ldata->read_tail; - ldata->canon_data = 0; ldata->erasing = 0; } @@ -1713,7 +1710,7 @@ static inline int input_available_p(struct tty_struct *tty, int amt) tty_flush_to_ldisc(tty); if (ldata->icanon && !L_EXTPROC(tty)) { - if (ldata->canon_data) + if (ldata->canon_head != ldata->read_tail) return 1; } else if (read_cnt(ldata) >= (amt ? amt : 1)) return 1; @@ -1850,15 +1847,8 @@ static int canon_copy_from_read_buf(struct tty_struct *tty, raw_spin_lock_irqsave(&ldata->read_lock, flags); ldata->read_tail += c; - if (found) { + if (found) __clear_bit(eol, ldata->read_flags); - /* this test should be redundant: - * we shouldn't be reading data if - * canon_data is 0 - */ - if (--ldata->canon_data < 0) - ldata->canon_data = 0; - } raw_spin_unlock_irqrestore(&ldata->read_lock, flags); if (found) @@ -2264,7 +2254,7 @@ static unsigned long inq_canon(struct n_tty_data *ldata) { size_t nr, head, tail; - if (!ldata->canon_data) + if (ldata->canon_head == ldata->read_tail) return 0; head = ldata->canon_head; tail = ldata->read_tail; From 6d76bd2618535c581f1673047b8341fd291abc67 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:14:26 -0400 Subject: [PATCH 0495/3400] n_tty: Make N_TTY ldisc receive path lockless n_tty has a single-producer/single-consumer input model; use lockless publish instead. Use termios_rwsem to exclude both consumer and producer while changing or resetting buffer indices, eg., when flushing. Also, claim exclusive termios_rwsem to safely retrieve the buffer indices from a thread other than consumer or producer (eg., TIOCINQ ioctl). Note the read_tail is published _after_ clearing the newline indicator in read_flags to avoid racing the producer. Drop read_lock spinlock. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 179 +++++++++++++++++++++++--------------------- 1 file changed, 95 insertions(+), 84 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 1098dd73a4f7..c7f71cb8ee1f 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -110,7 +110,6 @@ struct n_tty_data { struct mutex atomic_read_lock; struct mutex output_lock; struct mutex echo_lock; - raw_spinlock_t read_lock; }; static inline size_t read_cnt(struct n_tty_data *ldata) @@ -168,7 +167,10 @@ static int receive_room(struct tty_struct *tty) * * Re-schedules the flip buffer work if space just became available. * - * Locks: Concurrent update is protected with read_lock + * Caller holds exclusive termios_rwsem + * or + * n_tty_read()/consumer path: + * holds non-exclusive termios_rwsem */ static void n_tty_set_room(struct tty_struct *tty) @@ -191,34 +193,27 @@ static void n_tty_set_room(struct tty_struct *tty) } } -static void put_tty_queue_nolock(unsigned char c, struct n_tty_data *ldata) -{ - if (read_cnt(ldata) < N_TTY_BUF_SIZE) { - *read_buf_addr(ldata, ldata->read_head) = c; - ldata->read_head++; - } -} - /** * put_tty_queue - add character to tty * @c: character * @ldata: n_tty data * - * Add a character to the tty read_buf queue. This is done under the - * read_lock to serialize character addition and also to protect us - * against parallel reads or flushes + * Add a character to the tty read_buf queue. + * + * n_tty_receive_buf()/producer path: + * caller holds non-exclusive termios_rwsem + * modifies read_head + * + * read_head is only considered 'published' if canonical mode is + * not active. */ static void put_tty_queue(unsigned char c, struct n_tty_data *ldata) { - unsigned long flags; - /* - * The problem of stomping on the buffers ends here. - * Why didn't anyone see this one coming? --AJK - */ - raw_spin_lock_irqsave(&ldata->read_lock, flags); - put_tty_queue_nolock(c, ldata); - raw_spin_unlock_irqrestore(&ldata->read_lock, flags); + if (read_cnt(ldata) < N_TTY_BUF_SIZE) { + *read_buf_addr(ldata, ldata->read_head) = c; + ldata->read_head++; + } } /** @@ -228,16 +223,13 @@ static void put_tty_queue(unsigned char c, struct n_tty_data *ldata) * Reset the read buffer counters and clear the flags. * Called from n_tty_open() and n_tty_flush_buffer(). * - * Locking: tty_read_lock for read fields. + * Locking: caller holds exclusive termios_rwsem + * (or locking is not required) */ static void reset_buffer_flags(struct n_tty_data *ldata) { - unsigned long flags; - - raw_spin_lock_irqsave(&ldata->read_lock, flags); ldata->read_head = ldata->canon_head = ldata->read_tail = 0; - raw_spin_unlock_irqrestore(&ldata->read_lock, flags); mutex_lock(&ldata->echo_lock); ldata->echo_pos = ldata->echo_cnt = ldata->echo_overrun = 0; @@ -267,16 +259,33 @@ static void n_tty_packet_mode_flush(struct tty_struct *tty) * buffer flushed (eg at hangup) or when the N_TTY line discipline * internally has to clean the pending queue (for example some signals). * - * Locking: ctrl_lock, read_lock. + * Holds termios_rwsem to exclude producer/consumer while + * buffer indices are reset. + * + * Locking: ctrl_lock, exclusive termios_rwsem */ static void n_tty_flush_buffer(struct tty_struct *tty) { + down_write(&tty->termios_rwsem); reset_buffer_flags(tty->disc_data); n_tty_set_room(tty); if (tty->link) n_tty_packet_mode_flush(tty); + up_write(&tty->termios_rwsem); +} + +static ssize_t chars_in_buffer(struct tty_struct *tty) +{ + struct n_tty_data *ldata = tty->disc_data; + ssize_t n = 0; + + if (!ldata->icanon) + n = read_cnt(ldata); + else + n = ldata->canon_head - ldata->read_tail; + return n; } /** @@ -286,28 +295,19 @@ static void n_tty_flush_buffer(struct tty_struct *tty) * Report the number of characters buffered to be delivered to user * at this instant in time. * - * Locking: read_lock + * Locking: exclusive termios_rwsem */ -static ssize_t chars_in_buffer(struct tty_struct *tty) -{ - struct n_tty_data *ldata = tty->disc_data; - unsigned long flags; - ssize_t n = 0; - - raw_spin_lock_irqsave(&ldata->read_lock, flags); - if (!ldata->icanon) - n = read_cnt(ldata); - else - n = ldata->canon_head - ldata->read_tail; - raw_spin_unlock_irqrestore(&ldata->read_lock, flags); - return n; -} - static ssize_t n_tty_chars_in_buffer(struct tty_struct *tty) { + ssize_t n; + WARN_ONCE(1, "%s is deprecated and scheduled for removal.", __func__); - return chars_in_buffer(tty); + + down_write(&tty->termios_rwsem); + n = chars_in_buffer(tty); + up_write(&tty->termios_rwsem); + return n; } /** @@ -915,7 +915,12 @@ static inline void finish_erasing(struct n_tty_data *ldata) * present in the stream from the driver layer. Handles the complexities * of UTF-8 multibyte symbols. * - * Locking: read_lock for tty buffers + * n_tty_receive_buf()/producer path: + * caller holds non-exclusive termios_rwsem + * modifies read_head + * + * Modifying the read_head is not considered a publish in this context + * because canonical mode is active -- only canon_head publishes */ static void eraser(unsigned char c, struct tty_struct *tty) @@ -925,9 +930,7 @@ static void eraser(unsigned char c, struct tty_struct *tty) size_t head; size_t cnt; int seen_alnums; - unsigned long flags; - /* FIXME: locking needed ? */ if (ldata->read_head == ldata->canon_head) { /* process_output('\a', tty); */ /* what do you think? */ return; @@ -938,15 +941,11 @@ static void eraser(unsigned char c, struct tty_struct *tty) kill_type = WERASE; else { if (!L_ECHO(tty)) { - raw_spin_lock_irqsave(&ldata->read_lock, flags); ldata->read_head = ldata->canon_head; - raw_spin_unlock_irqrestore(&ldata->read_lock, flags); return; } if (!L_ECHOK(tty) || !L_ECHOKE(tty) || !L_ECHOE(tty)) { - raw_spin_lock_irqsave(&ldata->read_lock, flags); ldata->read_head = ldata->canon_head; - raw_spin_unlock_irqrestore(&ldata->read_lock, flags); finish_erasing(ldata); echo_char(KILL_CHAR(tty), tty); /* Add a newline if ECHOK is on and ECHOKE is off. */ @@ -958,7 +957,6 @@ static void eraser(unsigned char c, struct tty_struct *tty) } seen_alnums = 0; - /* FIXME: Locking ?? */ while (ldata->read_head != ldata->canon_head) { head = ldata->read_head; @@ -980,9 +978,7 @@ static void eraser(unsigned char c, struct tty_struct *tty) break; } cnt = ldata->read_head - head; - raw_spin_lock_irqsave(&ldata->read_lock, flags); ldata->read_head = head; - raw_spin_unlock_irqrestore(&ldata->read_lock, flags); if (L_ECHO(tty)) { if (L_ECHOPRT(tty)) { if (!ldata->erasing) { @@ -1071,7 +1067,11 @@ static inline void isig(int sig, struct tty_struct *tty) * An RS232 break event has been hit in the incoming bitstream. This * can cause a variety of events depending upon the termios settings. * - * Called from the receive_buf path so single threaded. + * n_tty_receive_buf()/producer path: + * caller holds non-exclusive termios_rwsem + * publishes read_head via put_tty_queue() + * + * Note: may get exclusive termios_rwsem if flushing input buffer */ static inline void n_tty_receive_break(struct tty_struct *tty) @@ -1083,8 +1083,11 @@ static inline void n_tty_receive_break(struct tty_struct *tty) if (I_BRKINT(tty)) { isig(SIGINT, tty); if (!L_NOFLSH(tty)) { + /* flushing needs exclusive termios_rwsem */ + up_read(&tty->termios_rwsem); n_tty_flush_buffer(tty); tty_driver_flush_buffer(tty); + down_read(&tty->termios_rwsem); } return; } @@ -1131,7 +1134,11 @@ static inline void n_tty_receive_overrun(struct tty_struct *tty) * @c: character * * Process a parity error and queue the right data to indicate - * the error case if necessary. Locking as per n_tty_receive_buf. + * the error case if necessary. + * + * n_tty_receive_buf()/producer path: + * caller holds non-exclusive termios_rwsem + * publishes read_head via put_tty_queue() */ static inline void n_tty_receive_parity_error(struct tty_struct *tty, unsigned char c) @@ -1159,12 +1166,16 @@ static inline void n_tty_receive_parity_error(struct tty_struct *tty, * Process an individual character of input received from the driver. * This is serialized with respect to itself by the rules for the * driver above. + * + * n_tty_receive_buf()/producer path: + * caller holds non-exclusive termios_rwsem + * publishes canon_head if canonical mode is active + * otherwise, publishes read_head via put_tty_queue() */ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) { struct n_tty_data *ldata = tty->disc_data; - unsigned long flags; int parmrk; if (ldata->raw) { @@ -1253,8 +1264,11 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) if (c == SUSP_CHAR(tty)) { send_signal: if (!L_NOFLSH(tty)) { + /* flushing needs exclusive termios_rwsem */ + up_read(&tty->termios_rwsem); n_tty_flush_buffer(tty); tty_driver_flush_buffer(tty); + down_read(&tty->termios_rwsem); } if (I_IXON(tty)) start_tty(tty); @@ -1355,11 +1369,9 @@ send_signal: put_tty_queue(c, ldata); handle_newline: - raw_spin_lock_irqsave(&ldata->read_lock, flags); set_bit(ldata->read_head & (N_TTY_BUF_SIZE - 1), ldata->read_flags); - put_tty_queue_nolock(c, ldata); + put_tty_queue(c, ldata); ldata->canon_head = ldata->read_head; - raw_spin_unlock_irqrestore(&ldata->read_lock, flags); kill_fasync(&tty->fasync, SIGIO, POLL_IN); if (waitqueue_active(&tty->read_wait)) wake_up_interruptible(&tty->read_wait); @@ -1420,6 +1432,10 @@ static void n_tty_write_wakeup(struct tty_struct *tty) * been received. This function must be called from soft contexts * not from interrupt context. The driver is responsible for making * calls one at a time and in order (or using flush_to_ldisc) + * + * n_tty_receive_buf()/producer path: + * claims non-exclusive termios_rwsem + * publishes read_head and canon_head */ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, @@ -1430,10 +1446,8 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, char *f, flags = TTY_NORMAL; int i; char buf[64]; - unsigned long cpuflags; if (ldata->real_raw) { - raw_spin_lock_irqsave(&ldata->read_lock, cpuflags); i = min(N_TTY_BUF_SIZE - read_cnt(ldata), N_TTY_BUF_SIZE - (ldata->read_head & (N_TTY_BUF_SIZE - 1))); i = min(count, i); @@ -1447,7 +1461,6 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, i = min(count, i); memcpy(read_buf_addr(ldata, ldata->read_head), cp, i); ldata->read_head += i; - raw_spin_unlock_irqrestore(&ldata->read_lock, cpuflags); } else { for (i = count, p = cp, f = fp; i; i--, p++) { if (f) @@ -1677,7 +1690,6 @@ static int n_tty_open(struct tty_struct *tty) mutex_init(&ldata->atomic_read_lock); mutex_init(&ldata->output_lock); mutex_init(&ldata->echo_lock); - raw_spin_lock_init(&ldata->read_lock); /* These are ugly. Currently a malloc failure here can panic */ ldata->read_buf = kzalloc(N_TTY_BUF_SIZE, GFP_KERNEL); @@ -1733,6 +1745,9 @@ static inline int input_available_p(struct tty_struct *tty, int amt) * * Called under the ldata->atomic_read_lock sem * + * n_tty_read()/consumer path: + * caller holds non-exclusive termios_rwsem + * read_tail published */ static int copy_from_read_buf(struct tty_struct *tty, @@ -1743,27 +1758,22 @@ static int copy_from_read_buf(struct tty_struct *tty, struct n_tty_data *ldata = tty->disc_data; int retval; size_t n; - unsigned long flags; bool is_eof; size_t tail = ldata->read_tail & (N_TTY_BUF_SIZE - 1); retval = 0; - raw_spin_lock_irqsave(&ldata->read_lock, flags); n = min(read_cnt(ldata), N_TTY_BUF_SIZE - tail); n = min(*nr, n); - raw_spin_unlock_irqrestore(&ldata->read_lock, flags); if (n) { retval = copy_to_user(*b, read_buf_addr(ldata, tail), n); n -= retval; is_eof = n == 1 && read_buf(ldata, tail) == EOF_CHAR(tty); tty_audit_add_data(tty, read_buf_addr(ldata, tail), n, ldata->icanon); - raw_spin_lock_irqsave(&ldata->read_lock, flags); ldata->read_tail += n; /* Turn single EOF into zero-length read */ if (L_EXTPROC(tty) && ldata->icanon && is_eof && !read_cnt(ldata)) n = 0; - raw_spin_unlock_irqrestore(&ldata->read_lock, flags); *b += n; *nr -= n; } @@ -1781,6 +1791,10 @@ static int copy_from_read_buf(struct tty_struct *tty, * character into the user-space buffer. * * Called under the atomic_read_lock mutex + * + * n_tty_read()/consumer path: + * caller holds non-exclusive termios_rwsem + * read_tail published */ static int canon_copy_from_read_buf(struct tty_struct *tty, @@ -1788,21 +1802,15 @@ static int canon_copy_from_read_buf(struct tty_struct *tty, size_t *nr) { struct n_tty_data *ldata = tty->disc_data; - unsigned long flags; size_t n, size, more, c; size_t eol; size_t tail; int ret, found = 0; /* N.B. avoid overrun if nr == 0 */ - - raw_spin_lock_irqsave(&ldata->read_lock, flags); - n = min(*nr, read_cnt(ldata)); - if (!n) { - raw_spin_unlock_irqrestore(&ldata->read_lock, flags); + if (!n) return 0; - } tail = ldata->read_tail & (N_TTY_BUF_SIZE - 1); size = min_t(size_t, tail + n, N_TTY_BUF_SIZE); @@ -1830,8 +1838,6 @@ static int canon_copy_from_read_buf(struct tty_struct *tty, n_tty_trace("%s: eol:%zu found:%d n:%zu c:%zu size:%zu more:%zu\n", __func__, eol, found, n, c, size, more); - raw_spin_unlock_irqrestore(&ldata->read_lock, flags); - if (n > size) { ret = copy_to_user(*b, read_buf_addr(ldata, tail), size); if (ret) @@ -1845,11 +1851,10 @@ static int canon_copy_from_read_buf(struct tty_struct *tty, *b += n; *nr -= n; - raw_spin_lock_irqsave(&ldata->read_lock, flags); - ldata->read_tail += c; if (found) - __clear_bit(eol, ldata->read_flags); - raw_spin_unlock_irqrestore(&ldata->read_lock, flags); + clear_bit(eol, ldata->read_flags); + smp_mb__after_clear_bit(); + ldata->read_tail += c; if (found) tty_audit_push(tty); @@ -1913,6 +1918,10 @@ static int job_control(struct tty_struct *tty, struct file *file) * a hangup. Always called in user context, may sleep. * * This code must be sure never to sleep through a hangup. + * + * n_tty_read()/consumer path: + * claims non-exclusive termios_rwsem + * publishes read_tail */ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, @@ -2279,10 +2288,12 @@ static int n_tty_ioctl(struct tty_struct *tty, struct file *file, case TIOCOUTQ: return put_user(tty_chars_in_buffer(tty), (int __user *) arg); case TIOCINQ: - /* FIXME: Locking */ - retval = read_cnt(ldata); + down_write(&tty->termios_rwsem); if (L_ICANON(tty)) retval = inq_canon(ldata); + else + retval = read_cnt(ldata); + up_write(&tty->termios_rwsem); return put_user(retval, (unsigned int __user *) arg); default: return n_tty_ioctl_helper(tty, file, cmd, arg); From 6f9b028a8fb9ba4cef0bd04ad4ce149c3f1e838f Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:14:27 -0400 Subject: [PATCH 0496/3400] n_tty: Reset lnext if canonical mode changes lnext escapes the next input character as a literal, and must be reset when canonical mode changes (to avoid misinterpreting a special character as a literal if canonical mode is changed back again). lnext is specifically not reset on a buffer flush so as to avoid misinterpreting the next input character as a special character. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index c7f71cb8ee1f..e63beab3d1c3 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1574,6 +1574,7 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old) bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE); ldata->canon_head = ldata->read_tail; ldata->erasing = 0; + ldata->lnext = 0; } if (canon_change && !L_ICANON(tty) && read_cnt(ldata)) From d1913e3916f35eb043e8d770839dd96c1379007d Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:14:28 -0400 Subject: [PATCH 0497/3400] n_tty: Fix type mismatches in receive_buf raw copy Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index e63beab3d1c3..fe1c39992c51 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1444,24 +1444,27 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, struct n_tty_data *ldata = tty->disc_data; const unsigned char *p; char *f, flags = TTY_NORMAL; - int i; char buf[64]; if (ldata->real_raw) { - i = min(N_TTY_BUF_SIZE - read_cnt(ldata), - N_TTY_BUF_SIZE - (ldata->read_head & (N_TTY_BUF_SIZE - 1))); - i = min(count, i); - memcpy(read_buf_addr(ldata, ldata->read_head), cp, i); - ldata->read_head += i; - cp += i; - count -= i; + size_t n, head; - i = min(N_TTY_BUF_SIZE - read_cnt(ldata), - N_TTY_BUF_SIZE - (ldata->read_head & (N_TTY_BUF_SIZE - 1))); - i = min(count, i); - memcpy(read_buf_addr(ldata, ldata->read_head), cp, i); - ldata->read_head += i; + head = ldata->read_head & (N_TTY_BUF_SIZE - 1); + n = N_TTY_BUF_SIZE - max(read_cnt(ldata), head); + n = min_t(size_t, count, n); + memcpy(read_buf_addr(ldata, head), cp, n); + ldata->read_head += n; + cp += n; + count -= n; + + head = ldata->read_head & (N_TTY_BUF_SIZE - 1); + n = N_TTY_BUF_SIZE - max(read_cnt(ldata), head); + n = min_t(size_t, count, n); + memcpy(read_buf_addr(ldata, head), cp, n); + ldata->read_head += n; } else { + int i; + for (i = count, p = cp, f = fp; i; i--, p++) { if (f) flags = *f++; From f95499c3030fe1bfad57745f2db1959c5b43dca8 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:14:29 -0400 Subject: [PATCH 0498/3400] n_tty: Don't wait for buffer work in read() loop User-space read() can run concurrently with receiving from device; waiting for receive_buf() to complete is not required. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index fe1c39992c51..a6eea30d0911 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1724,7 +1724,6 @@ static inline int input_available_p(struct tty_struct *tty, int amt) { struct n_tty_data *ldata = tty->disc_data; - tty_flush_to_ldisc(tty); if (ldata->icanon && !L_EXTPROC(tty)) { if (ldata->canon_head != ldata->read_tail) return 1; From fb7aa03db605e4f0b9a62cd4c77177c2596edd95 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:14:30 -0400 Subject: [PATCH 0499/3400] n_tty: Separate buffer indices to prevent cache-line sharing If the read buffer indices are in the same cache-line, cpus will contended over the cache-line (so called 'false sharing'). Separate the producer-published fields from the consumer-published fields; document the locks relevant to each field. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index a6eea30d0911..d0c8805d8131 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -82,29 +82,38 @@ #endif struct n_tty_data { - unsigned int column; + /* producer-published */ + size_t read_head; + size_t canon_head; + DECLARE_BITMAP(process_char_map, 256); + + /* private to n_tty_receive_overrun (single-threaded) */ unsigned long overrun_time; int num_overrun; /* non-atomic */ bool no_room; + /* must hold exclusive termios_rwsem to reset these */ unsigned char lnext:1, erasing:1, raw:1, real_raw:1, icanon:1; unsigned char echo_overrun:1; - DECLARE_BITMAP(process_char_map, 256); + /* shared by producer and consumer */ + char *read_buf; DECLARE_BITMAP(read_flags, N_TTY_BUF_SIZE); - char *read_buf; - size_t read_head; - size_t read_tail; int minimum_to_wake; + /* consumer-published */ + size_t read_tail; + + /* protected by echo_lock */ unsigned char *echo_buf; unsigned int echo_pos; unsigned int echo_cnt; - size_t canon_head; + /* protected by output lock */ + unsigned int column; unsigned int canon_column; struct mutex atomic_read_lock; From d8c1f929aa8164cd8eaa830068d2fa3159c0764a Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:14:31 -0400 Subject: [PATCH 0500/3400] tty: Only guarantee termios read safety for throttle/unthrottle No tty driver modifies termios during throttle() or unthrottle(). Therefore, only read safety is required. However, tty_throttle_safe and tty_unthrottle_safe must still be mutually exclusive; introduce throttle_mutex for that purpose. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 4 ---- drivers/tty/tty_io.c | 1 + drivers/tty/tty_ioctl.c | 8 ++++---- include/linux/tty.h | 1 + 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index d0c8805d8131..b78ee464bd09 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1518,9 +1518,7 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, tty_set_flow_change(tty, TTY_THROTTLE_SAFE); if (receive_room(tty) >= TTY_THRESHOLD_THROTTLE) break; - up_read(&tty->termios_rwsem); throttled = tty_throttle_safe(tty); - down_read(&tty->termios_rwsem); if (!throttled) break; } @@ -2086,9 +2084,7 @@ do_it_again: if (!tty->count) break; n_tty_set_room(tty); - up_read(&tty->termios_rwsem); unthrottled = tty_unthrottle_safe(tty); - down_read(&tty->termios_rwsem); if (!unthrottled) break; } diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 639e24ade9bf..1b32da6f6cdd 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -3015,6 +3015,7 @@ void initialize_tty_struct(struct tty_struct *tty, tty->session = NULL; tty->pgrp = NULL; mutex_init(&tty->legacy_mutex); + mutex_init(&tty->throttle_mutex); init_rwsem(&tty->termios_rwsem); init_ldsem(&tty->ldisc_sem); init_waitqueue_head(&tty->write_wait); diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c index 9ce20df8a2c8..03ba081c5772 100644 --- a/drivers/tty/tty_ioctl.c +++ b/drivers/tty/tty_ioctl.c @@ -151,7 +151,7 @@ int tty_throttle_safe(struct tty_struct *tty) { int ret = 0; - down_write(&tty->termios_rwsem); + mutex_lock(&tty->throttle_mutex); if (!test_bit(TTY_THROTTLED, &tty->flags)) { if (tty->flow_change != TTY_THROTTLE_SAFE) ret = 1; @@ -161,7 +161,7 @@ int tty_throttle_safe(struct tty_struct *tty) tty->ops->throttle(tty); } } - up_write(&tty->termios_rwsem); + mutex_unlock(&tty->throttle_mutex); return ret; } @@ -182,7 +182,7 @@ int tty_unthrottle_safe(struct tty_struct *tty) { int ret = 0; - down_write(&tty->termios_rwsem); + mutex_lock(&tty->throttle_mutex); if (test_bit(TTY_THROTTLED, &tty->flags)) { if (tty->flow_change != TTY_UNTHROTTLE_SAFE) ret = 1; @@ -192,7 +192,7 @@ int tty_unthrottle_safe(struct tty_struct *tty) tty->ops->unthrottle(tty); } } - up_write(&tty->termios_rwsem); + mutex_unlock(&tty->throttle_mutex); return ret; } diff --git a/include/linux/tty.h b/include/linux/tty.h index d3042076d163..57a70d1d0412 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -244,6 +244,7 @@ struct tty_struct { struct mutex atomic_write_lock; struct mutex legacy_mutex; + struct mutex throttle_mutex; struct rw_semaphore termios_rwsem; spinlock_t ctrl_lock; /* Termios values are protected by the termios rwsem */ From 9a4aec2dd5b54606b3508e0e064750f516009650 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:14:32 -0400 Subject: [PATCH 0501/3400] n_tty: Move chars_in_buffer() to factor throttle/unthrottle Prepare to factor throttle and unthrottle into helper functions; relocate chars_in_buffer() to avoid forward declaration. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index b78ee464bd09..9ec0c68aa739 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -202,6 +202,18 @@ static void n_tty_set_room(struct tty_struct *tty) } } +static ssize_t chars_in_buffer(struct tty_struct *tty) +{ + struct n_tty_data *ldata = tty->disc_data; + ssize_t n = 0; + + if (!ldata->icanon) + n = read_cnt(ldata); + else + n = ldata->canon_head - ldata->read_tail; + return n; +} + /** * put_tty_queue - add character to tty * @c: character @@ -285,18 +297,6 @@ static void n_tty_flush_buffer(struct tty_struct *tty) up_write(&tty->termios_rwsem); } -static ssize_t chars_in_buffer(struct tty_struct *tty) -{ - struct n_tty_data *ldata = tty->disc_data; - ssize_t n = 0; - - if (!ldata->icanon) - n = read_cnt(ldata); - else - n = ldata->canon_head - ldata->read_tail; - return n; -} - /** * n_tty_chars_in_buffer - report available bytes * @tty: tty device From 6367ca72f1fad60de7ef607e10a999ed86ca6a8b Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:14:33 -0400 Subject: [PATCH 0502/3400] n_tty: Factor throttle/unthrottle into helper functions Prepare for special handling of pty throttle/unthrottle; factor flow control into helper functions. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 81 +++++++++++++++++++++++++-------------------- 1 file changed, 46 insertions(+), 35 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 9ec0c68aa739..9e13c804ae72 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -214,6 +214,50 @@ static ssize_t chars_in_buffer(struct tty_struct *tty) return n; } +static inline void n_tty_check_throttle(struct tty_struct *tty) +{ + /* + * Check the remaining room for the input canonicalization + * mode. We don't want to throttle the driver if we're in + * canonical mode and don't have a newline yet! + */ + while (1) { + int throttled; + tty_set_flow_change(tty, TTY_THROTTLE_SAFE); + if (receive_room(tty) >= TTY_THRESHOLD_THROTTLE) + break; + throttled = tty_throttle_safe(tty); + if (!throttled) + break; + } + __tty_set_flow_change(tty, 0); +} + +static inline void n_tty_check_unthrottle(struct tty_struct *tty) +{ + /* If there is enough space in the read buffer now, let the + * low-level driver know. We use chars_in_buffer() to + * check the buffer, as it now knows about canonical mode. + * Otherwise, if the driver is throttled and the line is + * longer than TTY_THRESHOLD_UNTHROTTLE in canonical mode, + * we won't get any more characters. + */ + + while (1) { + int unthrottled; + tty_set_flow_change(tty, TTY_UNTHROTTLE_SAFE); + if (chars_in_buffer(tty) > TTY_THRESHOLD_UNTHROTTLE) + break; + if (!tty->count) + break; + n_tty_set_room(tty); + unthrottled = tty_unthrottle_safe(tty); + if (!unthrottled) + break; + } + __tty_set_flow_change(tty, 0); +} + /** * put_tty_queue - add character to tty * @c: character @@ -1508,21 +1552,7 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, wake_up_interruptible(&tty->read_wait); } - /* - * Check the remaining room for the input canonicalization - * mode. We don't want to throttle the driver if we're in - * canonical mode and don't have a newline yet! - */ - while (1) { - int throttled; - tty_set_flow_change(tty, TTY_THROTTLE_SAFE); - if (receive_room(tty) >= TTY_THRESHOLD_THROTTLE) - break; - throttled = tty_throttle_safe(tty); - if (!throttled) - break; - } - __tty_set_flow_change(tty, 0); + n_tty_check_throttle(tty); } static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, @@ -2069,26 +2099,7 @@ do_it_again: } } - /* If there is enough space in the read buffer now, let the - * low-level driver know. We use chars_in_buffer() to - * check the buffer, as it now knows about canonical mode. - * Otherwise, if the driver is throttled and the line is - * longer than TTY_THRESHOLD_UNTHROTTLE in canonical mode, - * we won't get any more characters. - */ - while (1) { - int unthrottled; - tty_set_flow_change(tty, TTY_UNTHROTTLE_SAFE); - if (chars_in_buffer(tty) > TTY_THRESHOLD_UNTHROTTLE) - break; - if (!tty->count) - break; - n_tty_set_room(tty); - unthrottled = tty_unthrottle_safe(tty); - if (!unthrottled) - break; - } - __tty_set_flow_change(tty, 0); + n_tty_check_unthrottle(tty); if (b - buf >= minimum) break; From ee0bab83ce65b6f6910cfc0c8278351a0583531b Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:14:34 -0400 Subject: [PATCH 0503/3400] n_tty: Move n_tty_write_wakeup() to avoid forward declaration Prepare to special case pty flow control; avoid forward declaration. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 9e13c804ae72..0e3efc1ed2d5 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -214,6 +214,21 @@ static ssize_t chars_in_buffer(struct tty_struct *tty) return n; } +/** + * n_tty_write_wakeup - asynchronous I/O notifier + * @tty: tty device + * + * Required for the ptys, serial driver etc. since processes + * that attach themselves to the master and rely on ASYNC + * IO must be woken up + */ + +static void n_tty_write_wakeup(struct tty_struct *tty) +{ + if (tty->fasync && test_and_clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) + kill_fasync(&tty->fasync, SIGIO, POLL_OUT); +} + static inline void n_tty_check_throttle(struct tty_struct *tty) { /* @@ -1458,22 +1473,6 @@ handle_newline: put_tty_queue(c, ldata); } - -/** - * n_tty_write_wakeup - asynchronous I/O notifier - * @tty: tty device - * - * Required for the ptys, serial driver etc. since processes - * that attach themselves to the master and rely on ASYNC - * IO must be woken up - */ - -static void n_tty_write_wakeup(struct tty_struct *tty) -{ - if (tty->fasync && test_and_clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) - kill_fasync(&tty->fasync, SIGIO, POLL_OUT); -} - /** * n_tty_receive_buf - data receive * @tty: terminal device From 3afb1b394a49d1237c9c0af8e8b724ddfe5b94ba Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Tue, 23 Jul 2013 08:47:30 -0400 Subject: [PATCH 0504/3400] n_tty: Special case pty flow control The pty driver forces ldisc flow control on, regardless of available receive buffer space, so the writer can be woken whenever unthrottle is called. However, this 'forced throttle' has performance consequences, as multiple atomic operations are necessary to unthrottle and perform the write wakeup for every input line (in canonical mode). Instead, short-circuit the unthrottle if the tty is a pty and perform the write wakeup directly. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 0e3efc1ed2d5..59eb444fe17c 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -231,6 +231,8 @@ static void n_tty_write_wakeup(struct tty_struct *tty) static inline void n_tty_check_throttle(struct tty_struct *tty) { + if (tty->driver->type == TTY_DRIVER_TYPE_PTY) + return; /* * Check the remaining room for the input canonicalization * mode. We don't want to throttle the driver if we're in @@ -250,6 +252,18 @@ static inline void n_tty_check_throttle(struct tty_struct *tty) static inline void n_tty_check_unthrottle(struct tty_struct *tty) { + if (tty->driver->type == TTY_DRIVER_TYPE_PTY && + tty->link->ldisc->ops->write_wakeup == n_tty_write_wakeup) { + if (chars_in_buffer(tty) > TTY_THRESHOLD_UNTHROTTLE) + return; + if (!tty->count) + return; + n_tty_set_room(tty); + n_tty_write_wakeup(tty->link); + wake_up_interruptible_poll(&tty->link->write_wait, POLLOUT); + return; + } + /* If there is enough space in the read buffer now, let the * low-level driver know. We use chars_in_buffer() to * check the buffer, as it now knows about canonical mode. From f0f947c124e05ec977019b974b12dfe171dd7148 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:14:36 -0400 Subject: [PATCH 0505/3400] n_tty: Queue buffer work on any available cpu Scheduling buffer work on the same cpu as the read() thread limits the parallelism now possible between the receive_buf path and the n_tty_read() path. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 59eb444fe17c..a69470e02bf4 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -198,7 +198,7 @@ static void n_tty_set_room(struct tty_struct *tty) */ WARN_RATELIMIT(test_bit(TTY_LDISC_HALTED, &tty->flags), "scheduling buffer work for halted ldisc\n"); - schedule_work(&tty->port->buf.work); + queue_work(system_unbound_wq, &tty->port->buf.work); } } From 1fc359fc3ea72314cc3ebdfa94c60e020c152cd2 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:36:01 -0400 Subject: [PATCH 0506/3400] tty: Compute flip buffer ptrs The char_buf_ptr and flag_buf_ptr values are trivially derived from the .data field offset; compute values as needed. Fixes a long-standing type-mismatch with the char and flag ptrs. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_buffer.c | 22 ++++++++++------------ include/linux/tty.h | 12 ++++++++++-- include/linux/tty_flip.h | 4 ++-- 3 files changed, 22 insertions(+), 16 deletions(-) diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index ff1b2e37c3ca..170674cb68fc 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -71,8 +71,6 @@ static struct tty_buffer *tty_buffer_alloc(struct tty_port *port, size_t size) p->next = NULL; p->commit = 0; p->read = 0; - p->char_buf_ptr = (char *)(p->data); - p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size; port->buf.memory_used += size; return p; } @@ -265,8 +263,8 @@ int tty_insert_flip_string_fixed_flag(struct tty_port *port, if (unlikely(space == 0)) { break; } - memcpy(tb->char_buf_ptr + tb->used, chars, space); - memset(tb->flag_buf_ptr + tb->used, flag, space); + memcpy(char_buf_ptr(tb, tb->used), chars, space); + memset(flag_buf_ptr(tb, tb->used), flag, space); tb->used += space; copied += space; chars += space; @@ -303,8 +301,8 @@ int tty_insert_flip_string_flags(struct tty_port *port, if (unlikely(space == 0)) { break; } - memcpy(tb->char_buf_ptr + tb->used, chars, space); - memcpy(tb->flag_buf_ptr + tb->used, flags, space); + memcpy(char_buf_ptr(tb, tb->used), chars, space); + memcpy(flag_buf_ptr(tb, tb->used), flags, space); tb->used += space; copied += space; chars += space; @@ -364,8 +362,8 @@ int tty_prepare_flip_string(struct tty_port *port, unsigned char **chars, int space = tty_buffer_request_room(port, size); if (likely(space)) { struct tty_buffer *tb = port->buf.tail; - *chars = tb->char_buf_ptr + tb->used; - memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space); + *chars = char_buf_ptr(tb, tb->used); + memset(flag_buf_ptr(tb, tb->used), TTY_NORMAL, space); tb->used += space; } return space; @@ -394,8 +392,8 @@ int tty_prepare_flip_string_flags(struct tty_port *port, int space = tty_buffer_request_room(port, size); if (likely(space)) { struct tty_buffer *tb = port->buf.tail; - *chars = tb->char_buf_ptr + tb->used; - *flags = tb->flag_buf_ptr + tb->used; + *chars = char_buf_ptr(tb, tb->used); + *flags = flag_buf_ptr(tb, tb->used); tb->used += space; } return space; @@ -407,8 +405,8 @@ static int receive_buf(struct tty_struct *tty, struct tty_buffer *head, int count) { struct tty_ldisc *disc = tty->ldisc; - char *p = head->char_buf_ptr + head->read; - unsigned char *f = head->flag_buf_ptr + head->read; + unsigned char *p = char_buf_ptr(head, head->read); + char *f = flag_buf_ptr(head, head->read); if (disc->ops->receive_buf2) count = disc->ops->receive_buf2(tty, p, f, count); diff --git a/include/linux/tty.h b/include/linux/tty.h index 57a70d1d0412..87bbaa31ebf5 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -31,8 +31,6 @@ struct tty_buffer { struct tty_buffer *next; - char *char_buf_ptr; - unsigned char *flag_buf_ptr; int used; int size; int commit; @@ -41,6 +39,16 @@ struct tty_buffer { unsigned long data[0]; }; +static inline unsigned char *char_buf_ptr(struct tty_buffer *b, int ofs) +{ + return ((unsigned char *)b->data) + ofs; +} + +static inline char *flag_buf_ptr(struct tty_buffer *b, int ofs) +{ + return (char *)char_buf_ptr(b, ofs) + b->size; +} + /* * We default to dicing tty buffer allocations to this many characters * in order to avoid multiple page allocations. We know the size of diff --git a/include/linux/tty_flip.h b/include/linux/tty_flip.h index e0f252633b47..ad0303994c32 100644 --- a/include/linux/tty_flip.h +++ b/include/linux/tty_flip.h @@ -18,8 +18,8 @@ static inline int tty_insert_flip_char(struct tty_port *port, { struct tty_buffer *tb = port->buf.tail; if (tb && tb->used < tb->size) { - tb->flag_buf_ptr[tb->used] = flag; - tb->char_buf_ptr[tb->used++] = ch; + *flag_buf_ptr(tb, tb->used) = flag; + *char_buf_ptr(tb, tb->used++) = ch; return 1; } return tty_insert_flip_string_flags(port, &ch, &flag, 1); From 1cef50e317c3395c6e8451f2b82a155db6ef2b42 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:36:02 -0400 Subject: [PATCH 0507/3400] tty: Fix flip buffer free list Since flip buffers are size-aligned to 256 bytes and all flip buffers 512-bytes or larger are not added to the free list, the free list only contains 256-byte flip buffers. Remove the list search when allocating a new flip buffer. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_buffer.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index 170674cb68fc..a5e396217f76 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -18,6 +18,10 @@ #include #include + +#define MIN_TTYB_SIZE 256 +#define TTYB_ALIGN_MASK 255 + /** * tty_buffer_free_all - free buffers used by a tty * @tty: tty to free from @@ -94,7 +98,7 @@ static void tty_buffer_free(struct tty_port *port, struct tty_buffer *b) buf->memory_used -= b->size; WARN_ON(buf->memory_used < 0); - if (b->size >= 512) + if (b->size > MIN_TTYB_SIZE) kfree(b); else { b->next = buf->free; @@ -176,9 +180,10 @@ void tty_buffer_flush(struct tty_struct *tty) static struct tty_buffer *tty_buffer_find(struct tty_port *port, size_t size) { struct tty_buffer **tbh = &port->buf.free; - while ((*tbh) != NULL) { - struct tty_buffer *t = *tbh; - if (t->size >= size) { + if (size <= MIN_TTYB_SIZE) { + if (*tbh) { + struct tty_buffer *t = *tbh; + *tbh = t->next; t->next = NULL; t->used = 0; @@ -187,10 +192,9 @@ static struct tty_buffer *tty_buffer_find(struct tty_port *port, size_t size) port->buf.memory_used += t->size; return t; } - tbh = &((*tbh)->next); } /* Round the buffer size out */ - size = (size + 0xFF) & ~0xFF; + size = __ALIGN_MASK(size, TTYB_ALIGN_MASK); return tty_buffer_alloc(port, size); /* Should possibly check if this fails for the largest buffer we have queued and recycle that ? */ From 9dd5139f973f55ab4b2e9aff8171781f1e55b29d Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:36:03 -0400 Subject: [PATCH 0508/3400] tty: Factor flip buffer initialization into helper function Factor shared code; prepare for adding 0-sized sentinel flip buffer. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_buffer.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index a5e396217f76..56d460295c87 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -22,6 +22,15 @@ #define MIN_TTYB_SIZE 256 #define TTYB_ALIGN_MASK 255 +static void tty_buffer_reset(struct tty_buffer *p, size_t size) +{ + p->used = 0; + p->size = size; + p->next = NULL; + p->commit = 0; + p->read = 0; +} + /** * tty_buffer_free_all - free buffers used by a tty * @tty: tty to free from @@ -70,11 +79,8 @@ static struct tty_buffer *tty_buffer_alloc(struct tty_port *port, size_t size) p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC); if (p == NULL) return NULL; - p->used = 0; - p->size = size; - p->next = NULL; - p->commit = 0; - p->read = 0; + + tty_buffer_reset(p, size); port->buf.memory_used += size; return p; } @@ -185,10 +191,7 @@ static struct tty_buffer *tty_buffer_find(struct tty_port *port, size_t size) struct tty_buffer *t = *tbh; *tbh = t->next; - t->next = NULL; - t->used = 0; - t->commit = 0; - t->read = 0; + tty_buffer_reset(t, t->size); port->buf.memory_used += t->size; return t; } From 11b9faa44df76189b8346ff602a2c01c610c37eb Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:36:04 -0400 Subject: [PATCH 0509/3400] tty: Merge tty_buffer_find() into tty_buffer_alloc() tty_buffer_find() implements a simple free list lookaside cache. Merge this functionality into tty_buffer_alloc() to reflect the more traditional alloc/free symmetry. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_buffer.c | 50 +++++++++++++++------------------------- 1 file changed, 18 insertions(+), 32 deletions(-) diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index 56d460295c87..a428fa2f7259 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -64,6 +64,8 @@ void tty_buffer_free_all(struct tty_port *port) * @size: desired size (characters) * * Allocate a new tty buffer to hold the desired number of characters. + * We round our buffers off in 256 character chunks to get better + * allocation behaviour. * Return NULL if out of memory or the allocation would exceed the * per device queue * @@ -72,14 +74,29 @@ void tty_buffer_free_all(struct tty_port *port) static struct tty_buffer *tty_buffer_alloc(struct tty_port *port, size_t size) { + struct tty_buffer **tbh = &port->buf.free; struct tty_buffer *p; + /* Round the buffer size out */ + size = __ALIGN_MASK(size, TTYB_ALIGN_MASK); + + if (size <= MIN_TTYB_SIZE) { + if (*tbh) { + p = *tbh; + *tbh = p->next; + goto found; + } + } + + /* Should possibly check if this fails for the largest buffer we + have queued and recycle that ? */ if (port->buf.memory_used + size > 65536) return NULL; p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC); if (p == NULL) return NULL; +found: tty_buffer_reset(p, size); port->buf.memory_used += size; return p; @@ -171,37 +188,6 @@ void tty_buffer_flush(struct tty_struct *tty) spin_unlock_irqrestore(&buf->lock, flags); } -/** - * tty_buffer_find - find a free tty buffer - * @tty: tty owning the buffer - * @size: characters wanted - * - * Locate an existing suitable tty buffer or if we are lacking one then - * allocate a new one. We round our buffers off in 256 character chunks - * to get better allocation behaviour. - * - * Locking: Caller must hold tty->buf.lock - */ - -static struct tty_buffer *tty_buffer_find(struct tty_port *port, size_t size) -{ - struct tty_buffer **tbh = &port->buf.free; - if (size <= MIN_TTYB_SIZE) { - if (*tbh) { - struct tty_buffer *t = *tbh; - - *tbh = t->next; - tty_buffer_reset(t, t->size); - port->buf.memory_used += t->size; - return t; - } - } - /* Round the buffer size out */ - size = __ALIGN_MASK(size, TTYB_ALIGN_MASK); - return tty_buffer_alloc(port, size); - /* Should possibly check if this fails for the largest buffer we - have queued and recycle that ? */ -} /** * tty_buffer_request_room - grow tty buffer if needed * @tty: tty structure @@ -230,7 +216,7 @@ int tty_buffer_request_room(struct tty_port *port, size_t size) if (left < size) { /* This is the slow path - looking for new buffers to use */ - if ((n = tty_buffer_find(port, size)) != NULL) { + if ((n = tty_buffer_alloc(port, size)) != NULL) { if (b != NULL) { b->next = n; b->commit = b->used; From 2cf7b67e87f0d8db025cff12b5d29c0663bbcd87 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:36:05 -0400 Subject: [PATCH 0510/3400] tty: Use generic names for flip buffer list cursors Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_buffer.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index a428fa2f7259..0259a766b875 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -44,15 +44,15 @@ static void tty_buffer_reset(struct tty_buffer *p, size_t size) void tty_buffer_free_all(struct tty_port *port) { struct tty_bufhead *buf = &port->buf; - struct tty_buffer *thead; + struct tty_buffer *p; - while ((thead = buf->head) != NULL) { - buf->head = thead->next; - kfree(thead); + while ((p = buf->head) != NULL) { + buf->head = p->next; + kfree(p); } - while ((thead = buf->free) != NULL) { - buf->free = thead->next; - kfree(thead); + while ((p = buf->free) != NULL) { + buf->free = p->next; + kfree(p); } buf->tail = NULL; buf->memory_used = 0; @@ -143,13 +143,13 @@ static void tty_buffer_free(struct tty_port *port, struct tty_buffer *b) static void __tty_buffer_flush(struct tty_port *port) { struct tty_bufhead *buf = &port->buf; - struct tty_buffer *thead; + struct tty_buffer *next; if (unlikely(buf->head == NULL)) return; - while ((thead = buf->head->next) != NULL) { + while ((next = buf->head->next) != NULL) { tty_buffer_free(port, buf->head); - buf->head = thead; + buf->head = next; } WARN_ON(buf->head != buf->tail); buf->head->read = buf->head->commit; From 809850b7a5fcc0a96d023e1171a7944c60fd5a71 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:36:06 -0400 Subject: [PATCH 0511/3400] tty: Use lockless flip buffer free list In preparation for lockless flip buffers, make the flip buffer free list lockless. NB: using llist is not the optimal solution, as the driver and buffer work may contend over the llist head unnecessarily. However, test measurements indicate this contention is low. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_buffer.c | 29 ++++++++++++----------------- include/linux/llist.h | 23 +++++++++++++++++++++++ include/linux/tty.h | 8 ++++++-- 3 files changed, 41 insertions(+), 19 deletions(-) diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index 0259a766b875..069640e5b9c0 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -44,16 +44,17 @@ static void tty_buffer_reset(struct tty_buffer *p, size_t size) void tty_buffer_free_all(struct tty_port *port) { struct tty_bufhead *buf = &port->buf; - struct tty_buffer *p; + struct tty_buffer *p, *next; + struct llist_node *llist; while ((p = buf->head) != NULL) { buf->head = p->next; kfree(p); } - while ((p = buf->free) != NULL) { - buf->free = p->next; + llist = llist_del_all(&buf->free); + llist_for_each_entry_safe(p, next, llist, free) kfree(p); - } + buf->tail = NULL; buf->memory_used = 0; } @@ -68,22 +69,20 @@ void tty_buffer_free_all(struct tty_port *port) * allocation behaviour. * Return NULL if out of memory or the allocation would exceed the * per device queue - * - * Locking: Caller must hold tty->buf.lock */ static struct tty_buffer *tty_buffer_alloc(struct tty_port *port, size_t size) { - struct tty_buffer **tbh = &port->buf.free; + struct llist_node *free; struct tty_buffer *p; /* Round the buffer size out */ size = __ALIGN_MASK(size, TTYB_ALIGN_MASK); if (size <= MIN_TTYB_SIZE) { - if (*tbh) { - p = *tbh; - *tbh = p->next; + free = llist_del_first(&port->buf.free); + if (free) { + p = llist_entry(free, struct tty_buffer, free); goto found; } } @@ -109,8 +108,6 @@ found: * * Free a tty buffer, or add it to the free list according to our * internal strategy - * - * Locking: Caller must hold tty->buf.lock */ static void tty_buffer_free(struct tty_port *port, struct tty_buffer *b) @@ -123,10 +120,8 @@ static void tty_buffer_free(struct tty_port *port, struct tty_buffer *b) if (b->size > MIN_TTYB_SIZE) kfree(b); - else { - b->next = buf->free; - buf->free = b; - } + else + llist_add(&b->free, &buf->free); } /** @@ -542,7 +537,7 @@ void tty_buffer_init(struct tty_port *port) spin_lock_init(&buf->lock); buf->head = NULL; buf->tail = NULL; - buf->free = NULL; + init_llist_head(&buf->free); buf->memory_used = 0; INIT_WORK(&buf->work, flush_to_ldisc); } diff --git a/include/linux/llist.h b/include/linux/llist.h index cdaa7f023899..8828a78dec9a 100644 --- a/include/linux/llist.h +++ b/include/linux/llist.h @@ -124,6 +124,29 @@ static inline void init_llist_head(struct llist_head *list) &(pos)->member != NULL; \ (pos) = llist_entry((pos)->member.next, typeof(*(pos)), member)) +/** + * llist_for_each_entry_safe - iterate over some deleted entries of lock-less list of given type + * safe against removal of list entry + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @node: the first entry of deleted list entries. + * @member: the name of the llist_node with the struct. + * + * In general, some entries of the lock-less list can be traversed + * safely only after being removed from list, so start with an entry + * instead of list head. + * + * If being used on entries deleted from lock-less list directly, the + * traverse order is from the newest to the oldest added entry. If + * you want to traverse from the oldest to the newest, you must + * reverse the order by yourself before traversing. + */ +#define llist_for_each_entry_safe(pos, n, node, member) \ + for (pos = llist_entry((node), typeof(*pos), member); \ + &pos->member != NULL && \ + (n = llist_entry(pos->member.next, typeof(*n), member), true); \ + pos = n) + /** * llist_empty - tests whether a lock-less list is empty * @head: the list to test diff --git a/include/linux/tty.h b/include/linux/tty.h index 87bbaa31ebf5..5043b12f23ea 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -11,6 +11,7 @@ #include #include #include +#include @@ -30,7 +31,10 @@ #define __DISABLED_CHAR '\0' struct tty_buffer { - struct tty_buffer *next; + union { + struct tty_buffer *next; + struct llist_node free; + }; int used; int size; int commit; @@ -65,7 +69,7 @@ struct tty_bufhead { spinlock_t lock; struct tty_buffer *head; /* Queue head */ struct tty_buffer *tail; /* Active buffer */ - struct tty_buffer *free; /* Free queue head */ + struct llist_head free; /* Free queue head */ int memory_used; /* Buffer space used excluding free queue */ }; From 7391ee16950e772076d321792d9fbf030f921345 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:36:07 -0400 Subject: [PATCH 0512/3400] tty: Simplify flip buffer list with 0-sized sentinel Use a 0-sized sentinel to avoid assigning the head ptr from the driver side thread. This also eliminates testing head/tail for NULL. When the sentinel is first 'consumed' by the buffer work (or by tty_buffer_flush()), it is detached from the list but not freed nor added to the free list. Both buffer work and tty_buffer_flush() continue to preserve at least 1 flip buffer to which head & tail is pointed. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_buffer.c | 49 +++++++++++++++------------------------- include/linux/tty.h | 1 + 2 files changed, 19 insertions(+), 31 deletions(-) diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index 069640e5b9c0..231b7a8710f1 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -49,13 +49,16 @@ void tty_buffer_free_all(struct tty_port *port) while ((p = buf->head) != NULL) { buf->head = p->next; - kfree(p); + if (p->size > 0) + kfree(p); } llist = llist_del_all(&buf->free); llist_for_each_entry_safe(p, next, llist, free) kfree(p); - buf->tail = NULL; + tty_buffer_reset(&buf->sentinel, 0); + buf->head = &buf->sentinel; + buf->tail = &buf->sentinel; buf->memory_used = 0; } @@ -120,7 +123,7 @@ static void tty_buffer_free(struct tty_port *port, struct tty_buffer *b) if (b->size > MIN_TTYB_SIZE) kfree(b); - else + else if (b->size > 0) llist_add(&b->free, &buf->free); } @@ -140,8 +143,6 @@ static void __tty_buffer_flush(struct tty_port *port) struct tty_bufhead *buf = &port->buf; struct tty_buffer *next; - if (unlikely(buf->head == NULL)) - return; while ((next = buf->head->next) != NULL) { tty_buffer_free(port, buf->head); buf->head = next; @@ -200,23 +201,14 @@ int tty_buffer_request_room(struct tty_port *port, size_t size) int left; unsigned long flags; spin_lock_irqsave(&buf->lock, flags); - /* OPTIMISATION: We could keep a per tty "zero" sized buffer to - remove this conditional if its worth it. This would be invisible - to the callers */ b = buf->tail; - if (b != NULL) - left = b->size - b->used; - else - left = 0; + left = b->size - b->used; if (left < size) { /* This is the slow path - looking for new buffers to use */ if ((n = tty_buffer_alloc(port, size)) != NULL) { - if (b != NULL) { - b->next = n; - b->commit = b->used; - } else - buf->head = n; + b->next = n; + b->commit = b->used; buf->tail = n; } else size = left; @@ -247,10 +239,8 @@ int tty_insert_flip_string_fixed_flag(struct tty_port *port, int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE); int space = tty_buffer_request_room(port, goal); struct tty_buffer *tb = port->buf.tail; - /* If there is no space then tb may be NULL */ - if (unlikely(space == 0)) { + if (unlikely(space == 0)) break; - } memcpy(char_buf_ptr(tb, tb->used), chars, space); memset(flag_buf_ptr(tb, tb->used), flag, space); tb->used += space; @@ -285,10 +275,8 @@ int tty_insert_flip_string_flags(struct tty_port *port, int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE); int space = tty_buffer_request_room(port, goal); struct tty_buffer *tb = port->buf.tail; - /* If there is no space then tb may be NULL */ - if (unlikely(space == 0)) { + if (unlikely(space == 0)) break; - } memcpy(char_buf_ptr(tb, tb->used), chars, space); memcpy(flag_buf_ptr(tb, tb->used), flags, space); tb->used += space; @@ -322,8 +310,7 @@ void tty_schedule_flip(struct tty_port *port) WARN_ON(port->low_latency); spin_lock_irqsave(&buf->lock, flags); - if (buf->tail != NULL) - buf->tail->commit = buf->tail->used; + buf->tail->commit = buf->tail->used; spin_unlock_irqrestore(&buf->lock, flags); schedule_work(&buf->work); } @@ -438,8 +425,8 @@ static void flush_to_ldisc(struct work_struct *work) spin_lock_irqsave(&buf->lock, flags); if (!test_and_set_bit(TTYP_FLUSHING, &port->iflags)) { - struct tty_buffer *head; - while ((head = buf->head) != NULL) { + while (1) { + struct tty_buffer *head = buf->head; int count; count = head->commit - head->read; @@ -509,8 +496,7 @@ void tty_flip_buffer_push(struct tty_port *port) unsigned long flags; spin_lock_irqsave(&buf->lock, flags); - if (buf->tail != NULL) - buf->tail->commit = buf->tail->used; + buf->tail->commit = buf->tail->used; spin_unlock_irqrestore(&buf->lock, flags); if (port->low_latency) @@ -535,8 +521,9 @@ void tty_buffer_init(struct tty_port *port) struct tty_bufhead *buf = &port->buf; spin_lock_init(&buf->lock); - buf->head = NULL; - buf->tail = NULL; + tty_buffer_reset(&buf->sentinel, 0); + buf->head = &buf->sentinel; + buf->tail = &buf->sentinel; init_llist_head(&buf->free); buf->memory_used = 0; INIT_WORK(&buf->work, flush_to_ldisc); diff --git a/include/linux/tty.h b/include/linux/tty.h index 5043b12f23ea..2e93eb831c61 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -67,6 +67,7 @@ static inline char *flag_buf_ptr(struct tty_buffer *b, int ofs) struct tty_bufhead { struct work_struct work; spinlock_t lock; + struct tty_buffer sentinel; struct tty_buffer *head; /* Queue head */ struct tty_buffer *tail; /* Active buffer */ struct llist_head free; /* Free queue head */ From 7bfe0b7116be207cf2204ae06335cc89d8f8ee02 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:36:08 -0400 Subject: [PATCH 0513/3400] tty: Track flip buffer memory limit atomically Lockless flip buffers require atomically updating the bytes-in-use watermark. The pty driver also peeks at the watermark value to limit memory consumption to a much lower value than the default; query the watermark with new fn, tty_buffer_space_avail(). Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/pty.c | 10 +++------- drivers/tty/tty_buffer.c | 37 +++++++++++++++++++++++++++++++------ include/linux/tty.h | 3 +-- include/linux/tty_flip.h | 1 + 4 files changed, 36 insertions(+), 15 deletions(-) diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index 1b39dd639ee9..b38a28bd9511 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -89,17 +89,13 @@ static void pty_unthrottle(struct tty_struct *tty) * pty_space - report space left for writing * @to: tty we are writing into * - * The tty buffers allow 64K but we sneak a peak and clip at 8K this - * allows a lot of overspill room for echo and other fun messes to - * be handled properly + * Limit the buffer space used by ptys to 8k. */ static int pty_space(struct tty_struct *to) { - int n = 8192 - to->port->buf.memory_used; - if (n < 0) - return 0; - return n; + int n = tty_buffer_space_avail(to->port); + return min(n, 8192); } /** diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index 231b7a8710f1..5d5a56407aa8 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -22,6 +22,31 @@ #define MIN_TTYB_SIZE 256 #define TTYB_ALIGN_MASK 255 +/* + * Byte threshold to limit memory consumption for flip buffers. + * The actual memory limit is > 2x this amount. + */ +#define TTYB_MEM_LIMIT 65536 + + +/** + * tty_buffer_space_avail - return unused buffer space + * @port - tty_port owning the flip buffer + * + * Returns the # of bytes which can be written by the driver without + * reaching the buffer limit. + * + * Note: this does not guarantee that memory is available to write + * the returned # of bytes (use tty_prepare_flip_string_xxx() to + * pre-allocate if memory guarantee is required). + */ + +int tty_buffer_space_avail(struct tty_port *port) +{ + int space = TTYB_MEM_LIMIT - atomic_read(&port->buf.memory_used); + return max(space, 0); +} + static void tty_buffer_reset(struct tty_buffer *p, size_t size) { p->used = 0; @@ -59,7 +84,8 @@ void tty_buffer_free_all(struct tty_port *port) tty_buffer_reset(&buf->sentinel, 0); buf->head = &buf->sentinel; buf->tail = &buf->sentinel; - buf->memory_used = 0; + + atomic_set(&buf->memory_used, 0); } /** @@ -92,7 +118,7 @@ static struct tty_buffer *tty_buffer_alloc(struct tty_port *port, size_t size) /* Should possibly check if this fails for the largest buffer we have queued and recycle that ? */ - if (port->buf.memory_used + size > 65536) + if (atomic_read(&port->buf.memory_used) > TTYB_MEM_LIMIT) return NULL; p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC); if (p == NULL) @@ -100,7 +126,7 @@ static struct tty_buffer *tty_buffer_alloc(struct tty_port *port, size_t size) found: tty_buffer_reset(p, size); - port->buf.memory_used += size; + atomic_add(size, &port->buf.memory_used); return p; } @@ -118,8 +144,7 @@ static void tty_buffer_free(struct tty_port *port, struct tty_buffer *b) struct tty_bufhead *buf = &port->buf; /* Dumb strategy for now - should keep some stats */ - buf->memory_used -= b->size; - WARN_ON(buf->memory_used < 0); + WARN_ON(atomic_sub_return(b->size, &buf->memory_used) < 0); if (b->size > MIN_TTYB_SIZE) kfree(b); @@ -525,7 +550,7 @@ void tty_buffer_init(struct tty_port *port) buf->head = &buf->sentinel; buf->tail = &buf->sentinel; init_llist_head(&buf->free); - buf->memory_used = 0; + atomic_set(&buf->memory_used, 0); INIT_WORK(&buf->work, flush_to_ldisc); } diff --git a/include/linux/tty.h b/include/linux/tty.h index 2e93eb831c61..7c124541f011 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -71,8 +71,7 @@ struct tty_bufhead { struct tty_buffer *head; /* Queue head */ struct tty_buffer *tail; /* Active buffer */ struct llist_head free; /* Free queue head */ - int memory_used; /* Buffer space used excluding - free queue */ + atomic_t memory_used; /* In-use buffers excluding free list */ }; /* * When a break, frame error, or parity error happens, these codes are diff --git a/include/linux/tty_flip.h b/include/linux/tty_flip.h index ad0303994c32..6944ed2ce692 100644 --- a/include/linux/tty_flip.h +++ b/include/linux/tty_flip.h @@ -1,6 +1,7 @@ #ifndef _LINUX_TTY_FLIP_H #define _LINUX_TTY_FLIP_H +extern int tty_buffer_space_avail(struct tty_port *port); extern int tty_buffer_request_room(struct tty_port *port, size_t size); extern int tty_insert_flip_string_flags(struct tty_port *port, const unsigned char *chars, const char *flags, size_t size); From e8437d7ecbc50198705331449367d401ebb3181f Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:36:09 -0400 Subject: [PATCH 0514/3400] tty: Make driver-side flip buffers lockless Driver-side flip buffer input is already single-threaded; 'publish' the .next link as the last operation on the tail buffer so the 'consumer' sees the already-completed flip buffer. The commit buffer index is already 'published' by driver-side functions. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_buffer.c | 31 ++++--------------------------- 1 file changed, 4 insertions(+), 27 deletions(-) diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index 5d5a56407aa8..685757c6ce87 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -62,8 +62,6 @@ static void tty_buffer_reset(struct tty_buffer *p, size_t size) * * Remove all the buffers pending on a tty whether queued with data * or in the free ring. Must be called when the tty is no longer in use - * - * Locking: none */ void tty_buffer_free_all(struct tty_port *port) @@ -216,29 +214,26 @@ void tty_buffer_flush(struct tty_struct *tty) * * Make at least size bytes of linear space available for the tty * buffer. If we fail return the size we managed to find. - * - * Locking: Takes port->buf.lock */ int tty_buffer_request_room(struct tty_port *port, size_t size) { struct tty_bufhead *buf = &port->buf; struct tty_buffer *b, *n; int left; - unsigned long flags; - spin_lock_irqsave(&buf->lock, flags); + b = buf->tail; left = b->size - b->used; if (left < size) { /* This is the slow path - looking for new buffers to use */ if ((n = tty_buffer_alloc(port, size)) != NULL) { - b->next = n; - b->commit = b->used; buf->tail = n; + b->commit = b->used; + smp_mb(); + b->next = n; } else size = left; } - spin_unlock_irqrestore(&buf->lock, flags); return size; } EXPORT_SYMBOL_GPL(tty_buffer_request_room); @@ -252,8 +247,6 @@ EXPORT_SYMBOL_GPL(tty_buffer_request_room); * * Queue a series of bytes to the tty buffering. All the characters * passed are marked with the supplied flag. Returns the number added. - * - * Locking: Called functions may take port->buf.lock */ int tty_insert_flip_string_fixed_flag(struct tty_port *port, @@ -288,8 +281,6 @@ EXPORT_SYMBOL(tty_insert_flip_string_fixed_flag); * Queue a series of bytes to the tty buffering. For each character * the flags array indicates the status of the character. Returns the * number added. - * - * Locking: Called functions may take port->buf.lock */ int tty_insert_flip_string_flags(struct tty_port *port, @@ -324,19 +315,14 @@ EXPORT_SYMBOL(tty_insert_flip_string_flags); * processing by the line discipline. * Note that this function can only be used when the low_latency flag * is unset. Otherwise the workqueue won't be flushed. - * - * Locking: Takes port->buf.lock */ void tty_schedule_flip(struct tty_port *port) { struct tty_bufhead *buf = &port->buf; - unsigned long flags; WARN_ON(port->low_latency); - spin_lock_irqsave(&buf->lock, flags); buf->tail->commit = buf->tail->used; - spin_unlock_irqrestore(&buf->lock, flags); schedule_work(&buf->work); } EXPORT_SYMBOL(tty_schedule_flip); @@ -352,8 +338,6 @@ EXPORT_SYMBOL(tty_schedule_flip); * accounted for as ready for normal characters. This is used for drivers * that need their own block copy routines into the buffer. There is no * guarantee the buffer is a DMA target! - * - * Locking: May call functions taking port->buf.lock */ int tty_prepare_flip_string(struct tty_port *port, unsigned char **chars, @@ -382,8 +366,6 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string); * accounted for as ready for characters. This is used for drivers * that need their own block copy routines into the buffer. There is no * guarantee the buffer is a DMA target! - * - * Locking: May call functions taking port->buf.lock */ int tty_prepare_flip_string_flags(struct tty_port *port, @@ -511,18 +493,13 @@ void tty_flush_to_ldisc(struct tty_struct *tty) * * In the event of the queue being busy for flipping the work will be * held off and retried later. - * - * Locking: tty buffer lock. Driver locks in low latency mode. */ void tty_flip_buffer_push(struct tty_port *port) { struct tty_bufhead *buf = &port->buf; - unsigned long flags; - spin_lock_irqsave(&buf->lock, flags); buf->tail->commit = buf->tail->used; - spin_unlock_irqrestore(&buf->lock, flags); if (port->low_latency) flush_to_ldisc(&buf->work); From e9975fdec0138f1b2a85b9624e41660abd9865d4 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:36:10 -0400 Subject: [PATCH 0515/3400] tty: Ensure single-threaded flip buffer consumer with mutex The buffer work may race with parallel tty_buffer_flush. Use a mutex to guarantee exclusive modify access to the head flip buffer. Remove the unneeded spin lock. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dgrp/dgrp_tty.c | 2 ++ drivers/tty/tty_buffer.c | 40 ++++++++++++++++----------------- include/linux/tty.h | 2 +- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/drivers/staging/dgrp/dgrp_tty.c b/drivers/staging/dgrp/dgrp_tty.c index 654f6010b473..0d52de3729c6 100644 --- a/drivers/staging/dgrp/dgrp_tty.c +++ b/drivers/staging/dgrp/dgrp_tty.c @@ -1120,7 +1120,9 @@ static void dgrp_tty_close(struct tty_struct *tty, struct file *file) if (!sent_printer_offstr) dgrp_tty_flush_buffer(tty); + spin_unlock_irqrestore(&nd->nd_lock, lock_flags); tty_ldisc_flush(tty); + spin_lock_irqsave(&nd->nd_lock, lock_flags); break; } diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index 685757c6ce87..c3c606c52722 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -157,8 +157,6 @@ static void tty_buffer_free(struct tty_port *port, struct tty_buffer *b) * flush all the buffers containing receive data. Caller must * hold the buffer lock and must have ensured no parallel flush to * ldisc is running. - * - * Locking: Caller must hold tty->buf.lock */ static void __tty_buffer_flush(struct tty_port *port) @@ -182,29 +180,29 @@ static void __tty_buffer_flush(struct tty_port *port) * being processed by flush_to_ldisc then we defer the processing * to that function * - * Locking: none + * Locking: takes flush_mutex to ensure single-threaded flip buffer + * 'consumer' */ void tty_buffer_flush(struct tty_struct *tty) { struct tty_port *port = tty->port; struct tty_bufhead *buf = &port->buf; - unsigned long flags; - - spin_lock_irqsave(&buf->lock, flags); + mutex_lock(&buf->flush_mutex); /* If the data is being pushed to the tty layer then we can't process it here. Instead set a flag and the flush_to_ldisc path will process the flush request before it exits */ if (test_bit(TTYP_FLUSHING, &port->iflags)) { set_bit(TTYP_FLUSHPENDING, &port->iflags); - spin_unlock_irqrestore(&buf->lock, flags); + mutex_unlock(&buf->flush_mutex); wait_event(tty->read_wait, test_bit(TTYP_FLUSHPENDING, &port->iflags) == 0); return; - } else - __tty_buffer_flush(port); - spin_unlock_irqrestore(&buf->lock, flags); + } + + __tty_buffer_flush(port); + mutex_unlock(&buf->flush_mutex); } /** @@ -408,9 +406,10 @@ receive_buf(struct tty_struct *tty, struct tty_buffer *head, int count) * This routine is called out of the software interrupt to flush data * from the buffer chain to the line discipline. * - * Locking: holds tty->buf.lock to guard buffer list. Drops the lock - * while invoking the line discipline receive_buf method. The - * receive_buf method is single threaded for each tty instance. + * The receive_buf method is single threaded for each tty instance. + * + * Locking: takes flush_mutex to ensure single-threaded flip buffer + * 'consumer' */ static void flush_to_ldisc(struct work_struct *work) @@ -418,7 +417,6 @@ static void flush_to_ldisc(struct work_struct *work) struct tty_port *port = container_of(work, struct tty_port, buf.work); struct tty_bufhead *buf = &port->buf; struct tty_struct *tty; - unsigned long flags; struct tty_ldisc *disc; tty = port->itty; @@ -429,7 +427,7 @@ static void flush_to_ldisc(struct work_struct *work) if (disc == NULL) return; - spin_lock_irqsave(&buf->lock, flags); + mutex_lock(&buf->flush_mutex); if (!test_and_set_bit(TTYP_FLUSHING, &port->iflags)) { while (1) { @@ -444,11 +442,13 @@ static void flush_to_ldisc(struct work_struct *work) tty_buffer_free(port, head); continue; } - spin_unlock_irqrestore(&buf->lock, flags); + + mutex_unlock(&buf->flush_mutex); count = receive_buf(tty, head, count); - spin_lock_irqsave(&buf->lock, flags); + mutex_lock(&buf->flush_mutex); + /* Ldisc or user is trying to flush the buffers. We may have a deferred request to flush the input buffer, if so pull the chain under the lock @@ -464,7 +464,7 @@ static void flush_to_ldisc(struct work_struct *work) clear_bit(TTYP_FLUSHING, &port->iflags); } - spin_unlock_irqrestore(&buf->lock, flags); + mutex_unlock(&buf->flush_mutex); tty_ldisc_deref(disc); } @@ -514,15 +514,13 @@ EXPORT_SYMBOL(tty_flip_buffer_push); * * Set up the initial state of the buffer management for a tty device. * Must be called before the other tty buffer functions are used. - * - * Locking: none */ void tty_buffer_init(struct tty_port *port) { struct tty_bufhead *buf = &port->buf; - spin_lock_init(&buf->lock); + mutex_init(&buf->flush_mutex); tty_buffer_reset(&buf->sentinel, 0); buf->head = &buf->sentinel; buf->tail = &buf->sentinel; diff --git a/include/linux/tty.h b/include/linux/tty.h index 7c124541f011..1c8fef0e3ff6 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -66,7 +66,7 @@ static inline char *flag_buf_ptr(struct tty_buffer *b, int ofs) struct tty_bufhead { struct work_struct work; - spinlock_t lock; + struct mutex flush_mutex; struct tty_buffer sentinel; struct tty_buffer *head; /* Queue head */ struct tty_buffer *tail; /* Active buffer */ From d7a68be4f265be10e24be931c257af30ca55566b Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:36:11 -0400 Subject: [PATCH 0516/3400] tty: Only perform flip buffer flush from tty_buffer_flush() Now that dropping the buffer lock is not necessary (as result of converting the spin lock to a mutex), the flip buffer flush no longer needs to be handled by the buffer work. Simply signal a flush is required; the buffer work will exit the i/o loop, which allows tty_buffer_flush() to proceed. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_buffer.c | 59 +++++++++++++--------------------------- include/linux/tty.h | 1 - 2 files changed, 19 insertions(+), 41 deletions(-) diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index c3c606c52722..39cae611fe59 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -189,19 +189,11 @@ void tty_buffer_flush(struct tty_struct *tty) struct tty_port *port = tty->port; struct tty_bufhead *buf = &port->buf; - mutex_lock(&buf->flush_mutex); - /* If the data is being pushed to the tty layer then we can't - process it here. Instead set a flag and the flush_to_ldisc - path will process the flush request before it exits */ - if (test_bit(TTYP_FLUSHING, &port->iflags)) { - set_bit(TTYP_FLUSHPENDING, &port->iflags); - mutex_unlock(&buf->flush_mutex); - wait_event(tty->read_wait, - test_bit(TTYP_FLUSHPENDING, &port->iflags) == 0); - return; - } + set_bit(TTYP_FLUSHPENDING, &port->iflags); + mutex_lock(&buf->flush_mutex); __tty_buffer_flush(port); + clear_bit(TTYP_FLUSHPENDING, &port->iflags); mutex_unlock(&buf->flush_mutex); } @@ -429,39 +421,26 @@ static void flush_to_ldisc(struct work_struct *work) mutex_lock(&buf->flush_mutex); - if (!test_and_set_bit(TTYP_FLUSHING, &port->iflags)) { - while (1) { - struct tty_buffer *head = buf->head; - int count; + while (1) { + struct tty_buffer *head = buf->head; + int count; - count = head->commit - head->read; - if (!count) { - if (head->next == NULL) - break; - buf->head = head->next; - tty_buffer_free(port, head); - continue; - } + /* Ldisc or user is trying to flush the buffers. */ + if (test_bit(TTYP_FLUSHPENDING, &port->iflags)) + break; - mutex_unlock(&buf->flush_mutex); - - count = receive_buf(tty, head, count); - - mutex_lock(&buf->flush_mutex); - - /* Ldisc or user is trying to flush the buffers. - We may have a deferred request to flush the - input buffer, if so pull the chain under the lock - and empty the queue */ - if (test_bit(TTYP_FLUSHPENDING, &port->iflags)) { - __tty_buffer_flush(port); - clear_bit(TTYP_FLUSHPENDING, &port->iflags); - wake_up(&tty->read_wait); - break; - } else if (!count) + count = head->commit - head->read; + if (!count) { + if (head->next == NULL) break; + buf->head = head->next; + tty_buffer_free(port, head); + continue; } - clear_bit(TTYP_FLUSHING, &port->iflags); + + count = receive_buf(tty, head, count); + if (!count) + break; } mutex_unlock(&buf->flush_mutex); diff --git a/include/linux/tty.h b/include/linux/tty.h index 1c8fef0e3ff6..1d5bacca3652 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -213,7 +213,6 @@ struct tty_port { wait_queue_head_t delta_msr_wait; /* Modem status change */ unsigned long flags; /* TTY flags ASY_*/ unsigned long iflags; /* TTYP_ internal flags */ -#define TTYP_FLUSHING 1 /* Flushing to ldisc in progress */ #define TTYP_FLUSHPENDING 2 /* Queued buffer flush pending */ unsigned char console:1, /* port is a console */ low_latency:1; /* direct buffer flush */ From 8c1fb49ba107c7db9441ef6ec0ab5830d112cc2a Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:36:12 -0400 Subject: [PATCH 0517/3400] tty: Avoid false-sharing flip buffer ptrs Separate the head and tail ptrs to avoid cache-line contention (so called 'false-sharing') between concurrent threads. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- include/linux/tty.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/tty.h b/include/linux/tty.h index 1d5bacca3652..b8e8adf95bf3 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -65,13 +65,13 @@ static inline char *flag_buf_ptr(struct tty_buffer *b, int ofs) struct tty_bufhead { + struct tty_buffer *head; /* Queue head */ struct work_struct work; struct mutex flush_mutex; struct tty_buffer sentinel; - struct tty_buffer *head; /* Queue head */ - struct tty_buffer *tail; /* Active buffer */ struct llist_head free; /* Free queue head */ atomic_t memory_used; /* In-use buffers excluding free list */ + struct tty_buffer *tail; /* Active buffer */ }; /* * When a break, frame error, or parity error happens, these codes are From 0f56bd2f6a97d8b0eb5c8f9bc04b83a6c16d1d48 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:36:13 -0400 Subject: [PATCH 0518/3400] tty: Use non-atomic state to signal flip buffer flush pending Atomic bit ops are no longer required to indicate a flip buffer flush is pending, as the flush_mutex is sufficient barrier. Remove the unnecessary port .iflags field and localize flip buffer state to struct tty_bufhead. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_buffer.c | 7 ++++--- include/linux/tty.h | 3 +-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index 39cae611fe59..fb042b9a8d68 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -189,11 +189,11 @@ void tty_buffer_flush(struct tty_struct *tty) struct tty_port *port = tty->port; struct tty_bufhead *buf = &port->buf; - set_bit(TTYP_FLUSHPENDING, &port->iflags); + buf->flushpending = 1; mutex_lock(&buf->flush_mutex); __tty_buffer_flush(port); - clear_bit(TTYP_FLUSHPENDING, &port->iflags); + buf->flushpending = 0; mutex_unlock(&buf->flush_mutex); } @@ -426,7 +426,7 @@ static void flush_to_ldisc(struct work_struct *work) int count; /* Ldisc or user is trying to flush the buffers. */ - if (test_bit(TTYP_FLUSHPENDING, &port->iflags)) + if (buf->flushpending) break; count = head->commit - head->read; @@ -505,6 +505,7 @@ void tty_buffer_init(struct tty_port *port) buf->tail = &buf->sentinel; init_llist_head(&buf->free); atomic_set(&buf->memory_used, 0); + buf->flushpending = 0; INIT_WORK(&buf->work, flush_to_ldisc); } diff --git a/include/linux/tty.h b/include/linux/tty.h index b8e8adf95bf3..991575fe3451 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -68,6 +68,7 @@ struct tty_bufhead { struct tty_buffer *head; /* Queue head */ struct work_struct work; struct mutex flush_mutex; + unsigned int flushpending:1; struct tty_buffer sentinel; struct llist_head free; /* Free queue head */ atomic_t memory_used; /* In-use buffers excluding free list */ @@ -212,8 +213,6 @@ struct tty_port { wait_queue_head_t close_wait; /* Close waiters */ wait_queue_head_t delta_msr_wait; /* Modem status change */ unsigned long flags; /* TTY flags ASY_*/ - unsigned long iflags; /* TTYP_ internal flags */ -#define TTYP_FLUSHPENDING 2 /* Queued buffer flush pending */ unsigned char console:1, /* port is a console */ low_latency:1; /* direct buffer flush */ struct mutex mutex; /* Locking */ From 47aa658a015440906def231f54685c4d5d49dc38 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:36:14 -0400 Subject: [PATCH 0519/3400] tty: Merge __tty_flush_buffer() into lone call site __tty_flush_buffer() is now only called by tty_flush_buffer(); merge functions. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_buffer.c | 29 ++++++----------------------- 1 file changed, 6 insertions(+), 23 deletions(-) diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index fb042b9a8d68..dbe4a718e2dc 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -150,28 +150,6 @@ static void tty_buffer_free(struct tty_port *port, struct tty_buffer *b) llist_add(&b->free, &buf->free); } -/** - * __tty_buffer_flush - flush full tty buffers - * @tty: tty to flush - * - * flush all the buffers containing receive data. Caller must - * hold the buffer lock and must have ensured no parallel flush to - * ldisc is running. - */ - -static void __tty_buffer_flush(struct tty_port *port) -{ - struct tty_bufhead *buf = &port->buf; - struct tty_buffer *next; - - while ((next = buf->head->next) != NULL) { - tty_buffer_free(port, buf->head); - buf->head = next; - } - WARN_ON(buf->head != buf->tail); - buf->head->read = buf->head->commit; -} - /** * tty_buffer_flush - flush full tty buffers * @tty: tty to flush @@ -188,11 +166,16 @@ void tty_buffer_flush(struct tty_struct *tty) { struct tty_port *port = tty->port; struct tty_bufhead *buf = &port->buf; + struct tty_buffer *next; buf->flushpending = 1; mutex_lock(&buf->flush_mutex); - __tty_buffer_flush(port); + while ((next = buf->head->next) != NULL) { + tty_buffer_free(port, buf->head); + buf->head = next; + } + buf->head->read = buf->head->commit; buf->flushpending = 0; mutex_unlock(&buf->flush_mutex); } From a7c8d58c79853adeebf0a1ddc9c63e433b4d97f1 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:36:15 -0400 Subject: [PATCH 0520/3400] tty: Fix unsafe vt paste_selection() Convert the tty_buffer_flush() exclusion mechanism to a public interface - tty_buffer_lock/unlock_exclusive() - and use the interface to safely write the paste selection to the line discipline. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_buffer.c | 61 ++++++++++++++++++++++++++++++-------- drivers/tty/vt/selection.c | 4 ++- include/linux/tty.h | 4 +-- include/linux/tty_flip.h | 3 ++ 4 files changed, 56 insertions(+), 16 deletions(-) diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index dbe4a718e2dc..f22e116db105 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -29,6 +29,42 @@ #define TTYB_MEM_LIMIT 65536 +/** + * tty_buffer_lock_exclusive - gain exclusive access to buffer + * tty_buffer_unlock_exclusive - release exclusive access + * + * @port - tty_port owning the flip buffer + * + * Guarantees safe use of the line discipline's receive_buf() method by + * excluding the buffer work and any pending flush from using the flip + * buffer. Data can continue to be added concurrently to the flip buffer + * from the driver side. + * + * On release, the buffer work is restarted if there is data in the + * flip buffer + */ + +void tty_buffer_lock_exclusive(struct tty_port *port) +{ + struct tty_bufhead *buf = &port->buf; + + atomic_inc(&buf->priority); + mutex_lock(&buf->lock); +} + +void tty_buffer_unlock_exclusive(struct tty_port *port) +{ + struct tty_bufhead *buf = &port->buf; + int restart; + + restart = buf->head->commit != buf->head->read; + + atomic_dec(&buf->priority); + mutex_unlock(&buf->lock); + if (restart) + queue_work(system_unbound_wq, &buf->work); +} + /** * tty_buffer_space_avail - return unused buffer space * @port - tty_port owning the flip buffer @@ -158,7 +194,7 @@ static void tty_buffer_free(struct tty_port *port, struct tty_buffer *b) * being processed by flush_to_ldisc then we defer the processing * to that function * - * Locking: takes flush_mutex to ensure single-threaded flip buffer + * Locking: takes buffer lock to ensure single-threaded flip buffer * 'consumer' */ @@ -168,16 +204,16 @@ void tty_buffer_flush(struct tty_struct *tty) struct tty_bufhead *buf = &port->buf; struct tty_buffer *next; - buf->flushpending = 1; + atomic_inc(&buf->priority); - mutex_lock(&buf->flush_mutex); + mutex_lock(&buf->lock); while ((next = buf->head->next) != NULL) { tty_buffer_free(port, buf->head); buf->head = next; } buf->head->read = buf->head->commit; - buf->flushpending = 0; - mutex_unlock(&buf->flush_mutex); + atomic_dec(&buf->priority); + mutex_unlock(&buf->lock); } /** @@ -383,7 +419,7 @@ receive_buf(struct tty_struct *tty, struct tty_buffer *head, int count) * * The receive_buf method is single threaded for each tty instance. * - * Locking: takes flush_mutex to ensure single-threaded flip buffer + * Locking: takes buffer lock to ensure single-threaded flip buffer * 'consumer' */ @@ -402,14 +438,14 @@ static void flush_to_ldisc(struct work_struct *work) if (disc == NULL) return; - mutex_lock(&buf->flush_mutex); + mutex_lock(&buf->lock); while (1) { struct tty_buffer *head = buf->head; int count; - /* Ldisc or user is trying to flush the buffers. */ - if (buf->flushpending) + /* Ldisc or user is trying to gain exclusive access */ + if (atomic_read(&buf->priority)) break; count = head->commit - head->read; @@ -426,7 +462,7 @@ static void flush_to_ldisc(struct work_struct *work) break; } - mutex_unlock(&buf->flush_mutex); + mutex_unlock(&buf->lock); tty_ldisc_deref(disc); } @@ -482,13 +518,12 @@ void tty_buffer_init(struct tty_port *port) { struct tty_bufhead *buf = &port->buf; - mutex_init(&buf->flush_mutex); + mutex_init(&buf->lock); tty_buffer_reset(&buf->sentinel, 0); buf->head = &buf->sentinel; buf->tail = &buf->sentinel; init_llist_head(&buf->free); atomic_set(&buf->memory_used, 0); - buf->flushpending = 0; + atomic_set(&buf->priority, 0); INIT_WORK(&buf->work, flush_to_ldisc); } - diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c index 2ca8d6b6514c..ea27804d87af 100644 --- a/drivers/tty/vt/selection.c +++ b/drivers/tty/vt/selection.c @@ -24,6 +24,7 @@ #include #include #include +#include /* Don't take this from : 011-015 on the screen aren't spaces */ #define isspace(c) ((c) == ' ') @@ -346,8 +347,8 @@ int paste_selection(struct tty_struct *tty) console_unlock(); ld = tty_ldisc_ref_wait(tty); + tty_buffer_lock_exclusive(&vc->port); - /* FIXME: this is completely unsafe */ add_wait_queue(&vc->paste_wait, &wait); while (sel_buffer && sel_buffer_lth > pasted) { set_current_state(TASK_INTERRUPTIBLE); @@ -363,6 +364,7 @@ int paste_selection(struct tty_struct *tty) remove_wait_queue(&vc->paste_wait, &wait); __set_current_state(TASK_RUNNING); + tty_buffer_unlock_exclusive(&vc->port); tty_ldisc_deref(ld); return 0; } diff --git a/include/linux/tty.h b/include/linux/tty.h index 991575fe3451..7a9a3b0a6b5a 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -67,8 +67,8 @@ static inline char *flag_buf_ptr(struct tty_buffer *b, int ofs) struct tty_bufhead { struct tty_buffer *head; /* Queue head */ struct work_struct work; - struct mutex flush_mutex; - unsigned int flushpending:1; + struct mutex lock; + atomic_t priority; struct tty_buffer sentinel; struct llist_head free; /* Free queue head */ atomic_t memory_used; /* In-use buffers excluding free list */ diff --git a/include/linux/tty_flip.h b/include/linux/tty_flip.h index 6944ed2ce692..21ddd7d9ea1f 100644 --- a/include/linux/tty_flip.h +++ b/include/linux/tty_flip.h @@ -32,4 +32,7 @@ static inline int tty_insert_flip_string(struct tty_port *port, return tty_insert_flip_string_fixed_flag(port, chars, TTY_NORMAL, size); } +extern void tty_buffer_lock_exclusive(struct tty_port *port); +extern void tty_buffer_unlock_exclusive(struct tty_port *port); + #endif /* _LINUX_TTY_FLIP_H */ From 9114fe8ccf1871f630d2c14cd60e5f455b015459 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 09:36:16 -0400 Subject: [PATCH 0521/3400] tty: Remove private constant from global namespace TTY_BUFFER_PAGE is only used within drivers/tty/tty_buffer.c; relocate to that file scope. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_buffer.c | 10 ++++++++++ include/linux/tty.h | 11 ----------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index f22e116db105..c043136fbe51 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -28,6 +28,16 @@ */ #define TTYB_MEM_LIMIT 65536 +/* + * We default to dicing tty buffer allocations to this many characters + * in order to avoid multiple page allocations. We know the size of + * tty_buffer itself but it must also be taken into account that the + * the buffer is 256 byte aligned. See tty_buffer_find for the allocation + * logic this must match + */ + +#define TTY_BUFFER_PAGE (((PAGE_SIZE - sizeof(struct tty_buffer)) / 2) & ~0xFF) + /** * tty_buffer_lock_exclusive - gain exclusive access to buffer diff --git a/include/linux/tty.h b/include/linux/tty.h index 7a9a3b0a6b5a..5fd5d6f1ebc4 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -53,17 +53,6 @@ static inline char *flag_buf_ptr(struct tty_buffer *b, int ofs) return (char *)char_buf_ptr(b, ofs) + b->size; } -/* - * We default to dicing tty buffer allocations to this many characters - * in order to avoid multiple page allocations. We know the size of - * tty_buffer itself but it must also be taken into account that the - * the buffer is 256 byte aligned. See tty_buffer_find for the allocation - * logic this must match - */ - -#define TTY_BUFFER_PAGE (((PAGE_SIZE - sizeof(struct tty_buffer)) / 2) & ~0xFF) - - struct tty_bufhead { struct tty_buffer *head; /* Queue head */ struct work_struct work; From ae56f3304107f70e26a389d845db76d6b949c114 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 10:04:21 -0400 Subject: [PATCH 0522/3400] n_tty: Remove unused echo_overrun field The echo_overrun field is only assigned and never tested; remove it. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index a69470e02bf4..c1c721fa8766 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -96,7 +96,6 @@ struct n_tty_data { /* must hold exclusive termios_rwsem to reset these */ unsigned char lnext:1, erasing:1, raw:1, real_raw:1, icanon:1; - unsigned char echo_overrun:1; /* shared by producer and consumer */ char *read_buf; @@ -326,7 +325,7 @@ static void reset_buffer_flags(struct n_tty_data *ldata) ldata->read_head = ldata->canon_head = ldata->read_tail = 0; mutex_lock(&ldata->echo_lock); - ldata->echo_pos = ldata->echo_cnt = ldata->echo_overrun = 0; + ldata->echo_pos = ldata->echo_cnt = 0; mutex_unlock(&ldata->echo_lock); ldata->erasing = 0; @@ -782,14 +781,11 @@ static void process_echoes(struct tty_struct *tty) if (nr == 0) { ldata->echo_pos = 0; ldata->echo_cnt = 0; - ldata->echo_overrun = 0; } else { int num_processed = ldata->echo_cnt - nr; ldata->echo_pos += num_processed; ldata->echo_pos &= N_TTY_BUF_SIZE - 1; ldata->echo_cnt = nr; - if (num_processed > 0) - ldata->echo_overrun = 0; } mutex_unlock(&ldata->echo_lock); @@ -835,8 +831,6 @@ static void add_echo_byte(unsigned char c, struct n_tty_data *ldata) ldata->echo_pos++; } ldata->echo_pos &= N_TTY_BUF_SIZE - 1; - - ldata->echo_overrun = 1; } else { new_byte_pos = ldata->echo_pos + ldata->echo_cnt; new_byte_pos &= N_TTY_BUF_SIZE - 1; From addaebccf63a8c9f7c7a62ce1ceb9da4307c5a1c Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 10:04:22 -0400 Subject: [PATCH 0523/3400] n_tty: Use separate head and tail indices for echo_buf Instead of using a single index to track the current echo_buf position, use a head index when adding to the buffer and a tail index when consuming from the buffer. Allow these head and tail indices to wrap at max representable value; perform modulo reduction via helper functions when accessing the buffer. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 88 ++++++++++++++++++--------------------------- 1 file changed, 35 insertions(+), 53 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index c1c721fa8766..18d72a0258ce 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -108,7 +108,8 @@ struct n_tty_data { /* protected by echo_lock */ unsigned char *echo_buf; - unsigned int echo_pos; + size_t echo_head; + size_t echo_tail; unsigned int echo_cnt; /* protected by output lock */ @@ -135,6 +136,16 @@ static inline unsigned char *read_buf_addr(struct n_tty_data *ldata, size_t i) return &ldata->read_buf[i & (N_TTY_BUF_SIZE - 1)]; } +static inline unsigned char echo_buf(struct n_tty_data *ldata, size_t i) +{ + return ldata->echo_buf[i & (N_TTY_BUF_SIZE - 1)]; +} + +static inline unsigned char *echo_buf_addr(struct n_tty_data *ldata, size_t i) +{ + return &ldata->echo_buf[i & (N_TTY_BUF_SIZE - 1)]; +} + static inline int tty_put_user(struct tty_struct *tty, unsigned char x, unsigned char __user *ptr) { @@ -325,7 +336,7 @@ static void reset_buffer_flags(struct n_tty_data *ldata) ldata->read_head = ldata->canon_head = ldata->read_tail = 0; mutex_lock(&ldata->echo_lock); - ldata->echo_pos = ldata->echo_cnt = 0; + ldata->echo_head = ldata->echo_tail = ldata->echo_cnt = 0; mutex_unlock(&ldata->echo_lock); ldata->erasing = 0; @@ -640,8 +651,8 @@ static void process_echoes(struct tty_struct *tty) { struct n_tty_data *ldata = tty->disc_data; int space, nr; + size_t tail; unsigned char c; - unsigned char *cp, *buf_end; if (!ldata->echo_cnt) return; @@ -651,14 +662,12 @@ static void process_echoes(struct tty_struct *tty) space = tty_write_room(tty); - buf_end = ldata->echo_buf + N_TTY_BUF_SIZE; - cp = ldata->echo_buf + ldata->echo_pos; + tail = ldata->echo_tail; nr = ldata->echo_cnt; while (nr > 0) { - c = *cp; + c = echo_buf(ldata, tail); if (c == ECHO_OP_START) { unsigned char op; - unsigned char *opp; int no_space_left = 0; /* @@ -666,18 +675,13 @@ static void process_echoes(struct tty_struct *tty) * operation, get the next byte, which is either the * op code or a control character value. */ - opp = cp + 1; - if (opp == buf_end) - opp -= N_TTY_BUF_SIZE; - op = *opp; + op = echo_buf(ldata, tail + 1); switch (op) { unsigned int num_chars, num_bs; case ECHO_OP_ERASE_TAB: - if (++opp == buf_end) - opp -= N_TTY_BUF_SIZE; - num_chars = *opp; + num_chars = echo_buf(ldata, tail + 2); /* * Determine how many columns to go back @@ -703,20 +707,20 @@ static void process_echoes(struct tty_struct *tty) if (ldata->column > 0) ldata->column--; } - cp += 3; + tail += 3; nr -= 3; break; case ECHO_OP_SET_CANON_COL: ldata->canon_column = ldata->column; - cp += 2; + tail += 2; nr -= 2; break; case ECHO_OP_MOVE_BACK_COL: if (ldata->column > 0) ldata->column--; - cp += 2; + tail += 2; nr -= 2; break; @@ -729,7 +733,7 @@ static void process_echoes(struct tty_struct *tty) tty_put_char(tty, ECHO_OP_START); ldata->column++; space--; - cp += 2; + tail += 2; nr -= 2; break; @@ -751,7 +755,7 @@ static void process_echoes(struct tty_struct *tty) tty_put_char(tty, op ^ 0100); ldata->column += 2; space -= 2; - cp += 2; + tail += 2; nr -= 2; } @@ -769,24 +773,13 @@ static void process_echoes(struct tty_struct *tty) tty_put_char(tty, c); space -= 1; } - cp += 1; + tail += 1; nr -= 1; } - - /* When end of circular buffer reached, wrap around */ - if (cp >= buf_end) - cp -= N_TTY_BUF_SIZE; } - if (nr == 0) { - ldata->echo_pos = 0; - ldata->echo_cnt = 0; - } else { - int num_processed = ldata->echo_cnt - nr; - ldata->echo_pos += num_processed; - ldata->echo_pos &= N_TTY_BUF_SIZE - 1; - ldata->echo_cnt = nr; - } + ldata->echo_tail = tail; + ldata->echo_cnt = nr; mutex_unlock(&ldata->echo_lock); mutex_unlock(&ldata->output_lock); @@ -807,37 +800,26 @@ static void process_echoes(struct tty_struct *tty) static void add_echo_byte(unsigned char c, struct n_tty_data *ldata) { - int new_byte_pos; - if (ldata->echo_cnt == N_TTY_BUF_SIZE) { - /* Circular buffer is already at capacity */ - new_byte_pos = ldata->echo_pos; - + size_t head = ldata->echo_head; /* * Since the buffer start position needs to be advanced, * be sure to step by a whole operation byte group. */ - if (ldata->echo_buf[ldata->echo_pos] == ECHO_OP_START) { - if (ldata->echo_buf[(ldata->echo_pos + 1) & - (N_TTY_BUF_SIZE - 1)] == - ECHO_OP_ERASE_TAB) { - ldata->echo_pos += 3; + if (echo_buf(ldata, head) == ECHO_OP_START) { + if (echo_buf(ldata, head + 1) == ECHO_OP_ERASE_TAB) { + ldata->echo_tail += 3; ldata->echo_cnt -= 2; } else { - ldata->echo_pos += 2; + ldata->echo_tail += 2; ldata->echo_cnt -= 1; } - } else { - ldata->echo_pos++; - } - ldata->echo_pos &= N_TTY_BUF_SIZE - 1; - } else { - new_byte_pos = ldata->echo_pos + ldata->echo_cnt; - new_byte_pos &= N_TTY_BUF_SIZE - 1; + } else + ldata->echo_tail++; + } else ldata->echo_cnt++; - } - ldata->echo_buf[new_byte_pos] = c; + *echo_buf_addr(ldata, ldata->echo_head++) = c; } /** From 862eeffef1b465a12412f4ae6e5987ae292c968d Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 10:04:23 -0400 Subject: [PATCH 0524/3400] n_tty: Replace echo_cnt with computed value Prepare for lockless echo_buf handling; compute current byte count of echo_buf from head and tail indices. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 18d72a0258ce..8406a23ee920 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -110,7 +110,6 @@ struct n_tty_data { unsigned char *echo_buf; size_t echo_head; size_t echo_tail; - unsigned int echo_cnt; /* protected by output lock */ unsigned int column; @@ -336,7 +335,7 @@ static void reset_buffer_flags(struct n_tty_data *ldata) ldata->read_head = ldata->canon_head = ldata->read_tail = 0; mutex_lock(&ldata->echo_lock); - ldata->echo_head = ldata->echo_tail = ldata->echo_cnt = 0; + ldata->echo_head = ldata->echo_tail = 0; mutex_unlock(&ldata->echo_lock); ldata->erasing = 0; @@ -654,7 +653,7 @@ static void process_echoes(struct tty_struct *tty) size_t tail; unsigned char c; - if (!ldata->echo_cnt) + if (ldata->echo_head == ldata->echo_tail) return; mutex_lock(&ldata->output_lock); @@ -663,7 +662,7 @@ static void process_echoes(struct tty_struct *tty) space = tty_write_room(tty); tail = ldata->echo_tail; - nr = ldata->echo_cnt; + nr = ldata->echo_head - ldata->echo_tail; while (nr > 0) { c = echo_buf(ldata, tail); if (c == ECHO_OP_START) { @@ -779,7 +778,6 @@ static void process_echoes(struct tty_struct *tty) } ldata->echo_tail = tail; - ldata->echo_cnt = nr; mutex_unlock(&ldata->echo_lock); mutex_unlock(&ldata->output_lock); @@ -800,24 +798,20 @@ static void process_echoes(struct tty_struct *tty) static void add_echo_byte(unsigned char c, struct n_tty_data *ldata) { - if (ldata->echo_cnt == N_TTY_BUF_SIZE) { + if (ldata->echo_head - ldata->echo_tail == N_TTY_BUF_SIZE) { size_t head = ldata->echo_head; /* * Since the buffer start position needs to be advanced, * be sure to step by a whole operation byte group. */ if (echo_buf(ldata, head) == ECHO_OP_START) { - if (echo_buf(ldata, head + 1) == ECHO_OP_ERASE_TAB) { + if (echo_buf(ldata, head + 1) == ECHO_OP_ERASE_TAB) ldata->echo_tail += 3; - ldata->echo_cnt -= 2; - } else { + else ldata->echo_tail += 2; - ldata->echo_cnt -= 1; - } } else ldata->echo_tail++; - } else - ldata->echo_cnt++; + } *echo_buf_addr(ldata, ldata->echo_head++) = c; } From 17bd79074003d73f2207289b9d3ce0553d000856 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 10:04:24 -0400 Subject: [PATCH 0525/3400] n_tty: Remove echo_lock Adding data to echo_buf (via add_echo_byte()) is guaranteed to be single-threaded, since all callers are from the n_tty_receive_buf() path. Processing the echo_buf can be called from either the n_tty_receive_buf() path or the n_tty_write() path; however, these callers are already serialized by output_lock. Publish cumulative echo_head changes to echo_commit; process echo_buf from echo_tail to echo_commit; remove echo_lock. On echo_buf overrun, claim output_lock to serialize changes to echo_tail. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 75 +++++++++++++++++---------------------------- 1 file changed, 28 insertions(+), 47 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 8406a23ee920..3b499451b7ed 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -106,10 +106,10 @@ struct n_tty_data { /* consumer-published */ size_t read_tail; - /* protected by echo_lock */ unsigned char *echo_buf; size_t echo_head; size_t echo_tail; + size_t echo_commit; /* protected by output lock */ unsigned int column; @@ -117,7 +117,6 @@ struct n_tty_data { struct mutex atomic_read_lock; struct mutex output_lock; - struct mutex echo_lock; }; static inline size_t read_cnt(struct n_tty_data *ldata) @@ -333,10 +332,7 @@ static void put_tty_queue(unsigned char c, struct n_tty_data *ldata) static void reset_buffer_flags(struct n_tty_data *ldata) { ldata->read_head = ldata->canon_head = ldata->read_tail = 0; - - mutex_lock(&ldata->echo_lock); - ldata->echo_head = ldata->echo_tail = 0; - mutex_unlock(&ldata->echo_lock); + ldata->echo_head = ldata->echo_tail = ldata->echo_commit = 0; ldata->erasing = 0; bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE); @@ -642,8 +638,7 @@ break_out: * are prioritized. Also, when control characters are echoed with a * prefixed "^", the pair is treated atomically and thus not separated. * - * Locking: output_lock to protect column state and space left, - * echo_lock to protect the echo buffer + * Locking: output_lock to protect column state and space left */ static void process_echoes(struct tty_struct *tty) @@ -653,16 +648,15 @@ static void process_echoes(struct tty_struct *tty) size_t tail; unsigned char c; - if (ldata->echo_head == ldata->echo_tail) + if (ldata->echo_commit == ldata->echo_tail) return; mutex_lock(&ldata->output_lock); - mutex_lock(&ldata->echo_lock); space = tty_write_room(tty); tail = ldata->echo_tail; - nr = ldata->echo_head - ldata->echo_tail; + nr = ldata->echo_commit - ldata->echo_tail; while (nr > 0) { c = echo_buf(ldata, tail); if (c == ECHO_OP_START) { @@ -779,13 +773,21 @@ static void process_echoes(struct tty_struct *tty) ldata->echo_tail = tail; - mutex_unlock(&ldata->echo_lock); mutex_unlock(&ldata->output_lock); if (tty->ops->flush_chars) tty->ops->flush_chars(tty); } +static void commit_echoes(struct tty_struct *tty) +{ + struct n_tty_data *ldata = tty->disc_data; + + smp_mb(); + ldata->echo_commit = ldata->echo_head; + process_echoes(tty); +} + /** * add_echo_byte - add a byte to the echo buffer * @c: unicode byte to echo @@ -793,13 +795,16 @@ static void process_echoes(struct tty_struct *tty) * * Add a character or operation byte to the echo buffer. * - * Should be called under the echo lock to protect the echo buffer. + * Locks: may claim output_lock to prevent concurrent modify of + * echo_tail by process_echoes(). */ static void add_echo_byte(unsigned char c, struct n_tty_data *ldata) { if (ldata->echo_head - ldata->echo_tail == N_TTY_BUF_SIZE) { size_t head = ldata->echo_head; + + mutex_lock(&ldata->output_lock); /* * Since the buffer start position needs to be advanced, * be sure to step by a whole operation byte group. @@ -811,6 +816,7 @@ static void add_echo_byte(unsigned char c, struct n_tty_data *ldata) ldata->echo_tail += 2; } else ldata->echo_tail++; + mutex_unlock(&ldata->output_lock); } *echo_buf_addr(ldata, ldata->echo_head++) = c; @@ -821,16 +827,12 @@ static void add_echo_byte(unsigned char c, struct n_tty_data *ldata) * @ldata: n_tty data * * Add an operation to the echo buffer to move back one column. - * - * Locking: echo_lock to protect the echo buffer */ static void echo_move_back_col(struct n_tty_data *ldata) { - mutex_lock(&ldata->echo_lock); add_echo_byte(ECHO_OP_START, ldata); add_echo_byte(ECHO_OP_MOVE_BACK_COL, ldata); - mutex_unlock(&ldata->echo_lock); } /** @@ -839,16 +841,12 @@ static void echo_move_back_col(struct n_tty_data *ldata) * * Add an operation to the echo buffer to set the canon column * to the current column. - * - * Locking: echo_lock to protect the echo buffer */ static void echo_set_canon_col(struct n_tty_data *ldata) { - mutex_lock(&ldata->echo_lock); add_echo_byte(ECHO_OP_START, ldata); add_echo_byte(ECHO_OP_SET_CANON_COL, ldata); - mutex_unlock(&ldata->echo_lock); } /** @@ -864,15 +862,11 @@ static void echo_set_canon_col(struct n_tty_data *ldata) * of input. This information will be used later, along with * canon column (if applicable), to go back the correct number * of columns. - * - * Locking: echo_lock to protect the echo buffer */ static void echo_erase_tab(unsigned int num_chars, int after_tab, struct n_tty_data *ldata) { - mutex_lock(&ldata->echo_lock); - add_echo_byte(ECHO_OP_START, ldata); add_echo_byte(ECHO_OP_ERASE_TAB, ldata); @@ -884,8 +878,6 @@ static void echo_erase_tab(unsigned int num_chars, int after_tab, num_chars |= 0x80; add_echo_byte(num_chars, ldata); - - mutex_unlock(&ldata->echo_lock); } /** @@ -897,20 +889,16 @@ static void echo_erase_tab(unsigned int num_chars, int after_tab, * L_ECHO(tty) is true. Called from the driver receive_buf path. * * This variant does not treat control characters specially. - * - * Locking: echo_lock to protect the echo buffer */ static void echo_char_raw(unsigned char c, struct n_tty_data *ldata) { - mutex_lock(&ldata->echo_lock); if (c == ECHO_OP_START) { add_echo_byte(ECHO_OP_START, ldata); add_echo_byte(ECHO_OP_START, ldata); } else { add_echo_byte(c, ldata); } - mutex_unlock(&ldata->echo_lock); } /** @@ -923,16 +911,12 @@ static void echo_char_raw(unsigned char c, struct n_tty_data *ldata) * * This variant tags control characters to be echoed as "^X" * (where X is the letter representing the control char). - * - * Locking: echo_lock to protect the echo buffer */ static void echo_char(unsigned char c, struct tty_struct *tty) { struct n_tty_data *ldata = tty->disc_data; - mutex_lock(&ldata->echo_lock); - if (c == ECHO_OP_START) { add_echo_byte(ECHO_OP_START, ldata); add_echo_byte(ECHO_OP_START, ldata); @@ -941,8 +925,6 @@ static void echo_char(unsigned char c, struct tty_struct *tty) add_echo_byte(ECHO_OP_START, ldata); add_echo_byte(c, ldata); } - - mutex_unlock(&ldata->echo_lock); } /** @@ -1284,7 +1266,7 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) if (ldata->canon_head == ldata->read_head) echo_set_canon_col(ldata); echo_char(c, tty); - process_echoes(tty); + commit_echoes(tty); } if (parmrk) put_tty_queue(c, ldata); @@ -1295,7 +1277,7 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) if (I_IXON(tty)) { if (c == START_CHAR(tty)) { start_tty(tty); - process_echoes(tty); + commit_echoes(tty); return; } if (c == STOP_CHAR(tty)) { @@ -1326,7 +1308,7 @@ send_signal: start_tty(tty); if (L_ECHO(tty)) { echo_char(c, tty); - process_echoes(tty); + commit_echoes(tty); } isig(signal, tty); return; @@ -1345,7 +1327,7 @@ send_signal: if (c == ERASE_CHAR(tty) || c == KILL_CHAR(tty) || (c == WERASE_CHAR(tty) && L_IEXTEN(tty))) { eraser(c, tty); - process_echoes(tty); + commit_echoes(tty); return; } if (c == LNEXT_CHAR(tty) && L_IEXTEN(tty)) { @@ -1355,7 +1337,7 @@ send_signal: if (L_ECHOCTL(tty)) { echo_char_raw('^', ldata); echo_char_raw('\b', ldata); - process_echoes(tty); + commit_echoes(tty); } } return; @@ -1371,7 +1353,7 @@ send_signal: echo_char(read_buf(ldata, tail), tty); tail++; } - process_echoes(tty); + commit_echoes(tty); return; } if (c == '\n') { @@ -1382,7 +1364,7 @@ send_signal: } if (L_ECHO(tty) || L_ECHONL(tty)) { echo_char_raw('\n', ldata); - process_echoes(tty); + commit_echoes(tty); } goto handle_newline; } @@ -1411,7 +1393,7 @@ send_signal: if (ldata->canon_head == ldata->read_head) echo_set_canon_col(ldata); echo_char(c, tty); - process_echoes(tty); + commit_echoes(tty); } /* * XXX does PARMRK doubling happen for @@ -1448,7 +1430,7 @@ handle_newline: echo_set_canon_col(ldata); echo_char(c, tty); } - process_echoes(tty); + commit_echoes(tty); } if (parmrk) @@ -1713,7 +1695,6 @@ static int n_tty_open(struct tty_struct *tty) ldata->overrun_time = jiffies; mutex_init(&ldata->atomic_read_lock); mutex_init(&ldata->output_lock); - mutex_init(&ldata->echo_lock); /* These are ugly. Currently a malloc failure here can panic */ ldata->read_buf = kzalloc(N_TTY_BUF_SIZE, GFP_KERNEL); From 019ebdf9f26fd2e43b9e1af576835183e95dc82e Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 10:04:25 -0400 Subject: [PATCH 0526/3400] n_tty: Eliminate echo_commit memory barrier Use output_lock mutex as a memory barrier when storing echo_commit. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 3b499451b7ed..0f76b9096840 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -638,21 +638,16 @@ break_out: * are prioritized. Also, when control characters are echoed with a * prefixed "^", the pair is treated atomically and thus not separated. * - * Locking: output_lock to protect column state and space left + * Locking: callers must hold output_lock */ -static void process_echoes(struct tty_struct *tty) +static void __process_echoes(struct tty_struct *tty) { struct n_tty_data *ldata = tty->disc_data; int space, nr; size_t tail; unsigned char c; - if (ldata->echo_commit == ldata->echo_tail) - return; - - mutex_lock(&ldata->output_lock); - space = tty_write_room(tty); tail = ldata->echo_tail; @@ -772,20 +767,34 @@ static void process_echoes(struct tty_struct *tty) } ldata->echo_tail = tail; - - mutex_unlock(&ldata->output_lock); - - if (tty->ops->flush_chars) - tty->ops->flush_chars(tty); } static void commit_echoes(struct tty_struct *tty) { struct n_tty_data *ldata = tty->disc_data; - smp_mb(); + mutex_lock(&ldata->output_lock); ldata->echo_commit = ldata->echo_head; - process_echoes(tty); + __process_echoes(tty); + mutex_unlock(&ldata->output_lock); + + if (tty->ops->flush_chars) + tty->ops->flush_chars(tty); +} + +static void process_echoes(struct tty_struct *tty) +{ + struct n_tty_data *ldata = tty->disc_data; + + if (!L_ECHO(tty) || ldata->echo_commit == ldata->echo_tail) + return; + + mutex_lock(&ldata->output_lock); + __process_echoes(tty); + mutex_unlock(&ldata->output_lock); + + if (tty->ops->flush_chars) + tty->ops->flush_chars(tty); } /** From cbfd0340ae1993378fd47179db949e050e16e697 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 10:04:26 -0400 Subject: [PATCH 0527/3400] n_tty: Process echoes in blocks Byte-by-byte echo output is painfully slow, requiring a lock/unlock cycle for every input byte. Instead, perform the echo output in blocks of 256 characters, and at least once per flip buffer receive. Enough space is reserved in the echo buffer to guarantee a full block can be saved without overrunning the echo output. Overrun is prevented by discarding the oldest echoes until enough space exists in the echo buffer to receive at least a full block of new echoes. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 70 ++++++++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 23 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 0f76b9096840..20983afb6086 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -74,6 +74,11 @@ #define ECHO_OP_SET_CANON_COL 0x81 #define ECHO_OP_ERASE_TAB 0x82 +#define ECHO_COMMIT_WATERMARK 256 +#define ECHO_BLOCK 256 +#define ECHO_DISCARD_WATERMARK N_TTY_BUF_SIZE - (ECHO_BLOCK + 32) + + #undef N_TTY_TRACE #ifdef N_TTY_TRACE # define n_tty_trace(f, args...) trace_printk(f, ##args) @@ -766,15 +771,40 @@ static void __process_echoes(struct tty_struct *tty) } } + /* If the echo buffer is nearly full (so that the possibility exists + * of echo overrun before the next commit), then discard enough + * data at the tail to prevent a subsequent overrun */ + while (ldata->echo_commit - tail >= ECHO_DISCARD_WATERMARK) { + if (echo_buf(ldata, tail == ECHO_OP_START)) { + if (echo_buf(ldata, tail) == ECHO_OP_ERASE_TAB) + tail += 3; + else + tail += 2; + } else + tail++; + } + ldata->echo_tail = tail; } static void commit_echoes(struct tty_struct *tty) { struct n_tty_data *ldata = tty->disc_data; + size_t nr, old; + size_t head; + + head = ldata->echo_head; + old = ldata->echo_commit - ldata->echo_tail; + + /* Process committed echoes if the accumulated # of bytes + * is over the threshold (and try again each time another + * block is accumulated) */ + nr = head - ldata->echo_tail; + if (nr < ECHO_COMMIT_WATERMARK || (nr % ECHO_BLOCK > old % ECHO_BLOCK)) + return; mutex_lock(&ldata->output_lock); - ldata->echo_commit = ldata->echo_head; + ldata->echo_commit = head; __process_echoes(tty); mutex_unlock(&ldata->output_lock); @@ -797,37 +827,29 @@ static void process_echoes(struct tty_struct *tty) tty->ops->flush_chars(tty); } +static void flush_echoes(struct tty_struct *tty) +{ + struct n_tty_data *ldata = tty->disc_data; + + if (!L_ECHO(tty) || ldata->echo_commit == ldata->echo_head) + return; + + mutex_lock(&ldata->output_lock); + ldata->echo_commit = ldata->echo_head; + __process_echoes(tty); + mutex_unlock(&ldata->output_lock); +} + /** * add_echo_byte - add a byte to the echo buffer * @c: unicode byte to echo * @ldata: n_tty data * * Add a character or operation byte to the echo buffer. - * - * Locks: may claim output_lock to prevent concurrent modify of - * echo_tail by process_echoes(). */ -static void add_echo_byte(unsigned char c, struct n_tty_data *ldata) +static inline void add_echo_byte(unsigned char c, struct n_tty_data *ldata) { - if (ldata->echo_head - ldata->echo_tail == N_TTY_BUF_SIZE) { - size_t head = ldata->echo_head; - - mutex_lock(&ldata->output_lock); - /* - * Since the buffer start position needs to be advanced, - * be sure to step by a whole operation byte group. - */ - if (echo_buf(ldata, head) == ECHO_OP_START) { - if (echo_buf(ldata, head + 1) == ECHO_OP_ERASE_TAB) - ldata->echo_tail += 3; - else - ldata->echo_tail += 2; - } else - ldata->echo_tail++; - mutex_unlock(&ldata->output_lock); - } - *echo_buf_addr(ldata, ldata->echo_head++) = c; } @@ -1515,6 +1537,8 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, break; } } + + flush_echoes(tty); if (tty->ops->flush_chars) tty->ops->flush_chars(tty); } From bc5b1ec5860a9bf52842be4a3a9d96e19f06c11d Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 10:04:27 -0400 Subject: [PATCH 0528/3400] n_tty: Only flush echo output if actually output Don't have the driver flush received echoes if no echoes were actually output. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 20983afb6086..59f3f10f37f3 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -646,14 +646,14 @@ break_out: * Locking: callers must hold output_lock */ -static void __process_echoes(struct tty_struct *tty) +static size_t __process_echoes(struct tty_struct *tty) { struct n_tty_data *ldata = tty->disc_data; - int space, nr; + int space, old_space; size_t tail; unsigned char c; - space = tty_write_room(tty); + old_space = space = tty_write_room(tty); tail = ldata->echo_tail; nr = ldata->echo_commit - ldata->echo_tail; @@ -785,12 +785,13 @@ static void __process_echoes(struct tty_struct *tty) } ldata->echo_tail = tail; + return old_space - space; } static void commit_echoes(struct tty_struct *tty) { struct n_tty_data *ldata = tty->disc_data; - size_t nr, old; + size_t nr, old, echoed; size_t head; head = ldata->echo_head; @@ -805,25 +806,26 @@ static void commit_echoes(struct tty_struct *tty) mutex_lock(&ldata->output_lock); ldata->echo_commit = head; - __process_echoes(tty); + echoed = __process_echoes(tty); mutex_unlock(&ldata->output_lock); - if (tty->ops->flush_chars) + if (echoed && tty->ops->flush_chars) tty->ops->flush_chars(tty); } static void process_echoes(struct tty_struct *tty) { struct n_tty_data *ldata = tty->disc_data; + size_t echoed; if (!L_ECHO(tty) || ldata->echo_commit == ldata->echo_tail) return; mutex_lock(&ldata->output_lock); - __process_echoes(tty); + echoed = __process_echoes(tty); mutex_unlock(&ldata->output_lock); - if (tty->ops->flush_chars) + if (echoed && tty->ops->flush_chars) tty->ops->flush_chars(tty); } From 29c7c5ca36d9c132cf9c37a09bc43626e790fb4c Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 10:04:28 -0400 Subject: [PATCH 0529/3400] n_tty: Eliminate counter in __process_echoes Since neither echo_commit nor echo_tail can change for the duration of __process_echoes loop, substitute index comparison for the snapshot counter. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 59f3f10f37f3..7f15b269cf3e 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -656,8 +656,7 @@ static size_t __process_echoes(struct tty_struct *tty) old_space = space = tty_write_room(tty); tail = ldata->echo_tail; - nr = ldata->echo_commit - ldata->echo_tail; - while (nr > 0) { + while (ldata->echo_commit != tail) { c = echo_buf(ldata, tail); if (c == ECHO_OP_START) { unsigned char op; @@ -701,20 +700,17 @@ static size_t __process_echoes(struct tty_struct *tty) ldata->column--; } tail += 3; - nr -= 3; break; case ECHO_OP_SET_CANON_COL: ldata->canon_column = ldata->column; tail += 2; - nr -= 2; break; case ECHO_OP_MOVE_BACK_COL: if (ldata->column > 0) ldata->column--; tail += 2; - nr -= 2; break; case ECHO_OP_START: @@ -727,7 +723,6 @@ static size_t __process_echoes(struct tty_struct *tty) ldata->column++; space--; tail += 2; - nr -= 2; break; default: @@ -749,7 +744,6 @@ static size_t __process_echoes(struct tty_struct *tty) ldata->column += 2; space -= 2; tail += 2; - nr -= 2; } if (no_space_left) @@ -767,7 +761,6 @@ static size_t __process_echoes(struct tty_struct *tty) space -= 1; } tail += 1; - nr -= 1; } } From 9dfd16ddea9bdbc8343340e543732db0a467ae32 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 10:04:29 -0400 Subject: [PATCH 0530/3400] n_tty: Avoid false-sharing echo buffer indices Separate the head & commit indices from the tail index to avoid cache-line contention (so called 'false-sharing') between concurrent threads. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 7f15b269cf3e..d4d71350a71d 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -90,6 +90,8 @@ struct n_tty_data { /* producer-published */ size_t read_head; size_t canon_head; + size_t echo_head; + size_t echo_commit; DECLARE_BITMAP(process_char_map, 256); /* private to n_tty_receive_overrun (single-threaded) */ @@ -105,20 +107,17 @@ struct n_tty_data { /* shared by producer and consumer */ char *read_buf; DECLARE_BITMAP(read_flags, N_TTY_BUF_SIZE); + unsigned char *echo_buf; int minimum_to_wake; /* consumer-published */ size_t read_tail; - unsigned char *echo_buf; - size_t echo_head; - size_t echo_tail; - size_t echo_commit; - /* protected by output lock */ unsigned int column; unsigned int canon_column; + size_t echo_tail; struct mutex atomic_read_lock; struct mutex output_lock; From 40d5e0905a03601d40cd4e46b8690093c2355d03 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 10:21:17 -0400 Subject: [PATCH 0531/3400] n_tty: Fix EOF push handling In canonical mode, an EOF which is not the first character of the line causes read() to complete and return the number of characters read so far (commonly referred to as EOF push). However, if the previous read() returned because the user buffer was full _and_ the next character is an EOF not at the beginning of the line, read() must not return 0, thus mistakenly indicating the end-of-file condition. The TTY_PUSH flag is used to indicate an EOF was received which is not at the beginning of the line. Because the EOF push condition is evaluated by a thread other than the read(), multiple EOF pushes can cause a premature end-of-file to be indicated. Instead, discover the 'EOF push as first read character' condition from the read() thread itself, and restart the i/o loop if detected. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 34 +++++++++++++++++----------------- drivers/tty/tty_io.c | 1 - include/linux/tty.h | 1 - 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index d4d71350a71d..25aaf1afa221 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -113,6 +113,7 @@ struct n_tty_data { /* consumer-published */ size_t read_tail; + size_t line_start; /* protected by output lock */ unsigned int column; @@ -337,6 +338,7 @@ static void reset_buffer_flags(struct n_tty_data *ldata) { ldata->read_head = ldata->canon_head = ldata->read_tail = 0; ldata->echo_head = ldata->echo_tail = ldata->echo_commit = 0; + ldata->line_start = 0; ldata->erasing = 0; bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE); @@ -1396,8 +1398,6 @@ send_signal: if (c == EOF_CHAR(tty)) { if (read_cnt(ldata) >= N_TTY_BUF_SIZE) return; - if (ldata->canon_head != ldata->read_head) - set_bit(TTY_PUSH, &tty->flags); c = __DISABLED_CHAR; goto handle_newline; } @@ -1604,6 +1604,7 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old) canon_change = (old->c_lflag ^ tty->termios.c_lflag) & ICANON; if (canon_change) { bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE); + ldata->line_start = 0; ldata->canon_head = ldata->read_tail; ldata->erasing = 0; ldata->lnext = 0; @@ -1837,6 +1838,7 @@ static int canon_copy_from_read_buf(struct tty_struct *tty, size_t eol; size_t tail; int ret, found = 0; + bool eof_push = 0; /* N.B. avoid overrun if nr == 0 */ n = min(*nr, read_cnt(ldata)); @@ -1863,8 +1865,10 @@ static int canon_copy_from_read_buf(struct tty_struct *tty, n = (found + eol + size) & (N_TTY_BUF_SIZE - 1); c = n; - if (found && read_buf(ldata, eol) == __DISABLED_CHAR) + if (found && read_buf(ldata, eol) == __DISABLED_CHAR) { n--; + eof_push = !n && ldata->read_tail != ldata->line_start; + } n_tty_trace("%s: eol:%zu found:%d n:%zu c:%zu size:%zu more:%zu\n", __func__, eol, found, n, c, size, more); @@ -1887,9 +1891,11 @@ static int canon_copy_from_read_buf(struct tty_struct *tty, smp_mb__after_clear_bit(); ldata->read_tail += c; - if (found) + if (found) { + ldata->line_start = ldata->read_tail; tty_audit_push(tty); - return 0; + } + return eof_push ? -EAGAIN : 0; } extern ssize_t redirected_tty_write(struct file *, const char __user *, @@ -1964,12 +1970,10 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, int c; int minimum, time; ssize_t retval = 0; - ssize_t size; long timeout; unsigned long flags; int packet; -do_it_again: c = job_control(tty, file); if (c < 0) return c; @@ -2076,7 +2080,10 @@ do_it_again: if (ldata->icanon && !L_EXTPROC(tty)) { retval = canon_copy_from_read_buf(tty, &b, &nr); - if (retval) + if (retval == -EAGAIN) { + retval = 0; + continue; + } else if (retval) break; } else { int uncopied; @@ -2104,15 +2111,8 @@ do_it_again: ldata->minimum_to_wake = minimum; __set_current_state(TASK_RUNNING); - size = b - buf; - if (size) { - retval = size; - if (nr) - clear_bit(TTY_PUSH, &tty->flags); - } else if (test_and_clear_bit(TTY_PUSH, &tty->flags)) { - up_read(&tty->termios_rwsem); - goto do_it_again; - } + if (b - buf) + retval = b - buf; n_tty_set_room(tty); up_read(&tty->termios_rwsem); diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 1b32da6f6cdd..2174698dd6f7 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -664,7 +664,6 @@ static void __tty_hangup(struct tty_struct *tty, int exit_session) spin_lock_irq(&tty->ctrl_lock); clear_bit(TTY_THROTTLED, &tty->flags); - clear_bit(TTY_PUSH, &tty->flags); clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); put_pid(tty->session); put_pid(tty->pgrp); diff --git a/include/linux/tty.h b/include/linux/tty.h index 5fd5d6f1ebc4..554b732d8b55 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -304,7 +304,6 @@ struct tty_file_private { #define TTY_EXCLUSIVE 3 /* Exclusive open mode */ #define TTY_DEBUG 4 /* Debugging */ #define TTY_DO_WRITE_WAKEUP 5 /* Call write_wakeup after queuing new */ -#define TTY_PUSH 6 /* n_tty private */ #define TTY_CLOSING 7 /* ->close() in progress */ #define TTY_LDISC_OPEN 11 /* Line discipline is open */ #define TTY_PTY_LOCK 16 /* pty private */ From 8cb06c983822103da1cfe57b9901e60a00e61f67 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 10:21:18 -0400 Subject: [PATCH 0532/3400] n_tty: Remove alias ptrs in __receive_buf() The char and flag buffer local alias pointers, p and f, are unnecessary; remove them. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 25aaf1afa221..d6eba99785c4 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1485,8 +1485,7 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) { struct n_tty_data *ldata = tty->disc_data; - const unsigned char *p; - char *f, flags = TTY_NORMAL; + char flags = TTY_NORMAL; char buf[64]; if (ldata->real_raw) { @@ -1508,19 +1507,19 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, } else { int i; - for (i = count, p = cp, f = fp; i; i--, p++) { - if (f) - flags = *f++; + for (i = count; i; i--, cp++) { + if (fp) + flags = *fp++; switch (flags) { case TTY_NORMAL: - n_tty_receive_char(tty, *p); + n_tty_receive_char(tty, *cp); break; case TTY_BREAK: n_tty_receive_break(tty); break; case TTY_PARITY: case TTY_FRAME: - n_tty_receive_parity_error(tty, *p); + n_tty_receive_parity_error(tty, *cp); break; case TTY_OVERRUN: n_tty_receive_overrun(tty); From 20bafb3d23d108bc0a896eb8b7c1501f4f649b77 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 10:21:19 -0400 Subject: [PATCH 0533/3400] n_tty: Move buffers into n_tty_data Reduce pointer reloading and improve locality-of-reference; allocate read_buf and echo_buf within struct n_tty_data. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index d6eba99785c4..51cbdd22c18c 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -105,9 +105,9 @@ struct n_tty_data { unsigned char lnext:1, erasing:1, raw:1, real_raw:1, icanon:1; /* shared by producer and consumer */ - char *read_buf; + char read_buf[N_TTY_BUF_SIZE]; DECLARE_BITMAP(read_flags, N_TTY_BUF_SIZE); - unsigned char *echo_buf; + unsigned char echo_buf[N_TTY_BUF_SIZE]; int minimum_to_wake; @@ -1695,9 +1695,7 @@ static void n_tty_close(struct tty_struct *tty) if (tty->link) n_tty_packet_mode_flush(tty); - kfree(ldata->read_buf); - kfree(ldata->echo_buf); - kfree(ldata); + vfree(ldata); tty->disc_data = NULL; } @@ -1715,7 +1713,8 @@ static int n_tty_open(struct tty_struct *tty) { struct n_tty_data *ldata; - ldata = kzalloc(sizeof(*ldata), GFP_KERNEL); + /* Currently a malloc failure here can panic */ + ldata = vmalloc(sizeof(*ldata)); if (!ldata) goto err; @@ -1723,16 +1722,14 @@ static int n_tty_open(struct tty_struct *tty) mutex_init(&ldata->atomic_read_lock); mutex_init(&ldata->output_lock); - /* These are ugly. Currently a malloc failure here can panic */ - ldata->read_buf = kzalloc(N_TTY_BUF_SIZE, GFP_KERNEL); - ldata->echo_buf = kzalloc(N_TTY_BUF_SIZE, GFP_KERNEL); - if (!ldata->read_buf || !ldata->echo_buf) - goto err_free_bufs; - tty->disc_data = ldata; reset_buffer_flags(tty->disc_data); ldata->column = 0; + ldata->canon_column = 0; ldata->minimum_to_wake = 1; + ldata->num_overrun = 0; + ldata->no_room = 0; + ldata->lnext = 0; tty->closing = 0; /* indicate buffer work may resume */ clear_bit(TTY_LDISC_HALTED, &tty->flags); @@ -1740,10 +1737,6 @@ static int n_tty_open(struct tty_struct *tty) tty_unthrottle(tty); return 0; -err_free_bufs: - kfree(ldata->read_buf); - kfree(ldata->echo_buf); - kfree(ldata); err: return -ENOMEM; } From 1bb9d562856279a217a4e581a803dee9bb48a708 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 10:21:20 -0400 Subject: [PATCH 0534/3400] n_tty: Rename process_char_map to char_map Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 43 ++++++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 51cbdd22c18c..d598436d9bc6 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -92,7 +92,7 @@ struct n_tty_data { size_t canon_head; size_t echo_head; size_t echo_commit; - DECLARE_BITMAP(process_char_map, 256); + DECLARE_BITMAP(char_map, 256); /* private to n_tty_receive_overrun (single-threaded) */ unsigned long overrun_time; @@ -1278,7 +1278,7 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) * handle specially, do shortcut processing to speed things * up. */ - if (!test_bit(c, ldata->process_char_map) || ldata->lnext) { + if (!test_bit(c, ldata->char_map) || ldata->lnext) { ldata->lnext = 0; parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0; if (read_cnt(ldata) >= (N_TTY_BUF_SIZE - parmrk - 1)) { @@ -1618,41 +1618,38 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old) I_ICRNL(tty) || I_INLCR(tty) || L_ICANON(tty) || I_IXON(tty) || L_ISIG(tty) || L_ECHO(tty) || I_PARMRK(tty)) { - bitmap_zero(ldata->process_char_map, 256); + bitmap_zero(ldata->char_map, 256); if (I_IGNCR(tty) || I_ICRNL(tty)) - set_bit('\r', ldata->process_char_map); + set_bit('\r', ldata->char_map); if (I_INLCR(tty)) - set_bit('\n', ldata->process_char_map); + set_bit('\n', ldata->char_map); if (L_ICANON(tty)) { - set_bit(ERASE_CHAR(tty), ldata->process_char_map); - set_bit(KILL_CHAR(tty), ldata->process_char_map); - set_bit(EOF_CHAR(tty), ldata->process_char_map); - set_bit('\n', ldata->process_char_map); - set_bit(EOL_CHAR(tty), ldata->process_char_map); + set_bit(ERASE_CHAR(tty), ldata->char_map); + set_bit(KILL_CHAR(tty), ldata->char_map); + set_bit(EOF_CHAR(tty), ldata->char_map); + set_bit('\n', ldata->char_map); + set_bit(EOL_CHAR(tty), ldata->char_map); if (L_IEXTEN(tty)) { - set_bit(WERASE_CHAR(tty), - ldata->process_char_map); - set_bit(LNEXT_CHAR(tty), - ldata->process_char_map); - set_bit(EOL2_CHAR(tty), - ldata->process_char_map); + set_bit(WERASE_CHAR(tty), ldata->char_map); + set_bit(LNEXT_CHAR(tty), ldata->char_map); + set_bit(EOL2_CHAR(tty), ldata->char_map); if (L_ECHO(tty)) set_bit(REPRINT_CHAR(tty), - ldata->process_char_map); + ldata->char_map); } } if (I_IXON(tty)) { - set_bit(START_CHAR(tty), ldata->process_char_map); - set_bit(STOP_CHAR(tty), ldata->process_char_map); + set_bit(START_CHAR(tty), ldata->char_map); + set_bit(STOP_CHAR(tty), ldata->char_map); } if (L_ISIG(tty)) { - set_bit(INTR_CHAR(tty), ldata->process_char_map); - set_bit(QUIT_CHAR(tty), ldata->process_char_map); - set_bit(SUSP_CHAR(tty), ldata->process_char_map); + set_bit(INTR_CHAR(tty), ldata->char_map); + set_bit(QUIT_CHAR(tty), ldata->char_map); + set_bit(SUSP_CHAR(tty), ldata->char_map); } - clear_bit(__DISABLED_CHAR, ldata->process_char_map); + clear_bit(__DISABLED_CHAR, ldata->char_map); ldata->raw = 0; ldata->real_raw = 0; } else { From 781ad1c79379c723138945b633121a78e9e5485f Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 10:21:21 -0400 Subject: [PATCH 0535/3400] n_tty: Simplify __receive_buf loop count Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index d598436d9bc6..4f20bec011fb 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1505,21 +1505,19 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, memcpy(read_buf_addr(ldata, head), cp, n); ldata->read_head += n; } else { - int i; - - for (i = count; i; i--, cp++) { + while (count--) { if (fp) flags = *fp++; switch (flags) { case TTY_NORMAL: - n_tty_receive_char(tty, *cp); + n_tty_receive_char(tty, *cp++); break; case TTY_BREAK: n_tty_receive_break(tty); break; case TTY_PARITY: case TTY_FRAME: - n_tty_receive_parity_error(tty, *cp); + n_tty_receive_parity_error(tty, *cp++); break; case TTY_OVERRUN: n_tty_receive_overrun(tty); From 4a23a4df500f29603ee25995f9c1d3af79f7a994 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 10:21:22 -0400 Subject: [PATCH 0536/3400] n_tty: Factor 'real raw' receive_buf into standalone fn Convert to modal receive_buf() processing; factor real_raw receive_buf() into n_tty_receive_buf_real_raw(). Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 51 ++++++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 4f20bec011fb..f763f75b672b 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -242,7 +242,7 @@ static void n_tty_write_wakeup(struct tty_struct *tty) kill_fasync(&tty->fasync, SIGIO, POLL_OUT); } -static inline void n_tty_check_throttle(struct tty_struct *tty) +static void n_tty_check_throttle(struct tty_struct *tty) { if (tty->driver->type == TTY_DRIVER_TYPE_PTY) return; @@ -1481,6 +1481,28 @@ handle_newline: * publishes read_head and canon_head */ +static void +n_tty_receive_buf_real_raw(struct tty_struct *tty, const unsigned char *cp, + char *fp, int count) +{ + struct n_tty_data *ldata = tty->disc_data; + size_t n, head; + + head = ldata->read_head & (N_TTY_BUF_SIZE - 1); + n = N_TTY_BUF_SIZE - max(read_cnt(ldata), head); + n = min_t(size_t, count, n); + memcpy(read_buf_addr(ldata, head), cp, n); + ldata->read_head += n; + cp += n; + count -= n; + + head = ldata->read_head & (N_TTY_BUF_SIZE - 1); + n = N_TTY_BUF_SIZE - max(read_cnt(ldata), head); + n = min_t(size_t, count, n); + memcpy(read_buf_addr(ldata, head), cp, n); + ldata->read_head += n; +} + static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) { @@ -1488,23 +1510,9 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, char flags = TTY_NORMAL; char buf[64]; - if (ldata->real_raw) { - size_t n, head; - - head = ldata->read_head & (N_TTY_BUF_SIZE - 1); - n = N_TTY_BUF_SIZE - max(read_cnt(ldata), head); - n = min_t(size_t, count, n); - memcpy(read_buf_addr(ldata, head), cp, n); - ldata->read_head += n; - cp += n; - count -= n; - - head = ldata->read_head & (N_TTY_BUF_SIZE - 1); - n = N_TTY_BUF_SIZE - max(read_cnt(ldata), head); - n = min_t(size_t, count, n); - memcpy(read_buf_addr(ldata, head), cp, n); - ldata->read_head += n; - } else { + if (ldata->real_raw) + n_tty_receive_buf_real_raw(tty, cp, fp, count); + else { while (count--) { if (fp) flags = *fp++; @@ -1540,8 +1548,6 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, if (waitqueue_active(&tty->read_wait)) wake_up_interruptible(&tty->read_wait); } - - n_tty_check_throttle(tty); } static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, @@ -1549,6 +1555,7 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, { down_read(&tty->termios_rwsem); __receive_buf(tty, cp, fp, count); + n_tty_check_throttle(tty); up_read(&tty->termios_rwsem); } @@ -1564,8 +1571,10 @@ static int n_tty_receive_buf2(struct tty_struct *tty, const unsigned char *cp, if (!room) ldata->no_room = 1; count = min(count, room); - if (count) + if (count) { __receive_buf(tty, cp, fp, count); + n_tty_check_throttle(tty); + } up_read(&tty->termios_rwsem); From b0ac50be1f398ae1daedcf1ce71ac6b6409c88d2 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 10:21:23 -0400 Subject: [PATCH 0537/3400] n_tty: Factor signal char handling into separate fn Reduce the monolithic n_tty_receive_char() complexity; factor the handling of INTR_CHAR, QUIT_CHAR and SUSP_CHAR into n_tty_receive_signal_char(). Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 52 ++++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index f763f75b672b..68fc4c347970 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1219,6 +1219,26 @@ static inline void n_tty_receive_parity_error(struct tty_struct *tty, wake_up_interruptible(&tty->read_wait); } +static void +n_tty_receive_signal_char(struct tty_struct *tty, int signal, unsigned char c) +{ + if (!L_NOFLSH(tty)) { + /* flushing needs exclusive termios_rwsem */ + up_read(&tty->termios_rwsem); + n_tty_flush_buffer(tty); + tty_driver_flush_buffer(tty); + down_read(&tty->termios_rwsem); + } + if (I_IXON(tty)) + start_tty(tty); + if (L_ECHO(tty)) { + echo_char(c, tty); + commit_echoes(tty); + } + isig(signal, tty); + return; +} + /** * n_tty_receive_char - perform processing * @tty: terminal device @@ -1314,30 +1334,14 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) } if (L_ISIG(tty)) { - int signal; - signal = SIGINT; - if (c == INTR_CHAR(tty)) - goto send_signal; - signal = SIGQUIT; - if (c == QUIT_CHAR(tty)) - goto send_signal; - signal = SIGTSTP; - if (c == SUSP_CHAR(tty)) { -send_signal: - if (!L_NOFLSH(tty)) { - /* flushing needs exclusive termios_rwsem */ - up_read(&tty->termios_rwsem); - n_tty_flush_buffer(tty); - tty_driver_flush_buffer(tty); - down_read(&tty->termios_rwsem); - } - if (I_IXON(tty)) - start_tty(tty); - if (L_ECHO(tty)) { - echo_char(c, tty); - commit_echoes(tty); - } - isig(signal, tty); + if (c == INTR_CHAR(tty)) { + n_tty_receive_signal_char(tty, SIGINT, c); + return; + } else if (c == QUIT_CHAR(tty)) { + n_tty_receive_signal_char(tty, SIGQUIT, c); + return; + } else if (c == SUSP_CHAR(tty)) { + n_tty_receive_signal_char(tty, SIGTSTP, c); return; } } From d2f8d7abd1e7ac04a0b42df36b53fef00d5d73aa Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 10:21:24 -0400 Subject: [PATCH 0538/3400] n_tty: Factor flagged char handling into separate fn Prepare for modal receive_buf() handling; factor handling for TTY_BREAK, TTY_PARITY, TTY_FRAME and TTY_OVERRUN into n_tty_receive_char_flagged(). Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 50 ++++++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 68fc4c347970..6aa90332dd3e 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1468,6 +1468,29 @@ handle_newline: put_tty_queue(c, ldata); } +static void +n_tty_receive_char_flagged(struct tty_struct *tty, unsigned char c, char flag) +{ + char buf[64]; + + switch (flag) { + case TTY_BREAK: + n_tty_receive_break(tty); + break; + case TTY_PARITY: + case TTY_FRAME: + n_tty_receive_parity_error(tty, c); + break; + case TTY_OVERRUN: + n_tty_receive_overrun(tty); + break; + default: + printk(KERN_ERR "%s: unknown flag %d\n", + tty_name(tty, buf), flag); + break; + } +} + /** * n_tty_receive_buf - data receive * @tty: terminal device @@ -1511,34 +1534,19 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) { struct n_tty_data *ldata = tty->disc_data; - char flags = TTY_NORMAL; - char buf[64]; if (ldata->real_raw) n_tty_receive_buf_real_raw(tty, cp, fp, count); else { + char flag = TTY_NORMAL; + while (count--) { if (fp) - flags = *fp++; - switch (flags) { - case TTY_NORMAL: + flag = *fp++; + if (likely(flag == TTY_NORMAL)) n_tty_receive_char(tty, *cp++); - break; - case TTY_BREAK: - n_tty_receive_break(tty); - break; - case TTY_PARITY: - case TTY_FRAME: - n_tty_receive_parity_error(tty, *cp++); - break; - case TTY_OVERRUN: - n_tty_receive_overrun(tty); - break; - default: - printk(KERN_ERR "%s: unknown flag %d\n", - tty_name(tty, buf), flags); - break; - } + else + n_tty_receive_char_flagged(tty, *cp++, flag); } flush_echoes(tty); From 554117bdc8c245249f364ddcdbd65ae5701a5ead Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 10:21:25 -0400 Subject: [PATCH 0539/3400] n_tty: Factor raw mode receive_buf() into separate fn Convert to modal receive_buf() processing; factor raw mode per-char i/o into n_tty_receive_buf_raw(). Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 6aa90332dd3e..900ebbe0a7ab 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1259,11 +1259,6 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) struct n_tty_data *ldata = tty->disc_data; int parmrk; - if (ldata->raw) { - put_tty_queue(c, ldata); - return; - } - if (I_ISTRIP(tty)) c &= 0x7f; if (I_IUCLC(tty) && L_IEXTEN(tty)) @@ -1530,6 +1525,23 @@ n_tty_receive_buf_real_raw(struct tty_struct *tty, const unsigned char *cp, ldata->read_head += n; } +static void +n_tty_receive_buf_raw(struct tty_struct *tty, const unsigned char *cp, + char *fp, int count) +{ + struct n_tty_data *ldata = tty->disc_data; + char flag = TTY_NORMAL; + + while (count--) { + if (fp) + flag = *fp++; + if (likely(flag == TTY_NORMAL)) + put_tty_queue(*cp++, ldata); + else + n_tty_receive_char_flagged(tty, *cp++, flag); + } +} + static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) { @@ -1537,6 +1549,8 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, if (ldata->real_raw) n_tty_receive_buf_real_raw(tty, cp, fp, count); + else if (ldata->raw) + n_tty_receive_buf_raw(tty, cp, fp, count); else { char flag = TTY_NORMAL; From a1dd30e9b4c38a4a177106741b03ac6a55777286 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 10:21:26 -0400 Subject: [PATCH 0540/3400] n_tty: Special case EXTPROC receive_buf() as raw mode When EXTPROC is set without ISTRIP or IUCLC, processing is identical to raw mode; handle this receiving mode as a special-case of raw mode. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 900ebbe0a7ab..e9cfc77a1279 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1546,10 +1546,11 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) { struct n_tty_data *ldata = tty->disc_data; + bool preops = I_ISTRIP(tty) || (I_IUCLC(tty) && L_IEXTEN(tty)); if (ldata->real_raw) n_tty_receive_buf_real_raw(tty, cp, fp, count); - else if (ldata->raw) + else if (ldata->raw || (L_EXTPROC(tty) && !preops)) n_tty_receive_buf_raw(tty, cp, fp, count); else { char flag = TTY_NORMAL; From ad0cc7bafe498fb299043582e822fc4e74388edb Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 15 Jun 2013 10:21:27 -0400 Subject: [PATCH 0541/3400] n_tty: Factor tty->closing receive_buf() into separate fn Convert to modal receive_buf() processing; factor receive char processing when tty->closing into n_tty_receive_buf_closing(). Note that EXTPROC when ISTRIP or IUCLC is set continues to be handled by n_tty_receive_char(). Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 50 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 11 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index e9cfc77a1279..ed6c4e4d960a 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1276,17 +1276,6 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) process_echoes(tty); } - if (tty->closing) { - if (I_IXON(tty)) { - if (c == START_CHAR(tty)) { - start_tty(tty); - process_echoes(tty); - } else if (c == STOP_CHAR(tty)) - stop_tty(tty); - } - return; - } - /* * If the previous character was LNEXT, or we know that this * character is not one of the characters that we'll have to @@ -1463,6 +1452,27 @@ handle_newline: put_tty_queue(c, ldata); } +static inline void +n_tty_receive_char_closing(struct tty_struct *tty, unsigned char c) +{ + if (I_ISTRIP(tty)) + c &= 0x7f; + if (I_IUCLC(tty) && L_IEXTEN(tty)) + c = tolower(c); + + if (I_IXON(tty)) { + if (c == STOP_CHAR(tty)) + stop_tty(tty); + else if (c == START_CHAR(tty) || + (tty->stopped && !tty->flow_stopped && I_IXANY(tty) && + c != INTR_CHAR(tty) && c != QUIT_CHAR(tty) && + c != SUSP_CHAR(tty))) { + start_tty(tty); + process_echoes(tty); + } + } +} + static void n_tty_receive_char_flagged(struct tty_struct *tty, unsigned char c, char flag) { @@ -1542,6 +1552,22 @@ n_tty_receive_buf_raw(struct tty_struct *tty, const unsigned char *cp, } } +static void +n_tty_receive_buf_closing(struct tty_struct *tty, const unsigned char *cp, + char *fp, int count) +{ + char flag = TTY_NORMAL; + + while (count--) { + if (fp) + flag = *fp++; + if (likely(flag == TTY_NORMAL)) + n_tty_receive_char_closing(tty, *cp++); + else + n_tty_receive_char_flagged(tty, *cp++, flag); + } +} + static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) { @@ -1552,6 +1578,8 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, n_tty_receive_buf_real_raw(tty, cp, fp, count); else if (ldata->raw || (L_EXTPROC(tty) && !preops)) n_tty_receive_buf_raw(tty, cp, fp, count); + else if (tty->closing && !L_EXTPROC(tty)) + n_tty_receive_buf_closing(tty, cp, fp, count); else { char flag = TTY_NORMAL; From e5d950f024c05749da9cd64765b3daa0e2229f9f Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 23 Jul 2013 20:01:50 +0200 Subject: [PATCH 0542/3400] spi: bcm2835: don't check resource with devm_ioremap_resource devm_ioremap_resource does sanity checks on the given resource. No need to duplicate this in the driver. Signed-off-by: Wolfram Sang Signed-off-by: Mark Brown --- drivers/spi/spi-bcm2835.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index a4185e492321..7604c5204862 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -325,12 +325,6 @@ static int bcm2835_spi_probe(struct platform_device *pdev) init_completion(&bs->done); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "could not get memory resource\n"); - err = -ENODEV; - goto out_master_put; - } - bs->regs = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(bs->regs)) { err = PTR_ERR(bs->regs); From 900bfe33b6d46058c4dd64d4bff7f287baf2a34e Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 5 Jul 2013 18:53:22 +0100 Subject: [PATCH 0543/3400] spi/s3c64xx: Remove unused message queue Since the driver has been converted to use the core message pump code the only use of the messsage queue in the driver is a check to see if it is empty which will always succeed since nothing ever adds to the queue. Just remove the queue. Signed-off-by: Mark Brown Acked-by: Kukjin Kim --- drivers/spi/spi-s3c64xx.c | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 63e2070c6c14..3fb8c96ece41 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -172,7 +172,6 @@ struct s3c64xx_spi_port_config { * @master: Pointer to the SPI Protocol master. * @cntrlr_info: Platform specific data for the controller this driver manages. * @tgl_spi: Pointer to the last CS left untoggled by the cs_change hint. - * @queue: To log SPI xfer requests. * @lock: Controller specific lock. * @state: Set of FLAGS to indicate status. * @rx_dmach: Controller's DMA channel for Rx. @@ -193,7 +192,6 @@ struct s3c64xx_spi_driver_data { struct spi_master *master; struct s3c64xx_spi_info *cntrlr_info; struct spi_device *tgl_spi; - struct list_head queue; spinlock_t lock; unsigned long sfr_start; struct completion xfer_completion; @@ -1056,8 +1054,6 @@ static int s3c64xx_spi_setup(struct spi_device *spi) struct s3c64xx_spi_csinfo *cs = spi->controller_data; struct s3c64xx_spi_driver_data *sdd; struct s3c64xx_spi_info *sci; - struct spi_message *msg; - unsigned long flags; int err; sdd = spi_master_get_devdata(spi->master); @@ -1088,21 +1084,6 @@ static int s3c64xx_spi_setup(struct spi_device *spi) sci = sdd->cntrlr_info; - spin_lock_irqsave(&sdd->lock, flags); - - list_for_each_entry(msg, &sdd->queue, queue) { - /* Is some mssg is already queued for this device */ - if (msg->spi == spi) { - dev_err(&spi->dev, - "setup: attempt while mssg in queue!\n"); - spin_unlock_irqrestore(&sdd->lock, flags); - err = -EBUSY; - goto err_msgq; - } - } - - spin_unlock_irqrestore(&sdd->lock, flags); - pm_runtime_get_sync(&sdd->pdev->dev); /* Check if we can provide the requested rate */ @@ -1149,7 +1130,6 @@ setup_exit: /* setup() returns with device de-selected */ disable_cs(sdd, spi); -err_msgq: gpio_free(cs->line); spi_set_ctldata(spi, NULL); @@ -1442,7 +1422,6 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) spin_lock_init(&sdd->lock); init_completion(&sdd->xfer_completion); - INIT_LIST_HEAD(&sdd->queue); ret = devm_request_irq(&pdev->dev, irq, s3c64xx_spi_irq, 0, "spi-s3c64xx", sdd); From db0606ecd635de0522191e0200868a92ffc18b4d Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Mon, 15 Jul 2013 15:11:57 +0900 Subject: [PATCH 0544/3400] spi: s3c64xx: fix checkpatch error and warnings Fix the following checkpatch error and warnings: ERROR: "(foo*)" should be "(foo *)" WARNING: line over 80 characters WARNING: quoted string split across lines Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 3fb8c96ece41..61cffaff78fc 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -336,8 +336,10 @@ static int acquire_dma(struct s3c64xx_spi_driver_data *sdd) req.cap = DMA_SLAVE; req.client = &s3c64xx_spi_dma_client; - sdd->rx_dma.ch = (void *)sdd->ops->request(sdd->rx_dma.dmach, &req, dev, "rx"); - sdd->tx_dma.ch = (void *)sdd->ops->request(sdd->tx_dma.dmach, &req, dev, "tx"); + sdd->rx_dma.ch = (void *)sdd->ops->request(sdd->rx_dma.dmach, + &req, dev, "rx"); + sdd->tx_dma.ch = (void *)sdd->ops->request(sdd->tx_dma.dmach, + &req, dev, "tx"); return 1; } @@ -440,7 +442,7 @@ static int s3c64xx_spi_prepare_transfer(struct spi_master *spi) /* Acquire DMA channels */ sdd->rx_dma.ch = dma_request_slave_channel_compat(mask, filter, - (void*)sdd->rx_dma.dmach, dev, "rx"); + (void *)sdd->rx_dma.dmach, dev, "rx"); if (!sdd->rx_dma.ch) { dev_err(dev, "Failed to get RX DMA channel\n"); ret = -EBUSY; @@ -448,7 +450,7 @@ static int s3c64xx_spi_prepare_transfer(struct spi_master *spi) } sdd->tx_dma.ch = dma_request_slave_channel_compat(mask, filter, - (void*)sdd->tx_dma.dmach, dev, "tx"); + (void *)sdd->tx_dma.dmach, dev, "tx"); if (!sdd->tx_dma.ch) { dev_err(dev, "Failed to get TX DMA channel\n"); ret = -EBUSY; @@ -1344,16 +1346,14 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) if (!sdd->pdev->dev.of_node) { res = platform_get_resource(pdev, IORESOURCE_DMA, 0); if (!res) { - dev_warn(&pdev->dev, "Unable to get SPI tx dma " - "resource. Switching to poll mode\n"); + dev_warn(&pdev->dev, "Unable to get SPI tx dma resource. Switching to poll mode\n"); sdd->port_conf->quirks = S3C64XX_SPI_QUIRK_POLL; } else sdd->tx_dma.dmach = res->start; res = platform_get_resource(pdev, IORESOURCE_DMA, 1); if (!res) { - dev_warn(&pdev->dev, "Unable to get SPI rx dma " - "resource. Switching to poll mode\n"); + dev_warn(&pdev->dev, "Unable to get SPI rx dma resource. Switching to poll mode\n"); sdd->port_conf->quirks = S3C64XX_SPI_QUIRK_POLL; } else sdd->rx_dma.dmach = res->start; From c65bc4a8df3cd806e1868992bbc818b1267072d5 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 16 Jul 2013 08:53:33 +0900 Subject: [PATCH 0545/3400] spi: s3c64xx: fix printk warnings Fix the following build warnings when LPAE is enabled: drivers/spi/spi-s3c64xx.c:1466:2: warning: format '%x' expects argument of type 'unsigned int', but argument 4 has type 'resource_size_t' [-Wformat] drivers/spi/spi-s3c64xx.c:1466:2: warning: format '%x' expects argument of type 'unsigned int', but argument 5 has type 'resource_size_t' [-Wformat] Use vsprintf extension %pR to format resource. Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 61cffaff78fc..702a5362aaac 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -1443,8 +1443,8 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "Samsung SoC SPI Driver loaded for Bus SPI-%d with %d Slaves attached\n", sdd->port_id, master->num_chipselect); - dev_dbg(&pdev->dev, "\tIOmem=[0x%x-0x%x]\tDMA=[Rx-%d, Tx-%d]\n", - mem_res->end, mem_res->start, + dev_dbg(&pdev->dev, "\tIOmem=[%pR]\tDMA=[Rx-%d, Tx-%d]\n", + mem_res, sdd->rx_dma.dmach, sdd->tx_dma.dmach); pm_runtime_enable(&pdev->dev); From b998aca8ade221d592c8fc6b00687f2c4034d918 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Wed, 17 Jul 2013 17:54:11 +0900 Subject: [PATCH 0546/3400] spi: s3c64xx: fix casting warning sdd->ops->request is unsigned int, not unsigned long. Also, sdd->rx_dma.ch is a 'struct dma_chan *'. Thus, (void *) is converted to (struct dma_chan *)(unsigned long), in order to fix possible sparse warnings. Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 702a5362aaac..c9d0b1273be9 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -336,10 +336,10 @@ static int acquire_dma(struct s3c64xx_spi_driver_data *sdd) req.cap = DMA_SLAVE; req.client = &s3c64xx_spi_dma_client; - sdd->rx_dma.ch = (void *)sdd->ops->request(sdd->rx_dma.dmach, - &req, dev, "rx"); - sdd->tx_dma.ch = (void *)sdd->ops->request(sdd->tx_dma.dmach, - &req, dev, "tx"); + sdd->rx_dma.ch = (struct dma_chan *)(unsigned long)sdd->ops->request( + sdd->rx_dma.dmach, &req, dev, "rx"); + sdd->tx_dma.ch = (struct dma_chan *)(unsigned long)sdd->ops->request( + sdd->tx_dma.dmach, &req, dev, "tx"); return 1; } From 9234c636c52df48a3cf280428a1d04077eef21db Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 16 Jul 2013 16:34:39 +0800 Subject: [PATCH 0547/3400] regulator: as3711: Convert to use linear ranges The SD, ALDO, and DLDO vlotage tables are composed of linear ranges. This patch converts as3711 to use newly introduced helpers for multiple linear ranges. Below is the voltage table on datasheet: SD: 00h: DC/DC powered down 01h-40h: Volt = 0.6V + sdx_vsel * 12.5mV 41h-70h: Volt = 1.4V + (sdx_vsel - 40h) * 25mV 71h-7Fh: Volt = 2.6V + (sdx_vsel - 70h) * 50mV ALDO: 0h-0Fh: 1.2V + ldox_vsel * 50mV 10h-1Fh: 1.8V + (ldox_vsel - 10h) * 100mV DLDO: 00h-10h: Volt = 0.9V + ldox_vsel * 50mV 11h-1fh: Do not use 20h-3fh: Volt = 1.75V + (ldox_vsel - 20h) * 50mV Note, when convert to use linear ranges APIs, the equation for SD needs below adjustment because the linear ranges APIs wiil substract range->min_sel when apply the equation. SD ( the equation to be used with linear ranges APIs ) 01h-40h: Volt = 0.6125V + (sdx_vsel - 1h) * 12.5mV 41h-70h: Volt = 1.425V + (sdx_vsel - 41h) * 25mV 71h-7Fh: Volt = 2.650V + (sdx_vsel - 71h) * 50mV Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/as3711-regulator.c | 163 +++++---------------------- 1 file changed, 31 insertions(+), 132 deletions(-) diff --git a/drivers/regulator/as3711-regulator.c b/drivers/regulator/as3711-regulator.c index 3da6bd6950cf..8406cd745da2 100644 --- a/drivers/regulator/as3711-regulator.c +++ b/drivers/regulator/as3711-regulator.c @@ -30,102 +30,6 @@ struct as3711_regulator { struct regulator_dev *rdev; }; -static int as3711_list_voltage_sd(struct regulator_dev *rdev, - unsigned int selector) -{ - if (selector >= rdev->desc->n_voltages) - return -EINVAL; - - if (!selector) - return 0; - if (selector < 0x41) - return 600000 + selector * 12500; - if (selector < 0x71) - return 1400000 + (selector - 0x40) * 25000; - return 2600000 + (selector - 0x70) * 50000; -} - -static int as3711_list_voltage_aldo(struct regulator_dev *rdev, - unsigned int selector) -{ - if (selector >= rdev->desc->n_voltages) - return -EINVAL; - - if (selector < 0x10) - return 1200000 + selector * 50000; - return 1800000 + (selector - 0x10) * 100000; -} - -static int as3711_list_voltage_dldo(struct regulator_dev *rdev, - unsigned int selector) -{ - if (selector >= rdev->desc->n_voltages || - (selector > 0x10 && selector < 0x20)) - return -EINVAL; - - if (selector < 0x11) - return 900000 + selector * 50000; - return 1750000 + (selector - 0x20) * 50000; -} - -static int as3711_bound_check(struct regulator_dev *rdev, - int *min_uV, int *max_uV) -{ - struct as3711_regulator *reg = rdev_get_drvdata(rdev); - struct as3711_regulator_info *info = reg->reg_info; - - dev_dbg(&rdev->dev, "%s(), %d, %d, %d\n", __func__, - *min_uV, rdev->desc->min_uV, info->max_uV); - - if (*max_uV < *min_uV || - *min_uV > info->max_uV || rdev->desc->min_uV > *max_uV) - return -EINVAL; - - if (rdev->desc->n_voltages == 1) - return 0; - - if (*max_uV > info->max_uV) - *max_uV = info->max_uV; - - if (*min_uV < rdev->desc->min_uV) - *min_uV = rdev->desc->min_uV; - - return *min_uV; -} - -static int as3711_sel_check(int min, int max, int bottom, int step) -{ - int sel, voltage; - - /* Round up min, when dividing: keeps us within the range */ - sel = DIV_ROUND_UP(min - bottom, step); - voltage = sel * step + bottom; - pr_debug("%s(): select %d..%d in %d+N*%d: %d\n", __func__, - min, max, bottom, step, sel); - if (voltage > max) - return -EINVAL; - - return sel; -} - -static int as3711_map_voltage_sd(struct regulator_dev *rdev, - int min_uV, int max_uV) -{ - int ret; - - ret = as3711_bound_check(rdev, &min_uV, &max_uV); - if (ret <= 0) - return ret; - - if (min_uV <= 1400000) - return as3711_sel_check(min_uV, max_uV, 600000, 12500); - - if (min_uV <= 2600000) - return as3711_sel_check(min_uV, max_uV, 1400000, 25000) + 0x40; - - return as3711_sel_check(min_uV, max_uV, 2600000, 50000) + 0x70; -} - /* * The regulator API supports 4 modes of operataion: FAST, NORMAL, IDLE and * STANDBY. We map them in the following way to AS3711 SD1-4 DCDC modes: @@ -180,44 +84,14 @@ static unsigned int as3711_get_mode_sd(struct regulator_dev *rdev) return -EINVAL; } -static int as3711_map_voltage_aldo(struct regulator_dev *rdev, - int min_uV, int max_uV) -{ - int ret; - - ret = as3711_bound_check(rdev, &min_uV, &max_uV); - if (ret <= 0) - return ret; - - if (min_uV <= 1800000) - return as3711_sel_check(min_uV, max_uV, 1200000, 50000); - - return as3711_sel_check(min_uV, max_uV, 1800000, 100000) + 0x10; -} - -static int as3711_map_voltage_dldo(struct regulator_dev *rdev, - int min_uV, int max_uV) -{ - int ret; - - ret = as3711_bound_check(rdev, &min_uV, &max_uV); - if (ret <= 0) - return ret; - - if (min_uV <= 1700000) - return as3711_sel_check(min_uV, max_uV, 900000, 50000); - - return as3711_sel_check(min_uV, max_uV, 1750000, 50000) + 0x20; -} - static struct regulator_ops as3711_sd_ops = { .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, - .list_voltage = as3711_list_voltage_sd, - .map_voltage = as3711_map_voltage_sd, + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, .get_mode = as3711_get_mode_sd, .set_mode = as3711_set_mode_sd, }; @@ -228,8 +102,8 @@ static struct regulator_ops as3711_aldo_ops = { .disable = regulator_disable_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, - .list_voltage = as3711_list_voltage_aldo, - .map_voltage = as3711_map_voltage_aldo, + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, }; static struct regulator_ops as3711_dldo_ops = { @@ -238,8 +112,31 @@ static struct regulator_ops as3711_dldo_ops = { .disable = regulator_disable_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, - .list_voltage = as3711_list_voltage_dldo, - .map_voltage = as3711_map_voltage_dldo, + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, +}; + +static const struct regulator_linear_range as3711_sd_ranges[] = { + { .min_uV = 612500, .max_uV = 1400000, + .min_sel = 0x1, .max_sel = 0x40, .uV_step = 12500 }, + { .min_uV = 1425000, .max_uV = 2600000, + .min_sel = 0x41, .max_sel = 0x70, .uV_step = 25000 }, + { .min_uV = 2650000, .max_uV = 3350000, + .min_sel = 0x71, .max_sel = 0x7f, .uV_step = 50000 }, +}; + +static const struct regulator_linear_range as3711_aldo_ranges[] = { + { .min_uV = 1200000, .max_uV = 1950000, + .min_sel = 0, .max_sel = 0xf, .uV_step = 50000 }, + { .min_uV = 1800000, .max_uV = 3300000, + .min_sel = 0x10, .max_sel = 0x1f, .uV_step = 100000 }, +}; + +static const struct regulator_linear_range as3711_dldo_ranges[] = { + { .min_uV = 900000, .max_uV = 1700000, + .min_sel = 0, .max_sel = 0x10, .uV_step = 50000 }, + { .min_uV = 1750000, .max_uV = 3300000, + .min_sel = 0x20, .max_sel = 0x3f, .uV_step = 50000 }, }; #define AS3711_REG(_id, _en_reg, _en_bit, _vmask, _vshift, _min_uV, _max_uV, _sfx) \ @@ -256,6 +153,8 @@ static struct regulator_ops as3711_dldo_ops = { .enable_reg = AS3711_ ## _en_reg, \ .enable_mask = BIT(_en_bit), \ .min_uV = _min_uV, \ + .linear_ranges = as3711_ ## _sfx ## _ranges, \ + .n_linear_ranges = ARRAY_SIZE(as3711_ ## _sfx ## _ranges), \ }, \ .max_uV = _max_uV, \ } From fba6583be610dd83369ecba88d7ee84527d00cf1 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 20 Jul 2013 16:56:45 +0800 Subject: [PATCH 0548/3400] regulator: tps65912: Convert tps65912_ops_ldo to use linear ranges The ldo voltage table is composed of linear ranges. Below is the equation in original code (tps65912_vsel_to_uv_ldo): 0 ... 32: uv = vsel * 25000 + 800000; 33 ... 60: uv = (vsel - 32) * 50000 + 1600000; = (vsel -33) * 50000 + 1650000; 61 ...63: uv = (vsel - 60) * 100000 + 3000000; = (vsel - 61) * 100000 + 3100000; This patch converts tps65912_ops_ldo to use multiple linear ranges APIs. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/tps65912-regulator.c | 39 +++++++++++++------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/drivers/regulator/tps65912-regulator.c b/drivers/regulator/tps65912-regulator.c index 17e994e47dc1..281e52ac64ba 100644 --- a/drivers/regulator/tps65912-regulator.c +++ b/drivers/regulator/tps65912-regulator.c @@ -118,6 +118,15 @@ struct tps65912_reg { int eco_reg; }; +static const struct regulator_linear_range tps65912_ldo_ranges[] = { + { .min_uV = 800000, .max_uV = 1600000, .min_sel = 0, .max_sel = 32, + .uV_step = 25000 }, + { .min_uV = 1650000, .max_uV = 3000000, .min_sel = 33, .max_sel = 60, + .uV_step = 50000 }, + { .min_uV = 3100000, .max_uV = 3300000, .min_sel = 61, .max_sel = 63, + .uV_step = 100000 }, +}; + static int tps65912_get_range(struct tps65912_reg *pmic, int id) { struct tps65912 *mfd = pmic->mfd; @@ -184,20 +193,6 @@ static unsigned long tps65912_vsel_to_uv_range3(u8 vsel) return uv; } -static unsigned long tps65912_vsel_to_uv_ldo(u8 vsel) -{ - unsigned long uv = 0; - - if (vsel <= 32) - uv = ((vsel * 25000) + 800000); - else if (vsel > 32 && vsel <= 60) - uv = (((vsel - 32) * 50000) + 1600000); - else if (vsel > 60) - uv = (((vsel - 60) * 100000) + 3000000); - - return uv; -} - static int tps65912_get_ctrl_register(int id) { if (id >= TPS65912_REG_DCDC1 && id <= TPS65912_REG_LDO4) @@ -376,9 +371,6 @@ static int tps65912_list_voltage(struct regulator_dev *dev, unsigned selector) struct tps65912_reg *pmic = rdev_get_drvdata(dev); int range, voltage = 0, id = rdev_get_id(dev); - if (id >= TPS65912_REG_LDO1 && id <= TPS65912_REG_LDO10) - return tps65912_vsel_to_uv_ldo(selector); - if (id > TPS65912_REG_DCDC4) return -EINVAL; @@ -456,7 +448,8 @@ static struct regulator_ops tps65912_ops_ldo = { .disable = tps65912_reg_disable, .get_voltage_sel = tps65912_get_voltage_sel, .set_voltage_sel = tps65912_set_voltage_sel, - .list_voltage = tps65912_list_voltage, + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, }; static int tps65912_probe(struct platform_device *pdev) @@ -495,8 +488,14 @@ static int tps65912_probe(struct platform_device *pdev) pmic->desc[i].name = info->name; pmic->desc[i].id = i; pmic->desc[i].n_voltages = 64; - pmic->desc[i].ops = (i > TPS65912_REG_DCDC4 ? - &tps65912_ops_ldo : &tps65912_ops_dcdc); + if (i > TPS65912_REG_DCDC4) { + pmic->desc[i].ops = &tps65912_ops_ldo; + pmic->desc[i].linear_ranges = tps65912_ldo_ranges; + pmic->desc[i].n_linear_ranges = + ARRAY_SIZE(tps65912_ldo_ranges); + } else { + pmic->desc[i].ops = &tps65912_ops_dcdc; + } pmic->desc[i].type = REGULATOR_VOLTAGE; pmic->desc[i].owner = THIS_MODULE; range = tps65912_get_range(pmic, i); From f484f7a6bc6f0f871627cc1f83f56077a5dc6e47 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Wed, 24 Jul 2013 10:26:42 +0200 Subject: [PATCH 0549/3400] regmap: irq: make flags bool and put them in a bitfield This patch makes mask/wake_invert bool and puts all flags into a bitfield for consistency and to save some space. Signed-off-by: Philipp Zabel Signed-off-by: Mark Brown --- include/linux/regmap.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/linux/regmap.h b/include/linux/regmap.h index 34ebe7778033..99b0f7cad75c 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h @@ -486,10 +486,10 @@ struct regmap_irq_chip { unsigned int ack_base; unsigned int wake_base; unsigned int irq_reg_stride; - bool init_ack_masked; - unsigned int mask_invert; - unsigned int wake_invert; - bool runtime_pm; + bool init_ack_masked:1; + bool mask_invert:1; + bool wake_invert:1; + bool runtime_pm:1; int num_regs; From 68622bdfefb969fd7cf710545d7e758a732ab01d Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Wed, 24 Jul 2013 10:26:48 +0200 Subject: [PATCH 0550/3400] regmap: irq: document mask/wake_invert flags Signed-off-by: Philipp Zabel Signed-off-by: Mark Brown --- include/linux/regmap.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/regmap.h b/include/linux/regmap.h index 99b0f7cad75c..a3c68aad2381 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h @@ -471,6 +471,8 @@ struct regmap_irq { * @wake_base: Base address for wake enables. If zero unsupported. * @irq_reg_stride: Stride to use for chips where registers are not contiguous. * @init_ack_masked: Ack all masked interrupts once during initalization. + * @mask_invert: Inverted mask register: cleared bits are masked out. + * @wake_invert: Inverted wake register: cleared bits are wake enabled. * @runtime_pm: Hold a runtime PM lock on the device when accessing it. * * @num_regs: Number of registers in each control bank. From 86e35aea477f4cc5a724d8704f5e9d956c73d424 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Wed, 24 Jul 2013 09:30:05 -0400 Subject: [PATCH 0551/3400] n_tty: Fix build breakage on ppc64 Commit 20bafb3d23d108bc0a896eb8b7c1501f4f649b77 'n_tty: Move buffers into n_tty_data' broke the ppc64 build. Include vmalloc.h for the required function declarations. Reported-by: Stephen Rothwell Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index ed6c4e4d960a..2c120b634295 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -50,6 +50,7 @@ #include #include #include +#include /* number of characters left in xmit buffer before select has we have room */ From c2fda509667b0fda4372a237f5a59ea4570b1627 Mon Sep 17 00:00:00 2001 From: Lai Jiangshan Date: Wed, 24 Jul 2013 18:31:42 +0800 Subject: [PATCH 0552/3400] workqueue: allow work_on_cpu() to be called recursively If the @fn call work_on_cpu() again, the lockdep will complain: > [ INFO: possible recursive locking detected ] > 3.11.0-rc1-lockdep-fix-a #6 Not tainted > --------------------------------------------- > kworker/0:1/142 is trying to acquire lock: > ((&wfc.work)){+.+.+.}, at: [] flush_work+0x0/0xb0 > > but task is already holding lock: > ((&wfc.work)){+.+.+.}, at: [] process_one_work+0x169/0x610 > > other info that might help us debug this: > Possible unsafe locking scenario: > > CPU0 > ---- > lock((&wfc.work)); > lock((&wfc.work)); > > *** DEADLOCK *** It is false-positive lockdep report. In this sutiation, the two "wfc"s of the two work_on_cpu() are different, they are both on stack. flush_work() can't be deadlock. To fix this, we need to avoid the lockdep checking in this case, thus we instroduce a internal __flush_work() which skip the lockdep. tj: Minor comment adjustment. Signed-off-by: Lai Jiangshan Reported-by: "Srivatsa S. Bhat" Reported-by: Alexander Duyck Signed-off-by: Tejun Heo --- kernel/workqueue.c | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index f02c4a4a0c3c..55f5f0afcd0d 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -2817,6 +2817,19 @@ already_gone: return false; } +static bool __flush_work(struct work_struct *work) +{ + struct wq_barrier barr; + + if (start_flush_work(work, &barr)) { + wait_for_completion(&barr.done); + destroy_work_on_stack(&barr.work); + return true; + } else { + return false; + } +} + /** * flush_work - wait for a work to finish executing the last queueing instance * @work: the work to flush @@ -2830,18 +2843,10 @@ already_gone: */ bool flush_work(struct work_struct *work) { - struct wq_barrier barr; - lock_map_acquire(&work->lockdep_map); lock_map_release(&work->lockdep_map); - if (start_flush_work(work, &barr)) { - wait_for_completion(&barr.done); - destroy_work_on_stack(&barr.work); - return true; - } else { - return false; - } + return __flush_work(work); } EXPORT_SYMBOL_GPL(flush_work); @@ -4756,7 +4761,14 @@ long work_on_cpu(int cpu, long (*fn)(void *), void *arg) INIT_WORK_ONSTACK(&wfc.work, work_for_cpu_fn); schedule_work_on(cpu, &wfc.work); - flush_work(&wfc.work); + + /* + * The work item is on-stack and can't lead to deadlock through + * flushing. Use __flush_work() to avoid spurious lockdep warnings + * when work_on_cpu()s are nested. + */ + __flush_work(&wfc.work); + return wfc.ret; } EXPORT_SYMBOL_GPL(work_on_cpu); From 7d88d637a3c75257b7611f9feee0c17fa187ecc9 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Wed, 24 Jul 2013 08:29:49 -0400 Subject: [PATCH 0553/3400] n_tty: Factor standard per-char i/o into separate fn Simplify __receive_buf() into a dispatch function; perform per-char processing for all other modes not already handled. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 2c120b634295..951ecfeed8d3 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1569,6 +1569,22 @@ n_tty_receive_buf_closing(struct tty_struct *tty, const unsigned char *cp, } } +static void +n_tty_receive_buf_standard(struct tty_struct *tty, const unsigned char *cp, + char *fp, int count) +{ + char flag = TTY_NORMAL; + + while (count--) { + if (fp) + flag = *fp++; + if (likely(flag == TTY_NORMAL)) + n_tty_receive_char(tty, *cp++); + else + n_tty_receive_char_flagged(tty, *cp++, flag); + } +} + static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) { @@ -1582,16 +1598,7 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, else if (tty->closing && !L_EXTPROC(tty)) n_tty_receive_buf_closing(tty, cp, fp, count); else { - char flag = TTY_NORMAL; - - while (count--) { - if (fp) - flag = *fp++; - if (likely(flag == TTY_NORMAL)) - n_tty_receive_char(tty, *cp++); - else - n_tty_receive_char_flagged(tty, *cp++, flag); - } + n_tty_receive_buf_standard(tty, cp, fp, count); flush_echoes(tty); if (tty->ops->flush_chars) From 855df3c08968beac9d9a86536c43c0474684ac37 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Wed, 24 Jul 2013 08:29:50 -0400 Subject: [PATCH 0554/3400] n_tty: Eliminate char tests from IXANY restart test Relocate the IXANY restart tty test to code paths where the the received char is not START_CHAR, STOP_CHAR, INTR_CHAR, QUIT_CHAR or SUSP_CHAR. Fixes the condition when ISIG if off and one of INTR_CHAR, QUIT_CHAR or SUSP_CHAR does not restart i/o. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 951ecfeed8d3..f2e6bdb319cf 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1270,13 +1270,6 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) return; } - if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && - I_IXANY(tty) && c != START_CHAR(tty) && c != STOP_CHAR(tty) && - c != INTR_CHAR(tty) && c != QUIT_CHAR(tty) && c != SUSP_CHAR(tty)) { - start_tty(tty); - process_echoes(tty); - } - /* * If the previous character was LNEXT, or we know that this * character is not one of the characters that we'll have to @@ -1285,6 +1278,13 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) */ if (!test_bit(c, ldata->char_map) || ldata->lnext) { ldata->lnext = 0; + + if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && + I_IXANY(tty)) { + start_tty(tty); + process_echoes(tty); + } + parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0; if (read_cnt(ldata) >= (N_TTY_BUF_SIZE - parmrk - 1)) { /* beep if no space */ @@ -1331,6 +1331,11 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) } } + if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && I_IXANY(tty)) { + start_tty(tty); + process_echoes(tty); + } + if (c == '\r') { if (I_IGNCR(tty)) return; From 4b1f79c2d7352605b567cab49de20d3b67762ee3 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Wed, 24 Jul 2013 08:29:51 -0400 Subject: [PATCH 0555/3400] n_tty: Split n_tty_receive_char() Factor 'special' per-char processing into standalone fn, n_tty_receive_char_special(), which handles processing for chars marked in the char_map. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 103 ++++++++++++++++++++++++-------------------- 1 file changed, 56 insertions(+), 47 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index f2e6bdb319cf..8686124b1309 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1255,57 +1255,12 @@ n_tty_receive_signal_char(struct tty_struct *tty, int signal, unsigned char c) * otherwise, publishes read_head via put_tty_queue() */ -static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) +static void +n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) { struct n_tty_data *ldata = tty->disc_data; int parmrk; - if (I_ISTRIP(tty)) - c &= 0x7f; - if (I_IUCLC(tty) && L_IEXTEN(tty)) - c = tolower(c); - - if (L_EXTPROC(tty)) { - put_tty_queue(c, ldata); - return; - } - - /* - * If the previous character was LNEXT, or we know that this - * character is not one of the characters that we'll have to - * handle specially, do shortcut processing to speed things - * up. - */ - if (!test_bit(c, ldata->char_map) || ldata->lnext) { - ldata->lnext = 0; - - if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && - I_IXANY(tty)) { - start_tty(tty); - process_echoes(tty); - } - - parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0; - if (read_cnt(ldata) >= (N_TTY_BUF_SIZE - parmrk - 1)) { - /* beep if no space */ - if (L_ECHO(tty)) - process_output('\a', tty); - return; - } - if (L_ECHO(tty)) { - finish_erasing(ldata); - /* Record the column of first canon char. */ - if (ldata->canon_head == ldata->read_head) - echo_set_canon_col(ldata); - echo_char(c, tty); - commit_echoes(tty); - } - if (parmrk) - put_tty_queue(c, ldata); - put_tty_queue(c, ldata); - return; - } - if (I_IXON(tty)) { if (c == START_CHAR(tty)) { start_tty(tty); @@ -1458,6 +1413,60 @@ handle_newline: put_tty_queue(c, ldata); } +static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) +{ + struct n_tty_data *ldata = tty->disc_data; + int parmrk; + + if (I_ISTRIP(tty)) + c &= 0x7f; + if (I_IUCLC(tty) && L_IEXTEN(tty)) + c = tolower(c); + + if (L_EXTPROC(tty)) { + put_tty_queue(c, ldata); + return; + } + + /* + * If the previous character was LNEXT, or we know that this + * character is not one of the characters that we'll have to + * handle specially, do shortcut processing to speed things + * up. + */ + if (!test_bit(c, ldata->char_map) || ldata->lnext) { + ldata->lnext = 0; + + if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && + I_IXANY(tty)) { + start_tty(tty); + process_echoes(tty); + } + + parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0; + if (read_cnt(ldata) >= (N_TTY_BUF_SIZE - parmrk - 1)) { + /* beep if no space */ + if (L_ECHO(tty)) + process_output('\a', tty); + return; + } + if (L_ECHO(tty)) { + finish_erasing(ldata); + /* Record the column of first canon char. */ + if (ldata->canon_head == ldata->read_head) + echo_set_canon_col(ldata); + echo_char(c, tty); + commit_echoes(tty); + } + if (parmrk) + put_tty_queue(c, ldata); + put_tty_queue(c, ldata); + return; + } + + n_tty_receive_char_special(tty, c); +} + static inline void n_tty_receive_char_closing(struct tty_struct *tty, unsigned char c) { From 6baad008678cf07820a3099bfb2bb558b5d0fa2a Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Wed, 24 Jul 2013 08:29:52 -0400 Subject: [PATCH 0556/3400] n_tty: Factor ISTRIP and IUCLC receive_buf into separate fn Convert to modal receive_buf processing; factor char receive processing for unusual termios settings out of normal per-char i/o path. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 44 ++++++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 8686124b1309..59c73ee32fbf 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1418,16 +1418,6 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) struct n_tty_data *ldata = tty->disc_data; int parmrk; - if (I_ISTRIP(tty)) - c &= 0x7f; - if (I_IUCLC(tty) && L_IEXTEN(tty)) - c = tolower(c); - - if (L_EXTPROC(tty)) { - put_tty_queue(c, ldata); - return; - } - /* * If the previous character was LNEXT, or we know that this * character is not one of the characters that we'll have to @@ -1585,7 +1575,34 @@ n_tty_receive_buf_closing(struct tty_struct *tty, const unsigned char *cp, static void n_tty_receive_buf_standard(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count) + char *fp, int count) +{ + struct n_tty_data *ldata = tty->disc_data; + char flag = TTY_NORMAL; + + while (count--) { + if (fp) + flag = *fp++; + if (likely(flag == TTY_NORMAL)) { + unsigned char c = *cp++; + + if (I_ISTRIP(tty)) + c &= 0x7f; + if (I_IUCLC(tty) && L_IEXTEN(tty)) + c = tolower(c); + if (L_EXTPROC(tty)) { + put_tty_queue(c, ldata); + continue; + } + n_tty_receive_char(tty, c); + } else + n_tty_receive_char_flagged(tty, *cp++, flag); + } +} + +static void +n_tty_receive_buf_fast(struct tty_struct *tty, const unsigned char *cp, + char *fp, int count) { char flag = TTY_NORMAL; @@ -1612,7 +1629,10 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, else if (tty->closing && !L_EXTPROC(tty)) n_tty_receive_buf_closing(tty, cp, fp, count); else { - n_tty_receive_buf_standard(tty, cp, fp, count); + if (!preops) + n_tty_receive_buf_fast(tty, cp, fp, count); + else + n_tty_receive_buf_standard(tty, cp, fp, count); flush_echoes(tty); if (tty->ops->flush_chars) From 7de971b05055d31589955feb0f50963b78fe697a Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Wed, 24 Jul 2013 08:29:53 -0400 Subject: [PATCH 0557/3400] n_tty: Factor PARMRK from normal per-char i/o Handle PARMRK processing on the slow per-char i/o path. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 45 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 59c73ee32fbf..adc06af3a075 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1457,6 +1457,47 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) n_tty_receive_char_special(tty, c); } +static inline void +n_tty_receive_char_fast(struct tty_struct *tty, unsigned char c) +{ + struct n_tty_data *ldata = tty->disc_data; + + /* + * If the previous character was LNEXT, or we know that this + * character is not one of the characters that we'll have to + * handle specially, do shortcut processing to speed things + * up. + */ + if (!test_bit(c, ldata->char_map) || ldata->lnext) { + ldata->lnext = 0; + + if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && + I_IXANY(tty)) { + start_tty(tty); + process_echoes(tty); + } + + if (read_cnt(ldata) >= (N_TTY_BUF_SIZE - 1)) { + /* beep if no space */ + if (L_ECHO(tty)) + process_output('\a', tty); + return; + } + if (L_ECHO(tty)) { + finish_erasing(ldata); + /* Record the column of first canon char. */ + if (ldata->canon_head == ldata->read_head) + echo_set_canon_col(ldata); + echo_char(c, tty); + commit_echoes(tty); + } + put_tty_queue(c, ldata); + return; + } + + n_tty_receive_char_special(tty, c); +} + static inline void n_tty_receive_char_closing(struct tty_struct *tty, unsigned char c) { @@ -1610,7 +1651,7 @@ n_tty_receive_buf_fast(struct tty_struct *tty, const unsigned char *cp, if (fp) flag = *fp++; if (likely(flag == TTY_NORMAL)) - n_tty_receive_char(tty, *cp++); + n_tty_receive_char_fast(tty, *cp++); else n_tty_receive_char_flagged(tty, *cp++, flag); } @@ -1629,7 +1670,7 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, else if (tty->closing && !L_EXTPROC(tty)) n_tty_receive_buf_closing(tty, cp, fp, count); else { - if (!preops) + if (!preops && !I_PARMRK(tty)) n_tty_receive_buf_fast(tty, cp, fp, count); else n_tty_receive_buf_standard(tty, cp, fp, count); From 19e2ad6a09f0c06dbca19c98e5f4584269d913dd Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Wed, 24 Jul 2013 08:29:54 -0400 Subject: [PATCH 0558/3400] n_tty: Remove overflow tests from receive_buf() path Always pre-figure the space available in the read_buf and limit the inbound receive request to that amount. For compatibility reasons with the non-flow-controlled interface, n_tty_receive_buf() will continue filling read_buf until all data has been received or receive_room() returns 0. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 85 ++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 48 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index adc06af3a075..f66d95f949d1 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -316,12 +316,9 @@ static inline void n_tty_check_unthrottle(struct tty_struct *tty) * not active. */ -static void put_tty_queue(unsigned char c, struct n_tty_data *ldata) +static inline void put_tty_queue(unsigned char c, struct n_tty_data *ldata) { - if (read_cnt(ldata) < N_TTY_BUF_SIZE) { - *read_buf_addr(ldata, ldata->read_head) = c; - ldata->read_head++; - } + *read_buf_addr(ldata, ldata->read_head++) = c; } /** @@ -1333,11 +1330,6 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) return; } if (c == '\n') { - if (read_cnt(ldata) >= N_TTY_BUF_SIZE) { - if (L_ECHO(tty)) - process_output('\a', tty); - return; - } if (L_ECHO(tty) || L_ECHONL(tty)) { echo_char_raw('\n', ldata); commit_echoes(tty); @@ -1345,8 +1337,6 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) goto handle_newline; } if (c == EOF_CHAR(tty)) { - if (read_cnt(ldata) >= N_TTY_BUF_SIZE) - return; c = __DISABLED_CHAR; goto handle_newline; } @@ -1354,11 +1344,6 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) (c == EOL2_CHAR(tty) && L_IEXTEN(tty))) { parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0; - if (read_cnt(ldata) >= (N_TTY_BUF_SIZE - parmrk)) { - if (L_ECHO(tty)) - process_output('\a', tty); - return; - } /* * XXX are EOL_CHAR and EOL2_CHAR echoed?!? */ @@ -1388,12 +1373,6 @@ handle_newline: } parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0; - if (read_cnt(ldata) >= (N_TTY_BUF_SIZE - parmrk - 1)) { - /* beep if no space */ - if (L_ECHO(tty)) - process_output('\a', tty); - return; - } if (L_ECHO(tty)) { finish_erasing(ldata); if (c == '\n') @@ -1432,14 +1411,6 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) start_tty(tty); process_echoes(tty); } - - parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0; - if (read_cnt(ldata) >= (N_TTY_BUF_SIZE - parmrk - 1)) { - /* beep if no space */ - if (L_ECHO(tty)) - process_output('\a', tty); - return; - } if (L_ECHO(tty)) { finish_erasing(ldata); /* Record the column of first canon char. */ @@ -1448,6 +1419,7 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) echo_char(c, tty); commit_echoes(tty); } + parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0; if (parmrk) put_tty_queue(c, ldata); put_tty_queue(c, ldata); @@ -1476,13 +1448,6 @@ n_tty_receive_char_fast(struct tty_struct *tty, unsigned char c) start_tty(tty); process_echoes(tty); } - - if (read_cnt(ldata) >= (N_TTY_BUF_SIZE - 1)) { - /* beep if no space */ - if (L_ECHO(tty)) - process_output('\a', tty); - return; - } if (L_ECHO(tty)) { finish_erasing(ldata); /* Record the column of first canon char. */ @@ -1691,8 +1656,23 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) { + int room, n; + down_read(&tty->termios_rwsem); - __receive_buf(tty, cp, fp, count); + + while (1) { + room = receive_room(tty); + n = min(count, room); + if (!n) + break; + __receive_buf(tty, cp, fp, n); + cp += n; + if (fp) + fp += n; + count -= n; + } + + tty->receive_room = room; n_tty_check_throttle(tty); up_read(&tty->termios_rwsem); } @@ -1701,22 +1681,31 @@ static int n_tty_receive_buf2(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) { struct n_tty_data *ldata = tty->disc_data; - int room; + int room, n, rcvd = 0; down_read(&tty->termios_rwsem); - tty->receive_room = room = receive_room(tty); - if (!room) - ldata->no_room = 1; - count = min(count, room); - if (count) { - __receive_buf(tty, cp, fp, count); - n_tty_check_throttle(tty); + while (1) { + room = receive_room(tty); + n = min(count, room); + if (!n) { + if (!room) + ldata->no_room = 1; + break; + } + __receive_buf(tty, cp, fp, n); + cp += n; + if (fp) + fp += n; + count -= n; + rcvd += n; } + tty->receive_room = room; + n_tty_check_throttle(tty); up_read(&tty->termios_rwsem); - return count; + return rcvd; } int is_ignored(int sig) From 4b293492ae9ca87b4410fafae1fe2ea6eafb3c87 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Wed, 24 Jul 2013 08:29:55 -0400 Subject: [PATCH 0559/3400] n_tty: Un-inline single-use functions gcc will likely inline these single-use functions anyway; remove inline modifier. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index f66d95f949d1..735826359a66 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -264,7 +264,7 @@ static void n_tty_check_throttle(struct tty_struct *tty) __tty_set_flow_change(tty, 0); } -static inline void n_tty_check_unthrottle(struct tty_struct *tty) +static void n_tty_check_unthrottle(struct tty_struct *tty) { if (tty->driver->type == TTY_DRIVER_TYPE_PTY && tty->link->ldisc->ops->write_wakeup == n_tty_write_wakeup) { @@ -1110,7 +1110,7 @@ static void eraser(unsigned char c, struct tty_struct *tty) * Locking: ctrl_lock */ -static inline void isig(int sig, struct tty_struct *tty) +static void isig(int sig, struct tty_struct *tty) { struct pid *tty_pgrp = tty_get_pgrp(tty); if (tty_pgrp) { @@ -1133,7 +1133,7 @@ static inline void isig(int sig, struct tty_struct *tty) * Note: may get exclusive termios_rwsem if flushing input buffer */ -static inline void n_tty_receive_break(struct tty_struct *tty) +static void n_tty_receive_break(struct tty_struct *tty) { struct n_tty_data *ldata = tty->disc_data; @@ -1171,7 +1171,7 @@ static inline void n_tty_receive_break(struct tty_struct *tty) * private. */ -static inline void n_tty_receive_overrun(struct tty_struct *tty) +static void n_tty_receive_overrun(struct tty_struct *tty) { struct n_tty_data *ldata = tty->disc_data; char buf[64]; @@ -1199,8 +1199,7 @@ static inline void n_tty_receive_overrun(struct tty_struct *tty) * caller holds non-exclusive termios_rwsem * publishes read_head via put_tty_queue() */ -static inline void n_tty_receive_parity_error(struct tty_struct *tty, - unsigned char c) +static void n_tty_receive_parity_error(struct tty_struct *tty, unsigned char c) { struct n_tty_data *ldata = tty->disc_data; From e60d27c4d8b33ba20896b76b6558f061bc6460ff Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Wed, 24 Jul 2013 08:29:56 -0400 Subject: [PATCH 0560/3400] n_tty: Factor LNEXT processing from per-char i/o path LNEXT processing accounts for ~15% of total cpu time in end-to-end tty i/o; factor the lnext test/clear from the per-char i/o path. Instead, attempt to immediately handle the literal next char if not at the end of this received buffer; otherwise, handle the first char of the next received buffer as the literal next char, then continue with normal i/o. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 166 +++++++++++++++++++++++++------------------- 1 file changed, 94 insertions(+), 72 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 735826359a66..dd8ae0cad1d5 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1249,9 +1249,11 @@ n_tty_receive_signal_char(struct tty_struct *tty, int signal, unsigned char c) * caller holds non-exclusive termios_rwsem * publishes canon_head if canonical mode is active * otherwise, publishes read_head via put_tty_queue() + * + * Returns 1 if LNEXT was received, else returns 0 */ -static void +static int n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) { struct n_tty_data *ldata = tty->disc_data; @@ -1261,24 +1263,24 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) if (c == START_CHAR(tty)) { start_tty(tty); commit_echoes(tty); - return; + return 0; } if (c == STOP_CHAR(tty)) { stop_tty(tty); - return; + return 0; } } if (L_ISIG(tty)) { if (c == INTR_CHAR(tty)) { n_tty_receive_signal_char(tty, SIGINT, c); - return; + return 0; } else if (c == QUIT_CHAR(tty)) { n_tty_receive_signal_char(tty, SIGQUIT, c); - return; + return 0; } else if (c == SUSP_CHAR(tty)) { n_tty_receive_signal_char(tty, SIGTSTP, c); - return; + return 0; } } @@ -1289,7 +1291,7 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) if (c == '\r') { if (I_IGNCR(tty)) - return; + return 0; if (I_ICRNL(tty)) c = '\n'; } else if (c == '\n' && I_INLCR(tty)) @@ -1300,7 +1302,7 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) (c == WERASE_CHAR(tty) && L_IEXTEN(tty))) { eraser(c, tty); commit_echoes(tty); - return; + return 0; } if (c == LNEXT_CHAR(tty) && L_IEXTEN(tty)) { ldata->lnext = 1; @@ -1312,10 +1314,9 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) commit_echoes(tty); } } - return; + return 1; } - if (c == REPRINT_CHAR(tty) && L_ECHO(tty) && - L_IEXTEN(tty)) { + if (c == REPRINT_CHAR(tty) && L_ECHO(tty) && L_IEXTEN(tty)) { size_t tail = ldata->canon_head; finish_erasing(ldata); @@ -1326,7 +1327,7 @@ n_tty_receive_char_special(struct tty_struct *tty, unsigned char c) tail++; } commit_echoes(tty); - return; + return 0; } if (c == '\n') { if (L_ECHO(tty) || L_ECHONL(tty)) { @@ -1367,7 +1368,7 @@ handle_newline: kill_fasync(&tty->fasync, SIGIO, POLL_IN); if (waitqueue_active(&tty->read_wait)) wake_up_interruptible(&tty->read_wait); - return; + return 0; } } @@ -1389,43 +1390,36 @@ handle_newline: put_tty_queue(c, ldata); put_tty_queue(c, ldata); + return 0; } -static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) +static inline void +n_tty_receive_char_inline(struct tty_struct *tty, unsigned char c) { struct n_tty_data *ldata = tty->disc_data; int parmrk; - /* - * If the previous character was LNEXT, or we know that this - * character is not one of the characters that we'll have to - * handle specially, do shortcut processing to speed things - * up. - */ - if (!test_bit(c, ldata->char_map) || ldata->lnext) { - ldata->lnext = 0; - - if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && - I_IXANY(tty)) { - start_tty(tty); - process_echoes(tty); - } - if (L_ECHO(tty)) { - finish_erasing(ldata); - /* Record the column of first canon char. */ - if (ldata->canon_head == ldata->read_head) - echo_set_canon_col(ldata); - echo_char(c, tty); - commit_echoes(tty); - } - parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0; - if (parmrk) - put_tty_queue(c, ldata); - put_tty_queue(c, ldata); - return; + if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && I_IXANY(tty)) { + start_tty(tty); + process_echoes(tty); } + if (L_ECHO(tty)) { + finish_erasing(ldata); + /* Record the column of first canon char. */ + if (ldata->canon_head == ldata->read_head) + echo_set_canon_col(ldata); + echo_char(c, tty); + commit_echoes(tty); + } + parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0; + if (parmrk) + put_tty_queue(c, ldata); + put_tty_queue(c, ldata); +} - n_tty_receive_char_special(tty, c); +static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) +{ + n_tty_receive_char_inline(tty, c); } static inline void @@ -1433,33 +1427,19 @@ n_tty_receive_char_fast(struct tty_struct *tty, unsigned char c) { struct n_tty_data *ldata = tty->disc_data; - /* - * If the previous character was LNEXT, or we know that this - * character is not one of the characters that we'll have to - * handle specially, do shortcut processing to speed things - * up. - */ - if (!test_bit(c, ldata->char_map) || ldata->lnext) { - ldata->lnext = 0; - - if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && - I_IXANY(tty)) { - start_tty(tty); - process_echoes(tty); - } - if (L_ECHO(tty)) { - finish_erasing(ldata); - /* Record the column of first canon char. */ - if (ldata->canon_head == ldata->read_head) - echo_set_canon_col(ldata); - echo_char(c, tty); - commit_echoes(tty); - } - put_tty_queue(c, ldata); - return; + if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && I_IXANY(tty)) { + start_tty(tty); + process_echoes(tty); } - - n_tty_receive_char_special(tty, c); + if (L_ECHO(tty)) { + finish_erasing(ldata); + /* Record the column of first canon char. */ + if (ldata->canon_head == ldata->read_head) + echo_set_canon_col(ldata); + echo_char(c, tty); + commit_echoes(tty); + } + put_tty_queue(c, ldata); } static inline void @@ -1506,6 +1486,22 @@ n_tty_receive_char_flagged(struct tty_struct *tty, unsigned char c, char flag) } } +static void +n_tty_receive_char_lnext(struct tty_struct *tty, unsigned char c, char flag) +{ + struct n_tty_data *ldata = tty->disc_data; + + ldata->lnext = 0; + if (likely(flag == TTY_NORMAL)) { + if (I_ISTRIP(tty)) + c &= 0x7f; + if (I_IUCLC(tty) && L_IEXTEN(tty)) + c = tolower(c); + n_tty_receive_char(tty, c); + } else + n_tty_receive_char_flagged(tty, c, flag); +} + /** * n_tty_receive_buf - data receive * @tty: terminal device @@ -1599,7 +1595,14 @@ n_tty_receive_buf_standard(struct tty_struct *tty, const unsigned char *cp, put_tty_queue(c, ldata); continue; } - n_tty_receive_char(tty, c); + if (!test_bit(c, ldata->char_map)) + n_tty_receive_char_inline(tty, c); + else if (n_tty_receive_char_special(tty, c) && count) { + if (fp) + flag = *fp++; + n_tty_receive_char_lnext(tty, *cp++, flag); + count--; + } } else n_tty_receive_char_flagged(tty, *cp++, flag); } @@ -1609,14 +1612,24 @@ static void n_tty_receive_buf_fast(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) { + struct n_tty_data *ldata = tty->disc_data; char flag = TTY_NORMAL; while (count--) { if (fp) flag = *fp++; - if (likely(flag == TTY_NORMAL)) - n_tty_receive_char_fast(tty, *cp++); - else + if (likely(flag == TTY_NORMAL)) { + unsigned char c = *cp++; + + if (!test_bit(c, ldata->char_map)) + n_tty_receive_char_fast(tty, c); + else if (n_tty_receive_char_special(tty, c) && count) { + if (fp) + flag = *fp++; + n_tty_receive_char_lnext(tty, *cp++, flag); + count--; + } + } else n_tty_receive_char_flagged(tty, *cp++, flag); } } @@ -1634,6 +1647,15 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, else if (tty->closing && !L_EXTPROC(tty)) n_tty_receive_buf_closing(tty, cp, fp, count); else { + if (ldata->lnext) { + char flag = TTY_NORMAL; + + if (fp) + flag = *fp++; + n_tty_receive_char_lnext(tty, *cp++, flag); + count--; + } + if (!preops && !I_PARMRK(tty)) n_tty_receive_buf_fast(tty, cp, fp, count); else From 5ede52538ee2b2202d9dff5b06c33bfde421e6e4 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Wed, 24 Jul 2013 08:29:57 -0400 Subject: [PATCH 0561/3400] tty: Remove extra wakeup from pty write() path Acquiring the write_wait queue spin lock now accounts for the largest slice of cpu time on the tty write path. Two factors contribute to this situation; a overly-pessimistic line discipline write loop which _always_ sets up a wait loop even if i/o will immediately succeed, and on ptys, a wakeup storm from reads and writes. Writer wakeup does not need to be performed by the pty driver. Firstly, since the actual i/o is performed within the write, the line discipline write loop will continue while space remains in the flip buffers. Secondly, when space becomes avail in the line discipline receive buffer (and thus also in the flip buffers), the pty unthrottle re-wakes the writer (non-flow-controlled line disciplines unconditionally unthrottle the driver when data is received). Thus, existing in-kernel i/o is guaranteed to advance. Finally, writer wakeup occurs at the conclusion of the line discipline write (in tty_write_unlock()). This guarantees that any user-space write waiters are woken to continue additional i/o. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/pty.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index b38a28bd9511..b940127ba1c8 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -121,10 +121,8 @@ static int pty_write(struct tty_struct *tty, const unsigned char *buf, int c) /* Stuff the data into the input queue of the other end */ c = tty_insert_flip_string(to->port, buf, c); /* And shovel */ - if (c) { + if (c) tty_flip_buffer_push(to->port); - tty_wakeup(tty); - } } return c; } From 12da3d35a9381cda892ffbed3c1f13670832b622 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 24 Jul 2013 12:06:20 +0530 Subject: [PATCH 0562/3400] staging: lustre: Remove version.h header inclusion in kp30.h version.h header inclusion is not necessary as detected by versioncheck. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/linux/kp30.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h b/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h index 5ba099595a99..2e5c85071647 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h @@ -55,7 +55,6 @@ #include #include #include -#include #include #include #include From ac20a8af710718d5fc2c93e5d063e6cc2dcf38b2 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 24 Jul 2013 12:06:21 +0530 Subject: [PATCH 0563/3400] staging: lustre: Remove version.h header inclusion in linux-cpu.h version.h header inclusion is not necessary as detected by versioncheck. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/linux/linux-cpu.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/linux-cpu.h b/drivers/staging/lustre/include/linux/libcfs/linux/linux-cpu.h index 5f793f223750..36928791e75d 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/linux-cpu.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/linux-cpu.h @@ -46,8 +46,6 @@ #include #include #include -#include - #ifdef CONFIG_SMP From 71930337f4df062ad1806b4c2f9c2ec461a65775 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 24 Jul 2013 12:06:22 +0530 Subject: [PATCH 0564/3400] staging: lustre: Remove version.h header inclusion in linux-prim.h version.h header inclusion is not necessary as detected by versioncheck. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/linux/linux-prim.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/linux-prim.h b/drivers/staging/lustre/include/linux/libcfs/linux/linux-prim.h index a4963a8dfdd8..acdf7ee089f2 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/linux-prim.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/linux-prim.h @@ -49,7 +49,6 @@ #include #include #include -#include #include #include #include From 9136e118e04aa9cb22bd67b8b14a1555e20c20a1 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 24 Jul 2013 12:06:23 +0530 Subject: [PATCH 0565/3400] staging: lustre: Remove version.h header inclusion in linux-time.h version.h header inclusion is not necessary as detected by versioncheck. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/linux/linux-time.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/linux-time.h b/drivers/staging/lustre/include/linux/libcfs/linux/linux-time.h index 4a48b914b42a..a386d1b1286b 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/linux-time.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/linux-time.h @@ -91,7 +91,6 @@ #include #include -#include #include #include From 95eed10b20a97de95c424425616a4edd8fb4d1b8 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 24 Jul 2013 12:06:24 +0530 Subject: [PATCH 0566/3400] staging: lustre: Remove version.h header inclusion in socklnd_lib-linux.h version.h header inclusion is not necessary as detected by versioncheck. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.h b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.h index 3c135786dc11..384eb7ca1c82 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.h +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.h @@ -41,7 +41,6 @@ #include #include -#include #include #include #include From 3c5534cfca74f2239a0e7d1f7554567d79b4a3ca Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 24 Jul 2013 12:06:25 +0530 Subject: [PATCH 0567/3400] staging: lustre: Remove version.h header inclusion in lprocfs_status.h version.h header inclusion is not necessary as detected by versioncheck. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/linux/lprocfs_status.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/include/linux/lprocfs_status.h b/drivers/staging/lustre/lustre/include/linux/lprocfs_status.h index 586692272d78..4bcc4dcca3da 100644 --- a/drivers/staging/lustre/lustre/include/linux/lprocfs_status.h +++ b/drivers/staging/lustre/lustre/include/linux/lprocfs_status.h @@ -48,7 +48,6 @@ #include #include -#include #include #include #include From 082013e97d93fcc38f076a71b21b9233eadbf740 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 24 Jul 2013 12:06:26 +0530 Subject: [PATCH 0568/3400] staging: lustre: Remove version.h header inclusion in lustre_handles.h version.h header inclusion is not necessary as detected by versioncheck. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/linux/lustre_handles.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_handles.h b/drivers/staging/lustre/lustre/include/linux/lustre_handles.h index ecf184051252..459b2380600f 100644 --- a/drivers/staging/lustre/lustre/include/linux/lustre_handles.h +++ b/drivers/staging/lustre/lustre/include/linux/lustre_handles.h @@ -42,7 +42,6 @@ #include #include #include -#include #include #include From 98201dee66e057c0ed40fe40b73e951b17d95abd Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 24 Jul 2013 12:06:27 +0530 Subject: [PATCH 0569/3400] staging: lustre: Remove version.h header inclusion in lustre_lite.h version.h header inclusion is not necessary as detected by versioncheck. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/linux/lustre_lite.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_lite.h b/drivers/staging/lustre/lustre/include/linux/lustre_lite.h index c95dff900b58..9e5df8dabe80 100644 --- a/drivers/staging/lustre/lustre/include/linux/lustre_lite.h +++ b/drivers/staging/lustre/lustre/include/linux/lustre_lite.h @@ -40,8 +40,6 @@ #endif -#include - #include #include From 73086c2a522cc6756f637863f79fe76ed740a05a Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 24 Jul 2013 12:06:28 +0530 Subject: [PATCH 0570/3400] staging: lustre: Remove version.h header inclusion in lustre_net.h version.h header inclusion is not necessary as detected by versioncheck. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/linux/lustre_net.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_net.h b/drivers/staging/lustre/lustre/include/linux/lustre_net.h index 2d7c425d7012..05de4d87db9a 100644 --- a/drivers/staging/lustre/lustre/include/linux/lustre_net.h +++ b/drivers/staging/lustre/lustre/include/linux/lustre_net.h @@ -39,7 +39,6 @@ #error Do not #include this file directly. #include instead #endif -#include #include /* XXX Liang: should be moved to other header instead of here */ From 1194231f4d7b65074dd7420e9c9916df1ab505c4 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 24 Jul 2013 12:06:29 +0530 Subject: [PATCH 0571/3400] staging: lustre: Remove version.h header inclusion in lustre_quota.h version.h header inclusion is not necessary as detected by versioncheck. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/linux/lustre_quota.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_quota.h b/drivers/staging/lustre/lustre/include/linux/lustre_quota.h index 421866b004cf..a39505014c82 100644 --- a/drivers/staging/lustre/lustre/include/linux/lustre_quota.h +++ b/drivers/staging/lustre/lustre/include/linux/lustre_quota.h @@ -39,7 +39,6 @@ #error Do not #include this file directly. #include instead #endif -#include #include #include #include From f1289cba70c3b51e2bb30516ef734cc9c5576602 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 24 Jul 2013 12:06:30 +0530 Subject: [PATCH 0572/3400] staging: lustre: Remove version.h header inclusion in lustre_user.h version.h header inclusion is not necessary as detected by versioncheck. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/linux/lustre_user.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_user.h b/drivers/staging/lustre/lustre/include/linux/lustre_user.h index ea9393c625cc..9cc2849f3f85 100644 --- a/drivers/staging/lustre/lustre/include/linux/lustre_user.h +++ b/drivers/staging/lustre/lustre/include/linux/lustre_user.h @@ -41,7 +41,6 @@ #ifndef _LINUX_LUSTRE_USER_H #define _LINUX_LUSTRE_USER_H -# include # include /* From 1e591d1be945264014168cb32661b7402018f585 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 24 Jul 2013 12:06:31 +0530 Subject: [PATCH 0573/3400] staging: lustre: Remove version.h header inclusion in linux-debug.c version.h header inclusion is not necessary as detected by versioncheck. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c index 9b5fa919aa4a..0069b5ea1c28 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c @@ -55,7 +55,6 @@ #include #include #include -#include # define DEBUG_SUBSYSTEM S_LNET From f2ca6c65f642af85ab212ef0f06c8ef3fca39db8 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 24 Jul 2013 12:06:32 +0530 Subject: [PATCH 0574/3400] staging: lustre: Remove version.h header inclusion in dir.c version.h header inclusion is not necessary as detected by versioncheck. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/dir.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index a94e463f0498..002b37448682 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -41,7 +41,6 @@ #include #include #include -#include #include #include // for wait_on_buffer #include From 686570c83f7f2ea6db94fdd3869255d3f322ed77 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 24 Jul 2013 12:06:33 +0530 Subject: [PATCH 0575/3400] staging: lustre: Remove version.h header inclusion in llite_capa.c version.h header inclusion is not necessary as detected by versioncheck. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/llite_capa.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/llite/llite_capa.c b/drivers/staging/lustre/lustre/llite/llite_capa.c index b6fd9593325a..cfc5ad388c1c 100644 --- a/drivers/staging/lustre/lustre/llite/llite_capa.c +++ b/drivers/staging/lustre/lustre/llite/llite_capa.c @@ -41,7 +41,6 @@ #define DEBUG_SUBSYSTEM S_LLITE #include -#include #include #include #include From abef43cfbfc9aab014175576518305371c0f45f6 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 24 Jul 2013 12:06:34 +0530 Subject: [PATCH 0576/3400] staging: lustre: Remove version.h header inclusion in llite_lib.c version.h header inclusion is not necessary as detected by versioncheck. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/llite_lib.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index d7d87b1539b4..e8bf49fa7bbf 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -42,7 +42,6 @@ #include #include -#include #include #include From accd0b6bb1fbc96726b8b88489c82577874a6132 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 24 Jul 2013 12:06:35 +0530 Subject: [PATCH 0577/3400] staging: lustre: Remove version.h header inclusion in llite_mmap.c version.h header inclusion is not necessary as detected by versioncheck. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/llite_mmap.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/llite/llite_mmap.c b/drivers/staging/lustre/lustre/llite/llite_mmap.c index d9590d85634a..32a57e85300b 100644 --- a/drivers/staging/lustre/lustre/llite/llite_mmap.c +++ b/drivers/staging/lustre/lustre/llite/llite_mmap.c @@ -40,7 +40,6 @@ #include #include #include -#include #include #include From fff5096ff5f979346532693b01031731e504fd7d Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 24 Jul 2013 12:06:36 +0530 Subject: [PATCH 0578/3400] staging: lustre: Remove version.h header inclusion in lproc_llite.c version.h header inclusion is not necessary as detected by versioncheck. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/lproc_llite.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/llite/lproc_llite.c b/drivers/staging/lustre/lustre/llite/lproc_llite.c index a7b12fdd76b1..3ad391ae5894 100644 --- a/drivers/staging/lustre/lustre/llite/lproc_llite.c +++ b/drivers/staging/lustre/lustre/llite/lproc_llite.c @@ -35,7 +35,6 @@ */ #define DEBUG_SUBSYSTEM S_LLITE -#include #include #include #include From 4917e5bc033a844e1eefd3f2bf86965b887ba767 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 24 Jul 2013 12:06:37 +0530 Subject: [PATCH 0579/3400] staging: lustre: Remove version.h header inclusion in remote_perm.c version.h header inclusion is not necessary as detected by versioncheck. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/remote_perm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/llite/remote_perm.c b/drivers/staging/lustre/lustre/llite/remote_perm.c index 4f176e16e01c..0bc334803c90 100644 --- a/drivers/staging/lustre/lustre/llite/remote_perm.c +++ b/drivers/staging/lustre/lustre/llite/remote_perm.c @@ -45,7 +45,6 @@ #include #include -#include #include #include From 7dd39928e17b5c55145efdc013d1d375fb3b573f Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 24 Jul 2013 12:06:38 +0530 Subject: [PATCH 0580/3400] staging: lustre: Remove version.h header inclusion in super25.c version.h header inclusion is not necessary as detected by versioncheck. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/super25.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/llite/super25.c b/drivers/staging/lustre/lustre/llite/super25.c index ea06f1a18776..0beaf4e76b4b 100644 --- a/drivers/staging/lustre/lustre/llite/super25.c +++ b/drivers/staging/lustre/lustre/llite/super25.c @@ -38,7 +38,6 @@ #include #include -#include #include #include #include From 5995d8ac27aaa594431d738a98c43e6eaea1330a Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 24 Jul 2013 12:06:39 +0530 Subject: [PATCH 0581/3400] staging: lustre: Remove version.h header inclusion in symlink.c version.h header inclusion is not necessary as detected by versioncheck. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/symlink.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/llite/symlink.c b/drivers/staging/lustre/lustre/llite/symlink.c index 5260e989a4e5..9208afb95f12 100644 --- a/drivers/staging/lustre/lustre/llite/symlink.c +++ b/drivers/staging/lustre/lustre/llite/symlink.c @@ -37,7 +37,6 @@ #include #include #include -#include #define DEBUG_SUBSYSTEM S_LLITE #include From 0c3242044ba3b0cf7794d628b837a9466f819088 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 24 Jul 2013 12:06:40 +0530 Subject: [PATCH 0582/3400] staging: lustre: Remove version.h header inclusion in lproc_lmv.c version.h header inclusion is not necessary as detected by versioncheck. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/lmv/lproc_lmv.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/lmv/lproc_lmv.c b/drivers/staging/lustre/lustre/lmv/lproc_lmv.c index d1c45b583cbb..edb5a3a99d57 100644 --- a/drivers/staging/lustre/lustre/lmv/lproc_lmv.c +++ b/drivers/staging/lustre/lustre/lmv/lproc_lmv.c @@ -36,7 +36,6 @@ #define DEBUG_SUBSYSTEM S_CLASS -#include #include #include #include From 386ac14033da97aba40f17675f33acdf7a310691 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 24 Jul 2013 12:06:41 +0530 Subject: [PATCH 0583/3400] staging: lustre: Remove version.h header inclusion in lproc_lov.c version.h header inclusion is not necessary as detected by versioncheck. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/lov/lproc_lov.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/lov/lproc_lov.c b/drivers/staging/lustre/lustre/lov/lproc_lov.c index 5b2c0d88add1..15744e13a3f2 100644 --- a/drivers/staging/lustre/lustre/lov/lproc_lov.c +++ b/drivers/staging/lustre/lustre/lov/lproc_lov.c @@ -35,7 +35,6 @@ */ #define DEBUG_SUBSYSTEM S_CLASS -#include #include #include #include From 18b98a3b489ddb7cf0afb155a311da791d5f012c Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 24 Jul 2013 12:06:42 +0530 Subject: [PATCH 0584/3400] staging: lustre: Remove version.h header inclusion in fsfilt_ext3.c version.h header inclusion is not necessary as detected by versioncheck. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/lvfs/fsfilt_ext3.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/lvfs/fsfilt_ext3.c b/drivers/staging/lustre/lustre/lvfs/fsfilt_ext3.c index c1e99b37572e..ee75994003e1 100644 --- a/drivers/staging/lustre/lustre/lvfs/fsfilt_ext3.c +++ b/drivers/staging/lustre/lustre/lvfs/fsfilt_ext3.c @@ -48,7 +48,6 @@ #include #include #include -#include #include #include From 828dd755b76d8a83b6f3aa9fd34a0fd60b8787ba Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 24 Jul 2013 12:06:43 +0530 Subject: [PATCH 0585/3400] staging: lustre: Remove version.h header inclusion in lvfs_linux.c version.h header inclusion is not necessary as detected by versioncheck. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/lvfs/lvfs_linux.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c b/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c index e70d8fe99888..80b841a049cd 100644 --- a/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c +++ b/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c @@ -40,13 +40,11 @@ #define DEBUG_SUBSYSTEM S_FILTER -#include #include #include #include #include #include -#include #include #include #include From 777a9f4aa7dcd2c1c3573a5c0e739286678d509b Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 24 Jul 2013 12:06:44 +0530 Subject: [PATCH 0586/3400] staging: lustre: Remove version.h header inclusion in lproc_mdc.c version.h header inclusion is not necessary as detected by versioncheck. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/mdc/lproc_mdc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/mdc/lproc_mdc.c b/drivers/staging/lustre/lustre/mdc/lproc_mdc.c index 6592478e9b6d..75300847f912 100644 --- a/drivers/staging/lustre/lustre/mdc/lproc_mdc.c +++ b/drivers/staging/lustre/lustre/mdc/lproc_mdc.c @@ -35,7 +35,6 @@ */ #define DEBUG_SUBSYSTEM S_CLASS -#include #include #include #include From 0564e2aa47b103ab6b3cae489188a85871b96400 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 24 Jul 2013 12:06:45 +0530 Subject: [PATCH 0587/3400] staging: lustre: Remove version.h header inclusion in lproc_mgc.c version.h header inclusion is not necessary as detected by versioncheck. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/mgc/lproc_mgc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/mgc/lproc_mgc.c b/drivers/staging/lustre/lustre/mgc/lproc_mgc.c index 1105eaa24313..ebecec2b0078 100644 --- a/drivers/staging/lustre/lustre/mgc/lproc_mgc.c +++ b/drivers/staging/lustre/lustre/mgc/lproc_mgc.c @@ -35,7 +35,6 @@ */ #define DEBUG_SUBSYSTEM S_CLASS -#include #include #include #include From c3f8f3d83adadacf3ba0835a8100ddf399ce9940 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 24 Jul 2013 12:06:46 +0530 Subject: [PATCH 0588/3400] staging: lustre: Remove version.h header inclusion in capa.c version.h header inclusion is not necessary as detected by versioncheck. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/capa.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/obdclass/capa.c b/drivers/staging/lustre/lustre/obdclass/capa.c index 3e532f5106e4..5eea9bec054a 100644 --- a/drivers/staging/lustre/lustre/obdclass/capa.c +++ b/drivers/staging/lustre/lustre/obdclass/capa.c @@ -42,7 +42,6 @@ #define DEBUG_SUBSYSTEM S_SEC -#include #include #include #include From b17984687cea1362f26f4444d9238df876b255ef Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 24 Jul 2013 12:06:47 +0530 Subject: [PATCH 0589/3400] staging: lustre: Remove version.h header inclusion in linux-sysctl.c version.h header inclusion is not necessary as detected by versioncheck. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c index 7b94cb7b58e0..8fe6a019d1e3 100644 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c +++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include From 831ed1965233e93b7c9f64b038c2254cad7e3139 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 24 Jul 2013 12:06:48 +0530 Subject: [PATCH 0590/3400] staging: lustre: Remove version.h header inclusion in obd_mount.c version.h header inclusion is not necessary as detected by versioncheck. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/obd_mount.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/obdclass/obd_mount.c b/drivers/staging/lustre/lustre/obdclass/obd_mount.c index f5585ccaff19..28d174ab750d 100644 --- a/drivers/staging/lustre/lustre/obdclass/obd_mount.c +++ b/drivers/staging/lustre/lustre/obdclass/obd_mount.c @@ -50,7 +50,6 @@ #include #include #include -#include #include #include #include From 8688a49cd95839d881948b5b074077d786e3be6c Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 24 Jul 2013 12:06:49 +0530 Subject: [PATCH 0591/3400] staging: lustre: Remove version.h header inclusion in lproc_osc.c version.h header inclusion is not necessary as detected by versioncheck. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/osc/lproc_osc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/osc/lproc_osc.c b/drivers/staging/lustre/lustre/osc/lproc_osc.c index d2f219877927..90d24d8dea21 100644 --- a/drivers/staging/lustre/lustre/osc/lproc_osc.c +++ b/drivers/staging/lustre/lustre/osc/lproc_osc.c @@ -35,7 +35,6 @@ */ #define DEBUG_SUBSYSTEM S_CLASS -#include #include #include #include From 305591a58d855d0f82a582059596124f9a3503c2 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 09:55:00 -0700 Subject: [PATCH 0592/3400] staging: comedi: ni_mio_common: needs As reported by the kbuild test robot: Commit: d92fef8d2552ffde42b6092cb467f3021ebf8b98 staging: comedi: do not include if its not needed Removed the include from the ni_atmio driver, which did not need it. Unfortunately, this driver includes ni_mio_common.c, which does need it. Add the include of to the ni_mio_common.c source where it is needed. Signed-off-by: H Hartley Sweeten Reported-by: kbuild test robot Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_mio_common.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 458331d3fcb7..04f4b7dce332 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -58,6 +58,7 @@ #include #include +#include #include "8255.h" #include "mite.h" #include "comedi_fc.h" From 76a1de328462f353950ba1e614da1cef1e95bdc1 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 09:55:39 -0700 Subject: [PATCH 0593/3400] staging: comedi: comedi_buf: needs As reported by the kbuild test robot: Commit: ce157f8032bbd46d9427034c335b0afd751da25d staging: comedi: con't rely on comedidev.h to include headers Removed most the includes from comedidev.h and pushed only the needed ones to all the comedi drivers. This one was missed. Signed-off-by: H Hartley Sweeten Reported-by: kbuild test robot Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_buf.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/comedi/comedi_buf.c b/drivers/staging/comedi/comedi_buf.c index b4c001b6f88f..94b2385fb0af 100644 --- a/drivers/staging/comedi/comedi_buf.c +++ b/drivers/staging/comedi/comedi_buf.c @@ -15,6 +15,8 @@ * GNU General Public License for more details. */ +#include + #include "comedidev.h" #include "comedi_internal.h" From 66f42cc2187ea2cc624adda597fc1506ca1af176 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Jul 2013 10:06:35 -0700 Subject: [PATCH 0594/3400] staging: lustre: remove [f]printf() macros that aren't being used This isn't userspace, it's the kernel, luckily these weren't being used, so just remove them entirely so no one gets any ideas... Cc: Peng Tao Cc: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/linux/kp30.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h b/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h index 2e5c85071647..5bd09ccf3a3c 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h @@ -83,8 +83,6 @@ /******************************************************************************/ -# define fprintf(a, format, b...) CDEBUG(D_OTHER, format , ## b) -# define printf(format, b...) CDEBUG(D_OTHER, format , ## b) # define time(a) CURRENT_TIME /******************************************************************************/ From 0f1c743b992908ac2a31c7fec0e0fcac003deee5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Jul 2013 10:11:47 -0700 Subject: [PATCH 0595/3400] staging: lustre: don't use time() or CFS_CURRENT_TIME It's just "CURRENT_TIME", don't redefine a macro for something so simple as that... Cc: Peng Tao Cc: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/include/linux/libcfs/libcfs_private.h | 4 ---- drivers/staging/lustre/include/linux/libcfs/linux/kp30.h | 4 ---- drivers/staging/lustre/lustre/llite/llite_lib.c | 6 +++--- drivers/staging/lustre/lustre/osc/osc_io.c | 4 ++-- 4 files changed, 5 insertions(+), 13 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h index 62ef8a749002..b033aa499def 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h @@ -455,10 +455,6 @@ int cfs_match_nid(lnet_nid_t nid, struct list_head *list); /* logical equivalence */ #define equi(a, b) (!!(a) == !!(b)) -#ifndef CFS_CURRENT_TIME -# define CFS_CURRENT_TIME time(0) -#endif - /* -------------------------------------------------------------------- * Light-weight trace * Support for temporary event tracing with minimal Heisenberg effect. diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h b/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h index 5bd09ccf3a3c..073f4d1f176e 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/kp30.h @@ -81,10 +81,6 @@ #define CFS_SYSFS_MODULE_PARM 1 /* module parameters accessible via sysfs */ -/******************************************************************************/ - -# define time(a) CURRENT_TIME - /******************************************************************************/ /* Light-weight trace * Support for temporary event tracing with minimal Heisenberg effect. */ diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index e8bf49fa7bbf..890268834510 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -1408,17 +1408,17 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr) /* We mark all of the fields "set" so MDS/OST does not re-set them */ if (attr->ia_valid & ATTR_CTIME) { - attr->ia_ctime = CFS_CURRENT_TIME; + attr->ia_ctime = CURRENT_TIME; attr->ia_valid |= ATTR_CTIME_SET; } if (!(attr->ia_valid & ATTR_ATIME_SET) && (attr->ia_valid & ATTR_ATIME)) { - attr->ia_atime = CFS_CURRENT_TIME; + attr->ia_atime = CURRENT_TIME; attr->ia_valid |= ATTR_ATIME_SET; } if (!(attr->ia_valid & ATTR_MTIME_SET) && (attr->ia_valid & ATTR_MTIME)) { - attr->ia_mtime = CFS_CURRENT_TIME; + attr->ia_mtime = CURRENT_TIME; attr->ia_valid |= ATTR_MTIME_SET; } diff --git a/drivers/staging/lustre/lustre/osc/osc_io.c b/drivers/staging/lustre/lustre/osc/osc_io.c index 70aad1aeec63..342c46e2c91d 100644 --- a/drivers/staging/lustre/lustre/osc/osc_io.c +++ b/drivers/staging/lustre/lustre/osc/osc_io.c @@ -523,7 +523,7 @@ static int osc_io_read_start(const struct lu_env *env, cl_object_attr_lock(obj); result = cl_object_attr_get(env, obj, attr); if (result == 0) { - attr->cat_atime = LTIME_S(CFS_CURRENT_TIME); + attr->cat_atime = LTIME_S(CURRENT_TIME); result = cl_object_attr_set(env, obj, attr, CAT_ATIME); } @@ -547,7 +547,7 @@ static int osc_io_write_start(const struct lu_env *env, result = cl_object_attr_get(env, obj, attr); if (result == 0) { attr->cat_mtime = attr->cat_ctime = - LTIME_S(CFS_CURRENT_TIME); + LTIME_S(CURRENT_TIME); result = cl_object_attr_set(env, obj, attr, CAT_MTIME | CAT_CTIME); } From c0426cf7df119c68a9715713f9dbf07862172f04 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Jul 2013 10:21:26 -0700 Subject: [PATCH 0596/3400] staging: lustre: a typedef for 'struct miscdevice'??? Come on, that's just silly... Anyway, remove the typedef and fix up the initializer to use named fields, otherwise bad things might happen in the future. Cc: Peng Tao Cc: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/include/linux/libcfs/libcfs.h | 5 ----- .../lustre/include/linux/libcfs/linux/linux-prim.h | 14 -------------- .../lustre/lustre/libcfs/linux/linux-module.c | 8 ++++---- drivers/staging/lustre/lustre/libcfs/module.c | 2 +- drivers/staging/lustre/lustre/obdclass/class_obd.c | 2 +- .../lustre/lustre/obdclass/linux/linux-module.c | 2 +- 6 files changed, 7 insertions(+), 26 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs.h b/drivers/staging/lustre/include/linux/libcfs/libcfs.h index 2983ce412b66..0f76da5c6c2d 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs.h @@ -124,11 +124,6 @@ void libcfs_sock_release(socket_t *sock); /* * libcfs pseudo device operations * - * struct psdev_t and - * misc_register() and - * misc_deregister() are declared in - * libcfs//-prim.h - * * It's just draft now. */ diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/linux-prim.h b/drivers/staging/lustre/include/linux/libcfs/linux/linux-prim.h index acdf7ee089f2..03903ab8f0cc 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/linux-prim.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/linux-prim.h @@ -78,20 +78,6 @@ #define NR_CPUS 1 #endif -/* - * cache - */ - -/* - * IRQs - */ - - -/* - * Pseudo device register - */ -typedef struct miscdevice psdev_t; - /* * Sysctl register */ diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c index 6b0054ff7915..d8f320e6f4b6 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c @@ -176,8 +176,8 @@ static struct file_operations libcfs_fops = { release : libcfs_psdev_release }; -psdev_t libcfs_dev = { - LNET_MINOR, - "lnet", - &libcfs_fops +struct miscdevice libcfs_dev = { + .minor = LNET_MINOR, + .name = "lnet", + .fops = &libcfs_fops, }; diff --git a/drivers/staging/lustre/lustre/libcfs/module.c b/drivers/staging/lustre/lustre/libcfs/module.c index 3372537c6f3b..52525bc7ddb0 100644 --- a/drivers/staging/lustre/lustre/libcfs/module.c +++ b/drivers/staging/lustre/lustre/libcfs/module.c @@ -365,7 +365,7 @@ MODULE_AUTHOR("Peter J. Braam "); MODULE_DESCRIPTION("Portals v3.1"); MODULE_LICENSE("GPL"); -extern psdev_t libcfs_dev; +extern struct miscdevice libcfs_dev; extern struct rw_semaphore cfs_tracefile_sem; extern struct mutex cfs_trace_thread_mutex; extern struct cfs_wi_sched *cfs_sched_rehash; diff --git a/drivers/staging/lustre/lustre/obdclass/class_obd.c b/drivers/staging/lustre/lustre/obdclass/class_obd.c index 799a1ed8701f..deebf806cde0 100644 --- a/drivers/staging/lustre/lustre/obdclass/class_obd.c +++ b/drivers/staging/lustre/lustre/obdclass/class_obd.c @@ -432,7 +432,7 @@ int class_handle_ioctl(unsigned int cmd, unsigned long arg) RETURN(err); } /* class_handle_ioctl */ -extern psdev_t obd_psdev; +extern struct miscdevice obd_psdev; #define OBD_INIT_CHECK int obd_init_checks(void) diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c index 2abacf206531..9fe53f3a98ce 100644 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c +++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c @@ -211,7 +211,7 @@ static struct file_operations obd_psdev_fops = { }; /* modules setup */ -psdev_t obd_psdev = { +struct miscdevice obd_psdev = { .minor = OBD_DEV_MINOR, .name = OBD_DEV_NAME, .fops = &obd_psdev_fops, From 847e0fb220799debd44cb4b8526a248a287913d9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Jul 2013 10:25:17 -0700 Subject: [PATCH 0597/3400] staging: lustre: NR_CPUS is always defined So don't redefine it. Cc: Peng Tao Cc: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/include/linux/libcfs/linux/linux-cpu.h | 1 - .../staging/lustre/include/linux/libcfs/linux/linux-prim.h | 5 ----- .../lustre/include/linux/libcfs/linux/portals_compat25.h | 5 ----- 3 files changed, 11 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/linux-cpu.h b/drivers/staging/lustre/include/linux/libcfs/linux/linux-cpu.h index 36928791e75d..8dd354d51606 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/linux-cpu.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/linux-cpu.h @@ -81,7 +81,6 @@ struct cfs_cpt_table { /** * comment out definitions for compatible layer - * #define CFS_CPU_NR NR_CPUS * * typedef cpumask_t cfs_cpumask_t; * diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/linux-prim.h b/drivers/staging/lustre/include/linux/libcfs/linux/linux-prim.h index 03903ab8f0cc..e2a6c10ae4e6 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/linux-prim.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/linux-prim.h @@ -73,11 +73,6 @@ #define cfs_for_each_possible_cpu(cpu) for_each_cpu(cpu) #endif -#ifdef NR_CPUS -#else -#define NR_CPUS 1 -#endif - /* * Sysctl register */ diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/portals_compat25.h b/drivers/staging/lustre/include/linux/libcfs/linux/portals_compat25.h index 132a4bec3575..6cf758dbf9ef 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/portals_compat25.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/portals_compat25.h @@ -104,11 +104,6 @@ int proc_call_handler(void *data, int write, #define cfs_for_each_possible_cpu(cpu) for_each_cpu(cpu) #endif -#ifdef NR_CPUS -#else -#define NR_CPUS 1 -#endif - #define cfs_register_sysctl_table(t, a) register_sysctl_table(t) #endif /* _PORTALS_COMPAT_H */ From 78eb90927139abc3048056820611722f4b5247f6 Mon Sep 17 00:00:00 2001 From: Thomas Leibovici Date: Thu, 25 Jul 2013 01:17:24 +0800 Subject: [PATCH 0598/3400] staging/lustre/lmv: support DNE with HSM. Send HSM requests to the appropriate MDT. Split lists of fids of HSM actions into one list per MDT. Move kuc registration/unregistration from MDC to LMV as this is not MDT related. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3365 Lustre-change: http://review.whamcloud.com/6714 Signed-off-by: Thomas Leibovici Reviewed-by: John L. Hammond Reviewed-by: jacques-Charles Lafoucriere Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/lmv/lmv_obd.c | 200 +++++++++++++++++- .../staging/lustre/lustre/mdc/mdc_request.c | 18 +- 2 files changed, 205 insertions(+), 13 deletions(-) diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 5bd952a6dd65..11c8d644d5ea 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -783,6 +784,125 @@ out_fid2path: RETURN(rc); } +static int lmv_hsm_req_count(struct lmv_obd *lmv, + const struct hsm_user_request *hur, + const struct lmv_tgt_desc *tgt_mds) +{ + int i, nr = 0; + struct lmv_tgt_desc *curr_tgt; + + /* count how many requests must be sent to the given target */ + for (i = 0; i < hur->hur_request.hr_itemcount; i++) { + curr_tgt = lmv_find_target(lmv, &hur->hur_user_item[i].hui_fid); + if (obd_uuid_equals(&curr_tgt->ltd_uuid, &tgt_mds->ltd_uuid)) + nr++; + } + return nr; +} + +static void lmv_hsm_req_build(struct lmv_obd *lmv, + struct hsm_user_request *hur_in, + const struct lmv_tgt_desc *tgt_mds, + struct hsm_user_request *hur_out) +{ + int i, nr_out; + struct lmv_tgt_desc *curr_tgt; + + /* build the hsm_user_request for the given target */ + hur_out->hur_request = hur_in->hur_request; + nr_out = 0; + for (i = 0; i < hur_in->hur_request.hr_itemcount; i++) { + curr_tgt = lmv_find_target(lmv, + &hur_in->hur_user_item[i].hui_fid); + if (obd_uuid_equals(&curr_tgt->ltd_uuid, &tgt_mds->ltd_uuid)) { + hur_out->hur_user_item[nr_out] = + hur_in->hur_user_item[i]; + nr_out++; + } + } + hur_out->hur_request.hr_itemcount = nr_out; + memcpy(hur_data(hur_out), hur_data(hur_in), + hur_in->hur_request.hr_data_len); +} + +static int lmv_hsm_ct_unregister(struct lmv_obd *lmv, unsigned int cmd, int len, + struct lustre_kernelcomm *lk, void *uarg) +{ + int i, rc = 0; + ENTRY; + + /* unregister request (call from llapi_hsm_copytool_fini) */ + for (i = 0; i < lmv->desc.ld_tgt_count; i++) { + /* best effort: try to clean as much as possible + * (continue on error) */ + obd_iocontrol(cmd, lmv->tgts[i]->ltd_exp, len, lk, uarg); + } + + /* Whatever the result, remove copytool from kuc groups. + * Unreached coordinators will get EPIPE on next requests + * and will unregister automatically. + */ + rc = libcfs_kkuc_group_rem(lk->lk_uid, lk->lk_group); + RETURN(rc); +} + +static int lmv_hsm_ct_register(struct lmv_obd *lmv, unsigned int cmd, int len, + struct lustre_kernelcomm *lk, void *uarg) +{ + struct file *filp; + int i, j, err; + int rc = 0; + bool any_set = false; + ENTRY; + + /* All or nothing: try to register to all MDS. + * In case of failure, unregister from previous MDS, + * except if it because of inactive target. */ + for (i = 0; i < lmv->desc.ld_tgt_count; i++) { + err = obd_iocontrol(cmd, lmv->tgts[i]->ltd_exp, + len, lk, uarg); + if (err) { + if (lmv->tgts[i]->ltd_active) { + /* permanent error */ + CERROR("error: iocontrol MDC %s on MDT" + "idx %d cmd %x: err = %d\n", + lmv->tgts[i]->ltd_uuid.uuid, + i, cmd, err); + rc = err; + lk->lk_flags |= LK_FLG_STOP; + /* unregister from previous MDS */ + for (j = 0; j < i; j++) + obd_iocontrol(cmd, + lmv->tgts[j]->ltd_exp, + len, lk, uarg); + RETURN(rc); + } + /* else: transient error. + * kuc will register to the missing MDT + * when it is back */ + } else { + any_set = true; + } + } + + if (!any_set) + /* no registration done: return error */ + RETURN(-ENOTCONN); + + /* at least one registration done, with no failure */ + filp = fget(lk->lk_wfd); + if (filp == NULL) { + RETURN(-EBADF); + } + rc = libcfs_kkuc_group_add(filp, lk->lk_uid, lk->lk_group, lk->lk_data); + if (rc != 0 && filp != NULL) + fput(filp); + RETURN(rc); +} + + + + static int lmv_iocontrol(unsigned int cmd, struct obd_export *exp, int len, void *karg, void *uarg) { @@ -908,7 +1028,77 @@ static int lmv_iocontrol(unsigned int cmd, struct obd_export *exp, } case LL_IOC_HSM_STATE_GET: case LL_IOC_HSM_STATE_SET: - case LL_IOC_HSM_ACTION: + case LL_IOC_HSM_ACTION: { + struct md_op_data *op_data = karg; + struct lmv_tgt_desc *tgt; + + tgt = lmv_find_target(lmv, &op_data->op_fid1); + if (IS_ERR(tgt)) + RETURN(PTR_ERR(tgt)); + + if (tgt->ltd_exp == NULL) + RETURN(-EINVAL); + + rc = obd_iocontrol(cmd, tgt->ltd_exp, len, karg, uarg); + break; + } + case LL_IOC_HSM_PROGRESS: { + const struct hsm_progress_kernel *hpk = karg; + struct lmv_tgt_desc *tgt; + + tgt = lmv_find_target(lmv, &hpk->hpk_fid); + if (IS_ERR(tgt)) + RETURN(PTR_ERR(tgt)); + rc = obd_iocontrol(cmd, tgt->ltd_exp, len, karg, uarg); + break; + } + case LL_IOC_HSM_REQUEST: { + struct hsm_user_request *hur = karg; + struct lmv_tgt_desc *tgt; + unsigned int reqcount = hur->hur_request.hr_itemcount; + + if (reqcount == 0) + RETURN(0); + + /* if the request is about a single fid + * or if there is a single MDS, no need to split + * the request. */ + if (reqcount == 1 || count == 1) { + tgt = lmv_find_target(lmv, + &hur->hur_user_item[0].hui_fid); + if (IS_ERR(tgt)) + RETURN(PTR_ERR(tgt)); + rc = obd_iocontrol(cmd, tgt->ltd_exp, len, karg, uarg); + } else { + /* split fid list to their respective MDS */ + for (i = 0; i < count; i++) { + unsigned int nr, reqlen; + int rc1; + struct hsm_user_request *req; + + nr = lmv_hsm_req_count(lmv, hur, lmv->tgts[i]); + if (nr == 0) /* nothing for this MDS */ + continue; + + /* build a request with fids for this MDS */ + reqlen = offsetof(typeof(*hur), + hur_user_item[nr]) + + hur->hur_request.hr_data_len; + OBD_ALLOC_LARGE(req, reqlen); + if (req == NULL) + RETURN(-ENOMEM); + + lmv_hsm_req_build(lmv, hur, lmv->tgts[i], req); + + rc1 = obd_iocontrol(cmd, lmv->tgts[i]->ltd_exp, + reqlen, req, uarg); + if (rc1 != 0 && rc == 0) + rc = rc1; + OBD_FREE_LARGE(req, reqlen); + } + } + break; + } case LL_IOC_LOV_SWAP_LAYOUTS: { struct md_op_data *op_data = karg; struct lmv_tgt_desc *tgt1, *tgt2; @@ -931,6 +1121,14 @@ static int lmv_iocontrol(unsigned int cmd, struct obd_export *exp, rc = obd_iocontrol(cmd, tgt1->ltd_exp, len, karg, uarg); break; } + case LL_IOC_HSM_CT_START: { + struct lustre_kernelcomm *lk = karg; + if (lk->lk_flags & LK_FLG_STOP) + rc = lmv_hsm_ct_unregister(lmv, cmd, len, lk, uarg); + else + rc = lmv_hsm_ct_register(lmv, cmd, len, lk, uarg); + break; + } default: for (i = 0; i < count; i++) { struct obd_device *mdc_obd; diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index b8bf2dcee09f..191edc6470cd 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -1771,6 +1771,9 @@ static int mdc_iocontrol(unsigned int cmd, struct obd_export *exp, int len, GOTO(out, rc); case LL_IOC_HSM_CT_START: rc = mdc_ioc_hsm_ct_start(exp, karg); + /* ignore if it was already registered on this MDS. */ + if (rc == -EEXIST) + rc = 0; GOTO(out, rc); case LL_IOC_HSM_PROGRESS: rc = mdc_ioc_hsm_progress(exp, karg); @@ -1988,19 +1991,10 @@ static int mdc_ioc_hsm_ct_start(struct obd_export *exp, lk->lk_uid, lk->lk_group, lk->lk_flags); if (lk->lk_flags & LK_FLG_STOP) { - rc = libcfs_kkuc_group_rem(lk->lk_uid, lk->lk_group); /* Unregister with the coordinator */ - if (rc == 0) - rc = mdc_ioc_hsm_ct_unregister(imp); + rc = mdc_ioc_hsm_ct_unregister(imp); } else { - struct file *fp = fget(lk->lk_wfd); - - rc = libcfs_kkuc_group_add(fp, lk->lk_uid, lk->lk_group, - lk->lk_data); - if (rc && fp) - fput(fp); - if (rc == 0) - rc = mdc_ioc_hsm_ct_register(imp, archive); + rc = mdc_ioc_hsm_ct_register(imp, archive); } return rc; @@ -2325,7 +2319,7 @@ static int mdc_import_event(struct obd_device *obd, struct obd_import *imp, } case IMP_EVENT_ACTIVE: rc = obd_notify_observer(obd, obd, OBD_NOTIFY_ACTIVE, NULL); - /* restore re-establish kuc registration after reconnecting */ + /* redo the kuc registration after reconnecting */ if (rc == 0) rc = mdc_kuc_reregister(imp); break; From 8a48df7080b2fa0aed2b8df74437a39217c1eb8c Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Thu, 25 Jul 2013 01:17:25 +0800 Subject: [PATCH 0599/3400] staging/lustre/llite: handle io init failure in ll_fault_io_init() In ll_fault_io_init(), if cl_io_init() has failed then cleanup and return an ERR_PTR(). This fixes an oops in the page fault handling code when a partially initialized io is used. In ll_page_mkwrite0() do not call cl_io_fini() on an ERR_PTR(). Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3487 Lustre-change: http://review.whamcloud.com/6735 Signed-off-by: John L. Hammond Reviewed-by: Lai Siyao Reviewed-by: Jinshan Xiong Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/llite/llite_mmap.c | 36 +++++++++++-------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/llite_mmap.c b/drivers/staging/lustre/lustre/llite/llite_mmap.c index 32a57e85300b..a4061ee15b62 100644 --- a/drivers/staging/lustre/lustre/llite/llite_mmap.c +++ b/drivers/staging/lustre/lustre/llite/llite_mmap.c @@ -106,11 +106,12 @@ struct cl_io *ll_fault_io_init(struct vm_area_struct *vma, struct cl_env_nest *nest, pgoff_t index, unsigned long *ra_flags) { - struct file *file = vma->vm_file; - struct inode *inode = file->f_dentry->d_inode; - struct cl_io *io; - struct cl_fault_io *fio; - struct lu_env *env; + struct file *file = vma->vm_file; + struct inode *inode = file->f_dentry->d_inode; + struct cl_io *io; + struct cl_fault_io *fio; + struct lu_env *env; + int rc; ENTRY; *env_ret = NULL; @@ -151,17 +152,22 @@ struct cl_io *ll_fault_io_init(struct vm_area_struct *vma, CDEBUG(D_MMAP, "vm_flags: %lx (%lu %d)\n", vma->vm_flags, fio->ft_index, fio->ft_executable); - if (cl_io_init(env, io, CIT_FAULT, io->ci_obj) == 0) { + rc = cl_io_init(env, io, CIT_FAULT, io->ci_obj); + if (rc == 0) { struct ccc_io *cio = ccc_env_io(env); struct ll_file_data *fd = LUSTRE_FPRIVATE(file); LASSERT(cio->cui_cl.cis_io == io); - /* mmap lock must be MANDATORY - * it has to cache pages. */ + /* mmap lock must be MANDATORY it has to cache + * pages. */ io->ci_lockreq = CILR_MANDATORY; - - cio->cui_fd = fd; + cio->cui_fd = fd; + } else { + LASSERT(rc < 0); + cl_io_fini(env, io); + cl_env_nested_put(nest, env); + io = ERR_PTR(rc); } return io; @@ -189,7 +195,7 @@ static int ll_page_mkwrite0(struct vm_area_struct *vma, struct page *vmpage, result = io->ci_result; if (result < 0) - GOTO(out, result); + GOTO(out_io, result); io->u.ci_fault.ft_mkwrite = 1; io->u.ci_fault.ft_writable = 1; @@ -251,14 +257,14 @@ static int ll_page_mkwrite0(struct vm_area_struct *vma, struct page *vmpage, } EXIT; -out: +out_io: cl_io_fini(env, io); cl_env_nested_put(&nest, env); - +out: CDEBUG(D_MMAP, "%s mkwrite with %d\n", current->comm, result); - LASSERT(ergo(result == 0, PageLocked(vmpage))); - return(result); + + return result; } From f84d3d4735a1c96a745c453de8390936a7eb72d3 Mon Sep 17 00:00:00 2001 From: Sebastien Buisson Date: Thu, 25 Jul 2013 01:17:26 +0800 Subject: [PATCH 0600/3400] staging/lustre: fix 'data race condition' issues in at_reset() Fix 'data race condition' defects found by Coverity version 6.5.0: Data race condition (MISSING_LOCK) Accessing variable without holding lock. Elsewhere, this variable is accessed with lock held. at_reset() needs to take at->at_lock before modifying its members. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2744 Lustre-change: http://review.whamcloud.com/6569 Signed-off-by: Sebastien Buisson Reviewed-by: Bob Glossman Reviewed-by: Keith Mannthey Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lustre_import.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/lustre/lustre/include/lustre_import.h b/drivers/staging/lustre/lustre/include/lustre_import.h index 3a5dd6a94c08..67259eb43cde 100644 --- a/drivers/staging/lustre/lustre/include/lustre_import.h +++ b/drivers/staging/lustre/lustre/include/lustre_import.h @@ -336,9 +336,11 @@ static inline unsigned int at_timeout2est(unsigned int val) } static inline void at_reset(struct adaptive_timeout *at, int val) { + spin_lock(&at->at_lock); at->at_current = val; at->at_worst_ever = val; at->at_worst_time = cfs_time_current_sec(); + spin_unlock(&at->at_lock); } static inline void at_init(struct adaptive_timeout *at, int val, int flags) { memset(at, 0, sizeof(*at)); From ae5ef67b9a71dba0dc4b045cca102c4ab3c0bd5f Mon Sep 17 00:00:00 2001 From: Sebastien Buisson Date: Thu, 25 Jul 2013 01:17:27 +0800 Subject: [PATCH 0601/3400] staging/lustre/llite: fix 'data race condition' issues of lli_flags Fix 'data race condition' defects found by Coverity version 6.5.0: Data race condition (MISSING_LOCK) Accessing variable without holding lock. Elsewhere, this variable is accessed with lock held. lli->lli_flags need to be protected by lli->lli_lock. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2744 Lustre-change: http://review.whamcloud.com/6571 Signed-off-by: Sebastien Buisson Reviewed-by: Fan Yong Reviewed-by: Keith Mannthey Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/llite_lib.c | 4 ++++ drivers/staging/lustre/lustre/llite/namei.c | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 890268834510..b44a3d6d0edd 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -1189,7 +1189,9 @@ void ll_clear_inode(struct inode *inode) LASSERT(lli->lli_opendir_pid == 0); } + spin_lock(&lli->lli_lock); ll_i2info(inode)->lli_flags &= ~LLIF_MDS_SIZE_LOCK; + spin_unlock(&lli->lli_lock); md_null_inode(sbi->ll_md_exp, ll_inode2fid(inode)); LASSERT(!lli->lli_open_fd_write_count); @@ -1756,7 +1758,9 @@ void ll_update_inode(struct inode *inode, struct lustre_md *md) /* Use old size assignment to avoid * deadlock bz14138 & bz14326 */ i_size_write(inode, body->size); + spin_lock(&lli->lli_lock); lli->lli_flags |= LLIF_MDS_SIZE_LOCK; + spin_unlock(&lli->lli_lock); } ldlm_lock_decref(&lockh, mode); } diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index 8e948a71dd64..333e55f692f1 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -275,8 +275,11 @@ int ll_md_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc, CDEBUG(D_INODE, "invaliding layout %d.\n", rc); } - if (bits & MDS_INODELOCK_UPDATE) + if (bits & MDS_INODELOCK_UPDATE) { + spin_lock(&lli->lli_lock); lli->lli_flags &= ~LLIF_MDS_SIZE_LOCK; + spin_unlock(&lli->lli_lock); + } if (S_ISDIR(inode->i_mode) && (bits & MDS_INODELOCK_UPDATE)) { From 631abc6e65a7777afcdfa126343db99eaba03c3b Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Thu, 25 Jul 2013 01:17:30 +0800 Subject: [PATCH 0602/3400] staging/lustre/obdclass: use a dummy structure for lu_ref_link Move the definition of struct lu_ref_link to lu_ref.h. If USE_LU_REF is not defined then define it to be the empty struct. Change the return type of lu_ref_add() and lu_ref_add_atomic() to void. Add lu_ref_add_at() taking same arguments as lu_ref_add() togerther with a pointer to a struct lu_ref_link and returning void. Adjust all structures containing a lu_ref_link pointer to contain a struct lu_ref_link instead. Use lu_ref_add_at() and lu_ref_del_at() to handle embedded lu_ref_links. [Original patch mainly changes lu_ref.[ch] but in upstream client we don't have lu_ref code in the hope of moving to kobject refcounting. So the patch only picks the other pieces of original patch, in order to keep code in sync and make it easier to port future patches.] Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3059 Lustre-change: http://review.whamcloud.com/5920 Signed-off-by: John L. Hammond Reviewed-by: Alex Zhuravlev Reviewed-by: Jinshan Xiong Reviewed-by: Mike Pershin Reviewed-by: Oleg Drokin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/include/cl_object.h | 10 +++++----- .../staging/lustre/lustre/include/lu_object.h | 18 +++++++++++++----- drivers/staging/lustre/lustre/include/lu_ref.h | 14 +++++++++++++- drivers/staging/lustre/lustre/obdclass/cl_io.c | 17 +++++++++-------- .../staging/lustre/lustre/obdclass/cl_lock.c | 6 +++--- .../staging/lustre/lustre/obdclass/cl_page.c | 5 +++-- .../staging/lustre/lustre/obdclass/lu_object.c | 15 ++++++++------- drivers/staging/lustre/lustre/osc/osc_cache.c | 8 +++++--- 8 files changed, 59 insertions(+), 34 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index 4bb68801d3a9..4a478504c45e 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -768,11 +768,11 @@ struct cl_page { /** List of references to this page, for debugging. */ struct lu_ref cp_reference; /** Link to an object, for debugging. */ - struct lu_ref_link *cp_obj_ref; + struct lu_ref_link cp_obj_ref; /** Link to a queue, for debugging. */ - struct lu_ref_link *cp_queue_ref; + struct lu_ref_link cp_queue_ref; /** Per-page flags from enum cl_page_flags. Protected by a VM lock. */ - unsigned cp_flags; + unsigned cp_flags; /** Assigned if doing a sync_io */ struct cl_sync_io *cp_sync_io; }; @@ -1625,7 +1625,7 @@ struct cl_lock { /** * A reference for cl_lock::cll_descr::cld_obj. For debugging. */ - struct lu_ref_link *cll_obj_ref; + struct lu_ref_link cll_obj_ref; #ifdef CONFIG_LOCKDEP /* "dep_map" name is assumed by lockdep.h macros. */ struct lockdep_map dep_map; @@ -2517,7 +2517,7 @@ struct cl_req_obj { /** object itself */ struct cl_object *ro_obj; /** reference to cl_req_obj::ro_obj. For debugging. */ - struct lu_ref_link *ro_obj_ref; + struct lu_ref_link ro_obj_ref; /* something else? Number of pages for a given object? */ }; diff --git a/drivers/staging/lustre/lustre/include/lu_object.h b/drivers/staging/lustre/lustre/include/lu_object.h index 94760481bd30..8077898e88ec 100644 --- a/drivers/staging/lustre/lustre/include/lu_object.h +++ b/drivers/staging/lustre/lustre/include/lu_object.h @@ -496,7 +496,7 @@ struct lu_object { /** * Link to the device, for debugging. */ - struct lu_ref_link *lo_dev_ref; + struct lu_ref_link lo_dev_ref; }; enum lu_object_header_flags { @@ -873,11 +873,19 @@ static inline __u32 lu_object_attr(const struct lu_object *o) return o->lo_header->loh_attr; } -static inline struct lu_ref_link *lu_object_ref_add(struct lu_object *o, - const char *scope, - const void *source) +static inline void lu_object_ref_add(struct lu_object *o, + const char *scope, + const void *source) { - return lu_ref_add(&o->lo_header->loh_reference, scope, source); + lu_ref_add(&o->lo_header->loh_reference, scope, source); +} + +static inline void lu_object_ref_add_at(struct lu_object *o, + struct lu_ref_link *link, + const char *scope, + const void *source) +{ + lu_ref_add_at(&o->lo_header->loh_reference, link, scope, source); } static inline void lu_object_ref_del(struct lu_object *o, diff --git a/drivers/staging/lustre/lustre/include/lu_ref.h b/drivers/staging/lustre/lustre/include/lu_ref.h index 624c19be1524..50a2a7f786dc 100644 --- a/drivers/staging/lustre/lustre/include/lu_ref.h +++ b/drivers/staging/lustre/lustre/include/lu_ref.h @@ -108,7 +108,12 @@ */ -struct lu_ref {}; +/* + * dummy data structures/functions to pass compile for now. + * We need to reimplement them with kref. + */ +struct lu_ref {}; +struct lu_ref_link {}; static inline void lu_ref_init(struct lu_ref *ref) { @@ -132,6 +137,13 @@ static inline struct lu_ref_link *lu_ref_add_atomic(struct lu_ref *ref, return NULL; } +static inline void lu_ref_add_at(struct lu_ref *ref, + struct lu_ref_link *link, + const char *scope, + const void *source) +{ +} + static inline void lu_ref_del(struct lu_ref *ref, const char *scope, const void *source) { diff --git a/drivers/staging/lustre/lustre/obdclass/cl_io.c b/drivers/staging/lustre/lustre/obdclass/cl_io.c index 75c9be8875e0..f3f03154f094 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_io.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_io.c @@ -1105,7 +1105,7 @@ void cl_page_list_add(struct cl_page_list *plist, struct cl_page *page) LASSERT(list_empty(&page->cp_batch)); list_add_tail(&page->cp_batch, &plist->pl_pages); ++plist->pl_nr; - page->cp_queue_ref = lu_ref_add(&page->cp_reference, "queue", plist); + lu_ref_add_at(&page->cp_reference, &page->cp_queue_ref, "queue", plist); cl_page_get(page); EXIT; } @@ -1126,7 +1126,7 @@ void cl_page_list_del(const struct lu_env *env, mutex_unlock(&page->cp_mutex); lockdep_on(); --plist->pl_nr; - lu_ref_del_at(&page->cp_reference, page->cp_queue_ref, "queue", plist); + lu_ref_del_at(&page->cp_reference, &page->cp_queue_ref, "queue", plist); cl_page_put(env, page); EXIT; } @@ -1146,8 +1146,8 @@ void cl_page_list_move(struct cl_page_list *dst, struct cl_page_list *src, list_move_tail(&page->cp_batch, &dst->pl_pages); --src->pl_nr; ++dst->pl_nr; - lu_ref_set_at(&page->cp_reference, - page->cp_queue_ref, "queue", src, dst); + lu_ref_set_at(&page->cp_reference, &page->cp_queue_ref, "queue", + src, dst); EXIT; } EXPORT_SYMBOL(cl_page_list_move); @@ -1202,7 +1202,8 @@ void cl_page_list_disown(const struct lu_env *env, * XXX cl_page_disown0() will fail if page is not locked. */ cl_page_disown0(env, io, page); - lu_ref_del(&page->cp_reference, "queue", plist); + lu_ref_del_at(&page->cp_reference, &page->cp_queue_ref, "queue", + plist); cl_page_put(env, page); } EXIT; @@ -1449,7 +1450,7 @@ static void cl_req_free(const struct lu_env *env, struct cl_req *req) struct cl_object *obj = req->crq_o[i].ro_obj; if (obj != NULL) { lu_object_ref_del_at(&obj->co_lu, - req->crq_o[i].ro_obj_ref, + &req->crq_o[i].ro_obj_ref, "cl_req", req); cl_object_put(env, obj); } @@ -1570,8 +1571,8 @@ void cl_req_page_add(const struct lu_env *env, if (rqo->ro_obj == NULL) { rqo->ro_obj = obj; cl_object_get(obj); - rqo->ro_obj_ref = lu_object_ref_add(&obj->co_lu, - "cl_req", req); + lu_object_ref_add_at(&obj->co_lu, &rqo->ro_obj_ref, + "cl_req", req); break; } } diff --git a/drivers/staging/lustre/lustre/obdclass/cl_lock.c b/drivers/staging/lustre/lustre/obdclass/cl_lock.c index d34e044fc854..958c1e531cfb 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_lock.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_lock.c @@ -267,7 +267,7 @@ static void cl_lock_free(const struct lu_env *env, struct cl_lock *lock) } CS_LOCK_DEC(obj, total); CS_LOCKSTATE_DEC(obj, lock->cll_state); - lu_object_ref_del_at(&obj->co_lu, lock->cll_obj_ref, "cl_lock", lock); + lu_object_ref_del_at(&obj->co_lu, &lock->cll_obj_ref, "cl_lock", lock); cl_object_put(env, obj); lu_ref_fini(&lock->cll_reference); lu_ref_fini(&lock->cll_holders); @@ -373,8 +373,8 @@ static struct cl_lock *cl_lock_alloc(const struct lu_env *env, lock->cll_descr = *descr; lock->cll_state = CLS_NEW; cl_object_get(obj); - lock->cll_obj_ref = lu_object_ref_add(&obj->co_lu, - "cl_lock", lock); + lu_object_ref_add_at(&obj->co_lu, &lock->cll_obj_ref, "cl_lock", + lock); INIT_LIST_HEAD(&lock->cll_layers); INIT_LIST_HEAD(&lock->cll_linkage); INIT_LIST_HEAD(&lock->cll_inclosure); diff --git a/drivers/staging/lustre/lustre/obdclass/cl_page.c b/drivers/staging/lustre/lustre/obdclass/cl_page.c index bb9335911c34..d9ca5d500570 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_page.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_page.c @@ -270,7 +270,7 @@ static void cl_page_free(const struct lu_env *env, struct cl_page *page) } CS_PAGE_DEC(obj, total); CS_PAGESTATE_DEC(obj, page->cp_state); - lu_object_ref_del_at(&obj->co_lu, page->cp_obj_ref, "cl_page", page); + lu_object_ref_del_at(&obj->co_lu, &page->cp_obj_ref, "cl_page", page); cl_object_put(env, obj); lu_ref_fini(&page->cp_reference); OBD_FREE(page, pagesize); @@ -305,7 +305,8 @@ static struct cl_page *cl_page_alloc(const struct lu_env *env, atomic_inc(&page->cp_ref); page->cp_obj = o; cl_object_get(o); - page->cp_obj_ref = lu_object_ref_add(&o->co_lu, "cl_page",page); + lu_object_ref_add_at(&o->co_lu, &page->cp_obj_ref, "cl_page", + page); page->cp_index = ind; cl_page_state_set_trust(page, CPS_CACHED); page->cp_type = type; diff --git a/drivers/staging/lustre/lustre/obdclass/lu_object.c b/drivers/staging/lustre/lustre/obdclass/lu_object.c index ce0444f6911c..896f24a8b3b6 100644 --- a/drivers/staging/lustre/lustre/obdclass/lu_object.c +++ b/drivers/staging/lustre/lustre/obdclass/lu_object.c @@ -1147,15 +1147,16 @@ EXPORT_SYMBOL(lu_device_fini); * Initialize object \a o that is part of compound object \a h and was created * by device \a d. */ -int lu_object_init(struct lu_object *o, - struct lu_object_header *h, struct lu_device *d) +int lu_object_init(struct lu_object *o, struct lu_object_header *h, + struct lu_device *d) { - memset(o, 0, sizeof *o); + memset(o, 0, sizeof(*o)); o->lo_header = h; - o->lo_dev = d; + o->lo_dev = d; lu_device_get(d); - o->lo_dev_ref = lu_ref_add(&d->ld_reference, "lu_object", o); + lu_ref_add_at(&d->ld_reference, &o->lo_dev_ref, "lu_object", o); INIT_LIST_HEAD(&o->lo_linkage); + return 0; } EXPORT_SYMBOL(lu_object_init); @@ -1170,8 +1171,8 @@ void lu_object_fini(struct lu_object *o) LASSERT(list_empty(&o->lo_linkage)); if (dev != NULL) { - lu_ref_del_at(&dev->ld_reference, - o->lo_dev_ref , "lu_object", o); + lu_ref_del_at(&dev->ld_reference, &o->lo_dev_ref, + "lu_object", o); lu_device_put(dev); o->lo_dev = NULL; } diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c index 0a0ec6f7d2dd..6b0a842dfca0 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cache.c +++ b/drivers/staging/lustre/lustre/osc/osc_cache.c @@ -2064,7 +2064,7 @@ static void osc_check_rpcs(const struct lu_env *env, struct client_obd *cli, while ((osc = osc_next_obj(cli)) != NULL) { struct cl_object *obj = osc2cl(osc); - struct lu_ref_link *link; + struct lu_ref_link link; OSC_IO_DEBUG(osc, "%lu in flight\n", rpcs_in_flight(cli)); @@ -2075,7 +2075,8 @@ static void osc_check_rpcs(const struct lu_env *env, struct client_obd *cli, cl_object_get(obj); client_obd_list_unlock(&cli->cl_loi_list_lock); - link = lu_object_ref_add(&obj->co_lu, "check", current); + lu_object_ref_add_at(&obj->co_lu, &link, "check", + current); /* attempt some read/write balancing by alternating between * reads and writes in an object. The makes_rpc checks here @@ -2116,7 +2117,8 @@ static void osc_check_rpcs(const struct lu_env *env, struct client_obd *cli, osc_object_unlock(osc); osc_list_maint(cli, osc); - lu_object_ref_del_at(&obj->co_lu, link, "check", current); + lu_object_ref_del_at(&obj->co_lu, &link, "check", + current); cl_object_put(env, obj); client_obd_list_lock(&cli->cl_loi_list_lock); From 543487c7a2670bb0d96c00673a44b74360e3b6c1 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Tue, 16 Jul 2013 10:22:12 -0400 Subject: [PATCH 0603/3400] nohz: Do not warn about unstable tsc unless user uses nohz_full If the user enables CONFIG_NO_HZ_FULL and runs the kernel on a machine with an unstable TSC, it will produce a WARN_ON dump as well as taint the kernel. This is a bit extreme for a kernel that just enables a feature but doesn't use it. The warning should only happen if the user tries to use the feature by either adding nohz_full to the kernel command line, or by enabling CONFIG_NO_HZ_FULL_ALL that makes nohz used on all CPUs at boot up. Note, this second feature should not (yet) be used by distros or anyone that doesn't care if NO_HZ is used or not. Signed-off-by: Steven Rostedt Cc: Paul E. McKenney Cc: Ingo Molnar Cc: Thomas Gleixner Cc: Peter Zijlstra Cc: Borislav Petkov Cc: Li Zhong Cc: Mike Galbraith Cc: Kevin Hilman Signed-off-by: Frederic Weisbecker --- kernel/time/tick-sched.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index e80183f4a6c4..1102534a1a57 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -182,7 +182,8 @@ static bool can_stop_full_tick(void) * Don't allow the user to think they can get * full NO_HZ with this machine. */ - WARN_ONCE(1, "NO_HZ FULL will not work with unstable sched clock"); + WARN_ONCE(have_nohz_full_mask, + "NO_HZ FULL will not work with unstable sched clock"); return false; } #endif From ca06416b2b4fa562cd3c3f9eb4198c3b2a983342 Mon Sep 17 00:00:00 2001 From: Li Zhong Date: Tue, 16 Jul 2013 12:18:47 +0800 Subject: [PATCH 0604/3400] nohz: fix compile warning in tick_nohz_init() cpu is not used after commit 5b8621a68fdcd2baf1d3b413726f913a5254d46a Signed-off-by: Li Zhong Cc: Steven Rostedt Cc: Paul E. McKenney Cc: Ingo Molnar Cc: Thomas Gleixner Cc: Peter Zijlstra Cc: Borislav Petkov Cc: Li Zhong Cc: Mike Galbraith Cc: Kevin Hilman Signed-off-by: Frederic Weisbecker --- kernel/time/tick-sched.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 1102534a1a57..9563c744dad2 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -344,8 +344,6 @@ static int tick_nohz_init_all(void) void __init tick_nohz_init(void) { - int cpu; - if (!have_nohz_full_mask) { if (tick_nohz_init_all() < 0) return; From 0dd6f4a414ef45a6b562566a31e1bb46fccdaf45 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 12:23:34 -0700 Subject: [PATCH 0605/3400] staging: comedi: mite.h: needs As reported by the kbuild test robot: Commit: 0bdab509bf9c6d838dc0a3b1d68bbf841fc20b5a staging: comedi: usee comedi_alloc_devpriv Removed the include of from many of the comedi drivers. Unfortunately, this header uses kfree() in an inline function. Instead of adding to each of the drivers that use this header, include slab.h here. Signed-off-by: H Hartley Sweeten Reported-by: kbuild test robot Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/mite.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/comedi/drivers/mite.h b/drivers/staging/comedi/drivers/mite.h index d4487e888e64..8423b8bf3384 100644 --- a/drivers/staging/comedi/drivers/mite.h +++ b/drivers/staging/comedi/drivers/mite.h @@ -21,6 +21,7 @@ #include #include +#include #include "../comedidev.h" /* #define DEBUG_MITE */ From 46fd3c61e21a2906b2444ee854bcfefda60bcc4c Mon Sep 17 00:00:00 2001 From: Liu Xuezhao Date: Thu, 25 Jul 2013 02:08:17 +0800 Subject: [PATCH 0606/3400] staging/lustre/obdclass: add obd_target.h Move some server-side data structures form obd.h to obd_target.h. To remove some code dependencies use HAVE_SERVER_SUPPORT to protect some llog/fsfilt_* functions. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-1330 Lustre-change: http://review.whamcloud.com/2678 Signed-off-by: Liu Xuezhao Signed-off-by: John L. Hammond Reviewed-by: Andreas Dilger Reviewed-by: Peng Tao Reviewed-by: Mike Pershin Signed-off-by: Peng Tao Signed-off-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../lustre/include/linux/lustre_fsfilt.h | 10 - .../lustre/lustre/include/lprocfs_status.h | 36 -- drivers/staging/lustre/lustre/include/obd.h | 140 +---- .../staging/lustre/lustre/lvfs/lvfs_linux.c | 1 - .../staging/lustre/lustre/obdclass/Makefile | 2 +- .../lustre/lustre/obdclass/lprocfs_jobstats.c | 560 ------------------ .../lustre/lustre/obdclass/obd_mount.c | 1 - 7 files changed, 3 insertions(+), 747 deletions(-) delete mode 100644 drivers/staging/lustre/lustre/obdclass/lprocfs_jobstats.c diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_fsfilt.h b/drivers/staging/lustre/lustre/include/linux/lustre_fsfilt.h index 6c7260957383..e637006203ab 100644 --- a/drivers/staging/lustre/lustre/include/linux/lustre_fsfilt.h +++ b/drivers/staging/lustre/lustre/include/linux/lustre_fsfilt.h @@ -145,16 +145,6 @@ static inline int fsfilt_commit(struct obd_device *obd, struct inode *inode, return rc; } -static inline int fsfilt_map_inode_pages(struct obd_device *obd, - struct inode *inode, - struct page **page, int pages, - unsigned long *blocks, - int create, struct mutex *mutex) -{ - return obd->obd_fsops->fs_map_inode_pages(inode, page, pages, blocks, - create, mutex); -} - static inline int fsfilt_read_record(struct obd_device *obd, struct file *file, void *buf, loff_t size, loff_t *offs) { diff --git a/drivers/staging/lustre/lustre/include/lprocfs_status.h b/drivers/staging/lustre/lustre/include/lprocfs_status.h index 7a0536436120..d7f1be96189b 100644 --- a/drivers/staging/lustre/lustre/include/lprocfs_status.h +++ b/drivers/staging/lustre/lustre/include/lprocfs_status.h @@ -370,18 +370,6 @@ static inline void s2dhms(struct dhms *ts, time_t secs) #define JOBSTATS_DISABLE "disable" #define JOBSTATS_PROCNAME_UID "procname_uid" -typedef void (*cntr_init_callback)(struct lprocfs_stats *stats); - -struct obd_job_stats { - cfs_hash_t *ojs_hash; - struct list_head ojs_list; - rwlock_t ojs_lock; /* protect the obj_list */ - cntr_init_callback ojs_cntr_init_fn; - int ojs_cntr_num; - int ojs_cleanup_interval; - time_t ojs_last_cleanup; -}; - #ifdef LPROCFS extern int lprocfs_stats_alloc_one(struct lprocfs_stats *stats, @@ -748,16 +736,6 @@ struct file_operations name##_fops = { \ .release = lprocfs_single_release, \ }; -/* lprocfs_jobstats.c */ -int lprocfs_job_stats_log(struct obd_device *obd, char *jobid, - int event, long amount); -void lprocfs_job_stats_fini(struct obd_device *obd); -int lprocfs_job_stats_init(struct obd_device *obd, int cntr_num, - cntr_init_callback fn); -int lprocfs_rd_job_interval(struct seq_file *m, void *data); -int lprocfs_wr_job_interval(struct file *file, const char *buffer, - unsigned long count, void *data); - /* lproc_ptlrpc.c */ struct ptlrpc_request; extern void target_print_req(void *seq_file, struct ptlrpc_request *req); @@ -1018,20 +996,6 @@ __u64 lprocfs_stats_collector(struct lprocfs_stats *stats, int idx, #define LPROC_SEQ_FOPS_RW_TYPE(name, type) #define LPROC_SEQ_FOPS_WR_ONLY(name, type) -/* lprocfs_jobstats.c */ -static inline -int lprocfs_job_stats_log(struct obd_device *obd, char *jobid, int event, - long amount) -{ return 0; } -static inline -void lprocfs_job_stats_fini(struct obd_device *obd) -{ return; } -static inline -int lprocfs_job_stats_init(struct obd_device *obd, int cntr_num, - cntr_init_callback fn) -{ return 0; } - - /* lproc_ptlrpc.c */ #define target_print_req NULL diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 797a6afbddaa..094eb96515dc 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -49,6 +49,8 @@ #define IOC_MDC_MAX_NR 50 #include +#include +#include #include #include #include @@ -56,9 +58,6 @@ #include #include -#include - - #define MAX_OBD_DEVICES 8192 struct osc_async_rc { @@ -254,30 +253,6 @@ struct brw_page { obd_flag flag; }; -/* Individual type definitions */ - -struct ost_server_data; - -struct osd_properties { - size_t osd_max_ea_size; -}; - -#define OBT_MAGIC 0xBDDECEAE -/* hold common fields for "target" device */ -struct obd_device_target { - __u32 obt_magic; - __u32 obt_instance; - struct super_block *obt_sb; - /** last_rcvd file */ - struct file *obt_rcvd_filp; - __u64 obt_mount_count; - struct rw_semaphore obt_rwsem; - struct vfsmount *obt_vfsmnt; - struct file *obt_health_check_filp; - struct osd_properties obt_osd_properties; - struct obd_job_stats obt_jobstats; -}; - /* llog contexts */ enum llog_ctxt_id { LLOG_CONFIG_ORIG_CTXT = 0, @@ -299,94 +274,6 @@ enum llog_ctxt_id { LLOG_MAX_CTXTS }; -#define FILTER_SUBDIR_COUNT 32 /* set to zero for no subdirs */ - -struct filter_subdirs { - struct dentry *dentry[FILTER_SUBDIR_COUNT]; -}; - - -struct filter_ext { - __u64 fe_start; - __u64 fe_end; -}; - -struct filter_obd { - /* NB this field MUST be first */ - struct obd_device_target fo_obt; - const char *fo_fstype; - - int fo_group_count; - struct dentry *fo_dentry_O; - struct dentry **fo_dentry_O_groups; - struct filter_subdirs *fo_dentry_O_sub; - struct mutex fo_init_lock; /* group initialization lock*/ - int fo_committed_group; - - spinlock_t fo_objidlock; /* protect fo_lastobjid */ - - unsigned long fo_destroys_in_progress; - struct mutex fo_create_locks[FILTER_SUBDIR_COUNT]; - - struct list_head fo_export_list; - int fo_subdir_count; - - obd_size fo_tot_dirty; /* protected by obd_osfs_lock */ - obd_size fo_tot_granted; /* all values in bytes */ - obd_size fo_tot_pending; - int fo_tot_granted_clients; - - obd_size fo_readcache_max_filesize; - spinlock_t fo_flags_lock; - unsigned int fo_read_cache:1, /**< enable read-only cache */ - fo_writethrough_cache:1,/**< read cache writes */ - fo_mds_ost_sync:1, /**< MDS-OST orphan recovery*/ - fo_raid_degraded:1;/**< RAID device degraded */ - - struct obd_import *fo_mdc_imp; - struct obd_uuid fo_mdc_uuid; - struct lustre_handle fo_mdc_conn; - struct file **fo_last_objid_files; - __u64 *fo_last_objids; /* last created objid for groups, - * protected by fo_objidlock */ - - struct mutex fo_alloc_lock; - - atomic_t fo_r_in_flight; - atomic_t fo_w_in_flight; - - /* - * per-filter pool of kiobuf's allocated by filter_common_setup() and - * torn down by filter_cleanup(). - * - * This pool contains kiobuf used by - * filter_{prep,commit}rw_{read,write}() and is shared by all OST - * threads. - * - * Locking: protected by internal lock of cfs_hash, pool can be - * found from this hash table by t_id of ptlrpc_thread. - */ - struct cfs_hash *fo_iobuf_hash; - - struct brw_stats fo_filter_stats; - - int fo_fmd_max_num; /* per exp filter_mod_data */ - int fo_fmd_max_age; /* jiffies to fmd expiry */ - unsigned long fo_syncjournal:1, /* sync journal on writes */ - fo_sync_lock_cancel:2;/* sync on lock cancel */ - - - /* sptlrpc stuff */ - rwlock_t fo_sptlrpc_lock; - struct sptlrpc_rule_set fo_sptlrpc_rset; - - /* capability related */ - unsigned int fo_fl_oss_capa; - struct list_head fo_capa_keys; - struct hlist_head *fo_capa_hash; - int fo_sec_level; -}; - struct timeout_item { enum timeout_event ti_event; cfs_time_t ti_timeout; @@ -552,25 +439,6 @@ struct obd_id_info { obd_id *data; }; -/* */ - -struct echo_obd { - struct obd_device_target eo_obt; - struct obdo eo_oa; - spinlock_t eo_lock; - __u64 eo_lastino; - struct lustre_handle eo_nl_lock; - atomic_t eo_prep; -}; - -struct ost_obd { - struct ptlrpc_service *ost_service; - struct ptlrpc_service *ost_create_service; - struct ptlrpc_service *ost_io_service; - struct ptlrpc_service *ost_seq_service; - struct mutex ost_health_mutex; -}; - struct echo_client_obd { struct obd_export *ec_exp; /* the local connection to osc/lov */ spinlock_t ec_lock; @@ -1052,12 +920,8 @@ struct obd_device { int obd_recovery_stage; union { - struct obd_device_target obt; - struct filter_obd filter; struct client_obd cli; - struct ost_obd ost; struct echo_client_obd echo_client; - struct echo_obd echo; struct lov_obd lov; struct lmv_obd lmv; } u; diff --git a/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c b/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c index 80b841a049cd..9d19d0a79be8 100644 --- a/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c +++ b/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c @@ -46,7 +46,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/staging/lustre/lustre/obdclass/Makefile b/drivers/staging/lustre/lustre/obdclass/Makefile index b80c13c6f5dd..8a0e08ced454 100644 --- a/drivers/staging/lustre/lustre/obdclass/Makefile +++ b/drivers/staging/lustre/lustre/obdclass/Makefile @@ -3,7 +3,7 @@ obj-$(CONFIG_LUSTRE_FS) += obdclass.o llog_test.o obdclass-y := linux/linux-module.o linux/linux-obdo.o linux/linux-sysctl.o \ llog.o llog_cat.o llog_obd.o llog_swab.o class_obd.o debug.o \ genops.o uuid.o llog_ioctl.o lprocfs_status.o \ - lprocfs_jobstats.o lustre_handles.o lustre_peer.o llog_osd.o \ + lustre_handles.o lustre_peer.o llog_osd.o \ local_storage.o statfs_pack.o obdo.o obd_config.o obd_mount.o\ mea.o lu_object.o dt_object.o capa.o cl_object.o \ cl_page.o cl_lock.o cl_io.o lu_ref.o acl.o idmap.o \ diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_jobstats.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_jobstats.c deleted file mode 100644 index 7f6072c4b7f8..000000000000 --- a/drivers/staging/lustre/lustre/obdclass/lprocfs_jobstats.c +++ /dev/null @@ -1,560 +0,0 @@ -/* GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * 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 version 2 for more details (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf - * - * GPL HEADER END - */ -/* - * Copyright (c) 2011, 2012, Intel Corporation. - * Use is subject to license terms. - * - * Author: Niu Yawei - */ -/* - * lustre/obdclass/lprocfs_jobstats.c - */ - -#ifndef EXPORT_SYMTAB -# define EXPORT_SYMTAB -#endif -#define DEBUG_SUBSYSTEM S_CLASS - - -#include -#include -#include - -#if defined(LPROCFS) - -/* - * JobID formats & JobID environment variable names for supported - * job schedulers: - * - * SLURM: - * JobID format: 32 bit integer. - * JobID env var: SLURM_JOB_ID. - * SGE: - * JobID format: Decimal integer range to 99999. - * JobID env var: JOB_ID. - * LSF: - * JobID format: 6 digit integer by default (up to 999999), can be - * increased to 10 digit (up to 2147483646). - * JobID env var: LSB_JOBID. - * Loadleveler: - * JobID format: String of machine_name.cluster_id.process_id, for - * example: fr2n02.32.0 - * JobID env var: LOADL_STEP_ID. - * PBS: - * JobID format: String of sequence_number[.server_name][@server]. - * JobID env var: PBS_JOBID. - * Maui/MOAB: - * JobID format: Same as PBS. - * JobID env var: Same as PBS. - */ - -struct job_stat { - struct hlist_node js_hash; - struct list_head js_list; - atomic_t js_refcount; - char js_jobid[JOBSTATS_JOBID_SIZE]; - time_t js_timestamp; /* seconds */ - struct lprocfs_stats *js_stats; - struct obd_job_stats *js_jobstats; -}; - -static unsigned job_stat_hash(cfs_hash_t *hs, const void *key, unsigned mask) -{ - return cfs_hash_djb2_hash(key, strlen(key), mask); -} - -static void *job_stat_key(struct hlist_node *hnode) -{ - struct job_stat *job; - job = hlist_entry(hnode, struct job_stat, js_hash); - return job->js_jobid; -} - -static int job_stat_keycmp(const void *key, struct hlist_node *hnode) -{ - struct job_stat *job; - job = hlist_entry(hnode, struct job_stat, js_hash); - return (strlen(job->js_jobid) == strlen(key)) && - !strncmp(job->js_jobid, key, strlen(key)); -} - -static void *job_stat_object(struct hlist_node *hnode) -{ - return hlist_entry(hnode, struct job_stat, js_hash); -} - -static void job_stat_get(cfs_hash_t *hs, struct hlist_node *hnode) -{ - struct job_stat *job; - job = hlist_entry(hnode, struct job_stat, js_hash); - atomic_inc(&job->js_refcount); -} - -static void job_free(struct job_stat *job) -{ - LASSERT(atomic_read(&job->js_refcount) == 0); - LASSERT(job->js_jobstats); - - write_lock(&job->js_jobstats->ojs_lock); - list_del_init(&job->js_list); - write_unlock(&job->js_jobstats->ojs_lock); - - lprocfs_free_stats(&job->js_stats); - OBD_FREE_PTR(job); -} - -static void job_putref(struct job_stat *job) -{ - LASSERT(atomic_read(&job->js_refcount) > 0); - if (atomic_dec_and_test(&job->js_refcount)) - job_free(job); -} - -static void job_stat_put_locked(cfs_hash_t *hs, struct hlist_node *hnode) -{ - struct job_stat *job; - job = hlist_entry(hnode, struct job_stat, js_hash); - job_putref(job); -} - -static void job_stat_exit(cfs_hash_t *hs, struct hlist_node *hnode) -{ - CERROR("Should not have any items!"); -} - -static cfs_hash_ops_t job_stats_hash_ops = { - .hs_hash = job_stat_hash, - .hs_key = job_stat_key, - .hs_keycmp = job_stat_keycmp, - .hs_object = job_stat_object, - .hs_get = job_stat_get, - .hs_put_locked = job_stat_put_locked, - .hs_exit = job_stat_exit, -}; - -static int job_iter_callback(cfs_hash_t *hs, cfs_hash_bd_t *bd, - struct hlist_node *hnode, void *data) -{ - time_t oldest = *((time_t *)data); - struct job_stat *job; - - job = hlist_entry(hnode, struct job_stat, js_hash); - if (!oldest || job->js_timestamp < oldest) - cfs_hash_bd_del_locked(hs, bd, hnode); - - return 0; -} - -static void lprocfs_job_cleanup(struct obd_job_stats *stats, bool force) -{ - time_t oldest, now; - - if (stats->ojs_cleanup_interval == 0) - return; - - now = cfs_time_current_sec(); - if (!force && now < stats->ojs_last_cleanup + - stats->ojs_cleanup_interval) - return; - - oldest = now - stats->ojs_cleanup_interval; - cfs_hash_for_each_safe(stats->ojs_hash, job_iter_callback, - &oldest); - stats->ojs_last_cleanup = cfs_time_current_sec(); -} - -static struct job_stat *job_alloc(char *jobid, struct obd_job_stats *jobs) -{ - struct job_stat *job; - - LASSERT(jobs->ojs_cntr_num && jobs->ojs_cntr_init_fn); - - OBD_ALLOC_PTR(job); - if (job == NULL) - return NULL; - - job->js_stats = lprocfs_alloc_stats(jobs->ojs_cntr_num, 0); - if (job->js_stats == NULL) { - OBD_FREE_PTR(job); - return NULL; - } - - jobs->ojs_cntr_init_fn(job->js_stats); - - memcpy(job->js_jobid, jobid, JOBSTATS_JOBID_SIZE); - job->js_timestamp = cfs_time_current_sec(); - job->js_jobstats = jobs; - INIT_HLIST_NODE(&job->js_hash); - INIT_LIST_HEAD(&job->js_list); - atomic_set(&job->js_refcount, 1); - - return job; -} - -int lprocfs_job_stats_log(struct obd_device *obd, char *jobid, - int event, long amount) -{ - struct obd_job_stats *stats = &obd->u.obt.obt_jobstats; - struct job_stat *job, *job2; - ENTRY; - - LASSERT(stats && stats->ojs_hash); - - lprocfs_job_cleanup(stats, false); - - if (!jobid || !strlen(jobid)) - RETURN(-EINVAL); - - if (strlen(jobid) >= JOBSTATS_JOBID_SIZE) { - CERROR("Invalid jobid size (%lu), expect(%d)\n", - (unsigned long)strlen(jobid) + 1, JOBSTATS_JOBID_SIZE); - RETURN(-EINVAL); - } - - job = cfs_hash_lookup(stats->ojs_hash, jobid); - if (job) - goto found; - - job = job_alloc(jobid, stats); - if (job == NULL) - RETURN(-ENOMEM); - - job2 = cfs_hash_findadd_unique(stats->ojs_hash, job->js_jobid, - &job->js_hash); - if (job2 != job) { - job_putref(job); - job = job2; - /* We cannot LASSERT(!list_empty(&job->js_list)) here, - * since we just lost the race for inserting "job" into the - * ojs_list, and some other thread is doing it _right_now_. - * Instead, be content the other thread is doing this, since - * "job2" was initialized in job_alloc() already. LU-2163 */ - } else { - LASSERT(list_empty(&job->js_list)); - write_lock(&stats->ojs_lock); - list_add_tail(&job->js_list, &stats->ojs_list); - write_unlock(&stats->ojs_lock); - } - -found: - LASSERT(stats == job->js_jobstats); - LASSERT(stats->ojs_cntr_num > event); - job->js_timestamp = cfs_time_current_sec(); - lprocfs_counter_add(job->js_stats, event, amount); - - job_putref(job); - RETURN(0); -} -EXPORT_SYMBOL(lprocfs_job_stats_log); - -void lprocfs_job_stats_fini(struct obd_device *obd) -{ - struct obd_job_stats *stats = &obd->u.obt.obt_jobstats; - time_t oldest = 0; - - if (stats->ojs_hash == NULL) - return; - cfs_hash_for_each_safe(stats->ojs_hash, job_iter_callback, &oldest); - cfs_hash_putref(stats->ojs_hash); - stats->ojs_hash = NULL; - LASSERT(list_empty(&stats->ojs_list)); -} -EXPORT_SYMBOL(lprocfs_job_stats_fini); - -static void *lprocfs_jobstats_seq_start(struct seq_file *p, loff_t *pos) -{ - struct obd_job_stats *stats = p->private; - loff_t off = *pos; - struct job_stat *job; - - read_lock(&stats->ojs_lock); - if (off == 0) - return SEQ_START_TOKEN; - off--; - list_for_each_entry(job, &stats->ojs_list, js_list) { - if (!off--) - return job; - } - return NULL; -} - -static void lprocfs_jobstats_seq_stop(struct seq_file *p, void *v) -{ - struct obd_job_stats *stats = p->private; - - read_unlock(&stats->ojs_lock); -} - -static void *lprocfs_jobstats_seq_next(struct seq_file *p, void *v, loff_t *pos) -{ - struct obd_job_stats *stats = p->private; - struct job_stat *job; - struct list_head *next; - - ++*pos; - if (v == SEQ_START_TOKEN) { - next = stats->ojs_list.next; - } else { - job = (struct job_stat *)v; - next = job->js_list.next; - } - - return next == &stats->ojs_list ? NULL : - list_entry(next, struct job_stat, js_list); -} - -/* - * Example of output on MDT: - * - * job_stats: - * - job_id: test_id.222.25844 - * snapshot_time: 1322494486 - * open: { samples: 3, unit: reqs } - * close: { samples: 3, unit: reqs } - * mknod: { samples: 0, unit: reqs } - * link: { samples: 0, unit: reqs } - * unlink: { samples: 0, unit: reqs } - * mkdir: { samples: 0, unit: reqs } - * rmdir: { samples: 0, unit: reqs } - * rename: { samples: 1, unit: reqs } - * getattr: { samples: 7, unit: reqs } - * setattr: { samples: 0, unit: reqs } - * getxattr: { samples: 0, unit: reqs } - * setxattr: { samples: 0, unit: reqs } - * statfs: { samples: 0, unit: reqs } - * sync: { samples: 0, unit: reqs } - * - * Example of output on OST: - * - * job_stats: - * - job_id 4854 - * snapshot_time: 1322494602 - * read: { samples: 0, unit: bytes, min: 0, max: 0, sum: 0 } - * write: { samples: 1, unit: bytes, min: 10, max: 10, sum: 10 } - * setattr: { samples: 0, unit: reqs } - * punch: { samples: 0, unit: reqs } - * sync: { samples: 0, unit: reqs } - */ - -static const char spaces[] = " "; - -static int inline width(const char *str, int len) -{ - return len - min((int)strlen(str), 15); -} - -static int lprocfs_jobstats_seq_show(struct seq_file *p, void *v) -{ - struct job_stat *job = v; - struct lprocfs_stats *s; - struct lprocfs_counter ret; - struct lprocfs_counter_header *cntr_header; - int i; - - if (v == SEQ_START_TOKEN) { - seq_printf(p, "job_stats:\n"); - return 0; - } - - seq_printf(p, "- %-16s %s\n", "job_id:", job->js_jobid); - seq_printf(p, " %-16s %ld\n", "snapshot_time:", job->js_timestamp); - - s = job->js_stats; - for (i = 0; i < s->ls_num; i++) { - cntr_header = &s->ls_cnt_header[i]; - lprocfs_stats_collect(s, i, &ret); - - seq_printf(p, " %s:%.*s { samples: %11"LPF64"u", - cntr_header->lc_name, - width(cntr_header->lc_name, 15), spaces, - ret.lc_count); - if (cntr_header->lc_units[0] != '\0') - seq_printf(p, ", unit: %5s", cntr_header->lc_units); - - if (cntr_header->lc_config & LPROCFS_CNTR_AVGMINMAX) { - seq_printf(p, ", min:%8"LPF64"u, max:%8"LPF64"u," - " sum:%16"LPF64"u", - ret.lc_count ? ret.lc_min : 0, - ret.lc_count ? ret.lc_max : 0, - ret.lc_count ? ret.lc_sum : 0); - } - if (cntr_header->lc_config & LPROCFS_CNTR_STDDEV) { - seq_printf(p, ", sumsq: %18"LPF64"u", - ret.lc_count ? ret.lc_sumsquare : 0); - } - - seq_printf(p, " }\n"); - - } - return 0; -} - -struct seq_operations lprocfs_jobstats_seq_sops = { - start: lprocfs_jobstats_seq_start, - stop: lprocfs_jobstats_seq_stop, - next: lprocfs_jobstats_seq_next, - show: lprocfs_jobstats_seq_show, -}; - -static int lprocfs_jobstats_seq_open(struct inode *inode, struct file *file) -{ - struct seq_file *seq; - int rc; - - rc = seq_open(file, &lprocfs_jobstats_seq_sops); - if (rc) - return rc; - seq = file->private_data; - seq->private = PDE_DATA(inode); - return 0; -} - -static ssize_t lprocfs_jobstats_seq_write(struct file *file, const char *buf, - size_t len, loff_t *off) -{ - struct seq_file *seq = file->private_data; - struct obd_job_stats *stats = seq->private; - char jobid[JOBSTATS_JOBID_SIZE]; - int all = 0; - struct job_stat *job; - - if (!memcmp(buf, "clear", strlen("clear"))) { - all = 1; - } else if (len < JOBSTATS_JOBID_SIZE) { - memset(jobid, 0, JOBSTATS_JOBID_SIZE); - /* Trim '\n' if any */ - if (buf[len - 1] == '\n') - memcpy(jobid, buf, len - 1); - else - memcpy(jobid, buf, len); - } else { - return -EINVAL; - } - - LASSERT(stats->ojs_hash); - if (all) { - time_t oldest = 0; - cfs_hash_for_each_safe(stats->ojs_hash, job_iter_callback, - &oldest); - return len; - } - - if (!strlen(jobid)) - return -EINVAL; - - job = cfs_hash_lookup(stats->ojs_hash, jobid); - if (!job) - return -EINVAL; - - cfs_hash_del_key(stats->ojs_hash, jobid); - - job_putref(job); - return len; -} - -struct file_operations lprocfs_jobstats_seq_fops = { - .owner = THIS_MODULE, - .open = lprocfs_jobstats_seq_open, - .read = seq_read, - .write = lprocfs_jobstats_seq_write, - .llseek = seq_lseek, - .release = lprocfs_seq_release, -}; - -int lprocfs_job_stats_init(struct obd_device *obd, int cntr_num, - cntr_init_callback init_fn) -{ - struct proc_dir_entry *entry; - struct obd_job_stats *stats; - ENTRY; - - LASSERT(obd->obd_proc_entry != NULL); - LASSERT(obd->obd_type->typ_name); - - if (strcmp(obd->obd_type->typ_name, LUSTRE_MDT_NAME) && - strcmp(obd->obd_type->typ_name, LUSTRE_OST_NAME)) { - CERROR("Invalid obd device type.\n"); - RETURN(-EINVAL); - } - stats = &obd->u.obt.obt_jobstats; - - LASSERT(stats->ojs_hash == NULL); - stats->ojs_hash = cfs_hash_create("JOB_STATS", - HASH_JOB_STATS_CUR_BITS, - HASH_JOB_STATS_MAX_BITS, - HASH_JOB_STATS_BKT_BITS, 0, - CFS_HASH_MIN_THETA, - CFS_HASH_MAX_THETA, - &job_stats_hash_ops, - CFS_HASH_DEFAULT); - if (stats->ojs_hash == NULL) - RETURN(-ENOMEM); - - INIT_LIST_HEAD(&stats->ojs_list); - rwlock_init(&stats->ojs_lock); - stats->ojs_cntr_num = cntr_num; - stats->ojs_cntr_init_fn = init_fn; - stats->ojs_cleanup_interval = 600; /* 10 mins by default */ - stats->ojs_last_cleanup = cfs_time_current_sec(); - - entry = proc_create_data("job_stats", 0644, obd->obd_proc_entry, - &lprocfs_jobstats_seq_fops, stats); - if (entry) - RETURN(0); - else - RETURN(-ENOMEM); -} -EXPORT_SYMBOL(lprocfs_job_stats_init); - -int lprocfs_rd_job_interval(struct seq_file *m, void *data) -{ - struct obd_device *obd = (struct obd_device *)data; - struct obd_job_stats *stats; - - LASSERT(obd != NULL); - stats = &obd->u.obt.obt_jobstats; - return seq_printf(m, "%d\n", stats->ojs_cleanup_interval); -} -EXPORT_SYMBOL(lprocfs_rd_job_interval); - -int lprocfs_wr_job_interval(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - struct obd_device *obd = (struct obd_device *)data; - struct obd_job_stats *stats; - int val, rc; - - LASSERT(obd != NULL); - stats = &obd->u.obt.obt_jobstats; - - rc = lprocfs_write_helper(buffer, count, &val); - if (rc) - return rc; - - stats->ojs_cleanup_interval = val; - lprocfs_job_cleanup(stats, true); - - return count; - -} -EXPORT_SYMBOL(lprocfs_wr_job_interval); - -#endif /* LPROCFS*/ diff --git a/drivers/staging/lustre/lustre/obdclass/obd_mount.c b/drivers/staging/lustre/lustre/obdclass/obd_mount.c index 28d174ab750d..533a49395f32 100644 --- a/drivers/staging/lustre/lustre/obdclass/obd_mount.c +++ b/drivers/staging/lustre/lustre/obdclass/obd_mount.c @@ -47,7 +47,6 @@ #include #include -#include #include #include #include From 17dc1597c5051757b58c5397f5162a21a746ecb7 Mon Sep 17 00:00:00 2001 From: Peng Tao Date: Thu, 25 Jul 2013 02:08:18 +0800 Subject: [PATCH 0607/3400] staging/lustre: fix build on non-x86 On non-x86 we will build with Lustre's errno translate code but it has a few issues. Cc: Andreas Dilger Signed-off-by: Peng Tao Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ptlrpc/Makefile | 2 +- drivers/staging/lustre/lustre/ptlrpc/errno.c | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/staging/lustre/lustre/ptlrpc/Makefile b/drivers/staging/lustre/lustre/ptlrpc/Makefile index a379558bc687..6d78b80487f2 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/Makefile +++ b/drivers/staging/lustre/lustre/ptlrpc/Makefile @@ -16,7 +16,7 @@ ptlrpc_objs += sec.o sec_bulk.o sec_gc.o sec_config.o sec_lproc.o ptlrpc_objs += sec_null.o sec_plain.o nrs.o nrs_fifo.o ptlrpc-y := $(ldlm_objs) $(ptlrpc_objs) -ptlrpc-$(CONFIG_LUSTRE_TRANSLATE_ERRNOS) += errno.c +ptlrpc-$(CONFIG_LUSTRE_TRANSLATE_ERRNOS) += errno.o obj-$(CONFIG_PTLRPC_GSS) += gss/ diff --git a/drivers/staging/lustre/lustre/ptlrpc/errno.c b/drivers/staging/lustre/lustre/ptlrpc/errno.c index 46e259e4098b..1c1006333960 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/errno.c +++ b/drivers/staging/lustre/lustre/ptlrpc/errno.c @@ -25,7 +25,7 @@ * Copyright (c) 2013, Intel Corporation. */ -#include +#include #include /* @@ -184,7 +184,6 @@ static int lustre_errno_hton_mapping[] = { [EBADTYPE] = LUSTRE_EBADTYPE, [EJUKEBOX] = LUSTRE_EJUKEBOX, [EIOCBQUEUED] = LUSTRE_EIOCBQUEUED, - [EIOCBRETRY] = LUSTRE_EIOCBRETRY }; static int lustre_errno_ntoh_mapping[] = { @@ -331,7 +330,6 @@ static int lustre_errno_ntoh_mapping[] = { [LUSTRE_EBADTYPE] = EBADTYPE, [LUSTRE_EJUKEBOX] = EJUKEBOX, [LUSTRE_EIOCBQUEUED] = EIOCBQUEUED, - [LUSTRE_EIOCBRETRY] = EIOCBRETRY }; unsigned int lustre_errno_hton(unsigned int h) From 61e121047645122c47714fcda684d0ee67f444af Mon Sep 17 00:00:00 2001 From: Won Kang Date: Thu, 25 Jul 2013 03:36:17 +0900 Subject: [PATCH 0608/3400] staging: gdm7240: adding LTE USB driver GCT Semiconductor GDM7240 is 4G LTE chip. This driver supports GCT reference platform as a USB device. Signed-off-by: Won Kang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/Kconfig | 2 + drivers/staging/Makefile | 1 + drivers/staging/gdm724x/Kconfig | 15 + drivers/staging/gdm724x/Makefile | 7 + drivers/staging/gdm724x/TODO | 15 + drivers/staging/gdm724x/gdm_endian.c | 67 ++ drivers/staging/gdm724x/gdm_endian.h | 49 ++ drivers/staging/gdm724x/gdm_lte.c | 920 ++++++++++++++++++++++ drivers/staging/gdm724x/gdm_lte.h | 80 ++ drivers/staging/gdm724x/gdm_mux.c | 700 +++++++++++++++++ drivers/staging/gdm724x/gdm_mux.h | 85 +++ drivers/staging/gdm724x/gdm_tty.c | 367 +++++++++ drivers/staging/gdm724x/gdm_tty.h | 59 ++ drivers/staging/gdm724x/gdm_usb.c | 1047 ++++++++++++++++++++++++++ drivers/staging/gdm724x/gdm_usb.h | 110 +++ drivers/staging/gdm724x/hci.h | 55 ++ drivers/staging/gdm724x/hci_packet.h | 93 +++ drivers/staging/gdm724x/lte_ioctl.h | 58 ++ drivers/staging/gdm724x/netlink_k.c | 161 ++++ drivers/staging/gdm724x/netlink_k.h | 25 + 20 files changed, 3916 insertions(+) create mode 100644 drivers/staging/gdm724x/Kconfig create mode 100644 drivers/staging/gdm724x/Makefile create mode 100644 drivers/staging/gdm724x/TODO create mode 100644 drivers/staging/gdm724x/gdm_endian.c create mode 100644 drivers/staging/gdm724x/gdm_endian.h create mode 100644 drivers/staging/gdm724x/gdm_lte.c create mode 100644 drivers/staging/gdm724x/gdm_lte.h create mode 100644 drivers/staging/gdm724x/gdm_mux.c create mode 100644 drivers/staging/gdm724x/gdm_mux.h create mode 100644 drivers/staging/gdm724x/gdm_tty.c create mode 100644 drivers/staging/gdm724x/gdm_tty.h create mode 100644 drivers/staging/gdm724x/gdm_usb.c create mode 100644 drivers/staging/gdm724x/gdm_usb.h create mode 100644 drivers/staging/gdm724x/hci.h create mode 100644 drivers/staging/gdm724x/hci_packet.h create mode 100644 drivers/staging/gdm724x/lte_ioctl.h create mode 100644 drivers/staging/gdm724x/netlink_k.c create mode 100644 drivers/staging/gdm724x/netlink_k.h diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 57d8b3444600..d55bc344c5ea 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -118,6 +118,8 @@ source "drivers/staging/ozwpan/Kconfig" source "drivers/staging/gdm72xx/Kconfig" +source "drivers/staging/gdm724x/Kconfig" + source "drivers/staging/silicom/Kconfig" source "drivers/staging/ced1401/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 429321f15105..c23cf3b60c34 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -52,6 +52,7 @@ obj-$(CONFIG_MFD_NVEC) += nvec/ obj-$(CONFIG_ANDROID) += android/ obj-$(CONFIG_USB_WPAN_HCD) += ozwpan/ obj-$(CONFIG_WIMAX_GDM72XX) += gdm72xx/ +obj-$(CONFIG_LTE_GDM724X) += gdm724x/ obj-$(CONFIG_NET_VENDOR_SILICOM) += silicom/ obj-$(CONFIG_CED1401) += ced1401/ obj-$(CONFIG_DRM_IMX) += imx-drm/ diff --git a/drivers/staging/gdm724x/Kconfig b/drivers/staging/gdm724x/Kconfig new file mode 100644 index 000000000000..10f7be10305d --- /dev/null +++ b/drivers/staging/gdm724x/Kconfig @@ -0,0 +1,15 @@ +# +# GCT GDM724x LTE driver configuration +# + +config LTE_GDM724X + tristate "GCT GDM724x LTE support" + depends on NET && USB + help + This driver supports GCT GDM724x LTE chip based USB modem devices. + It exposes 4 network devices to be used per PDN and 2 tty devices to be + used for AT commands and DM monitoring applications. + The modules will be called gdmulte.ko and gdmtty.ko + + GCT-ATCx can be used for AT Commands + GCT-DMx can be used for LTE protocol monitoring diff --git a/drivers/staging/gdm724x/Makefile b/drivers/staging/gdm724x/Makefile new file mode 100644 index 000000000000..ba7f11a6a097 --- /dev/null +++ b/drivers/staging/gdm724x/Makefile @@ -0,0 +1,7 @@ +obj-$(CONFIG_LTE_GDM724X) := gdmulte.o +gdmulte-y += gdm_lte.o netlink_k.o +gdmulte-y += gdm_usb.o gdm_endian.o + +obj-$(CONFIG_LTE_GDM724X) += gdmtty.o +gdmtty-y := gdm_tty.o gdm_mux.o + diff --git a/drivers/staging/gdm724x/TODO b/drivers/staging/gdm724x/TODO new file mode 100644 index 000000000000..cd89214aa265 --- /dev/null +++ b/drivers/staging/gdm724x/TODO @@ -0,0 +1,15 @@ +TODO: +- Clean up coding style to meet kernel standard. (80 line limit, netdev_err) +- Remove test for host endian +- Remove confusing macros (endian, hci_send, sdu_send, rcv_with_cb) +- Fixes for every instances of function returning -1 +- Check for skb->len in gdm_lte_emulate_arp() +- Use ALIGN() macro for dummy_cnt in up_to_host() +- Error handling in init_usb() +- Explain reason for multiples of 512 bytes in alloc_tx_struct() +- Review use of atomic allocation for tx structs +- No error checking for alloc_tx_struct in do_tx() + +Patches to: + Jonathan Kim + Dean ahn diff --git a/drivers/staging/gdm724x/gdm_endian.c b/drivers/staging/gdm724x/gdm_endian.c new file mode 100644 index 000000000000..02934093ce7f --- /dev/null +++ b/drivers/staging/gdm724x/gdm_endian.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +#include +#include "gdm_endian.h" + +void set_endian(struct gdm_endian *ed, u8 dev_endian) +{ + u8 a[2] = {0x12, 0x34}; + u8 b[2] = {0, }; + u16 c = 0x1234; + + if (dev_endian == ENDIANNESS_BIG) + ed->dev_ed = ENDIANNESS_BIG; + else + ed->dev_ed = ENDIANNESS_LITTLE; + + memcpy(b, &c, 2); + + if (a[0] != b[0]) + ed->host_ed = ENDIANNESS_LITTLE; + else + ed->host_ed = ENDIANNESS_BIG; + +} + +u16 gdm_cpu_to_dev16(struct gdm_endian *ed, u16 x) +{ + if (ed->dev_ed == ed->host_ed) + return x; + + return Endian16_Swap(x); +} + +u16 gdm_dev16_to_cpu(struct gdm_endian *ed, u16 x) +{ + if (ed->dev_ed == ed->host_ed) + return x; + + return Endian16_Swap(x); +} + +u32 gdm_cpu_to_dev32(struct gdm_endian *ed, u32 x) +{ + if (ed->dev_ed == ed->host_ed) + return x; + + return Endian32_Swap(x); +} + +u32 gdm_dev32_to_cpu(struct gdm_endian *ed, u32 x) +{ + if (ed->dev_ed == ed->host_ed) + return x; + + return Endian32_Swap(x); +} diff --git a/drivers/staging/gdm724x/gdm_endian.h b/drivers/staging/gdm724x/gdm_endian.h new file mode 100644 index 000000000000..775794db6ab6 --- /dev/null +++ b/drivers/staging/gdm724x/gdm_endian.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +#ifndef __GDM_ENDIAN_H__ +#define __GDM_ENDIAN_H__ + +#include + +#define Endian16_Swap(value) \ + ((((u16)((value) & 0x00FF)) << 8) | \ + (((u16)((value) & 0xFF00)) >> 8)) + +#define Endian32_Swap(value) \ + ((((u32)((value) & 0x000000FF)) << 24) | \ + (((u32)((value) & 0x0000FF00)) << 8) | \ + (((u32)((value) & 0x00FF0000)) >> 8) | \ + (((u32)((value) & 0xFF000000)) >> 24)) + +enum { + ENDIANNESS_MIN = 0, + ENDIANNESS_UNKNOWN, + ENDIANNESS_LITTLE, + ENDIANNESS_BIG, + ENDIANNESS_MIDDLE, + ENDIANNESS_MAX +}; + +struct gdm_endian { + u8 dev_ed; + u8 host_ed; +}; + +void set_endian(struct gdm_endian *ed, u8 dev_endian); +u16 gdm_cpu_to_dev16(struct gdm_endian *ed, u16 x); +u16 gdm_dev16_to_cpu(struct gdm_endian *ed, u16 x); +u32 gdm_cpu_to_dev32(struct gdm_endian *ed, u32 x); +u32 gdm_dev32_to_cpu(struct gdm_endian *ed, u32 x); + +#endif /*__GDM_ENDIAN_H__*/ diff --git a/drivers/staging/gdm724x/gdm_lte.c b/drivers/staging/gdm724x/gdm_lte.c new file mode 100644 index 000000000000..357474acb371 --- /dev/null +++ b/drivers/staging/gdm724x/gdm_lte.c @@ -0,0 +1,920 @@ +/* + * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gdm_lte.h" +#include "netlink_k.h" +#include "hci.h" +#include "hci_packet.h" +#include "gdm_endian.h" +#include "lte_ioctl.h" + +/* + * Netlink protocol number + */ +#define NETLINK_LTE 30 + +/* + * Default MTU Size + */ +#define DEFAULT_MTU_SIZE 1500 + +#define gdm_dev_endian(n) (\ + n->phy_dev->get_endian(n->phy_dev->priv_dev)) + +#define gdm_lte_hci_send(n, d, l) (\ + n->phy_dev->send_hci_func(n->phy_dev->priv_dev, d, l, NULL, NULL)) + +#define gdm_lte_sdu_send(n, d, l, c, b, i, t) (\ + n->phy_dev->send_sdu_func(n->phy_dev->priv_dev, d, l, n->pdn_table.dft_eps_id, 0, c, b, i, t)) + +#define gdm_lte_rcv_with_cb(n, c, b, e) (\ + n->rcv_func(n->priv_dev, c, b, e)) + +#define IP_VERSION_4 4 +#define IP_VERSION_6 6 + +static struct { + int ref_cnt; + struct sock *sock; +} lte_event; + +static struct device_type wwan_type = { + .name = "wwan", +}; + +static int gdm_lte_open(struct net_device *dev) +{ + netif_start_queue(dev); + return 0; +} + +static int gdm_lte_close(struct net_device *dev) +{ + netif_stop_queue(dev); + return 0; +} + +static int gdm_lte_set_config(struct net_device *dev, struct ifmap *map) +{ + if (dev->flags & IFF_UP) + return -EBUSY; + return 0; +} + +static void tx_complete(void *arg) +{ + struct nic *nic = arg; + + if (netif_queue_stopped(nic->netdev)) + netif_wake_queue(nic->netdev); +} + +static int gdm_lte_rx(struct sk_buff *skb, struct nic *nic, int nic_type) +{ + int ret; + + ret = netif_rx_ni(skb); + if (ret == NET_RX_DROP) { + printk(KERN_ERR "glte: rx - dropped\n"); + nic->stats.rx_dropped++; + } else { + nic->stats.rx_packets++; + nic->stats.rx_bytes += skb->len + ETH_HLEN; + } + + return 0; +} + +int gdm_lte_emulate_arp(struct sk_buff *skb_in, u32 nic_type) +{ + struct nic *nic = netdev_priv(skb_in->dev); + struct sk_buff *skb_out; + struct ethhdr eth; + struct vlan_ethhdr vlan_eth; + struct arphdr *arp_in; + struct arphdr *arp_out; + struct arpdata { + u8 ar_sha[ETH_ALEN]; + u8 ar_sip[4]; + u8 ar_tha[ETH_ALEN]; + u8 ar_tip[4]; + }; + struct arpdata *arp_data_in; + struct arpdata *arp_data_out; + u8 arp_temp[60]; + void *mac_header_data; + u32 mac_header_len; + + /* Format the mac header so that it can be put to skb */ + if (ntohs(((struct ethhdr *)skb_in->data)->h_proto) == ETH_P_8021Q) { + memcpy(&vlan_eth, skb_in->data, sizeof(struct vlan_ethhdr)); + mac_header_data = &vlan_eth; + mac_header_len = VLAN_ETH_HLEN; + } else { + memcpy(ð, skb_in->data, sizeof(struct ethhdr)); + mac_header_data = ð + mac_header_len = ETH_HLEN; + } + + /* Get the pointer of the original request */ + arp_in = (struct arphdr *)(skb_in->data + mac_header_len); + arp_data_in = (struct arpdata *)(skb_in->data + mac_header_len + sizeof(struct arphdr)); + + /* Get the pointer of the outgoing response */ + arp_out = (struct arphdr *)arp_temp; + arp_data_out = (struct arpdata *)(arp_temp + sizeof(struct arphdr)); + + /* Copy the arp header */ + memcpy(arp_out, arp_in, sizeof(struct arphdr)); + arp_out->ar_op = htons(ARPOP_REPLY); + + /* Copy the arp payload: based on 2 bytes of mac and fill the IP */ + arp_data_out->ar_sha[0] = arp_data_in->ar_sha[0]; + arp_data_out->ar_sha[1] = arp_data_in->ar_sha[1]; + memcpy(&arp_data_out->ar_sha[2], &arp_data_in->ar_tip[0], 4); + memcpy(&arp_data_out->ar_sip[0], &arp_data_in->ar_tip[0], 4); + memcpy(&arp_data_out->ar_tha[0], &arp_data_in->ar_sha[0], 6); + memcpy(&arp_data_out->ar_tip[0], &arp_data_in->ar_sip[0], 4); + + /* Fill the destination mac with source mac of the received packet */ + memcpy(mac_header_data, mac_header_data + ETH_ALEN, ETH_ALEN); + /* Fill the source mac with nic's source mac */ + memcpy(mac_header_data + ETH_ALEN, nic->src_mac_addr, ETH_ALEN); + + /* Alloc skb and reserve align */ + skb_out = dev_alloc_skb(skb_in->len); + if (!skb_out) + return -ENOMEM; + skb_reserve(skb_out, NET_IP_ALIGN); + + memcpy(skb_put(skb_out, mac_header_len), mac_header_data, mac_header_len); + memcpy(skb_put(skb_out, sizeof(struct arphdr)), arp_out, sizeof(struct arphdr)); + memcpy(skb_put(skb_out, sizeof(struct arpdata)), arp_data_out, sizeof(struct arpdata)); + + skb_out->protocol = ((struct ethhdr *)mac_header_data)->h_proto; + skb_out->dev = skb_in->dev; + skb_reset_mac_header(skb_out); + skb_pull(skb_out, ETH_HLEN); + + gdm_lte_rx(skb_out, nic, nic_type); + + return 0; +} + +int icmp6_checksum(struct ipv6hdr *ipv6, u16 *ptr, int len) +{ + unsigned short *w = ptr; + int sum = 0; + int i; + + union { + struct { + u8 ph_src[16]; + u8 ph_dst[16]; + u32 ph_len; + u8 ph_zero[3]; + u8 ph_nxt; + } ph __packed; + u16 pa[20]; + } pseudo_header; + + memset(&pseudo_header, 0, sizeof(pseudo_header)); + memcpy(&pseudo_header.ph.ph_src, &ipv6->saddr.in6_u.u6_addr8, 16); + memcpy(&pseudo_header.ph.ph_dst, &ipv6->daddr.in6_u.u6_addr8, 16); + pseudo_header.ph.ph_len = ipv6->payload_len; + pseudo_header.ph.ph_nxt = ipv6->nexthdr; + + w = (u16 *)&pseudo_header; + for (i = 0; i < sizeof(pseudo_header.pa) / sizeof(pseudo_header.pa[0]); i++) + sum += pseudo_header.pa[i]; + + w = ptr; + while (len > 1) { + sum += *w++; + len -= 2; + } + + sum = (sum >> 16) + (sum & 0xFFFF); + sum += (sum >> 16); + sum = ~sum & 0xffff; + + return sum; +} + +int gdm_lte_emulate_ndp(struct sk_buff *skb_in, u32 nic_type) +{ + struct nic *nic = netdev_priv(skb_in->dev); + struct sk_buff *skb_out; + struct ethhdr eth; + struct vlan_ethhdr vlan_eth; + struct neighbour_advertisement { + u8 target_address[16]; + u8 type; + u8 length; + u8 link_layer_address[6]; + }; + struct neighbour_advertisement na; + struct neighbour_solicitation { + u8 target_address[16]; + }; + struct neighbour_solicitation *ns; + struct ipv6hdr *ipv6_in; + struct ipv6hdr ipv6_out; + struct icmp6hdr *icmp6_in; + struct icmp6hdr icmp6_out; + + void *mac_header_data; + u32 mac_header_len; + + /* Format the mac header so that it can be put to skb */ + if (ntohs(((struct ethhdr *)skb_in->data)->h_proto) == ETH_P_8021Q) { + memcpy(&vlan_eth, skb_in->data, sizeof(struct vlan_ethhdr)); + if (ntohs(vlan_eth.h_vlan_encapsulated_proto) != ETH_P_IPV6) + return -1; + mac_header_data = &vlan_eth; + mac_header_len = VLAN_ETH_HLEN; + } else { + memcpy(ð, skb_in->data, sizeof(struct ethhdr)); + if (ntohs(eth.h_proto) != ETH_P_IPV6) + return -1; + mac_header_data = ð + mac_header_len = ETH_HLEN; + } + + /* Check if this is IPv6 ICMP packet */ + ipv6_in = (struct ipv6hdr *)(skb_in->data + mac_header_len); + if (ipv6_in->version != 6 || ipv6_in->nexthdr != IPPROTO_ICMPV6) + return -1; + + /* Check if this is NDP packet */ + icmp6_in = (struct icmp6hdr *)(skb_in->data + mac_header_len + sizeof(struct ipv6hdr)); + if (icmp6_in->icmp6_type == NDISC_ROUTER_SOLICITATION) { /* Check RS */ + return -1; + } else if (icmp6_in->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) { /* Check NS */ + u8 icmp_na[sizeof(struct icmp6hdr) + sizeof(struct neighbour_advertisement)]; + u8 zero_addr8[16] = {0,}; + + if (memcmp(ipv6_in->saddr.in6_u.u6_addr8, zero_addr8, 16) == 0) + /* Duplicate Address Detection: Source IP is all zero */ + return 0; + + icmp6_out.icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT; + icmp6_out.icmp6_code = 0; + icmp6_out.icmp6_cksum = 0; + icmp6_out.icmp6_dataun.un_data32[0] = htonl(0x60000000); /* R=0, S=1, O=1 */ + + ns = (struct neighbour_solicitation *)(skb_in->data + mac_header_len + sizeof(struct ipv6hdr) + sizeof(struct icmp6hdr)); + memcpy(&na.target_address, ns->target_address, 16); + na.type = 0x02; + na.length = 1; + na.link_layer_address[0] = 0x00; + na.link_layer_address[1] = 0x0a; + na.link_layer_address[2] = 0x3b; + na.link_layer_address[3] = 0xaf; + na.link_layer_address[4] = 0x63; + na.link_layer_address[5] = 0xc7; + + memcpy(&ipv6_out, ipv6_in, sizeof(struct ipv6hdr)); + memcpy(ipv6_out.saddr.in6_u.u6_addr8, &na.target_address, 16); + memcpy(ipv6_out.daddr.in6_u.u6_addr8, ipv6_in->saddr.in6_u.u6_addr8, 16); + ipv6_out.payload_len = htons(sizeof(struct icmp6hdr) + sizeof(struct neighbour_advertisement)); + + memcpy(icmp_na, &icmp6_out, sizeof(struct icmp6hdr)); + memcpy(icmp_na + sizeof(struct icmp6hdr), &na, sizeof(struct neighbour_advertisement)); + + icmp6_out.icmp6_cksum = icmp6_checksum(&ipv6_out, (u16 *)icmp_na, sizeof(icmp_na)); + } else { + return -1; + } + + /* Fill the destination mac with source mac of the received packet */ + memcpy(mac_header_data, mac_header_data + ETH_ALEN, ETH_ALEN); + /* Fill the source mac with nic's source mac */ + memcpy(mac_header_data + ETH_ALEN, nic->src_mac_addr, ETH_ALEN); + + /* Alloc skb and reserve align */ + skb_out = dev_alloc_skb(skb_in->len); + if (!skb_out) + return -ENOMEM; + skb_reserve(skb_out, NET_IP_ALIGN); + + memcpy(skb_put(skb_out, mac_header_len), mac_header_data, mac_header_len); + memcpy(skb_put(skb_out, sizeof(struct ipv6hdr)), &ipv6_out, sizeof(struct ipv6hdr)); + memcpy(skb_put(skb_out, sizeof(struct icmp6hdr)), &icmp6_out, sizeof(struct icmp6hdr)); + memcpy(skb_put(skb_out, sizeof(struct neighbour_advertisement)), &na, sizeof(struct neighbour_advertisement)); + + skb_out->protocol = ((struct ethhdr *)mac_header_data)->h_proto; + skb_out->dev = skb_in->dev; + skb_reset_mac_header(skb_out); + skb_pull(skb_out, ETH_HLEN); + + gdm_lte_rx(skb_out, nic, nic_type); + + return 0; +} + +static s32 gdm_lte_tx_nic_type(struct net_device *dev, struct sk_buff *skb) +{ + struct nic *nic = netdev_priv(dev); + struct ethhdr *eth; + struct vlan_ethhdr *vlan_eth; + struct iphdr *ip; + struct ipv6hdr *ipv6; + int mac_proto; + void *network_data; + u32 nic_type = 0; + + /* NIC TYPE is based on the nic_id of this net_device */ + nic_type = 0x00000010 | nic->nic_id; + + /* Get ethernet protocol */ + eth = (struct ethhdr *)skb->data; + if (ntohs(eth->h_proto) == ETH_P_8021Q) { + vlan_eth = (struct vlan_ethhdr *)skb->data; + mac_proto = ntohs(vlan_eth->h_vlan_encapsulated_proto); + network_data = skb->data + VLAN_ETH_HLEN; + nic_type |= NIC_TYPE_F_VLAN; + } else { + mac_proto = ntohs(eth->h_proto); + network_data = skb->data + ETH_HLEN; + } + + /* Process packet for nic type */ + switch (mac_proto) { + case ETH_P_ARP: + nic_type |= NIC_TYPE_ARP; + break; + case ETH_P_IP: + nic_type |= NIC_TYPE_F_IPV4; + ip = (struct iphdr *)network_data; + + /* Check DHCPv4 */ + if (ip->protocol == IPPROTO_UDP) { + struct udphdr *udp = (struct udphdr *)(network_data + sizeof(struct iphdr)); + if (ntohs(udp->dest) == 67 || ntohs(udp->dest) == 68) + nic_type |= NIC_TYPE_F_DHCP; + } + break; + case ETH_P_IPV6: + nic_type |= NIC_TYPE_F_IPV6; + ipv6 = (struct ipv6hdr *)network_data; + + if (ipv6->nexthdr == IPPROTO_ICMPV6) /* Check NDP request */ { + struct icmp6hdr *icmp6 = (struct icmp6hdr *)(network_data + sizeof(struct ipv6hdr)); + if (/*icmp6->icmp6_type == NDISC_ROUTER_SOLICITATION || */ + icmp6->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) + nic_type |= NIC_TYPE_ICMPV6; + } else if (ipv6->nexthdr == IPPROTO_UDP) /* Check DHCPv6 */ { + struct udphdr *udp = (struct udphdr *)(network_data + sizeof(struct ipv6hdr)); + if (ntohs(udp->dest) == 546 || ntohs(udp->dest) == 547) + nic_type |= NIC_TYPE_F_DHCP; + } + break; + default: + break; + } + + return nic_type; +} + +static int gdm_lte_tx(struct sk_buff *skb, struct net_device *dev) +{ + struct nic *nic = netdev_priv(dev); + u32 nic_type; + void *data_buf; + int data_len; + int idx; + int ret = 0; + + nic_type = gdm_lte_tx_nic_type(dev, skb); + if (nic_type == 0) { + printk(KERN_ERR "glte: tx - invalid nic_type\n"); + return -1; + } + + if (nic_type & NIC_TYPE_ARP) { + if (gdm_lte_emulate_arp(skb, nic_type) == 0) { + dev_kfree_skb(skb); + return 0; + } + } + + if (nic_type & NIC_TYPE_ICMPV6) { + if (gdm_lte_emulate_ndp(skb, nic_type) == 0) { + dev_kfree_skb(skb); + return 0; + } + } + + /* + Need byte shift (that is, remove VLAN tag) if there is one + For the case of ARP, this breaks the offset as vlan_ethhdr+4 is treated as ethhdr + However, it shouldn't be a problem as the reponse starts from arp_hdr and ethhdr + is created by this driver based on the NIC mac + */ + if (nic_type & NIC_TYPE_F_VLAN) { + struct vlan_ethhdr *vlan_eth = (struct vlan_ethhdr *)skb->data; + nic->vlan_id = ntohs(vlan_eth->h_vlan_TCI) & VLAN_VID_MASK; + data_buf = skb->data + (VLAN_ETH_HLEN - ETH_HLEN); + data_len = skb->len - (VLAN_ETH_HLEN - ETH_HLEN); + } else { + nic->vlan_id = 0; + data_buf = skb->data; + data_len = skb->len; + } + + /* If it is a ICMPV6 packet, clear all the other bits : for backward compatibilty with the firmware */ + if (nic_type & NIC_TYPE_ICMPV6) + nic_type = NIC_TYPE_ICMPV6; + + /* If it is not a dhcp packet, clear all the flag bits : original NIC, otherwise the special flag (IPVX | DHCP) */ + if (!(nic_type & NIC_TYPE_F_DHCP)) + nic_type &= NIC_TYPE_MASK; + + sscanf(dev->name, "lte%d", &idx); + + ret = gdm_lte_sdu_send(nic, + data_buf, + data_len, + tx_complete, + nic, + idx, + nic_type); + + if (ret == TX_NO_BUFFER || ret == TX_NO_SPC) { + netif_stop_queue(dev); + if (ret == TX_NO_BUFFER) + ret = 0; + else + ret = -ENOSPC; + } else if (ret == TX_NO_DEV) { + ret = -ENODEV; + } + + /* Updates tx stats */ + if (ret) { + nic->stats.tx_dropped++; + } else { + nic->stats.tx_packets++; + nic->stats.tx_bytes += data_len; + } + dev_kfree_skb(skb); + + return 0; +} + +static struct net_device_stats *gdm_lte_stats(struct net_device *dev) +{ + struct nic *nic = netdev_priv(dev); + return &nic->stats; +} + +static void get_dev_endian(struct data_t *data, struct net_device *dev) +{ + struct nic *nic = netdev_priv(dev); + unsigned long ret; + + ret = copy_to_user(data->buf, gdm_dev_endian(nic), sizeof(struct dev_endian_t)); + if (ret) + printk(KERN_INFO "glte: state - failed to copy\n"); +} + +static int gdm_lte_ioctl_get_data(struct wm_req_t *req, struct net_device *dev) +{ + u16 id = req->data_id; + + switch (id) { + case GET_ENDIAN_INFO: + /* required for the user space application to find out device endian */ + get_dev_endian(&req->data, dev); + break; + default: + printk(KERN_ERR "glte: ioctl - unknown type %d\n", id); + break; + } + return 0; +} + +static int gdm_lte_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + struct wm_req_t *req = (struct wm_req_t *)ifr; + + if (cmd != SIOCLTEIOCTL || req->cmd != SIOCG_DATA || req->data_id >= 100) + return -EOPNOTSUPP; + + return gdm_lte_ioctl_get_data(req, dev); +} + +static int gdm_lte_event_send(struct net_device *dev, char *buf, int len) +{ + struct nic *nic = netdev_priv(dev); + struct hci_packet *hci = (struct hci_packet *)buf; + int idx; + + sscanf(dev->name, "lte%d", &idx); + + return netlink_send(lte_event.sock, idx, 0, buf, + gdm_dev16_to_cpu(gdm_dev_endian(nic), hci->len) + HCI_HEADER_SIZE); +} + +static void gdm_lte_event_rcv(struct net_device *dev, u16 type, void *msg, int len) +{ + struct nic *nic = netdev_priv(dev); + + gdm_lte_hci_send(nic, msg, len); +} + +int gdm_lte_event_init(void) +{ + if (lte_event.ref_cnt == 0) + lte_event.sock = netlink_init(NETLINK_LTE, gdm_lte_event_rcv); + + if (lte_event.sock) { + lte_event.ref_cnt++; + return 0; + } + + printk(KERN_ERR "glte: event init failed\n"); + return -1; +} + +void gdm_lte_event_exit(void) +{ + if (lte_event.sock && --lte_event.ref_cnt == 0) { + netlink_exit(lte_event.sock); + lte_event.sock = NULL; + } +} + +static u8 find_dev_index(u32 nic_type) +{ + u8 index; + + index = (u8)(nic_type & 0x0000000f); + if (index > MAX_NIC_TYPE) + index = 0; + + return index; +} + +static void gdm_lte_netif_rx(struct net_device *dev, char *buf, int len, int flagged_nic_type) +{ + u32 nic_type; + struct nic *nic; + struct sk_buff *skb; + struct ethhdr eth; + struct vlan_ethhdr vlan_eth; + void *mac_header_data; + u32 mac_header_len; + char ip_version = 0; + + nic_type = flagged_nic_type & NIC_TYPE_MASK; + nic = netdev_priv(dev); + + if (flagged_nic_type & NIC_TYPE_F_DHCP) { + /* Change the destination mac address with the one requested the IP */ + if (flagged_nic_type & NIC_TYPE_F_IPV4) { + struct dhcp_packet { + u8 op; /* BOOTREQUEST or BOOTREPLY */ + u8 htype; /* hardware address type. 1 = 10mb ethernet */ + u8 hlen; /* hardware address length */ + u8 hops; /* used by relay agents only */ + u32 xid; /* unique id */ + u16 secs; /* elapsed since client began acquisition/renewal */ + u16 flags; /* only one flag so far: */ + #define BROADCAST_FLAG 0x8000 /* "I need broadcast replies" */ + u32 ciaddr; /* client IP (if client is in BOUND, RENEW or REBINDING state) */ + u32 yiaddr; /* 'your' (client) IP address */ + /* IP address of next server to use in bootstrap, returned in DHCPOFFER, DHCPACK by server */ + u32 siaddr_nip; + u32 gateway_nip; /* relay agent IP address */ + u8 chaddr[16]; /* link-layer client hardware address (MAC) */ + u8 sname[64]; /* server host name (ASCIZ) */ + u8 file[128]; /* boot file name (ASCIZ) */ + u32 cookie; /* fixed first four option bytes (99,130,83,99 dec) */ + } __packed; + void *addr = buf + sizeof(struct iphdr) + sizeof(struct udphdr) + offsetof(struct dhcp_packet, chaddr); + memcpy(nic->dest_mac_addr, addr, ETH_ALEN); + } + } + + if (nic->vlan_id > 0) { + mac_header_data = (void *)&vlan_eth; + mac_header_len = VLAN_ETH_HLEN; + } else { + mac_header_data = (void *)ð + mac_header_len = ETH_HLEN; + } + + /* Format the data so that it can be put to skb */ + memcpy(mac_header_data, nic->dest_mac_addr, ETH_ALEN); + memcpy(mac_header_data + ETH_ALEN, nic->src_mac_addr, ETH_ALEN); + + vlan_eth.h_vlan_TCI = htons(nic->vlan_id); + vlan_eth.h_vlan_proto = htons(ETH_P_8021Q); + + if (nic_type == NIC_TYPE_ARP) { + /* Should be response: Only happens because there was a request from the host */ + eth.h_proto = htons(ETH_P_ARP); + vlan_eth.h_vlan_encapsulated_proto = htons(ETH_P_ARP); + } else { + ip_version = buf[0] >> 4; + if (ip_version == IP_VERSION_4) { + eth.h_proto = htons(ETH_P_IP); + vlan_eth.h_vlan_encapsulated_proto = htons(ETH_P_IP); + } else if (ip_version == IP_VERSION_6) { + eth.h_proto = htons(ETH_P_IPV6); + vlan_eth.h_vlan_encapsulated_proto = htons(ETH_P_IPV6); + } else { + printk(KERN_ERR "glte: Unknown IP version %d\n", ip_version); + return; + } + } + + /* Alloc skb and reserve align */ + skb = dev_alloc_skb(len + mac_header_len + NET_IP_ALIGN); + if (!skb) + return; + skb_reserve(skb, NET_IP_ALIGN); + + memcpy(skb_put(skb, mac_header_len), mac_header_data, mac_header_len); + memcpy(skb_put(skb, len), buf, len); + + skb->protocol = ((struct ethhdr *)mac_header_data)->h_proto; + skb->dev = dev; + skb_reset_mac_header(skb); + skb_pull(skb, ETH_HLEN); + + gdm_lte_rx(skb, nic, nic_type); +} + +static void gdm_lte_multi_sdu_pkt(struct phy_dev *phy_dev, char *buf, int len) +{ + struct net_device *dev; + struct multi_sdu *multi_sdu = (struct multi_sdu *)buf; + struct sdu *sdu = NULL; + u8 *data = (u8 *)multi_sdu->data; + u16 i = 0; + u16 num_packet; + u16 hci_len; + u16 cmd_evt; + u32 nic_type; + u8 index; + + hci_len = gdm_dev16_to_cpu(phy_dev->get_endian(phy_dev->priv_dev), multi_sdu->len); + num_packet = gdm_dev16_to_cpu(phy_dev->get_endian(phy_dev->priv_dev), multi_sdu->num_packet); + + for (i = 0; i < num_packet; i++) { + sdu = (struct sdu *)data; + + cmd_evt = gdm_dev16_to_cpu(phy_dev->get_endian(phy_dev->priv_dev), sdu->cmd_evt); + hci_len = gdm_dev16_to_cpu(phy_dev->get_endian(phy_dev->priv_dev), sdu->len); + nic_type = gdm_dev32_to_cpu(phy_dev->get_endian(phy_dev->priv_dev), sdu->nic_type); + + if (cmd_evt != LTE_RX_SDU) { + printk(KERN_ERR "glte: rx sdu wrong hci %04x\n", cmd_evt); + return; + } + if (hci_len < 12) { + printk(KERN_ERR "glte: rx sdu invalid len %d\n", hci_len); + return; + } + + index = find_dev_index(nic_type); + if (index < MAX_NIC_TYPE) { + dev = phy_dev->dev[index]; + gdm_lte_netif_rx(dev, (char *)sdu->data, (int)(hci_len-12), nic_type); + } else { + printk(KERN_ERR "glte: rx sdu invalid nic_type : %x\n", nic_type); + } + + data += ((hci_len+3) & 0xfffc) + HCI_HEADER_SIZE; + } +} + +static void gdm_lte_pdn_table(struct net_device *dev, char *buf, int len) +{ + struct nic *nic = netdev_priv(dev); + struct hci_pdn_table_ind *pdn_table = (struct hci_pdn_table_ind *)buf; + + if (pdn_table->activate) { + nic->pdn_table.activate = pdn_table->activate; + nic->pdn_table.dft_eps_id = gdm_dev32_to_cpu(gdm_dev_endian(nic), pdn_table->dft_eps_id); + nic->pdn_table.nic_type = gdm_dev32_to_cpu(gdm_dev_endian(nic), pdn_table->nic_type); + + printk(KERN_INFO "glte: pdn %s activated, nic_type=0x%x\n", + dev->name, nic->pdn_table.nic_type); + } else { + memset(&nic->pdn_table, 0x00, sizeof(struct pdn_table)); + printk(KERN_INFO "glte: pdn %s deactivated\n", + dev->name); + } +} + +static int gdm_lte_receive_pkt(struct phy_dev *phy_dev, char *buf, int len) +{ + struct hci_packet *hci = (struct hci_packet *)buf; + struct hci_pdn_table_ind *pdn_table = (struct hci_pdn_table_ind *)buf; + struct sdu *sdu; + struct net_device *dev; + int ret = 0; + u16 cmd_evt; + u32 nic_type; + u8 index; + + if (!len) + return ret; + + cmd_evt = gdm_dev16_to_cpu(phy_dev->get_endian(phy_dev->priv_dev), hci->cmd_evt); + + dev = phy_dev->dev[0]; + if (dev == NULL) + return 0; + + switch (cmd_evt) { + case LTE_RX_SDU: + sdu = (struct sdu *)hci->data; + nic_type = gdm_dev32_to_cpu(phy_dev->get_endian(phy_dev->priv_dev), sdu->nic_type); + index = find_dev_index(nic_type); + dev = phy_dev->dev[index]; + gdm_lte_netif_rx(dev, hci->data, len, nic_type); + break; + case LTE_RX_MULTI_SDU: + gdm_lte_multi_sdu_pkt(phy_dev, buf, len); + break; + case LTE_LINK_ON_OFF_INDICATION: + { + struct hci_connect_ind *connect_ind = (struct hci_connect_ind *)buf; + printk(KERN_INFO "glte: link %s\n", + connect_ind->connect ? "on" : "off"); + } + break; + case LTE_PDN_TABLE_IND: + pdn_table = (struct hci_pdn_table_ind *)buf; + nic_type = gdm_dev32_to_cpu(phy_dev->get_endian(phy_dev->priv_dev), pdn_table->nic_type); + index = find_dev_index(nic_type); + dev = phy_dev->dev[index]; + gdm_lte_pdn_table(dev, buf, len); + /* Fall through */ + default: + ret = gdm_lte_event_send(dev, buf, len); + break; + } + + return ret; +} + +static int rx_complete(void *arg, void *data, int len, int context) +{ + struct phy_dev *phy_dev = (struct phy_dev *)arg; + + return gdm_lte_receive_pkt(phy_dev, (char *)data, len); +} + +void start_rx_proc(struct phy_dev *phy_dev) +{ + int i; + + for (i = 0; i < MAX_RX_SUBMIT_COUNT; i++) + gdm_lte_rcv_with_cb(phy_dev, rx_complete, phy_dev, USB_COMPLETE); +} + +static struct net_device_ops gdm_netdev_ops = { + .ndo_open = gdm_lte_open, + .ndo_stop = gdm_lte_close, + .ndo_set_config = gdm_lte_set_config, + .ndo_start_xmit = gdm_lte_tx, + .ndo_get_stats = gdm_lte_stats, + .ndo_do_ioctl = gdm_lte_ioctl, +}; + +static u8 gdm_lte_macaddr[ETH_ALEN] = {0x00, 0x0a, 0x3b, 0x00, 0x00, 0x00}; + +static void form_mac_address(u8 *dev_addr, u8 *nic_src, u8 *nic_dest, u8 *mac_address, u8 index) +{ + /* Form the dev_addr */ + if (!mac_address) + memcpy(dev_addr, gdm_lte_macaddr, ETH_ALEN); + else + memcpy(dev_addr, mac_address, ETH_ALEN); + + /* The last byte of the mac address should be less than or equal to 0xFC */ + dev_addr[ETH_ALEN-1] += index; + + /* Create random nic src and copy the first 3 bytes to be the same as dev_addr */ + random_ether_addr(nic_src); + memcpy(nic_src, dev_addr, 3); + + /* Copy the nic_dest from dev_addr*/ + memcpy(nic_dest, dev_addr, ETH_ALEN); +} + +static void validate_mac_address(u8 *mac_address) +{ + /* if zero address or multicast bit set, restore the default value */ + if (is_zero_ether_addr(mac_address) || (mac_address[0] & 0x01)) { + printk(KERN_ERR "glte: MAC invalid, restoring default\n"); + memcpy(mac_address, gdm_lte_macaddr, 6); + } +} + +int register_lte_device(struct phy_dev *phy_dev, struct device *dev, u8 *mac_address) +{ + struct nic *nic; + struct net_device *net; + char pdn_dev_name[16]; + int ret = 0; + u8 index; + + validate_mac_address(mac_address); + + for (index = 0; index < MAX_NIC_TYPE; index++) { + /* Create device name lteXpdnX */ + sprintf(pdn_dev_name, "lte%%dpdn%d", index); + + /* Allocate netdev */ + net = alloc_netdev(sizeof(struct nic), pdn_dev_name, ether_setup); + if (net == NULL) { + printk(KERN_ERR "glte: alloc_netdev failed\n"); + ret = -ENOMEM; + goto err; + } + net->netdev_ops = &gdm_netdev_ops; + net->flags &= ~IFF_MULTICAST; + net->mtu = DEFAULT_MTU_SIZE; + + nic = netdev_priv(net); + memset(nic, 0, sizeof(struct nic)); + nic->netdev = net; + nic->phy_dev = phy_dev; + nic->nic_id = index; + + form_mac_address( + net->dev_addr, + nic->src_mac_addr, + nic->dest_mac_addr, + mac_address, + index); + + SET_NETDEV_DEV(net, dev); + SET_NETDEV_DEVTYPE(net, &wwan_type); + + ret = register_netdev(net); + if (ret) + goto err; + + netif_carrier_on(net); + + phy_dev->dev[index] = net; + } + + return 0; + +err: + unregister_lte_device(phy_dev); + + return ret; +} + +void unregister_lte_device(struct phy_dev *phy_dev) +{ + struct net_device *net; + int index; + + for (index = 0; index < MAX_NIC_TYPE; index++) { + net = phy_dev->dev[index]; + if (net == NULL) + continue; + + unregister_netdev(net); + free_netdev(net); + } +} diff --git a/drivers/staging/gdm724x/gdm_lte.h b/drivers/staging/gdm724x/gdm_lte.h new file mode 100644 index 000000000000..1614e917c004 --- /dev/null +++ b/drivers/staging/gdm724x/gdm_lte.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +#ifndef _GDM_LTE_H_ +#define _GDM_LTE_H_ + +#include +#include +#include + +#include "gdm_endian.h" + +#define MAX_NIC_TYPE 4 +#define MAX_RX_SUBMIT_COUNT 3 +#define DRIVER_VERSION "3.7.17.0" + +enum TX_ERROR_CODE { + TX_NO_ERROR = 0, + TX_NO_DEV, + TX_NO_SPC, + TX_NO_BUFFER, +}; + +enum CALLBACK_CONTEXT { + KERNEL_THREAD = 0, + USB_COMPLETE, +}; + +struct pdn_table { + u8 activate; + u32 dft_eps_id; + u32 nic_type; +} __packed; + +struct nic; + +struct phy_dev { + void *priv_dev; + struct net_device *dev[MAX_NIC_TYPE]; + int (*send_hci_func)(void *priv_dev, void *data, int len, + void (*cb)(void *cb_data), void *cb_data); + int (*send_sdu_func)(void *priv_dev, void *data, int len, + unsigned int dftEpsId, unsigned int epsId, + void (*cb)(void *cb_data), void *cb_data, + int dev_idx, int nic_type); + int (*rcv_func)(void *priv_dev, + int (*cb)(void *cb_data, void *data, int len, int context), + void *cb_data, int context); + struct gdm_endian *(*get_endian)(void *priv_dev); +}; + +struct nic { + struct net_device *netdev; + struct phy_dev *phy_dev; + struct net_device_stats stats; + struct pdn_table pdn_table; + u8 dest_mac_addr[ETH_ALEN]; + u8 src_mac_addr[ETH_ALEN]; + u32 nic_id; + u16 vlan_id; +}; + +int gdm_lte_event_init(void); +void gdm_lte_event_exit(void); + +void start_rx_proc(struct phy_dev *phy_dev); +int register_lte_device(struct phy_dev *phy_dev, struct device *dev, u8 *mac_address); +void unregister_lte_device(struct phy_dev *phy_dev); + +#endif /* _GDM_LTE_H_ */ diff --git a/drivers/staging/gdm724x/gdm_mux.c b/drivers/staging/gdm724x/gdm_mux.c new file mode 100644 index 000000000000..2199f1bcbc84 --- /dev/null +++ b/drivers/staging/gdm724x/gdm_mux.c @@ -0,0 +1,700 @@ +/* + * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gdm_mux.h" +#include "gdm_tty.h" + +struct workqueue_struct *mux_rx_wq; + +static u16 packet_type[TTY_MAX_COUNT] = {0xF011, 0xF010}; + +#define USB_DEVICE_CDC_DATA(vid, pid) \ + .match_flags = \ + USB_DEVICE_ID_MATCH_DEVICE |\ + USB_DEVICE_ID_MATCH_INT_CLASS |\ + USB_DEVICE_ID_MATCH_INT_SUBCLASS,\ + .idVendor = vid,\ + .idProduct = pid,\ + .bInterfaceClass = USB_CLASS_COMM,\ + .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM + +static const struct usb_device_id id_table[] = { + { USB_DEVICE_CDC_DATA(0x1076, 0x8000) }, /* GCT GDM7240 */ + { USB_DEVICE_CDC_DATA(0x1076, 0x8f00) }, /* GCT GDM7243 */ + { USB_DEVICE_CDC_DATA(0x1076, 0x9000) }, /* GCT GDM7243 */ + { USB_DEVICE_CDC_DATA(0x1d74, 0x2300) }, /* LGIT Phoenix */ + {} +}; + + +MODULE_DEVICE_TABLE(usb, id_table); + +int packet_type_to_index(u16 packetType) +{ + int i; + + for (i = 0; i < TTY_MAX_COUNT; i++) { + if (packet_type[i] == packetType) + return i; + } + + return -1; +} + +static struct mux_tx *alloc_mux_tx(int len) +{ + struct mux_tx *t = NULL; + + t = kzalloc(sizeof(struct mux_tx), GFP_ATOMIC); + if (!t) + return NULL; + + t->urb = usb_alloc_urb(0, GFP_ATOMIC); + t->buf = kmalloc(MUX_TX_MAX_SIZE, GFP_ATOMIC); + if (!t->urb || !t->buf) { + usb_free_urb(t->urb); + kfree(t->buf); + kfree(t); + return NULL; + } + + return t; +} + +static void free_mux_tx(struct mux_tx *t) +{ + if (t) { + usb_free_urb(t->urb); + kfree(t->buf); + kfree(t); + } +} + +static struct mux_rx *alloc_mux_rx(void) +{ + struct mux_rx *r = NULL; + + r = kzalloc(sizeof(struct mux_rx), GFP_ATOMIC); + if (!r) + return NULL; + + r->urb = usb_alloc_urb(0, GFP_ATOMIC); + r->buf = kmalloc(MUX_RX_MAX_SIZE, GFP_ATOMIC); + if (!r->urb || !r->buf) { + usb_free_urb(r->urb); + kfree(r->buf); + kfree(r); + return NULL; + } + + return r; +} + +static void free_mux_rx(struct mux_rx *r) +{ + if (r) { + usb_free_urb(r->urb); + kfree(r->buf); + kfree(r); + } +} + +static struct mux_rx *get_rx_struct(struct rx_cxt *rx) +{ + struct mux_rx *r; + unsigned long flags; + + spin_lock_irqsave(&rx->free_list_lock, flags); + + if (list_empty(&rx->rx_free_list)) { + spin_unlock_irqrestore(&rx->free_list_lock, flags); + return NULL; + } + + r = list_entry(rx->rx_free_list.prev, struct mux_rx, free_list); + list_del(&r->free_list); + + spin_unlock_irqrestore(&rx->free_list_lock, flags); + + return r; +} + +static void put_rx_struct(struct rx_cxt *rx, struct mux_rx *r) +{ + unsigned long flags; + + spin_lock_irqsave(&rx->free_list_lock, flags); + list_add_tail(&r->free_list, &rx->rx_free_list); + spin_unlock_irqrestore(&rx->free_list_lock, flags); +} + + +static int up_to_host(struct mux_rx *r) +{ + struct mux_dev *mux_dev = (struct mux_dev *)r->mux_dev; + struct mux_pkt_header *mux_header; + unsigned int start_flag; + unsigned int payload_size; + unsigned short packet_type; + int remain; + int dummy_cnt; + u32 packet_size_sum = r->offset; + int index; + int ret = TO_HOST_INVALID_PACKET; + int len = r->len; + + while (1) { + mux_header = (struct mux_pkt_header *)(r->buf + packet_size_sum); + start_flag = __le32_to_cpu(mux_header->start_flag); + payload_size = __le32_to_cpu(mux_header->payload_size); + packet_type = __le16_to_cpu(mux_header->packet_type); + + if (start_flag != START_FLAG) { + printk(KERN_ERR "glte: invalid START_FLAG %x\n", + start_flag); + break; + } + + remain = (MUX_HEADER_SIZE + payload_size) % 4; + dummy_cnt = remain ? (4-remain) : 0; + + if (len - packet_size_sum < + MUX_HEADER_SIZE + payload_size + dummy_cnt) { + printk(KERN_ERR "glte: invalid payload : %d %d %04x\n", + payload_size, len, + packet_type + ); + break; + } + + index = packet_type_to_index(packet_type); + if (index < 0) { + printk(KERN_ERR "glte: invalid index %d\n", index); + break; + } + + ret = r->callback(mux_header->data, + payload_size, + index, + mux_dev->minor[index], + RECV_PACKET_PROCESS_CONTINUE + ); + if (ret == TO_HOST_BUFFER_REQUEST_FAIL) { + r->offset += packet_size_sum; + break; + } + + packet_size_sum += MUX_HEADER_SIZE + payload_size + dummy_cnt; + if (len - packet_size_sum <= MUX_HEADER_SIZE + 2) { + ret = r->callback(NULL, + 0, + index, + mux_dev->minor[index], + RECV_PACKET_PROCESS_COMPLETE + ); + break; + } + } + + return ret; +} + +static void do_rx(struct work_struct *work) +{ + struct mux_dev *mux_dev = + container_of(work, struct mux_dev , work_rx.work); + struct mux_rx *r; + struct rx_cxt *rx = (struct rx_cxt *)&mux_dev->rx; + unsigned long flags; + int ret = 0; + + while (1) { + spin_lock_irqsave(&rx->to_host_lock, flags); + if (list_empty(&rx->to_host_list)) { + spin_unlock_irqrestore(&rx->to_host_lock, flags); + break; + } + r = list_entry(rx->to_host_list.next, struct mux_rx, to_host_list); + list_del(&r->to_host_list); + spin_unlock_irqrestore(&rx->to_host_lock, flags); + + ret = up_to_host(r); + if (ret == TO_HOST_BUFFER_REQUEST_FAIL) + printk(KERN_ERR "glte: failed to send mux data to host\n"); + else + put_rx_struct(rx, r); + } +} + +static void remove_rx_submit_list(struct mux_rx *r, struct rx_cxt *rx) +{ + unsigned long flags; + struct mux_rx *r_remove, *r_remove_next; + + spin_lock_irqsave(&rx->submit_list_lock, flags); + list_for_each_entry_safe(r_remove, r_remove_next, &rx->rx_submit_list, rx_submit_list) { + if (r == r_remove) + list_del(&r->rx_submit_list); + } + spin_unlock_irqrestore(&rx->submit_list_lock, flags); +} + +static void gdm_mux_rcv_complete(struct urb *urb) +{ + struct mux_rx *r = urb->context; + struct mux_dev *mux_dev = (struct mux_dev *)r->mux_dev; + struct rx_cxt *rx = &mux_dev->rx; + unsigned long flags; + + remove_rx_submit_list(r, rx); + + if (urb->status) { + if (mux_dev->usb_state == PM_NORMAL) + printk(KERN_ERR "glte: gdm_mux_rcv_complete urb status error %d\n", urb->status); + put_rx_struct(rx, r); + } else { + r->len = r->urb->actual_length; + spin_lock_irqsave(&rx->to_host_lock, flags); + list_add_tail(&r->to_host_list, &rx->to_host_list); + queue_work(mux_rx_wq, &mux_dev->work_rx.work); + spin_unlock_irqrestore(&rx->to_host_lock, flags); + } +} + +static int gdm_mux_recv(void *priv_dev, + int (*cb)(void *data, int len, int tty_index, int minor, int complete) + ) +{ + struct mux_dev *mux_dev = priv_dev; + struct usb_device *usbdev = mux_dev->usbdev; + struct mux_rx *r; + struct rx_cxt *rx = &mux_dev->rx; + unsigned long flags; + int ret; + + if (!usbdev) { + printk(KERN_ERR "glte: device is disconnected\n"); + return -ENODEV; + } + + r = get_rx_struct(rx); + if (!r) { + printk(KERN_ERR "glte: get_rx_struct fail\n"); + return -ENOMEM; + } + + r->offset = 0; + r->mux_dev = (void *)mux_dev; + r->callback = cb; + mux_dev->rx_cb = cb; + + usb_fill_bulk_urb(r->urb, + usbdev, + usb_rcvbulkpipe(usbdev, 0x86), + r->buf, + MUX_RX_MAX_SIZE, + gdm_mux_rcv_complete, + r); + + spin_lock_irqsave(&rx->submit_list_lock, flags); + list_add_tail(&r->rx_submit_list, &rx->rx_submit_list); + spin_unlock_irqrestore(&rx->submit_list_lock, flags); + + ret = usb_submit_urb(r->urb, GFP_KERNEL); + + if (ret) { + spin_lock_irqsave(&rx->submit_list_lock, flags); + list_del(&r->rx_submit_list); + spin_unlock_irqrestore(&rx->submit_list_lock, flags); + + put_rx_struct(rx, r); + + printk(KERN_ERR "glte: usb_submit_urb ret=%d\n", ret); + } + + usb_mark_last_busy(usbdev); + + return ret; +} + +static void gdm_mux_send_complete(struct urb *urb) +{ + struct mux_tx *t = urb->context; + + if (urb->status == -ECONNRESET) { + printk(KERN_INFO "glte: CONNRESET\n"); + free_mux_tx(t); + return; + } + + if (t->callback) + t->callback(t->cb_data); + + free_mux_tx(t); +} + +static int gdm_mux_send(void *priv_dev, void *data, int len, int tty_index, + void (*cb)(void *data), void *cb_data) +{ + struct mux_dev *mux_dev = priv_dev; + struct usb_device *usbdev = mux_dev->usbdev; + struct mux_pkt_header *mux_header; + struct mux_tx *t = NULL; + static u32 seq_num = 1; + int remain; + int dummy_cnt; + int total_len; + int ret; + unsigned long flags; + + if (mux_dev->usb_state == PM_SUSPEND) { + ret = usb_autopm_get_interface(mux_dev->intf); + if (!ret) + usb_autopm_put_interface(mux_dev->intf); + } + + spin_lock_irqsave(&mux_dev->write_lock, flags); + + remain = (MUX_HEADER_SIZE + len) % 4; + dummy_cnt = remain ? (4 - remain) : 0; + + total_len = len + MUX_HEADER_SIZE + dummy_cnt; + + t = alloc_mux_tx(total_len); + if (!t) { + printk(KERN_ERR "glte: alloc_mux_tx fail\n"); + spin_unlock_irqrestore(&mux_dev->write_lock, flags); + return -ENOMEM; + } + + mux_header = (struct mux_pkt_header *)t->buf; + mux_header->start_flag = __cpu_to_le32(START_FLAG); + mux_header->seq_num = __cpu_to_le32(seq_num++); + mux_header->payload_size = __cpu_to_le32((u32)len); + mux_header->packet_type = __cpu_to_le16(packet_type[tty_index]); + + memcpy(t->buf+MUX_HEADER_SIZE, data, len); + memset(t->buf+MUX_HEADER_SIZE+len, 0, dummy_cnt); + + t->len = total_len; + t->callback = cb; + t->cb_data = cb_data; + + usb_fill_bulk_urb(t->urb, + usbdev, + usb_sndbulkpipe(usbdev, 5), + t->buf, + total_len, + gdm_mux_send_complete, + t); + + ret = usb_submit_urb(t->urb, GFP_KERNEL); + + spin_unlock_irqrestore(&mux_dev->write_lock, flags); + + if (ret) + printk(KERN_ERR "glte: usb_submit_urb Error : %d\n", ret); + + usb_mark_last_busy(usbdev); + + return ret; +} + +static int gdm_mux_send_control(void *priv_dev, int request, int value, void *buf, int len) +{ + struct mux_dev *mux_dev = priv_dev; + struct usb_device *usbdev = mux_dev->usbdev; + int ret; + + ret = usb_control_msg(usbdev, + usb_sndctrlpipe(usbdev, 0), + request, + USB_RT_ACM, + value, + 2, + buf, + len, + 5000 + ); + + if (ret < 0) + printk(KERN_ERR "glte: usb_control_msg error : %d\n", ret); + + return ret < 0 ? ret : 0; +} + +static void release_usb(struct mux_dev *mux_dev) +{ + struct rx_cxt *rx = &mux_dev->rx; + struct mux_rx *r, *r_next; + unsigned long flags; + + cancel_delayed_work(&mux_dev->work_rx); + + spin_lock_irqsave(&rx->submit_list_lock, flags); + list_for_each_entry_safe(r, r_next, &rx->rx_submit_list, rx_submit_list) { + spin_unlock_irqrestore(&rx->submit_list_lock, flags); + usb_kill_urb(r->urb); + spin_lock_irqsave(&rx->submit_list_lock, flags); + } + spin_unlock_irqrestore(&rx->submit_list_lock, flags); + + spin_lock_irqsave(&rx->free_list_lock, flags); + list_for_each_entry_safe(r, r_next, &rx->rx_free_list, free_list) { + list_del(&r->free_list); + free_mux_rx(r); + } + spin_unlock_irqrestore(&rx->free_list_lock, flags); + + spin_lock_irqsave(&rx->to_host_lock, flags); + list_for_each_entry_safe(r, r_next, &rx->to_host_list, to_host_list) { + if (r->mux_dev == (void *)mux_dev) { + list_del(&r->to_host_list); + free_mux_rx(r); + } + } + spin_unlock_irqrestore(&rx->to_host_lock, flags); +} + + +static int init_usb(struct mux_dev *mux_dev) +{ + struct mux_rx *r; + struct rx_cxt *rx = &mux_dev->rx; + int ret = 0; + int i; + + spin_lock_init(&mux_dev->write_lock); + INIT_LIST_HEAD(&rx->to_host_list); + INIT_LIST_HEAD(&rx->rx_submit_list); + INIT_LIST_HEAD(&rx->rx_free_list); + spin_lock_init(&rx->to_host_lock); + spin_lock_init(&rx->submit_list_lock); + spin_lock_init(&rx->free_list_lock); + + for (i = 0; i < MAX_ISSUE_NUM * 2; i++) { + r = alloc_mux_rx(); + if (r == NULL) { + ret = -ENOMEM; + break; + } + + list_add(&r->free_list, &rx->rx_free_list); + } + + INIT_DELAYED_WORK(&mux_dev->work_rx, do_rx); + + return ret; +} + +static int gdm_mux_probe(struct usb_interface *intf, const struct usb_device_id *id) +{ + struct mux_dev *mux_dev = NULL; + struct tty_dev *tty_dev = NULL; + u16 idVendor, idProduct; + int bInterfaceNumber; + int ret = 0; + int i; + struct usb_device *usbdev = interface_to_usbdev(intf); + bInterfaceNumber = intf->cur_altsetting->desc.bInterfaceNumber; + + idVendor = __le16_to_cpu(usbdev->descriptor.idVendor); + idProduct = __le16_to_cpu(usbdev->descriptor.idProduct); + + printk(KERN_INFO "glte: mux vid = 0x%04x pid = 0x%04x\n", + idVendor, idProduct); + + if (bInterfaceNumber != 2) { + ret = -ENODEV; + goto out; + } + + mux_dev = kzalloc(sizeof(struct mux_dev), GFP_KERNEL); + if (!mux_dev) { + ret = -ENOMEM; + goto out; + } + + tty_dev = kzalloc(sizeof(struct tty_dev), GFP_KERNEL); + if (!tty_dev) { + kfree(mux_dev); + ret = -ENOMEM; + goto out; + } + + mux_dev->usbdev = usbdev; + mux_dev->control_intf = intf; + + ret = init_usb(mux_dev); + if (ret < 0) + goto out; + + tty_dev->priv_dev = (void *)mux_dev; + tty_dev->send_func = gdm_mux_send; + tty_dev->recv_func = gdm_mux_recv; + tty_dev->send_control = gdm_mux_send_control; + + if (register_lte_tty_device(tty_dev, &intf->dev) < 0) { + unregister_lte_tty_device(tty_dev); + mux_dev = tty_dev->priv_dev; + + ret = -1; + goto out; + } + for (i = 0; i < TTY_MAX_COUNT; i++) + mux_dev->minor[i] = tty_dev->minor[i]; + +out: + if (ret < 0) { + kfree(tty_dev); + if (mux_dev) { + release_usb(mux_dev); + kfree(mux_dev); + } + } else { + mux_dev->intf = intf; + mux_dev->usb_state = PM_NORMAL; + } + + usb_get_dev(usbdev); + usb_set_intfdata(intf, tty_dev); + + return ret; +} + +static void gdm_mux_disconnect(struct usb_interface *intf) +{ + struct tty_dev *tty_dev; + struct mux_dev *mux_dev; + struct usb_device *usbdev = interface_to_usbdev(intf); + + tty_dev = usb_get_intfdata(intf); + + mux_dev = tty_dev->priv_dev; + + release_usb(mux_dev); + unregister_lte_tty_device(tty_dev); + + kfree(mux_dev); + kfree(tty_dev); + + usb_put_dev(usbdev); +} + +static int gdm_mux_suspend(struct usb_interface *intf, pm_message_t pm_msg) +{ + struct tty_dev *tty_dev; + struct mux_dev *mux_dev; + struct rx_cxt *rx; + struct mux_rx *r, *r_next; + unsigned long flags; + + tty_dev = usb_get_intfdata(intf); + mux_dev = tty_dev->priv_dev; + rx = &mux_dev->rx; + + if (mux_dev->usb_state != PM_NORMAL) { + printk(KERN_ERR "glte: usb suspend - invalid state\n"); + return -1; + } + + mux_dev->usb_state = PM_SUSPEND; + + + spin_lock_irqsave(&rx->submit_list_lock, flags); + list_for_each_entry_safe(r, r_next, &rx->rx_submit_list, rx_submit_list) { + spin_unlock_irqrestore(&rx->submit_list_lock, flags); + usb_kill_urb(r->urb); + spin_lock_irqsave(&rx->submit_list_lock, flags); + } + spin_unlock_irqrestore(&rx->submit_list_lock, flags); + + return 0; +} + +static int gdm_mux_resume(struct usb_interface *intf) +{ + struct tty_dev *tty_dev; + struct mux_dev *mux_dev; + u8 i; + + tty_dev = usb_get_intfdata(intf); + mux_dev = tty_dev->priv_dev; + + if (mux_dev->usb_state != PM_SUSPEND) { + printk(KERN_ERR "glte: usb resume - invalid state\n"); + return -1; + } + + mux_dev->usb_state = PM_NORMAL; + + for (i = 0; i < MAX_ISSUE_NUM; i++) + gdm_mux_recv(mux_dev, mux_dev->rx_cb); + + return 0; +} + +static struct usb_driver gdm_mux_driver = { + .name = "gdm_mux", + .probe = gdm_mux_probe, + .disconnect = gdm_mux_disconnect, + .id_table = id_table, + .supports_autosuspend = 1, + .suspend = gdm_mux_suspend, + .resume = gdm_mux_resume, + .reset_resume = gdm_mux_resume, +}; + +static int __init gdm_usb_mux_init(void) +{ + + mux_rx_wq = create_workqueue("mux_rx_wq"); + if (mux_rx_wq == NULL) { + printk(KERN_ERR "glte: work queue create fail"); + return -1; + } + + register_lte_tty_driver(); + + return usb_register(&gdm_mux_driver); +} + +static void __exit gdm_usb_mux_exit(void) +{ + unregister_lte_tty_driver(); + + if (mux_rx_wq) { + flush_workqueue(mux_rx_wq); + destroy_workqueue(mux_rx_wq); + } + + usb_deregister(&gdm_mux_driver); +} + +module_init(gdm_usb_mux_init); +module_exit(gdm_usb_mux_exit); + +MODULE_DESCRIPTION("GCT LTE TTY Device Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/gdm724x/gdm_mux.h b/drivers/staging/gdm724x/gdm_mux.h new file mode 100644 index 000000000000..e8cfa8d401e3 --- /dev/null +++ b/drivers/staging/gdm724x/gdm_mux.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +#ifndef _GDM_MUX_H_ +#define _GDM_MUX_H_ + +#include +#include +#include + +#define PM_NORMAL 0 +#define PM_SUSPEND 1 + +#define USB_RT_ACM (USB_TYPE_CLASS | USB_RECIP_INTERFACE) + +#define START_FLAG 0xA512485A +#define MUX_HEADER_SIZE 14 +#define MUX_TX_MAX_SIZE (1024*10) +#define MUX_RX_MAX_SIZE (1024*30) +#define AT_PKT_TYPE 0xF011 +#define DM_PKT_TYPE 0xF010 + +#define RETRY_TIMER 30 /* msec */ + +struct mux_pkt_header { + unsigned int start_flag; + unsigned int seq_num; + unsigned int payload_size; + unsigned short packet_type; + unsigned char data[0]; +}; + +struct mux_tx { + struct urb *urb; + u8 *buf; + int len; + void (*callback)(void *cb_data); + void *cb_data; +}; + +struct mux_rx { + struct list_head free_list; + struct list_head rx_submit_list; + struct list_head to_host_list; + struct urb *urb; + u8 *buf; + void *mux_dev; + u32 offset; + u32 len; + int (*callback)(void *data, int len, int tty_index, int minor, int complete); +}; + +struct rx_cxt { + struct list_head to_host_list; + struct list_head rx_submit_list; + struct list_head rx_free_list; + spinlock_t to_host_lock; + spinlock_t submit_list_lock; + spinlock_t free_list_lock; +}; + +struct mux_dev { + struct usb_device *usbdev; + struct usb_interface *control_intf; + struct usb_interface *data_intf; + struct rx_cxt rx; + struct delayed_work work_rx; + struct usb_interface *intf; + int usb_state; + int (*rx_cb)(void *data, int len, int tty_index, int minor, int complete); + spinlock_t write_lock; + u8 minor[2]; +}; + +#endif /* _GDM_MUX_H_ */ diff --git a/drivers/staging/gdm724x/gdm_tty.c b/drivers/staging/gdm724x/gdm_tty.c new file mode 100644 index 000000000000..4d4040e3b101 --- /dev/null +++ b/drivers/staging/gdm724x/gdm_tty.c @@ -0,0 +1,367 @@ +/* + * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "gdm_tty.h" + +#define GDM_TTY_MAJOR 0 +#define GDM_TTY_MINOR 32 + +#define ACM_CTRL_DTR 0x01 +#define ACM_CTRL_RTS 0x02 +#define ACM_CTRL_DSR 0x02 +#define ACM_CTRL_RI 0x08 +#define ACM_CTRL_DCD 0x01 + +#define WRITE_SIZE 2048 + +#define MUX_TX_MAX_SIZE 2048 + +#define gdm_tty_send(n, d, l, i, c, b) (\ + n->tty_dev->send_func(n->tty_dev->priv_dev, d, l, i, c, b)) +#define gdm_tty_recv(n, c) (\ + n->tty_dev->recv_func(n->tty_dev->priv_dev, c)) +#define gdm_tty_send_control(n, r, v, d, l) (\ + n->tty_dev->send_control(n->tty_dev->priv_dev, r, v, d, l)) + +#define acm_set_comm_feature(n, v) \ + gdm_tty_send_control(n, 0x02, v, NULL, 0) + +#define GDM_TTY_READY(tty_str) (tty_str && tty_str->tty_dev && tty_str->port.count) + +struct tty_driver *g_tty_drv[TTY_MAX_COUNT] = {NULL, }; +struct tty_str *g_tty_str[TTY_MAX_COUNT][GDM_TTY_MINOR] = {{NULL, }, }; + +static char *DRIVER_STRING[TTY_MAX_COUNT] = {"GCTATC", "GCTDM"}; +static char *DEVICE_STRING[TTY_MAX_COUNT] = {"GCT-ATC", "GCT-DM"}; + +static DEFINE_MUTEX(open_mutex); + +static struct tty_port_operations gdm_tty_port_ops = { +}; + +static int gdm_tty_open(struct tty_struct *tty, struct file *filp) +{ + struct tty_str *tty_str = NULL; + int i; + int ret = 0; + + mutex_lock(&open_mutex); + + for (i = 0; i < TTY_MAX_COUNT; i++) { + if (!strcmp(tty->driver->driver_name, DRIVER_STRING[i])) { + tty_str = g_tty_str[i][tty->index]; + break; + } + } + + if (!tty_str) { + printk(KERN_INFO "glte: no tty device\n"); + mutex_unlock(&open_mutex); + return -ENODEV; + } + + set_bit(TTY_NO_WRITE_SPLIT, &tty->flags); + + tty->driver_data = tty_str; + tty_port_tty_set(&tty_str->port, tty); + tty_str->port.count++; + set_bit(ASYNCB_INITIALIZED, &tty_str->port.flags); + ret = tty_port_block_til_ready(&tty_str->port, tty, filp); + + mutex_unlock(&open_mutex); + + return ret; +} + +static void gdm_tty_close(struct tty_struct *tty, struct file *filp) +{ + struct tty_str *tty_str = tty->driver_data; + int i; + + if (!tty_str) { + printk(KERN_INFO "glte: tty device already close\n"); + return; + } + + if (tty_str->port.count != 0) { + tty_port_close_start(&tty_str->port, tty, filp); + tty_port_close_end(&tty_str->port, tty); + + if (tty_str->port.count == 0) + tty_port_tty_set(&tty_str->port, NULL); + tty_str->port.tty = NULL; + } + + if (!tty_str->tty_dev) { + for (i = 0; i < TTY_MAX_COUNT; i++) { + if (!strcmp(tty->driver->driver_name, DRIVER_STRING[i])) + break; + } + + if (i < TTY_MAX_COUNT) { + tty_unregister_device(g_tty_drv[i], tty->index); + tty_port_tty_set(&tty_str->port, NULL); + kfree(tty_str); + g_tty_str[i][tty->index] = NULL; + } + } +} + +static int gdm_tty_recv_complete(void *data, int len, int index, int minor, int complete) +{ + struct tty_str *tty_str = g_tty_str[index][minor]; + struct tty_struct *tty; + + if (!GDM_TTY_READY(tty_str)) { + if (complete == RECV_PACKET_PROCESS_COMPLETE) + gdm_tty_recv(tty_str, gdm_tty_recv_complete); + return TO_HOST_PORT_CLOSE; + } + + if (!data || !len) + goto complete_routine; + + tty = tty_port_tty_get(&tty_str->port); + + if (tty_buffer_request_room(tty, len) == len) { + tty_insert_flip_string(tty, data, len); + tty_flip_buffer_push(tty); + } else { + tty_kref_put(tty); + return TO_HOST_BUFFER_REQUEST_FAIL; + } + + tty_kref_put(tty); +complete_routine: + if (complete == RECV_PACKET_PROCESS_COMPLETE) + gdm_tty_recv(tty_str, gdm_tty_recv_complete); + + return TO_HOST_SUCCESS; +} + +static void gdm_tty_send_complete(void *arg) +{ + struct tty_str *tty_str = (struct tty_str *)arg; + struct tty_struct *tty; + + if (!GDM_TTY_READY(tty_str)) + return; + + tty = tty_port_tty_get(&tty_str->port); + tty_wakeup(tty); + tty_kref_put(tty); +} + +static int gdm_tty_write(struct tty_struct *tty, const unsigned char *buf, int len) +{ + struct tty_str *tty_str = tty->driver_data; + int remain = len; + int sent_len = 0; + int sending_len = 0; + + if (!GDM_TTY_READY(tty_str)) + return -ENODEV; + + if (!len) + return 0; + + while (1) { + sending_len = remain > MUX_TX_MAX_SIZE ? MUX_TX_MAX_SIZE : remain; + gdm_tty_send(tty_str, + (void *)(buf+sent_len), + sending_len, + tty_str->tty_drv_index, + gdm_tty_send_complete, + tty_str + ); + sent_len += sending_len; + remain -= sending_len; + if (remain <= 0) + break; + } + + return len; +} + +static int gdm_tty_write_room(struct tty_struct *tty) +{ + struct tty_str *tty_str = tty->driver_data; + + if (!GDM_TTY_READY(tty_str)) + return -ENODEV; + + return WRITE_SIZE; +} + +static int gdm_tty_tiocmget(struct tty_struct *tty) +{ + struct tty_str *tty_str = tty->driver_data; + + if (!GDM_TTY_READY(tty_str)) + return -ENODEV; + + return (0 & ACM_CTRL_DTR ? TIOCM_DTR : 0) | + (0 & ACM_CTRL_RTS ? TIOCM_RTS : 0) | + (0 & ACM_CTRL_DSR ? TIOCM_DSR : 0) | + (0 & ACM_CTRL_RI ? TIOCM_RI : 0) | + (0 & ACM_CTRL_DCD ? TIOCM_CD : 0) | + TIOCM_CTS; +} + +static int gdm_tty_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) +{ + struct tty_str *tty_str = tty->driver_data; + + if (!GDM_TTY_READY(tty_str)) + return -ENODEV; + + return 1; +} + +int register_lte_tty_device(struct tty_dev *tty_dev, struct device *dev) +{ + struct tty_str *tty_str; + int i, j; + + for (i = 0; i < TTY_MAX_COUNT; i++) { + for (j = 0; j < GDM_TTY_MINOR; j++) { + if (!g_tty_str[i][j]) + break; + } + + if (j == GDM_TTY_MINOR) { + tty_dev->minor[i] = j; + return -1; + } + + tty_str = kmalloc(sizeof(struct tty_str), GFP_KERNEL); + if (!tty_str) + return -ENOMEM; + + g_tty_str[i][j] = tty_str; + + tty_str->tty_dev = tty_dev; + tty_str->tty_drv_index = i; + tty_dev->minor[i] = j; + tty_port_init(&tty_str->port); + tty_str->port.ops = &gdm_tty_port_ops; + + if (strcmp(DEVICE_STRING[i], "GCT-ATC") != 0) + dev = NULL; + tty_register_device(g_tty_drv[i], j, dev); + } + + acm_set_comm_feature(tty_str, 1); + + for (i = 0; i < MAX_ISSUE_NUM; i++) + gdm_tty_recv(tty_str, gdm_tty_recv_complete); + + return 0; +} + +void unregister_lte_tty_device(struct tty_dev *tty_dev) +{ + struct tty_str *tty_str; + int i; + + for (i = 0; i < TTY_MAX_COUNT; i++) { + if (tty_dev->minor[i] >= GDM_TTY_MINOR) + continue; + + tty_str = g_tty_str[i][tty_dev->minor[i]]; + if (!tty_str) + continue; + + tty_str->tty_dev = NULL; + + if (!tty_str->port.count) { + tty_unregister_device(g_tty_drv[i], tty_dev->minor[i]); + tty_port_tty_set(&tty_str->port, NULL); + kfree(tty_str); + g_tty_str[i][tty_dev->minor[i]] = NULL; + } + } +} + +static void gdm_tty_set_termios(struct tty_struct *tty, struct ktermios *termios_old) +{ + return; +} + +static const struct tty_operations gdm_tty_ops = { + .open = gdm_tty_open, + .close = gdm_tty_close, + .write = gdm_tty_write, + .write_room = gdm_tty_write_room, + .tiocmget = gdm_tty_tiocmget, + .tiocmset = gdm_tty_tiocmset, + .set_termios = gdm_tty_set_termios, +}; + +int register_lte_tty_driver(void) +{ + struct tty_driver *tty_driver = NULL; + int i; + int ret; + + for (i = 0; i < TTY_MAX_COUNT; i++) { + tty_driver = alloc_tty_driver(GDM_TTY_MINOR); + if (!tty_driver) { + printk(KERN_ERR "glte: alloc_tty_driver fail\n"); + return -ENOMEM; + } + + tty_driver->owner = THIS_MODULE; + tty_driver->driver_name = DRIVER_STRING[i]; + tty_driver->name = DEVICE_STRING[i]; + tty_driver->major = GDM_TTY_MAJOR; + tty_driver->type = TTY_DRIVER_TYPE_SERIAL; + tty_driver->subtype = SERIAL_TYPE_NORMAL; + tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; + tty_driver->init_termios = tty_std_termios; + tty_driver->init_termios.c_cflag = B9600 | CS8 | HUPCL | CLOCAL; + tty_driver->init_termios.c_lflag = ISIG | ICANON | IEXTEN; + tty_set_operations(tty_driver, &gdm_tty_ops); + + ret = tty_register_driver(tty_driver); + + g_tty_drv[i] = tty_driver; + } + + return ret; +} + +void unregister_lte_tty_driver(void) +{ + struct tty_driver *tty_driver; + int i; + + for (i = 0; i < TTY_MAX_COUNT; i++) { + tty_driver = g_tty_drv[i]; + if (tty_driver) { + tty_unregister_driver(tty_driver); + put_tty_driver(tty_driver); + } + } +} diff --git a/drivers/staging/gdm724x/gdm_tty.h b/drivers/staging/gdm724x/gdm_tty.h new file mode 100644 index 000000000000..bfe654eb378b --- /dev/null +++ b/drivers/staging/gdm724x/gdm_tty.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +#ifndef _GDM_TTY_H_ +#define _GDM_TTY_H_ + +#include +#include +#include + + +#define TTY_MAX_COUNT 2 + +#define MAX_ISSUE_NUM 3 + +enum TO_HOST_RESULT { + TO_HOST_SUCCESS = 0, + TO_HOST_BUFFER_REQUEST_FAIL = 1, + TO_HOST_PORT_CLOSE = 2, + TO_HOST_INVALID_PACKET = 3, +}; + +enum RECV_PACKET_PROCESS { + RECV_PACKET_PROCESS_COMPLETE = 0, + RECV_PACKET_PROCESS_CONTINUE = 1, +}; + +struct tty_dev { + void *priv_dev; + int (*send_func)(void *priv_dev, void *data, int len, int tty_index, + void (*cb)(void *cb_data), void *cb_data); + int (*recv_func)(void *priv_dev, int (*cb)(void *data, int len, int tty_index, int minor, int complete)); + int (*send_control)(void *priv_dev, int request, int value, void *data, int len); + u8 minor[2]; +}; + +struct tty_str { + struct tty_dev *tty_dev; + int tty_drv_index; + struct tty_port port; +}; + +int register_lte_tty_driver(void); +void unregister_lte_tty_driver(void); +int register_lte_tty_device(struct tty_dev *tty_dev, struct device *dev); +void unregister_lte_tty_device(struct tty_dev *tty_dev); + +#endif /* _GDM_USB_H_ */ + diff --git a/drivers/staging/gdm724x/gdm_usb.c b/drivers/staging/gdm724x/gdm_usb.c new file mode 100644 index 000000000000..40d362e5b959 --- /dev/null +++ b/drivers/staging/gdm724x/gdm_usb.c @@ -0,0 +1,1047 @@ +/* + * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gdm_usb.h" +#include "gdm_lte.h" +#include "hci.h" +#include "hci_packet.h" +#include "gdm_endian.h" + +#define USB_DEVICE_CDC_DATA(vid, pid) \ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS,\ + .idVendor = vid,\ + .idProduct = pid,\ + .bInterfaceClass = USB_CLASS_COMM,\ + .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET + +#define USB_DEVICE_MASS_DATA(vid, pid) \ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO,\ + .idVendor = vid,\ + .idProduct = pid,\ + .bInterfaceSubClass = USB_SC_SCSI, \ + .bInterfaceClass = USB_CLASS_MASS_STORAGE,\ + .bInterfaceProtocol = USB_PR_BULK + +static const struct usb_device_id id_table[] = { + { USB_DEVICE_CDC_DATA(VID_GCT, PID_GDM7240) }, /* GCT GDM7240 */ + { USB_DEVICE_CDC_DATA(VID_GCT, PID_GDM7243) }, /* GCT GDM7243 */ + { } +}; + +MODULE_DEVICE_TABLE(usb, id_table); + +static struct workqueue_struct *usb_tx_wq; +static struct workqueue_struct *usb_rx_wq; + +static void do_tx(struct work_struct *work); +static void do_rx(struct work_struct *work); + +static int gdm_usb_recv(void *priv_dev, + int (*cb)(void *cb_data, void *data, int len, int context), + void *cb_data, + int context); + +static int request_mac_address(struct lte_udev *udev) +{ + u8 buf[16] = {0,}; + struct hci_packet *hci = (struct hci_packet *)buf; + struct usb_device *usbdev = udev->usbdev; + int actual; + int ret = -1; + + hci->cmd_evt = gdm_cpu_to_dev16(&udev->gdm_ed, LTE_GET_INFORMATION); + hci->len = gdm_cpu_to_dev16(&udev->gdm_ed, 1); + hci->data[0] = MAC_ADDRESS; + + ret = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 2), buf, 5, + &actual, 1000); + + udev->request_mac_addr = 1; + + return ret; +} + +static struct usb_tx *alloc_tx_struct(int len) +{ + struct usb_tx *t = NULL; + int ret = 0; + + t = kmalloc(sizeof(struct usb_tx), GFP_ATOMIC); + if (!t) { + ret = -ENOMEM; + goto out; + } + memset(t, 0, sizeof(struct usb_tx)); + + t->urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!(len % 512)) + len++; + + t->buf = kmalloc(len, GFP_ATOMIC); + if (!t->urb || !t->buf) { + ret = -ENOMEM; + goto out; + } + +out: + if (ret < 0) { + if (t) { + usb_free_urb(t->urb); + kfree(t->buf); + kfree(t); + } + return NULL; + } + + return t; +} + +static struct usb_tx_sdu *alloc_tx_sdu_struct(void) +{ + struct usb_tx_sdu *t_sdu = NULL; + int ret = 0; + + + t_sdu = kmalloc(sizeof(struct usb_tx_sdu), GFP_ATOMIC); + if (!t_sdu) { + ret = -ENOMEM; + goto out; + } + memset(t_sdu, 0, sizeof(struct usb_tx_sdu)); + + t_sdu->buf = kmalloc(SDU_BUF_SIZE, GFP_ATOMIC); + if (!t_sdu->buf) { + ret = -ENOMEM; + goto out; + } +out: + + if (ret < 0) { + if (t_sdu) { + kfree(t_sdu->buf); + kfree(t_sdu); + } + return NULL; + } + + return t_sdu; +} + +static void free_tx_struct(struct usb_tx *t) +{ + if (t) { + usb_free_urb(t->urb); + kfree(t->buf); + kfree(t); + } +} + +static void free_tx_sdu_struct(struct usb_tx_sdu *t_sdu) +{ + if (t_sdu) { + kfree(t_sdu->buf); + kfree(t_sdu); + } +} + +static struct usb_tx_sdu *get_tx_sdu_struct(struct tx_cxt *tx, int *no_spc) +{ + struct usb_tx_sdu *t_sdu; + + if (list_empty(&tx->free_list)) + return NULL; + + t_sdu = list_entry(tx->free_list.next, struct usb_tx_sdu, list); + list_del(&t_sdu->list); + + tx->avail_count--; + + *no_spc = list_empty(&tx->free_list) ? 1 : 0; + + return t_sdu; +} + +static void put_tx_struct(struct tx_cxt *tx, struct usb_tx_sdu *t_sdu) +{ + list_add_tail(&t_sdu->list, &tx->free_list); + tx->avail_count++; +} + +static struct usb_rx *alloc_rx_struct(void) +{ + struct usb_rx *r = NULL; + int ret = 0; + + r = kmalloc(sizeof(struct usb_rx), GFP_ATOMIC); + if (!r) { + ret = -ENOMEM; + goto out; + } + + r->urb = usb_alloc_urb(0, GFP_ATOMIC); + r->buf = kmalloc(RX_BUF_SIZE, GFP_ATOMIC); + if (!r->urb || !r->buf) { + ret = -ENOMEM; + goto out; + } +out: + + if (ret < 0) { + if (r) { + usb_free_urb(r->urb); + kfree(r->buf); + kfree(r); + } + return NULL; + } + + return r; +} + +static void free_rx_struct(struct usb_rx *r) +{ + if (r) { + usb_free_urb(r->urb); + kfree(r->buf); + kfree(r); + } +} + +static struct usb_rx *get_rx_struct(struct rx_cxt *rx, int *no_spc) +{ + struct usb_rx *r; + unsigned long flags; + + spin_lock_irqsave(&rx->rx_lock, flags); + + if (list_empty(&rx->free_list)) { + spin_unlock_irqrestore(&rx->rx_lock, flags); + return NULL; + } + + r = list_entry(rx->free_list.next, struct usb_rx, free_list); + list_del(&r->free_list); + + rx->avail_count--; + + *no_spc = list_empty(&rx->free_list) ? 1 : 0; + + spin_unlock_irqrestore(&rx->rx_lock, flags); + + return r; +} + +static void put_rx_struct(struct rx_cxt *rx, struct usb_rx *r) +{ + unsigned long flags; + + spin_lock_irqsave(&rx->rx_lock, flags); + + list_add_tail(&r->free_list, &rx->free_list); + rx->avail_count++; + + spin_unlock_irqrestore(&rx->rx_lock, flags); +} + +static void release_usb(struct lte_udev *udev) +{ + struct rx_cxt *rx = &udev->rx; + struct tx_cxt *tx = &udev->tx; + struct usb_tx *t, *t_next; + struct usb_rx *r, *r_next; + struct usb_tx_sdu *t_sdu, *t_sdu_next; + unsigned long flags; + + spin_lock_irqsave(&tx->lock, flags); + list_for_each_entry_safe(t_sdu, t_sdu_next, &tx->sdu_list, list) + { + list_del(&t_sdu->list); + free_tx_sdu_struct(t_sdu); + } + + list_for_each_entry_safe(t, t_next, &tx->hci_list, list) + { + list_del(&t->list); + free_tx_struct(t); + } + + list_for_each_entry_safe(t_sdu, t_sdu_next, &tx->free_list, list) + { + list_del(&t_sdu->list); + free_tx_sdu_struct(t_sdu); + } + spin_unlock_irqrestore(&tx->lock, flags); + + spin_lock_irqsave(&rx->submit_lock, flags); + list_for_each_entry_safe(r, r_next, &rx->rx_submit_list, rx_submit_list) + { + spin_unlock_irqrestore(&rx->submit_lock, flags); + usb_kill_urb(r->urb); + spin_lock_irqsave(&rx->submit_lock, flags); + } + spin_unlock_irqrestore(&rx->submit_lock, flags); + + spin_lock_irqsave(&rx->rx_lock, flags); + list_for_each_entry_safe(r, r_next, &rx->free_list, free_list) + { + list_del(&r->free_list); + free_rx_struct(r); + } + spin_unlock_irqrestore(&rx->rx_lock, flags); + + spin_lock_irqsave(&rx->to_host_lock, flags); + list_for_each_entry_safe(r, r_next, &rx->to_host_list, to_host_list) + { + if (r->index == (void *)udev) { + list_del(&r->to_host_list); + free_rx_struct(r); + } + } + spin_unlock_irqrestore(&rx->to_host_lock, flags); +} + +static int init_usb(struct lte_udev *udev) +{ + int ret = 0; + int i; + struct tx_cxt *tx = &udev->tx; + struct rx_cxt *rx = &udev->rx; + struct usb_tx_sdu *t_sdu = NULL; + struct usb_rx *r = NULL; + + udev->send_complete = 1; + udev->tx_stop = 0; + udev->request_mac_addr = 0; + udev->usb_state = PM_NORMAL; + + INIT_LIST_HEAD(&tx->sdu_list); + INIT_LIST_HEAD(&tx->hci_list); + INIT_LIST_HEAD(&tx->free_list); + INIT_LIST_HEAD(&rx->rx_submit_list); + INIT_LIST_HEAD(&rx->free_list); + INIT_LIST_HEAD(&rx->to_host_list); + spin_lock_init(&tx->lock); + spin_lock_init(&rx->rx_lock); + spin_lock_init(&rx->submit_lock); + spin_lock_init(&rx->to_host_lock); + + tx->avail_count = 0; + rx->avail_count = 0; + + udev->rx_cb = NULL; + + for (i = 0; i < MAX_NUM_SDU_BUF; i++) { + t_sdu = alloc_tx_sdu_struct(); + if (t_sdu == NULL) { + ret = -ENOMEM; + goto fail; + } + + list_add(&t_sdu->list, &tx->free_list); + tx->avail_count++; + } + + for (i = 0; i < MAX_RX_SUBMIT_COUNT*2; i++) { + r = alloc_rx_struct(); + if (r == NULL) { + ret = -ENOMEM; + goto fail; + } + + list_add(&r->free_list, &rx->free_list); + rx->avail_count++; + } + INIT_DELAYED_WORK(&udev->work_tx, do_tx); + INIT_DELAYED_WORK(&udev->work_rx, do_rx); + return 0; +fail: + return ret; +} + +static int set_mac_address(u8 *data, void *arg) +{ + struct phy_dev *phy_dev = (struct phy_dev *)arg; + struct lte_udev *udev = phy_dev->priv_dev; + struct tlv *tlv = (struct tlv *)data; + u8 mac_address[ETH_ALEN] = {0, }; + + if (tlv->type == MAC_ADDRESS && udev->request_mac_addr) { + memcpy(mac_address, tlv->data, tlv->len); + + if (register_lte_device(phy_dev, &udev->intf->dev, mac_address) < 0) + printk(KERN_ERR "glte: register lte device failed\n"); + + udev->request_mac_addr = 0; + + return 1; + } + + return 0; +} + +static void do_rx(struct work_struct *work) +{ + struct lte_udev *udev = container_of(work, struct lte_udev, work_rx.work); + struct rx_cxt *rx = &udev->rx; + struct usb_rx *r; + struct hci_packet *hci; + struct phy_dev *phy_dev; + u16 cmd_evt; + int ret; + unsigned long flags; + + while (1) { + spin_lock_irqsave(&rx->to_host_lock, flags); + if (list_empty(&rx->to_host_list)) { + spin_unlock_irqrestore(&rx->to_host_lock, flags); + break; + } + r = list_entry(rx->to_host_list.next, struct usb_rx, to_host_list); + list_del(&r->to_host_list); + spin_unlock_irqrestore(&rx->to_host_lock, flags); + + phy_dev = (struct phy_dev *)r->cb_data; + udev = (struct lte_udev *)phy_dev->priv_dev; + hci = (struct hci_packet *)r->buf; + cmd_evt = gdm_dev16_to_cpu(&udev->gdm_ed, hci->cmd_evt); + + switch (cmd_evt) { + case LTE_GET_INFORMATION_RESULT: + if (set_mac_address(hci->data, r->cb_data) == 0) { + ret = r->callback(r->cb_data, + r->buf, + r->urb->actual_length, + KERNEL_THREAD); + } + break; + + default: + if (r->callback) { + ret = r->callback(r->cb_data, + r->buf, + r->urb->actual_length, + KERNEL_THREAD); + + if (ret == -EAGAIN) + printk(KERN_ERR "glte: failed to send received data\n"); + } + break; + } + + put_rx_struct(rx, r); + + gdm_usb_recv(udev, + r->callback, + r->cb_data, + USB_COMPLETE); + } +} + +static void remove_rx_submit_list(struct usb_rx *r, struct rx_cxt *rx) +{ + unsigned long flags; + struct usb_rx *r_remove, *r_remove_next; + + spin_lock_irqsave(&rx->submit_lock, flags); + list_for_each_entry_safe(r_remove, r_remove_next, &rx->rx_submit_list, rx_submit_list) + { + if (r == r_remove) { + list_del(&r->rx_submit_list); + break; + } + } + spin_unlock_irqrestore(&rx->submit_lock, flags); +} + +static void gdm_usb_rcv_complete(struct urb *urb) +{ + struct usb_rx *r = urb->context; + struct rx_cxt *rx = r->rx; + unsigned long flags; + struct lte_udev *udev = container_of(r->rx, struct lte_udev, rx); + struct usb_device *usbdev = udev->usbdev; + + remove_rx_submit_list(r, rx); + + if (!urb->status && r->callback) { + spin_lock_irqsave(&rx->to_host_lock, flags); + list_add_tail(&r->to_host_list, &rx->to_host_list); + queue_work(usb_rx_wq, &udev->work_rx.work); + spin_unlock_irqrestore(&rx->to_host_lock, flags); + } else { + if (urb->status && udev->usb_state == PM_NORMAL) + printk(KERN_ERR "glte: gdm_usb_rcv_complete urb status error %d\n", urb->status); + + put_rx_struct(rx, r); + } + + usb_mark_last_busy(usbdev); +} + +static int gdm_usb_recv(void *priv_dev, + int (*cb)(void *cb_data, void *data, int len, int context), + void *cb_data, + int context) +{ + struct lte_udev *udev = priv_dev; + struct usb_device *usbdev = udev->usbdev; + struct rx_cxt *rx = &udev->rx; + struct usb_rx *r; + int no_spc; + int ret; + unsigned long flags; + + if (!udev->usbdev) { + printk(KERN_ERR "glte: invalid device\n"); + return -ENODEV; + } + + r = get_rx_struct(rx, &no_spc); + if (!r) { + printk(KERN_ERR "glte: Out of Memory\n"); + return -ENOMEM; + } + + udev->rx_cb = cb; + r->callback = cb; + r->cb_data = cb_data; + r->index = (void *)udev; + r->rx = rx; + + usb_fill_bulk_urb(r->urb, + usbdev, + usb_rcvbulkpipe(usbdev, 0x83), + r->buf, + RX_BUF_SIZE, + gdm_usb_rcv_complete, + r); + + spin_lock_irqsave(&rx->submit_lock, flags); + list_add_tail(&r->rx_submit_list, &rx->rx_submit_list); + spin_unlock_irqrestore(&rx->submit_lock, flags); + + if (context == KERNEL_THREAD) + ret = usb_submit_urb(r->urb, GFP_KERNEL); + else + ret = usb_submit_urb(r->urb, GFP_ATOMIC); + + if (ret) { + spin_lock_irqsave(&rx->submit_lock, flags); + list_del(&r->rx_submit_list); + spin_unlock_irqrestore(&rx->submit_lock, flags); + + printk(KERN_ERR "glte: usb_submit_urb fail (%p)\n", r); + put_rx_struct(rx, r); + } + + return ret; +} + +static void gdm_usb_send_complete(struct urb *urb) +{ + struct usb_tx *t = urb->context; + struct tx_cxt *tx = t->tx; + struct lte_udev *udev = container_of(tx, struct lte_udev, tx); + unsigned long flags; + + if (urb->status == -ECONNRESET) { + printk(KERN_INFO "glte: CONNRESET\n"); + return; + } + + if (t->callback) + t->callback(t->cb_data); + + free_tx_struct(t); + + spin_lock_irqsave(&tx->lock, flags); + udev->send_complete = 1; + queue_work(usb_tx_wq, &udev->work_tx.work); + spin_unlock_irqrestore(&tx->lock, flags); +} + +static int send_tx_packet(struct usb_device *usbdev, struct usb_tx *t, u32 len) +{ + int ret = 0; + + if (!(len%512)) + len++; + + usb_fill_bulk_urb(t->urb, + usbdev, + usb_sndbulkpipe(usbdev, 2), + t->buf, + len, + gdm_usb_send_complete, + t); + + ret = usb_submit_urb(t->urb, GFP_ATOMIC); + + if (ret) + printk(KERN_ERR "glte: usb_submit_urb fail %d\n", ret); + + usb_mark_last_busy(usbdev); + + return ret; +} + +static u32 packet_aggregation(struct lte_udev *udev, u8 *send_buf) +{ + struct tx_cxt *tx = &udev->tx; + struct usb_tx_sdu *t_sdu = NULL; + struct multi_sdu *multi_sdu = (struct multi_sdu *)send_buf; + u16 send_len = 0; + u16 num_packet = 0; + unsigned long flags; + + multi_sdu->cmd_evt = gdm_cpu_to_dev16(&udev->gdm_ed, LTE_TX_MULTI_SDU); + + while (num_packet < MAX_PACKET_IN_MULTI_SDU) { + spin_lock_irqsave(&tx->lock, flags); + if (list_empty(&tx->sdu_list)) { + spin_unlock_irqrestore(&tx->lock, flags); + break; + } + + t_sdu = list_entry(tx->sdu_list.next, struct usb_tx_sdu, list); + if (send_len + t_sdu->len > MAX_SDU_SIZE) { + spin_unlock_irqrestore(&tx->lock, flags); + break; + } + + list_del(&t_sdu->list); + spin_unlock_irqrestore(&tx->lock, flags); + + memcpy(multi_sdu->data + send_len, t_sdu->buf, t_sdu->len); + + send_len += (t_sdu->len + 3) & 0xfffc; + num_packet++; + + if (tx->avail_count > 10) + t_sdu->callback(t_sdu->cb_data); + + spin_lock_irqsave(&tx->lock, flags); + put_tx_struct(tx, t_sdu); + spin_unlock_irqrestore(&tx->lock, flags); + } + + multi_sdu->len = gdm_cpu_to_dev16(&udev->gdm_ed, send_len); + multi_sdu->num_packet = gdm_cpu_to_dev16(&udev->gdm_ed, num_packet); + + return send_len + offsetof(struct multi_sdu, data); +} + +static void do_tx(struct work_struct *work) +{ + struct lte_udev *udev = container_of(work, struct lte_udev, work_tx.work); + struct usb_device *usbdev = udev->usbdev; + struct tx_cxt *tx = &udev->tx; + struct usb_tx *t = NULL; + int is_send = 0; + u32 len = 0; + unsigned long flags; + + if (!usb_autopm_get_interface(udev->intf)) + usb_autopm_put_interface(udev->intf); + + if (udev->usb_state == PM_SUSPEND) + return; + + spin_lock_irqsave(&tx->lock, flags); + if (!udev->send_complete) { + spin_unlock_irqrestore(&tx->lock, flags); + return; + } else { + udev->send_complete = 0; + } + + if (!list_empty(&tx->hci_list)) { + t = list_entry(tx->hci_list.next, struct usb_tx, list); + list_del(&t->list); + len = t->len; + t->is_sdu = 0; + is_send = 1; + } else if (!list_empty(&tx->sdu_list)) { + if (udev->tx_stop) { + udev->send_complete = 1; + spin_unlock_irqrestore(&tx->lock, flags); + return; + } + + t = alloc_tx_struct(TX_BUF_SIZE); + t->callback = NULL; + t->tx = tx; + t->is_sdu = 1; + is_send = 1; + } + + if (!is_send) { + udev->send_complete = 1; + spin_unlock_irqrestore(&tx->lock, flags); + return; + } + spin_unlock_irqrestore(&tx->lock, flags); + + if (t->is_sdu) + len = packet_aggregation(udev, t->buf); + + if (send_tx_packet(usbdev, t, len)) { + printk(KERN_ERR "glte: send_tx_packet fail\n"); + t->callback = NULL; + gdm_usb_send_complete(t->urb); + } +} + +#define SDU_PARAM_LEN 12 +static int gdm_usb_sdu_send(void *priv_dev, void *data, int len, + unsigned int dftEpsId, unsigned int epsId, + void (*cb)(void *data), void *cb_data, + int dev_idx, int nic_type) +{ + struct lte_udev *udev = priv_dev; + struct tx_cxt *tx = &udev->tx; + struct usb_tx_sdu *t_sdu; + struct sdu *sdu = NULL; + unsigned long flags; + int no_spc = 0; + u16 send_len; + + if (!udev->usbdev) { + printk(KERN_ERR "glte: sdu send - invalid device\n"); + return TX_NO_DEV; + } + + spin_lock_irqsave(&tx->lock, flags); + t_sdu = get_tx_sdu_struct(tx, &no_spc); + spin_unlock_irqrestore(&tx->lock, flags); + + if (t_sdu == NULL) { + printk(KERN_ERR "glte: sdu send - free list empty\n"); + return TX_NO_SPC; + } + + sdu = (struct sdu *)t_sdu->buf; + sdu->cmd_evt = gdm_cpu_to_dev16(&udev->gdm_ed, LTE_TX_SDU); + if (nic_type == NIC_TYPE_ARP) { + send_len = len + SDU_PARAM_LEN; + memcpy(sdu->data, data, len); + } else { + send_len = len - ETH_HLEN; + send_len += SDU_PARAM_LEN; + memcpy(sdu->data, data+ETH_HLEN, len-ETH_HLEN); + } + + sdu->len = gdm_cpu_to_dev16(&udev->gdm_ed, send_len); + sdu->dftEpsId = gdm_cpu_to_dev32(&udev->gdm_ed, dftEpsId); + sdu->bearer_ID = gdm_cpu_to_dev32(&udev->gdm_ed, epsId); + sdu->nic_type = gdm_cpu_to_dev32(&udev->gdm_ed, nic_type); + + t_sdu->len = send_len + HCI_HEADER_SIZE; + t_sdu->callback = cb; + t_sdu->cb_data = cb_data; + + spin_lock_irqsave(&tx->lock, flags); + list_add_tail(&t_sdu->list, &tx->sdu_list); + queue_work(usb_tx_wq, &udev->work_tx.work); + spin_unlock_irqrestore(&tx->lock, flags); + + if (no_spc) + return TX_NO_BUFFER; + + return 0; +} + +static int gdm_usb_hci_send(void *priv_dev, void *data, int len, + void (*cb)(void *data), void *cb_data) +{ + struct lte_udev *udev = priv_dev; + struct tx_cxt *tx = &udev->tx; + struct usb_tx *t; + unsigned long flags; + + if (!udev->usbdev) { + printk(KERN_ERR "glte: hci send - invalid device\n"); + return -ENODEV; + } + + t = alloc_tx_struct(len); + if (t == NULL) { + printk(KERN_ERR "glte: hci_send - out of memory\n"); + return -ENOMEM; + } + + memcpy(t->buf, data, len); + t->callback = cb; + t->cb_data = cb_data; + t->len = len; + t->tx = tx; + t->is_sdu = 0; + + spin_lock_irqsave(&tx->lock, flags); + list_add_tail(&t->list, &tx->hci_list); + queue_work(usb_tx_wq, &udev->work_tx.work); + spin_unlock_irqrestore(&tx->lock, flags); + + return 0; +} + +static struct gdm_endian *gdm_usb_get_endian(void *priv_dev) +{ + struct lte_udev *udev = priv_dev; + + return &udev->gdm_ed; +} + +static int gdm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) +{ + int ret = 0; + struct phy_dev *phy_dev = NULL; + struct lte_udev *udev = NULL; + u16 idVendor, idProduct; + int bInterfaceNumber; + struct usb_device *usbdev = interface_to_usbdev(intf); + + bInterfaceNumber = intf->cur_altsetting->desc.bInterfaceNumber; + idVendor = __le16_to_cpu(usbdev->descriptor.idVendor); + idProduct = __le16_to_cpu(usbdev->descriptor.idProduct); + + printk(KERN_INFO "glte: net vid = 0x%04x pid = 0x%04x\n", idVendor, idProduct); + + if (bInterfaceNumber > NETWORK_INTERFACE) { + printk(KERN_INFO "glte: not a network device"); + return -1; + } + + phy_dev = kmalloc(sizeof(struct phy_dev), GFP_ATOMIC); + if (!phy_dev) { + ret = -ENOMEM; + goto out; + } + + udev = kmalloc(sizeof(struct lte_udev), GFP_ATOMIC); + if (!udev) { + ret = -ENOMEM; + goto out; + } + + memset(phy_dev, 0, sizeof(struct phy_dev)); + memset(udev, 0, sizeof(struct lte_udev)); + + phy_dev->priv_dev = (void *)udev; + phy_dev->send_hci_func = gdm_usb_hci_send; + phy_dev->send_sdu_func = gdm_usb_sdu_send; + phy_dev->rcv_func = gdm_usb_recv; + phy_dev->get_endian = gdm_usb_get_endian; + + udev->usbdev = usbdev; + ret = init_usb(udev); + if (ret < 0) { + printk(KERN_ERR "glte: init_usb func fail\n"); + goto out; + } + udev->intf = intf; + + intf->needs_remote_wakeup = 1; + usb_enable_autosuspend(usbdev); + pm_runtime_set_autosuspend_delay(&usbdev->dev, AUTO_SUSPEND_TIMER); + + /* List up hosts with big endians, otherwise, defaults to little endian */ + if (idProduct == PID_GDM7243) + set_endian(&udev->gdm_ed, ENDIANNESS_BIG); + else + set_endian(&udev->gdm_ed, ENDIANNESS_LITTLE); + + ret = request_mac_address(udev); + if (ret < 0) { + printk(KERN_ERR "glte: request Mac address failed\n"); + goto out; + } + + start_rx_proc(phy_dev); +out: + + if (ret < 0) { + kfree(phy_dev); + if (udev) { + release_usb(udev); + kfree(udev); + } + } + + usb_get_dev(usbdev); + usb_set_intfdata(intf, phy_dev); + + return ret; +} + +static void gdm_usb_disconnect(struct usb_interface *intf) +{ + struct phy_dev *phy_dev; + struct lte_udev *udev; + u16 idVendor, idProduct; + struct usb_device *usbdev; + usbdev = interface_to_usbdev(intf); + + idVendor = __le16_to_cpu(usbdev->descriptor.idVendor); + idProduct = __le16_to_cpu(usbdev->descriptor.idProduct); + + phy_dev = usb_get_intfdata(intf); + + udev = phy_dev->priv_dev; + unregister_lte_device(phy_dev); + + release_usb(udev); + + kfree(udev); + udev = NULL; + + kfree(phy_dev); + phy_dev = NULL; + + usb_put_dev(usbdev); +} + +static int gdm_usb_suspend(struct usb_interface *intf, pm_message_t pm_msg) +{ + struct phy_dev *phy_dev; + struct lte_udev *udev; + struct rx_cxt *rx; + struct usb_rx *r; + struct usb_rx *r_next; + unsigned long flags; + + phy_dev = usb_get_intfdata(intf); + udev = phy_dev->priv_dev; + rx = &udev->rx; + if (udev->usb_state != PM_NORMAL) { + printk(KERN_ERR "glte: usb suspend - invalid state"); + return -1; + } + + udev->usb_state = PM_SUSPEND; + + spin_lock_irqsave(&rx->submit_lock, flags); + list_for_each_entry_safe(r, r_next, &rx->rx_submit_list, rx_submit_list) + { + spin_unlock_irqrestore(&rx->submit_lock, flags); + usb_kill_urb(r->urb); + spin_lock_irqsave(&rx->submit_lock, flags); + } + spin_unlock_irqrestore(&rx->submit_lock, flags); + + return 0; +} + +static int gdm_usb_resume(struct usb_interface *intf) +{ + struct phy_dev *phy_dev; + struct lte_udev *udev; + struct tx_cxt *tx; + struct rx_cxt *rx; + unsigned long flags; + int issue_count; + int i; + + phy_dev = usb_get_intfdata(intf); + udev = phy_dev->priv_dev; + rx = &udev->rx; + + if (udev->usb_state != PM_SUSPEND) { + printk(KERN_ERR "glte: usb resume - invalid state"); + return -1; + } + udev->usb_state = PM_NORMAL; + + spin_lock_irqsave(&rx->rx_lock, flags); + issue_count = rx->avail_count - MAX_RX_SUBMIT_COUNT; + spin_unlock_irqrestore(&rx->rx_lock, flags); + + if (issue_count >= 0) { + for (i = 0; i < issue_count; i++) + gdm_usb_recv(phy_dev->priv_dev, + udev->rx_cb, + phy_dev, + USB_COMPLETE); + } + + tx = &udev->tx; + spin_lock_irqsave(&tx->lock, flags); + queue_work(usb_tx_wq, &udev->work_tx.work); + spin_unlock_irqrestore(&tx->lock, flags); + + return 0; +} + +static struct usb_driver gdm_usb_lte_driver = { + .name = "gdm_lte", + .probe = gdm_usb_probe, + .disconnect = gdm_usb_disconnect, + .id_table = id_table, + .supports_autosuspend = 1, + .suspend = gdm_usb_suspend, + .resume = gdm_usb_resume, + .reset_resume = gdm_usb_resume, +}; + +static int __init gdm_usb_lte_init(void) +{ + if (gdm_lte_event_init() < 0) { + printk(KERN_ERR "glte: error creating event\n"); + return -1; + } + + usb_tx_wq = create_workqueue("usb_tx_wq"); + if (usb_tx_wq == NULL) + return -1; + + usb_rx_wq = create_workqueue("usb_rx_wq"); + if (usb_rx_wq == NULL) + return -1; + + return usb_register(&gdm_usb_lte_driver); +} + +static void __exit gdm_usb_lte_exit(void) +{ + gdm_lte_event_exit(); + + usb_deregister(&gdm_usb_lte_driver); + + if (usb_tx_wq) { + flush_workqueue(usb_tx_wq); + destroy_workqueue(usb_tx_wq); + } + + if (usb_rx_wq) { + flush_workqueue(usb_rx_wq); + destroy_workqueue(usb_rx_wq); + } +} + +module_init(gdm_usb_lte_init); +module_exit(gdm_usb_lte_exit); + +MODULE_VERSION(DRIVER_VERSION); +MODULE_DESCRIPTION("GCT LTE USB Device Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/gdm724x/gdm_usb.h b/drivers/staging/gdm724x/gdm_usb.h new file mode 100644 index 000000000000..38f6537dced0 --- /dev/null +++ b/drivers/staging/gdm724x/gdm_usb.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +#ifndef _GDM_USB_H_ +#define _GDM_USB_H_ + +#include +#include +#include +#include +#include + +#include "gdm_endian.h" +#include "hci_packet.h" + +#define PM_NORMAL 0 +#define PM_SUSPEND 1 +#define AUTO_SUSPEND_TIMER 5000 /* ms */ + +#define RX_BUF_SIZE (1024*32) +#define TX_BUF_SIZE (1024*32) +#define SDU_BUF_SIZE 2048 +#define MAX_SDU_SIZE (1024*30) +#define MAX_PACKET_IN_MULTI_SDU 256 + +#define VID_GCT 0x1076 +#define PID_GDM7240 0x8000 +#define PID_GDM7243 0x9000 + +#define NETWORK_INTERFACE 1 +#define USB_SC_SCSI 0x06 +#define USB_PR_BULK 0x50 + +#define MAX_NUM_SDU_BUF 64 + +struct usb_tx { + struct list_head list; + struct urb *urb; + u8 *buf; + u32 len; + void (*callback)(void *cb_data); + void *cb_data; + struct tx_cxt *tx; + u8 is_sdu; +}; + +struct usb_tx_sdu { + struct list_head list; + u8 *buf; + u32 len; + void (*callback)(void *cb_data); + void *cb_data; +}; + +struct usb_rx { + struct list_head to_host_list; + struct list_head free_list; + struct list_head rx_submit_list; + struct rx_cxt *rx; + struct urb *urb; + u8 *buf; + int (*callback)(void *cb_data, void *data, int len, int context); + void *cb_data; + void *index; +}; + +struct tx_cxt { + struct list_head sdu_list; + struct list_head hci_list; + struct list_head free_list; + u32 avail_count; + spinlock_t lock; +}; + +struct rx_cxt { + struct list_head to_host_list; + struct list_head rx_submit_list; + struct list_head free_list; + u32 avail_count; + spinlock_t to_host_lock; + spinlock_t rx_lock; + spinlock_t submit_lock; +}; + +struct lte_udev { + struct usb_device *usbdev; + struct gdm_endian gdm_ed; + struct tx_cxt tx; + struct rx_cxt rx; + struct delayed_work work_tx; + struct delayed_work work_rx; + u8 send_complete; + u8 tx_stop; + struct usb_interface *intf; + int (*rx_cb)(void *cb_data, void *data, int len, int context); + int usb_state; + u8 request_mac_addr; +}; + +#endif /* _GDM_USB_H_ */ diff --git a/drivers/staging/gdm724x/hci.h b/drivers/staging/gdm724x/hci.h new file mode 100644 index 000000000000..9a591b0db516 --- /dev/null +++ b/drivers/staging/gdm724x/hci.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +#ifndef _HCI_H_ +#define _HCI_H_ + +#define LTE_GET_INFORMATION 0x3002 +#define LTE_GET_INFORMATION_RESULT 0xB003 + #define MAC_ADDRESS 0xA2 + +#define LTE_LINK_ON_OFF_INDICATION 0xB133 +#define LTE_PDN_TABLE_IND 0xB143 + +#define LTE_TX_SDU 0x3200 +#define LTE_RX_SDU 0xB201 +#define LTE_TX_MULTI_SDU 0x3202 +#define LTE_RX_MULTI_SDU 0xB203 + +#define LTE_DL_SDU_FLOW_CONTROL 0x3305 +#define LTE_UL_SDU_FLOW_CONTROL 0xB306 + +#define LTE_AT_CMD_TO_DEVICE 0x3307 +#define LTE_AT_CMD_FROM_DEVICE 0xB308 + +#define LTE_SDIO_DM_SEND_PKT 0x3312 +#define LTE_SDIO_DM_RECV_PKT 0xB313 + +#define LTE_NV_RESTORE_REQUEST 0xB30C +#define LTE_NV_RESTORE_RESPONSE 0x330D +#define LTE_NV_SAVE_REQUEST 0xB30E + #define NV_TYPE_LTE_INFO 0x00 + #define NV_TYPE_BOARD_CONFIG 0x01 + #define NV_TYPE_RF_CAL 0x02 + #define NV_TYPE_TEMP 0x03 + #define NV_TYPE_NET_INFO 0x04 + #define NV_TYPE_SAFETY_INFO 0x05 + #define NV_TYPE_CDMA_CAL 0x06 + #define NV_TYPE_VENDOR 0x07 + #define NV_TYPE_ALL 0xff +#define LTE_NV_SAVE_RESPONSE 0x330F + +#define LTE_AT_CMD_TO_DEVICE_EXT 0x3323 +#define LTE_AT_CMD_FROM_DEVICE_EXT 0xB324 + +#endif /* _HCI_H_ */ diff --git a/drivers/staging/gdm724x/hci_packet.h b/drivers/staging/gdm724x/hci_packet.h new file mode 100644 index 000000000000..7fba8a687faf --- /dev/null +++ b/drivers/staging/gdm724x/hci_packet.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +#ifndef _HCI_PACKET_H_ +#define _HCI_PACKET_H_ + +#define HCI_HEADER_SIZE 4 + +/* + * The NIC type definition: + * For backward compatibility, lower 16 bits used as they were. + * Lower 16 bit: NIC_TYPE values + * Uppoer 16 bit: NIC_TYPE Flags + */ +#define NIC_TYPE_NIC0 0x00000010 +#define NIC_TYPE_NIC1 0x00000011 +#define NIC_TYPE_NIC2 0x00000012 +#define NIC_TYPE_NIC3 0x00000013 +#define NIC_TYPE_ARP 0x00000100 +#define NIC_TYPE_ICMPV6 0x00000200 +#define NIC_TYPE_MASK 0x0000FFFF +#define NIC_TYPE_F_IPV4 0x00010000 +#define NIC_TYPE_F_IPV6 0x00020000 +#define NIC_TYPE_F_DHCP 0x00040000 +#define NIC_TYPE_F_NDP 0x00080000 +#define NIC_TYPE_F_VLAN 0x00100000 + +struct hci_packet { + u16 cmd_evt; + u16 len; + u8 data[0]; +} __packed; + +struct tlv { + u8 type; + u8 len; + u8 *data[1]; +} __packed; + +struct sdu_header { + u16 cmd_evt; + u16 len; + u32 dftEpsId; + u32 bearer_ID; + u32 nic_type; +} __packed; + +struct sdu { + u16 cmd_evt; + u16 len; + u32 dftEpsId; + u32 bearer_ID; + u32 nic_type; + u8 data[0]; +} __packed; + +struct multi_sdu { + u16 cmd_evt; + u16 len; + u16 num_packet; + u16 reserved; + u8 data[0]; +} __packed; + +struct hci_pdn_table_ind { + u16 cmd_evt; + u16 len; + u8 activate; + u32 dft_eps_id; + u32 nic_type; + u8 pdn_type; + u8 ipv4_addr[4]; + u8 ipv6_intf_id[8]; +} __packed; + +struct hci_connect_ind { + u16 cmd_evt; + u16 len; + u32 connect; +} __packed; + + +#endif /* _HCI_PACKET_H_ */ diff --git a/drivers/staging/gdm724x/lte_ioctl.h b/drivers/staging/gdm724x/lte_ioctl.h new file mode 100644 index 000000000000..4f890e50add9 --- /dev/null +++ b/drivers/staging/gdm724x/lte_ioctl.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +#ifndef _LTE_IOCTL_H_ +#define _LTE_IOCTL_H_ + +#define SIOCLTEIOCTL SIOCDEVPRIVATE +#define SIOCG_DATA 0x8D10 +#define SIOCS_DATA 0x8D11 + +/* + * For historical reason, ioctl number and structure must be maintained + */ +enum { + LINK_ON, + LINK_OFF, + GET_NETWORK_STATICS, + RX_STOP, + RX_RESUME, + GET_DRV_VER, + GET_SDIO_DEVICE_STATUS, + GET_ENDIAN_INFO, +}; + +struct dev_endian_t { + unsigned char dev_endian; + unsigned char host_endian; +} __packed; + +struct data_t { + long len; + void *buf; +} __packed; + +struct wm_req_t { + union { + char ifrn_name[IFNAMSIZ]; + } ifr_ifrn; + unsigned short cmd; + unsigned short data_id; + struct data_t data; +} __packed; + +#ifndef ifr_name +#define ifr_name (ifr_ifrn.ifrm_name) +#endif + +#endif /* _LTE_IOCTL_H_ */ diff --git a/drivers/staging/gdm724x/netlink_k.c b/drivers/staging/gdm724x/netlink_k.c new file mode 100644 index 000000000000..9819bf014857 --- /dev/null +++ b/drivers/staging/gdm724x/netlink_k.c @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include + +#include "netlink_k.h" + +#if defined(DEFINE_MUTEX) +static DEFINE_MUTEX(netlink_mutex); +#else +static struct semaphore netlink_mutex; +#define mutex_lock(x) down(x) +#define mutex_unlock(x) up(x) +#endif + +#define ND_MAX_GROUP 30 +#define ND_IFINDEX_LEN sizeof(int) +#define ND_NLMSG_SPACE(len) (NLMSG_SPACE(len) + ND_IFINDEX_LEN) +#define ND_NLMSG_DATA(nlh) ((void *)((char *)NLMSG_DATA(nlh) + ND_IFINDEX_LEN)) +#define ND_NLMSG_S_LEN(len) (len+ND_IFINDEX_LEN) +#define ND_NLMSG_R_LEN(nlh) (nlh->nlmsg_len-ND_IFINDEX_LEN) +#define ND_NLMSG_IFIDX(nlh) NLMSG_DATA(nlh) +#define ND_MAX_MSG_LEN (1024 * 32) + +static void (*rcv_cb)(struct net_device *dev, u16 type, void *msg, int len); + +static void netlink_rcv_cb(struct sk_buff *skb) +{ + struct nlmsghdr *nlh; + struct net_device *dev; + u32 mlen; + void *msg; + int ifindex; + + if (!rcv_cb) { + printk(KERN_ERR "glte: nl cb - unregistered\n"); + return; + } + + if (skb->len < NLMSG_SPACE(0)) { + printk(KERN_ERR "glte: nl cb - invalid skb length\n"); + return; + } + + nlh = (struct nlmsghdr *)skb->data; + + if (skb->len < nlh->nlmsg_len || nlh->nlmsg_len > ND_MAX_MSG_LEN) { + printk(KERN_ERR "glte: nl cb - invalid length (%d,%d)\n", + skb->len, nlh->nlmsg_len); + return; + } + + memcpy(&ifindex, ND_NLMSG_IFIDX(nlh), ND_IFINDEX_LEN); + msg = ND_NLMSG_DATA(nlh); + mlen = ND_NLMSG_R_LEN(nlh); + + dev = dev_get_by_index(&init_net, ifindex); + if (dev) { + rcv_cb(dev, nlh->nlmsg_type, msg, mlen); + dev_put(dev); + } else { + printk(KERN_ERR "glte: nl cb - dev (%d) not found\n", ifindex); + } +} + +static void netlink_rcv(struct sk_buff *skb) +{ + mutex_lock(&netlink_mutex); + netlink_rcv_cb(skb); + mutex_unlock(&netlink_mutex); +} + +struct sock *netlink_init(int unit, + void (*cb)(struct net_device *dev, u16 type, void *msg, int len)) +{ + struct sock *sock; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) + struct netlink_kernel_cfg cfg = { + .input = netlink_rcv, + }; +#endif + +#if !defined(DEFINE_MUTEX) + init_MUTEX(&netlink_mutex); +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0) + sock = netlink_kernel_create(&init_net, unit, 0, netlink_rcv, NULL, + THIS_MODULE); +#elif LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0) + sock = netlink_kernel_create(&init_net, unit, THIS_MODULE, &cfg); +#else + sock = netlink_kernel_create(&init_net, unit, &cfg); +#endif + + if (sock) + rcv_cb = cb; + + return sock; +} + +void netlink_exit(struct sock *sock) +{ + sock_release(sock->sk_socket); +} + +int netlink_send(struct sock *sock, int group, u16 type, void *msg, int len) +{ + static u32 seq; + struct sk_buff *skb = NULL; + struct nlmsghdr *nlh; + int ret = 0; + + if (group > ND_MAX_GROUP) + return -EINVAL; + + if (!netlink_has_listeners(sock, group+1)) + return -ESRCH; + + skb = alloc_skb(NLMSG_SPACE(len), GFP_ATOMIC); + if (!skb) + return -ENOMEM; + + seq++; + + nlh = nlmsg_put(skb, 0, seq, type, len, 0); + memcpy(NLMSG_DATA(nlh), msg, len); +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0) + NETLINK_CB(skb).pid = 0; +#else + NETLINK_CB(skb).portid = 0; +#endif + NETLINK_CB(skb).dst_group = 0; + + ret = netlink_broadcast(sock, skb, 0, group+1, GFP_ATOMIC); + if (!ret) + return len; + + if (ret != -ESRCH) + printk(KERN_ERR "glte: nl broadcast g=%d, t=%d, l=%d, r=%d\n", + group, type, len, ret); + else if (netlink_has_listeners(sock, group+1)) + return -EAGAIN; + + return ret; +} diff --git a/drivers/staging/gdm724x/netlink_k.h b/drivers/staging/gdm724x/netlink_k.h new file mode 100644 index 000000000000..589486d76714 --- /dev/null +++ b/drivers/staging/gdm724x/netlink_k.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +#ifndef _NETLINK_K_H +#define _NETLINK_K_H + +#include +#include + +struct sock *netlink_init(int unit, + void (*cb)(struct net_device *dev, u16 type, void *msg, int len)); +void netlink_exit(struct sock *sock); +int netlink_send(struct sock *sock, int group, u16 type, void *msg, int len); + +#endif /* _NETLINK_K_H_ */ From 57a39f6d727f240f61fd6262195f6dd635939522 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Jul 2013 13:15:23 -0700 Subject: [PATCH 0609/3400] staging: gdm724x: gdm_tty: fix tty api build warnings This fixes the build warnings due to changes in the tty api. Note, I don't know if the reference counting is correct, but at least there are no more build warnings. Also the tty code needs to be reworked, no static arrays of tty devices and the like... Cc: Won Kang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gdm724x/gdm_tty.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/staging/gdm724x/gdm_tty.c b/drivers/staging/gdm724x/gdm_tty.c index 4d4040e3b101..64904e012dc8 100644 --- a/drivers/staging/gdm724x/gdm_tty.c +++ b/drivers/staging/gdm724x/gdm_tty.c @@ -131,7 +131,7 @@ static void gdm_tty_close(struct tty_struct *tty, struct file *filp) static int gdm_tty_recv_complete(void *data, int len, int index, int minor, int complete) { struct tty_str *tty_str = g_tty_str[index][minor]; - struct tty_struct *tty; + struct tty_port *tty_port; if (!GDM_TTY_READY(tty_str)) { if (complete == RECV_PACKET_PROCESS_COMPLETE) @@ -142,17 +142,15 @@ static int gdm_tty_recv_complete(void *data, int len, int index, int minor, int if (!data || !len) goto complete_routine; - tty = tty_port_tty_get(&tty_str->port); + tty_port = &tty_str->port; - if (tty_buffer_request_room(tty, len) == len) { - tty_insert_flip_string(tty, data, len); - tty_flip_buffer_push(tty); + if (tty_buffer_request_room(tty_port, len) == len) { + tty_insert_flip_string(tty_port, data, len); + tty_flip_buffer_push(tty_port); } else { - tty_kref_put(tty); return TO_HOST_BUFFER_REQUEST_FAIL; } - tty_kref_put(tty); complete_routine: if (complete == RECV_PACKET_PROCESS_COMPLETE) gdm_tty_recv(tty_str, gdm_tty_recv_complete); From ca7ea39361aafc769cea5d68e021fccf0dbb714b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Jul 2013 13:16:53 -0700 Subject: [PATCH 0610/3400] staging: gdm724x: add tty stuff to TODO file. At the least, this should be dynamic, and all of the tty stuff needs to be audited really well. Cc: Won Kang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gdm724x/TODO | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/gdm724x/TODO b/drivers/staging/gdm724x/TODO index cd89214aa265..b2b571ecb063 100644 --- a/drivers/staging/gdm724x/TODO +++ b/drivers/staging/gdm724x/TODO @@ -9,6 +9,7 @@ TODO: - Explain reason for multiples of 512 bytes in alloc_tx_struct() - Review use of atomic allocation for tx structs - No error checking for alloc_tx_struct in do_tx() +- fix up static tty port allocation to be dynamic Patches to: Jonathan Kim From 497a2e02a1d159269464b531aa6a3e8a60138e25 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Jul 2013 13:22:29 -0700 Subject: [PATCH 0611/3400] staging: gdm724x: remove unneeded TO_HOST_SUCCESS enum 0 is always success in the kernel, just use that. Cc: Won Kang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gdm724x/gdm_tty.c | 2 +- drivers/staging/gdm724x/gdm_tty.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/gdm724x/gdm_tty.c b/drivers/staging/gdm724x/gdm_tty.c index 64904e012dc8..a19c14ffe6a9 100644 --- a/drivers/staging/gdm724x/gdm_tty.c +++ b/drivers/staging/gdm724x/gdm_tty.c @@ -155,7 +155,7 @@ complete_routine: if (complete == RECV_PACKET_PROCESS_COMPLETE) gdm_tty_recv(tty_str, gdm_tty_recv_complete); - return TO_HOST_SUCCESS; + return 0; } static void gdm_tty_send_complete(void *arg) diff --git a/drivers/staging/gdm724x/gdm_tty.h b/drivers/staging/gdm724x/gdm_tty.h index bfe654eb378b..046744b5adae 100644 --- a/drivers/staging/gdm724x/gdm_tty.h +++ b/drivers/staging/gdm724x/gdm_tty.h @@ -24,7 +24,6 @@ #define MAX_ISSUE_NUM 3 enum TO_HOST_RESULT { - TO_HOST_SUCCESS = 0, TO_HOST_BUFFER_REQUEST_FAIL = 1, TO_HOST_PORT_CLOSE = 2, TO_HOST_INVALID_PACKET = 3, From aee9440d78bda37ae07f27c862aee4ec8ddf97ea Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Jul 2013 13:26:12 -0700 Subject: [PATCH 0612/3400] staging: gdm724x: fix up line lengths in the .h files This fixes up the coding style line lengths in the .h files for this driver. Cc: Won Kang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gdm724x/gdm_lte.h | 6 ++++-- drivers/staging/gdm724x/gdm_mux.h | 6 ++++-- drivers/staging/gdm724x/gdm_tty.h | 6 ++++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/staging/gdm724x/gdm_lte.h b/drivers/staging/gdm724x/gdm_lte.h index 1614e917c004..90c9d51fcaf0 100644 --- a/drivers/staging/gdm724x/gdm_lte.h +++ b/drivers/staging/gdm724x/gdm_lte.h @@ -54,7 +54,8 @@ struct phy_dev { void (*cb)(void *cb_data), void *cb_data, int dev_idx, int nic_type); int (*rcv_func)(void *priv_dev, - int (*cb)(void *cb_data, void *data, int len, int context), + int (*cb)(void *cb_data, void *data, int len, + int context), void *cb_data, int context); struct gdm_endian *(*get_endian)(void *priv_dev); }; @@ -74,7 +75,8 @@ int gdm_lte_event_init(void); void gdm_lte_event_exit(void); void start_rx_proc(struct phy_dev *phy_dev); -int register_lte_device(struct phy_dev *phy_dev, struct device *dev, u8 *mac_address); +int register_lte_device(struct phy_dev *phy_dev, struct device *dev, + u8 *mac_address); void unregister_lte_device(struct phy_dev *phy_dev); #endif /* _GDM_LTE_H_ */ diff --git a/drivers/staging/gdm724x/gdm_mux.h b/drivers/staging/gdm724x/gdm_mux.h index e8cfa8d401e3..d5b0b54dd539 100644 --- a/drivers/staging/gdm724x/gdm_mux.h +++ b/drivers/staging/gdm724x/gdm_mux.h @@ -57,7 +57,8 @@ struct mux_rx { void *mux_dev; u32 offset; u32 len; - int (*callback)(void *data, int len, int tty_index, int minor, int complete); + int (*callback)(void *data, int len, int tty_index, int minor, + int complete); }; struct rx_cxt { @@ -77,7 +78,8 @@ struct mux_dev { struct delayed_work work_rx; struct usb_interface *intf; int usb_state; - int (*rx_cb)(void *data, int len, int tty_index, int minor, int complete); + int (*rx_cb)(void *data, int len, int tty_index, int minor, + int complete); spinlock_t write_lock; u8 minor[2]; }; diff --git a/drivers/staging/gdm724x/gdm_tty.h b/drivers/staging/gdm724x/gdm_tty.h index 046744b5adae..faeaa412eca0 100644 --- a/drivers/staging/gdm724x/gdm_tty.h +++ b/drivers/staging/gdm724x/gdm_tty.h @@ -38,8 +38,10 @@ struct tty_dev { void *priv_dev; int (*send_func)(void *priv_dev, void *data, int len, int tty_index, void (*cb)(void *cb_data), void *cb_data); - int (*recv_func)(void *priv_dev, int (*cb)(void *data, int len, int tty_index, int minor, int complete)); - int (*send_control)(void *priv_dev, int request, int value, void *data, int len); + int (*recv_func)(void *priv_dev, int (*cb)(void *data, int len, + int tty_index, int minor, int complete)); + int (*send_control)(void *priv_dev, int request, int value, void *data, + int len); u8 minor[2]; }; From 3ce20a710f1dac8f5073d1b138039c75dd46d967 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 8 Jul 2013 11:34:19 -0700 Subject: [PATCH 0613/3400] misc: c2port: use dev_bin_attrs instead of hand-coding it Classes support a list of default binary attributes, so use that in the c2port driver, instead of hand creating and destroying the file, which is racing with userspace. Bonus is this removes lines of code. Cc: Rodolfo Giometti Signed-off-by: Greg Kroah-Hartman -- drivers/misc/c2port/core.c | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) --- drivers/misc/c2port/core.c | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/drivers/misc/c2port/core.c b/drivers/misc/c2port/core.c index f32550a74bdd..a3b8370c7dea 100644 --- a/drivers/misc/c2port/core.c +++ b/drivers/misc/c2port/core.c @@ -867,14 +867,17 @@ static struct device_attribute c2port_attrs[] = { __ATTR_NULL, }; -static struct bin_attribute c2port_bin_attrs = { - .attr = { - .name = "flash_data", - .mode = 0644 +static struct bin_attribute c2port_bin_attrs[] = { + { + .attr = { + .name = "flash_data", + .mode = 0644 + }, + .read = c2port_read_flash_data, + .write = c2port_write_flash_data, + /* .size is computed at run-time */ }, - .read = c2port_read_flash_data, - .write = c2port_write_flash_data, - /* .size is computed at run-time */ + __ATTR_NULL }; /* @@ -907,6 +910,8 @@ struct c2port_device *c2port_device_register(char *name, goto error_idr_alloc; c2dev->id = ret; + c2port_bin_attrs[0].size = ops->blocks_num * ops->block_size; + c2dev->dev = device_create(c2port_class, NULL, 0, c2dev, "c2port%d", c2dev->id); if (unlikely(IS_ERR(c2dev->dev))) { @@ -919,12 +924,6 @@ struct c2port_device *c2port_device_register(char *name, c2dev->ops = ops; mutex_init(&c2dev->mutex); - /* Create binary file */ - c2port_bin_attrs.size = ops->blocks_num * ops->block_size; - ret = device_create_bin_file(c2dev->dev, &c2port_bin_attrs); - if (unlikely(ret)) - goto error_device_create_bin_file; - /* By default C2 port access is off */ c2dev->access = c2dev->flash_access = 0; ops->access(c2dev, 0); @@ -937,9 +936,6 @@ struct c2port_device *c2port_device_register(char *name, return c2dev; -error_device_create_bin_file: - device_destroy(c2port_class, 0); - error_device_create: spin_lock_irq(&c2port_idr_lock); idr_remove(&c2port_idr, c2dev->id); @@ -959,7 +955,6 @@ void c2port_device_unregister(struct c2port_device *c2dev) dev_info(c2dev->dev, "C2 port %s removed\n", c2dev->name); - device_remove_bin_file(c2dev->dev, &c2port_bin_attrs); spin_lock_irq(&c2port_idr_lock); idr_remove(&c2port_idr, c2dev->id); spin_unlock_irq(&c2port_idr_lock); @@ -985,6 +980,7 @@ static int __init c2port_init(void) return PTR_ERR(c2port_class); } c2port_class->dev_attrs = c2port_attrs; + c2port_class->dev_bin_attrs = c2port_bin_attrs; return 0; } From 2e6a9e8428d2c391b94d3bcd01c3a3319a1f90b3 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 2 Jul 2013 12:22:05 -0700 Subject: [PATCH 0614/3400] USB: remove unneeded idr.h include None of these USB files need idr.h, so don't include it. Cc: Alexander Shishkin Reviewed-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/endpoint.c | 1 - drivers/usb/musb/musb_core.c | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c index 68cc6532e749..f13a289a0743 100644 --- a/drivers/usb/core/endpoint.c +++ b/drivers/usb/core/endpoint.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include "usb.h" diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 29a24ced6748..9e59710efee7 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -99,7 +99,6 @@ #include #include #include -#include #include #include "musb_core.h" From 0511b36399434d49d3a6b58cf49be90d96e66848 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 2 Jul 2013 12:22:06 -0700 Subject: [PATCH 0615/3400] USB: sl811: move debug files from proc to debugfs Drivers should not be putting debug files in /proc/ that is what debugfs is for, so move the sl811 driver's debug file to debugfs. Reviewed-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/sl811-hcd.c | 38 +++++++++++------------------------- drivers/usb/host/sl811.h | 2 +- 2 files changed, 12 insertions(+), 28 deletions(-) diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index c11c5d8f94e0..d8938630e092 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c @@ -48,6 +48,8 @@ #include #include #include +#include +#include #include #include @@ -63,11 +65,6 @@ MODULE_ALIAS("platform:sl811-hcd"); #define DRIVER_VERSION "19 May 2005" - -#ifndef DEBUG -# define STUB_DEBUG_FILE -#endif - /* for now, use only one transfer register bank */ #undef USE_B @@ -1373,16 +1370,6 @@ sl811h_bus_resume(struct usb_hcd *hcd) /*-------------------------------------------------------------------------*/ -#ifdef STUB_DEBUG_FILE - -static inline void create_debug_file(struct sl811 *sl811) { } -static inline void remove_debug_file(struct sl811 *sl811) { } - -#else - -#include -#include - static void dump_irq(struct seq_file *s, char *label, u8 mask) { seq_printf(s, "%s %02x%s%s%s%s%s%s\n", label, mask, @@ -1394,7 +1381,7 @@ static void dump_irq(struct seq_file *s, char *label, u8 mask) (mask & SL11H_INTMASK_DP) ? " dp" : ""); } -static int proc_sl811h_show(struct seq_file *s, void *unused) +static int sl811h_show(struct seq_file *s, void *unused) { struct sl811 *sl811 = s->private; struct sl811h_ep *ep; @@ -1505,34 +1492,31 @@ static int proc_sl811h_show(struct seq_file *s, void *unused) return 0; } -static int proc_sl811h_open(struct inode *inode, struct file *file) +static int sl811h_open(struct inode *inode, struct file *file) { - return single_open(file, proc_sl811h_show, PDE_DATA(inode)); + return single_open(file, sl811h_show, inode->i_private); } -static const struct file_operations proc_ops = { - .open = proc_sl811h_open, +static const struct file_operations debug_ops = { + .open = sl811h_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; /* expect just one sl811 per system */ -static const char proc_filename[] = "driver/sl811h"; - static void create_debug_file(struct sl811 *sl811) { - sl811->pde = proc_create_data(proc_filename, 0, NULL, &proc_ops, sl811); + sl811->debug_file = debugfs_create_file("sl811h", S_IRUGO, + usb_debug_root, sl811, + &debug_ops); } static void remove_debug_file(struct sl811 *sl811) { - if (sl811->pde) - remove_proc_entry(proc_filename, NULL); + debugfs_remove(sl811->debug_file); } -#endif - /*-------------------------------------------------------------------------*/ static void diff --git a/drivers/usb/host/sl811.h b/drivers/usb/host/sl811.h index 7ac5c5ee4a3e..1e23ef49bec1 100644 --- a/drivers/usb/host/sl811.h +++ b/drivers/usb/host/sl811.h @@ -122,7 +122,7 @@ struct sl811 { void __iomem *addr_reg; void __iomem *data_reg; struct sl811_platform_data *board; - struct proc_dir_entry *pde; + struct dentry *debug_file; unsigned long stat_insrmv; unsigned long stat_wake; From a6363463e8f5c7996aff6fa1285ff6c7cc3d3f6d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 2 Jul 2013 12:22:07 -0700 Subject: [PATCH 0616/3400] USB: isp1362: move debug files from proc to debugfs Drivers should not be putting debug files in /proc/ that is what debugfs is for, so move the isp1362 driver's debug file to debugfs. Reviewed-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/isp1362-hcd.c | 45 +++++++++------------------------- drivers/usb/host/isp1362.h | 2 +- 2 files changed, 12 insertions(+), 35 deletions(-) diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c index fd76256c7e74..c15463b898e2 100644 --- a/drivers/usb/host/isp1362-hcd.c +++ b/drivers/usb/host/isp1362-hcd.c @@ -78,6 +78,8 @@ #include #include #include +#include +#include #include #include @@ -88,7 +90,6 @@ static int dbg_level; module_param(dbg_level, int, 0644); #else module_param(dbg_level, int, 0); -#define STUB_DEBUG_FILE #endif #include "../core/usb.h" @@ -1907,20 +1908,6 @@ static int isp1362_bus_resume(struct usb_hcd *hcd) /*-------------------------------------------------------------------------*/ -#ifdef STUB_DEBUG_FILE - -static inline void create_debug_file(struct isp1362_hcd *isp1362_hcd) -{ -} -static inline void remove_debug_file(struct isp1362_hcd *isp1362_hcd) -{ -} - -#else - -#include -#include - static void dump_irq(struct seq_file *s, char *label, u16 mask) { seq_printf(s, "%-15s %04x%s%s%s%s%s%s\n", label, mask, @@ -2063,7 +2050,7 @@ static void dump_regs(struct seq_file *s, struct isp1362_hcd *isp1362_hcd) isp1362_read_reg16(isp1362_hcd, HCATLDTCTO)); } -static int proc_isp1362_show(struct seq_file *s, void *unused) +static int isp1362_show(struct seq_file *s, void *unused) { struct isp1362_hcd *isp1362_hcd = s->private; struct isp1362_ep *ep; @@ -2167,41 +2154,31 @@ static int proc_isp1362_show(struct seq_file *s, void *unused) return 0; } -static int proc_isp1362_open(struct inode *inode, struct file *file) +static int isp1362_open(struct inode *inode, struct file *file) { - return single_open(file, proc_isp1362_show, PDE_DATA(inode)); + return single_open(file, isp1362_show, inode); } -static const struct file_operations proc_ops = { - .open = proc_isp1362_open, +static const struct file_operations debug_ops = { + .open = isp1362_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; /* expect just one isp1362_hcd per system */ -static const char proc_filename[] = "driver/isp1362"; - static void create_debug_file(struct isp1362_hcd *isp1362_hcd) { - struct proc_dir_entry *pde; - - pde = proc_create_data(proc_filename, 0, NULL, &proc_ops, isp1362_hcd); - if (pde == NULL) { - pr_warning("%s: Failed to create debug file '%s'\n", __func__, proc_filename); - return; - } - isp1362_hcd->pde = pde; + isp1362_hcd->debug_file = debugfs_create_file("isp1362", S_IRUGO, + usb_debug_root, + isp1362_hcd, &debug_ops); } static void remove_debug_file(struct isp1362_hcd *isp1362_hcd) { - if (isp1362_hcd->pde) - remove_proc_entry(proc_filename, NULL); + debugfs_remove(isp1362_hcd->debug_file); } -#endif - /*-------------------------------------------------------------------------*/ static void __isp1362_sw_reset(struct isp1362_hcd *isp1362_hcd) diff --git a/drivers/usb/host/isp1362.h b/drivers/usb/host/isp1362.h index 7b34699f5a65..3b0b4847c3a9 100644 --- a/drivers/usb/host/isp1362.h +++ b/drivers/usb/host/isp1362.h @@ -480,7 +480,7 @@ struct isp1362_hcd { struct isp1362_platform_data *board; - struct proc_dir_entry *pde; + struct dentry *debug_file; unsigned long stat1, stat2, stat4, stat8, stat16; /* HC registers */ From 0ec473b5267d01762b610d57e168b0401a137f3a Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 24 Jul 2013 14:13:03 -0700 Subject: [PATCH 0617/3400] staging: gdm724x: Update logging Make the logging prefixes match the module names by adding #define pr_fmt(fmt) KBUILD_MODNAME and converting printks to netdev_ when a struct netdevice * is available and and pr_ when not. Remove embedded prefixes. Add missing terminating newlines. Remove an unnecessary rx-dropped message. Remove an unnecessary temporary variable. Signed-off-by: Joe Perches Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gdm724x/gdm_lte.c | 38 ++++++++++++------------- drivers/staging/gdm724x/gdm_mux.c | 41 ++++++++++++++------------- drivers/staging/gdm724x/gdm_tty.c | 8 ++++-- drivers/staging/gdm724x/gdm_usb.c | 43 +++++++++++++++-------------- drivers/staging/gdm724x/netlink_k.c | 12 ++++---- 5 files changed, 73 insertions(+), 69 deletions(-) diff --git a/drivers/staging/gdm724x/gdm_lte.c b/drivers/staging/gdm724x/gdm_lte.c index 357474acb371..0c336345f946 100644 --- a/drivers/staging/gdm724x/gdm_lte.c +++ b/drivers/staging/gdm724x/gdm_lte.c @@ -11,6 +11,8 @@ * GNU General Public License for more details. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -103,7 +105,6 @@ static int gdm_lte_rx(struct sk_buff *skb, struct nic *nic, int nic_type) ret = netif_rx_ni(skb); if (ret == NET_RX_DROP) { - printk(KERN_ERR "glte: rx - dropped\n"); nic->stats.rx_dropped++; } else { nic->stats.rx_packets++; @@ -416,7 +417,7 @@ static int gdm_lte_tx(struct sk_buff *skb, struct net_device *dev) nic_type = gdm_lte_tx_nic_type(dev, skb); if (nic_type == 0) { - printk(KERN_ERR "glte: tx - invalid nic_type\n"); + netdev_err(dev, "tx - invalid nic_type\n"); return -1; } @@ -504,7 +505,7 @@ static void get_dev_endian(struct data_t *data, struct net_device *dev) ret = copy_to_user(data->buf, gdm_dev_endian(nic), sizeof(struct dev_endian_t)); if (ret) - printk(KERN_INFO "glte: state - failed to copy\n"); + netdev_info(dev, "state - failed to copy\n"); } static int gdm_lte_ioctl_get_data(struct wm_req_t *req, struct net_device *dev) @@ -517,7 +518,7 @@ static int gdm_lte_ioctl_get_data(struct wm_req_t *req, struct net_device *dev) get_dev_endian(&req->data, dev); break; default: - printk(KERN_ERR "glte: ioctl - unknown type %d\n", id); + netdev_err(dev, "ioctl - unknown type %d\n", id); break; } return 0; @@ -562,7 +563,7 @@ int gdm_lte_event_init(void) return 0; } - printk(KERN_ERR "glte: event init failed\n"); + pr_err("event init failed\n"); return -1; } @@ -654,7 +655,7 @@ static void gdm_lte_netif_rx(struct net_device *dev, char *buf, int len, int fla eth.h_proto = htons(ETH_P_IPV6); vlan_eth.h_vlan_encapsulated_proto = htons(ETH_P_IPV6); } else { - printk(KERN_ERR "glte: Unknown IP version %d\n", ip_version); + netdev_err(dev, "Unknown IP version %d\n", ip_version); return; } } @@ -700,11 +701,11 @@ static void gdm_lte_multi_sdu_pkt(struct phy_dev *phy_dev, char *buf, int len) nic_type = gdm_dev32_to_cpu(phy_dev->get_endian(phy_dev->priv_dev), sdu->nic_type); if (cmd_evt != LTE_RX_SDU) { - printk(KERN_ERR "glte: rx sdu wrong hci %04x\n", cmd_evt); + pr_err("rx sdu wrong hci %04x\n", cmd_evt); return; } if (hci_len < 12) { - printk(KERN_ERR "glte: rx sdu invalid len %d\n", hci_len); + pr_err("rx sdu invalid len %d\n", hci_len); return; } @@ -713,7 +714,7 @@ static void gdm_lte_multi_sdu_pkt(struct phy_dev *phy_dev, char *buf, int len) dev = phy_dev->dev[index]; gdm_lte_netif_rx(dev, (char *)sdu->data, (int)(hci_len-12), nic_type); } else { - printk(KERN_ERR "glte: rx sdu invalid nic_type : %x\n", nic_type); + pr_err("rx sdu invalid nic_type :%x\n", nic_type); } data += ((hci_len+3) & 0xfffc) + HCI_HEADER_SIZE; @@ -730,12 +731,11 @@ static void gdm_lte_pdn_table(struct net_device *dev, char *buf, int len) nic->pdn_table.dft_eps_id = gdm_dev32_to_cpu(gdm_dev_endian(nic), pdn_table->dft_eps_id); nic->pdn_table.nic_type = gdm_dev32_to_cpu(gdm_dev_endian(nic), pdn_table->nic_type); - printk(KERN_INFO "glte: pdn %s activated, nic_type=0x%x\n", - dev->name, nic->pdn_table.nic_type); + netdev_info(dev, "pdn activated, nic_type=0x%x\n", + nic->pdn_table.nic_type); } else { memset(&nic->pdn_table, 0x00, sizeof(struct pdn_table)); - printk(KERN_INFO "glte: pdn %s deactivated\n", - dev->name); + netdev_info(dev, "pdn deactivated\n"); } } @@ -771,11 +771,9 @@ static int gdm_lte_receive_pkt(struct phy_dev *phy_dev, char *buf, int len) gdm_lte_multi_sdu_pkt(phy_dev, buf, len); break; case LTE_LINK_ON_OFF_INDICATION: - { - struct hci_connect_ind *connect_ind = (struct hci_connect_ind *)buf; - printk(KERN_INFO "glte: link %s\n", - connect_ind->connect ? "on" : "off"); - } + netdev_info(dev, "link %s\n", + ((struct hci_connect_ind *)buf)->connect + ? "on" : "off"); break; case LTE_PDN_TABLE_IND: pdn_table = (struct hci_pdn_table_ind *)buf; @@ -841,7 +839,7 @@ static void validate_mac_address(u8 *mac_address) { /* if zero address or multicast bit set, restore the default value */ if (is_zero_ether_addr(mac_address) || (mac_address[0] & 0x01)) { - printk(KERN_ERR "glte: MAC invalid, restoring default\n"); + pr_err("MAC invalid, restoring default\n"); memcpy(mac_address, gdm_lte_macaddr, 6); } } @@ -863,7 +861,7 @@ int register_lte_device(struct phy_dev *phy_dev, struct device *dev, u8 *mac_add /* Allocate netdev */ net = alloc_netdev(sizeof(struct nic), pdn_dev_name, ether_setup); if (net == NULL) { - printk(KERN_ERR "glte: alloc_netdev failed\n"); + pr_err("alloc_netdev failed\n"); ret = -ENOMEM; goto err; } diff --git a/drivers/staging/gdm724x/gdm_mux.c b/drivers/staging/gdm724x/gdm_mux.c index 2199f1bcbc84..f570bc00c990 100644 --- a/drivers/staging/gdm724x/gdm_mux.c +++ b/drivers/staging/gdm724x/gdm_mux.c @@ -11,6 +11,8 @@ * GNU General Public License for more details. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -172,8 +174,7 @@ static int up_to_host(struct mux_rx *r) packet_type = __le16_to_cpu(mux_header->packet_type); if (start_flag != START_FLAG) { - printk(KERN_ERR "glte: invalid START_FLAG %x\n", - start_flag); + pr_err("invalid START_FLAG %x\n", start_flag); break; } @@ -182,16 +183,14 @@ static int up_to_host(struct mux_rx *r) if (len - packet_size_sum < MUX_HEADER_SIZE + payload_size + dummy_cnt) { - printk(KERN_ERR "glte: invalid payload : %d %d %04x\n", - payload_size, len, - packet_type - ); + pr_err("invalid payload : %d %d %04x\n", + payload_size, len, packet_type); break; } index = packet_type_to_index(packet_type); if (index < 0) { - printk(KERN_ERR "glte: invalid index %d\n", index); + pr_err("invalid index %d\n", index); break; } @@ -242,7 +241,7 @@ static void do_rx(struct work_struct *work) ret = up_to_host(r); if (ret == TO_HOST_BUFFER_REQUEST_FAIL) - printk(KERN_ERR "glte: failed to send mux data to host\n"); + pr_err("failed to send mux data to host\n"); else put_rx_struct(rx, r); } @@ -272,7 +271,8 @@ static void gdm_mux_rcv_complete(struct urb *urb) if (urb->status) { if (mux_dev->usb_state == PM_NORMAL) - printk(KERN_ERR "glte: gdm_mux_rcv_complete urb status error %d\n", urb->status); + pr_err("%s: urb status error %d\n", + __func__, urb->status); put_rx_struct(rx, r); } else { r->len = r->urb->actual_length; @@ -295,13 +295,13 @@ static int gdm_mux_recv(void *priv_dev, int ret; if (!usbdev) { - printk(KERN_ERR "glte: device is disconnected\n"); + pr_err("device is disconnected\n"); return -ENODEV; } r = get_rx_struct(rx); if (!r) { - printk(KERN_ERR "glte: get_rx_struct fail\n"); + pr_err("get_rx_struct fail\n"); return -ENOMEM; } @@ -331,7 +331,7 @@ static int gdm_mux_recv(void *priv_dev, put_rx_struct(rx, r); - printk(KERN_ERR "glte: usb_submit_urb ret=%d\n", ret); + pr_err("usb_submit_urb ret=%d\n", ret); } usb_mark_last_busy(usbdev); @@ -344,7 +344,7 @@ static void gdm_mux_send_complete(struct urb *urb) struct mux_tx *t = urb->context; if (urb->status == -ECONNRESET) { - printk(KERN_INFO "glte: CONNRESET\n"); + pr_info("CONNRESET\n"); free_mux_tx(t); return; } @@ -384,7 +384,7 @@ static int gdm_mux_send(void *priv_dev, void *data, int len, int tty_index, t = alloc_mux_tx(total_len); if (!t) { - printk(KERN_ERR "glte: alloc_mux_tx fail\n"); + pr_err("alloc_mux_tx fail\n"); spin_unlock_irqrestore(&mux_dev->write_lock, flags); return -ENOMEM; } @@ -415,7 +415,7 @@ static int gdm_mux_send(void *priv_dev, void *data, int len, int tty_index, spin_unlock_irqrestore(&mux_dev->write_lock, flags); if (ret) - printk(KERN_ERR "glte: usb_submit_urb Error : %d\n", ret); + pr_err("usb_submit_urb Error: %d\n", ret); usb_mark_last_busy(usbdev); @@ -440,7 +440,7 @@ static int gdm_mux_send_control(void *priv_dev, int request, int value, void *bu ); if (ret < 0) - printk(KERN_ERR "glte: usb_control_msg error : %d\n", ret); + pr_err("usb_control_msg error: %d\n", ret); return ret < 0 ? ret : 0; } @@ -523,8 +523,7 @@ static int gdm_mux_probe(struct usb_interface *intf, const struct usb_device_id idVendor = __le16_to_cpu(usbdev->descriptor.idVendor); idProduct = __le16_to_cpu(usbdev->descriptor.idProduct); - printk(KERN_INFO "glte: mux vid = 0x%04x pid = 0x%04x\n", - idVendor, idProduct); + pr_info("mux vid = 0x%04x pid = 0x%04x\n", idVendor, idProduct); if (bInterfaceNumber != 2) { ret = -ENODEV; @@ -616,7 +615,7 @@ static int gdm_mux_suspend(struct usb_interface *intf, pm_message_t pm_msg) rx = &mux_dev->rx; if (mux_dev->usb_state != PM_NORMAL) { - printk(KERN_ERR "glte: usb suspend - invalid state\n"); + pr_err("usb suspend - invalid state\n"); return -1; } @@ -644,7 +643,7 @@ static int gdm_mux_resume(struct usb_interface *intf) mux_dev = tty_dev->priv_dev; if (mux_dev->usb_state != PM_SUSPEND) { - printk(KERN_ERR "glte: usb resume - invalid state\n"); + pr_err("usb resume - invalid state\n"); return -1; } @@ -672,7 +671,7 @@ static int __init gdm_usb_mux_init(void) mux_rx_wq = create_workqueue("mux_rx_wq"); if (mux_rx_wq == NULL) { - printk(KERN_ERR "glte: work queue create fail"); + pr_err("work queue create fail\n"); return -1; } diff --git a/drivers/staging/gdm724x/gdm_tty.c b/drivers/staging/gdm724x/gdm_tty.c index a19c14ffe6a9..357daa80560f 100644 --- a/drivers/staging/gdm724x/gdm_tty.c +++ b/drivers/staging/gdm724x/gdm_tty.c @@ -11,6 +11,8 @@ * GNU General Public License for more details. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -76,7 +78,7 @@ static int gdm_tty_open(struct tty_struct *tty, struct file *filp) } if (!tty_str) { - printk(KERN_INFO "glte: no tty device\n"); + pr_info("no tty device\n"); mutex_unlock(&open_mutex); return -ENODEV; } @@ -100,7 +102,7 @@ static void gdm_tty_close(struct tty_struct *tty, struct file *filp) int i; if (!tty_str) { - printk(KERN_INFO "glte: tty device already close\n"); + pr_info("tty device already closed\n"); return; } @@ -326,7 +328,7 @@ int register_lte_tty_driver(void) for (i = 0; i < TTY_MAX_COUNT; i++) { tty_driver = alloc_tty_driver(GDM_TTY_MINOR); if (!tty_driver) { - printk(KERN_ERR "glte: alloc_tty_driver fail\n"); + pr_err("alloc_tty_driver fail\n"); return -ENOMEM; } diff --git a/drivers/staging/gdm724x/gdm_usb.c b/drivers/staging/gdm724x/gdm_usb.c index 40d362e5b959..2e658f84486c 100644 --- a/drivers/staging/gdm724x/gdm_usb.c +++ b/drivers/staging/gdm724x/gdm_usb.c @@ -11,6 +11,8 @@ * GNU General Public License for more details. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -390,7 +392,7 @@ static int set_mac_address(u8 *data, void *arg) memcpy(mac_address, tlv->data, tlv->len); if (register_lte_device(phy_dev, &udev->intf->dev, mac_address) < 0) - printk(KERN_ERR "glte: register lte device failed\n"); + pr_err("register lte device failed\n"); udev->request_mac_addr = 0; @@ -444,7 +446,7 @@ static void do_rx(struct work_struct *work) KERNEL_THREAD); if (ret == -EAGAIN) - printk(KERN_ERR "glte: failed to send received data\n"); + pr_err("failed to send received data\n"); } break; } @@ -491,7 +493,8 @@ static void gdm_usb_rcv_complete(struct urb *urb) spin_unlock_irqrestore(&rx->to_host_lock, flags); } else { if (urb->status && udev->usb_state == PM_NORMAL) - printk(KERN_ERR "glte: gdm_usb_rcv_complete urb status error %d\n", urb->status); + pr_err("%s: urb status error %d\n", + __func__, urb->status); put_rx_struct(rx, r); } @@ -513,13 +516,13 @@ static int gdm_usb_recv(void *priv_dev, unsigned long flags; if (!udev->usbdev) { - printk(KERN_ERR "glte: invalid device\n"); + pr_err("invalid device\n"); return -ENODEV; } r = get_rx_struct(rx, &no_spc); if (!r) { - printk(KERN_ERR "glte: Out of Memory\n"); + pr_err("Out of Memory\n"); return -ENOMEM; } @@ -551,7 +554,7 @@ static int gdm_usb_recv(void *priv_dev, list_del(&r->rx_submit_list); spin_unlock_irqrestore(&rx->submit_lock, flags); - printk(KERN_ERR "glte: usb_submit_urb fail (%p)\n", r); + pr_err("usb_submit_urb failed (%p)\n", r); put_rx_struct(rx, r); } @@ -566,7 +569,7 @@ static void gdm_usb_send_complete(struct urb *urb) unsigned long flags; if (urb->status == -ECONNRESET) { - printk(KERN_INFO "glte: CONNRESET\n"); + pr_info("CONNRESET\n"); return; } @@ -599,7 +602,7 @@ static int send_tx_packet(struct usb_device *usbdev, struct usb_tx *t, u32 len) ret = usb_submit_urb(t->urb, GFP_ATOMIC); if (ret) - printk(KERN_ERR "glte: usb_submit_urb fail %d\n", ret); + pr_err("usb_submit_urb failed: %d\n", ret); usb_mark_last_busy(usbdev); @@ -707,7 +710,7 @@ static void do_tx(struct work_struct *work) len = packet_aggregation(udev, t->buf); if (send_tx_packet(usbdev, t, len)) { - printk(KERN_ERR "glte: send_tx_packet fail\n"); + pr_err("send_tx_packet failed\n"); t->callback = NULL; gdm_usb_send_complete(t->urb); } @@ -728,7 +731,7 @@ static int gdm_usb_sdu_send(void *priv_dev, void *data, int len, u16 send_len; if (!udev->usbdev) { - printk(KERN_ERR "glte: sdu send - invalid device\n"); + pr_err("sdu send - invalid device\n"); return TX_NO_DEV; } @@ -737,7 +740,7 @@ static int gdm_usb_sdu_send(void *priv_dev, void *data, int len, spin_unlock_irqrestore(&tx->lock, flags); if (t_sdu == NULL) { - printk(KERN_ERR "glte: sdu send - free list empty\n"); + pr_err("sdu send - free list empty\n"); return TX_NO_SPC; } @@ -781,13 +784,13 @@ static int gdm_usb_hci_send(void *priv_dev, void *data, int len, unsigned long flags; if (!udev->usbdev) { - printk(KERN_ERR "glte: hci send - invalid device\n"); + pr_err("hci send - invalid device\n"); return -ENODEV; } t = alloc_tx_struct(len); if (t == NULL) { - printk(KERN_ERR "glte: hci_send - out of memory\n"); + pr_err("hci_send - out of memory\n"); return -ENOMEM; } @@ -826,10 +829,10 @@ static int gdm_usb_probe(struct usb_interface *intf, const struct usb_device_id idVendor = __le16_to_cpu(usbdev->descriptor.idVendor); idProduct = __le16_to_cpu(usbdev->descriptor.idProduct); - printk(KERN_INFO "glte: net vid = 0x%04x pid = 0x%04x\n", idVendor, idProduct); + pr_info("net vid = 0x%04x pid = 0x%04x\n", idVendor, idProduct); if (bInterfaceNumber > NETWORK_INTERFACE) { - printk(KERN_INFO "glte: not a network device"); + pr_info("not a network device\n"); return -1; } @@ -857,7 +860,7 @@ static int gdm_usb_probe(struct usb_interface *intf, const struct usb_device_id udev->usbdev = usbdev; ret = init_usb(udev); if (ret < 0) { - printk(KERN_ERR "glte: init_usb func fail\n"); + pr_err("init_usb func failed\n"); goto out; } udev->intf = intf; @@ -874,7 +877,7 @@ static int gdm_usb_probe(struct usb_interface *intf, const struct usb_device_id ret = request_mac_address(udev); if (ret < 0) { - printk(KERN_ERR "glte: request Mac address failed\n"); + pr_err("request Mac address failed\n"); goto out; } @@ -935,7 +938,7 @@ static int gdm_usb_suspend(struct usb_interface *intf, pm_message_t pm_msg) udev = phy_dev->priv_dev; rx = &udev->rx; if (udev->usb_state != PM_NORMAL) { - printk(KERN_ERR "glte: usb suspend - invalid state"); + pr_err("usb suspend - invalid state\n"); return -1; } @@ -968,7 +971,7 @@ static int gdm_usb_resume(struct usb_interface *intf) rx = &udev->rx; if (udev->usb_state != PM_SUSPEND) { - printk(KERN_ERR "glte: usb resume - invalid state"); + pr_err("usb resume - invalid state\n"); return -1; } udev->usb_state = PM_NORMAL; @@ -1007,7 +1010,7 @@ static struct usb_driver gdm_usb_lte_driver = { static int __init gdm_usb_lte_init(void) { if (gdm_lte_event_init() < 0) { - printk(KERN_ERR "glte: error creating event\n"); + pr_err("error creating event\n"); return -1; } diff --git a/drivers/staging/gdm724x/netlink_k.c b/drivers/staging/gdm724x/netlink_k.c index 9819bf014857..90004a7a16c2 100644 --- a/drivers/staging/gdm724x/netlink_k.c +++ b/drivers/staging/gdm724x/netlink_k.c @@ -11,6 +11,8 @@ * GNU General Public License for more details. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -48,19 +50,19 @@ static void netlink_rcv_cb(struct sk_buff *skb) int ifindex; if (!rcv_cb) { - printk(KERN_ERR "glte: nl cb - unregistered\n"); + pr_err("nl cb - unregistered\n"); return; } if (skb->len < NLMSG_SPACE(0)) { - printk(KERN_ERR "glte: nl cb - invalid skb length\n"); + pr_err("nl cb - invalid skb length\n"); return; } nlh = (struct nlmsghdr *)skb->data; if (skb->len < nlh->nlmsg_len || nlh->nlmsg_len > ND_MAX_MSG_LEN) { - printk(KERN_ERR "glte: nl cb - invalid length (%d,%d)\n", + pr_err("nl cb - invalid length (%d,%d)\n", skb->len, nlh->nlmsg_len); return; } @@ -74,7 +76,7 @@ static void netlink_rcv_cb(struct sk_buff *skb) rcv_cb(dev, nlh->nlmsg_type, msg, mlen); dev_put(dev); } else { - printk(KERN_ERR "glte: nl cb - dev (%d) not found\n", ifindex); + pr_err("nl cb - dev (%d) not found\n", ifindex); } } @@ -152,7 +154,7 @@ int netlink_send(struct sock *sock, int group, u16 type, void *msg, int len) return len; if (ret != -ESRCH) - printk(KERN_ERR "glte: nl broadcast g=%d, t=%d, l=%d, r=%d\n", + pr_err("nl broadcast g=%d, t=%d, l=%d, r=%d\n", group, type, len, ret); else if (netlink_has_listeners(sock, group+1)) return -EAGAIN; From dee4a0be69c0e2996188e0c46478eadc280a8954 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Wed, 24 Jul 2013 16:43:51 -0400 Subject: [PATCH 0618/3400] tty: Fix lock order in tty_do_resize() Commits 6a1c0680cf3ba94356ecd58833e1540c93472a57 and 9356b535fcb71db494fc434acceb79f56d15bda2, respectively 'tty: Convert termios_mutex to termios_rwsem' and 'n_tty: Access termios values safely' introduced a circular lock dependency with console_lock and termios_rwsem. The lockdep report [1] shows that n_tty_write() will attempt to claim console_lock while holding the termios_rwsem, whereas tty_do_resize() may already hold the console_lock while claiming the termios_rwsem. Since n_tty_write() and tty_do_resize() do not contend over the same data -- the tty->winsize structure -- correct the lock dependency by introducing a new lock which specifically serializes access to tty->winsize only. [1] Lockdep report ====================================================== [ INFO: possible circular locking dependency detected ] 3.10.0-0+tip-xeon+lockdep #0+tip Not tainted ------------------------------------------------------- modprobe/277 is trying to acquire lock: (&tty->termios_rwsem){++++..}, at: [] tty_do_resize+0x36/0xe0 but task is already holding lock: ((fb_notifier_list).rwsem){.+.+.+}, at: [] __blocking_notifier_call_chain+0x56/0xc0 which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #2 ((fb_notifier_list).rwsem){.+.+.+}: [] lock_acquire+0x92/0x1f0 [] down_read+0x47/0x5c [] __blocking_notifier_call_chain+0x56/0xc0 [] blocking_notifier_call_chain+0x16/0x20 [] fb_notifier_call_chain+0x1b/0x20 [] register_framebuffer+0x1e2/0x320 [] drm_fb_helper_initial_config+0x371/0x540 [drm_kms_helper] [] nouveau_fbcon_init+0x105/0x140 [nouveau] [] nouveau_drm_load+0x43f/0x610 [nouveau] [] drm_get_pci_dev+0x17e/0x2a0 [drm] [] nouveau_drm_probe+0x25a/0x2a0 [nouveau] [] local_pci_probe+0x4b/0x80 [] pci_device_probe+0x111/0x120 [] driver_probe_device+0x8b/0x3a0 [] __driver_attach+0xab/0xb0 [] bus_for_each_dev+0x5d/0xa0 [] driver_attach+0x1e/0x20 [] bus_add_driver+0x111/0x290 [] driver_register+0x77/0x170 [] __pci_register_driver+0x64/0x70 [] drm_pci_init+0x11a/0x130 [drm] [] nouveau_drm_init+0x4d/0x1000 [nouveau] [] do_one_initcall+0xea/0x1a0 [] load_module+0x123b/0x1bf0 [] SyS_init_module+0xd7/0x120 [] system_call_fastpath+0x16/0x1b -> #1 (console_lock){+.+.+.}: [] lock_acquire+0x92/0x1f0 [] console_lock+0x77/0x80 [] con_flush_chars+0x31/0x50 [] n_tty_write+0x1ec/0x4d0 [] tty_write+0x159/0x2e0 [] redirected_tty_write+0xb5/0xc0 [] vfs_write+0xc5/0x1f0 [] SyS_write+0x55/0xa0 [] system_call_fastpath+0x16/0x1b -> #0 (&tty->termios_rwsem){++++..}: [] __lock_acquire+0x1c43/0x1d30 [] lock_acquire+0x92/0x1f0 [] down_write+0x44/0x70 [] tty_do_resize+0x36/0xe0 [] vc_do_resize+0x3e1/0x4c0 [] vc_resize+0x1f/0x30 [] fbcon_init+0x385/0x5a0 [] visual_init+0xbc/0x120 [] do_bind_con_driver+0x163/0x320 [] do_take_over_console+0x61/0x70 [] do_fbcon_takeover+0x63/0xc0 [] fbcon_event_notify+0x715/0x820 [] notifier_call_chain+0x5d/0x110 [] __blocking_notifier_call_chain+0x6c/0xc0 [] blocking_notifier_call_chain+0x16/0x20 [] fb_notifier_call_chain+0x1b/0x20 [] register_framebuffer+0x1e2/0x320 [] drm_fb_helper_initial_config+0x371/0x540 [drm_kms_helper] [] nouveau_fbcon_init+0x105/0x140 [nouveau] [] nouveau_drm_load+0x43f/0x610 [nouveau] [] drm_get_pci_dev+0x17e/0x2a0 [drm] [] nouveau_drm_probe+0x25a/0x2a0 [nouveau] [] local_pci_probe+0x4b/0x80 [] pci_device_probe+0x111/0x120 [] driver_probe_device+0x8b/0x3a0 [] __driver_attach+0xab/0xb0 [] bus_for_each_dev+0x5d/0xa0 [] driver_attach+0x1e/0x20 [] bus_add_driver+0x111/0x290 [] driver_register+0x77/0x170 [] __pci_register_driver+0x64/0x70 [] drm_pci_init+0x11a/0x130 [drm] [] nouveau_drm_init+0x4d/0x1000 [nouveau] [] do_one_initcall+0xea/0x1a0 [] load_module+0x123b/0x1bf0 [] SyS_init_module+0xd7/0x120 [] system_call_fastpath+0x16/0x1b other info that might help us debug this: Chain exists of: &tty->termios_rwsem --> console_lock --> (fb_notifier_list).rwsem Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock((fb_notifier_list).rwsem); lock(console_lock); lock((fb_notifier_list).rwsem); lock(&tty->termios_rwsem); *** DEADLOCK *** 7 locks held by modprobe/277: #0: (&__lockdep_no_validate__){......}, at: [] __driver_attach+0x5b/0xb0 #1: (&__lockdep_no_validate__){......}, at: [] __driver_attach+0x69/0xb0 #2: (drm_global_mutex){+.+.+.}, at: [] drm_get_pci_dev+0xbd/0x2a0 [drm] #3: (registration_lock){+.+.+.}, at: [] register_framebuffer+0x25/0x320 #4: (&fb_info->lock){+.+.+.}, at: [] lock_fb_info+0x26/0x60 #5: (console_lock){+.+.+.}, at: [] register_framebuffer+0x1d4/0x320 #6: ((fb_notifier_list).rwsem){.+.+.+}, at: [] __blocking_notifier_call_chain+0x56/0xc0 stack backtrace: CPU: 0 PID: 277 Comm: modprobe Not tainted 3.10.0-0+tip-xeon+lockdep #0+tip Hardware name: Dell Inc. Precision WorkStation T5400 /0RW203, BIOS A11 04/30/2012 ffffffff8213e5e0 ffff8802aa2fb298 ffffffff81755f19 ffff8802aa2fb2e8 ffffffff8174f506 ffff8802aa2fa000 ffff8802aa2fb378 ffff8802aa2ea8e8 ffff8802aa2ea910 ffff8802aa2ea8e8 0000000000000006 0000000000000007 Call Trace: [] dump_stack+0x19/0x1b [] print_circular_bug+0x1fb/0x20c [] __lock_acquire+0x1c43/0x1d30 [] ? mark_held_locks+0xae/0x120 [] ? trace_hardirqs_on_caller+0x105/0x1d0 [] lock_acquire+0x92/0x1f0 [] ? tty_do_resize+0x36/0xe0 [] down_write+0x44/0x70 [] ? tty_do_resize+0x36/0xe0 [] tty_do_resize+0x36/0xe0 [] vc_do_resize+0x3e1/0x4c0 [] vc_resize+0x1f/0x30 [] fbcon_init+0x385/0x5a0 [] visual_init+0xbc/0x120 [] do_bind_con_driver+0x163/0x320 [] do_take_over_console+0x61/0x70 [] do_fbcon_takeover+0x63/0xc0 [] fbcon_event_notify+0x715/0x820 [] notifier_call_chain+0x5d/0x110 [] __blocking_notifier_call_chain+0x6c/0xc0 [] blocking_notifier_call_chain+0x16/0x20 [] fb_notifier_call_chain+0x1b/0x20 [] register_framebuffer+0x1e2/0x320 [] drm_fb_helper_initial_config+0x371/0x540 [drm_kms_helper] [] ? kmemleak_alloc+0x5b/0xc0 [] ? kmem_cache_alloc_trace+0x104/0x290 [] ? drm_fb_helper_single_add_all_connectors+0x81/0xf0 [drm_kms_helper] [] nouveau_fbcon_init+0x105/0x140 [nouveau] [] nouveau_drm_load+0x43f/0x610 [nouveau] [] drm_get_pci_dev+0x17e/0x2a0 [drm] [] nouveau_drm_probe+0x25a/0x2a0 [nouveau] [] ? _raw_spin_unlock_irqrestore+0x42/0x80 [] local_pci_probe+0x4b/0x80 [] pci_device_probe+0x111/0x120 [] driver_probe_device+0x8b/0x3a0 [] __driver_attach+0xab/0xb0 [] ? driver_probe_device+0x3a0/0x3a0 [] bus_for_each_dev+0x5d/0xa0 [] driver_attach+0x1e/0x20 [] bus_add_driver+0x111/0x290 [] ? 0xffffffffa0229fff [] driver_register+0x77/0x170 [] ? 0xffffffffa0229fff [] __pci_register_driver+0x64/0x70 [] drm_pci_init+0x11a/0x130 [drm] [] ? 0xffffffffa0229fff [] ? 0xffffffffa0229fff [] nouveau_drm_init+0x4d/0x1000 [nouveau] [] do_one_initcall+0xea/0x1a0 [] load_module+0x123b/0x1bf0 [] ? ddebug_proc_open+0xb0/0xb0 [] ? trace_hardirqs_on_thunk+0x3a/0x3f [] SyS_init_module+0xd7/0x120 [] system_call_fastpath+0x16/0x1b Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/pty.c | 4 ++-- drivers/tty/tty_io.c | 11 ++++++----- include/linux/tty.h | 3 ++- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index b940127ba1c8..25c9bc783722 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -281,7 +281,7 @@ static int pty_resize(struct tty_struct *tty, struct winsize *ws) struct tty_struct *pty = tty->link; /* For a PTY we need to lock the tty side */ - down_write(&tty->termios_rwsem); + mutex_lock(&tty->winsize_mutex); if (!memcmp(ws, &tty->winsize, sizeof(*ws))) goto done; @@ -308,7 +308,7 @@ static int pty_resize(struct tty_struct *tty, struct winsize *ws) tty->winsize = *ws; pty->winsize = *ws; /* Never used so will go away soon */ done: - up_write(&tty->termios_rwsem); + mutex_unlock(&tty->winsize_mutex); return 0; } diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 2174698dd6f7..26bb78c30a00 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -2229,7 +2229,7 @@ static int tiocsti(struct tty_struct *tty, char __user *p) * * Copies the kernel idea of the window size into the user buffer. * - * Locking: tty->termios_rwsem is taken to ensure the winsize data + * Locking: tty->winsize_mutex is taken to ensure the winsize data * is consistent. */ @@ -2237,9 +2237,9 @@ static int tiocgwinsz(struct tty_struct *tty, struct winsize __user *arg) { int err; - down_read(&tty->termios_rwsem); + mutex_lock(&tty->winsize_mutex); err = copy_to_user(arg, &tty->winsize, sizeof(*arg)); - up_read(&tty->termios_rwsem); + mutex_unlock(&tty->winsize_mutex); return err ? -EFAULT: 0; } @@ -2260,7 +2260,7 @@ int tty_do_resize(struct tty_struct *tty, struct winsize *ws) unsigned long flags; /* Lock the tty */ - down_write(&tty->termios_rwsem); + mutex_lock(&tty->winsize_mutex); if (!memcmp(ws, &tty->winsize, sizeof(*ws))) goto done; /* Get the PID values and reference them so we can @@ -2275,7 +2275,7 @@ int tty_do_resize(struct tty_struct *tty, struct winsize *ws) tty->winsize = *ws; done: - up_write(&tty->termios_rwsem); + mutex_unlock(&tty->winsize_mutex); return 0; } EXPORT_SYMBOL(tty_do_resize); @@ -3016,6 +3016,7 @@ void initialize_tty_struct(struct tty_struct *tty, mutex_init(&tty->legacy_mutex); mutex_init(&tty->throttle_mutex); init_rwsem(&tty->termios_rwsem); + mutex_init(&tty->winsize_mutex); init_ldsem(&tty->ldisc_sem); init_waitqueue_head(&tty->write_wait); init_waitqueue_head(&tty->read_wait); diff --git a/include/linux/tty.h b/include/linux/tty.h index 554b732d8b55..64f864651d86 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -245,6 +245,7 @@ struct tty_struct { struct mutex legacy_mutex; struct mutex throttle_mutex; struct rw_semaphore termios_rwsem; + struct mutex winsize_mutex; spinlock_t ctrl_lock; /* Termios values are protected by the termios rwsem */ struct ktermios termios, termios_locked; @@ -254,7 +255,7 @@ struct tty_struct { struct pid *session; unsigned long flags; int count; - struct winsize winsize; /* termios rwsem */ + struct winsize winsize; /* winsize_mutex */ unsigned char stopped:1, hw_stopped:1, flow_stopped:1, packet:1; unsigned char ctrl_status; /* ctrl_lock */ unsigned int receive_room; /* Bytes free for queue */ From f3c909b42902034dd1e54abdc770c6284fe3fb7e Mon Sep 17 00:00:00 2001 From: Aldo Iljazi Date: Mon, 8 Jul 2013 22:28:00 +0300 Subject: [PATCH 0619/3400] Drivers: tty: n_gsm.c: fixed 7 errors & 6 warnings that checkpatch complained Specifically: n_gsm.c:810: ERROR: space required before the open parenthesis '(' n_gsm.c:830: WARNING: line over 80 characters n_gsm.c:971: ERROR: trailing whitespace n_gsm.c:984: ERROR: code indent should use tabs where possible n_gsm.c:984: WARNING: please, no space before tabs n_gsm.c:984: WARNING: please, no spaces at the start of a line n_gsm.c:1141: WARNING: space prohibited before semicolon n_gsm.c:1743: ERROR: space required before the open brace '{' n_gsm.c:1744: WARNING: line over 80 characters n_gsm.c:1745: ERROR: code indent should use tabs where possible n_gsm.c:1746: ERROR: code indent should use tabs where possible n_gsm.c:2908: WARNING: line over 80 characters n_gsm.c:2912: ERROR: trailing whitespace Signed-off-by: Aldo Iljazi Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_gsm.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 642239015b46..c0f76da55304 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -807,7 +807,7 @@ static int gsm_dlci_data_output(struct gsm_mux *gsm, struct gsm_dlci *dlci) int h = dlci->adaption - 1; total_size = 0; - while(1) { + while (1) { len = kfifo_len(dlci->fifo); if (len == 0) return total_size; @@ -827,8 +827,8 @@ static int gsm_dlci_data_output(struct gsm_mux *gsm, struct gsm_dlci *dlci) switch (dlci->adaption) { case 1: /* Unstructured */ break; - case 2: /* Unstructed with modem bits. Always one byte as we never - send inline break data */ + case 2: /* Unstructed with modem bits. + Always one byte as we never send inline break data */ *dp++ = gsm_encode_modem(dlci); break; } @@ -968,7 +968,7 @@ static void gsm_dlci_data_kick(struct gsm_dlci *dlci) unsigned long flags; int sweep; - if (dlci->constipated) + if (dlci->constipated) return; spin_lock_irqsave(&dlci->gsm->tx_lock, flags); @@ -981,7 +981,7 @@ static void gsm_dlci_data_kick(struct gsm_dlci *dlci) gsm_dlci_data_output(dlci->gsm, dlci); } if (sweep) - gsm_dlci_data_sweep(dlci->gsm); + gsm_dlci_data_sweep(dlci->gsm); spin_unlock_irqrestore(&dlci->gsm->tx_lock, flags); } @@ -1138,7 +1138,7 @@ static void gsm_control_modem(struct gsm_mux *gsm, u8 *data, int clen) static void gsm_control_rls(struct gsm_mux *gsm, u8 *data, int clen) { struct tty_port *port; - unsigned int addr = 0 ; + unsigned int addr = 0; u8 bits; int len = clen; u8 *dp = data; @@ -1740,10 +1740,11 @@ static void gsm_queue(struct gsm_mux *gsm) if ((gsm->control & ~PF) == UI) gsm->fcs = gsm_fcs_add_block(gsm->fcs, gsm->buf, gsm->len); - if (gsm->encoding == 0){ - /* WARNING: gsm->received_fcs is used for gsm->encoding = 0 only. - In this case it contain the last piece of data - required to generate final CRC */ + if (gsm->encoding == 0) { + /* WARNING: gsm->received_fcs is used for + gsm->encoding = 0 only. + In this case it contain the last piece of data + required to generate final CRC */ gsm->fcs = gsm_fcs_add(gsm->fcs, gsm->received_fcs); } if (gsm->fcs != GOOD_FCS) { @@ -2904,9 +2905,11 @@ static int gsmtty_install(struct tty_driver *driver, struct tty_struct *tty) gsm = gsm_mux[mux]; if (gsm->dead) return -EL2HLT; - /* If DLCI 0 is not yet fully open return an error. This is ok from a locking - perspective as we don't have to worry about this if DLCI0 is lost */ - if (gsm->dlci[0] && gsm->dlci[0]->state != DLCI_OPEN) + /* If DLCI 0 is not yet fully open return an error. + This is ok from a locking + perspective as we don't have to worry about this + if DLCI0 is lost */ + if (gsm->dlci[0] && gsm->dlci[0]->state != DLCI_OPEN) return -EL2NSYNC; dlci = gsm->dlci[line]; if (dlci == NULL) { From e84f54fc58ada30f67b7353f6c16c3c4aa7c8da5 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 10 Jul 2013 16:57:46 +0100 Subject: [PATCH 0620/3400] drivers/tty/serial: don't use devm_pinctrl_get_select_default() in probe Since commit ab78029 (drivers/pinctrl: grab default handles from device core), we can rely on device core for setting the default pins. Compile tested only. Acked-by: Linus Walleij (personally at LCE13) Signed-off-by: Wolfram Sang Acked-by: Nicolas Ferre Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/atmel_serial.c | 8 -------- drivers/tty/serial/imx.c | 9 --------- drivers/tty/serial/mxs-auart.c | 8 -------- drivers/tty/serial/omap-serial.c | 9 --------- 4 files changed, 34 deletions(-) diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 691265faebbe..0e39facfcb07 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -39,7 +39,6 @@ #include #include #include -#include #include #include @@ -1775,7 +1774,6 @@ static int atmel_serial_probe(struct platform_device *pdev) struct atmel_uart_data *pdata = pdev->dev.platform_data; void *data; int ret = -ENODEV; - struct pinctrl *pinctrl; BUILD_BUG_ON(ATMEL_SERIAL_RINGSIZE & (ATMEL_SERIAL_RINGSIZE - 1)); @@ -1809,12 +1807,6 @@ static int atmel_serial_probe(struct platform_device *pdev) if (ret) goto err; - pinctrl = devm_pinctrl_get_select_default(&pdev->dev); - if (IS_ERR(pinctrl)) { - ret = PTR_ERR(pinctrl); - goto err; - } - if (!atmel_use_dma_rx(&port->uart)) { ret = -ENOMEM; data = kmalloc(sizeof(struct atmel_uart_char) diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 415cec62073f..2797e55d9753 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -47,7 +47,6 @@ #include #include #include -#include #include #include @@ -1507,7 +1506,6 @@ static int serial_imx_probe(struct platform_device *pdev) void __iomem *base; int ret = 0; struct resource *res; - struct pinctrl *pinctrl; sport = devm_kzalloc(&pdev->dev, sizeof(*sport), GFP_KERNEL); if (!sport) @@ -1543,13 +1541,6 @@ static int serial_imx_probe(struct platform_device *pdev) sport->timer.function = imx_timeout; sport->timer.data = (unsigned long)sport; - pinctrl = devm_pinctrl_get_select_default(&pdev->dev); - if (IS_ERR(pinctrl)) { - ret = PTR_ERR(pinctrl); - dev_err(&pdev->dev, "failed to get default pinctrl: %d\n", ret); - return ret; - } - sport->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); if (IS_ERR(sport->clk_ipg)) { ret = PTR_ERR(sport->clk_ipg); diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c index 4f5f161896a1..a63a20e0d69d 100644 --- a/drivers/tty/serial/mxs-auart.c +++ b/drivers/tty/serial/mxs-auart.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -1015,7 +1014,6 @@ static int mxs_auart_probe(struct platform_device *pdev) u32 version; int ret = 0; struct resource *r; - struct pinctrl *pinctrl; s = kzalloc(sizeof(struct mxs_auart_port), GFP_KERNEL); if (!s) { @@ -1029,12 +1027,6 @@ static int mxs_auart_probe(struct platform_device *pdev) else if (ret < 0) goto out_free; - pinctrl = devm_pinctrl_get_select_default(&pdev->dev); - if (IS_ERR(pinctrl)) { - ret = PTR_ERR(pinctrl); - goto out_free; - } - if (of_id) { pdev->id_entry = of_id->data; s->devtype = pdev->id_entry->driver_data; diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index b6d172873076..eacb0def3d96 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -40,7 +40,6 @@ #include #include #include -#include #include #define OMAP_MAX_HSUART_PORTS 6 @@ -160,7 +159,6 @@ struct uart_omap_port { u32 latency; u32 calc_latency; struct work_struct qos_work; - struct pinctrl *pins; bool is_suspending; }; @@ -1468,13 +1466,6 @@ static int serial_omap_probe(struct platform_device *pdev) goto err_port_line; } - up->pins = devm_pinctrl_get_select_default(&pdev->dev); - if (IS_ERR(up->pins)) { - dev_warn(&pdev->dev, "did not get pins for uart%i error: %li\n", - up->port.line, PTR_ERR(up->pins)); - up->pins = NULL; - } - sprintf(up->name, "OMAP UART%d", up->port.line); up->port.mapbase = mem->start; up->port.membase = devm_ioremap(&pdev->dev, mem->start, From 33e745a192c272130b02b86d5dea5b577a291ed7 Mon Sep 17 00:00:00 2001 From: Hendrik Brueckner Date: Tue, 2 Jul 2013 17:07:14 +0200 Subject: [PATCH 0621/3400] tty/hvc_console: Add DTR/RTS callback to handle HUPCL control Introduce a new callback to explicitly handle the HUPCL termios control flag. This prepares for a follow-up commit for the hvc_iucv device driver to improve handling when to drop an established network connection. The callback naming is based on the recently added tty_port interface to facilitate a potential refactoring of the hvc_console to use tty_port functions. Signed-off-by: Hendrik Brueckner Signed-off-by: Greg Kroah-Hartman --- drivers/tty/hvc/hvc_console.c | 11 ++++++++++- drivers/tty/hvc/hvc_console.h | 3 +++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c index eb255e807c06..9eba119bcdd3 100644 --- a/drivers/tty/hvc/hvc_console.c +++ b/drivers/tty/hvc/hvc_console.c @@ -361,7 +361,12 @@ static int hvc_open(struct tty_struct *tty, struct file * filp) tty->driver_data = NULL; tty_port_put(&hp->port); printk(KERN_ERR "hvc_open: request_irq failed with rc %d.\n", rc); - } + } else + /* We are ready... raise DTR/RTS */ + if (C_BAUD(tty)) + if (hp->ops->dtr_rts) + hp->ops->dtr_rts(hp, 1); + /* Force wakeup of the polling thread */ hvc_kick(); @@ -393,6 +398,10 @@ static void hvc_close(struct tty_struct *tty, struct file * filp) /* We are done with the tty pointer now. */ tty_port_tty_set(&hp->port, NULL); + if (C_HUPCL(tty)) + if (hp->ops->dtr_rts) + hp->ops->dtr_rts(hp, 0); + if (hp->ops->notifier_del) hp->ops->notifier_del(hp, hp->data); diff --git a/drivers/tty/hvc/hvc_console.h b/drivers/tty/hvc/hvc_console.h index 674d23cb919a..913101980827 100644 --- a/drivers/tty/hvc/hvc_console.h +++ b/drivers/tty/hvc/hvc_console.h @@ -75,6 +75,9 @@ struct hv_ops { /* tiocmget/set implementation */ int (*tiocmget)(struct hvc_struct *hp); int (*tiocmset)(struct hvc_struct *hp, unsigned int set, unsigned int clear); + + /* Callbacks to handle tty ports */ + void (*dtr_rts)(struct hvc_struct *hp, int raise); }; /* Register a vterm and a slot index for use as a console (console_init) */ From 74b3b4cd80f43b094b5cb78e73bf612383d80749 Mon Sep 17 00:00:00 2001 From: Hendrik Brueckner Date: Tue, 2 Jul 2013 17:07:15 +0200 Subject: [PATCH 0622/3400] tty/hvc_iucv: Disconnect IUCV connection when lowering DTR Implement the dtr_rts() hvc console callback to improve control when to disconnect the IUCV connection. Previously, the IUCV connection was disconnected during the notifier_del() callback, i.e., when the last file descriptor to the hvc terminal device was closed. Recent changes in login programs caused undesired disconnects during the login phase. To prevent these kind of disconnects, implement the dtr_rts callback to implicitly handle the HUPCL termios control via the hvc_console driver. Signed-off-by: Hendrik Brueckner Signed-off-by: Greg Kroah-Hartman --- drivers/tty/hvc/hvc_iucv.c | 64 ++++++++++++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 13 deletions(-) diff --git a/drivers/tty/hvc/hvc_iucv.c b/drivers/tty/hvc/hvc_iucv.c index 9d47f50c2755..fd17a9b804b8 100644 --- a/drivers/tty/hvc/hvc_iucv.c +++ b/drivers/tty/hvc/hvc_iucv.c @@ -655,6 +655,49 @@ static void hvc_iucv_notifier_hangup(struct hvc_struct *hp, int id) spin_unlock_bh(&priv->lock); } +/** + * hvc_iucv_dtr_rts() - HVC notifier for handling DTR/RTS + * @hp: Pointer the HVC device (struct hvc_struct) + * @raise: Non-zero to raise or zero to lower DTR/RTS lines + * + * This routine notifies the HVC back-end to raise or lower DTR/RTS + * lines. Raising DTR/RTS is ignored. Lowering DTR/RTS indicates to + * drop the IUCV connection (similar to hang up the modem). + */ +static void hvc_iucv_dtr_rts(struct hvc_struct *hp, int raise) +{ + struct hvc_iucv_private *priv; + struct iucv_path *path; + + /* Raising the DTR/RTS is ignored as IUCV connections can be + * established at any times. + */ + if (raise) + return; + + priv = hvc_iucv_get_private(hp->vtermno); + if (!priv) + return; + + /* Lowering the DTR/RTS lines disconnects an established IUCV + * connection. + */ + flush_sndbuf_sync(priv); + + spin_lock_bh(&priv->lock); + path = priv->path; /* save reference to IUCV path */ + priv->path = NULL; + priv->iucv_state = IUCV_DISCONN; + spin_unlock_bh(&priv->lock); + + /* Sever IUCV path outside of priv->lock due to lock ordering of: + * priv->lock <--> iucv_table_lock */ + if (path) { + iucv_path_sever(path, NULL); + iucv_path_free(path); + } +} + /** * hvc_iucv_notifier_del() - HVC notifier for closing a TTY for the last time. * @hp: Pointer to the HVC device (struct hvc_struct) @@ -662,15 +705,15 @@ static void hvc_iucv_notifier_hangup(struct hvc_struct *hp, int id) * the index of an struct hvc_iucv_private instance. * * This routine notifies the HVC back-end that the last tty device fd has been - * closed. The function calls hvc_iucv_cleanup() to clean up the struct - * hvc_iucv_private instance. + * closed. The function cleans up tty resources. The clean-up of the IUCV + * connection is done in hvc_iucv_dtr_rts() and depends on the HUPCL termios + * control setting. * * Locking: struct hvc_iucv_private->lock */ static void hvc_iucv_notifier_del(struct hvc_struct *hp, int id) { struct hvc_iucv_private *priv; - struct iucv_path *path; priv = hvc_iucv_get_private(id); if (!priv) @@ -679,17 +722,11 @@ static void hvc_iucv_notifier_del(struct hvc_struct *hp, int id) flush_sndbuf_sync(priv); spin_lock_bh(&priv->lock); - path = priv->path; /* save reference to IUCV path */ - priv->path = NULL; - hvc_iucv_cleanup(priv); + destroy_tty_buffer_list(&priv->tty_outqueue); + destroy_tty_buffer_list(&priv->tty_inqueue); + priv->tty_state = TTY_CLOSED; + priv->sndbuf_len = 0; spin_unlock_bh(&priv->lock); - - /* sever IUCV path outside of priv->lock due to lock ordering of: - * priv->lock <--> iucv_table_lock */ - if (path) { - iucv_path_sever(path, NULL); - iucv_path_free(path); - } } /** @@ -931,6 +968,7 @@ static const struct hv_ops hvc_iucv_ops = { .notifier_add = hvc_iucv_notifier_add, .notifier_del = hvc_iucv_notifier_del, .notifier_hangup = hvc_iucv_notifier_hangup, + .dtr_rts = hvc_iucv_dtr_rts, }; /* Suspend / resume device operations */ From 7b5d4122d39f7c26ce42806b7a67cf04537545e6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Jul 2013 15:28:02 -0700 Subject: [PATCH 0623/3400] Revert "misc: c2port: use dev_bin_attrs instead of hand-coding it" This reverts commit 3ce20a710f1dac8f5073d1b138039c75dd46d967 It should go in through the driver-core tree, not the char-misc tree, my mistake. Signed-off-by: Greg Kroah-Hartman --- drivers/misc/c2port/core.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/drivers/misc/c2port/core.c b/drivers/misc/c2port/core.c index a3b8370c7dea..f32550a74bdd 100644 --- a/drivers/misc/c2port/core.c +++ b/drivers/misc/c2port/core.c @@ -867,17 +867,14 @@ static struct device_attribute c2port_attrs[] = { __ATTR_NULL, }; -static struct bin_attribute c2port_bin_attrs[] = { - { - .attr = { - .name = "flash_data", - .mode = 0644 - }, - .read = c2port_read_flash_data, - .write = c2port_write_flash_data, - /* .size is computed at run-time */ +static struct bin_attribute c2port_bin_attrs = { + .attr = { + .name = "flash_data", + .mode = 0644 }, - __ATTR_NULL + .read = c2port_read_flash_data, + .write = c2port_write_flash_data, + /* .size is computed at run-time */ }; /* @@ -910,8 +907,6 @@ struct c2port_device *c2port_device_register(char *name, goto error_idr_alloc; c2dev->id = ret; - c2port_bin_attrs[0].size = ops->blocks_num * ops->block_size; - c2dev->dev = device_create(c2port_class, NULL, 0, c2dev, "c2port%d", c2dev->id); if (unlikely(IS_ERR(c2dev->dev))) { @@ -924,6 +919,12 @@ struct c2port_device *c2port_device_register(char *name, c2dev->ops = ops; mutex_init(&c2dev->mutex); + /* Create binary file */ + c2port_bin_attrs.size = ops->blocks_num * ops->block_size; + ret = device_create_bin_file(c2dev->dev, &c2port_bin_attrs); + if (unlikely(ret)) + goto error_device_create_bin_file; + /* By default C2 port access is off */ c2dev->access = c2dev->flash_access = 0; ops->access(c2dev, 0); @@ -936,6 +937,9 @@ struct c2port_device *c2port_device_register(char *name, return c2dev; +error_device_create_bin_file: + device_destroy(c2port_class, 0); + error_device_create: spin_lock_irq(&c2port_idr_lock); idr_remove(&c2port_idr, c2dev->id); @@ -955,6 +959,7 @@ void c2port_device_unregister(struct c2port_device *c2dev) dev_info(c2dev->dev, "C2 port %s removed\n", c2dev->name); + device_remove_bin_file(c2dev->dev, &c2port_bin_attrs); spin_lock_irq(&c2port_idr_lock); idr_remove(&c2port_idr, c2dev->id); spin_unlock_irq(&c2port_idr_lock); @@ -980,7 +985,6 @@ static int __init c2port_init(void) return PTR_ERR(c2port_class); } c2port_class->dev_attrs = c2port_attrs; - c2port_class->dev_bin_attrs = c2port_bin_attrs; return 0; } From a332eeac4d196f927893b21f0d923b89cf545acc Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Jul 2013 15:05:04 -0700 Subject: [PATCH 0624/3400] misc: c2port: use dev_bin_attrs instead of hand-coding it Classes support a list of default binary attributes, so use that in the c2port driver, instead of hand creating and destroying the file, which is racing with userspace. Bonus is this removes lines of code. Cc: Rodolfo Giometti Signed-off-by: Greg Kroah-Hartman --- drivers/misc/c2port/core.c | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/drivers/misc/c2port/core.c b/drivers/misc/c2port/core.c index f32550a74bdd..a3b8370c7dea 100644 --- a/drivers/misc/c2port/core.c +++ b/drivers/misc/c2port/core.c @@ -867,14 +867,17 @@ static struct device_attribute c2port_attrs[] = { __ATTR_NULL, }; -static struct bin_attribute c2port_bin_attrs = { - .attr = { - .name = "flash_data", - .mode = 0644 +static struct bin_attribute c2port_bin_attrs[] = { + { + .attr = { + .name = "flash_data", + .mode = 0644 + }, + .read = c2port_read_flash_data, + .write = c2port_write_flash_data, + /* .size is computed at run-time */ }, - .read = c2port_read_flash_data, - .write = c2port_write_flash_data, - /* .size is computed at run-time */ + __ATTR_NULL }; /* @@ -907,6 +910,8 @@ struct c2port_device *c2port_device_register(char *name, goto error_idr_alloc; c2dev->id = ret; + c2port_bin_attrs[0].size = ops->blocks_num * ops->block_size; + c2dev->dev = device_create(c2port_class, NULL, 0, c2dev, "c2port%d", c2dev->id); if (unlikely(IS_ERR(c2dev->dev))) { @@ -919,12 +924,6 @@ struct c2port_device *c2port_device_register(char *name, c2dev->ops = ops; mutex_init(&c2dev->mutex); - /* Create binary file */ - c2port_bin_attrs.size = ops->blocks_num * ops->block_size; - ret = device_create_bin_file(c2dev->dev, &c2port_bin_attrs); - if (unlikely(ret)) - goto error_device_create_bin_file; - /* By default C2 port access is off */ c2dev->access = c2dev->flash_access = 0; ops->access(c2dev, 0); @@ -937,9 +936,6 @@ struct c2port_device *c2port_device_register(char *name, return c2dev; -error_device_create_bin_file: - device_destroy(c2port_class, 0); - error_device_create: spin_lock_irq(&c2port_idr_lock); idr_remove(&c2port_idr, c2dev->id); @@ -959,7 +955,6 @@ void c2port_device_unregister(struct c2port_device *c2dev) dev_info(c2dev->dev, "C2 port %s removed\n", c2dev->name); - device_remove_bin_file(c2dev->dev, &c2port_bin_attrs); spin_lock_irq(&c2port_idr_lock); idr_remove(&c2port_idr, c2dev->id); spin_unlock_irq(&c2port_idr_lock); @@ -985,6 +980,7 @@ static int __init c2port_init(void) return PTR_ERR(c2port_class); } c2port_class->dev_attrs = c2port_attrs; + c2port_class->dev_bin_attrs = c2port_bin_attrs; return 0; } From 62e13505b4eff7a0e94bdcb1f4fd76cbe4a96ff1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Jul 2013 15:05:06 -0700 Subject: [PATCH 0625/3400] bsr: convert bsr_class to use dev_groups The dev_attrs field of struct class is going away soon, dev_groups should be used instead. This converts the bsr bsr_class code to use the correct field. Cc: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/char/bsr.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/char/bsr.c b/drivers/char/bsr.c index 97467053a01b..0671e45daa57 100644 --- a/drivers/char/bsr.c +++ b/drivers/char/bsr.c @@ -95,6 +95,7 @@ bsr_size_show(struct device *dev, struct device_attribute *attr, char *buf) struct bsr_dev *bsr_dev = dev_get_drvdata(dev); return sprintf(buf, "%u\n", bsr_dev->bsr_bytes); } +static DEVICE_ATTR_RO(bsr_size); static ssize_t bsr_stride_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -102,20 +103,23 @@ bsr_stride_show(struct device *dev, struct device_attribute *attr, char *buf) struct bsr_dev *bsr_dev = dev_get_drvdata(dev); return sprintf(buf, "%u\n", bsr_dev->bsr_stride); } +static DEVICE_ATTR_RO(bsr_stride); static ssize_t -bsr_len_show(struct device *dev, struct device_attribute *attr, char *buf) +bsr_length_show(struct device *dev, struct device_attribute *attr, char *buf) { struct bsr_dev *bsr_dev = dev_get_drvdata(dev); return sprintf(buf, "%llu\n", bsr_dev->bsr_len); } +static DEVICE_ATTR_RO(bsr_length); -static struct device_attribute bsr_dev_attrs[] = { - __ATTR(bsr_size, S_IRUGO, bsr_size_show, NULL), - __ATTR(bsr_stride, S_IRUGO, bsr_stride_show, NULL), - __ATTR(bsr_length, S_IRUGO, bsr_len_show, NULL), - __ATTR_NULL +static struct attribute *bsr_dev_attrs[] = { + &dev_attr_bsr_size.attr, + &dev_attr_bsr_stride.attr, + &dev_attr_bsr_length.attr, + NULL, }; +ATTRIBUTE_GROUPS(bsr_dev); static int bsr_mmap(struct file *filp, struct vm_area_struct *vma) { @@ -308,7 +312,7 @@ static int __init bsr_init(void) ret = PTR_ERR(bsr_class); goto out_err_1; } - bsr_class->dev_attrs = bsr_dev_attrs; + bsr_class->dev_groups = bsr_dev_groups; ret = alloc_chrdev_region(&bsr_dev, 0, BSR_MAX_DEVS, "bsr"); bsr_major = MAJOR(bsr_dev); From e017a84b9397f50e22ba219d0b2875bf48a6573f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Jul 2013 15:05:07 -0700 Subject: [PATCH 0626/3400] tile: srom: convert srom_class to use dev_groups The dev_attrs field of struct class is going away soon, dev_groups should be used instead. This converts the tile srom_class code to use the correct field. Cc: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/char/tile-srom.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/char/tile-srom.c b/drivers/char/tile-srom.c index 7faeb1cde97d..344e97b91014 100644 --- a/drivers/char/tile-srom.c +++ b/drivers/char/tile-srom.c @@ -279,33 +279,37 @@ loff_t srom_llseek(struct file *file, loff_t offset, int origin) return fixed_size_llseek(file, offset, origin, srom->total_size); } -static ssize_t total_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t total_size_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct srom_dev *srom = dev_get_drvdata(dev); return sprintf(buf, "%u\n", srom->total_size); } +static DEVICE_ATTR_RO(total_size); -static ssize_t sector_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t sector_size_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct srom_dev *srom = dev_get_drvdata(dev); return sprintf(buf, "%u\n", srom->sector_size); } +static DEVICE_ATTR_RO(sector_size); -static ssize_t page_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t page_size_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct srom_dev *srom = dev_get_drvdata(dev); return sprintf(buf, "%u\n", srom->page_size); } +static DEVICE_ATTR_RO(page_size); -static struct device_attribute srom_dev_attrs[] = { - __ATTR(total_size, S_IRUGO, total_show, NULL), - __ATTR(sector_size, S_IRUGO, sector_show, NULL), - __ATTR(page_size, S_IRUGO, page_show, NULL), - __ATTR_NULL +static struct attribute srom_dev_attrs[] = { + &dev_attr_total_size.attr, + &dev_attr_sector_size.attr, + &dev_attr_page_size.attr, + NULL, }; +ATTRIBUTE_GROUPS(srom_dev); static char *srom_devnode(struct device *dev, umode_t *mode) { @@ -418,7 +422,7 @@ static int srom_init(void) result = PTR_ERR(srom_class); goto fail_cdev; } - srom_class->dev_attrs = srom_dev_attrs; + srom_class->dev_groups = srom_dev_groups; srom_class->devnode = srom_devnode; /* Do per-partition initialization */ From eb375597e2d456499bfa427fb398ab36bdc837e5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Jul 2013 15:05:15 -0700 Subject: [PATCH 0627/3400] c2port: convert class code to use dev_groups The dev_attrs field of struct class is going away soon, dev_groups should be used instead. This converts the c2port class code to use the correct field. Cc: Rodolfo Giometti Signed-off-by: Greg Kroah-Hartman --- drivers/misc/c2port/core.c | 50 ++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/drivers/misc/c2port/core.c b/drivers/misc/c2port/core.c index a3b8370c7dea..abe6e251e368 100644 --- a/drivers/misc/c2port/core.c +++ b/drivers/misc/c2port/core.c @@ -311,6 +311,7 @@ static ssize_t c2port_show_name(struct device *dev, return sprintf(buf, "%s\n", c2dev->name); } +static DEVICE_ATTR(name, 0444, c2port_show_name, NULL); static ssize_t c2port_show_flash_blocks_num(struct device *dev, struct device_attribute *attr, char *buf) @@ -320,6 +321,7 @@ static ssize_t c2port_show_flash_blocks_num(struct device *dev, return sprintf(buf, "%d\n", ops->blocks_num); } +static DEVICE_ATTR(flash_blocks_num, 0444, c2port_show_flash_blocks_num, NULL); static ssize_t c2port_show_flash_block_size(struct device *dev, struct device_attribute *attr, char *buf) @@ -329,6 +331,7 @@ static ssize_t c2port_show_flash_block_size(struct device *dev, return sprintf(buf, "%d\n", ops->block_size); } +static DEVICE_ATTR(flash_block_size, 0444, c2port_show_flash_block_size, NULL); static ssize_t c2port_show_flash_size(struct device *dev, struct device_attribute *attr, char *buf) @@ -338,18 +341,18 @@ static ssize_t c2port_show_flash_size(struct device *dev, return sprintf(buf, "%d\n", ops->blocks_num * ops->block_size); } +static DEVICE_ATTR(flash_size, 0444, c2port_show_flash_size, NULL); -static ssize_t c2port_show_access(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t access_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct c2port_device *c2dev = dev_get_drvdata(dev); return sprintf(buf, "%d\n", c2dev->access); } -static ssize_t c2port_store_access(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t access_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct c2port_device *c2dev = dev_get_drvdata(dev); struct c2port_ops *ops = c2dev->ops; @@ -375,6 +378,7 @@ static ssize_t c2port_store_access(struct device *dev, return count; } +static DEVICE_ATTR_RW(access); static ssize_t c2port_store_reset(struct device *dev, struct device_attribute *attr, @@ -395,6 +399,7 @@ static ssize_t c2port_store_reset(struct device *dev, return count; } +static DEVICE_ATTR(reset, 0200, NULL, c2port_store_reset); static ssize_t __c2port_show_dev_id(struct c2port_device *dev, char *buf) { @@ -431,6 +436,7 @@ static ssize_t c2port_show_dev_id(struct device *dev, return ret; } +static DEVICE_ATTR(dev_id, 0444, c2port_show_dev_id, NULL); static ssize_t __c2port_show_rev_id(struct c2port_device *dev, char *buf) { @@ -467,6 +473,7 @@ static ssize_t c2port_show_rev_id(struct device *dev, return ret; } +static DEVICE_ATTR(rev_id, 0444, c2port_show_rev_id, NULL); static ssize_t c2port_show_flash_access(struct device *dev, struct device_attribute *attr, char *buf) @@ -536,6 +543,8 @@ static ssize_t c2port_store_flash_access(struct device *dev, return count; } +static DEVICE_ATTR(flash_access, 0644, c2port_show_flash_access, + c2port_store_flash_access); static ssize_t __c2port_write_flash_erase(struct c2port_device *dev) { @@ -616,6 +625,7 @@ static ssize_t c2port_store_flash_erase(struct device *dev, return count; } +static DEVICE_ATTR(flash_erase, 0200, NULL, c2port_store_flash_erase); static ssize_t __c2port_read_flash_data(struct c2port_device *dev, char *buffer, loff_t offset, size_t count) @@ -850,22 +860,20 @@ static ssize_t c2port_write_flash_data(struct file *filp, struct kobject *kobj, /* * Class attributes */ - -static struct device_attribute c2port_attrs[] = { - __ATTR(name, 0444, c2port_show_name, NULL), - __ATTR(flash_blocks_num, 0444, c2port_show_flash_blocks_num, NULL), - __ATTR(flash_block_size, 0444, c2port_show_flash_block_size, NULL), - __ATTR(flash_size, 0444, c2port_show_flash_size, NULL), - __ATTR(access, 0644, c2port_show_access, c2port_store_access), - __ATTR(reset, 0200, NULL, c2port_store_reset), - __ATTR(dev_id, 0444, c2port_show_dev_id, NULL), - __ATTR(rev_id, 0444, c2port_show_rev_id, NULL), - - __ATTR(flash_access, 0644, c2port_show_flash_access, - c2port_store_flash_access), - __ATTR(flash_erase, 0200, NULL, c2port_store_flash_erase), - __ATTR_NULL, +static struct attribute *c2port_attrs[] = { + &dev_attr_name.attr, + &dev_attr_flash_blocks_num.attr, + &dev_attr_flash_block_size.attr, + &dev_attr_flash_size.attr, + &dev_attr_access.attr, + &dev_attr_reset.attr, + &dev_attr_dev_id.attr, + &dev_attr_rev_id.attr, + &dev_attr_flash_access.attr, + &dev_attr_flash_erase.attr, + NULL, }; +ATTRIBUTE_GROUPS(c2port); static struct bin_attribute c2port_bin_attrs[] = { { @@ -979,7 +987,7 @@ static int __init c2port_init(void) printk(KERN_ERR "c2port: failed to allocate class\n"); return PTR_ERR(c2port_class); } - c2port_class->dev_attrs = c2port_attrs; + c2port_class->dev_groups = c2port_groups; c2port_class->dev_bin_attrs = c2port_bin_attrs; return 0; From 899826f16a034f1ab6d23cd5b60cd113eaefad19 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Jul 2013 15:05:16 -0700 Subject: [PATCH 0628/3400] enclosure: convert class code to use dev_groups The dev_attrs field of struct class is going away soon, dev_groups should be used instead. This converts the enclosure class code to use the correct field. Cc: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/misc/enclosure.c | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/drivers/misc/enclosure.c b/drivers/misc/enclosure.c index 00e5fcac8fdf..0e8df41aaf14 100644 --- a/drivers/misc/enclosure.c +++ b/drivers/misc/enclosure.c @@ -239,7 +239,7 @@ static void enclosure_component_release(struct device *dev) put_device(dev->parent); } -static const struct attribute_group *enclosure_groups[]; +static const struct attribute_group *enclosure_component_groups[]; /** * enclosure_component_register - add a particular component to an enclosure @@ -282,7 +282,7 @@ enclosure_component_register(struct enclosure_device *edev, dev_set_name(cdev, "%u", number); cdev->release = enclosure_component_release; - cdev->groups = enclosure_groups; + cdev->groups = enclosure_component_groups; err = device_register(cdev); if (err) { @@ -365,25 +365,26 @@ EXPORT_SYMBOL_GPL(enclosure_remove_device); * sysfs pieces below */ -static ssize_t enclosure_show_components(struct device *cdev, - struct device_attribute *attr, - char *buf) +static ssize_t components_show(struct device *cdev, + struct device_attribute *attr, char *buf) { struct enclosure_device *edev = to_enclosure_device(cdev); return snprintf(buf, 40, "%d\n", edev->components); } +static DEVICE_ATTR_RO(components); -static struct device_attribute enclosure_attrs[] = { - __ATTR(components, S_IRUGO, enclosure_show_components, NULL), - __ATTR_NULL +static struct attribute *enclosure_class_attrs[] = { + &dev_attr_components.attr, + NULL, }; +ATTRIBUTE_GROUPS(enclosure_class); static struct class enclosure_class = { .name = "enclosure", .owner = THIS_MODULE, .dev_release = enclosure_release, - .dev_attrs = enclosure_attrs, + .dev_groups = enclosure_class_groups, }; static const char *const enclosure_status [] = { @@ -536,15 +537,7 @@ static struct attribute *enclosure_component_attrs[] = { &dev_attr_type.attr, NULL }; - -static struct attribute_group enclosure_group = { - .attrs = enclosure_component_attrs, -}; - -static const struct attribute_group *enclosure_groups[] = { - &enclosure_group, - NULL -}; +ATTRIBUTE_GROUPS(enclosure_component); static int __init enclosure_init(void) { From c9dce927e96c002856ac93b3a43115c33b6c1a74 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Jul 2013 15:05:23 -0700 Subject: [PATCH 0629/3400] UIO: convert class code to use dev_groups The dev_attrs field of struct class is going away soon, dev_groups should be used instead. This converts the uio class code to use the correct field. Cc: Hans J. Koch Signed-off-by: Greg Kroah-Hartman --- drivers/uio/uio.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c index 3b96f18593b3..170a178d661a 100644 --- a/drivers/uio/uio.c +++ b/drivers/uio/uio.c @@ -224,38 +224,42 @@ static struct kobj_type portio_attr_type = { .default_attrs = portio_attrs, }; -static ssize_t show_name(struct device *dev, +static ssize_t name_show(struct device *dev, struct device_attribute *attr, char *buf) { struct uio_device *idev = dev_get_drvdata(dev); return sprintf(buf, "%s\n", idev->info->name); } +static DEVICE_ATTR_RO(name); -static ssize_t show_version(struct device *dev, +static ssize_t version_show(struct device *dev, struct device_attribute *attr, char *buf) { struct uio_device *idev = dev_get_drvdata(dev); return sprintf(buf, "%s\n", idev->info->version); } +static DEVICE_ATTR_RO(version); -static ssize_t show_event(struct device *dev, +static ssize_t event_show(struct device *dev, struct device_attribute *attr, char *buf) { struct uio_device *idev = dev_get_drvdata(dev); return sprintf(buf, "%u\n", (unsigned int)atomic_read(&idev->event)); } +static DEVICE_ATTR_RO(event); -static struct device_attribute uio_class_attributes[] = { - __ATTR(name, S_IRUGO, show_name, NULL), - __ATTR(version, S_IRUGO, show_version, NULL), - __ATTR(event, S_IRUGO, show_event, NULL), - {} +static struct attribute *uio_attrs[] = { + &dev_attr_name.attr, + &dev_attr_version.attr, + &dev_attr_event.attr, + NULL, }; +ATTRIBUTE_GROUPS(uio); /* UIO class infrastructure */ static struct class uio_class = { .name = "uio", - .dev_attrs = uio_class_attributes, + .dev_groups = uio_groups, }; /* From e56341ad380114454119ac043e6d710ddbbb7710 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Jul 2013 15:05:25 -0700 Subject: [PATCH 0630/3400] staging: comedi: convert class code to use dev_groups The dev_attrs field of struct class is going away soon, dev_groups should be used instead. This converts the comedi class code to use the correct field. Cc: Ian Abbott Reviewed-by: H Hartley Sweeten Acked-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_fops.c | 39 ++++++++++++++-------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 8647518259f6..2f2ff8f08783 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -262,7 +262,7 @@ static int resize_async_buffer(struct comedi_device *dev, /* sysfs attribute files */ -static ssize_t show_max_read_buffer_kb(struct device *csdev, +static ssize_t max_read_buffer_kb_show(struct device *csdev, struct device_attribute *attr, char *buf) { unsigned int minor = MINOR(csdev->devt); @@ -283,7 +283,7 @@ static ssize_t show_max_read_buffer_kb(struct device *csdev, return snprintf(buf, PAGE_SIZE, "%i\n", size); } -static ssize_t store_max_read_buffer_kb(struct device *csdev, +static ssize_t max_read_buffer_kb_store(struct device *csdev, struct device_attribute *attr, const char *buf, size_t count) { @@ -314,8 +314,9 @@ static ssize_t store_max_read_buffer_kb(struct device *csdev, return err ? err : count; } +static DEVICE_ATTR_RW(max_read_buffer_kb); -static ssize_t show_read_buffer_kb(struct device *csdev, +static ssize_t read_buffer_kb_show(struct device *csdev, struct device_attribute *attr, char *buf) { unsigned int minor = MINOR(csdev->devt); @@ -336,7 +337,7 @@ static ssize_t show_read_buffer_kb(struct device *csdev, return snprintf(buf, PAGE_SIZE, "%i\n", size); } -static ssize_t store_read_buffer_kb(struct device *csdev, +static ssize_t read_buffer_kb_store(struct device *csdev, struct device_attribute *attr, const char *buf, size_t count) { @@ -367,8 +368,9 @@ static ssize_t store_read_buffer_kb(struct device *csdev, return err ? err : count; } +static DEVICE_ATTR_RW(read_buffer_kb); -static ssize_t show_max_write_buffer_kb(struct device *csdev, +static ssize_t max_write_buffer_kb_show(struct device *csdev, struct device_attribute *attr, char *buf) { @@ -390,7 +392,7 @@ static ssize_t show_max_write_buffer_kb(struct device *csdev, return snprintf(buf, PAGE_SIZE, "%i\n", size); } -static ssize_t store_max_write_buffer_kb(struct device *csdev, +static ssize_t max_write_buffer_kb_store(struct device *csdev, struct device_attribute *attr, const char *buf, size_t count) { @@ -421,8 +423,9 @@ static ssize_t store_max_write_buffer_kb(struct device *csdev, return err ? err : count; } +static DEVICE_ATTR_RW(max_write_buffer_kb); -static ssize_t show_write_buffer_kb(struct device *csdev, +static ssize_t write_buffer_kb_show(struct device *csdev, struct device_attribute *attr, char *buf) { unsigned int minor = MINOR(csdev->devt); @@ -443,7 +446,7 @@ static ssize_t show_write_buffer_kb(struct device *csdev, return snprintf(buf, PAGE_SIZE, "%i\n", size); } -static ssize_t store_write_buffer_kb(struct device *csdev, +static ssize_t write_buffer_kb_store(struct device *csdev, struct device_attribute *attr, const char *buf, size_t count) { @@ -474,18 +477,16 @@ static ssize_t store_write_buffer_kb(struct device *csdev, return err ? err : count; } +static DEVICE_ATTR_RW(write_buffer_kb); -static struct device_attribute comedi_dev_attrs[] = { - __ATTR(max_read_buffer_kb, S_IRUGO | S_IWUSR, - show_max_read_buffer_kb, store_max_read_buffer_kb), - __ATTR(read_buffer_kb, S_IRUGO | S_IWUSR | S_IWGRP, - show_read_buffer_kb, store_read_buffer_kb), - __ATTR(max_write_buffer_kb, S_IRUGO | S_IWUSR, - show_max_write_buffer_kb, store_max_write_buffer_kb), - __ATTR(write_buffer_kb, S_IRUGO | S_IWUSR | S_IWGRP, - show_write_buffer_kb, store_write_buffer_kb), - __ATTR_NULL +static struct attribute *comedi_dev_attrs[] = { + &dev_attr_max_read_buffer_kb.attr, + &dev_attr_read_buffer_kb.attr, + &dev_attr_max_write_buffer_kb.attr, + &dev_attr_write_buffer_kb.attr, + NULL, }; +ATTRIBUTE_GROUPS(comedi_dev); static void comedi_set_subdevice_runflags(struct comedi_subdevice *s, unsigned mask, unsigned bits) @@ -2554,7 +2555,7 @@ static int __init comedi_init(void) return PTR_ERR(comedi_class); } - comedi_class->dev_attrs = comedi_dev_attrs; + comedi_class->dev_groups = comedi_dev_groups; /* XXX requires /proc interface */ comedi_proc_init(); From ac3785d5c15922c8a4c6b9e050a5bc59895a6b9b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Jul 2013 15:05:37 -0700 Subject: [PATCH 0631/3400] c2port: convert class code to use bin_attrs in groups Now that attribute groups support binary attributes, use them instead of the dev_bin_attrs field in struct class, as that is going away soon. Cc: Rodolfo Giometti Signed-off-by: Greg Kroah-Hartman --- drivers/misc/c2port/core.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/drivers/misc/c2port/core.c b/drivers/misc/c2port/core.c index abe6e251e368..464419b36440 100644 --- a/drivers/misc/c2port/core.c +++ b/drivers/misc/c2port/core.c @@ -856,6 +856,9 @@ static ssize_t c2port_write_flash_data(struct file *filp, struct kobject *kobj, return ret; } +/* size is computed at run-time */ +static BIN_ATTR(flash_data, 0644, c2port_read_flash_data, + c2port_write_flash_data, 0); /* * Class attributes @@ -873,19 +876,20 @@ static struct attribute *c2port_attrs[] = { &dev_attr_flash_erase.attr, NULL, }; -ATTRIBUTE_GROUPS(c2port); -static struct bin_attribute c2port_bin_attrs[] = { - { - .attr = { - .name = "flash_data", - .mode = 0644 - }, - .read = c2port_read_flash_data, - .write = c2port_write_flash_data, - /* .size is computed at run-time */ - }, - __ATTR_NULL +static struct bin_attribute *c2port_bin_attrs[] = { + &bin_attr_flash_data, + NULL, +}; + +static const struct attribute_group c2port_group = { + .attrs = c2port_attrs, + .bin_attrs = c2port_bin_attrs, +}; + +static const struct attribute_group *c2port_groups[] = { + &c2port_group, + NULL, }; /* @@ -918,7 +922,7 @@ struct c2port_device *c2port_device_register(char *name, goto error_idr_alloc; c2dev->id = ret; - c2port_bin_attrs[0].size = ops->blocks_num * ops->block_size; + bin_attr_flash_data.size = ops->blocks_num * ops->block_size; c2dev->dev = device_create(c2port_class, NULL, 0, c2dev, "c2port%d", c2dev->id); @@ -988,7 +992,6 @@ static int __init c2port_init(void) return PTR_ERR(c2port_class); } c2port_class->dev_groups = c2port_groups; - c2port_class->dev_bin_attrs = c2port_bin_attrs; return 0; } From 10e232c597ac757e7f8600649f7e872e86de190f Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Fri, 28 Jun 2013 09:38:12 +0800 Subject: [PATCH 0632/3400] USB: check sg buffer size in usb_submit_urb USB spec stats that short packet can only appear at the end of transfer. Because lost of HC(EHCI/UHCI/OHCI/...) can't build a full packet from discontinuous buffers, we introduce the limit in usb_submit_urb() to avoid such kind of bad sg buffers coming from driver. The limit might be a bit strict: - platform has iommu to do sg list mapping - some host controllers may support to build full packet from discontinuous buffers. But considered that most of HCs don't support that, and driver need work well or keep consistent on different HCs and ARCHs, we have to introduce the limit. Currently, only usbtest is reported to pass such sg buffers to HC, and other users(mass storage, usbfs) don't have the problem. We don't check it on USB wireless device, because: - wireless devices can't be attached to common USB bus(EHCI/UHCI/OHCI/...) - the max packet size of endpoint may be odd, and often can't devide 4KB which is a typical usage in usb mass storage application Reported-by: Konstantin Filatov Reported-by: Denis V. Lunev Cc: Felipe Balbi Acked-by: Alan Stern Signed-off-by: Ming Lei Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/urb.c | 8 ++++++++ include/linux/usb.h | 4 +++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index 16927fa88fbd..e75115a04a2e 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -7,6 +7,7 @@ #include #include #include +#include #define to_urb(d) container_of(d, struct urb, kref) @@ -413,6 +414,13 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) urb->iso_frame_desc[n].status = -EXDEV; urb->iso_frame_desc[n].actual_length = 0; } + } else if (dev->speed != USB_SPEED_WIRELESS && urb->num_sgs) { + struct scatterlist *sg; + int i; + + for_each_sg(urb->sg, sg, urb->num_sgs - 1, i) + if (sg->length % max) + return -EINVAL; } /* the I/O buffer must be mapped/unmapped, except when length=0 */ diff --git a/include/linux/usb.h b/include/linux/usb.h index a232b7ece1f6..e99b2a114af4 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -1258,7 +1258,9 @@ typedef void (*usb_complete_t)(struct urb *); * the device driver is saying that it provided this DMA address, * which the host controller driver should use in preference to the * transfer_buffer. - * @sg: scatter gather buffer list + * @sg: scatter gather buffer list, the buffer size of each element in + * the list (except the last) must be divisible by the endpoint's + * max packet size * @num_mapped_sgs: (internal) number of mapped sg entries * @num_sgs: number of entries in the sg list * @transfer_buffer_length: How big is transfer_buffer. The transfer may From 1dd3d123239179fad5de5dc00a6e0014a1918fde Mon Sep 17 00:00:00 2001 From: Yuan-Hsin Chen Date: Wed, 19 Jun 2013 19:53:04 +0000 Subject: [PATCH 0633/3400] usb: host: Faraday fotg210-hcd driver FOTG210 is an OTG controller which can be configured as an USB2.0 host. FOTG210 host is an ehci-like controller with some differences. First, register layout of FOTG210 is incompatible with EHCI. Furthermore, FOTG210 is lack of siTDs which means iTDs are used for both HS and FS ISO transfer. Signed-off-by: Yuan-Hsin Chen Signed-off-by: Greg Kroah-Hartman --- drivers/usb/Makefile | 1 + drivers/usb/host/Kconfig | 12 + drivers/usb/host/Makefile | 1 + drivers/usb/host/fotg210-hcd.c | 6049 ++++++++++++++++++++++++++++++++ drivers/usb/host/fotg210.h | 750 ++++ 5 files changed, 6813 insertions(+) create mode 100644 drivers/usb/host/fotg210-hcd.c create mode 100644 drivers/usb/host/fotg210.h diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index 238c5d47cadb..5460abf045de 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_USB_ISP1760_HCD) += host/ obj-$(CONFIG_USB_IMX21_HCD) += host/ obj-$(CONFIG_USB_FSL_MPH_DR_OF) += host/ obj-$(CONFIG_USB_FUSBH200_HCD) += host/ +obj-$(CONFIG_USB_FOTG210_HCD) += host/ obj-$(CONFIG_USB_C67X00_HCD) += c67x00/ diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 4263d011392c..cf521d6551dd 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -354,6 +354,18 @@ config USB_FUSBH200_HCD To compile this driver as a module, choose M here: the module will be called fusbh200-hcd. +config USB_FOTG210_HCD + tristate "FOTG210 HCD support" + depends on USB + default N + ---help--- + Faraday FOTG210 is an OTG controller which can be configured as + an USB2.0 host. It is designed to meet USB2.0 EHCI specification + with minor modification. + + To compile this driver as a module, choose M here: the + module will be called fotg210-hcd. + config USB_OHCI_HCD tristate "OHCI HCD (USB 1.1) support" select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index bea71127b15f..829a3397882a 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -58,3 +58,4 @@ obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o obj-$(CONFIG_USB_HCD_BCMA) += bcma-hcd.o obj-$(CONFIG_USB_HCD_SSB) += ssb-hcd.o obj-$(CONFIG_USB_FUSBH200_HCD) += fusbh200-hcd.o +obj-$(CONFIG_USB_FOTG210_HCD) += fotg210-hcd.o diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c new file mode 100644 index 000000000000..fce13bcc4a3e --- /dev/null +++ b/drivers/usb/host/fotg210-hcd.c @@ -0,0 +1,6049 @@ +/* + * Faraday FOTG210 EHCI-like driver + * + * Copyright (c) 2013 Faraday Technology Corporation + * + * Author: Yuan-Hsin Chen + * Feng-Hsin Chiang + * Po-Yu Chuang + * + * Most of code borrowed from the Linux-3.7 EHCI 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 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/*-------------------------------------------------------------------------*/ +#define DRIVER_AUTHOR "Yuan-Hsin Chen" +#define DRIVER_DESC "FOTG210 Host Controller (EHCI) Driver" + +static const char hcd_name[] = "fotg210_hcd"; + +#undef VERBOSE_DEBUG +#undef FOTG210_URB_TRACE + +#ifdef DEBUG +#define FOTG210_STATS +#endif + +/* magic numbers that can affect system performance */ +#define FOTG210_TUNE_CERR 3 /* 0-3 qtd retries; 0 == don't stop */ +#define FOTG210_TUNE_RL_HS 4 /* nak throttle; see 4.9 */ +#define FOTG210_TUNE_RL_TT 0 +#define FOTG210_TUNE_MULT_HS 1 /* 1-3 transactions/uframe; 4.10.3 */ +#define FOTG210_TUNE_MULT_TT 1 +/* + * Some drivers think it's safe to schedule isochronous transfers more than + * 256 ms into the future (partly as a result of an old bug in the scheduling + * code). In an attempt to avoid trouble, we will use a minimum scheduling + * length of 512 frames instead of 256. + */ +#define FOTG210_TUNE_FLS 1 /* (medium) 512-frame schedule */ + +/* Initial IRQ latency: faster than hw default */ +static int log2_irq_thresh; /* 0 to 6 */ +module_param(log2_irq_thresh, int, S_IRUGO); +MODULE_PARM_DESC(log2_irq_thresh, "log2 IRQ latency, 1-64 microframes"); + +/* initial park setting: slower than hw default */ +static unsigned park; +module_param(park, uint, S_IRUGO); +MODULE_PARM_DESC(park, "park setting; 1-3 back-to-back async packets"); + +/* for link power management(LPM) feature */ +static unsigned int hird; +module_param(hird, int, S_IRUGO); +MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us"); + +#define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT) + +#include "fotg210.h" + +/*-------------------------------------------------------------------------*/ + +#define fotg210_dbg(fotg210, fmt, args...) \ + dev_dbg(fotg210_to_hcd(fotg210)->self.controller , fmt , ## args) +#define fotg210_err(fotg210, fmt, args...) \ + dev_err(fotg210_to_hcd(fotg210)->self.controller , fmt , ## args) +#define fotg210_info(fotg210, fmt, args...) \ + dev_info(fotg210_to_hcd(fotg210)->self.controller , fmt , ## args) +#define fotg210_warn(fotg210, fmt, args...) \ + dev_warn(fotg210_to_hcd(fotg210)->self.controller , fmt , ## args) + +#ifdef VERBOSE_DEBUG +# define fotg210_vdbg fotg210_dbg +#else + static inline void fotg210_vdbg(struct fotg210_hcd *fotg210, ...) {} +#endif + +#ifdef DEBUG + +/* check the values in the HCSPARAMS register + * (host controller _Structural_ parameters) + * see EHCI spec, Table 2-4 for each value + */ +static void dbg_hcs_params(struct fotg210_hcd *fotg210, char *label) +{ + u32 params = fotg210_readl(fotg210, &fotg210->caps->hcs_params); + + fotg210_dbg(fotg210, + "%s hcs_params 0x%x ports=%d\n", + label, params, + HCS_N_PORTS(params) + ); +} +#else + +static inline void dbg_hcs_params(struct fotg210_hcd *fotg210, char *label) {} + +#endif + +#ifdef DEBUG + +/* check the values in the HCCPARAMS register + * (host controller _Capability_ parameters) + * see EHCI Spec, Table 2-5 for each value + * */ +static void dbg_hcc_params(struct fotg210_hcd *fotg210, char *label) +{ + u32 params = fotg210_readl(fotg210, &fotg210->caps->hcc_params); + + fotg210_dbg(fotg210, + "%s hcc_params %04x uframes %s%s\n", + label, + params, + HCC_PGM_FRAMELISTLEN(params) ? "256/512/1024" : "1024", + HCC_CANPARK(params) ? " park" : ""); +} +#else + +static inline void dbg_hcc_params(struct fotg210_hcd *fotg210, char *label) {} + +#endif + +#ifdef DEBUG + +static void __maybe_unused +dbg_qtd(const char *label, struct fotg210_hcd *fotg210, struct fotg210_qtd *qtd) +{ + fotg210_dbg(fotg210, "%s td %p n%08x %08x t%08x p0=%08x\n", label, qtd, + hc32_to_cpup(fotg210, &qtd->hw_next), + hc32_to_cpup(fotg210, &qtd->hw_alt_next), + hc32_to_cpup(fotg210, &qtd->hw_token), + hc32_to_cpup(fotg210, &qtd->hw_buf[0])); + if (qtd->hw_buf[1]) + fotg210_dbg(fotg210, " p1=%08x p2=%08x p3=%08x p4=%08x\n", + hc32_to_cpup(fotg210, &qtd->hw_buf[1]), + hc32_to_cpup(fotg210, &qtd->hw_buf[2]), + hc32_to_cpup(fotg210, &qtd->hw_buf[3]), + hc32_to_cpup(fotg210, &qtd->hw_buf[4])); +} + +static void __maybe_unused +dbg_qh(const char *label, struct fotg210_hcd *fotg210, struct fotg210_qh *qh) +{ + struct fotg210_qh_hw *hw = qh->hw; + + fotg210_dbg(fotg210, "%s qh %p n%08x info %x %x qtd %x\n", label, + qh, hw->hw_next, hw->hw_info1, hw->hw_info2, hw->hw_current); + dbg_qtd("overlay", fotg210, (struct fotg210_qtd *) &hw->hw_qtd_next); +} + +static void __maybe_unused +dbg_itd(const char *label, struct fotg210_hcd *fotg210, struct fotg210_itd *itd) +{ + fotg210_dbg(fotg210, "%s[%d] itd %p, next %08x, urb %p\n", + label, itd->frame, itd, hc32_to_cpu(fotg210, itd->hw_next), + itd->urb); + fotg210_dbg(fotg210, + " trans: %08x %08x %08x %08x %08x %08x %08x %08x\n", + hc32_to_cpu(fotg210, itd->hw_transaction[0]), + hc32_to_cpu(fotg210, itd->hw_transaction[1]), + hc32_to_cpu(fotg210, itd->hw_transaction[2]), + hc32_to_cpu(fotg210, itd->hw_transaction[3]), + hc32_to_cpu(fotg210, itd->hw_transaction[4]), + hc32_to_cpu(fotg210, itd->hw_transaction[5]), + hc32_to_cpu(fotg210, itd->hw_transaction[6]), + hc32_to_cpu(fotg210, itd->hw_transaction[7])); + fotg210_dbg(fotg210, + " buf: %08x %08x %08x %08x %08x %08x %08x\n", + hc32_to_cpu(fotg210, itd->hw_bufp[0]), + hc32_to_cpu(fotg210, itd->hw_bufp[1]), + hc32_to_cpu(fotg210, itd->hw_bufp[2]), + hc32_to_cpu(fotg210, itd->hw_bufp[3]), + hc32_to_cpu(fotg210, itd->hw_bufp[4]), + hc32_to_cpu(fotg210, itd->hw_bufp[5]), + hc32_to_cpu(fotg210, itd->hw_bufp[6])); + fotg210_dbg(fotg210, " index: %d %d %d %d %d %d %d %d\n", + itd->index[0], itd->index[1], itd->index[2], + itd->index[3], itd->index[4], itd->index[5], + itd->index[6], itd->index[7]); +} + +static int __maybe_unused +dbg_status_buf(char *buf, unsigned len, const char *label, u32 status) +{ + return scnprintf(buf, len, + "%s%sstatus %04x%s%s%s%s%s%s%s%s%s%s", + label, label[0] ? " " : "", status, + (status & STS_ASS) ? " Async" : "", + (status & STS_PSS) ? " Periodic" : "", + (status & STS_RECL) ? " Recl" : "", + (status & STS_HALT) ? " Halt" : "", + (status & STS_IAA) ? " IAA" : "", + (status & STS_FATAL) ? " FATAL" : "", + (status & STS_FLR) ? " FLR" : "", + (status & STS_PCD) ? " PCD" : "", + (status & STS_ERR) ? " ERR" : "", + (status & STS_INT) ? " INT" : "" + ); +} + +static int __maybe_unused +dbg_intr_buf(char *buf, unsigned len, const char *label, u32 enable) +{ + return scnprintf(buf, len, + "%s%sintrenable %02x%s%s%s%s%s%s", + label, label[0] ? " " : "", enable, + (enable & STS_IAA) ? " IAA" : "", + (enable & STS_FATAL) ? " FATAL" : "", + (enable & STS_FLR) ? " FLR" : "", + (enable & STS_PCD) ? " PCD" : "", + (enable & STS_ERR) ? " ERR" : "", + (enable & STS_INT) ? " INT" : "" + ); +} + +static const char *const fls_strings[] = { "1024", "512", "256", "??" }; + +static int +dbg_command_buf(char *buf, unsigned len, const char *label, u32 command) +{ + return scnprintf(buf, len, + "%s%scommand %07x %s=%d ithresh=%d%s%s%s " + "period=%s%s %s", + label, label[0] ? " " : "", command, + (command & CMD_PARK) ? " park" : "(park)", + CMD_PARK_CNT(command), + (command >> 16) & 0x3f, + (command & CMD_IAAD) ? " IAAD" : "", + (command & CMD_ASE) ? " Async" : "", + (command & CMD_PSE) ? " Periodic" : "", + fls_strings[(command >> 2) & 0x3], + (command & CMD_RESET) ? " Reset" : "", + (command & CMD_RUN) ? "RUN" : "HALT" + ); +} + +static int +dbg_port_buf(char *buf, unsigned len, const char *label, int port, u32 status) +{ + char *sig; + + /* signaling state */ + switch (status & (3 << 10)) { + case 0 << 10: + sig = "se0"; + break; + case 1 << 10: + sig = "k"; + break; /* low speed */ + case 2 << 10: + sig = "j"; + break; + default: + sig = "?"; + break; + } + + return scnprintf(buf, len, + "%s%sport:%d status %06x %d " + "sig=%s%s%s%s%s%s%s%s", + label, label[0] ? " " : "", port, status, + status>>25,/*device address */ + sig, + (status & PORT_RESET) ? " RESET" : "", + (status & PORT_SUSPEND) ? " SUSPEND" : "", + (status & PORT_RESUME) ? " RESUME" : "", + (status & PORT_PEC) ? " PEC" : "", + (status & PORT_PE) ? " PE" : "", + (status & PORT_CSC) ? " CSC" : "", + (status & PORT_CONNECT) ? " CONNECT" : ""); +} + +#else +static inline void __maybe_unused +dbg_qh(char *label, struct fotg210_hcd *fotg210, struct fotg210_qh *qh) +{} + +static inline int __maybe_unused +dbg_status_buf(char *buf, unsigned len, const char *label, u32 status) +{ return 0; } + +static inline int __maybe_unused +dbg_command_buf(char *buf, unsigned len, const char *label, u32 command) +{ return 0; } + +static inline int __maybe_unused +dbg_intr_buf(char *buf, unsigned len, const char *label, u32 enable) +{ return 0; } + +static inline int __maybe_unused +dbg_port_buf(char *buf, unsigned len, const char *label, int port, u32 status) +{ return 0; } + +#endif /* DEBUG */ + +/* functions have the "wrong" filename when they're output... */ +#define dbg_status(fotg210, label, status) { \ + char _buf[80]; \ + dbg_status_buf(_buf, sizeof(_buf), label, status); \ + fotg210_dbg(fotg210, "%s\n", _buf); \ +} + +#define dbg_cmd(fotg210, label, command) { \ + char _buf[80]; \ + dbg_command_buf(_buf, sizeof(_buf), label, command); \ + fotg210_dbg(fotg210, "%s\n", _buf); \ +} + +#define dbg_port(fotg210, label, port, status) { \ + char _buf[80]; \ + dbg_port_buf(_buf, sizeof(_buf), label, port, status); \ + fotg210_dbg(fotg210, "%s\n", _buf); \ +} + +/*-------------------------------------------------------------------------*/ + +#ifdef STUB_DEBUG_FILES + +static inline void create_debug_files(struct fotg210_hcd *bus) { } +static inline void remove_debug_files(struct fotg210_hcd *bus) { } + +#else + +/* troubleshooting help: expose state in debugfs */ + +static int debug_async_open(struct inode *, struct file *); +static int debug_periodic_open(struct inode *, struct file *); +static int debug_registers_open(struct inode *, struct file *); +static int debug_async_open(struct inode *, struct file *); + +static ssize_t debug_output(struct file*, char __user*, size_t, loff_t*); +static int debug_close(struct inode *, struct file *); + +static const struct file_operations debug_async_fops = { + .owner = THIS_MODULE, + .open = debug_async_open, + .read = debug_output, + .release = debug_close, + .llseek = default_llseek, +}; +static const struct file_operations debug_periodic_fops = { + .owner = THIS_MODULE, + .open = debug_periodic_open, + .read = debug_output, + .release = debug_close, + .llseek = default_llseek, +}; +static const struct file_operations debug_registers_fops = { + .owner = THIS_MODULE, + .open = debug_registers_open, + .read = debug_output, + .release = debug_close, + .llseek = default_llseek, +}; + +static struct dentry *fotg210_debug_root; + +struct debug_buffer { + ssize_t (*fill_func)(struct debug_buffer *); /* fill method */ + struct usb_bus *bus; + struct mutex mutex; /* protect filling of buffer */ + size_t count; /* number of characters filled into buffer */ + char *output_buf; + size_t alloc_size; +}; + +#define speed_char(info1)({ char tmp; \ + switch (info1 & (3 << 12)) { \ + case QH_FULL_SPEED: \ + tmp = 'f'; break; \ + case QH_LOW_SPEED: \ + tmp = 'l'; break; \ + case QH_HIGH_SPEED: \ + tmp = 'h'; break; \ + default: \ + tmp = '?'; break; \ + }; tmp; }) + +static inline char token_mark(struct fotg210_hcd *fotg210, __hc32 token) +{ + __u32 v = hc32_to_cpu(fotg210, token); + + if (v & QTD_STS_ACTIVE) + return '*'; + if (v & QTD_STS_HALT) + return '-'; + if (!IS_SHORT_READ(v)) + return ' '; + /* tries to advance through hw_alt_next */ + return '/'; +} + +static void qh_lines( + struct fotg210_hcd *fotg210, + struct fotg210_qh *qh, + char **nextp, + unsigned *sizep +) +{ + u32 scratch; + u32 hw_curr; + struct fotg210_qtd *td; + unsigned temp; + unsigned size = *sizep; + char *next = *nextp; + char mark; + __le32 list_end = FOTG210_LIST_END(fotg210); + struct fotg210_qh_hw *hw = qh->hw; + + if (hw->hw_qtd_next == list_end) /* NEC does this */ + mark = '@'; + else + mark = token_mark(fotg210, hw->hw_token); + if (mark == '/') { /* qh_alt_next controls qh advance? */ + if ((hw->hw_alt_next & QTD_MASK(fotg210)) + == fotg210->async->hw->hw_alt_next) + mark = '#'; /* blocked */ + else if (hw->hw_alt_next == list_end) + mark = '.'; /* use hw_qtd_next */ + /* else alt_next points to some other qtd */ + } + scratch = hc32_to_cpup(fotg210, &hw->hw_info1); + hw_curr = (mark == '*') ? hc32_to_cpup(fotg210, &hw->hw_current) : 0; + temp = scnprintf(next, size, + "qh/%p dev%d %cs ep%d %08x %08x(%08x%c %s nak%d)", + qh, scratch & 0x007f, + speed_char(scratch), + (scratch >> 8) & 0x000f, + scratch, hc32_to_cpup(fotg210, &hw->hw_info2), + hc32_to_cpup(fotg210, &hw->hw_token), mark, + (cpu_to_hc32(fotg210, QTD_TOGGLE) & hw->hw_token) + ? "data1" : "data0", + (hc32_to_cpup(fotg210, &hw->hw_alt_next) >> 1) & 0x0f); + size -= temp; + next += temp; + + /* hc may be modifying the list as we read it ... */ + list_for_each_entry(td, &qh->qtd_list, qtd_list) { + scratch = hc32_to_cpup(fotg210, &td->hw_token); + mark = ' '; + if (hw_curr == td->qtd_dma) + mark = '*'; + else if (hw->hw_qtd_next == cpu_to_hc32(fotg210, td->qtd_dma)) + mark = '+'; + else if (QTD_LENGTH(scratch)) { + if (td->hw_alt_next == fotg210->async->hw->hw_alt_next) + mark = '#'; + else if (td->hw_alt_next != list_end) + mark = '/'; + } + temp = snprintf(next, size, + "\n\t%p%c%s len=%d %08x urb %p", + td, mark, ({ char *tmp; + switch ((scratch>>8)&0x03) { + case 0: + tmp = "out"; + break; + case 1: + tmp = "in"; + break; + case 2: + tmp = "setup"; + break; + default: + tmp = "?"; + break; + } tmp; }), + (scratch >> 16) & 0x7fff, + scratch, + td->urb); + if (size < temp) + temp = size; + size -= temp; + next += temp; + if (temp == size) + goto done; + } + + temp = snprintf(next, size, "\n"); + if (size < temp) + temp = size; + size -= temp; + next += temp; + +done: + *sizep = size; + *nextp = next; +} + +static ssize_t fill_async_buffer(struct debug_buffer *buf) +{ + struct usb_hcd *hcd; + struct fotg210_hcd *fotg210; + unsigned long flags; + unsigned temp, size; + char *next; + struct fotg210_qh *qh; + + hcd = bus_to_hcd(buf->bus); + fotg210 = hcd_to_fotg210(hcd); + next = buf->output_buf; + size = buf->alloc_size; + + *next = 0; + + /* dumps a snapshot of the async schedule. + * usually empty except for long-term bulk reads, or head. + * one QH per line, and TDs we know about + */ + spin_lock_irqsave(&fotg210->lock, flags); + for (qh = fotg210->async->qh_next.qh; size > 0 && qh; + qh = qh->qh_next.qh) + qh_lines(fotg210, qh, &next, &size); + if (fotg210->async_unlink && size > 0) { + temp = scnprintf(next, size, "\nunlink =\n"); + size -= temp; + next += temp; + + for (qh = fotg210->async_unlink; size > 0 && qh; + qh = qh->unlink_next) + qh_lines(fotg210, qh, &next, &size); + } + spin_unlock_irqrestore(&fotg210->lock, flags); + + return strlen(buf->output_buf); +} + +#define DBG_SCHED_LIMIT 64 +static ssize_t fill_periodic_buffer(struct debug_buffer *buf) +{ + struct usb_hcd *hcd; + struct fotg210_hcd *fotg210; + unsigned long flags; + union fotg210_shadow p, *seen; + unsigned temp, size, seen_count; + char *next; + unsigned i; + __hc32 tag; + + seen = kmalloc(DBG_SCHED_LIMIT * sizeof(*seen), GFP_ATOMIC); + if (!seen) + return 0; + seen_count = 0; + + hcd = bus_to_hcd(buf->bus); + fotg210 = hcd_to_fotg210(hcd); + next = buf->output_buf; + size = buf->alloc_size; + + temp = scnprintf(next, size, "size = %d\n", fotg210->periodic_size); + size -= temp; + next += temp; + + /* dump a snapshot of the periodic schedule. + * iso changes, interrupt usually doesn't. + */ + spin_lock_irqsave(&fotg210->lock, flags); + for (i = 0; i < fotg210->periodic_size; i++) { + p = fotg210->pshadow[i]; + if (likely(!p.ptr)) + continue; + tag = Q_NEXT_TYPE(fotg210, fotg210->periodic[i]); + + temp = scnprintf(next, size, "%4d: ", i); + size -= temp; + next += temp; + + do { + struct fotg210_qh_hw *hw; + + switch (hc32_to_cpu(fotg210, tag)) { + case Q_TYPE_QH: + hw = p.qh->hw; + temp = scnprintf(next, size, " qh%d-%04x/%p", + p.qh->period, + hc32_to_cpup(fotg210, + &hw->hw_info2) + /* uframe masks */ + & (QH_CMASK | QH_SMASK), + p.qh); + size -= temp; + next += temp; + /* don't repeat what follows this qh */ + for (temp = 0; temp < seen_count; temp++) { + if (seen[temp].ptr != p.ptr) + continue; + if (p.qh->qh_next.ptr) { + temp = scnprintf(next, size, + " ..."); + size -= temp; + next += temp; + } + break; + } + /* show more info the first time around */ + if (temp == seen_count) { + u32 scratch = hc32_to_cpup(fotg210, + &hw->hw_info1); + struct fotg210_qtd *qtd; + char *type = ""; + + /* count tds, get ep direction */ + temp = 0; + list_for_each_entry(qtd, + &p.qh->qtd_list, + qtd_list) { + temp++; + switch (0x03 & (hc32_to_cpu( + fotg210, + qtd->hw_token) >> 8)) { + case 0: + type = "out"; + continue; + case 1: + type = "in"; + continue; + } + } + + temp = scnprintf(next, size, + "(%c%d ep%d%s " + "[%d/%d] q%d p%d)", + speed_char(scratch), + scratch & 0x007f, + (scratch >> 8) & 0x000f, type, + p.qh->usecs, p.qh->c_usecs, + temp, + 0x7ff & (scratch >> 16)); + + if (seen_count < DBG_SCHED_LIMIT) + seen[seen_count++].qh = p.qh; + } else + temp = 0; + tag = Q_NEXT_TYPE(fotg210, hw->hw_next); + p = p.qh->qh_next; + break; + case Q_TYPE_FSTN: + temp = scnprintf(next, size, + " fstn-%8x/%p", p.fstn->hw_prev, + p.fstn); + tag = Q_NEXT_TYPE(fotg210, p.fstn->hw_next); + p = p.fstn->fstn_next; + break; + case Q_TYPE_ITD: + temp = scnprintf(next, size, + " itd/%p", p.itd); + tag = Q_NEXT_TYPE(fotg210, p.itd->hw_next); + p = p.itd->itd_next; + break; + } + size -= temp; + next += temp; + } while (p.ptr); + + temp = scnprintf(next, size, "\n"); + size -= temp; + next += temp; + } + spin_unlock_irqrestore(&fotg210->lock, flags); + kfree(seen); + + return buf->alloc_size - size; +} +#undef DBG_SCHED_LIMIT + +static const char *rh_state_string(struct fotg210_hcd *fotg210) +{ + switch (fotg210->rh_state) { + case FOTG210_RH_HALTED: + return "halted"; + case FOTG210_RH_SUSPENDED: + return "suspended"; + case FOTG210_RH_RUNNING: + return "running"; + case FOTG210_RH_STOPPING: + return "stopping"; + } + return "?"; +} + +static ssize_t fill_registers_buffer(struct debug_buffer *buf) +{ + struct usb_hcd *hcd; + struct fotg210_hcd *fotg210; + unsigned long flags; + unsigned temp, size, i; + char *next, scratch[80]; + static const char fmt[] = "%*s\n"; + static const char label[] = ""; + + hcd = bus_to_hcd(buf->bus); + fotg210 = hcd_to_fotg210(hcd); + next = buf->output_buf; + size = buf->alloc_size; + + spin_lock_irqsave(&fotg210->lock, flags); + + if (!HCD_HW_ACCESSIBLE(hcd)) { + size = scnprintf(next, size, + "bus %s, device %s\n" + "%s\n" + "SUSPENDED(no register access)\n", + hcd->self.controller->bus->name, + dev_name(hcd->self.controller), + hcd->product_desc); + goto done; + } + + /* Capability Registers */ + i = HC_VERSION(fotg210, fotg210_readl(fotg210, + &fotg210->caps->hc_capbase)); + temp = scnprintf(next, size, + "bus %s, device %s\n" + "%s\n" + "EHCI %x.%02x, rh state %s\n", + hcd->self.controller->bus->name, + dev_name(hcd->self.controller), + hcd->product_desc, + i >> 8, i & 0x0ff, rh_state_string(fotg210)); + size -= temp; + next += temp; + + /* FIXME interpret both types of params */ + i = fotg210_readl(fotg210, &fotg210->caps->hcs_params); + temp = scnprintf(next, size, "structural params 0x%08x\n", i); + size -= temp; + next += temp; + + i = fotg210_readl(fotg210, &fotg210->caps->hcc_params); + temp = scnprintf(next, size, "capability params 0x%08x\n", i); + size -= temp; + next += temp; + + /* Operational Registers */ + temp = dbg_status_buf(scratch, sizeof(scratch), label, + fotg210_readl(fotg210, &fotg210->regs->status)); + temp = scnprintf(next, size, fmt, temp, scratch); + size -= temp; + next += temp; + + temp = dbg_command_buf(scratch, sizeof(scratch), label, + fotg210_readl(fotg210, &fotg210->regs->command)); + temp = scnprintf(next, size, fmt, temp, scratch); + size -= temp; + next += temp; + + temp = dbg_intr_buf(scratch, sizeof(scratch), label, + fotg210_readl(fotg210, &fotg210->regs->intr_enable)); + temp = scnprintf(next, size, fmt, temp, scratch); + size -= temp; + next += temp; + + temp = scnprintf(next, size, "uframe %04x\n", + fotg210_read_frame_index(fotg210)); + size -= temp; + next += temp; + + if (fotg210->async_unlink) { + temp = scnprintf(next, size, "async unlink qh %p\n", + fotg210->async_unlink); + size -= temp; + next += temp; + } + +#ifdef FOTG210_STATS + temp = scnprintf(next, size, + "irq normal %ld err %ld iaa %ld(lost %ld)\n", + fotg210->stats.normal, fotg210->stats.error, fotg210->stats.iaa, + fotg210->stats.lost_iaa); + size -= temp; + next += temp; + + temp = scnprintf(next, size, "complete %ld unlink %ld\n", + fotg210->stats.complete, fotg210->stats.unlink); + size -= temp; + next += temp; +#endif + +done: + spin_unlock_irqrestore(&fotg210->lock, flags); + + return buf->alloc_size - size; +} + +static struct debug_buffer *alloc_buffer(struct usb_bus *bus, + ssize_t (*fill_func)(struct debug_buffer *)) +{ + struct debug_buffer *buf; + + buf = kzalloc(sizeof(struct debug_buffer), GFP_KERNEL); + + if (buf) { + buf->bus = bus; + buf->fill_func = fill_func; + mutex_init(&buf->mutex); + buf->alloc_size = PAGE_SIZE; + } + + return buf; +} + +static int fill_buffer(struct debug_buffer *buf) +{ + int ret = 0; + + if (!buf->output_buf) + buf->output_buf = vmalloc(buf->alloc_size); + + if (!buf->output_buf) { + ret = -ENOMEM; + goto out; + } + + ret = buf->fill_func(buf); + + if (ret >= 0) { + buf->count = ret; + ret = 0; + } + +out: + return ret; +} + +static ssize_t debug_output(struct file *file, char __user *user_buf, + size_t len, loff_t *offset) +{ + struct debug_buffer *buf = file->private_data; + int ret = 0; + + mutex_lock(&buf->mutex); + if (buf->count == 0) { + ret = fill_buffer(buf); + if (ret != 0) { + mutex_unlock(&buf->mutex); + goto out; + } + } + mutex_unlock(&buf->mutex); + + ret = simple_read_from_buffer(user_buf, len, offset, + buf->output_buf, buf->count); + +out: + return ret; + +} + +static int debug_close(struct inode *inode, struct file *file) +{ + struct debug_buffer *buf = file->private_data; + + if (buf) { + vfree(buf->output_buf); + kfree(buf); + } + + return 0; +} +static int debug_async_open(struct inode *inode, struct file *file) +{ + file->private_data = alloc_buffer(inode->i_private, fill_async_buffer); + + return file->private_data ? 0 : -ENOMEM; +} + +static int debug_periodic_open(struct inode *inode, struct file *file) +{ + struct debug_buffer *buf; + buf = alloc_buffer(inode->i_private, fill_periodic_buffer); + if (!buf) + return -ENOMEM; + + buf->alloc_size = (sizeof(void *) == 4 ? 6 : 8)*PAGE_SIZE; + file->private_data = buf; + return 0; +} + +static int debug_registers_open(struct inode *inode, struct file *file) +{ + file->private_data = alloc_buffer(inode->i_private, + fill_registers_buffer); + + return file->private_data ? 0 : -ENOMEM; +} + +static inline void create_debug_files(struct fotg210_hcd *fotg210) +{ + struct usb_bus *bus = &fotg210_to_hcd(fotg210)->self; + + fotg210->debug_dir = debugfs_create_dir(bus->bus_name, + fotg210_debug_root); + if (!fotg210->debug_dir) + return; + + if (!debugfs_create_file("async", S_IRUGO, fotg210->debug_dir, bus, + &debug_async_fops)) + goto file_error; + + if (!debugfs_create_file("periodic", S_IRUGO, fotg210->debug_dir, bus, + &debug_periodic_fops)) + goto file_error; + + if (!debugfs_create_file("registers", S_IRUGO, fotg210->debug_dir, bus, + &debug_registers_fops)) + goto file_error; + + return; + +file_error: + debugfs_remove_recursive(fotg210->debug_dir); +} + +static inline void remove_debug_files(struct fotg210_hcd *fotg210) +{ + debugfs_remove_recursive(fotg210->debug_dir); +} + +#endif /* STUB_DEBUG_FILES */ +/*-------------------------------------------------------------------------*/ + +/* + * handshake - spin reading hc until handshake completes or fails + * @ptr: address of hc register to be read + * @mask: bits to look at in result of read + * @done: value of those bits when handshake succeeds + * @usec: timeout in microseconds + * + * Returns negative errno, or zero on success + * + * Success happens when the "mask" bits have the specified value (hardware + * handshake done). There are two failure modes: "usec" have passed (major + * hardware flakeout), or the register reads as all-ones (hardware removed). + * + * That last failure should_only happen in cases like physical cardbus eject + * before driver shutdown. But it also seems to be caused by bugs in cardbus + * bridge shutdown: shutting down the bridge before the devices using it. + */ +static int handshake(struct fotg210_hcd *fotg210, void __iomem *ptr, + u32 mask, u32 done, int usec) +{ + u32 result; + + do { + result = fotg210_readl(fotg210, ptr); + if (result == ~(u32)0) /* card removed */ + return -ENODEV; + result &= mask; + if (result == done) + return 0; + udelay(1); + usec--; + } while (usec > 0); + return -ETIMEDOUT; +} + +/* + * Force HC to halt state from unknown (EHCI spec section 2.3). + * Must be called with interrupts enabled and the lock not held. + */ +static int fotg210_halt(struct fotg210_hcd *fotg210) +{ + u32 temp; + + spin_lock_irq(&fotg210->lock); + + /* disable any irqs left enabled by previous code */ + fotg210_writel(fotg210, 0, &fotg210->regs->intr_enable); + + /* + * This routine gets called during probe before fotg210->command + * has been initialized, so we can't rely on its value. + */ + fotg210->command &= ~CMD_RUN; + temp = fotg210_readl(fotg210, &fotg210->regs->command); + temp &= ~(CMD_RUN | CMD_IAAD); + fotg210_writel(fotg210, temp, &fotg210->regs->command); + + spin_unlock_irq(&fotg210->lock); + synchronize_irq(fotg210_to_hcd(fotg210)->irq); + + return handshake(fotg210, &fotg210->regs->status, + STS_HALT, STS_HALT, 16 * 125); +} + +/* + * Reset a non-running (STS_HALT == 1) controller. + * Must be called with interrupts enabled and the lock not held. + */ +static int fotg210_reset(struct fotg210_hcd *fotg210) +{ + int retval; + u32 command = fotg210_readl(fotg210, &fotg210->regs->command); + + /* If the EHCI debug controller is active, special care must be + * taken before and after a host controller reset */ + if (fotg210->debug && !dbgp_reset_prep(fotg210_to_hcd(fotg210))) + fotg210->debug = NULL; + + command |= CMD_RESET; + dbg_cmd(fotg210, "reset", command); + fotg210_writel(fotg210, command, &fotg210->regs->command); + fotg210->rh_state = FOTG210_RH_HALTED; + fotg210->next_statechange = jiffies; + retval = handshake(fotg210, &fotg210->regs->command, + CMD_RESET, 0, 250 * 1000); + + if (retval) + return retval; + + if (fotg210->debug) + dbgp_external_startup(fotg210_to_hcd(fotg210)); + + fotg210->port_c_suspend = fotg210->suspended_ports = + fotg210->resuming_ports = 0; + return retval; +} + +/* + * Idle the controller (turn off the schedules). + * Must be called with interrupts enabled and the lock not held. + */ +static void fotg210_quiesce(struct fotg210_hcd *fotg210) +{ + u32 temp; + + if (fotg210->rh_state != FOTG210_RH_RUNNING) + return; + + /* wait for any schedule enables/disables to take effect */ + temp = (fotg210->command << 10) & (STS_ASS | STS_PSS); + handshake(fotg210, &fotg210->regs->status, STS_ASS | STS_PSS, temp, + 16 * 125); + + /* then disable anything that's still active */ + spin_lock_irq(&fotg210->lock); + fotg210->command &= ~(CMD_ASE | CMD_PSE); + fotg210_writel(fotg210, fotg210->command, &fotg210->regs->command); + spin_unlock_irq(&fotg210->lock); + + /* hardware can take 16 microframes to turn off ... */ + handshake(fotg210, &fotg210->regs->status, STS_ASS | STS_PSS, 0, + 16 * 125); +} + +/*-------------------------------------------------------------------------*/ + +static void end_unlink_async(struct fotg210_hcd *fotg210); +static void unlink_empty_async(struct fotg210_hcd *fotg210); +static void fotg210_work(struct fotg210_hcd *fotg210); +static void start_unlink_intr(struct fotg210_hcd *fotg210, + struct fotg210_qh *qh); +static void end_unlink_intr(struct fotg210_hcd *fotg210, struct fotg210_qh *qh); + +/*-------------------------------------------------------------------------*/ + +/* Set a bit in the USBCMD register */ +static void fotg210_set_command_bit(struct fotg210_hcd *fotg210, u32 bit) +{ + fotg210->command |= bit; + fotg210_writel(fotg210, fotg210->command, &fotg210->regs->command); + + /* unblock posted write */ + fotg210_readl(fotg210, &fotg210->regs->command); +} + +/* Clear a bit in the USBCMD register */ +static void fotg210_clear_command_bit(struct fotg210_hcd *fotg210, u32 bit) +{ + fotg210->command &= ~bit; + fotg210_writel(fotg210, fotg210->command, &fotg210->regs->command); + + /* unblock posted write */ + fotg210_readl(fotg210, &fotg210->regs->command); +} + +/*-------------------------------------------------------------------------*/ + +/* + * EHCI timer support... Now using hrtimers. + * + * Lots of different events are triggered from fotg210->hrtimer. Whenever + * the timer routine runs, it checks each possible event; events that are + * currently enabled and whose expiration time has passed get handled. + * The set of enabled events is stored as a collection of bitflags in + * fotg210->enabled_hrtimer_events, and they are numbered in order of + * increasing delay values (ranging between 1 ms and 100 ms). + * + * Rather than implementing a sorted list or tree of all pending events, + * we keep track only of the lowest-numbered pending event, in + * fotg210->next_hrtimer_event. Whenever fotg210->hrtimer gets restarted, its + * expiration time is set to the timeout value for this event. + * + * As a result, events might not get handled right away; the actual delay + * could be anywhere up to twice the requested delay. This doesn't + * matter, because none of the events are especially time-critical. The + * ones that matter most all have a delay of 1 ms, so they will be + * handled after 2 ms at most, which is okay. In addition to this, we + * allow for an expiration range of 1 ms. + */ + +/* + * Delay lengths for the hrtimer event types. + * Keep this list sorted by delay length, in the same order as + * the event types indexed by enum fotg210_hrtimer_event in fotg210.h. + */ +static unsigned event_delays_ns[] = { + 1 * NSEC_PER_MSEC, /* FOTG210_HRTIMER_POLL_ASS */ + 1 * NSEC_PER_MSEC, /* FOTG210_HRTIMER_POLL_PSS */ + 1 * NSEC_PER_MSEC, /* FOTG210_HRTIMER_POLL_DEAD */ + 1125 * NSEC_PER_USEC, /* FOTG210_HRTIMER_UNLINK_INTR */ + 2 * NSEC_PER_MSEC, /* FOTG210_HRTIMER_FREE_ITDS */ + 6 * NSEC_PER_MSEC, /* FOTG210_HRTIMER_ASYNC_UNLINKS */ + 10 * NSEC_PER_MSEC, /* FOTG210_HRTIMER_IAA_WATCHDOG */ + 10 * NSEC_PER_MSEC, /* FOTG210_HRTIMER_DISABLE_PERIODIC */ + 15 * NSEC_PER_MSEC, /* FOTG210_HRTIMER_DISABLE_ASYNC */ + 100 * NSEC_PER_MSEC, /* FOTG210_HRTIMER_IO_WATCHDOG */ +}; + +/* Enable a pending hrtimer event */ +static void fotg210_enable_event(struct fotg210_hcd *fotg210, unsigned event, + bool resched) +{ + ktime_t *timeout = &fotg210->hr_timeouts[event]; + + if (resched) + *timeout = ktime_add(ktime_get(), + ktime_set(0, event_delays_ns[event])); + fotg210->enabled_hrtimer_events |= (1 << event); + + /* Track only the lowest-numbered pending event */ + if (event < fotg210->next_hrtimer_event) { + fotg210->next_hrtimer_event = event; + hrtimer_start_range_ns(&fotg210->hrtimer, *timeout, + NSEC_PER_MSEC, HRTIMER_MODE_ABS); + } +} + + +/* Poll the STS_ASS status bit; see when it agrees with CMD_ASE */ +static void fotg210_poll_ASS(struct fotg210_hcd *fotg210) +{ + unsigned actual, want; + + /* Don't enable anything if the controller isn't running (e.g., died) */ + if (fotg210->rh_state != FOTG210_RH_RUNNING) + return; + + want = (fotg210->command & CMD_ASE) ? STS_ASS : 0; + actual = fotg210_readl(fotg210, &fotg210->regs->status) & STS_ASS; + + if (want != actual) { + + /* Poll again later, but give up after about 20 ms */ + if (fotg210->ASS_poll_count++ < 20) { + fotg210_enable_event(fotg210, FOTG210_HRTIMER_POLL_ASS, + true); + return; + } + fotg210_dbg(fotg210, "Waited too long for the async schedule status (%x/%x), giving up\n", + want, actual); + } + fotg210->ASS_poll_count = 0; + + /* The status is up-to-date; restart or stop the schedule as needed */ + if (want == 0) { /* Stopped */ + if (fotg210->async_count > 0) + fotg210_set_command_bit(fotg210, CMD_ASE); + + } else { /* Running */ + if (fotg210->async_count == 0) { + + /* Turn off the schedule after a while */ + fotg210_enable_event(fotg210, + FOTG210_HRTIMER_DISABLE_ASYNC, + true); + } + } +} + +/* Turn off the async schedule after a brief delay */ +static void fotg210_disable_ASE(struct fotg210_hcd *fotg210) +{ + fotg210_clear_command_bit(fotg210, CMD_ASE); +} + + +/* Poll the STS_PSS status bit; see when it agrees with CMD_PSE */ +static void fotg210_poll_PSS(struct fotg210_hcd *fotg210) +{ + unsigned actual, want; + + /* Don't do anything if the controller isn't running (e.g., died) */ + if (fotg210->rh_state != FOTG210_RH_RUNNING) + return; + + want = (fotg210->command & CMD_PSE) ? STS_PSS : 0; + actual = fotg210_readl(fotg210, &fotg210->regs->status) & STS_PSS; + + if (want != actual) { + + /* Poll again later, but give up after about 20 ms */ + if (fotg210->PSS_poll_count++ < 20) { + fotg210_enable_event(fotg210, FOTG210_HRTIMER_POLL_PSS, + true); + return; + } + fotg210_dbg(fotg210, "Waited too long for the periodic schedule status (%x/%x), giving up\n", + want, actual); + } + fotg210->PSS_poll_count = 0; + + /* The status is up-to-date; restart or stop the schedule as needed */ + if (want == 0) { /* Stopped */ + if (fotg210->periodic_count > 0) + fotg210_set_command_bit(fotg210, CMD_PSE); + + } else { /* Running */ + if (fotg210->periodic_count == 0) { + + /* Turn off the schedule after a while */ + fotg210_enable_event(fotg210, + FOTG210_HRTIMER_DISABLE_PERIODIC, + true); + } + } +} + +/* Turn off the periodic schedule after a brief delay */ +static void fotg210_disable_PSE(struct fotg210_hcd *fotg210) +{ + fotg210_clear_command_bit(fotg210, CMD_PSE); +} + + +/* Poll the STS_HALT status bit; see when a dead controller stops */ +static void fotg210_handle_controller_death(struct fotg210_hcd *fotg210) +{ + if (!(fotg210_readl(fotg210, &fotg210->regs->status) & STS_HALT)) { + + /* Give up after a few milliseconds */ + if (fotg210->died_poll_count++ < 5) { + /* Try again later */ + fotg210_enable_event(fotg210, + FOTG210_HRTIMER_POLL_DEAD, true); + return; + } + fotg210_warn(fotg210, "Waited too long for the controller to stop, giving up\n"); + } + + /* Clean up the mess */ + fotg210->rh_state = FOTG210_RH_HALTED; + fotg210_writel(fotg210, 0, &fotg210->regs->intr_enable); + fotg210_work(fotg210); + end_unlink_async(fotg210); + + /* Not in process context, so don't try to reset the controller */ +} + + +/* Handle unlinked interrupt QHs once they are gone from the hardware */ +static void fotg210_handle_intr_unlinks(struct fotg210_hcd *fotg210) +{ + bool stopped = (fotg210->rh_state < FOTG210_RH_RUNNING); + + /* + * Process all the QHs on the intr_unlink list that were added + * before the current unlink cycle began. The list is in + * temporal order, so stop when we reach the first entry in the + * current cycle. But if the root hub isn't running then + * process all the QHs on the list. + */ + fotg210->intr_unlinking = true; + while (fotg210->intr_unlink) { + struct fotg210_qh *qh = fotg210->intr_unlink; + + if (!stopped && qh->unlink_cycle == fotg210->intr_unlink_cycle) + break; + fotg210->intr_unlink = qh->unlink_next; + qh->unlink_next = NULL; + end_unlink_intr(fotg210, qh); + } + + /* Handle remaining entries later */ + if (fotg210->intr_unlink) { + fotg210_enable_event(fotg210, FOTG210_HRTIMER_UNLINK_INTR, + true); + ++fotg210->intr_unlink_cycle; + } + fotg210->intr_unlinking = false; +} + + +/* Start another free-iTDs/siTDs cycle */ +static void start_free_itds(struct fotg210_hcd *fotg210) +{ + if (!(fotg210->enabled_hrtimer_events & + BIT(FOTG210_HRTIMER_FREE_ITDS))) { + fotg210->last_itd_to_free = list_entry( + fotg210->cached_itd_list.prev, + struct fotg210_itd, itd_list); + fotg210_enable_event(fotg210, FOTG210_HRTIMER_FREE_ITDS, true); + } +} + +/* Wait for controller to stop using old iTDs and siTDs */ +static void end_free_itds(struct fotg210_hcd *fotg210) +{ + struct fotg210_itd *itd, *n; + + if (fotg210->rh_state < FOTG210_RH_RUNNING) + fotg210->last_itd_to_free = NULL; + + list_for_each_entry_safe(itd, n, &fotg210->cached_itd_list, itd_list) { + list_del(&itd->itd_list); + dma_pool_free(fotg210->itd_pool, itd, itd->itd_dma); + if (itd == fotg210->last_itd_to_free) + break; + } + + if (!list_empty(&fotg210->cached_itd_list)) + start_free_itds(fotg210); +} + + +/* Handle lost (or very late) IAA interrupts */ +static void fotg210_iaa_watchdog(struct fotg210_hcd *fotg210) +{ + if (fotg210->rh_state != FOTG210_RH_RUNNING) + return; + + /* + * Lost IAA irqs wedge things badly; seen first with a vt8235. + * So we need this watchdog, but must protect it against both + * (a) SMP races against real IAA firing and retriggering, and + * (b) clean HC shutdown, when IAA watchdog was pending. + */ + if (fotg210->async_iaa) { + u32 cmd, status; + + /* If we get here, IAA is *REALLY* late. It's barely + * conceivable that the system is so busy that CMD_IAAD + * is still legitimately set, so let's be sure it's + * clear before we read STS_IAA. (The HC should clear + * CMD_IAAD when it sets STS_IAA.) + */ + cmd = fotg210_readl(fotg210, &fotg210->regs->command); + + /* + * If IAA is set here it either legitimately triggered + * after the watchdog timer expired (_way_ late, so we'll + * still count it as lost) ... or a silicon erratum: + * - VIA seems to set IAA without triggering the IRQ; + * - IAAD potentially cleared without setting IAA. + */ + status = fotg210_readl(fotg210, &fotg210->regs->status); + if ((status & STS_IAA) || !(cmd & CMD_IAAD)) { + COUNT(fotg210->stats.lost_iaa); + fotg210_writel(fotg210, STS_IAA, + &fotg210->regs->status); + } + + fotg210_vdbg(fotg210, "IAA watchdog: status %x cmd %x\n", + status, cmd); + end_unlink_async(fotg210); + } +} + + +/* Enable the I/O watchdog, if appropriate */ +static void turn_on_io_watchdog(struct fotg210_hcd *fotg210) +{ + /* Not needed if the controller isn't running or it's already enabled */ + if (fotg210->rh_state != FOTG210_RH_RUNNING || + (fotg210->enabled_hrtimer_events & + BIT(FOTG210_HRTIMER_IO_WATCHDOG))) + return; + + /* + * Isochronous transfers always need the watchdog. + * For other sorts we use it only if the flag is set. + */ + if (fotg210->isoc_count > 0 || (fotg210->need_io_watchdog && + fotg210->async_count + fotg210->intr_count > 0)) + fotg210_enable_event(fotg210, FOTG210_HRTIMER_IO_WATCHDOG, + true); +} + + +/* + * Handler functions for the hrtimer event types. + * Keep this array in the same order as the event types indexed by + * enum fotg210_hrtimer_event in fotg210.h. + */ +static void (*event_handlers[])(struct fotg210_hcd *) = { + fotg210_poll_ASS, /* FOTG210_HRTIMER_POLL_ASS */ + fotg210_poll_PSS, /* FOTG210_HRTIMER_POLL_PSS */ + fotg210_handle_controller_death, /* FOTG210_HRTIMER_POLL_DEAD */ + fotg210_handle_intr_unlinks, /* FOTG210_HRTIMER_UNLINK_INTR */ + end_free_itds, /* FOTG210_HRTIMER_FREE_ITDS */ + unlink_empty_async, /* FOTG210_HRTIMER_ASYNC_UNLINKS */ + fotg210_iaa_watchdog, /* FOTG210_HRTIMER_IAA_WATCHDOG */ + fotg210_disable_PSE, /* FOTG210_HRTIMER_DISABLE_PERIODIC */ + fotg210_disable_ASE, /* FOTG210_HRTIMER_DISABLE_ASYNC */ + fotg210_work, /* FOTG210_HRTIMER_IO_WATCHDOG */ +}; + +static enum hrtimer_restart fotg210_hrtimer_func(struct hrtimer *t) +{ + struct fotg210_hcd *fotg210 = + container_of(t, struct fotg210_hcd, hrtimer); + ktime_t now; + unsigned long events; + unsigned long flags; + unsigned e; + + spin_lock_irqsave(&fotg210->lock, flags); + + events = fotg210->enabled_hrtimer_events; + fotg210->enabled_hrtimer_events = 0; + fotg210->next_hrtimer_event = FOTG210_HRTIMER_NO_EVENT; + + /* + * Check each pending event. If its time has expired, handle + * the event; otherwise re-enable it. + */ + now = ktime_get(); + for_each_set_bit(e, &events, FOTG210_HRTIMER_NUM_EVENTS) { + if (now.tv64 >= fotg210->hr_timeouts[e].tv64) + event_handlers[e](fotg210); + else + fotg210_enable_event(fotg210, e, false); + } + + spin_unlock_irqrestore(&fotg210->lock, flags); + return HRTIMER_NORESTART; +} + +/*-------------------------------------------------------------------------*/ + +#define fotg210_bus_suspend NULL +#define fotg210_bus_resume NULL + +/*-------------------------------------------------------------------------*/ + +static int check_reset_complete( + struct fotg210_hcd *fotg210, + int index, + u32 __iomem *status_reg, + int port_status +) { + if (!(port_status & PORT_CONNECT)) + return port_status; + + /* if reset finished and it's still not enabled -- handoff */ + if (!(port_status & PORT_PE)) { + /* with integrated TT, there's nobody to hand it to! */ + fotg210_dbg(fotg210, + "Failed to enable port %d on root hub TT\n", + index+1); + return port_status; + } else { + fotg210_dbg(fotg210, "port %d reset complete, port enabled\n", + index + 1); + } + + return port_status; +} + +/*-------------------------------------------------------------------------*/ + + +/* build "status change" packet (one or two bytes) from HC registers */ + +static int +fotg210_hub_status_data(struct usb_hcd *hcd, char *buf) +{ + struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); + u32 temp, status; + u32 mask; + int retval = 1; + unsigned long flags; + + /* init status to no-changes */ + buf[0] = 0; + + /* Inform the core about resumes-in-progress by returning + * a non-zero value even if there are no status changes. + */ + status = fotg210->resuming_ports; + + mask = PORT_CSC | PORT_PEC; + /* PORT_RESUME from hardware ~= PORT_STAT_C_SUSPEND */ + + /* no hub change reports (bit 0) for now (power, ...) */ + + /* port N changes (bit N)? */ + spin_lock_irqsave(&fotg210->lock, flags); + + temp = fotg210_readl(fotg210, &fotg210->regs->port_status); + + /* + * Return status information even for ports with OWNER set. + * Otherwise khubd wouldn't see the disconnect event when a + * high-speed device is switched over to the companion + * controller by the user. + */ + + if ((temp & mask) != 0 || test_bit(0, &fotg210->port_c_suspend) + || (fotg210->reset_done[0] && time_after_eq( + jiffies, fotg210->reset_done[0]))) { + buf[0] |= 1 << 1; + status = STS_PCD; + } + /* FIXME autosuspend idle root hubs */ + spin_unlock_irqrestore(&fotg210->lock, flags); + return status ? retval : 0; +} + +/*-------------------------------------------------------------------------*/ + +static void +fotg210_hub_descriptor( + struct fotg210_hcd *fotg210, + struct usb_hub_descriptor *desc +) { + int ports = HCS_N_PORTS(fotg210->hcs_params); + u16 temp; + + desc->bDescriptorType = 0x29; + desc->bPwrOn2PwrGood = 10; /* fotg210 1.0, 2.3.9 says 20ms max */ + desc->bHubContrCurrent = 0; + + desc->bNbrPorts = ports; + temp = 1 + (ports / 8); + desc->bDescLength = 7 + 2 * temp; + + /* two bitmaps: ports removable, and usb 1.0 legacy PortPwrCtrlMask */ + memset(&desc->u.hs.DeviceRemovable[0], 0, temp); + memset(&desc->u.hs.DeviceRemovable[temp], 0xff, temp); + + temp = 0x0008; /* per-port overcurrent reporting */ + temp |= 0x0002; /* no power switching */ + desc->wHubCharacteristics = cpu_to_le16(temp); +} + +/*-------------------------------------------------------------------------*/ + +static int fotg210_hub_control( + struct usb_hcd *hcd, + u16 typeReq, + u16 wValue, + u16 wIndex, + char *buf, + u16 wLength +) { + struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); + int ports = HCS_N_PORTS(fotg210->hcs_params); + u32 __iomem *status_reg = &fotg210->regs->port_status; + u32 temp, temp1, status; + unsigned long flags; + int retval = 0; + unsigned selector; + + /* + * FIXME: support SetPortFeatures USB_PORT_FEAT_INDICATOR. + * HCS_INDICATOR may say we can change LEDs to off/amber/green. + * (track current state ourselves) ... blink for diagnostics, + * power, "this is the one", etc. EHCI spec supports this. + */ + + spin_lock_irqsave(&fotg210->lock, flags); + switch (typeReq) { + case ClearHubFeature: + switch (wValue) { + case C_HUB_LOCAL_POWER: + case C_HUB_OVER_CURRENT: + /* no hub-wide feature/status flags */ + break; + default: + goto error; + } + break; + case ClearPortFeature: + if (!wIndex || wIndex > ports) + goto error; + wIndex--; + temp = fotg210_readl(fotg210, status_reg); + temp &= ~PORT_RWC_BITS; + + /* + * Even if OWNER is set, so the port is owned by the + * companion controller, khubd needs to be able to clear + * the port-change status bits (especially + * USB_PORT_STAT_C_CONNECTION). + */ + + switch (wValue) { + case USB_PORT_FEAT_ENABLE: + fotg210_writel(fotg210, temp & ~PORT_PE, status_reg); + break; + case USB_PORT_FEAT_C_ENABLE: + fotg210_writel(fotg210, temp | PORT_PEC, status_reg); + break; + case USB_PORT_FEAT_SUSPEND: + if (temp & PORT_RESET) + goto error; + if (!(temp & PORT_SUSPEND)) + break; + if ((temp & PORT_PE) == 0) + goto error; + + /* resume signaling for 20 msec */ + fotg210_writel(fotg210, temp | PORT_RESUME, status_reg); + fotg210->reset_done[wIndex] = jiffies + + msecs_to_jiffies(20); + break; + case USB_PORT_FEAT_C_SUSPEND: + clear_bit(wIndex, &fotg210->port_c_suspend); + break; + case USB_PORT_FEAT_C_CONNECTION: + fotg210_writel(fotg210, temp | PORT_CSC, status_reg); + break; + case USB_PORT_FEAT_C_OVER_CURRENT: + fotg210_writel(fotg210, temp | OTGISR_OVC, + &fotg210->regs->otgisr); + break; + case USB_PORT_FEAT_C_RESET: + /* GetPortStatus clears reset */ + break; + default: + goto error; + } + fotg210_readl(fotg210, &fotg210->regs->command); + break; + case GetHubDescriptor: + fotg210_hub_descriptor(fotg210, (struct usb_hub_descriptor *) + buf); + break; + case GetHubStatus: + /* no hub-wide feature/status flags */ + memset(buf, 0, 4); + /*cpu_to_le32s ((u32 *) buf); */ + break; + case GetPortStatus: + if (!wIndex || wIndex > ports) + goto error; + wIndex--; + status = 0; + temp = fotg210_readl(fotg210, status_reg); + + /* wPortChange bits */ + if (temp & PORT_CSC) + status |= USB_PORT_STAT_C_CONNECTION << 16; + if (temp & PORT_PEC) + status |= USB_PORT_STAT_C_ENABLE << 16; + + temp1 = fotg210_readl(fotg210, &fotg210->regs->otgisr); + if (temp1 & OTGISR_OVC) + status |= USB_PORT_STAT_C_OVERCURRENT << 16; + + /* whoever resumes must GetPortStatus to complete it!! */ + if (temp & PORT_RESUME) { + + /* Remote Wakeup received? */ + if (!fotg210->reset_done[wIndex]) { + /* resume signaling for 20 msec */ + fotg210->reset_done[wIndex] = jiffies + + msecs_to_jiffies(20); + /* check the port again */ + mod_timer(&fotg210_to_hcd(fotg210)->rh_timer, + fotg210->reset_done[wIndex]); + } + + /* resume completed? */ + else if (time_after_eq(jiffies, + fotg210->reset_done[wIndex])) { + clear_bit(wIndex, &fotg210->suspended_ports); + set_bit(wIndex, &fotg210->port_c_suspend); + fotg210->reset_done[wIndex] = 0; + + /* stop resume signaling */ + temp = fotg210_readl(fotg210, status_reg); + fotg210_writel(fotg210, + temp & ~(PORT_RWC_BITS | PORT_RESUME), + status_reg); + clear_bit(wIndex, &fotg210->resuming_ports); + retval = handshake(fotg210, status_reg, + PORT_RESUME, 0, 2000 /* 2msec */); + if (retval != 0) { + fotg210_err(fotg210, + "port %d resume error %d\n", + wIndex + 1, retval); + goto error; + } + temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10)); + } + } + + /* whoever resets must GetPortStatus to complete it!! */ + if ((temp & PORT_RESET) + && time_after_eq(jiffies, + fotg210->reset_done[wIndex])) { + status |= USB_PORT_STAT_C_RESET << 16; + fotg210->reset_done[wIndex] = 0; + clear_bit(wIndex, &fotg210->resuming_ports); + + /* force reset to complete */ + fotg210_writel(fotg210, + temp & ~(PORT_RWC_BITS | PORT_RESET), + status_reg); + /* REVISIT: some hardware needs 550+ usec to clear + * this bit; seems too long to spin routinely... + */ + retval = handshake(fotg210, status_reg, + PORT_RESET, 0, 1000); + if (retval != 0) { + fotg210_err(fotg210, "port %d reset error %d\n", + wIndex + 1, retval); + goto error; + } + + /* see what we found out */ + temp = check_reset_complete(fotg210, wIndex, status_reg, + fotg210_readl(fotg210, status_reg)); + } + + if (!(temp & (PORT_RESUME|PORT_RESET))) { + fotg210->reset_done[wIndex] = 0; + clear_bit(wIndex, &fotg210->resuming_ports); + } + + /* transfer dedicated ports to the companion hc */ + if ((temp & PORT_CONNECT) && + test_bit(wIndex, &fotg210->companion_ports)) { + temp &= ~PORT_RWC_BITS; + fotg210_writel(fotg210, temp, status_reg); + fotg210_dbg(fotg210, "port %d --> companion\n", + wIndex + 1); + temp = fotg210_readl(fotg210, status_reg); + } + + /* + * Even if OWNER is set, there's no harm letting khubd + * see the wPortStatus values (they should all be 0 except + * for PORT_POWER anyway). + */ + + if (temp & PORT_CONNECT) { + status |= USB_PORT_STAT_CONNECTION; + status |= fotg210_port_speed(fotg210, temp); + } + if (temp & PORT_PE) + status |= USB_PORT_STAT_ENABLE; + + /* maybe the port was unsuspended without our knowledge */ + if (temp & (PORT_SUSPEND|PORT_RESUME)) { + status |= USB_PORT_STAT_SUSPEND; + } else if (test_bit(wIndex, &fotg210->suspended_ports)) { + clear_bit(wIndex, &fotg210->suspended_ports); + clear_bit(wIndex, &fotg210->resuming_ports); + fotg210->reset_done[wIndex] = 0; + if (temp & PORT_PE) + set_bit(wIndex, &fotg210->port_c_suspend); + } + + temp1 = fotg210_readl(fotg210, &fotg210->regs->otgisr); + if (temp1 & OTGISR_OVC) + status |= USB_PORT_STAT_OVERCURRENT; + if (temp & PORT_RESET) + status |= USB_PORT_STAT_RESET; + if (test_bit(wIndex, &fotg210->port_c_suspend)) + status |= USB_PORT_STAT_C_SUSPEND << 16; + +#ifndef VERBOSE_DEBUG + if (status & ~0xffff) /* only if wPortChange is interesting */ +#endif + dbg_port(fotg210, "GetStatus", wIndex + 1, temp); + put_unaligned_le32(status, buf); + break; + case SetHubFeature: + switch (wValue) { + case C_HUB_LOCAL_POWER: + case C_HUB_OVER_CURRENT: + /* no hub-wide feature/status flags */ + break; + default: + goto error; + } + break; + case SetPortFeature: + selector = wIndex >> 8; + wIndex &= 0xff; + + if (!wIndex || wIndex > ports) + goto error; + wIndex--; + temp = fotg210_readl(fotg210, status_reg); + temp &= ~PORT_RWC_BITS; + switch (wValue) { + case USB_PORT_FEAT_SUSPEND: + if ((temp & PORT_PE) == 0 + || (temp & PORT_RESET) != 0) + goto error; + + /* After above check the port must be connected. + * Set appropriate bit thus could put phy into low power + * mode if we have hostpc feature + */ + fotg210_writel(fotg210, temp | PORT_SUSPEND, + status_reg); + set_bit(wIndex, &fotg210->suspended_ports); + break; + case USB_PORT_FEAT_RESET: + if (temp & PORT_RESUME) + goto error; + /* line status bits may report this as low speed, + * which can be fine if this root hub has a + * transaction translator built in. + */ + fotg210_vdbg(fotg210, "port %d reset\n", wIndex + 1); + temp |= PORT_RESET; + temp &= ~PORT_PE; + + /* + * caller must wait, then call GetPortStatus + * usb 2.0 spec says 50 ms resets on root + */ + fotg210->reset_done[wIndex] = jiffies + + msecs_to_jiffies(50); + fotg210_writel(fotg210, temp, status_reg); + break; + + /* For downstream facing ports (these): one hub port is put + * into test mode according to USB2 11.24.2.13, then the hub + * must be reset (which for root hub now means rmmod+modprobe, + * or else system reboot). See EHCI 2.3.9 and 4.14 for info + * about the EHCI-specific stuff. + */ + case USB_PORT_FEAT_TEST: + if (!selector || selector > 5) + goto error; + spin_unlock_irqrestore(&fotg210->lock, flags); + fotg210_quiesce(fotg210); + spin_lock_irqsave(&fotg210->lock, flags); + + /* Put all enabled ports into suspend */ + temp = fotg210_readl(fotg210, status_reg) & + ~PORT_RWC_BITS; + if (temp & PORT_PE) + fotg210_writel(fotg210, temp | PORT_SUSPEND, + status_reg); + + spin_unlock_irqrestore(&fotg210->lock, flags); + fotg210_halt(fotg210); + spin_lock_irqsave(&fotg210->lock, flags); + + temp = fotg210_readl(fotg210, status_reg); + temp |= selector << 16; + fotg210_writel(fotg210, temp, status_reg); + break; + + default: + goto error; + } + fotg210_readl(fotg210, &fotg210->regs->command); + break; + + default: +error: + /* "stall" on error */ + retval = -EPIPE; + } + spin_unlock_irqrestore(&fotg210->lock, flags); + return retval; +} + +static void __maybe_unused fotg210_relinquish_port(struct usb_hcd *hcd, + int portnum) +{ + return; +} + +static int __maybe_unused fotg210_port_handed_over(struct usb_hcd *hcd, + int portnum) +{ + return 0; +} +/*-------------------------------------------------------------------------*/ +/* + * There's basically three types of memory: + * - data used only by the HCD ... kmalloc is fine + * - async and periodic schedules, shared by HC and HCD ... these + * need to use dma_pool or dma_alloc_coherent + * - driver buffers, read/written by HC ... single shot DMA mapped + * + * There's also "register" data (e.g. PCI or SOC), which is memory mapped. + * No memory seen by this driver is pageable. + */ + +/*-------------------------------------------------------------------------*/ + +/* Allocate the key transfer structures from the previously allocated pool */ + +static inline void fotg210_qtd_init(struct fotg210_hcd *fotg210, + struct fotg210_qtd *qtd, dma_addr_t dma) +{ + memset(qtd, 0, sizeof(*qtd)); + qtd->qtd_dma = dma; + qtd->hw_token = cpu_to_hc32(fotg210, QTD_STS_HALT); + qtd->hw_next = FOTG210_LIST_END(fotg210); + qtd->hw_alt_next = FOTG210_LIST_END(fotg210); + INIT_LIST_HEAD(&qtd->qtd_list); +} + +static struct fotg210_qtd *fotg210_qtd_alloc(struct fotg210_hcd *fotg210, + gfp_t flags) +{ + struct fotg210_qtd *qtd; + dma_addr_t dma; + + qtd = dma_pool_alloc(fotg210->qtd_pool, flags, &dma); + if (qtd != NULL) + fotg210_qtd_init(fotg210, qtd, dma); + + return qtd; +} + +static inline void fotg210_qtd_free(struct fotg210_hcd *fotg210, + struct fotg210_qtd *qtd) +{ + dma_pool_free(fotg210->qtd_pool, qtd, qtd->qtd_dma); +} + + +static void qh_destroy(struct fotg210_hcd *fotg210, struct fotg210_qh *qh) +{ + /* clean qtds first, and know this is not linked */ + if (!list_empty(&qh->qtd_list) || qh->qh_next.ptr) { + fotg210_dbg(fotg210, "unused qh not empty!\n"); + BUG(); + } + if (qh->dummy) + fotg210_qtd_free(fotg210, qh->dummy); + dma_pool_free(fotg210->qh_pool, qh->hw, qh->qh_dma); + kfree(qh); +} + +static struct fotg210_qh *fotg210_qh_alloc(struct fotg210_hcd *fotg210, + gfp_t flags) +{ + struct fotg210_qh *qh; + dma_addr_t dma; + + qh = kzalloc(sizeof(*qh), GFP_ATOMIC); + if (!qh) + goto done; + qh->hw = (struct fotg210_qh_hw *) + dma_pool_alloc(fotg210->qh_pool, flags, &dma); + if (!qh->hw) + goto fail; + memset(qh->hw, 0, sizeof(*qh->hw)); + qh->qh_dma = dma; + INIT_LIST_HEAD(&qh->qtd_list); + + /* dummy td enables safe urb queuing */ + qh->dummy = fotg210_qtd_alloc(fotg210, flags); + if (qh->dummy == NULL) { + fotg210_dbg(fotg210, "no dummy td\n"); + goto fail1; + } +done: + return qh; +fail1: + dma_pool_free(fotg210->qh_pool, qh->hw, qh->qh_dma); +fail: + kfree(qh); + return NULL; +} + +/*-------------------------------------------------------------------------*/ + +/* The queue heads and transfer descriptors are managed from pools tied + * to each of the "per device" structures. + * This is the initialisation and cleanup code. + */ + +static void fotg210_mem_cleanup(struct fotg210_hcd *fotg210) +{ + if (fotg210->async) + qh_destroy(fotg210, fotg210->async); + fotg210->async = NULL; + + if (fotg210->dummy) + qh_destroy(fotg210, fotg210->dummy); + fotg210->dummy = NULL; + + /* DMA consistent memory and pools */ + if (fotg210->qtd_pool) + dma_pool_destroy(fotg210->qtd_pool); + fotg210->qtd_pool = NULL; + + if (fotg210->qh_pool) { + dma_pool_destroy(fotg210->qh_pool); + fotg210->qh_pool = NULL; + } + + if (fotg210->itd_pool) + dma_pool_destroy(fotg210->itd_pool); + fotg210->itd_pool = NULL; + + if (fotg210->periodic) + dma_free_coherent(fotg210_to_hcd(fotg210)->self.controller, + fotg210->periodic_size * sizeof(u32), + fotg210->periodic, fotg210->periodic_dma); + fotg210->periodic = NULL; + + /* shadow periodic table */ + kfree(fotg210->pshadow); + fotg210->pshadow = NULL; +} + +/* remember to add cleanup code (above) if you add anything here */ +static int fotg210_mem_init(struct fotg210_hcd *fotg210, gfp_t flags) +{ + int i; + + /* QTDs for control/bulk/intr transfers */ + fotg210->qtd_pool = dma_pool_create("fotg210_qtd", + fotg210_to_hcd(fotg210)->self.controller, + sizeof(struct fotg210_qtd), + 32 /* byte alignment (for hw parts) */, + 4096 /* can't cross 4K */); + if (!fotg210->qtd_pool) + goto fail; + + /* QHs for control/bulk/intr transfers */ + fotg210->qh_pool = dma_pool_create("fotg210_qh", + fotg210_to_hcd(fotg210)->self.controller, + sizeof(struct fotg210_qh_hw), + 32 /* byte alignment (for hw parts) */, + 4096 /* can't cross 4K */); + if (!fotg210->qh_pool) + goto fail; + + fotg210->async = fotg210_qh_alloc(fotg210, flags); + if (!fotg210->async) + goto fail; + + /* ITD for high speed ISO transfers */ + fotg210->itd_pool = dma_pool_create("fotg210_itd", + fotg210_to_hcd(fotg210)->self.controller, + sizeof(struct fotg210_itd), + 64 /* byte alignment (for hw parts) */, + 4096 /* can't cross 4K */); + if (!fotg210->itd_pool) + goto fail; + + /* Hardware periodic table */ + fotg210->periodic = (__le32 *) + dma_alloc_coherent(fotg210_to_hcd(fotg210)->self.controller, + fotg210->periodic_size * sizeof(__le32), + &fotg210->periodic_dma, 0); + if (fotg210->periodic == NULL) + goto fail; + + for (i = 0; i < fotg210->periodic_size; i++) + fotg210->periodic[i] = FOTG210_LIST_END(fotg210); + + /* software shadow of hardware table */ + fotg210->pshadow = kcalloc(fotg210->periodic_size, sizeof(void *), + flags); + if (fotg210->pshadow != NULL) + return 0; + +fail: + fotg210_dbg(fotg210, "couldn't init memory\n"); + fotg210_mem_cleanup(fotg210); + return -ENOMEM; +} +/*-------------------------------------------------------------------------*/ +/* + * EHCI hardware queue manipulation ... the core. QH/QTD manipulation. + * + * Control, bulk, and interrupt traffic all use "qh" lists. They list "qtd" + * entries describing USB transactions, max 16-20kB/entry (with 4kB-aligned + * buffers needed for the larger number). We use one QH per endpoint, queue + * multiple urbs (all three types) per endpoint. URBs may need several qtds. + * + * ISO traffic uses "ISO TD" (itd) records, and (along with + * interrupts) needs careful scheduling. Performance improvements can be + * an ongoing challenge. That's in "ehci-sched.c". + * + * USB 1.1 devices are handled (a) by "companion" OHCI or UHCI root hubs, + * or otherwise through transaction translators (TTs) in USB 2.0 hubs using + * (b) special fields in qh entries or (c) split iso entries. TTs will + * buffer low/full speed data so the host collects it at high speed. + */ + +/*-------------------------------------------------------------------------*/ + +/* fill a qtd, returning how much of the buffer we were able to queue up */ + +static int +qtd_fill(struct fotg210_hcd *fotg210, struct fotg210_qtd *qtd, dma_addr_t buf, + size_t len, int token, int maxpacket) +{ + int i, count; + u64 addr = buf; + + /* one buffer entry per 4K ... first might be short or unaligned */ + qtd->hw_buf[0] = cpu_to_hc32(fotg210, (u32)addr); + qtd->hw_buf_hi[0] = cpu_to_hc32(fotg210, (u32)(addr >> 32)); + count = 0x1000 - (buf & 0x0fff); /* rest of that page */ + if (likely(len < count)) /* ... iff needed */ + count = len; + else { + buf += 0x1000; + buf &= ~0x0fff; + + /* per-qtd limit: from 16K to 20K (best alignment) */ + for (i = 1; count < len && i < 5; i++) { + addr = buf; + qtd->hw_buf[i] = cpu_to_hc32(fotg210, (u32)addr); + qtd->hw_buf_hi[i] = cpu_to_hc32(fotg210, + (u32)(addr >> 32)); + buf += 0x1000; + if ((count + 0x1000) < len) + count += 0x1000; + else + count = len; + } + + /* short packets may only terminate transfers */ + if (count != len) + count -= (count % maxpacket); + } + qtd->hw_token = cpu_to_hc32(fotg210, (count << 16) | token); + qtd->length = count; + + return count; +} + +/*-------------------------------------------------------------------------*/ + +static inline void +qh_update(struct fotg210_hcd *fotg210, struct fotg210_qh *qh, + struct fotg210_qtd *qtd) +{ + struct fotg210_qh_hw *hw = qh->hw; + + /* writes to an active overlay are unsafe */ + BUG_ON(qh->qh_state != QH_STATE_IDLE); + + hw->hw_qtd_next = QTD_NEXT(fotg210, qtd->qtd_dma); + hw->hw_alt_next = FOTG210_LIST_END(fotg210); + + /* Except for control endpoints, we make hardware maintain data + * toggle (like OHCI) ... here (re)initialize the toggle in the QH, + * and set the pseudo-toggle in udev. Only usb_clear_halt() will + * ever clear it. + */ + if (!(hw->hw_info1 & cpu_to_hc32(fotg210, QH_TOGGLE_CTL))) { + unsigned is_out, epnum; + + is_out = qh->is_out; + epnum = (hc32_to_cpup(fotg210, &hw->hw_info1) >> 8) & 0x0f; + if (unlikely(!usb_gettoggle(qh->dev, epnum, is_out))) { + hw->hw_token &= ~cpu_to_hc32(fotg210, QTD_TOGGLE); + usb_settoggle(qh->dev, epnum, is_out, 1); + } + } + + hw->hw_token &= cpu_to_hc32(fotg210, QTD_TOGGLE | QTD_STS_PING); +} + +/* if it weren't for a common silicon quirk (writing the dummy into the qh + * overlay, so qh->hw_token wrongly becomes inactive/halted), only fault + * recovery (including urb dequeue) would need software changes to a QH... + */ +static void +qh_refresh(struct fotg210_hcd *fotg210, struct fotg210_qh *qh) +{ + struct fotg210_qtd *qtd; + + if (list_empty(&qh->qtd_list)) + qtd = qh->dummy; + else { + qtd = list_entry(qh->qtd_list.next, + struct fotg210_qtd, qtd_list); + /* + * first qtd may already be partially processed. + * If we come here during unlink, the QH overlay region + * might have reference to the just unlinked qtd. The + * qtd is updated in qh_completions(). Update the QH + * overlay here. + */ + if (cpu_to_hc32(fotg210, qtd->qtd_dma) == qh->hw->hw_current) { + qh->hw->hw_qtd_next = qtd->hw_next; + qtd = NULL; + } + } + + if (qtd) + qh_update(fotg210, qh, qtd); +} + +/*-------------------------------------------------------------------------*/ + +static void qh_link_async(struct fotg210_hcd *fotg210, struct fotg210_qh *qh); + +static void fotg210_clear_tt_buffer_complete(struct usb_hcd *hcd, + struct usb_host_endpoint *ep) +{ + struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); + struct fotg210_qh *qh = ep->hcpriv; + unsigned long flags; + + spin_lock_irqsave(&fotg210->lock, flags); + qh->clearing_tt = 0; + if (qh->qh_state == QH_STATE_IDLE && !list_empty(&qh->qtd_list) + && fotg210->rh_state == FOTG210_RH_RUNNING) + qh_link_async(fotg210, qh); + spin_unlock_irqrestore(&fotg210->lock, flags); +} + +static void fotg210_clear_tt_buffer(struct fotg210_hcd *fotg210, + struct fotg210_qh *qh, + struct urb *urb, u32 token) +{ + + /* If an async split transaction gets an error or is unlinked, + * the TT buffer may be left in an indeterminate state. We + * have to clear the TT buffer. + * + * Note: this routine is never called for Isochronous transfers. + */ + if (urb->dev->tt && !usb_pipeint(urb->pipe) && !qh->clearing_tt) { +#ifdef DEBUG + struct usb_device *tt = urb->dev->tt->hub; + dev_dbg(&tt->dev, + "clear tt buffer port %d, a%d ep%d t%08x\n", + urb->dev->ttport, urb->dev->devnum, + usb_pipeendpoint(urb->pipe), token); +#endif /* DEBUG */ + if (urb->dev->tt->hub != + fotg210_to_hcd(fotg210)->self.root_hub) { + if (usb_hub_clear_tt_buffer(urb) == 0) + qh->clearing_tt = 1; + } + } +} + +static int qtd_copy_status( + struct fotg210_hcd *fotg210, + struct urb *urb, + size_t length, + u32 token +) +{ + int status = -EINPROGRESS; + + /* count IN/OUT bytes, not SETUP (even short packets) */ + if (likely(QTD_PID(token) != 2)) + urb->actual_length += length - QTD_LENGTH(token); + + /* don't modify error codes */ + if (unlikely(urb->unlinked)) + return status; + + /* force cleanup after short read; not always an error */ + if (unlikely(IS_SHORT_READ(token))) + status = -EREMOTEIO; + + /* serious "can't proceed" faults reported by the hardware */ + if (token & QTD_STS_HALT) { + if (token & QTD_STS_BABBLE) { + /* FIXME "must" disable babbling device's port too */ + status = -EOVERFLOW; + /* CERR nonzero + halt --> stall */ + } else if (QTD_CERR(token)) { + status = -EPIPE; + + /* In theory, more than one of the following bits can be set + * since they are sticky and the transaction is retried. + * Which to test first is rather arbitrary. + */ + } else if (token & QTD_STS_MMF) { + /* fs/ls interrupt xfer missed the complete-split */ + status = -EPROTO; + } else if (token & QTD_STS_DBE) { + status = (QTD_PID(token) == 1) /* IN ? */ + ? -ENOSR /* hc couldn't read data */ + : -ECOMM; /* hc couldn't write data */ + } else if (token & QTD_STS_XACT) { + /* timeout, bad CRC, wrong PID, etc */ + fotg210_dbg(fotg210, "devpath %s ep%d%s 3strikes\n", + urb->dev->devpath, + usb_pipeendpoint(urb->pipe), + usb_pipein(urb->pipe) ? "in" : "out"); + status = -EPROTO; + } else { /* unknown */ + status = -EPROTO; + } + + fotg210_vdbg(fotg210, + "dev%d ep%d%s qtd token %08x --> status %d\n", + usb_pipedevice(urb->pipe), + usb_pipeendpoint(urb->pipe), + usb_pipein(urb->pipe) ? "in" : "out", + token, status); + } + + return status; +} + +static void +fotg210_urb_done(struct fotg210_hcd *fotg210, struct urb *urb, int status) +__releases(fotg210->lock) +__acquires(fotg210->lock) +{ + if (likely(urb->hcpriv != NULL)) { + struct fotg210_qh *qh = (struct fotg210_qh *) urb->hcpriv; + + /* S-mask in a QH means it's an interrupt urb */ + if ((qh->hw->hw_info2 & cpu_to_hc32(fotg210, QH_SMASK)) != 0) { + + /* ... update hc-wide periodic stats (for usbfs) */ + fotg210_to_hcd(fotg210)->self.bandwidth_int_reqs--; + } + } + + if (unlikely(urb->unlinked)) { + COUNT(fotg210->stats.unlink); + } else { + /* report non-error and short read status as zero */ + if (status == -EINPROGRESS || status == -EREMOTEIO) + status = 0; + COUNT(fotg210->stats.complete); + } + +#ifdef FOTG210_URB_TRACE + fotg210_dbg(fotg210, + "%s %s urb %p ep%d%s status %d len %d/%d\n", + __func__, urb->dev->devpath, urb, + usb_pipeendpoint(urb->pipe), + usb_pipein(urb->pipe) ? "in" : "out", + status, + urb->actual_length, urb->transfer_buffer_length); +#endif + + /* complete() can reenter this HCD */ + usb_hcd_unlink_urb_from_ep(fotg210_to_hcd(fotg210), urb); + spin_unlock(&fotg210->lock); + usb_hcd_giveback_urb(fotg210_to_hcd(fotg210), urb, status); + spin_lock(&fotg210->lock); +} + +static int qh_schedule(struct fotg210_hcd *fotg210, struct fotg210_qh *qh); + +/* + * Process and free completed qtds for a qh, returning URBs to drivers. + * Chases up to qh->hw_current. Returns number of completions called, + * indicating how much "real" work we did. + */ +static unsigned +qh_completions(struct fotg210_hcd *fotg210, struct fotg210_qh *qh) +{ + struct fotg210_qtd *last, *end = qh->dummy; + struct list_head *entry, *tmp; + int last_status; + int stopped; + unsigned count = 0; + u8 state; + struct fotg210_qh_hw *hw = qh->hw; + + if (unlikely(list_empty(&qh->qtd_list))) + return count; + + /* completions (or tasks on other cpus) must never clobber HALT + * till we've gone through and cleaned everything up, even when + * they add urbs to this qh's queue or mark them for unlinking. + * + * NOTE: unlinking expects to be done in queue order. + * + * It's a bug for qh->qh_state to be anything other than + * QH_STATE_IDLE, unless our caller is scan_async() or + * scan_intr(). + */ + state = qh->qh_state; + qh->qh_state = QH_STATE_COMPLETING; + stopped = (state == QH_STATE_IDLE); + + rescan: + last = NULL; + last_status = -EINPROGRESS; + qh->needs_rescan = 0; + + /* remove de-activated QTDs from front of queue. + * after faults (including short reads), cleanup this urb + * then let the queue advance. + * if queue is stopped, handles unlinks. + */ + list_for_each_safe(entry, tmp, &qh->qtd_list) { + struct fotg210_qtd *qtd; + struct urb *urb; + u32 token = 0; + + qtd = list_entry(entry, struct fotg210_qtd, qtd_list); + urb = qtd->urb; + + /* clean up any state from previous QTD ...*/ + if (last) { + if (likely(last->urb != urb)) { + fotg210_urb_done(fotg210, last->urb, + last_status); + count++; + last_status = -EINPROGRESS; + } + fotg210_qtd_free(fotg210, last); + last = NULL; + } + + /* ignore urbs submitted during completions we reported */ + if (qtd == end) + break; + + /* hardware copies qtd out of qh overlay */ + rmb(); + token = hc32_to_cpu(fotg210, qtd->hw_token); + + /* always clean up qtds the hc de-activated */ + retry_xacterr: + if ((token & QTD_STS_ACTIVE) == 0) { + + /* Report Data Buffer Error: non-fatal but useful */ + if (token & QTD_STS_DBE) + fotg210_dbg(fotg210, + "detected DataBufferErr for urb %p ep%d%s len %d, qtd %p [qh %p]\n", + urb, + usb_endpoint_num(&urb->ep->desc), + usb_endpoint_dir_in(&urb->ep->desc) + ? "in" : "out", + urb->transfer_buffer_length, + qtd, + qh); + + /* 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 < QH_XACTERR_MAX && + !urb->unlinked) { + fotg210_dbg(fotg210, + "detected XactErr len %zu/%zu retry %d\n", + qtd->length - QTD_LENGTH(token), qtd->length, 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 | + (FOTG210_TUNE_CERR << 10); + qtd->hw_token = cpu_to_hc32(fotg210, + token); + wmb(); + hw->hw_token = cpu_to_hc32(fotg210, + token); + goto retry_xacterr; + } + stopped = 1; + + /* magic dummy for some short reads; qh won't advance. + * that silicon quirk can kick in with this dummy too. + * + * other short reads won't stop the queue, including + * control transfers (status stage handles that) or + * most other single-qtd reads ... the queue stops if + * URB_SHORT_NOT_OK was set so the driver submitting + * the urbs could clean it up. + */ + } else if (IS_SHORT_READ(token) + && !(qtd->hw_alt_next + & FOTG210_LIST_END(fotg210))) { + stopped = 1; + } + + /* stop scanning when we reach qtds the hc is using */ + } else if (likely(!stopped + && fotg210->rh_state >= FOTG210_RH_RUNNING)) { + break; + + /* scan the whole queue for unlinks whenever it stops */ + } else { + stopped = 1; + + /* cancel everything if we halt, suspend, etc */ + if (fotg210->rh_state < FOTG210_RH_RUNNING) + last_status = -ESHUTDOWN; + + /* this qtd is active; skip it unless a previous qtd + * for its urb faulted, or its urb was canceled. + */ + else if (last_status == -EINPROGRESS && !urb->unlinked) + continue; + + /* qh unlinked; token in overlay may be most current */ + if (state == QH_STATE_IDLE + && cpu_to_hc32(fotg210, qtd->qtd_dma) + == hw->hw_current) { + token = hc32_to_cpu(fotg210, hw->hw_token); + + /* An unlink may leave an incomplete + * async transaction in the TT buffer. + * We have to clear it. + */ + fotg210_clear_tt_buffer(fotg210, qh, urb, + token); + } + } + + /* unless we already know the urb's status, collect qtd status + * and update count of bytes transferred. in common short read + * cases with only one data qtd (including control transfers), + * queue processing won't halt. but with two or more qtds (for + * example, with a 32 KB transfer), when the first qtd gets a + * short read the second must be removed by hand. + */ + if (last_status == -EINPROGRESS) { + last_status = qtd_copy_status(fotg210, urb, + qtd->length, token); + if (last_status == -EREMOTEIO + && (qtd->hw_alt_next + & FOTG210_LIST_END(fotg210))) + last_status = -EINPROGRESS; + + /* As part of low/full-speed endpoint-halt processing + * we must clear the TT buffer (11.17.5). + */ + if (unlikely(last_status != -EINPROGRESS && + last_status != -EREMOTEIO)) { + /* The TT's in some hubs malfunction when they + * receive this request following a STALL (they + * stop sending isochronous packets). Since a + * STALL can't leave the TT buffer in a busy + * state (if you believe Figures 11-48 - 11-51 + * in the USB 2.0 spec), we won't clear the TT + * buffer in this case. Strictly speaking this + * is a violation of the spec. + */ + if (last_status != -EPIPE) + fotg210_clear_tt_buffer(fotg210, qh, + urb, token); + } + } + + /* if we're removing something not at the queue head, + * patch the hardware queue pointer. + */ + if (stopped && qtd->qtd_list.prev != &qh->qtd_list) { + last = list_entry(qtd->qtd_list.prev, + struct fotg210_qtd, qtd_list); + last->hw_next = qtd->hw_next; + } + + /* 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 = 0; + } + + /* last urb's completion might still need calling */ + if (likely(last != NULL)) { + fotg210_urb_done(fotg210, last->urb, last_status); + count++; + fotg210_qtd_free(fotg210, last); + } + + /* Do we need to rescan for URBs dequeued during a giveback? */ + if (unlikely(qh->needs_rescan)) { + /* If the QH is already unlinked, do the rescan now. */ + if (state == QH_STATE_IDLE) + goto rescan; + + /* Otherwise we have to wait until the QH is fully unlinked. + * Our caller will start an unlink if qh->needs_rescan is + * set. But if an unlink has already started, nothing needs + * to be done. + */ + if (state != QH_STATE_LINKED) + qh->needs_rescan = 0; + } + + /* restore original state; caller must unlink or relink */ + qh->qh_state = state; + + /* be sure the hardware's done with the qh before refreshing + * it after fault cleanup, or recovering from silicon wrongly + * overlaying the dummy qtd (which reduces DMA chatter). + */ + if (stopped != 0 || hw->hw_qtd_next == FOTG210_LIST_END(fotg210)) { + switch (state) { + case QH_STATE_IDLE: + qh_refresh(fotg210, qh); + break; + case QH_STATE_LINKED: + /* We won't refresh a QH that's linked (after the HC + * stopped the queue). That avoids a race: + * - HC reads first part of QH; + * - CPU updates that first part and the token; + * - HC reads rest of that QH, including token + * Result: HC gets an inconsistent image, and then + * DMAs to/from the wrong memory (corrupting it). + * + * That should be rare for interrupt transfers, + * except maybe high bandwidth ... + */ + + /* Tell the caller to start an unlink */ + qh->needs_rescan = 1; + break; + /* otherwise, unlink already started */ + } + } + + return count; +} + +/*-------------------------------------------------------------------------*/ + +/* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */ +#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03)) +/* ... and packet size, for any kind of endpoint descriptor */ +#define max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff) + +/* + * reverse of qh_urb_transaction: free a list of TDs. + * used for cleanup after errors, before HC sees an URB's TDs. + */ +static void qtd_list_free( + struct fotg210_hcd *fotg210, + struct urb *urb, + struct list_head *qtd_list +) { + struct list_head *entry, *temp; + + list_for_each_safe(entry, temp, qtd_list) { + struct fotg210_qtd *qtd; + + qtd = list_entry(entry, struct fotg210_qtd, qtd_list); + list_del(&qtd->qtd_list); + fotg210_qtd_free(fotg210, qtd); + } +} + +/* + * create a list of filled qtds for this URB; won't link into qh. + */ +static struct list_head * +qh_urb_transaction( + struct fotg210_hcd *fotg210, + struct urb *urb, + struct list_head *head, + gfp_t flags +) { + struct fotg210_qtd *qtd, *qtd_prev; + dma_addr_t buf; + int len, this_sg_len, maxpacket; + int is_input; + u32 token; + int i; + struct scatterlist *sg; + + /* + * URBs map to sequences of QTDs: one logical transaction + */ + qtd = fotg210_qtd_alloc(fotg210, flags); + if (unlikely(!qtd)) + return NULL; + list_add_tail(&qtd->qtd_list, head); + qtd->urb = urb; + + token = QTD_STS_ACTIVE; + token |= (FOTG210_TUNE_CERR << 10); + /* for split transactions, SplitXState initialized to zero */ + + len = urb->transfer_buffer_length; + is_input = usb_pipein(urb->pipe); + if (usb_pipecontrol(urb->pipe)) { + /* SETUP pid */ + qtd_fill(fotg210, qtd, urb->setup_dma, + sizeof(struct usb_ctrlrequest), + token | (2 /* "setup" */ << 8), 8); + + /* ... and always at least one more pid */ + token ^= QTD_TOGGLE; + qtd_prev = qtd; + qtd = fotg210_qtd_alloc(fotg210, flags); + if (unlikely(!qtd)) + goto cleanup; + qtd->urb = urb; + qtd_prev->hw_next = QTD_NEXT(fotg210, qtd->qtd_dma); + list_add_tail(&qtd->qtd_list, head); + + /* for zero length DATA stages, STATUS is always IN */ + if (len == 0) + token |= (1 /* "in" */ << 8); + } + + /* + * data transfer stage: buffer setup + */ + i = urb->num_mapped_sgs; + if (len > 0 && i > 0) { + sg = urb->sg; + buf = sg_dma_address(sg); + + /* urb->transfer_buffer_length may be smaller than the + * size of the scatterlist (or vice versa) + */ + this_sg_len = min_t(int, sg_dma_len(sg), len); + } else { + sg = NULL; + buf = urb->transfer_dma; + this_sg_len = len; + } + + if (is_input) + token |= (1 /* "in" */ << 8); + /* else it's already initted to "out" pid (0 << 8) */ + + maxpacket = max_packet(usb_maxpacket(urb->dev, urb->pipe, !is_input)); + + /* + * buffer gets wrapped in one or more qtds; + * last one may be "short" (including zero len) + * and may serve as a control status ack + */ + for (;;) { + int this_qtd_len; + + this_qtd_len = qtd_fill(fotg210, qtd, buf, this_sg_len, token, + maxpacket); + this_sg_len -= this_qtd_len; + len -= this_qtd_len; + buf += this_qtd_len; + + /* + * short reads advance to a "magic" dummy instead of the next + * qtd ... that forces the queue to stop, for manual cleanup. + * (this will usually be overridden later.) + */ + if (is_input) + qtd->hw_alt_next = fotg210->async->hw->hw_alt_next; + + /* qh makes control packets use qtd toggle; maybe switch it */ + if ((maxpacket & (this_qtd_len + (maxpacket - 1))) == 0) + token ^= QTD_TOGGLE; + + if (likely(this_sg_len <= 0)) { + if (--i <= 0 || len <= 0) + break; + sg = sg_next(sg); + buf = sg_dma_address(sg); + this_sg_len = min_t(int, sg_dma_len(sg), len); + } + + qtd_prev = qtd; + qtd = fotg210_qtd_alloc(fotg210, flags); + if (unlikely(!qtd)) + goto cleanup; + qtd->urb = urb; + qtd_prev->hw_next = QTD_NEXT(fotg210, qtd->qtd_dma); + list_add_tail(&qtd->qtd_list, head); + } + + /* + * unless the caller requires manual cleanup after short reads, + * have the alt_next mechanism keep the queue running after the + * last data qtd (the only one, for control and most other cases). + */ + if (likely((urb->transfer_flags & URB_SHORT_NOT_OK) == 0 + || usb_pipecontrol(urb->pipe))) + qtd->hw_alt_next = FOTG210_LIST_END(fotg210); + + /* + * control requests may need a terminating data "status" ack; + * other OUT ones may need a terminating short packet + * (zero length). + */ + if (likely(urb->transfer_buffer_length != 0)) { + int one_more = 0; + + if (usb_pipecontrol(urb->pipe)) { + one_more = 1; + token ^= 0x0100; /* "in" <--> "out" */ + token |= QTD_TOGGLE; /* force DATA1 */ + } else if (usb_pipeout(urb->pipe) + && (urb->transfer_flags & URB_ZERO_PACKET) + && !(urb->transfer_buffer_length % maxpacket)) { + one_more = 1; + } + if (one_more) { + qtd_prev = qtd; + qtd = fotg210_qtd_alloc(fotg210, flags); + if (unlikely(!qtd)) + goto cleanup; + qtd->urb = urb; + qtd_prev->hw_next = QTD_NEXT(fotg210, qtd->qtd_dma); + list_add_tail(&qtd->qtd_list, head); + + /* never any data in such packets */ + qtd_fill(fotg210, qtd, 0, 0, token, 0); + } + } + + /* by default, enable interrupt on urb completion */ + if (likely(!(urb->transfer_flags & URB_NO_INTERRUPT))) + qtd->hw_token |= cpu_to_hc32(fotg210, QTD_IOC); + return head; + +cleanup: + qtd_list_free(fotg210, urb, head); + return NULL; +} + +/*-------------------------------------------------------------------------*/ +/* + * Would be best to create all qh's from config descriptors, + * when each interface/altsetting is established. Unlink + * any previous qh and cancel its urbs first; endpoints are + * implicitly reset then (data toggle too). + * That'd mean updating how usbcore talks to HCDs. (2.7?) +*/ + + +/* + * Each QH holds a qtd list; a QH is used for everything except iso. + * + * For interrupt urbs, the scheduler must set the microframe scheduling + * mask(s) each time the QH gets scheduled. For highspeed, that's + * just one microframe in the s-mask. For split interrupt transactions + * there are additional complications: c-mask, maybe FSTNs. + */ +static struct fotg210_qh * +qh_make( + struct fotg210_hcd *fotg210, + struct urb *urb, + gfp_t flags +) { + struct fotg210_qh *qh = fotg210_qh_alloc(fotg210, flags); + u32 info1 = 0, info2 = 0; + int is_input, type; + int maxp = 0; + struct usb_tt *tt = urb->dev->tt; + struct fotg210_qh_hw *hw; + + if (!qh) + return qh; + + /* + * init endpoint/device data for this QH + */ + info1 |= usb_pipeendpoint(urb->pipe) << 8; + info1 |= usb_pipedevice(urb->pipe) << 0; + + is_input = usb_pipein(urb->pipe); + type = usb_pipetype(urb->pipe); + maxp = usb_maxpacket(urb->dev, urb->pipe, !is_input); + + /* 1024 byte maxpacket is a hardware ceiling. High bandwidth + * acts like up to 3KB, but is built from smaller packets. + */ + if (max_packet(maxp) > 1024) { + fotg210_dbg(fotg210, "bogus qh maxpacket %d\n", + max_packet(maxp)); + goto done; + } + + /* Compute interrupt scheduling parameters just once, and save. + * - allowing for high bandwidth, how many nsec/uframe are used? + * - split transactions need a second CSPLIT uframe; same question + * - splits also need a schedule gap (for full/low speed I/O) + * - qh has a polling interval + * + * For control/bulk requests, the HC or TT handles these. + */ + if (type == PIPE_INTERRUPT) { + qh->usecs = NS_TO_US(usb_calc_bus_time(USB_SPEED_HIGH, + is_input, 0, + hb_mult(maxp) * max_packet(maxp))); + qh->start = NO_FRAME; + + if (urb->dev->speed == USB_SPEED_HIGH) { + qh->c_usecs = 0; + qh->gap_uf = 0; + + qh->period = urb->interval >> 3; + if (qh->period == 0 && urb->interval != 1) { + /* NOTE interval 2 or 4 uframes could work. + * But interval 1 scheduling is simpler, and + * includes high bandwidth. + */ + urb->interval = 1; + } else if (qh->period > fotg210->periodic_size) { + qh->period = fotg210->periodic_size; + urb->interval = qh->period << 3; + } + } else { + int think_time; + + /* gap is f(FS/LS transfer times) */ + qh->gap_uf = 1 + usb_calc_bus_time(urb->dev->speed, + is_input, 0, maxp) / (125 * 1000); + + /* FIXME this just approximates SPLIT/CSPLIT times */ + if (is_input) { /* SPLIT, gap, CSPLIT+DATA */ + qh->c_usecs = qh->usecs + HS_USECS(0); + qh->usecs = HS_USECS(1); + } else { /* SPLIT+DATA, gap, CSPLIT */ + qh->usecs += HS_USECS(1); + qh->c_usecs = HS_USECS(0); + } + + think_time = tt ? tt->think_time : 0; + qh->tt_usecs = NS_TO_US(think_time + + usb_calc_bus_time(urb->dev->speed, + is_input, 0, max_packet(maxp))); + qh->period = urb->interval; + if (qh->period > fotg210->periodic_size) { + qh->period = fotg210->periodic_size; + urb->interval = qh->period; + } + } + } + + /* support for tt scheduling, and access to toggles */ + qh->dev = urb->dev; + + /* using TT? */ + switch (urb->dev->speed) { + case USB_SPEED_LOW: + info1 |= QH_LOW_SPEED; + /* FALL THROUGH */ + + case USB_SPEED_FULL: + /* EPS 0 means "full" */ + if (type != PIPE_INTERRUPT) + info1 |= (FOTG210_TUNE_RL_TT << 28); + if (type == PIPE_CONTROL) { + info1 |= QH_CONTROL_EP; /* for TT */ + info1 |= QH_TOGGLE_CTL; /* toggle from qtd */ + } + info1 |= maxp << 16; + + info2 |= (FOTG210_TUNE_MULT_TT << 30); + + /* Some Freescale processors have an erratum in which the + * port number in the queue head was 0..N-1 instead of 1..N. + */ + if (fotg210_has_fsl_portno_bug(fotg210)) + info2 |= (urb->dev->ttport-1) << 23; + else + info2 |= urb->dev->ttport << 23; + + /* set the address of the TT; for TDI's integrated + * root hub tt, leave it zeroed. + */ + if (tt && tt->hub != fotg210_to_hcd(fotg210)->self.root_hub) + info2 |= tt->hub->devnum << 16; + + /* NOTE: if (PIPE_INTERRUPT) { scheduler sets c-mask } */ + + break; + + case USB_SPEED_HIGH: /* no TT involved */ + info1 |= QH_HIGH_SPEED; + if (type == PIPE_CONTROL) { + info1 |= (FOTG210_TUNE_RL_HS << 28); + info1 |= 64 << 16; /* usb2 fixed maxpacket */ + info1 |= QH_TOGGLE_CTL; /* toggle from qtd */ + info2 |= (FOTG210_TUNE_MULT_HS << 30); + } else if (type == PIPE_BULK) { + info1 |= (FOTG210_TUNE_RL_HS << 28); + /* The USB spec says that high speed bulk endpoints + * always use 512 byte maxpacket. But some device + * vendors decided to ignore that, and MSFT is happy + * to help them do so. So now people expect to use + * such nonconformant devices with Linux too; sigh. + */ + info1 |= max_packet(maxp) << 16; + info2 |= (FOTG210_TUNE_MULT_HS << 30); + } else { /* PIPE_INTERRUPT */ + info1 |= max_packet(maxp) << 16; + info2 |= hb_mult(maxp) << 30; + } + break; + default: + fotg210_dbg(fotg210, "bogus dev %p speed %d\n", urb->dev, + urb->dev->speed); +done: + qh_destroy(fotg210, qh); + return NULL; + } + + /* NOTE: if (PIPE_INTERRUPT) { scheduler sets s-mask } */ + + /* init as live, toggle clear, advance to dummy */ + qh->qh_state = QH_STATE_IDLE; + hw = qh->hw; + hw->hw_info1 = cpu_to_hc32(fotg210, info1); + hw->hw_info2 = cpu_to_hc32(fotg210, info2); + qh->is_out = !is_input; + usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), !is_input, 1); + qh_refresh(fotg210, qh); + return qh; +} + +/*-------------------------------------------------------------------------*/ + +static void enable_async(struct fotg210_hcd *fotg210) +{ + if (fotg210->async_count++) + return; + + /* Stop waiting to turn off the async schedule */ + fotg210->enabled_hrtimer_events &= ~BIT(FOTG210_HRTIMER_DISABLE_ASYNC); + + /* Don't start the schedule until ASS is 0 */ + fotg210_poll_ASS(fotg210); + turn_on_io_watchdog(fotg210); +} + +static void disable_async(struct fotg210_hcd *fotg210) +{ + if (--fotg210->async_count) + return; + + /* The async schedule and async_unlink list are supposed to be empty */ + WARN_ON(fotg210->async->qh_next.qh || fotg210->async_unlink); + + /* Don't turn off the schedule until ASS is 1 */ + fotg210_poll_ASS(fotg210); +} + +/* move qh (and its qtds) onto async queue; maybe enable queue. */ + +static void qh_link_async(struct fotg210_hcd *fotg210, struct fotg210_qh *qh) +{ + __hc32 dma = QH_NEXT(fotg210, qh->qh_dma); + struct fotg210_qh *head; + + /* Don't link a QH if there's a Clear-TT-Buffer pending */ + if (unlikely(qh->clearing_tt)) + return; + + WARN_ON(qh->qh_state != QH_STATE_IDLE); + + /* clear halt and/or toggle; and maybe recover from silicon quirk */ + qh_refresh(fotg210, qh); + + /* splice right after start */ + head = fotg210->async; + qh->qh_next = head->qh_next; + qh->hw->hw_next = head->hw->hw_next; + wmb(); + + head->qh_next.qh = qh; + head->hw->hw_next = dma; + + qh->xacterrs = 0; + qh->qh_state = QH_STATE_LINKED; + /* qtd completions reported later by interrupt */ + + enable_async(fotg210); +} + +/*-------------------------------------------------------------------------*/ + +/* + * For control/bulk/interrupt, return QH with these TDs appended. + * Allocates and initializes the QH if necessary. + * Returns null if it can't allocate a QH it needs to. + * If the QH has TDs (urbs) already, that's great. + */ +static struct fotg210_qh *qh_append_tds( + struct fotg210_hcd *fotg210, + struct urb *urb, + struct list_head *qtd_list, + int epnum, + void **ptr +) +{ + struct fotg210_qh *qh = NULL; + __hc32 qh_addr_mask = cpu_to_hc32(fotg210, 0x7f); + + qh = (struct fotg210_qh *) *ptr; + if (unlikely(qh == NULL)) { + /* can't sleep here, we have fotg210->lock... */ + qh = qh_make(fotg210, urb, GFP_ATOMIC); + *ptr = qh; + } + if (likely(qh != NULL)) { + struct fotg210_qtd *qtd; + + if (unlikely(list_empty(qtd_list))) + qtd = NULL; + else + qtd = list_entry(qtd_list->next, struct fotg210_qtd, + qtd_list); + + /* control qh may need patching ... */ + if (unlikely(epnum == 0)) { + /* usb_reset_device() briefly reverts to address 0 */ + if (usb_pipedevice(urb->pipe) == 0) + qh->hw->hw_info1 &= ~qh_addr_mask; + } + + /* just one way to queue requests: swap with the dummy qtd. + * only hc or qh_refresh() ever modify the overlay. + */ + if (likely(qtd != NULL)) { + struct fotg210_qtd *dummy; + dma_addr_t dma; + __hc32 token; + + /* to avoid racing the HC, use the dummy td instead of + * the first td of our list (becomes new dummy). both + * tds stay deactivated until we're done, when the + * HC is allowed to fetch the old dummy (4.10.2). + */ + token = qtd->hw_token; + qtd->hw_token = HALT_BIT(fotg210); + + dummy = qh->dummy; + + dma = dummy->qtd_dma; + *dummy = *qtd; + dummy->qtd_dma = dma; + + list_del(&qtd->qtd_list); + list_add(&dummy->qtd_list, qtd_list); + list_splice_tail(qtd_list, &qh->qtd_list); + + fotg210_qtd_init(fotg210, qtd, qtd->qtd_dma); + qh->dummy = qtd; + + /* hc must see the new dummy at list end */ + dma = qtd->qtd_dma; + qtd = list_entry(qh->qtd_list.prev, + struct fotg210_qtd, qtd_list); + qtd->hw_next = QTD_NEXT(fotg210, dma); + + /* let the hc process these next qtds */ + wmb(); + dummy->hw_token = token; + + urb->hcpriv = qh; + } + } + return qh; +} + +/*-------------------------------------------------------------------------*/ + +static int +submit_async( + struct fotg210_hcd *fotg210, + struct urb *urb, + struct list_head *qtd_list, + gfp_t mem_flags +) { + int epnum; + unsigned long flags; + struct fotg210_qh *qh = NULL; + int rc; + + epnum = urb->ep->desc.bEndpointAddress; + +#ifdef FOTG210_URB_TRACE + { + struct fotg210_qtd *qtd; + qtd = list_entry(qtd_list->next, struct fotg210_qtd, qtd_list); + fotg210_dbg(fotg210, + "%s %s urb %p ep%d%s len %d, qtd %p [qh %p]\n", + __func__, urb->dev->devpath, urb, + epnum & 0x0f, (epnum & USB_DIR_IN) ? "in" : "out", + urb->transfer_buffer_length, + qtd, urb->ep->hcpriv); + } +#endif + + spin_lock_irqsave(&fotg210->lock, flags); + if (unlikely(!HCD_HW_ACCESSIBLE(fotg210_to_hcd(fotg210)))) { + rc = -ESHUTDOWN; + goto done; + } + rc = usb_hcd_link_urb_to_ep(fotg210_to_hcd(fotg210), urb); + if (unlikely(rc)) + goto done; + + qh = qh_append_tds(fotg210, urb, qtd_list, epnum, &urb->ep->hcpriv); + if (unlikely(qh == NULL)) { + usb_hcd_unlink_urb_from_ep(fotg210_to_hcd(fotg210), urb); + rc = -ENOMEM; + goto done; + } + + /* Control/bulk operations through TTs don't need scheduling, + * the HC and TT handle it when the TT has a buffer ready. + */ + if (likely(qh->qh_state == QH_STATE_IDLE)) + qh_link_async(fotg210, qh); + done: + spin_unlock_irqrestore(&fotg210->lock, flags); + if (unlikely(qh == NULL)) + qtd_list_free(fotg210, urb, qtd_list); + return rc; +} + +/*-------------------------------------------------------------------------*/ + +static void single_unlink_async(struct fotg210_hcd *fotg210, + struct fotg210_qh *qh) +{ + struct fotg210_qh *prev; + + /* Add to the end of the list of QHs waiting for the next IAAD */ + qh->qh_state = QH_STATE_UNLINK; + if (fotg210->async_unlink) + fotg210->async_unlink_last->unlink_next = qh; + else + fotg210->async_unlink = qh; + fotg210->async_unlink_last = qh; + + /* Unlink it from the schedule */ + prev = fotg210->async; + while (prev->qh_next.qh != qh) + prev = prev->qh_next.qh; + + prev->hw->hw_next = qh->hw->hw_next; + prev->qh_next = qh->qh_next; + if (fotg210->qh_scan_next == qh) + fotg210->qh_scan_next = qh->qh_next.qh; +} + +static void start_iaa_cycle(struct fotg210_hcd *fotg210, bool nested) +{ + /* + * Do nothing if an IAA cycle is already running or + * if one will be started shortly. + */ + if (fotg210->async_iaa || fotg210->async_unlinking) + return; + + /* Do all the waiting QHs at once */ + fotg210->async_iaa = fotg210->async_unlink; + fotg210->async_unlink = NULL; + + /* If the controller isn't running, we don't have to wait for it */ + if (unlikely(fotg210->rh_state < FOTG210_RH_RUNNING)) { + if (!nested) /* Avoid recursion */ + end_unlink_async(fotg210); + + /* Otherwise start a new IAA cycle */ + } else if (likely(fotg210->rh_state == FOTG210_RH_RUNNING)) { + /* Make sure the unlinks are all visible to the hardware */ + wmb(); + + fotg210_writel(fotg210, fotg210->command | CMD_IAAD, + &fotg210->regs->command); + fotg210_readl(fotg210, &fotg210->regs->command); + fotg210_enable_event(fotg210, FOTG210_HRTIMER_IAA_WATCHDOG, + true); + } +} + +/* the async qh for the qtds being unlinked are now gone from the HC */ + +static void end_unlink_async(struct fotg210_hcd *fotg210) +{ + struct fotg210_qh *qh; + + /* Process the idle QHs */ + restart: + fotg210->async_unlinking = true; + while (fotg210->async_iaa) { + qh = fotg210->async_iaa; + fotg210->async_iaa = qh->unlink_next; + qh->unlink_next = NULL; + + qh->qh_state = QH_STATE_IDLE; + qh->qh_next.qh = NULL; + + qh_completions(fotg210, qh); + if (!list_empty(&qh->qtd_list) && + fotg210->rh_state == FOTG210_RH_RUNNING) + qh_link_async(fotg210, qh); + disable_async(fotg210); + } + fotg210->async_unlinking = false; + + /* Start a new IAA cycle if any QHs are waiting for it */ + if (fotg210->async_unlink) { + start_iaa_cycle(fotg210, true); + if (unlikely(fotg210->rh_state < FOTG210_RH_RUNNING)) + goto restart; + } +} + +static void unlink_empty_async(struct fotg210_hcd *fotg210) +{ + struct fotg210_qh *qh, *next; + bool stopped = (fotg210->rh_state < FOTG210_RH_RUNNING); + bool check_unlinks_later = false; + + /* Unlink all the async QHs that have been empty for a timer cycle */ + next = fotg210->async->qh_next.qh; + while (next) { + qh = next; + next = qh->qh_next.qh; + + if (list_empty(&qh->qtd_list) && + qh->qh_state == QH_STATE_LINKED) { + if (!stopped && qh->unlink_cycle == + fotg210->async_unlink_cycle) + check_unlinks_later = true; + else + single_unlink_async(fotg210, qh); + } + } + + /* Start a new IAA cycle if any QHs are waiting for it */ + if (fotg210->async_unlink) + start_iaa_cycle(fotg210, false); + + /* QHs that haven't been empty for long enough will be handled later */ + if (check_unlinks_later) { + fotg210_enable_event(fotg210, FOTG210_HRTIMER_ASYNC_UNLINKS, + true); + ++fotg210->async_unlink_cycle; + } +} + +/* makes sure the async qh will become idle */ +/* caller must own fotg210->lock */ + +static void start_unlink_async(struct fotg210_hcd *fotg210, + struct fotg210_qh *qh) +{ + /* + * If the QH isn't linked then there's nothing we can do + * unless we were called during a giveback, in which case + * qh_completions() has to deal with it. + */ + if (qh->qh_state != QH_STATE_LINKED) { + if (qh->qh_state == QH_STATE_COMPLETING) + qh->needs_rescan = 1; + return; + } + + single_unlink_async(fotg210, qh); + start_iaa_cycle(fotg210, false); +} + +/*-------------------------------------------------------------------------*/ + +static void scan_async(struct fotg210_hcd *fotg210) +{ + struct fotg210_qh *qh; + bool check_unlinks_later = false; + + fotg210->qh_scan_next = fotg210->async->qh_next.qh; + while (fotg210->qh_scan_next) { + qh = fotg210->qh_scan_next; + fotg210->qh_scan_next = qh->qh_next.qh; + rescan: + /* clean any finished work for this qh */ + if (!list_empty(&qh->qtd_list)) { + int temp; + + /* + * Unlinks could happen here; completion reporting + * drops the lock. That's why fotg210->qh_scan_next + * always holds the next qh to scan; if the next qh + * gets unlinked then fotg210->qh_scan_next is adjusted + * in single_unlink_async(). + */ + temp = qh_completions(fotg210, qh); + if (qh->needs_rescan) { + start_unlink_async(fotg210, qh); + } else if (list_empty(&qh->qtd_list) + && qh->qh_state == QH_STATE_LINKED) { + qh->unlink_cycle = fotg210->async_unlink_cycle; + check_unlinks_later = true; + } else if (temp != 0) + goto rescan; + } + } + + /* + * Unlink empty entries, reducing DMA usage as well + * as HCD schedule-scanning costs. Delay for any qh + * we just scanned, there's a not-unusual case that it + * doesn't stay idle for long. + */ + if (check_unlinks_later && fotg210->rh_state == FOTG210_RH_RUNNING && + !(fotg210->enabled_hrtimer_events & + BIT(FOTG210_HRTIMER_ASYNC_UNLINKS))) { + fotg210_enable_event(fotg210, + FOTG210_HRTIMER_ASYNC_UNLINKS, true); + ++fotg210->async_unlink_cycle; + } +} +/*-------------------------------------------------------------------------*/ +/* + * EHCI scheduled transaction support: interrupt, iso, split iso + * These are called "periodic" transactions in the EHCI spec. + * + * Note that for interrupt transfers, the QH/QTD manipulation is shared + * with the "asynchronous" transaction support (control/bulk transfers). + * The only real difference is in how interrupt transfers are scheduled. + * + * For ISO, we make an "iso_stream" head to serve the same role as a QH. + * It keeps track of every ITD (or SITD) that's linked, and holds enough + * pre-calculated schedule data to make appending to the queue be quick. + */ + +static int fotg210_get_frame(struct usb_hcd *hcd); + +/*-------------------------------------------------------------------------*/ + +/* + * periodic_next_shadow - return "next" pointer on shadow list + * @periodic: host pointer to qh/itd + * @tag: hardware tag for type of this record + */ +static union fotg210_shadow * +periodic_next_shadow(struct fotg210_hcd *fotg210, + union fotg210_shadow *periodic, __hc32 tag) +{ + switch (hc32_to_cpu(fotg210, tag)) { + case Q_TYPE_QH: + return &periodic->qh->qh_next; + case Q_TYPE_FSTN: + return &periodic->fstn->fstn_next; + default: + return &periodic->itd->itd_next; + } +} + +static __hc32 * +shadow_next_periodic(struct fotg210_hcd *fotg210, + union fotg210_shadow *periodic, __hc32 tag) +{ + switch (hc32_to_cpu(fotg210, tag)) { + /* our fotg210_shadow.qh is actually software part */ + case Q_TYPE_QH: + return &periodic->qh->hw->hw_next; + /* others are hw parts */ + default: + return periodic->hw_next; + } +} + +/* caller must hold fotg210->lock */ +static void periodic_unlink(struct fotg210_hcd *fotg210, unsigned frame, + void *ptr) +{ + union fotg210_shadow *prev_p = &fotg210->pshadow[frame]; + __hc32 *hw_p = &fotg210->periodic[frame]; + union fotg210_shadow here = *prev_p; + + /* find predecessor of "ptr"; hw and shadow lists are in sync */ + while (here.ptr && here.ptr != ptr) { + prev_p = periodic_next_shadow(fotg210, prev_p, + Q_NEXT_TYPE(fotg210, *hw_p)); + hw_p = shadow_next_periodic(fotg210, &here, + Q_NEXT_TYPE(fotg210, *hw_p)); + here = *prev_p; + } + /* an interrupt entry (at list end) could have been shared */ + if (!here.ptr) + return; + + /* update shadow and hardware lists ... the old "next" pointers + * from ptr may still be in use, the caller updates them. + */ + *prev_p = *periodic_next_shadow(fotg210, &here, + Q_NEXT_TYPE(fotg210, *hw_p)); + + *hw_p = *shadow_next_periodic(fotg210, &here, + Q_NEXT_TYPE(fotg210, *hw_p)); +} + +/* how many of the uframe's 125 usecs are allocated? */ +static unsigned short +periodic_usecs(struct fotg210_hcd *fotg210, unsigned frame, unsigned uframe) +{ + __hc32 *hw_p = &fotg210->periodic[frame]; + union fotg210_shadow *q = &fotg210->pshadow[frame]; + unsigned usecs = 0; + struct fotg210_qh_hw *hw; + + while (q->ptr) { + switch (hc32_to_cpu(fotg210, Q_NEXT_TYPE(fotg210, *hw_p))) { + case Q_TYPE_QH: + hw = q->qh->hw; + /* is it in the S-mask? */ + if (hw->hw_info2 & cpu_to_hc32(fotg210, 1 << uframe)) + usecs += q->qh->usecs; + /* ... or C-mask? */ + if (hw->hw_info2 & cpu_to_hc32(fotg210, + 1 << (8 + uframe))) + usecs += q->qh->c_usecs; + hw_p = &hw->hw_next; + q = &q->qh->qh_next; + break; + /* case Q_TYPE_FSTN: */ + default: + /* for "save place" FSTNs, count the relevant INTR + * bandwidth from the previous frame + */ + if (q->fstn->hw_prev != FOTG210_LIST_END(fotg210)) + fotg210_dbg(fotg210, "ignoring FSTN cost ...\n"); + + hw_p = &q->fstn->hw_next; + q = &q->fstn->fstn_next; + break; + case Q_TYPE_ITD: + if (q->itd->hw_transaction[uframe]) + usecs += q->itd->stream->usecs; + hw_p = &q->itd->hw_next; + q = &q->itd->itd_next; + break; + } + } +#ifdef DEBUG + if (usecs > fotg210->uframe_periodic_max) + fotg210_err(fotg210, "uframe %d sched overrun: %d usecs\n", + frame * 8 + uframe, usecs); +#endif + return usecs; +} + +/*-------------------------------------------------------------------------*/ + +static int same_tt(struct usb_device *dev1, struct usb_device *dev2) +{ + if (!dev1->tt || !dev2->tt) + return 0; + if (dev1->tt != dev2->tt) + return 0; + if (dev1->tt->multi) + return dev1->ttport == dev2->ttport; + else + return 1; +} + +/* return true iff the device's transaction translator is available + * for a periodic transfer starting at the specified frame, using + * all the uframes in the mask. + */ +static int tt_no_collision( + struct fotg210_hcd *fotg210, + unsigned period, + struct usb_device *dev, + unsigned frame, + u32 uf_mask +) +{ + if (period == 0) /* error */ + return 0; + + /* note bandwidth wastage: split never follows csplit + * (different dev or endpoint) until the next uframe. + * calling convention doesn't make that distinction. + */ + for (; frame < fotg210->periodic_size; frame += period) { + union fotg210_shadow here; + __hc32 type; + struct fotg210_qh_hw *hw; + + here = fotg210->pshadow[frame]; + type = Q_NEXT_TYPE(fotg210, fotg210->periodic[frame]); + while (here.ptr) { + switch (hc32_to_cpu(fotg210, type)) { + case Q_TYPE_ITD: + type = Q_NEXT_TYPE(fotg210, here.itd->hw_next); + here = here.itd->itd_next; + continue; + case Q_TYPE_QH: + hw = here.qh->hw; + if (same_tt(dev, here.qh->dev)) { + u32 mask; + + mask = hc32_to_cpu(fotg210, + hw->hw_info2); + /* "knows" no gap is needed */ + mask |= mask >> 8; + if (mask & uf_mask) + break; + } + type = Q_NEXT_TYPE(fotg210, hw->hw_next); + here = here.qh->qh_next; + continue; + /* case Q_TYPE_FSTN: */ + default: + fotg210_dbg(fotg210, + "periodic frame %d bogus type %d\n", + frame, type); + } + + /* collision or error */ + return 0; + } + } + + /* no collision */ + return 1; +} + +/*-------------------------------------------------------------------------*/ + +static void enable_periodic(struct fotg210_hcd *fotg210) +{ + if (fotg210->periodic_count++) + return; + + /* Stop waiting to turn off the periodic schedule */ + fotg210->enabled_hrtimer_events &= + ~BIT(FOTG210_HRTIMER_DISABLE_PERIODIC); + + /* Don't start the schedule until PSS is 0 */ + fotg210_poll_PSS(fotg210); + turn_on_io_watchdog(fotg210); +} + +static void disable_periodic(struct fotg210_hcd *fotg210) +{ + if (--fotg210->periodic_count) + return; + + /* Don't turn off the schedule until PSS is 1 */ + fotg210_poll_PSS(fotg210); +} + +/*-------------------------------------------------------------------------*/ + +/* periodic schedule slots have iso tds (normal or split) first, then a + * sparse tree for active interrupt transfers. + * + * this just links in a qh; caller guarantees uframe masks are set right. + * no FSTN support (yet; fotg210 0.96+) + */ +static void qh_link_periodic(struct fotg210_hcd *fotg210, struct fotg210_qh *qh) +{ + unsigned i; + unsigned period = qh->period; + + dev_dbg(&qh->dev->dev, + "link qh%d-%04x/%p start %d [%d/%d us]\n", + period, hc32_to_cpup(fotg210, &qh->hw->hw_info2) + & (QH_CMASK | QH_SMASK), + qh, qh->start, qh->usecs, qh->c_usecs); + + /* high bandwidth, or otherwise every microframe */ + if (period == 0) + period = 1; + + for (i = qh->start; i < fotg210->periodic_size; i += period) { + union fotg210_shadow *prev = &fotg210->pshadow[i]; + __hc32 *hw_p = &fotg210->periodic[i]; + union fotg210_shadow here = *prev; + __hc32 type = 0; + + /* skip the iso nodes at list head */ + while (here.ptr) { + type = Q_NEXT_TYPE(fotg210, *hw_p); + if (type == cpu_to_hc32(fotg210, Q_TYPE_QH)) + break; + prev = periodic_next_shadow(fotg210, prev, type); + hw_p = shadow_next_periodic(fotg210, &here, type); + here = *prev; + } + + /* sorting each branch by period (slow-->fast) + * enables sharing interior tree nodes + */ + while (here.ptr && qh != here.qh) { + if (qh->period > here.qh->period) + break; + prev = &here.qh->qh_next; + hw_p = &here.qh->hw->hw_next; + here = *prev; + } + /* link in this qh, unless some earlier pass did that */ + if (qh != here.qh) { + qh->qh_next = here; + if (here.qh) + qh->hw->hw_next = *hw_p; + wmb(); + prev->qh = qh; + *hw_p = QH_NEXT(fotg210, qh->qh_dma); + } + } + qh->qh_state = QH_STATE_LINKED; + qh->xacterrs = 0; + + /* update per-qh bandwidth for usbfs */ + fotg210_to_hcd(fotg210)->self.bandwidth_allocated += qh->period + ? ((qh->usecs + qh->c_usecs) / qh->period) + : (qh->usecs * 8); + + list_add(&qh->intr_node, &fotg210->intr_qh_list); + + /* maybe enable periodic schedule processing */ + ++fotg210->intr_count; + enable_periodic(fotg210); +} + +static void qh_unlink_periodic(struct fotg210_hcd *fotg210, + struct fotg210_qh *qh) +{ + unsigned i; + unsigned period; + + /* + * If qh is for a low/full-speed device, simply unlinking it + * could interfere with an ongoing split transaction. To unlink + * it safely would require setting the QH_INACTIVATE bit and + * waiting at least one frame, as described in EHCI 4.12.2.5. + * + * We won't bother with any of this. Instead, we assume that the + * only reason for unlinking an interrupt QH while the current URB + * is still active is to dequeue all the URBs (flush the whole + * endpoint queue). + * + * If rebalancing the periodic schedule is ever implemented, this + * approach will no longer be valid. + */ + + /* high bandwidth, or otherwise part of every microframe */ + period = qh->period; + if (!period) + period = 1; + + for (i = qh->start; i < fotg210->periodic_size; i += period) + periodic_unlink(fotg210, i, qh); + + /* update per-qh bandwidth for usbfs */ + fotg210_to_hcd(fotg210)->self.bandwidth_allocated -= qh->period + ? ((qh->usecs + qh->c_usecs) / qh->period) + : (qh->usecs * 8); + + dev_dbg(&qh->dev->dev, + "unlink qh%d-%04x/%p start %d [%d/%d us]\n", + qh->period, + hc32_to_cpup(fotg210, &qh->hw->hw_info2) & + (QH_CMASK | QH_SMASK), qh, qh->start, qh->usecs, qh->c_usecs); + + /* qh->qh_next still "live" to HC */ + qh->qh_state = QH_STATE_UNLINK; + qh->qh_next.ptr = NULL; + + if (fotg210->qh_scan_next == qh) + fotg210->qh_scan_next = list_entry(qh->intr_node.next, + struct fotg210_qh, intr_node); + list_del(&qh->intr_node); +} + +static void start_unlink_intr(struct fotg210_hcd *fotg210, + struct fotg210_qh *qh) +{ + /* If the QH isn't linked then there's nothing we can do + * unless we were called during a giveback, in which case + * qh_completions() has to deal with it. + */ + if (qh->qh_state != QH_STATE_LINKED) { + if (qh->qh_state == QH_STATE_COMPLETING) + qh->needs_rescan = 1; + return; + } + + qh_unlink_periodic(fotg210, qh); + + /* Make sure the unlinks are visible before starting the timer */ + wmb(); + + /* + * The EHCI spec doesn't say how long it takes the controller to + * stop accessing an unlinked interrupt QH. The timer delay is + * 9 uframes; presumably that will be long enough. + */ + qh->unlink_cycle = fotg210->intr_unlink_cycle; + + /* New entries go at the end of the intr_unlink list */ + if (fotg210->intr_unlink) + fotg210->intr_unlink_last->unlink_next = qh; + else + fotg210->intr_unlink = qh; + fotg210->intr_unlink_last = qh; + + if (fotg210->intr_unlinking) + ; /* Avoid recursive calls */ + else if (fotg210->rh_state < FOTG210_RH_RUNNING) + fotg210_handle_intr_unlinks(fotg210); + else if (fotg210->intr_unlink == qh) { + fotg210_enable_event(fotg210, FOTG210_HRTIMER_UNLINK_INTR, + true); + ++fotg210->intr_unlink_cycle; + } +} + +static void end_unlink_intr(struct fotg210_hcd *fotg210, struct fotg210_qh *qh) +{ + struct fotg210_qh_hw *hw = qh->hw; + int rc; + + qh->qh_state = QH_STATE_IDLE; + hw->hw_next = FOTG210_LIST_END(fotg210); + + qh_completions(fotg210, qh); + + /* reschedule QH iff another request is queued */ + if (!list_empty(&qh->qtd_list) && + fotg210->rh_state == FOTG210_RH_RUNNING) { + rc = qh_schedule(fotg210, qh); + + /* An error here likely indicates handshake failure + * or no space left in the schedule. Neither fault + * should happen often ... + * + * FIXME kill the now-dysfunctional queued urbs + */ + if (rc != 0) + fotg210_err(fotg210, "can't reschedule qh %p, err %d\n", + qh, rc); + } + + /* maybe turn off periodic schedule */ + --fotg210->intr_count; + disable_periodic(fotg210); +} + +/*-------------------------------------------------------------------------*/ + +static int check_period( + struct fotg210_hcd *fotg210, + unsigned frame, + unsigned uframe, + unsigned period, + unsigned usecs +) { + int claimed; + + /* complete split running into next frame? + * given FSTN support, we could sometimes check... + */ + if (uframe >= 8) + return 0; + + /* convert "usecs we need" to "max already claimed" */ + usecs = fotg210->uframe_periodic_max - usecs; + + /* we "know" 2 and 4 uframe intervals were rejected; so + * for period 0, check _every_ microframe in the schedule. + */ + if (unlikely(period == 0)) { + do { + for (uframe = 0; uframe < 7; uframe++) { + claimed = periodic_usecs(fotg210, frame, + uframe); + if (claimed > usecs) + return 0; + } + } while ((frame += 1) < fotg210->periodic_size); + + /* just check the specified uframe, at that period */ + } else { + do { + claimed = periodic_usecs(fotg210, frame, uframe); + if (claimed > usecs) + return 0; + } while ((frame += period) < fotg210->periodic_size); + } + + /* success! */ + return 1; +} + +static int check_intr_schedule( + struct fotg210_hcd *fotg210, + unsigned frame, + unsigned uframe, + const struct fotg210_qh *qh, + __hc32 *c_maskp +) +{ + int retval = -ENOSPC; + u8 mask = 0; + + if (qh->c_usecs && uframe >= 6) /* FSTN territory? */ + goto done; + + if (!check_period(fotg210, frame, uframe, qh->period, qh->usecs)) + goto done; + if (!qh->c_usecs) { + retval = 0; + *c_maskp = 0; + goto done; + } + + /* Make sure this tt's buffer is also available for CSPLITs. + * We pessimize a bit; probably the typical full speed case + * doesn't need the second CSPLIT. + * + * NOTE: both SPLIT and CSPLIT could be checked in just + * one smart pass... + */ + mask = 0x03 << (uframe + qh->gap_uf); + *c_maskp = cpu_to_hc32(fotg210, mask << 8); + + mask |= 1 << uframe; + if (tt_no_collision(fotg210, qh->period, qh->dev, frame, mask)) { + if (!check_period(fotg210, frame, uframe + qh->gap_uf + 1, + qh->period, qh->c_usecs)) + goto done; + if (!check_period(fotg210, frame, uframe + qh->gap_uf, + qh->period, qh->c_usecs)) + goto done; + retval = 0; + } +done: + return retval; +} + +/* "first fit" scheduling policy used the first time through, + * or when the previous schedule slot can't be re-used. + */ +static int qh_schedule(struct fotg210_hcd *fotg210, struct fotg210_qh *qh) +{ + int status; + unsigned uframe; + __hc32 c_mask; + unsigned frame; /* 0..(qh->period - 1), or NO_FRAME */ + struct fotg210_qh_hw *hw = qh->hw; + + qh_refresh(fotg210, qh); + hw->hw_next = FOTG210_LIST_END(fotg210); + frame = qh->start; + + /* reuse the previous schedule slots, if we can */ + if (frame < qh->period) { + uframe = ffs(hc32_to_cpup(fotg210, &hw->hw_info2) & QH_SMASK); + status = check_intr_schedule(fotg210, frame, --uframe, + qh, &c_mask); + } else { + uframe = 0; + c_mask = 0; + status = -ENOSPC; + } + + /* else scan the schedule to find a group of slots such that all + * uframes have enough periodic bandwidth available. + */ + if (status) { + /* "normal" case, uframing flexible except with splits */ + if (qh->period) { + int i; + + for (i = qh->period; status && i > 0; --i) { + frame = ++fotg210->random_frame % qh->period; + for (uframe = 0; uframe < 8; uframe++) { + status = check_intr_schedule(fotg210, + frame, uframe, qh, + &c_mask); + if (status == 0) + break; + } + } + + /* qh->period == 0 means every uframe */ + } else { + frame = 0; + status = check_intr_schedule(fotg210, 0, 0, qh, + &c_mask); + } + if (status) + goto done; + qh->start = frame; + + /* reset S-frame and (maybe) C-frame masks */ + hw->hw_info2 &= cpu_to_hc32(fotg210, ~(QH_CMASK | QH_SMASK)); + hw->hw_info2 |= qh->period + ? cpu_to_hc32(fotg210, 1 << uframe) + : cpu_to_hc32(fotg210, QH_SMASK); + hw->hw_info2 |= c_mask; + } else + fotg210_dbg(fotg210, "reused qh %p schedule\n", qh); + + /* stuff into the periodic schedule */ + qh_link_periodic(fotg210, qh); +done: + return status; +} + +static int intr_submit( + struct fotg210_hcd *fotg210, + struct urb *urb, + struct list_head *qtd_list, + gfp_t mem_flags +) { + unsigned epnum; + unsigned long flags; + struct fotg210_qh *qh; + int status; + struct list_head empty; + + /* get endpoint and transfer/schedule data */ + epnum = urb->ep->desc.bEndpointAddress; + + spin_lock_irqsave(&fotg210->lock, flags); + + if (unlikely(!HCD_HW_ACCESSIBLE(fotg210_to_hcd(fotg210)))) { + status = -ESHUTDOWN; + goto done_not_linked; + } + status = usb_hcd_link_urb_to_ep(fotg210_to_hcd(fotg210), urb); + if (unlikely(status)) + goto done_not_linked; + + /* get qh and force any scheduling errors */ + INIT_LIST_HEAD(&empty); + qh = qh_append_tds(fotg210, urb, &empty, epnum, &urb->ep->hcpriv); + if (qh == NULL) { + status = -ENOMEM; + goto done; + } + if (qh->qh_state == QH_STATE_IDLE) { + status = qh_schedule(fotg210, qh); + if (status) + goto done; + } + + /* then queue the urb's tds to the qh */ + qh = qh_append_tds(fotg210, urb, qtd_list, epnum, &urb->ep->hcpriv); + BUG_ON(qh == NULL); + + /* ... update usbfs periodic stats */ + fotg210_to_hcd(fotg210)->self.bandwidth_int_reqs++; + +done: + if (unlikely(status)) + usb_hcd_unlink_urb_from_ep(fotg210_to_hcd(fotg210), urb); +done_not_linked: + spin_unlock_irqrestore(&fotg210->lock, flags); + if (status) + qtd_list_free(fotg210, urb, qtd_list); + + return status; +} + +static void scan_intr(struct fotg210_hcd *fotg210) +{ + struct fotg210_qh *qh; + + list_for_each_entry_safe(qh, fotg210->qh_scan_next, + &fotg210->intr_qh_list, intr_node) { + rescan: + /* clean any finished work for this qh */ + if (!list_empty(&qh->qtd_list)) { + int temp; + + /* + * Unlinks could happen here; completion reporting + * drops the lock. That's why fotg210->qh_scan_next + * always holds the next qh to scan; if the next qh + * gets unlinked then fotg210->qh_scan_next is adjusted + * in qh_unlink_periodic(). + */ + temp = qh_completions(fotg210, qh); + if (unlikely(qh->needs_rescan || + (list_empty(&qh->qtd_list) && + qh->qh_state == QH_STATE_LINKED))) + start_unlink_intr(fotg210, qh); + else if (temp != 0) + goto rescan; + } + } +} + +/*-------------------------------------------------------------------------*/ + +/* fotg210_iso_stream ops work with both ITD and SITD */ + +static struct fotg210_iso_stream * +iso_stream_alloc(gfp_t mem_flags) +{ + struct fotg210_iso_stream *stream; + + stream = kzalloc(sizeof(*stream), mem_flags); + if (likely(stream != NULL)) { + INIT_LIST_HEAD(&stream->td_list); + INIT_LIST_HEAD(&stream->free_list); + stream->next_uframe = -1; + } + return stream; +} + +static void +iso_stream_init( + struct fotg210_hcd *fotg210, + struct fotg210_iso_stream *stream, + struct usb_device *dev, + int pipe, + unsigned interval +) +{ + u32 buf1; + unsigned epnum, maxp; + int is_input; + long bandwidth; + unsigned multi; + + /* + * this might be a "high bandwidth" highspeed endpoint, + * as encoded in the ep descriptor's wMaxPacket field + */ + epnum = usb_pipeendpoint(pipe); + is_input = usb_pipein(pipe) ? USB_DIR_IN : 0; + maxp = usb_maxpacket(dev, pipe, !is_input); + if (is_input) + buf1 = (1 << 11); + else + buf1 = 0; + + maxp = max_packet(maxp); + multi = hb_mult(maxp); + buf1 |= maxp; + maxp *= multi; + + stream->buf0 = cpu_to_hc32(fotg210, (epnum << 8) | dev->devnum); + stream->buf1 = cpu_to_hc32(fotg210, buf1); + stream->buf2 = cpu_to_hc32(fotg210, multi); + + /* usbfs wants to report the average usecs per frame tied up + * when transfers on this endpoint are scheduled ... + */ + if (dev->speed == USB_SPEED_FULL) { + interval <<= 3; + stream->usecs = NS_TO_US(usb_calc_bus_time(dev->speed, + is_input, 1, maxp)); + stream->usecs /= 8; + } else { + stream->highspeed = 1; + stream->usecs = HS_USECS_ISO(maxp); + } + bandwidth = stream->usecs * 8; + bandwidth /= interval; + + stream->bandwidth = bandwidth; + stream->udev = dev; + stream->bEndpointAddress = is_input | epnum; + stream->interval = interval; + stream->maxp = maxp; +} + +static struct fotg210_iso_stream * +iso_stream_find(struct fotg210_hcd *fotg210, struct urb *urb) +{ + unsigned epnum; + struct fotg210_iso_stream *stream; + struct usb_host_endpoint *ep; + unsigned long flags; + + epnum = usb_pipeendpoint(urb->pipe); + if (usb_pipein(urb->pipe)) + ep = urb->dev->ep_in[epnum]; + else + ep = urb->dev->ep_out[epnum]; + + spin_lock_irqsave(&fotg210->lock, flags); + stream = ep->hcpriv; + + if (unlikely(stream == NULL)) { + stream = iso_stream_alloc(GFP_ATOMIC); + if (likely(stream != NULL)) { + ep->hcpriv = stream; + stream->ep = ep; + iso_stream_init(fotg210, stream, urb->dev, urb->pipe, + urb->interval); + } + + /* if dev->ep[epnum] is a QH, hw is set */ + } else if (unlikely(stream->hw != NULL)) { + fotg210_dbg(fotg210, "dev %s ep%d%s, not iso??\n", + urb->dev->devpath, epnum, + usb_pipein(urb->pipe) ? "in" : "out"); + stream = NULL; + } + + spin_unlock_irqrestore(&fotg210->lock, flags); + return stream; +} + +/*-------------------------------------------------------------------------*/ + +/* fotg210_iso_sched ops can be ITD-only or SITD-only */ + +static struct fotg210_iso_sched * +iso_sched_alloc(unsigned packets, gfp_t mem_flags) +{ + struct fotg210_iso_sched *iso_sched; + int size = sizeof(*iso_sched); + + size += packets * sizeof(struct fotg210_iso_packet); + iso_sched = kzalloc(size, mem_flags); + if (likely(iso_sched != NULL)) + INIT_LIST_HEAD(&iso_sched->td_list); + + return iso_sched; +} + +static inline void +itd_sched_init( + struct fotg210_hcd *fotg210, + struct fotg210_iso_sched *iso_sched, + struct fotg210_iso_stream *stream, + struct urb *urb +) +{ + unsigned i; + dma_addr_t dma = urb->transfer_dma; + + /* how many uframes are needed for these transfers */ + iso_sched->span = urb->number_of_packets * stream->interval; + + /* figure out per-uframe itd fields that we'll need later + * when we fit new itds into the schedule. + */ + for (i = 0; i < urb->number_of_packets; i++) { + struct fotg210_iso_packet *uframe = &iso_sched->packet[i]; + unsigned length; + dma_addr_t buf; + u32 trans; + + length = urb->iso_frame_desc[i].length; + buf = dma + urb->iso_frame_desc[i].offset; + + trans = FOTG210_ISOC_ACTIVE; + trans |= buf & 0x0fff; + if (unlikely(((i + 1) == urb->number_of_packets)) + && !(urb->transfer_flags & URB_NO_INTERRUPT)) + trans |= FOTG210_ITD_IOC; + trans |= length << 16; + uframe->transaction = cpu_to_hc32(fotg210, trans); + + /* might need to cross a buffer page within a uframe */ + uframe->bufp = (buf & ~(u64)0x0fff); + buf += length; + if (unlikely((uframe->bufp != (buf & ~(u64)0x0fff)))) + uframe->cross = 1; + } +} + +static void +iso_sched_free( + struct fotg210_iso_stream *stream, + struct fotg210_iso_sched *iso_sched +) +{ + if (!iso_sched) + return; + /* caller must hold fotg210->lock!*/ + list_splice(&iso_sched->td_list, &stream->free_list); + kfree(iso_sched); +} + +static int +itd_urb_transaction( + struct fotg210_iso_stream *stream, + struct fotg210_hcd *fotg210, + struct urb *urb, + gfp_t mem_flags +) +{ + struct fotg210_itd *itd; + dma_addr_t itd_dma; + int i; + unsigned num_itds; + struct fotg210_iso_sched *sched; + unsigned long flags; + + sched = iso_sched_alloc(urb->number_of_packets, mem_flags); + if (unlikely(sched == NULL)) + return -ENOMEM; + + itd_sched_init(fotg210, sched, stream, urb); + + if (urb->interval < 8) + num_itds = 1 + (sched->span + 7) / 8; + else + num_itds = urb->number_of_packets; + + /* allocate/init ITDs */ + spin_lock_irqsave(&fotg210->lock, flags); + for (i = 0; i < num_itds; i++) { + + /* + * Use iTDs from the free list, but not iTDs that may + * still be in use by the hardware. + */ + if (likely(!list_empty(&stream->free_list))) { + itd = list_first_entry(&stream->free_list, + struct fotg210_itd, itd_list); + if (itd->frame == fotg210->now_frame) + goto alloc_itd; + list_del(&itd->itd_list); + itd_dma = itd->itd_dma; + } else { + alloc_itd: + spin_unlock_irqrestore(&fotg210->lock, flags); + itd = dma_pool_alloc(fotg210->itd_pool, mem_flags, + &itd_dma); + spin_lock_irqsave(&fotg210->lock, flags); + if (!itd) { + iso_sched_free(stream, sched); + spin_unlock_irqrestore(&fotg210->lock, flags); + return -ENOMEM; + } + } + + memset(itd, 0, sizeof(*itd)); + itd->itd_dma = itd_dma; + list_add(&itd->itd_list, &sched->td_list); + } + spin_unlock_irqrestore(&fotg210->lock, flags); + + /* temporarily store schedule info in hcpriv */ + urb->hcpriv = sched; + urb->error_count = 0; + return 0; +} + +/*-------------------------------------------------------------------------*/ + +static inline int +itd_slot_ok( + struct fotg210_hcd *fotg210, + u32 mod, + u32 uframe, + u8 usecs, + u32 period +) +{ + uframe %= period; + do { + /* can't commit more than uframe_periodic_max usec */ + if (periodic_usecs(fotg210, uframe >> 3, uframe & 0x7) + > (fotg210->uframe_periodic_max - usecs)) + return 0; + + /* we know urb->interval is 2^N uframes */ + uframe += period; + } while (uframe < mod); + return 1; +} + +/* + * This scheduler plans almost as far into the future as it has actual + * periodic schedule slots. (Affected by TUNE_FLS, which defaults to + * "as small as possible" to be cache-friendlier.) That limits the size + * transfers you can stream reliably; avoid more than 64 msec per urb. + * Also avoid queue depths of less than fotg210's worst irq latency (affected + * by the per-urb URB_NO_INTERRUPT hint, the log2_irq_thresh module parameter, + * and other factors); or more than about 230 msec total (for portability, + * given FOTG210_TUNE_FLS and the slop). Or, write a smarter scheduler! + */ + +#define SCHEDULE_SLOP 80 /* microframes */ + +static int +iso_stream_schedule( + struct fotg210_hcd *fotg210, + struct urb *urb, + struct fotg210_iso_stream *stream +) +{ + u32 now, next, start, period, span; + int status; + unsigned mod = fotg210->periodic_size << 3; + struct fotg210_iso_sched *sched = urb->hcpriv; + + period = urb->interval; + span = sched->span; + + if (span > mod - SCHEDULE_SLOP) { + fotg210_dbg(fotg210, "iso request %p too long\n", urb); + status = -EFBIG; + goto fail; + } + + now = fotg210_read_frame_index(fotg210) & (mod - 1); + + /* Typical case: reuse current schedule, stream is still active. + * Hopefully there are no gaps from the host falling behind + * (irq delays etc), but if there are we'll take the next + * slot in the schedule, implicitly assuming URB_ISO_ASAP. + */ + if (likely(!list_empty(&stream->td_list))) { + u32 excess; + + /* For high speed devices, allow scheduling within the + * isochronous scheduling threshold. For full speed devices + * and Intel PCI-based controllers, don't (work around for + * Intel ICH9 bug). + */ + if (!stream->highspeed && fotg210->fs_i_thresh) + next = now + fotg210->i_thresh; + else + next = now; + + /* Fell behind (by up to twice the slop amount)? + * We decide based on the time of the last currently-scheduled + * slot, not the time of the next available slot. + */ + excess = (stream->next_uframe - period - next) & (mod - 1); + if (excess >= mod - 2 * SCHEDULE_SLOP) + start = next + excess - mod + period * + DIV_ROUND_UP(mod - excess, period); + else + start = next + excess + period; + if (start - now >= mod) { + fotg210_dbg(fotg210, "request %p would overflow (%d+%d >= %d)\n", + urb, start - now - period, period, + mod); + status = -EFBIG; + goto fail; + } + } + + /* need to schedule; when's the next (u)frame we could start? + * this is bigger than fotg210->i_thresh allows; scheduling itself + * isn't free, the slop should handle reasonably slow cpus. it + * can also help high bandwidth if the dma and irq loads don't + * jump until after the queue is primed. + */ + else { + int done = 0; + start = SCHEDULE_SLOP + (now & ~0x07); + + /* NOTE: assumes URB_ISO_ASAP, to limit complexity/bugs */ + + /* find a uframe slot with enough bandwidth. + * Early uframes are more precious because full-speed + * iso IN transfers can't use late uframes, + * and therefore they should be allocated last. + */ + next = start; + start += period; + do { + start--; + /* check schedule: enough space? */ + if (itd_slot_ok(fotg210, mod, start, + stream->usecs, period)) + done = 1; + } while (start > next && !done); + + /* no room in the schedule */ + if (!done) { + fotg210_dbg(fotg210, "iso resched full %p (now %d max %d)\n", + urb, now, now + mod); + status = -ENOSPC; + goto fail; + } + } + + /* Tried to schedule too far into the future? */ + if (unlikely(start - now + span - period + >= mod - 2 * SCHEDULE_SLOP)) { + fotg210_dbg(fotg210, "request %p would overflow (%d+%d >= %d)\n", + urb, start - now, span - period, + mod - 2 * SCHEDULE_SLOP); + status = -EFBIG; + goto fail; + } + + stream->next_uframe = start & (mod - 1); + + /* report high speed start in uframes; full speed, in frames */ + urb->start_frame = stream->next_uframe; + if (!stream->highspeed) + urb->start_frame >>= 3; + + /* Make sure scan_isoc() sees these */ + if (fotg210->isoc_count == 0) + fotg210->next_frame = now >> 3; + return 0; + + fail: + iso_sched_free(stream, sched); + urb->hcpriv = NULL; + return status; +} + +/*-------------------------------------------------------------------------*/ + +static inline void +itd_init(struct fotg210_hcd *fotg210, struct fotg210_iso_stream *stream, + struct fotg210_itd *itd) +{ + int i; + + /* it's been recently zeroed */ + itd->hw_next = FOTG210_LIST_END(fotg210); + itd->hw_bufp[0] = stream->buf0; + itd->hw_bufp[1] = stream->buf1; + itd->hw_bufp[2] = stream->buf2; + + for (i = 0; i < 8; i++) + itd->index[i] = -1; + + /* All other fields are filled when scheduling */ +} + +static inline void +itd_patch( + struct fotg210_hcd *fotg210, + struct fotg210_itd *itd, + struct fotg210_iso_sched *iso_sched, + unsigned index, + u16 uframe +) +{ + struct fotg210_iso_packet *uf = &iso_sched->packet[index]; + unsigned pg = itd->pg; + + uframe &= 0x07; + itd->index[uframe] = index; + + itd->hw_transaction[uframe] = uf->transaction; + itd->hw_transaction[uframe] |= cpu_to_hc32(fotg210, pg << 12); + itd->hw_bufp[pg] |= cpu_to_hc32(fotg210, uf->bufp & ~(u32)0); + itd->hw_bufp_hi[pg] |= cpu_to_hc32(fotg210, (u32)(uf->bufp >> 32)); + + /* iso_frame_desc[].offset must be strictly increasing */ + if (unlikely(uf->cross)) { + u64 bufp = uf->bufp + 4096; + + itd->pg = ++pg; + itd->hw_bufp[pg] |= cpu_to_hc32(fotg210, bufp & ~(u32)0); + itd->hw_bufp_hi[pg] |= cpu_to_hc32(fotg210, (u32)(bufp >> 32)); + } +} + +static inline void +itd_link(struct fotg210_hcd *fotg210, unsigned frame, struct fotg210_itd *itd) +{ + union fotg210_shadow *prev = &fotg210->pshadow[frame]; + __hc32 *hw_p = &fotg210->periodic[frame]; + union fotg210_shadow here = *prev; + __hc32 type = 0; + + /* skip any iso nodes which might belong to previous microframes */ + while (here.ptr) { + type = Q_NEXT_TYPE(fotg210, *hw_p); + if (type == cpu_to_hc32(fotg210, Q_TYPE_QH)) + break; + prev = periodic_next_shadow(fotg210, prev, type); + hw_p = shadow_next_periodic(fotg210, &here, type); + here = *prev; + } + + itd->itd_next = here; + itd->hw_next = *hw_p; + prev->itd = itd; + itd->frame = frame; + wmb(); + *hw_p = cpu_to_hc32(fotg210, itd->itd_dma | Q_TYPE_ITD); +} + +/* fit urb's itds into the selected schedule slot; activate as needed */ +static void itd_link_urb( + struct fotg210_hcd *fotg210, + struct urb *urb, + unsigned mod, + struct fotg210_iso_stream *stream +) +{ + int packet; + unsigned next_uframe, uframe, frame; + struct fotg210_iso_sched *iso_sched = urb->hcpriv; + struct fotg210_itd *itd; + + next_uframe = stream->next_uframe & (mod - 1); + + if (unlikely(list_empty(&stream->td_list))) { + fotg210_to_hcd(fotg210)->self.bandwidth_allocated + += stream->bandwidth; + fotg210_vdbg(fotg210, + "schedule devp %s ep%d%s-iso period %d start %d.%d\n", + urb->dev->devpath, stream->bEndpointAddress & 0x0f, + (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out", + urb->interval, + next_uframe >> 3, next_uframe & 0x7); + } + + /* fill iTDs uframe by uframe */ + for (packet = 0, itd = NULL; packet < urb->number_of_packets;) { + if (itd == NULL) { + /* ASSERT: we have all necessary itds */ + + /* ASSERT: no itds for this endpoint in this uframe */ + + itd = list_entry(iso_sched->td_list.next, + struct fotg210_itd, itd_list); + list_move_tail(&itd->itd_list, &stream->td_list); + itd->stream = stream; + itd->urb = urb; + itd_init(fotg210, stream, itd); + } + + uframe = next_uframe & 0x07; + frame = next_uframe >> 3; + + itd_patch(fotg210, itd, iso_sched, packet, uframe); + + next_uframe += stream->interval; + next_uframe &= mod - 1; + packet++; + + /* link completed itds into the schedule */ + if (((next_uframe >> 3) != frame) + || packet == urb->number_of_packets) { + itd_link(fotg210, frame & (fotg210->periodic_size - 1), + itd); + itd = NULL; + } + } + stream->next_uframe = next_uframe; + + /* don't need that schedule data any more */ + iso_sched_free(stream, iso_sched); + urb->hcpriv = NULL; + + ++fotg210->isoc_count; + enable_periodic(fotg210); +} + +#define ISO_ERRS (FOTG210_ISOC_BUF_ERR | FOTG210_ISOC_BABBLE |\ + FOTG210_ISOC_XACTERR) + +/* Process and recycle a completed ITD. Return true iff its urb completed, + * and hence its completion callback probably added things to the hardware + * schedule. + * + * Note that we carefully avoid recycling this descriptor until after any + * completion callback runs, so that it won't be reused quickly. That is, + * assuming (a) no more than two urbs per frame on this endpoint, and also + * (b) only this endpoint's completions submit URBs. It seems some silicon + * corrupts things if you reuse completed descriptors very quickly... + */ +static bool itd_complete(struct fotg210_hcd *fotg210, struct fotg210_itd *itd) +{ + struct urb *urb = itd->urb; + struct usb_iso_packet_descriptor *desc; + u32 t; + unsigned uframe; + int urb_index = -1; + struct fotg210_iso_stream *stream = itd->stream; + struct usb_device *dev; + bool retval = false; + + /* for each uframe with a packet */ + for (uframe = 0; uframe < 8; uframe++) { + if (likely(itd->index[uframe] == -1)) + continue; + urb_index = itd->index[uframe]; + desc = &urb->iso_frame_desc[urb_index]; + + t = hc32_to_cpup(fotg210, &itd->hw_transaction[uframe]); + itd->hw_transaction[uframe] = 0; + + /* report transfer status */ + if (unlikely(t & ISO_ERRS)) { + urb->error_count++; + if (t & FOTG210_ISOC_BUF_ERR) + desc->status = usb_pipein(urb->pipe) + ? -ENOSR /* hc couldn't read */ + : -ECOMM; /* hc couldn't write */ + else if (t & FOTG210_ISOC_BABBLE) + desc->status = -EOVERFLOW; + else /* (t & FOTG210_ISOC_XACTERR) */ + desc->status = -EPROTO; + + /* HC need not update length with this error */ + if (!(t & FOTG210_ISOC_BABBLE)) { + desc->actual_length = + fotg210_itdlen(urb, desc, t); + urb->actual_length += desc->actual_length; + } + } else if (likely((t & FOTG210_ISOC_ACTIVE) == 0)) { + desc->status = 0; + desc->actual_length = fotg210_itdlen(urb, desc, t); + urb->actual_length += desc->actual_length; + } else { + /* URB was too late */ + desc->status = -EXDEV; + } + } + + /* handle completion now? */ + if (likely((urb_index + 1) != urb->number_of_packets)) + goto done; + + /* ASSERT: it's really the last itd for this urb + list_for_each_entry (itd, &stream->td_list, itd_list) + BUG_ON (itd->urb == urb); + */ + + /* give urb back to the driver; completion often (re)submits */ + dev = urb->dev; + fotg210_urb_done(fotg210, urb, 0); + retval = true; + urb = NULL; + + --fotg210->isoc_count; + disable_periodic(fotg210); + + if (unlikely(list_is_singular(&stream->td_list))) { + fotg210_to_hcd(fotg210)->self.bandwidth_allocated + -= stream->bandwidth; + fotg210_vdbg(fotg210, + "deschedule devp %s ep%d%s-iso\n", + dev->devpath, stream->bEndpointAddress & 0x0f, + (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out"); + } + +done: + itd->urb = NULL; + + /* Add to the end of the free list for later reuse */ + list_move_tail(&itd->itd_list, &stream->free_list); + + /* Recycle the iTDs when the pipeline is empty (ep no longer in use) */ + if (list_empty(&stream->td_list)) { + list_splice_tail_init(&stream->free_list, + &fotg210->cached_itd_list); + start_free_itds(fotg210); + } + + return retval; +} + +/*-------------------------------------------------------------------------*/ + +static int itd_submit(struct fotg210_hcd *fotg210, struct urb *urb, + gfp_t mem_flags) +{ + int status = -EINVAL; + unsigned long flags; + struct fotg210_iso_stream *stream; + + /* Get iso_stream head */ + stream = iso_stream_find(fotg210, urb); + if (unlikely(stream == NULL)) { + fotg210_dbg(fotg210, "can't get iso stream\n"); + return -ENOMEM; + } + if (unlikely(urb->interval != stream->interval && + fotg210_port_speed(fotg210, 0) == + USB_PORT_STAT_HIGH_SPEED)) { + fotg210_dbg(fotg210, "can't change iso interval %d --> %d\n", + stream->interval, urb->interval); + goto done; + } + +#ifdef FOTG210_URB_TRACE + fotg210_dbg(fotg210, + "%s %s urb %p ep%d%s len %d, %d pkts %d uframes[%p]\n", + __func__, urb->dev->devpath, urb, + usb_pipeendpoint(urb->pipe), + usb_pipein(urb->pipe) ? "in" : "out", + urb->transfer_buffer_length, + urb->number_of_packets, urb->interval, + stream); +#endif + + /* allocate ITDs w/o locking anything */ + status = itd_urb_transaction(stream, fotg210, urb, mem_flags); + if (unlikely(status < 0)) { + fotg210_dbg(fotg210, "can't init itds\n"); + goto done; + } + + /* schedule ... need to lock */ + spin_lock_irqsave(&fotg210->lock, flags); + if (unlikely(!HCD_HW_ACCESSIBLE(fotg210_to_hcd(fotg210)))) { + status = -ESHUTDOWN; + goto done_not_linked; + } + status = usb_hcd_link_urb_to_ep(fotg210_to_hcd(fotg210), urb); + if (unlikely(status)) + goto done_not_linked; + status = iso_stream_schedule(fotg210, urb, stream); + if (likely(status == 0)) + itd_link_urb(fotg210, urb, fotg210->periodic_size << 3, stream); + else + usb_hcd_unlink_urb_from_ep(fotg210_to_hcd(fotg210), urb); + done_not_linked: + spin_unlock_irqrestore(&fotg210->lock, flags); + done: + return status; +} + +/*-------------------------------------------------------------------------*/ + +static void scan_isoc(struct fotg210_hcd *fotg210) +{ + unsigned uf, now_frame, frame; + unsigned fmask = fotg210->periodic_size - 1; + bool modified, live; + + /* + * When running, scan from last scan point up to "now" + * else clean up by scanning everything that's left. + * Touches as few pages as possible: cache-friendly. + */ + if (fotg210->rh_state >= FOTG210_RH_RUNNING) { + uf = fotg210_read_frame_index(fotg210); + now_frame = (uf >> 3) & fmask; + live = true; + } else { + now_frame = (fotg210->next_frame - 1) & fmask; + live = false; + } + fotg210->now_frame = now_frame; + + frame = fotg210->next_frame; + for (;;) { + union fotg210_shadow q, *q_p; + __hc32 type, *hw_p; + +restart: + /* scan each element in frame's queue for completions */ + q_p = &fotg210->pshadow[frame]; + hw_p = &fotg210->periodic[frame]; + q.ptr = q_p->ptr; + type = Q_NEXT_TYPE(fotg210, *hw_p); + modified = false; + + while (q.ptr != NULL) { + switch (hc32_to_cpu(fotg210, type)) { + case Q_TYPE_ITD: + /* If this ITD is still active, leave it for + * later processing ... check the next entry. + * No need to check for activity unless the + * frame is current. + */ + if (frame == now_frame && live) { + rmb(); + for (uf = 0; uf < 8; uf++) { + if (q.itd->hw_transaction[uf] & + ITD_ACTIVE(fotg210)) + break; + } + if (uf < 8) { + q_p = &q.itd->itd_next; + hw_p = &q.itd->hw_next; + type = Q_NEXT_TYPE(fotg210, + q.itd->hw_next); + q = *q_p; + break; + } + } + + /* Take finished ITDs out of the schedule + * and process them: recycle, maybe report + * URB completion. HC won't cache the + * pointer for much longer, if at all. + */ + *q_p = q.itd->itd_next; + *hw_p = q.itd->hw_next; + type = Q_NEXT_TYPE(fotg210, q.itd->hw_next); + wmb(); + modified = itd_complete(fotg210, q.itd); + q = *q_p; + break; + default: + fotg210_dbg(fotg210, "corrupt type %d frame %d shadow %p\n", + type, frame, q.ptr); + /* FALL THROUGH */ + case Q_TYPE_QH: + case Q_TYPE_FSTN: + /* End of the iTDs and siTDs */ + q.ptr = NULL; + break; + } + + /* assume completion callbacks modify the queue */ + if (unlikely(modified && fotg210->isoc_count > 0)) + goto restart; + } + + /* Stop when we have reached the current frame */ + if (frame == now_frame) + break; + frame = (frame + 1) & fmask; + } + fotg210->next_frame = now_frame; +} +/*-------------------------------------------------------------------------*/ +/* + * Display / Set uframe_periodic_max + */ +static ssize_t show_uframe_periodic_max(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct fotg210_hcd *fotg210; + int n; + + fotg210 = hcd_to_fotg210(bus_to_hcd(dev_get_drvdata(dev))); + n = scnprintf(buf, PAGE_SIZE, "%d\n", fotg210->uframe_periodic_max); + return n; +} + + +static ssize_t store_uframe_periodic_max(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct fotg210_hcd *fotg210; + unsigned uframe_periodic_max; + unsigned frame, uframe; + unsigned short allocated_max; + unsigned long flags; + ssize_t ret; + + fotg210 = hcd_to_fotg210(bus_to_hcd(dev_get_drvdata(dev))); + if (kstrtouint(buf, 0, &uframe_periodic_max) < 0) + return -EINVAL; + + if (uframe_periodic_max < 100 || uframe_periodic_max >= 125) { + fotg210_info(fotg210, "rejecting invalid request for uframe_periodic_max=%u\n", + uframe_periodic_max); + return -EINVAL; + } + + ret = -EINVAL; + + /* + * lock, so that our checking does not race with possible periodic + * bandwidth allocation through submitting new urbs. + */ + spin_lock_irqsave(&fotg210->lock, flags); + + /* + * for request to decrease max periodic bandwidth, we have to check + * every microframe in the schedule to see whether the decrease is + * possible. + */ + if (uframe_periodic_max < fotg210->uframe_periodic_max) { + allocated_max = 0; + + for (frame = 0; frame < fotg210->periodic_size; ++frame) + for (uframe = 0; uframe < 7; ++uframe) + allocated_max = max(allocated_max, + periodic_usecs(fotg210, frame, uframe)); + + if (allocated_max > uframe_periodic_max) { + fotg210_info(fotg210, + "cannot decrease uframe_periodic_max becase " + "periodic bandwidth is already allocated " + "(%u > %u)\n", + allocated_max, uframe_periodic_max); + goto out_unlock; + } + } + + /* increasing is always ok */ + + fotg210_info(fotg210, "setting max periodic bandwidth to %u%% (== %u usec/uframe)\n", + 100 * uframe_periodic_max/125, uframe_periodic_max); + + if (uframe_periodic_max != 100) + fotg210_warn(fotg210, "max periodic bandwidth set is non-standard\n"); + + fotg210->uframe_periodic_max = uframe_periodic_max; + ret = count; + +out_unlock: + spin_unlock_irqrestore(&fotg210->lock, flags); + return ret; +} + +static DEVICE_ATTR(uframe_periodic_max, 0644, show_uframe_periodic_max, + store_uframe_periodic_max); + +static inline int create_sysfs_files(struct fotg210_hcd *fotg210) +{ + struct device *controller = fotg210_to_hcd(fotg210)->self.controller; + int i = 0; + + if (i) + goto out; + + i = device_create_file(controller, &dev_attr_uframe_periodic_max); +out: + return i; +} + +static inline void remove_sysfs_files(struct fotg210_hcd *fotg210) +{ + struct device *controller = fotg210_to_hcd(fotg210)->self.controller; + + device_remove_file(controller, &dev_attr_uframe_periodic_max); +} +/*-------------------------------------------------------------------------*/ + +/* On some systems, leaving remote wakeup enabled prevents system shutdown. + * The firmware seems to think that powering off is a wakeup event! + * This routine turns off remote wakeup and everything else, on all ports. + */ +static void fotg210_turn_off_all_ports(struct fotg210_hcd *fotg210) +{ + u32 __iomem *status_reg = &fotg210->regs->port_status; + + fotg210_writel(fotg210, PORT_RWC_BITS, status_reg); +} + +/* + * Halt HC, turn off all ports, and let the BIOS use the companion controllers. + * Must be called with interrupts enabled and the lock not held. + */ +static void fotg210_silence_controller(struct fotg210_hcd *fotg210) +{ + fotg210_halt(fotg210); + + spin_lock_irq(&fotg210->lock); + fotg210->rh_state = FOTG210_RH_HALTED; + fotg210_turn_off_all_ports(fotg210); + spin_unlock_irq(&fotg210->lock); +} + +/* fotg210_shutdown kick in for silicon on any bus (not just pci, etc). + * This forcibly disables dma and IRQs, helping kexec and other cases + * where the next system software may expect clean state. + */ +static void fotg210_shutdown(struct usb_hcd *hcd) +{ + struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); + + spin_lock_irq(&fotg210->lock); + fotg210->shutdown = true; + fotg210->rh_state = FOTG210_RH_STOPPING; + fotg210->enabled_hrtimer_events = 0; + spin_unlock_irq(&fotg210->lock); + + fotg210_silence_controller(fotg210); + + hrtimer_cancel(&fotg210->hrtimer); +} + +/*-------------------------------------------------------------------------*/ + +/* + * fotg210_work is called from some interrupts, timers, and so on. + * it calls driver completion functions, after dropping fotg210->lock. + */ +static void fotg210_work(struct fotg210_hcd *fotg210) +{ + /* another CPU may drop fotg210->lock during a schedule scan while + * it reports urb completions. this flag guards against bogus + * attempts at re-entrant schedule scanning. + */ + if (fotg210->scanning) { + fotg210->need_rescan = true; + return; + } + fotg210->scanning = true; + + rescan: + fotg210->need_rescan = false; + if (fotg210->async_count) + scan_async(fotg210); + if (fotg210->intr_count > 0) + scan_intr(fotg210); + if (fotg210->isoc_count > 0) + scan_isoc(fotg210); + if (fotg210->need_rescan) + goto rescan; + fotg210->scanning = false; + + /* the IO watchdog guards against hardware or driver bugs that + * misplace IRQs, and should let us run completely without IRQs. + * such lossage has been observed on both VT6202 and VT8235. + */ + turn_on_io_watchdog(fotg210); +} + +/* + * Called when the fotg210_hcd module is removed. + */ +static void fotg210_stop(struct usb_hcd *hcd) +{ + struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); + + fotg210_dbg(fotg210, "stop\n"); + + /* no more interrupts ... */ + + spin_lock_irq(&fotg210->lock); + fotg210->enabled_hrtimer_events = 0; + spin_unlock_irq(&fotg210->lock); + + fotg210_quiesce(fotg210); + fotg210_silence_controller(fotg210); + fotg210_reset(fotg210); + + hrtimer_cancel(&fotg210->hrtimer); + remove_sysfs_files(fotg210); + remove_debug_files(fotg210); + + /* root hub is shut down separately (first, when possible) */ + spin_lock_irq(&fotg210->lock); + end_free_itds(fotg210); + spin_unlock_irq(&fotg210->lock); + fotg210_mem_cleanup(fotg210); + +#ifdef FOTG210_STATS + fotg210_dbg(fotg210, "irq normal %ld err %ld iaa %ld (lost %ld)\n", + fotg210->stats.normal, fotg210->stats.error, fotg210->stats.iaa, + fotg210->stats.lost_iaa); + fotg210_dbg(fotg210, "complete %ld unlink %ld\n", + fotg210->stats.complete, fotg210->stats.unlink); +#endif + + dbg_status(fotg210, "fotg210_stop completed", + fotg210_readl(fotg210, &fotg210->regs->status)); +} + +/* one-time init, only for memory state */ +static int hcd_fotg210_init(struct usb_hcd *hcd) +{ + struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); + u32 temp; + int retval; + u32 hcc_params; + struct fotg210_qh_hw *hw; + + spin_lock_init(&fotg210->lock); + + /* + * keep io watchdog by default, those good HCDs could turn off it later + */ + fotg210->need_io_watchdog = 1; + + hrtimer_init(&fotg210->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); + fotg210->hrtimer.function = fotg210_hrtimer_func; + fotg210->next_hrtimer_event = FOTG210_HRTIMER_NO_EVENT; + + hcc_params = fotg210_readl(fotg210, &fotg210->caps->hcc_params); + + /* + * by default set standard 80% (== 100 usec/uframe) max periodic + * bandwidth as required by USB 2.0 + */ + fotg210->uframe_periodic_max = 100; + + /* + * hw default: 1K periodic list heads, one per frame. + * periodic_size can shrink by USBCMD update if hcc_params allows. + */ + fotg210->periodic_size = DEFAULT_I_TDPS; + INIT_LIST_HEAD(&fotg210->intr_qh_list); + INIT_LIST_HEAD(&fotg210->cached_itd_list); + + if (HCC_PGM_FRAMELISTLEN(hcc_params)) { + /* periodic schedule size can be smaller than default */ + switch (FOTG210_TUNE_FLS) { + case 0: + fotg210->periodic_size = 1024; + break; + case 1: + fotg210->periodic_size = 512; + break; + case 2: + fotg210->periodic_size = 256; + break; + default: + BUG(); + } + } + retval = fotg210_mem_init(fotg210, GFP_KERNEL); + if (retval < 0) + return retval; + + /* controllers may cache some of the periodic schedule ... */ + fotg210->i_thresh = 2; + + /* + * dedicate a qh for the async ring head, since we couldn't unlink + * a 'real' qh without stopping the async schedule [4.8]. use it + * as the 'reclamation list head' too. + * its dummy is used in hw_alt_next of many tds, to prevent the qh + * from automatically advancing to the next td after short reads. + */ + fotg210->async->qh_next.qh = NULL; + hw = fotg210->async->hw; + hw->hw_next = QH_NEXT(fotg210, fotg210->async->qh_dma); + hw->hw_info1 = cpu_to_hc32(fotg210, QH_HEAD); + hw->hw_token = cpu_to_hc32(fotg210, QTD_STS_HALT); + hw->hw_qtd_next = FOTG210_LIST_END(fotg210); + fotg210->async->qh_state = QH_STATE_LINKED; + hw->hw_alt_next = QTD_NEXT(fotg210, fotg210->async->dummy->qtd_dma); + + /* clear interrupt enables, set irq latency */ + if (log2_irq_thresh < 0 || log2_irq_thresh > 6) + log2_irq_thresh = 0; + temp = 1 << (16 + log2_irq_thresh); + if (HCC_CANPARK(hcc_params)) { + /* HW default park == 3, on hardware that supports it (like + * NVidia and ALI silicon), maximizes throughput on the async + * schedule by avoiding QH fetches between transfers. + * + * With fast usb storage devices and NForce2, "park" seems to + * make problems: throughput reduction (!), data errors... + */ + if (park) { + park = min_t(unsigned, park, 3); + temp |= CMD_PARK; + temp |= park << 8; + } + fotg210_dbg(fotg210, "park %d\n", park); + } + if (HCC_PGM_FRAMELISTLEN(hcc_params)) { + /* periodic schedule size can be smaller than default */ + temp &= ~(3 << 2); + temp |= (FOTG210_TUNE_FLS << 2); + } + fotg210->command = temp; + + /* Accept arbitrarily long scatter-gather lists */ + if (!(hcd->driver->flags & HCD_LOCAL_MEM)) + hcd->self.sg_tablesize = ~0; + return 0; +} + +/* start HC running; it's halted, hcd_fotg210_init() has been run (once) */ +static int fotg210_run(struct usb_hcd *hcd) +{ + struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); + u32 temp; + u32 hcc_params; + + hcd->uses_new_polling = 1; + + /* EHCI spec section 4.1 */ + + fotg210_writel(fotg210, fotg210->periodic_dma, + &fotg210->regs->frame_list); + fotg210_writel(fotg210, (u32)fotg210->async->qh_dma, + &fotg210->regs->async_next); + + /* + * hcc_params controls whether fotg210->regs->segment must (!!!) + * be used; it constrains QH/ITD/SITD and QTD locations. + * pci_pool consistent memory always uses segment zero. + * streaming mappings for I/O buffers, like pci_map_single(), + * can return segments above 4GB, if the device allows. + * + * NOTE: the dma mask is visible through dma_supported(), so + * drivers can pass this info along ... like NETIF_F_HIGHDMA, + * Scsi_Host.highmem_io, and so forth. It's readonly to all + * host side drivers though. + */ + hcc_params = fotg210_readl(fotg210, &fotg210->caps->hcc_params); + + /* + * Philips, Intel, and maybe others need CMD_RUN before the + * root hub will detect new devices (why?); NEC doesn't + */ + fotg210->command &= ~(CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET); + fotg210->command |= CMD_RUN; + fotg210_writel(fotg210, fotg210->command, &fotg210->regs->command); + dbg_cmd(fotg210, "init", fotg210->command); + + /* + * Start, enabling full USB 2.0 functionality ... usb 1.1 devices + * are explicitly handed to companion controller(s), so no TT is + * involved with the root hub. (Except where one is integrated, + * and there's no companion controller unless maybe for USB OTG.) + * + * Turning on the CF flag will transfer ownership of all ports + * from the companions to the EHCI controller. If any of the + * companions are in the middle of a port reset at the time, it + * could cause trouble. Write-locking ehci_cf_port_reset_rwsem + * guarantees that no resets are in progress. After we set CF, + * a short delay lets the hardware catch up; new resets shouldn't + * be started before the port switching actions could complete. + */ + down_write(&ehci_cf_port_reset_rwsem); + fotg210->rh_state = FOTG210_RH_RUNNING; + /* unblock posted writes */ + fotg210_readl(fotg210, &fotg210->regs->command); + msleep(5); + up_write(&ehci_cf_port_reset_rwsem); + fotg210->last_periodic_enable = ktime_get_real(); + + temp = HC_VERSION(fotg210, + fotg210_readl(fotg210, &fotg210->caps->hc_capbase)); + fotg210_info(fotg210, + "USB %x.%x started, EHCI %x.%02x\n", + ((fotg210->sbrn & 0xf0)>>4), (fotg210->sbrn & 0x0f), + temp >> 8, temp & 0xff); + + fotg210_writel(fotg210, INTR_MASK, + &fotg210->regs->intr_enable); /* Turn On Interrupts */ + + /* GRR this is run-once init(), being done every time the HC starts. + * So long as they're part of class devices, we can't do it init() + * since the class device isn't created that early. + */ + create_debug_files(fotg210); + create_sysfs_files(fotg210); + + return 0; +} + +static int fotg210_setup(struct usb_hcd *hcd) +{ + struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); + int retval; + + fotg210->regs = (void __iomem *)fotg210->caps + + HC_LENGTH(fotg210, + fotg210_readl(fotg210, &fotg210->caps->hc_capbase)); + dbg_hcs_params(fotg210, "reset"); + dbg_hcc_params(fotg210, "reset"); + + /* cache this readonly data; minimize chip reads */ + fotg210->hcs_params = fotg210_readl(fotg210, + &fotg210->caps->hcs_params); + + fotg210->sbrn = HCD_USB2; + + /* data structure init */ + retval = hcd_fotg210_init(hcd); + if (retval) + return retval; + + retval = fotg210_halt(fotg210); + if (retval) + return retval; + + fotg210_reset(fotg210); + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +static irqreturn_t fotg210_irq(struct usb_hcd *hcd) +{ + struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); + u32 status, masked_status, pcd_status = 0, cmd; + int bh; + + spin_lock(&fotg210->lock); + + status = fotg210_readl(fotg210, &fotg210->regs->status); + + /* e.g. cardbus physical eject */ + if (status == ~(u32) 0) { + fotg210_dbg(fotg210, "device removed\n"); + goto dead; + } + + /* + * We don't use STS_FLR, but some controllers don't like it to + * remain on, so mask it out along with the other status bits. + */ + masked_status = status & (INTR_MASK | STS_FLR); + + /* Shared IRQ? */ + if (!masked_status || + unlikely(fotg210->rh_state == FOTG210_RH_HALTED)) { + spin_unlock(&fotg210->lock); + return IRQ_NONE; + } + + /* clear (just) interrupts */ + fotg210_writel(fotg210, masked_status, &fotg210->regs->status); + cmd = fotg210_readl(fotg210, &fotg210->regs->command); + bh = 0; + +#ifdef VERBOSE_DEBUG + /* unrequested/ignored: Frame List Rollover */ + dbg_status(fotg210, "irq", status); +#endif + + /* INT, ERR, and IAA interrupt rates can be throttled */ + + /* normal [4.15.1.2] or error [4.15.1.1] completion */ + if (likely((status & (STS_INT|STS_ERR)) != 0)) { + if (likely((status & STS_ERR) == 0)) + COUNT(fotg210->stats.normal); + else + COUNT(fotg210->stats.error); + bh = 1; + } + + /* complete the unlinking of some qh [4.15.2.3] */ + if (status & STS_IAA) { + + /* Turn off the IAA watchdog */ + fotg210->enabled_hrtimer_events &= + ~BIT(FOTG210_HRTIMER_IAA_WATCHDOG); + + /* + * Mild optimization: Allow another IAAD to reset the + * hrtimer, if one occurs before the next expiration. + * In theory we could always cancel the hrtimer, but + * tests show that about half the time it will be reset + * for some other event anyway. + */ + if (fotg210->next_hrtimer_event == FOTG210_HRTIMER_IAA_WATCHDOG) + ++fotg210->next_hrtimer_event; + + /* guard against (alleged) silicon errata */ + if (cmd & CMD_IAAD) + fotg210_dbg(fotg210, "IAA with IAAD still set?\n"); + if (fotg210->async_iaa) { + COUNT(fotg210->stats.iaa); + end_unlink_async(fotg210); + } else + fotg210_dbg(fotg210, "IAA with nothing unlinked?\n"); + } + + /* remote wakeup [4.3.1] */ + if (status & STS_PCD) { + int pstatus; + u32 __iomem *status_reg = &fotg210->regs->port_status; + + /* kick root hub later */ + pcd_status = status; + + /* resume root hub? */ + if (fotg210->rh_state == FOTG210_RH_SUSPENDED) + usb_hcd_resume_root_hub(hcd); + + pstatus = fotg210_readl(fotg210, status_reg); + + if (test_bit(0, &fotg210->suspended_ports) && + ((pstatus & PORT_RESUME) || + !(pstatus & PORT_SUSPEND)) && + (pstatus & PORT_PE) && + fotg210->reset_done[0] == 0) { + + /* start 20 msec resume signaling from this port, + * and make khubd collect PORT_STAT_C_SUSPEND to + * stop that signaling. Use 5 ms extra for safety, + * like usb_port_resume() does. + */ + fotg210->reset_done[0] = jiffies + msecs_to_jiffies(25); + set_bit(0, &fotg210->resuming_ports); + fotg210_dbg(fotg210, "port 1 remote wakeup\n"); + mod_timer(&hcd->rh_timer, fotg210->reset_done[0]); + } + } + + /* PCI errors [4.15.2.4] */ + if (unlikely((status & STS_FATAL) != 0)) { + fotg210_err(fotg210, "fatal error\n"); + dbg_cmd(fotg210, "fatal", cmd); + dbg_status(fotg210, "fatal", status); +dead: + usb_hc_died(hcd); + + /* Don't let the controller do anything more */ + fotg210->shutdown = true; + fotg210->rh_state = FOTG210_RH_STOPPING; + fotg210->command &= ~(CMD_RUN | CMD_ASE | CMD_PSE); + fotg210_writel(fotg210, fotg210->command, + &fotg210->regs->command); + fotg210_writel(fotg210, 0, &fotg210->regs->intr_enable); + fotg210_handle_controller_death(fotg210); + + /* Handle completions when the controller stops */ + bh = 0; + } + + if (bh) + fotg210_work(fotg210); + spin_unlock(&fotg210->lock); + if (pcd_status) + usb_hcd_poll_rh_status(hcd); + return IRQ_HANDLED; +} + +/*-------------------------------------------------------------------------*/ + +/* + * non-error returns are a promise to giveback() the urb later + * we drop ownership so next owner (or urb unlink) can get it + * + * urb + dev is in hcd.self.controller.urb_list + * we're queueing TDs onto software and hardware lists + * + * hcd-specific init for hcpriv hasn't been done yet + * + * NOTE: control, bulk, and interrupt share the same code to append TDs + * to a (possibly active) QH, and the same QH scanning code. + */ +static int fotg210_urb_enqueue( + struct usb_hcd *hcd, + struct urb *urb, + gfp_t mem_flags +) { + struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); + struct list_head qtd_list; + + INIT_LIST_HEAD(&qtd_list); + + switch (usb_pipetype(urb->pipe)) { + case PIPE_CONTROL: + /* qh_completions() code doesn't handle all the fault cases + * in multi-TD control transfers. Even 1KB is rare anyway. + */ + if (urb->transfer_buffer_length > (16 * 1024)) + return -EMSGSIZE; + /* FALLTHROUGH */ + /* case PIPE_BULK: */ + default: + if (!qh_urb_transaction(fotg210, urb, &qtd_list, mem_flags)) + return -ENOMEM; + return submit_async(fotg210, urb, &qtd_list, mem_flags); + + case PIPE_INTERRUPT: + if (!qh_urb_transaction(fotg210, urb, &qtd_list, mem_flags)) + return -ENOMEM; + return intr_submit(fotg210, urb, &qtd_list, mem_flags); + + case PIPE_ISOCHRONOUS: + return itd_submit(fotg210, urb, mem_flags); + } +} + +/* remove from hardware lists + * completions normally happen asynchronously + */ + +static int fotg210_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) +{ + struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); + struct fotg210_qh *qh; + unsigned long flags; + int rc; + + spin_lock_irqsave(&fotg210->lock, flags); + rc = usb_hcd_check_unlink_urb(hcd, urb, status); + if (rc) + goto done; + + switch (usb_pipetype(urb->pipe)) { + /* case PIPE_CONTROL: */ + /* case PIPE_BULK:*/ + default: + qh = (struct fotg210_qh *) urb->hcpriv; + if (!qh) + break; + switch (qh->qh_state) { + case QH_STATE_LINKED: + case QH_STATE_COMPLETING: + start_unlink_async(fotg210, qh); + break; + case QH_STATE_UNLINK: + case QH_STATE_UNLINK_WAIT: + /* already started */ + break; + case QH_STATE_IDLE: + /* QH might be waiting for a Clear-TT-Buffer */ + qh_completions(fotg210, qh); + break; + } + break; + + case PIPE_INTERRUPT: + qh = (struct fotg210_qh *) urb->hcpriv; + if (!qh) + break; + switch (qh->qh_state) { + case QH_STATE_LINKED: + case QH_STATE_COMPLETING: + start_unlink_intr(fotg210, qh); + break; + case QH_STATE_IDLE: + qh_completions(fotg210, qh); + break; + default: + fotg210_dbg(fotg210, "bogus qh %p state %d\n", + qh, qh->qh_state); + goto done; + } + break; + + case PIPE_ISOCHRONOUS: + /* itd... */ + + /* wait till next completion, do it then. */ + /* completion irqs can wait up to 1024 msec, */ + break; + } +done: + spin_unlock_irqrestore(&fotg210->lock, flags); + return rc; +} + +/*-------------------------------------------------------------------------*/ + +/* bulk qh holds the data toggle */ + +static void +fotg210_endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep) +{ + struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); + unsigned long flags; + struct fotg210_qh *qh, *tmp; + + /* ASSERT: any requests/urbs are being unlinked */ + /* ASSERT: nobody can be submitting urbs for this any more */ + +rescan: + spin_lock_irqsave(&fotg210->lock, flags); + qh = ep->hcpriv; + if (!qh) + goto done; + + /* endpoints can be iso streams. for now, we don't + * accelerate iso completions ... so spin a while. + */ + if (qh->hw == NULL) { + struct fotg210_iso_stream *stream = ep->hcpriv; + + if (!list_empty(&stream->td_list)) + goto idle_timeout; + + /* BUG_ON(!list_empty(&stream->free_list)); */ + kfree(stream); + goto done; + } + + if (fotg210->rh_state < FOTG210_RH_RUNNING) + qh->qh_state = QH_STATE_IDLE; + switch (qh->qh_state) { + case QH_STATE_LINKED: + case QH_STATE_COMPLETING: + for (tmp = fotg210->async->qh_next.qh; + tmp && tmp != qh; + tmp = tmp->qh_next.qh) + continue; + /* periodic qh self-unlinks on empty, and a COMPLETING qh + * may already be unlinked. + */ + if (tmp) + start_unlink_async(fotg210, qh); + /* FALL THROUGH */ + case QH_STATE_UNLINK: /* wait for hw to finish? */ + case QH_STATE_UNLINK_WAIT: +idle_timeout: + spin_unlock_irqrestore(&fotg210->lock, flags); + schedule_timeout_uninterruptible(1); + goto rescan; + case QH_STATE_IDLE: /* fully unlinked */ + if (qh->clearing_tt) + goto idle_timeout; + if (list_empty(&qh->qtd_list)) { + qh_destroy(fotg210, qh); + break; + } + /* else FALL THROUGH */ + default: + /* caller was supposed to have unlinked any requests; + * that's not our job. just leak this memory. + */ + fotg210_err(fotg210, "qh %p (#%02x) state %d%s\n", + qh, ep->desc.bEndpointAddress, qh->qh_state, + list_empty(&qh->qtd_list) ? "" : "(has tds)"); + break; + } + done: + ep->hcpriv = NULL; + spin_unlock_irqrestore(&fotg210->lock, flags); +} + +static void +fotg210_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep) +{ + struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); + struct fotg210_qh *qh; + int eptype = usb_endpoint_type(&ep->desc); + int epnum = usb_endpoint_num(&ep->desc); + int is_out = usb_endpoint_dir_out(&ep->desc); + unsigned long flags; + + if (eptype != USB_ENDPOINT_XFER_BULK && eptype != USB_ENDPOINT_XFER_INT) + return; + + spin_lock_irqsave(&fotg210->lock, flags); + qh = ep->hcpriv; + + /* For Bulk and Interrupt endpoints we maintain the toggle state + * in the hardware; the toggle bits in udev aren't used at all. + * When an endpoint is reset by usb_clear_halt() we must reset + * the toggle bit in the QH. + */ + if (qh) { + usb_settoggle(qh->dev, epnum, is_out, 0); + if (!list_empty(&qh->qtd_list)) { + WARN_ONCE(1, "clear_halt for a busy endpoint\n"); + } else if (qh->qh_state == QH_STATE_LINKED || + qh->qh_state == QH_STATE_COMPLETING) { + + /* The toggle value in the QH can't be updated + * while the QH is active. Unlink it now; + * re-linking will call qh_refresh(). + */ + if (eptype == USB_ENDPOINT_XFER_BULK) + start_unlink_async(fotg210, qh); + else + start_unlink_intr(fotg210, qh); + } + } + spin_unlock_irqrestore(&fotg210->lock, flags); +} + +static int fotg210_get_frame(struct usb_hcd *hcd) +{ + struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); + return (fotg210_read_frame_index(fotg210) >> 3) % + fotg210->periodic_size; +} + +/*-------------------------------------------------------------------------*/ + +/* + * The EHCI in ChipIdea HDRC cannot be a separate module or device, + * because its registers (and irq) are shared between host/gadget/otg + * functions and in order to facilitate role switching we cannot + * give the fotg210 driver exclusive access to those. + */ +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_LICENSE("GPL"); + +static const struct hc_driver fotg210_fotg210_hc_driver = { + .description = hcd_name, + .product_desc = "Faraday USB2.0 Host Controller", + .hcd_priv_size = sizeof(struct fotg210_hcd), + + /* + * generic hardware linkage + */ + .irq = fotg210_irq, + .flags = HCD_MEMORY | HCD_USB2, + + /* + * basic lifecycle operations + */ + .reset = hcd_fotg210_init, + .start = fotg210_run, + .stop = fotg210_stop, + .shutdown = fotg210_shutdown, + + /* + * managing i/o requests and associated device resources + */ + .urb_enqueue = fotg210_urb_enqueue, + .urb_dequeue = fotg210_urb_dequeue, + .endpoint_disable = fotg210_endpoint_disable, + .endpoint_reset = fotg210_endpoint_reset, + + /* + * scheduling support + */ + .get_frame_number = fotg210_get_frame, + + /* + * root hub support + */ + .hub_status_data = fotg210_hub_status_data, + .hub_control = fotg210_hub_control, + .bus_suspend = fotg210_bus_suspend, + .bus_resume = fotg210_bus_resume, + + .relinquish_port = fotg210_relinquish_port, + .port_handed_over = fotg210_port_handed_over, + + .clear_tt_buffer_complete = fotg210_clear_tt_buffer_complete, +}; + +static void fotg210_init(struct fotg210_hcd *fotg210) +{ + u32 value; + + iowrite32(GMIR_MDEV_INT | GMIR_MOTG_INT | GMIR_INT_POLARITY, + &fotg210->regs->gmir); + + value = ioread32(&fotg210->regs->otgcsr); + value &= ~OTGCSR_A_BUS_DROP; + value |= OTGCSR_A_BUS_REQ; + iowrite32(value, &fotg210->regs->otgcsr); +} + +/** + * fotg210_hcd_probe - initialize faraday FOTG210 HCDs + * + * Allocates basic resources for this USB host controller, and + * then invokes the start() method for the HCD associated with it + * through the hotplug entry's driver_data. + */ +static int fotg210_hcd_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct usb_hcd *hcd; + struct resource *res; + int irq; + int retval = -ENODEV; + struct fotg210_hcd *fotg210; + + if (usb_disabled()) + return -ENODEV; + + pdev->dev.power.power_state = PMSG_ON; + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res) { + dev_err(dev, + "Found HC with no IRQ. Check %s setup!\n", + dev_name(dev)); + return -ENODEV; + } + + irq = res->start; + + hcd = usb_create_hcd(&fotg210_fotg210_hc_driver, dev, + dev_name(dev)); + if (!hcd) { + dev_err(dev, "failed to create hcd with err %d\n", retval); + retval = -ENOMEM; + goto fail_create_hcd; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, + "Found HC with no register addr. Check %s setup!\n", + dev_name(dev)); + retval = -ENODEV; + goto fail_request_resource; + } + + hcd->rsrc_start = res->start; + hcd->rsrc_len = resource_size(res); + hcd->has_tt = 1; + + if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, + fotg210_fotg210_hc_driver.description)) { + dev_dbg(dev, "controller already in use\n"); + retval = -EBUSY; + goto fail_request_resource; + } + + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (!res) { + dev_err(dev, + "Found HC with no register addr. Check %s setup!\n", + dev_name(dev)); + retval = -ENODEV; + goto fail_request_resource; + } + + hcd->regs = ioremap_nocache(res->start, resource_size(res)); + if (hcd->regs == NULL) { + dev_dbg(dev, "error mapping memory\n"); + retval = -EFAULT; + goto fail_ioremap; + } + + fotg210 = hcd_to_fotg210(hcd); + + fotg210->caps = hcd->regs; + + retval = fotg210_setup(hcd); + if (retval) + goto fail_add_hcd; + + fotg210_init(fotg210); + + retval = usb_add_hcd(hcd, irq, IRQF_SHARED); + if (retval) { + dev_err(dev, "failed to add hcd with err %d\n", retval); + goto fail_add_hcd; + } + + return retval; + +fail_add_hcd: + iounmap(hcd->regs); +fail_ioremap: + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); +fail_request_resource: + usb_put_hcd(hcd); +fail_create_hcd: + dev_err(dev, "init %s fail, %d\n", dev_name(dev), retval); + return retval; +} + +/** + * fotg210_hcd_remove - shutdown processing for EHCI HCDs + * @dev: USB Host Controller being removed + * + */ +static int fotg210_hcd_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct usb_hcd *hcd = dev_get_drvdata(dev); + + if (!hcd) + return 0; + + usb_remove_hcd(hcd); + iounmap(hcd->regs); + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + usb_put_hcd(hcd); + + return 0; +} + +static struct platform_driver fotg210_hcd_driver = { + .driver = { + .name = "fotg210-hcd", + }, + .probe = fotg210_hcd_probe, + .remove = fotg210_hcd_remove, +}; + +static int __init fotg210_hcd_init(void) +{ + int retval = 0; + + if (usb_disabled()) + return -ENODEV; + + pr_info("%s: " DRIVER_DESC "\n", hcd_name); + set_bit(USB_EHCI_LOADED, &usb_hcds_loaded); + if (test_bit(USB_UHCI_LOADED, &usb_hcds_loaded) || + test_bit(USB_OHCI_LOADED, &usb_hcds_loaded)) + pr_warn(KERN_WARNING "Warning! fotg210_hcd should always be loaded before uhci_hcd and ohci_hcd, not after\n"); + + pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd\n", + hcd_name, + sizeof(struct fotg210_qh), sizeof(struct fotg210_qtd), + sizeof(struct fotg210_itd)); + +#ifdef DEBUG + fotg210_debug_root = debugfs_create_dir("fotg210", usb_debug_root); + if (!fotg210_debug_root) { + retval = -ENOENT; + goto err_debug; + } +#endif + + retval = platform_driver_register(&fotg210_hcd_driver); + if (retval < 0) + goto clean; + return retval; + + platform_driver_unregister(&fotg210_hcd_driver); +clean: +#ifdef DEBUG + debugfs_remove(fotg210_debug_root); + fotg210_debug_root = NULL; +err_debug: +#endif + clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded); + return retval; +} +module_init(fotg210_hcd_init); + +static void __exit fotg210_hcd_cleanup(void) +{ + platform_driver_unregister(&fotg210_hcd_driver); +#ifdef DEBUG + debugfs_remove(fotg210_debug_root); +#endif + clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded); +} +module_exit(fotg210_hcd_cleanup); diff --git a/drivers/usb/host/fotg210.h b/drivers/usb/host/fotg210.h new file mode 100644 index 000000000000..8920f9d32564 --- /dev/null +++ b/drivers/usb/host/fotg210.h @@ -0,0 +1,750 @@ +#ifndef __LINUX_FOTG210_H +#define __LINUX_FOTG210_H + +/* definitions used for the EHCI driver */ + +/* + * __hc32 and __hc16 are "Host Controller" types, they may be equivalent to + * __leXX (normally) or __beXX (given FOTG210_BIG_ENDIAN_DESC), depending on + * the host controller implementation. + * + * To facilitate the strongest possible byte-order checking from "sparse" + * and so on, we use __leXX unless that's not practical. + */ +#define __hc32 __le32 +#define __hc16 __le16 + +/* statistics can be kept for tuning/monitoring */ +struct fotg210_stats { + /* irq usage */ + unsigned long normal; + unsigned long error; + unsigned long iaa; + unsigned long lost_iaa; + + /* termination of urbs from core */ + unsigned long complete; + unsigned long unlink; +}; + +/* fotg210_hcd->lock guards shared data against other CPUs: + * fotg210_hcd: async, unlink, periodic (and shadow), ... + * usb_host_endpoint: hcpriv + * fotg210_qh: qh_next, qtd_list + * fotg210_qtd: qtd_list + * + * Also, hold this lock when talking to HC registers or + * when updating hw_* fields in shared qh/qtd/... structures. + */ + +#define FOTG210_MAX_ROOT_PORTS 1 /* see HCS_N_PORTS */ + +/* + * fotg210_rh_state values of FOTG210_RH_RUNNING or above mean that the + * controller may be doing DMA. Lower values mean there's no DMA. + */ +enum fotg210_rh_state { + FOTG210_RH_HALTED, + FOTG210_RH_SUSPENDED, + FOTG210_RH_RUNNING, + FOTG210_RH_STOPPING +}; + +/* + * Timer events, ordered by increasing delay length. + * Always update event_delays_ns[] and event_handlers[] (defined in + * ehci-timer.c) in parallel with this list. + */ +enum fotg210_hrtimer_event { + FOTG210_HRTIMER_POLL_ASS, /* Poll for async schedule off */ + FOTG210_HRTIMER_POLL_PSS, /* Poll for periodic schedule off */ + FOTG210_HRTIMER_POLL_DEAD, /* Wait for dead controller to stop */ + FOTG210_HRTIMER_UNLINK_INTR, /* Wait for interrupt QH unlink */ + FOTG210_HRTIMER_FREE_ITDS, /* Wait for unused iTDs and siTDs */ + FOTG210_HRTIMER_ASYNC_UNLINKS, /* Unlink empty async QHs */ + FOTG210_HRTIMER_IAA_WATCHDOG, /* Handle lost IAA interrupts */ + FOTG210_HRTIMER_DISABLE_PERIODIC, /* Wait to disable periodic sched */ + FOTG210_HRTIMER_DISABLE_ASYNC, /* Wait to disable async sched */ + FOTG210_HRTIMER_IO_WATCHDOG, /* Check for missing IRQs */ + FOTG210_HRTIMER_NUM_EVENTS /* Must come last */ +}; +#define FOTG210_HRTIMER_NO_EVENT 99 + +struct fotg210_hcd { /* one per controller */ + /* timing support */ + enum fotg210_hrtimer_event next_hrtimer_event; + unsigned enabled_hrtimer_events; + ktime_t hr_timeouts[FOTG210_HRTIMER_NUM_EVENTS]; + struct hrtimer hrtimer; + + int PSS_poll_count; + int ASS_poll_count; + int died_poll_count; + + /* glue to PCI and HCD framework */ + struct fotg210_caps __iomem *caps; + struct fotg210_regs __iomem *regs; + struct fotg210_dbg_port __iomem *debug; + + __u32 hcs_params; /* cached register copy */ + spinlock_t lock; + enum fotg210_rh_state rh_state; + + /* general schedule support */ + bool scanning:1; + bool need_rescan:1; + bool intr_unlinking:1; + bool async_unlinking:1; + bool shutdown:1; + struct fotg210_qh *qh_scan_next; + + /* async schedule support */ + struct fotg210_qh *async; + struct fotg210_qh *dummy; /* For AMD quirk use */ + struct fotg210_qh *async_unlink; + struct fotg210_qh *async_unlink_last; + struct fotg210_qh *async_iaa; + unsigned async_unlink_cycle; + unsigned async_count; /* async activity count */ + + /* periodic schedule support */ +#define DEFAULT_I_TDPS 1024 /* some HCs can do less */ + unsigned periodic_size; + __hc32 *periodic; /* hw periodic table */ + dma_addr_t periodic_dma; + struct list_head intr_qh_list; + unsigned i_thresh; /* uframes HC might cache */ + + union fotg210_shadow *pshadow; /* mirror hw periodic table */ + struct fotg210_qh *intr_unlink; + struct fotg210_qh *intr_unlink_last; + unsigned intr_unlink_cycle; + unsigned now_frame; /* frame from HC hardware */ + unsigned next_frame; /* scan periodic, start here */ + unsigned intr_count; /* intr activity count */ + unsigned isoc_count; /* isoc activity count */ + unsigned periodic_count; /* periodic activity count */ + /* max periodic time per uframe */ + unsigned uframe_periodic_max; + + + /* list of itds completed while now_frame was still active */ + struct list_head cached_itd_list; + struct fotg210_itd *last_itd_to_free; + + /* per root hub port */ + unsigned long reset_done[FOTG210_MAX_ROOT_PORTS]; + + /* bit vectors (one bit per port) */ + unsigned long bus_suspended; /* which ports were + already suspended at the start of a bus suspend */ + unsigned long companion_ports; /* which ports are + dedicated to the companion controller */ + unsigned long owned_ports; /* which ports are + owned by the companion during a bus suspend */ + unsigned long port_c_suspend; /* which ports have + the change-suspend feature turned on */ + unsigned long suspended_ports; /* which ports are + suspended */ + unsigned long resuming_ports; /* which ports have + started to resume */ + + /* per-HC memory pools (could be per-bus, but ...) */ + struct dma_pool *qh_pool; /* qh per active urb */ + struct dma_pool *qtd_pool; /* one or more per qh */ + struct dma_pool *itd_pool; /* itd per iso urb */ + + unsigned random_frame; + unsigned long next_statechange; + ktime_t last_periodic_enable; + u32 command; + + /* SILICON QUIRKS */ + unsigned need_io_watchdog:1; + unsigned fs_i_thresh:1; /* Intel iso scheduling */ + + u8 sbrn; /* packed release number */ + + /* irq statistics */ +#ifdef FOTG210_STATS + struct fotg210_stats stats; +# define COUNT(x) ((x)++) +#else +# define COUNT(x) +#endif + + /* debug files */ +#ifdef DEBUG + struct dentry *debug_dir; +#endif +}; + +/* convert between an HCD pointer and the corresponding FOTG210_HCD */ +static inline struct fotg210_hcd *hcd_to_fotg210(struct usb_hcd *hcd) +{ + return (struct fotg210_hcd *)(hcd->hcd_priv); +} +static inline struct usb_hcd *fotg210_to_hcd(struct fotg210_hcd *fotg210) +{ + return container_of((void *) fotg210, struct usb_hcd, hcd_priv); +} + +/*-------------------------------------------------------------------------*/ + +/* EHCI register interface, corresponds to EHCI Revision 0.95 specification */ + +/* Section 2.2 Host Controller Capability Registers */ +struct fotg210_caps { + /* these fields are specified as 8 and 16 bit registers, + * but some hosts can't perform 8 or 16 bit PCI accesses. + * some hosts treat caplength and hciversion as parts of a 32-bit + * register, others treat them as two separate registers, this + * affects the memory map for big endian controllers. + */ + u32 hc_capbase; +#define HC_LENGTH(fotg210, p) (0x00ff&((p) >> /* bits 7:0 / offset 00h */ \ + (fotg210_big_endian_capbase(fotg210) ? 24 : 0))) +#define HC_VERSION(fotg210, p) (0xffff&((p) >> /* bits 31:16 / offset 02h */ \ + (fotg210_big_endian_capbase(fotg210) ? 0 : 16))) + u32 hcs_params; /* HCSPARAMS - offset 0x4 */ +#define HCS_N_PORTS(p) (((p)>>0)&0xf) /* bits 3:0, ports on HC */ + + u32 hcc_params; /* HCCPARAMS - offset 0x8 */ +#define HCC_CANPARK(p) ((p)&(1 << 2)) /* true: can park on async qh */ +#define HCC_PGM_FRAMELISTLEN(p) ((p)&(1 << 1)) /* true: periodic_size changes*/ + u8 portroute[8]; /* nibbles for routing - offset 0xC */ +}; + + +/* Section 2.3 Host Controller Operational Registers */ +struct fotg210_regs { + + /* USBCMD: offset 0x00 */ + u32 command; + +/* EHCI 1.1 addendum */ +/* 23:16 is r/w intr rate, in microframes; default "8" == 1/msec */ +#define CMD_PARK (1<<11) /* enable "park" on async qh */ +#define CMD_PARK_CNT(c) (((c)>>8)&3) /* how many transfers to park for */ +#define CMD_IAAD (1<<6) /* "doorbell" interrupt async advance */ +#define CMD_ASE (1<<5) /* async schedule enable */ +#define CMD_PSE (1<<4) /* periodic schedule enable */ +/* 3:2 is periodic frame list size */ +#define CMD_RESET (1<<1) /* reset HC not bus */ +#define CMD_RUN (1<<0) /* start/stop HC */ + + /* USBSTS: offset 0x04 */ + u32 status; +#define STS_ASS (1<<15) /* Async Schedule Status */ +#define STS_PSS (1<<14) /* Periodic Schedule Status */ +#define STS_RECL (1<<13) /* Reclamation */ +#define STS_HALT (1<<12) /* Not running (any reason) */ +/* some bits reserved */ + /* these STS_* flags are also intr_enable bits (USBINTR) */ +#define STS_IAA (1<<5) /* Interrupted on async advance */ +#define STS_FATAL (1<<4) /* such as some PCI access errors */ +#define STS_FLR (1<<3) /* frame list rolled over */ +#define STS_PCD (1<<2) /* port change detect */ +#define STS_ERR (1<<1) /* "error" completion (overflow, ...) */ +#define STS_INT (1<<0) /* "normal" completion (short, ...) */ + + /* USBINTR: offset 0x08 */ + u32 intr_enable; + + /* FRINDEX: offset 0x0C */ + u32 frame_index; /* current microframe number */ + /* CTRLDSSEGMENT: offset 0x10 */ + u32 segment; /* address bits 63:32 if needed */ + /* PERIODICLISTBASE: offset 0x14 */ + u32 frame_list; /* points to periodic list */ + /* ASYNCLISTADDR: offset 0x18 */ + u32 async_next; /* address of next async queue head */ + + u32 reserved1; + /* PORTSC: offset 0x20 */ + u32 port_status; +/* 31:23 reserved */ +#define PORT_USB11(x) (((x)&(3<<10)) == (1<<10)) /* USB 1.1 device */ +#define PORT_RESET (1<<8) /* reset port */ +#define PORT_SUSPEND (1<<7) /* suspend port */ +#define PORT_RESUME (1<<6) /* resume it */ +#define PORT_PEC (1<<3) /* port enable change */ +#define PORT_PE (1<<2) /* port enable */ +#define PORT_CSC (1<<1) /* connect status change */ +#define PORT_CONNECT (1<<0) /* device connected */ +#define PORT_RWC_BITS (PORT_CSC | PORT_PEC) + u32 reserved2[19]; + + /* OTGCSR: offet 0x70 */ + u32 otgcsr; +#define OTGCSR_HOST_SPD_TYP (3 << 22) +#define OTGCSR_A_BUS_DROP (1 << 5) +#define OTGCSR_A_BUS_REQ (1 << 4) + + /* OTGISR: offset 0x74 */ + u32 otgisr; +#define OTGISR_OVC (1 << 10) + + u32 reserved3[15]; + + /* GMIR: offset 0xB4 */ + u32 gmir; +#define GMIR_INT_POLARITY (1 << 3) /*Active High*/ +#define GMIR_MHC_INT (1 << 2) +#define GMIR_MOTG_INT (1 << 1) +#define GMIR_MDEV_INT (1 << 0) +}; + +/* Appendix C, Debug port ... intended for use with special "debug devices" + * that can help if there's no serial console. (nonstandard enumeration.) + */ +struct fotg210_dbg_port { + u32 control; +#define DBGP_OWNER (1<<30) +#define DBGP_ENABLED (1<<28) +#define DBGP_DONE (1<<16) +#define DBGP_INUSE (1<<10) +#define DBGP_ERRCODE(x) (((x)>>7)&0x07) +# define DBGP_ERR_BAD 1 +# define DBGP_ERR_SIGNAL 2 +#define DBGP_ERROR (1<<6) +#define DBGP_GO (1<<5) +#define DBGP_OUT (1<<4) +#define DBGP_LEN(x) (((x)>>0)&0x0f) + u32 pids; +#define DBGP_PID_GET(x) (((x)>>16)&0xff) +#define DBGP_PID_SET(data, tok) (((data)<<8)|(tok)) + u32 data03; + u32 data47; + u32 address; +#define DBGP_EPADDR(dev, ep) (((dev)<<8)|(ep)) +}; + +#ifdef CONFIG_EARLY_PRINTK_DBGP +#include +extern int __init early_dbgp_init(char *s); +extern struct console early_dbgp_console; +#endif /* CONFIG_EARLY_PRINTK_DBGP */ + +struct usb_hcd; + +static inline int xen_dbgp_reset_prep(struct usb_hcd *hcd) +{ + return 1; /* Shouldn't this be 0? */ +} + +static inline int xen_dbgp_external_startup(struct usb_hcd *hcd) +{ + return -1; +} + +#ifdef CONFIG_EARLY_PRINTK_DBGP +/* Call backs from fotg210 host driver to fotg210 debug driver */ +extern int dbgp_external_startup(struct usb_hcd *); +extern int dbgp_reset_prep(struct usb_hcd *hcd); +#else +static inline int dbgp_reset_prep(struct usb_hcd *hcd) +{ + return xen_dbgp_reset_prep(hcd); +} +static inline int dbgp_external_startup(struct usb_hcd *hcd) +{ + return xen_dbgp_external_startup(hcd); +} +#endif + +/*-------------------------------------------------------------------------*/ + +#define QTD_NEXT(fotg210, dma) cpu_to_hc32(fotg210, (u32)dma) + +/* + * EHCI Specification 0.95 Section 3.5 + * QTD: describe data transfer components (buffer, direction, ...) + * See Fig 3-6 "Queue Element Transfer Descriptor Block Diagram". + * + * These are associated only with "QH" (Queue Head) structures, + * used with control, bulk, and interrupt transfers. + */ +struct fotg210_qtd { + /* first part defined by EHCI spec */ + __hc32 hw_next; /* see EHCI 3.5.1 */ + __hc32 hw_alt_next; /* see EHCI 3.5.2 */ + __hc32 hw_token; /* see EHCI 3.5.3 */ +#define QTD_TOGGLE (1 << 31) /* data toggle */ +#define QTD_LENGTH(tok) (((tok)>>16) & 0x7fff) +#define QTD_IOC (1 << 15) /* interrupt on complete */ +#define QTD_CERR(tok) (((tok)>>10) & 0x3) +#define QTD_PID(tok) (((tok)>>8) & 0x3) +#define QTD_STS_ACTIVE (1 << 7) /* HC may execute this */ +#define QTD_STS_HALT (1 << 6) /* halted on error */ +#define QTD_STS_DBE (1 << 5) /* data buffer error (in HC) */ +#define QTD_STS_BABBLE (1 << 4) /* device was babbling (qtd halted) */ +#define QTD_STS_XACT (1 << 3) /* device gave illegal response */ +#define QTD_STS_MMF (1 << 2) /* incomplete split transaction */ +#define QTD_STS_STS (1 << 1) /* split transaction state */ +#define QTD_STS_PING (1 << 0) /* issue PING? */ + +#define ACTIVE_BIT(fotg210) cpu_to_hc32(fotg210, QTD_STS_ACTIVE) +#define HALT_BIT(fotg210) cpu_to_hc32(fotg210, QTD_STS_HALT) +#define STATUS_BIT(fotg210) cpu_to_hc32(fotg210, QTD_STS_STS) + + __hc32 hw_buf[5]; /* see EHCI 3.5.4 */ + __hc32 hw_buf_hi[5]; /* Appendix B */ + + /* the rest is HCD-private */ + dma_addr_t qtd_dma; /* qtd address */ + struct list_head qtd_list; /* sw qtd list */ + struct urb *urb; /* qtd's urb */ + size_t length; /* length of buffer */ +} __aligned(32); + +/* mask NakCnt+T in qh->hw_alt_next */ +#define QTD_MASK(fotg210) cpu_to_hc32(fotg210, ~0x1f) + +#define IS_SHORT_READ(token) (QTD_LENGTH(token) != 0 && QTD_PID(token) == 1) + +/*-------------------------------------------------------------------------*/ + +/* type tag from {qh,itd,fstn}->hw_next */ +#define Q_NEXT_TYPE(fotg210, dma) ((dma) & cpu_to_hc32(fotg210, 3 << 1)) + +/* + * Now the following defines are not converted using the + * 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. + */ +/* values for that type tag */ +#define Q_TYPE_ITD (0 << 1) +#define Q_TYPE_QH (1 << 1) +#define Q_TYPE_SITD (2 << 1) +#define Q_TYPE_FSTN (3 << 1) + +/* next async queue entry, or pointer to interrupt/periodic QH */ +#define QH_NEXT(fotg210, dma) \ + (cpu_to_hc32(fotg210, (((u32)dma)&~0x01f)|Q_TYPE_QH)) + +/* for periodic/async schedules and qtd lists, mark end of list */ +#define FOTG210_LIST_END(fotg210) \ + cpu_to_hc32(fotg210, 1) /* "null pointer" to hw */ + +/* + * Entries in periodic shadow table are pointers to one of four kinds + * of data structure. That's dictated by the hardware; a type tag is + * encoded in the low bits of the hardware's periodic schedule. Use + * Q_NEXT_TYPE to get the tag. + * + * For entries in the async schedule, the type tag always says "qh". + */ +union fotg210_shadow { + struct fotg210_qh *qh; /* Q_TYPE_QH */ + struct fotg210_itd *itd; /* Q_TYPE_ITD */ + struct fotg210_fstn *fstn; /* Q_TYPE_FSTN */ + __hc32 *hw_next; /* (all types) */ + void *ptr; +}; + +/*-------------------------------------------------------------------------*/ + +/* + * EHCI Specification 0.95 Section 3.6 + * QH: describes control/bulk/interrupt endpoints + * See Fig 3-7 "Queue Head Structure Layout". + * + * These appear in both the async and (for interrupt) periodic schedules. + */ + +/* first part defined by EHCI spec */ +struct fotg210_qh_hw { + __hc32 hw_next; /* see EHCI 3.6.1 */ + __hc32 hw_info1; /* see EHCI 3.6.2 */ +#define QH_CONTROL_EP (1 << 27) /* FS/LS control endpoint */ +#define QH_HEAD (1 << 15) /* Head of async reclamation list */ +#define QH_TOGGLE_CTL (1 << 14) /* Data toggle control */ +#define QH_HIGH_SPEED (2 << 12) /* Endpoint speed */ +#define QH_LOW_SPEED (1 << 12) +#define QH_FULL_SPEED (0 << 12) +#define QH_INACTIVATE (1 << 7) /* Inactivate on next transaction */ + __hc32 hw_info2; /* see EHCI 3.6.2 */ +#define QH_SMASK 0x000000ff +#define QH_CMASK 0x0000ff00 +#define QH_HUBADDR 0x007f0000 +#define QH_HUBPORT 0x3f800000 +#define QH_MULT 0xc0000000 + __hc32 hw_current; /* qtd list - see EHCI 3.6.4 */ + + /* qtd overlay (hardware parts of a struct fotg210_qtd) */ + __hc32 hw_qtd_next; + __hc32 hw_alt_next; + __hc32 hw_token; + __hc32 hw_buf[5]; + __hc32 hw_buf_hi[5]; +} __aligned(32); + +struct fotg210_qh { + struct fotg210_qh_hw *hw; /* Must come first */ + /* the rest is HCD-private */ + dma_addr_t qh_dma; /* address of qh */ + union fotg210_shadow qh_next; /* ptr to qh; or periodic */ + struct list_head qtd_list; /* sw qtd list */ + struct list_head intr_node; /* list of intr QHs */ + struct fotg210_qtd *dummy; + struct fotg210_qh *unlink_next; /* next on unlink list */ + + unsigned unlink_cycle; + + u8 needs_rescan; /* Dequeue during giveback */ + u8 qh_state; +#define QH_STATE_LINKED 1 /* HC sees this */ +#define QH_STATE_UNLINK 2 /* HC may still see this */ +#define QH_STATE_IDLE 3 /* HC doesn't see this */ +#define QH_STATE_UNLINK_WAIT 4 /* LINKED and on unlink 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 */ + u8 c_usecs; /* ... split completion bw */ + u16 tt_usecs; /* tt downstream bandwidth */ + unsigned short period; /* polling interval */ + unsigned short start; /* where polling starts */ +#define NO_FRAME ((unsigned short)~0) /* pick new start */ + + struct usb_device *dev; /* access to TT */ + unsigned is_out:1; /* bulk or intr OUT */ + unsigned clearing_tt:1; /* Clear-TT-Buf in progress */ +}; + +/*-------------------------------------------------------------------------*/ + +/* description of one iso transaction (up to 3 KB data if highspeed) */ +struct fotg210_iso_packet { + /* These will be copied to iTD when scheduling */ + u64 bufp; /* itd->hw_bufp{,_hi}[pg] |= */ + __hc32 transaction; /* itd->hw_transaction[i] |= */ + u8 cross; /* buf crosses pages */ + /* for full speed OUT splits */ + u32 buf1; +}; + +/* temporary schedule data for packets from iso urbs (both speeds) + * each packet is one logical usb transaction to the device (not TT), + * beginning at stream->next_uframe + */ +struct fotg210_iso_sched { + struct list_head td_list; + unsigned span; + struct fotg210_iso_packet packet[0]; +}; + +/* + * fotg210_iso_stream - groups all (s)itds for this endpoint. + * acts like a qh would, if EHCI had them for ISO. + */ +struct fotg210_iso_stream { + /* first field matches fotg210_hq, but is NULL */ + struct fotg210_qh_hw *hw; + + u8 bEndpointAddress; + u8 highspeed; + struct list_head td_list; /* queued itds */ + struct list_head free_list; /* list of unused itds */ + struct usb_device *udev; + struct usb_host_endpoint *ep; + + /* output of (re)scheduling */ + int next_uframe; + __hc32 splits; + + /* the rest is derived from the endpoint descriptor, + * trusting urb->interval == f(epdesc->bInterval) and + * including the extra info for hw_bufp[0..2] + */ + u8 usecs, c_usecs; + u16 interval; + u16 tt_usecs; + u16 maxp; + u16 raw_mask; + unsigned bandwidth; + + /* This is used to initialize iTD's hw_bufp fields */ + __hc32 buf0; + __hc32 buf1; + __hc32 buf2; + + /* this is used to initialize sITD's tt info */ + __hc32 address; +}; + +/*-------------------------------------------------------------------------*/ + +/* + * EHCI Specification 0.95 Section 3.3 + * Fig 3-4 "Isochronous Transaction Descriptor (iTD)" + * + * Schedule records for high speed iso xfers + */ +struct fotg210_itd { + /* first part defined by EHCI spec */ + __hc32 hw_next; /* see EHCI 3.3.1 */ + __hc32 hw_transaction[8]; /* see EHCI 3.3.2 */ +#define FOTG210_ISOC_ACTIVE (1<<31) /* activate transfer this slot */ +#define FOTG210_ISOC_BUF_ERR (1<<30) /* Data buffer error */ +#define FOTG210_ISOC_BABBLE (1<<29) /* babble detected */ +#define FOTG210_ISOC_XACTERR (1<<28) /* XactErr - transaction error */ +#define FOTG210_ITD_LENGTH(tok) (((tok)>>16) & 0x0fff) +#define FOTG210_ITD_IOC (1 << 15) /* interrupt on complete */ + +#define ITD_ACTIVE(fotg210) cpu_to_hc32(fotg210, FOTG210_ISOC_ACTIVE) + + __hc32 hw_bufp[7]; /* see EHCI 3.3.3 */ + __hc32 hw_bufp_hi[7]; /* Appendix B */ + + /* the rest is HCD-private */ + dma_addr_t itd_dma; /* for this itd */ + union fotg210_shadow itd_next; /* ptr to periodic q entry */ + + struct urb *urb; + struct fotg210_iso_stream *stream; /* endpoint's queue */ + struct list_head itd_list; /* list of stream's itds */ + + /* any/all hw_transactions here may be used by that urb */ + unsigned frame; /* where scheduled */ + unsigned pg; + unsigned index[8]; /* in urb->iso_frame_desc */ +} __aligned(32); + +/*-------------------------------------------------------------------------*/ + +/* + * EHCI Specification 0.96 Section 3.7 + * Periodic Frame Span Traversal Node (FSTN) + * + * Manages split interrupt transactions (using TT) that span frame boundaries + * into uframes 0/1; see 4.12.2.2. In those uframes, a "save place" FSTN + * makes the HC jump (back) to a QH to scan for fs/ls QH completions until + * it hits a "restore" FSTN; then it returns to finish other uframe 0/1 work. + */ +struct fotg210_fstn { + __hc32 hw_next; /* any periodic q entry */ + __hc32 hw_prev; /* qh or FOTG210_LIST_END */ + + /* the rest is HCD-private */ + dma_addr_t fstn_dma; + union fotg210_shadow fstn_next; /* ptr to periodic q entry */ +} __aligned(32); + +/*-------------------------------------------------------------------------*/ + +/* Prepare the PORTSC wakeup flags during controller suspend/resume */ + +#define fotg210_prepare_ports_for_controller_suspend(fotg210, do_wakeup) \ + fotg210_adjust_port_wakeup_flags(fotg210, true, do_wakeup); + +#define fotg210_prepare_ports_for_controller_resume(fotg210) \ + fotg210_adjust_port_wakeup_flags(fotg210, false, false); + +/*-------------------------------------------------------------------------*/ + +/* + * Some EHCI controllers have a Transaction Translator built into the + * root hub. This is a non-standard feature. Each controller will need + * to add code to the following inline functions, and call them as + * needed (mostly in root hub code). + */ + +static inline unsigned int +fotg210_get_speed(struct fotg210_hcd *fotg210, unsigned int portsc) +{ + return (readl(&fotg210->regs->otgcsr) + & OTGCSR_HOST_SPD_TYP) >> 22; +} + +/* Returns the speed of a device attached to a port on the root hub. */ +static inline unsigned int +fotg210_port_speed(struct fotg210_hcd *fotg210, unsigned int portsc) +{ + switch (fotg210_get_speed(fotg210, portsc)) { + case 0: + return 0; + case 1: + return USB_PORT_STAT_LOW_SPEED; + case 2: + default: + return USB_PORT_STAT_HIGH_SPEED; + } +} + +/*-------------------------------------------------------------------------*/ + +#define fotg210_has_fsl_portno_bug(e) (0) + +/* + * While most USB host controllers implement their registers in + * little-endian format, a minority (celleb companion chip) implement + * them in big endian format. + * + * This attempts to support either format at compile time without a + * runtime penalty, or both formats with the additional overhead + * of checking a flag bit. + * + */ + +#define fotg210_big_endian_mmio(e) 0 +#define fotg210_big_endian_capbase(e) 0 + +static inline unsigned int fotg210_readl(const struct fotg210_hcd *fotg210, + __u32 __iomem *regs) +{ + return readl(regs); +} + +static inline void fotg210_writel(const struct fotg210_hcd *fotg210, + const unsigned int val, __u32 __iomem *regs) +{ + writel(val, regs); +} + +/* cpu to fotg210 */ +static inline __hc32 cpu_to_hc32(const struct fotg210_hcd *fotg210, const u32 x) +{ + return cpu_to_le32(x); +} + +/* fotg210 to cpu */ +static inline u32 hc32_to_cpu(const struct fotg210_hcd *fotg210, const __hc32 x) +{ + return le32_to_cpu(x); +} + +static inline u32 hc32_to_cpup(const struct fotg210_hcd *fotg210, + const __hc32 *x) +{ + return le32_to_cpup(x); +} + +/*-------------------------------------------------------------------------*/ + +static inline unsigned fotg210_read_frame_index(struct fotg210_hcd *fotg210) +{ + return fotg210_readl(fotg210, &fotg210->regs->frame_index); +} + +#define fotg210_itdlen(urb, desc, t) ({ \ + usb_pipein((urb)->pipe) ? \ + (desc)->length - FOTG210_ITD_LENGTH(t) : \ + FOTG210_ITD_LENGTH(t); \ +}) +/*-------------------------------------------------------------------------*/ + +#ifndef DEBUG +#define STUB_DEBUG_FILES +#endif /* DEBUG */ + +/*-------------------------------------------------------------------------*/ + +#endif /* __LINUX_FOTG210_H */ From 5447e0a652ba8907a0f4d88821acf7d37ef81af1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Jul 2013 16:10:58 -0700 Subject: [PATCH 0634/3400] Revert "usb: host: Faraday fotg210-hcd driver" This reverts commit 1dd3d123239179fad5de5dc00a6e0014a1918fde. The email address for the developer now bounces, which means they have moved on, so remove the driver until someone else from the company steps up to maintain it. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/Makefile | 1 - drivers/usb/host/Kconfig | 12 - drivers/usb/host/Makefile | 1 - drivers/usb/host/fotg210-hcd.c | 6049 -------------------------------- drivers/usb/host/fotg210.h | 750 ---- 5 files changed, 6813 deletions(-) delete mode 100644 drivers/usb/host/fotg210-hcd.c delete mode 100644 drivers/usb/host/fotg210.h diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index 5460abf045de..238c5d47cadb 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -26,7 +26,6 @@ obj-$(CONFIG_USB_ISP1760_HCD) += host/ obj-$(CONFIG_USB_IMX21_HCD) += host/ obj-$(CONFIG_USB_FSL_MPH_DR_OF) += host/ obj-$(CONFIG_USB_FUSBH200_HCD) += host/ -obj-$(CONFIG_USB_FOTG210_HCD) += host/ obj-$(CONFIG_USB_C67X00_HCD) += c67x00/ diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index cf521d6551dd..4263d011392c 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -354,18 +354,6 @@ config USB_FUSBH200_HCD To compile this driver as a module, choose M here: the module will be called fusbh200-hcd. -config USB_FOTG210_HCD - tristate "FOTG210 HCD support" - depends on USB - default N - ---help--- - Faraday FOTG210 is an OTG controller which can be configured as - an USB2.0 host. It is designed to meet USB2.0 EHCI specification - with minor modification. - - To compile this driver as a module, choose M here: the - module will be called fotg210-hcd. - config USB_OHCI_HCD tristate "OHCI HCD (USB 1.1) support" select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 829a3397882a..bea71127b15f 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -58,4 +58,3 @@ obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o obj-$(CONFIG_USB_HCD_BCMA) += bcma-hcd.o obj-$(CONFIG_USB_HCD_SSB) += ssb-hcd.o obj-$(CONFIG_USB_FUSBH200_HCD) += fusbh200-hcd.o -obj-$(CONFIG_USB_FOTG210_HCD) += fotg210-hcd.o diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c deleted file mode 100644 index fce13bcc4a3e..000000000000 --- a/drivers/usb/host/fotg210-hcd.c +++ /dev/null @@ -1,6049 +0,0 @@ -/* - * Faraday FOTG210 EHCI-like driver - * - * Copyright (c) 2013 Faraday Technology Corporation - * - * Author: Yuan-Hsin Chen - * Feng-Hsin Chiang - * Po-Yu Chuang - * - * Most of code borrowed from the Linux-3.7 EHCI 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 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 -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -/*-------------------------------------------------------------------------*/ -#define DRIVER_AUTHOR "Yuan-Hsin Chen" -#define DRIVER_DESC "FOTG210 Host Controller (EHCI) Driver" - -static const char hcd_name[] = "fotg210_hcd"; - -#undef VERBOSE_DEBUG -#undef FOTG210_URB_TRACE - -#ifdef DEBUG -#define FOTG210_STATS -#endif - -/* magic numbers that can affect system performance */ -#define FOTG210_TUNE_CERR 3 /* 0-3 qtd retries; 0 == don't stop */ -#define FOTG210_TUNE_RL_HS 4 /* nak throttle; see 4.9 */ -#define FOTG210_TUNE_RL_TT 0 -#define FOTG210_TUNE_MULT_HS 1 /* 1-3 transactions/uframe; 4.10.3 */ -#define FOTG210_TUNE_MULT_TT 1 -/* - * Some drivers think it's safe to schedule isochronous transfers more than - * 256 ms into the future (partly as a result of an old bug in the scheduling - * code). In an attempt to avoid trouble, we will use a minimum scheduling - * length of 512 frames instead of 256. - */ -#define FOTG210_TUNE_FLS 1 /* (medium) 512-frame schedule */ - -/* Initial IRQ latency: faster than hw default */ -static int log2_irq_thresh; /* 0 to 6 */ -module_param(log2_irq_thresh, int, S_IRUGO); -MODULE_PARM_DESC(log2_irq_thresh, "log2 IRQ latency, 1-64 microframes"); - -/* initial park setting: slower than hw default */ -static unsigned park; -module_param(park, uint, S_IRUGO); -MODULE_PARM_DESC(park, "park setting; 1-3 back-to-back async packets"); - -/* for link power management(LPM) feature */ -static unsigned int hird; -module_param(hird, int, S_IRUGO); -MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us"); - -#define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT) - -#include "fotg210.h" - -/*-------------------------------------------------------------------------*/ - -#define fotg210_dbg(fotg210, fmt, args...) \ - dev_dbg(fotg210_to_hcd(fotg210)->self.controller , fmt , ## args) -#define fotg210_err(fotg210, fmt, args...) \ - dev_err(fotg210_to_hcd(fotg210)->self.controller , fmt , ## args) -#define fotg210_info(fotg210, fmt, args...) \ - dev_info(fotg210_to_hcd(fotg210)->self.controller , fmt , ## args) -#define fotg210_warn(fotg210, fmt, args...) \ - dev_warn(fotg210_to_hcd(fotg210)->self.controller , fmt , ## args) - -#ifdef VERBOSE_DEBUG -# define fotg210_vdbg fotg210_dbg -#else - static inline void fotg210_vdbg(struct fotg210_hcd *fotg210, ...) {} -#endif - -#ifdef DEBUG - -/* check the values in the HCSPARAMS register - * (host controller _Structural_ parameters) - * see EHCI spec, Table 2-4 for each value - */ -static void dbg_hcs_params(struct fotg210_hcd *fotg210, char *label) -{ - u32 params = fotg210_readl(fotg210, &fotg210->caps->hcs_params); - - fotg210_dbg(fotg210, - "%s hcs_params 0x%x ports=%d\n", - label, params, - HCS_N_PORTS(params) - ); -} -#else - -static inline void dbg_hcs_params(struct fotg210_hcd *fotg210, char *label) {} - -#endif - -#ifdef DEBUG - -/* check the values in the HCCPARAMS register - * (host controller _Capability_ parameters) - * see EHCI Spec, Table 2-5 for each value - * */ -static void dbg_hcc_params(struct fotg210_hcd *fotg210, char *label) -{ - u32 params = fotg210_readl(fotg210, &fotg210->caps->hcc_params); - - fotg210_dbg(fotg210, - "%s hcc_params %04x uframes %s%s\n", - label, - params, - HCC_PGM_FRAMELISTLEN(params) ? "256/512/1024" : "1024", - HCC_CANPARK(params) ? " park" : ""); -} -#else - -static inline void dbg_hcc_params(struct fotg210_hcd *fotg210, char *label) {} - -#endif - -#ifdef DEBUG - -static void __maybe_unused -dbg_qtd(const char *label, struct fotg210_hcd *fotg210, struct fotg210_qtd *qtd) -{ - fotg210_dbg(fotg210, "%s td %p n%08x %08x t%08x p0=%08x\n", label, qtd, - hc32_to_cpup(fotg210, &qtd->hw_next), - hc32_to_cpup(fotg210, &qtd->hw_alt_next), - hc32_to_cpup(fotg210, &qtd->hw_token), - hc32_to_cpup(fotg210, &qtd->hw_buf[0])); - if (qtd->hw_buf[1]) - fotg210_dbg(fotg210, " p1=%08x p2=%08x p3=%08x p4=%08x\n", - hc32_to_cpup(fotg210, &qtd->hw_buf[1]), - hc32_to_cpup(fotg210, &qtd->hw_buf[2]), - hc32_to_cpup(fotg210, &qtd->hw_buf[3]), - hc32_to_cpup(fotg210, &qtd->hw_buf[4])); -} - -static void __maybe_unused -dbg_qh(const char *label, struct fotg210_hcd *fotg210, struct fotg210_qh *qh) -{ - struct fotg210_qh_hw *hw = qh->hw; - - fotg210_dbg(fotg210, "%s qh %p n%08x info %x %x qtd %x\n", label, - qh, hw->hw_next, hw->hw_info1, hw->hw_info2, hw->hw_current); - dbg_qtd("overlay", fotg210, (struct fotg210_qtd *) &hw->hw_qtd_next); -} - -static void __maybe_unused -dbg_itd(const char *label, struct fotg210_hcd *fotg210, struct fotg210_itd *itd) -{ - fotg210_dbg(fotg210, "%s[%d] itd %p, next %08x, urb %p\n", - label, itd->frame, itd, hc32_to_cpu(fotg210, itd->hw_next), - itd->urb); - fotg210_dbg(fotg210, - " trans: %08x %08x %08x %08x %08x %08x %08x %08x\n", - hc32_to_cpu(fotg210, itd->hw_transaction[0]), - hc32_to_cpu(fotg210, itd->hw_transaction[1]), - hc32_to_cpu(fotg210, itd->hw_transaction[2]), - hc32_to_cpu(fotg210, itd->hw_transaction[3]), - hc32_to_cpu(fotg210, itd->hw_transaction[4]), - hc32_to_cpu(fotg210, itd->hw_transaction[5]), - hc32_to_cpu(fotg210, itd->hw_transaction[6]), - hc32_to_cpu(fotg210, itd->hw_transaction[7])); - fotg210_dbg(fotg210, - " buf: %08x %08x %08x %08x %08x %08x %08x\n", - hc32_to_cpu(fotg210, itd->hw_bufp[0]), - hc32_to_cpu(fotg210, itd->hw_bufp[1]), - hc32_to_cpu(fotg210, itd->hw_bufp[2]), - hc32_to_cpu(fotg210, itd->hw_bufp[3]), - hc32_to_cpu(fotg210, itd->hw_bufp[4]), - hc32_to_cpu(fotg210, itd->hw_bufp[5]), - hc32_to_cpu(fotg210, itd->hw_bufp[6])); - fotg210_dbg(fotg210, " index: %d %d %d %d %d %d %d %d\n", - itd->index[0], itd->index[1], itd->index[2], - itd->index[3], itd->index[4], itd->index[5], - itd->index[6], itd->index[7]); -} - -static int __maybe_unused -dbg_status_buf(char *buf, unsigned len, const char *label, u32 status) -{ - return scnprintf(buf, len, - "%s%sstatus %04x%s%s%s%s%s%s%s%s%s%s", - label, label[0] ? " " : "", status, - (status & STS_ASS) ? " Async" : "", - (status & STS_PSS) ? " Periodic" : "", - (status & STS_RECL) ? " Recl" : "", - (status & STS_HALT) ? " Halt" : "", - (status & STS_IAA) ? " IAA" : "", - (status & STS_FATAL) ? " FATAL" : "", - (status & STS_FLR) ? " FLR" : "", - (status & STS_PCD) ? " PCD" : "", - (status & STS_ERR) ? " ERR" : "", - (status & STS_INT) ? " INT" : "" - ); -} - -static int __maybe_unused -dbg_intr_buf(char *buf, unsigned len, const char *label, u32 enable) -{ - return scnprintf(buf, len, - "%s%sintrenable %02x%s%s%s%s%s%s", - label, label[0] ? " " : "", enable, - (enable & STS_IAA) ? " IAA" : "", - (enable & STS_FATAL) ? " FATAL" : "", - (enable & STS_FLR) ? " FLR" : "", - (enable & STS_PCD) ? " PCD" : "", - (enable & STS_ERR) ? " ERR" : "", - (enable & STS_INT) ? " INT" : "" - ); -} - -static const char *const fls_strings[] = { "1024", "512", "256", "??" }; - -static int -dbg_command_buf(char *buf, unsigned len, const char *label, u32 command) -{ - return scnprintf(buf, len, - "%s%scommand %07x %s=%d ithresh=%d%s%s%s " - "period=%s%s %s", - label, label[0] ? " " : "", command, - (command & CMD_PARK) ? " park" : "(park)", - CMD_PARK_CNT(command), - (command >> 16) & 0x3f, - (command & CMD_IAAD) ? " IAAD" : "", - (command & CMD_ASE) ? " Async" : "", - (command & CMD_PSE) ? " Periodic" : "", - fls_strings[(command >> 2) & 0x3], - (command & CMD_RESET) ? " Reset" : "", - (command & CMD_RUN) ? "RUN" : "HALT" - ); -} - -static int -dbg_port_buf(char *buf, unsigned len, const char *label, int port, u32 status) -{ - char *sig; - - /* signaling state */ - switch (status & (3 << 10)) { - case 0 << 10: - sig = "se0"; - break; - case 1 << 10: - sig = "k"; - break; /* low speed */ - case 2 << 10: - sig = "j"; - break; - default: - sig = "?"; - break; - } - - return scnprintf(buf, len, - "%s%sport:%d status %06x %d " - "sig=%s%s%s%s%s%s%s%s", - label, label[0] ? " " : "", port, status, - status>>25,/*device address */ - sig, - (status & PORT_RESET) ? " RESET" : "", - (status & PORT_SUSPEND) ? " SUSPEND" : "", - (status & PORT_RESUME) ? " RESUME" : "", - (status & PORT_PEC) ? " PEC" : "", - (status & PORT_PE) ? " PE" : "", - (status & PORT_CSC) ? " CSC" : "", - (status & PORT_CONNECT) ? " CONNECT" : ""); -} - -#else -static inline void __maybe_unused -dbg_qh(char *label, struct fotg210_hcd *fotg210, struct fotg210_qh *qh) -{} - -static inline int __maybe_unused -dbg_status_buf(char *buf, unsigned len, const char *label, u32 status) -{ return 0; } - -static inline int __maybe_unused -dbg_command_buf(char *buf, unsigned len, const char *label, u32 command) -{ return 0; } - -static inline int __maybe_unused -dbg_intr_buf(char *buf, unsigned len, const char *label, u32 enable) -{ return 0; } - -static inline int __maybe_unused -dbg_port_buf(char *buf, unsigned len, const char *label, int port, u32 status) -{ return 0; } - -#endif /* DEBUG */ - -/* functions have the "wrong" filename when they're output... */ -#define dbg_status(fotg210, label, status) { \ - char _buf[80]; \ - dbg_status_buf(_buf, sizeof(_buf), label, status); \ - fotg210_dbg(fotg210, "%s\n", _buf); \ -} - -#define dbg_cmd(fotg210, label, command) { \ - char _buf[80]; \ - dbg_command_buf(_buf, sizeof(_buf), label, command); \ - fotg210_dbg(fotg210, "%s\n", _buf); \ -} - -#define dbg_port(fotg210, label, port, status) { \ - char _buf[80]; \ - dbg_port_buf(_buf, sizeof(_buf), label, port, status); \ - fotg210_dbg(fotg210, "%s\n", _buf); \ -} - -/*-------------------------------------------------------------------------*/ - -#ifdef STUB_DEBUG_FILES - -static inline void create_debug_files(struct fotg210_hcd *bus) { } -static inline void remove_debug_files(struct fotg210_hcd *bus) { } - -#else - -/* troubleshooting help: expose state in debugfs */ - -static int debug_async_open(struct inode *, struct file *); -static int debug_periodic_open(struct inode *, struct file *); -static int debug_registers_open(struct inode *, struct file *); -static int debug_async_open(struct inode *, struct file *); - -static ssize_t debug_output(struct file*, char __user*, size_t, loff_t*); -static int debug_close(struct inode *, struct file *); - -static const struct file_operations debug_async_fops = { - .owner = THIS_MODULE, - .open = debug_async_open, - .read = debug_output, - .release = debug_close, - .llseek = default_llseek, -}; -static const struct file_operations debug_periodic_fops = { - .owner = THIS_MODULE, - .open = debug_periodic_open, - .read = debug_output, - .release = debug_close, - .llseek = default_llseek, -}; -static const struct file_operations debug_registers_fops = { - .owner = THIS_MODULE, - .open = debug_registers_open, - .read = debug_output, - .release = debug_close, - .llseek = default_llseek, -}; - -static struct dentry *fotg210_debug_root; - -struct debug_buffer { - ssize_t (*fill_func)(struct debug_buffer *); /* fill method */ - struct usb_bus *bus; - struct mutex mutex; /* protect filling of buffer */ - size_t count; /* number of characters filled into buffer */ - char *output_buf; - size_t alloc_size; -}; - -#define speed_char(info1)({ char tmp; \ - switch (info1 & (3 << 12)) { \ - case QH_FULL_SPEED: \ - tmp = 'f'; break; \ - case QH_LOW_SPEED: \ - tmp = 'l'; break; \ - case QH_HIGH_SPEED: \ - tmp = 'h'; break; \ - default: \ - tmp = '?'; break; \ - }; tmp; }) - -static inline char token_mark(struct fotg210_hcd *fotg210, __hc32 token) -{ - __u32 v = hc32_to_cpu(fotg210, token); - - if (v & QTD_STS_ACTIVE) - return '*'; - if (v & QTD_STS_HALT) - return '-'; - if (!IS_SHORT_READ(v)) - return ' '; - /* tries to advance through hw_alt_next */ - return '/'; -} - -static void qh_lines( - struct fotg210_hcd *fotg210, - struct fotg210_qh *qh, - char **nextp, - unsigned *sizep -) -{ - u32 scratch; - u32 hw_curr; - struct fotg210_qtd *td; - unsigned temp; - unsigned size = *sizep; - char *next = *nextp; - char mark; - __le32 list_end = FOTG210_LIST_END(fotg210); - struct fotg210_qh_hw *hw = qh->hw; - - if (hw->hw_qtd_next == list_end) /* NEC does this */ - mark = '@'; - else - mark = token_mark(fotg210, hw->hw_token); - if (mark == '/') { /* qh_alt_next controls qh advance? */ - if ((hw->hw_alt_next & QTD_MASK(fotg210)) - == fotg210->async->hw->hw_alt_next) - mark = '#'; /* blocked */ - else if (hw->hw_alt_next == list_end) - mark = '.'; /* use hw_qtd_next */ - /* else alt_next points to some other qtd */ - } - scratch = hc32_to_cpup(fotg210, &hw->hw_info1); - hw_curr = (mark == '*') ? hc32_to_cpup(fotg210, &hw->hw_current) : 0; - temp = scnprintf(next, size, - "qh/%p dev%d %cs ep%d %08x %08x(%08x%c %s nak%d)", - qh, scratch & 0x007f, - speed_char(scratch), - (scratch >> 8) & 0x000f, - scratch, hc32_to_cpup(fotg210, &hw->hw_info2), - hc32_to_cpup(fotg210, &hw->hw_token), mark, - (cpu_to_hc32(fotg210, QTD_TOGGLE) & hw->hw_token) - ? "data1" : "data0", - (hc32_to_cpup(fotg210, &hw->hw_alt_next) >> 1) & 0x0f); - size -= temp; - next += temp; - - /* hc may be modifying the list as we read it ... */ - list_for_each_entry(td, &qh->qtd_list, qtd_list) { - scratch = hc32_to_cpup(fotg210, &td->hw_token); - mark = ' '; - if (hw_curr == td->qtd_dma) - mark = '*'; - else if (hw->hw_qtd_next == cpu_to_hc32(fotg210, td->qtd_dma)) - mark = '+'; - else if (QTD_LENGTH(scratch)) { - if (td->hw_alt_next == fotg210->async->hw->hw_alt_next) - mark = '#'; - else if (td->hw_alt_next != list_end) - mark = '/'; - } - temp = snprintf(next, size, - "\n\t%p%c%s len=%d %08x urb %p", - td, mark, ({ char *tmp; - switch ((scratch>>8)&0x03) { - case 0: - tmp = "out"; - break; - case 1: - tmp = "in"; - break; - case 2: - tmp = "setup"; - break; - default: - tmp = "?"; - break; - } tmp; }), - (scratch >> 16) & 0x7fff, - scratch, - td->urb); - if (size < temp) - temp = size; - size -= temp; - next += temp; - if (temp == size) - goto done; - } - - temp = snprintf(next, size, "\n"); - if (size < temp) - temp = size; - size -= temp; - next += temp; - -done: - *sizep = size; - *nextp = next; -} - -static ssize_t fill_async_buffer(struct debug_buffer *buf) -{ - struct usb_hcd *hcd; - struct fotg210_hcd *fotg210; - unsigned long flags; - unsigned temp, size; - char *next; - struct fotg210_qh *qh; - - hcd = bus_to_hcd(buf->bus); - fotg210 = hcd_to_fotg210(hcd); - next = buf->output_buf; - size = buf->alloc_size; - - *next = 0; - - /* dumps a snapshot of the async schedule. - * usually empty except for long-term bulk reads, or head. - * one QH per line, and TDs we know about - */ - spin_lock_irqsave(&fotg210->lock, flags); - for (qh = fotg210->async->qh_next.qh; size > 0 && qh; - qh = qh->qh_next.qh) - qh_lines(fotg210, qh, &next, &size); - if (fotg210->async_unlink && size > 0) { - temp = scnprintf(next, size, "\nunlink =\n"); - size -= temp; - next += temp; - - for (qh = fotg210->async_unlink; size > 0 && qh; - qh = qh->unlink_next) - qh_lines(fotg210, qh, &next, &size); - } - spin_unlock_irqrestore(&fotg210->lock, flags); - - return strlen(buf->output_buf); -} - -#define DBG_SCHED_LIMIT 64 -static ssize_t fill_periodic_buffer(struct debug_buffer *buf) -{ - struct usb_hcd *hcd; - struct fotg210_hcd *fotg210; - unsigned long flags; - union fotg210_shadow p, *seen; - unsigned temp, size, seen_count; - char *next; - unsigned i; - __hc32 tag; - - seen = kmalloc(DBG_SCHED_LIMIT * sizeof(*seen), GFP_ATOMIC); - if (!seen) - return 0; - seen_count = 0; - - hcd = bus_to_hcd(buf->bus); - fotg210 = hcd_to_fotg210(hcd); - next = buf->output_buf; - size = buf->alloc_size; - - temp = scnprintf(next, size, "size = %d\n", fotg210->periodic_size); - size -= temp; - next += temp; - - /* dump a snapshot of the periodic schedule. - * iso changes, interrupt usually doesn't. - */ - spin_lock_irqsave(&fotg210->lock, flags); - for (i = 0; i < fotg210->periodic_size; i++) { - p = fotg210->pshadow[i]; - if (likely(!p.ptr)) - continue; - tag = Q_NEXT_TYPE(fotg210, fotg210->periodic[i]); - - temp = scnprintf(next, size, "%4d: ", i); - size -= temp; - next += temp; - - do { - struct fotg210_qh_hw *hw; - - switch (hc32_to_cpu(fotg210, tag)) { - case Q_TYPE_QH: - hw = p.qh->hw; - temp = scnprintf(next, size, " qh%d-%04x/%p", - p.qh->period, - hc32_to_cpup(fotg210, - &hw->hw_info2) - /* uframe masks */ - & (QH_CMASK | QH_SMASK), - p.qh); - size -= temp; - next += temp; - /* don't repeat what follows this qh */ - for (temp = 0; temp < seen_count; temp++) { - if (seen[temp].ptr != p.ptr) - continue; - if (p.qh->qh_next.ptr) { - temp = scnprintf(next, size, - " ..."); - size -= temp; - next += temp; - } - break; - } - /* show more info the first time around */ - if (temp == seen_count) { - u32 scratch = hc32_to_cpup(fotg210, - &hw->hw_info1); - struct fotg210_qtd *qtd; - char *type = ""; - - /* count tds, get ep direction */ - temp = 0; - list_for_each_entry(qtd, - &p.qh->qtd_list, - qtd_list) { - temp++; - switch (0x03 & (hc32_to_cpu( - fotg210, - qtd->hw_token) >> 8)) { - case 0: - type = "out"; - continue; - case 1: - type = "in"; - continue; - } - } - - temp = scnprintf(next, size, - "(%c%d ep%d%s " - "[%d/%d] q%d p%d)", - speed_char(scratch), - scratch & 0x007f, - (scratch >> 8) & 0x000f, type, - p.qh->usecs, p.qh->c_usecs, - temp, - 0x7ff & (scratch >> 16)); - - if (seen_count < DBG_SCHED_LIMIT) - seen[seen_count++].qh = p.qh; - } else - temp = 0; - tag = Q_NEXT_TYPE(fotg210, hw->hw_next); - p = p.qh->qh_next; - break; - case Q_TYPE_FSTN: - temp = scnprintf(next, size, - " fstn-%8x/%p", p.fstn->hw_prev, - p.fstn); - tag = Q_NEXT_TYPE(fotg210, p.fstn->hw_next); - p = p.fstn->fstn_next; - break; - case Q_TYPE_ITD: - temp = scnprintf(next, size, - " itd/%p", p.itd); - tag = Q_NEXT_TYPE(fotg210, p.itd->hw_next); - p = p.itd->itd_next; - break; - } - size -= temp; - next += temp; - } while (p.ptr); - - temp = scnprintf(next, size, "\n"); - size -= temp; - next += temp; - } - spin_unlock_irqrestore(&fotg210->lock, flags); - kfree(seen); - - return buf->alloc_size - size; -} -#undef DBG_SCHED_LIMIT - -static const char *rh_state_string(struct fotg210_hcd *fotg210) -{ - switch (fotg210->rh_state) { - case FOTG210_RH_HALTED: - return "halted"; - case FOTG210_RH_SUSPENDED: - return "suspended"; - case FOTG210_RH_RUNNING: - return "running"; - case FOTG210_RH_STOPPING: - return "stopping"; - } - return "?"; -} - -static ssize_t fill_registers_buffer(struct debug_buffer *buf) -{ - struct usb_hcd *hcd; - struct fotg210_hcd *fotg210; - unsigned long flags; - unsigned temp, size, i; - char *next, scratch[80]; - static const char fmt[] = "%*s\n"; - static const char label[] = ""; - - hcd = bus_to_hcd(buf->bus); - fotg210 = hcd_to_fotg210(hcd); - next = buf->output_buf; - size = buf->alloc_size; - - spin_lock_irqsave(&fotg210->lock, flags); - - if (!HCD_HW_ACCESSIBLE(hcd)) { - size = scnprintf(next, size, - "bus %s, device %s\n" - "%s\n" - "SUSPENDED(no register access)\n", - hcd->self.controller->bus->name, - dev_name(hcd->self.controller), - hcd->product_desc); - goto done; - } - - /* Capability Registers */ - i = HC_VERSION(fotg210, fotg210_readl(fotg210, - &fotg210->caps->hc_capbase)); - temp = scnprintf(next, size, - "bus %s, device %s\n" - "%s\n" - "EHCI %x.%02x, rh state %s\n", - hcd->self.controller->bus->name, - dev_name(hcd->self.controller), - hcd->product_desc, - i >> 8, i & 0x0ff, rh_state_string(fotg210)); - size -= temp; - next += temp; - - /* FIXME interpret both types of params */ - i = fotg210_readl(fotg210, &fotg210->caps->hcs_params); - temp = scnprintf(next, size, "structural params 0x%08x\n", i); - size -= temp; - next += temp; - - i = fotg210_readl(fotg210, &fotg210->caps->hcc_params); - temp = scnprintf(next, size, "capability params 0x%08x\n", i); - size -= temp; - next += temp; - - /* Operational Registers */ - temp = dbg_status_buf(scratch, sizeof(scratch), label, - fotg210_readl(fotg210, &fotg210->regs->status)); - temp = scnprintf(next, size, fmt, temp, scratch); - size -= temp; - next += temp; - - temp = dbg_command_buf(scratch, sizeof(scratch), label, - fotg210_readl(fotg210, &fotg210->regs->command)); - temp = scnprintf(next, size, fmt, temp, scratch); - size -= temp; - next += temp; - - temp = dbg_intr_buf(scratch, sizeof(scratch), label, - fotg210_readl(fotg210, &fotg210->regs->intr_enable)); - temp = scnprintf(next, size, fmt, temp, scratch); - size -= temp; - next += temp; - - temp = scnprintf(next, size, "uframe %04x\n", - fotg210_read_frame_index(fotg210)); - size -= temp; - next += temp; - - if (fotg210->async_unlink) { - temp = scnprintf(next, size, "async unlink qh %p\n", - fotg210->async_unlink); - size -= temp; - next += temp; - } - -#ifdef FOTG210_STATS - temp = scnprintf(next, size, - "irq normal %ld err %ld iaa %ld(lost %ld)\n", - fotg210->stats.normal, fotg210->stats.error, fotg210->stats.iaa, - fotg210->stats.lost_iaa); - size -= temp; - next += temp; - - temp = scnprintf(next, size, "complete %ld unlink %ld\n", - fotg210->stats.complete, fotg210->stats.unlink); - size -= temp; - next += temp; -#endif - -done: - spin_unlock_irqrestore(&fotg210->lock, flags); - - return buf->alloc_size - size; -} - -static struct debug_buffer *alloc_buffer(struct usb_bus *bus, - ssize_t (*fill_func)(struct debug_buffer *)) -{ - struct debug_buffer *buf; - - buf = kzalloc(sizeof(struct debug_buffer), GFP_KERNEL); - - if (buf) { - buf->bus = bus; - buf->fill_func = fill_func; - mutex_init(&buf->mutex); - buf->alloc_size = PAGE_SIZE; - } - - return buf; -} - -static int fill_buffer(struct debug_buffer *buf) -{ - int ret = 0; - - if (!buf->output_buf) - buf->output_buf = vmalloc(buf->alloc_size); - - if (!buf->output_buf) { - ret = -ENOMEM; - goto out; - } - - ret = buf->fill_func(buf); - - if (ret >= 0) { - buf->count = ret; - ret = 0; - } - -out: - return ret; -} - -static ssize_t debug_output(struct file *file, char __user *user_buf, - size_t len, loff_t *offset) -{ - struct debug_buffer *buf = file->private_data; - int ret = 0; - - mutex_lock(&buf->mutex); - if (buf->count == 0) { - ret = fill_buffer(buf); - if (ret != 0) { - mutex_unlock(&buf->mutex); - goto out; - } - } - mutex_unlock(&buf->mutex); - - ret = simple_read_from_buffer(user_buf, len, offset, - buf->output_buf, buf->count); - -out: - return ret; - -} - -static int debug_close(struct inode *inode, struct file *file) -{ - struct debug_buffer *buf = file->private_data; - - if (buf) { - vfree(buf->output_buf); - kfree(buf); - } - - return 0; -} -static int debug_async_open(struct inode *inode, struct file *file) -{ - file->private_data = alloc_buffer(inode->i_private, fill_async_buffer); - - return file->private_data ? 0 : -ENOMEM; -} - -static int debug_periodic_open(struct inode *inode, struct file *file) -{ - struct debug_buffer *buf; - buf = alloc_buffer(inode->i_private, fill_periodic_buffer); - if (!buf) - return -ENOMEM; - - buf->alloc_size = (sizeof(void *) == 4 ? 6 : 8)*PAGE_SIZE; - file->private_data = buf; - return 0; -} - -static int debug_registers_open(struct inode *inode, struct file *file) -{ - file->private_data = alloc_buffer(inode->i_private, - fill_registers_buffer); - - return file->private_data ? 0 : -ENOMEM; -} - -static inline void create_debug_files(struct fotg210_hcd *fotg210) -{ - struct usb_bus *bus = &fotg210_to_hcd(fotg210)->self; - - fotg210->debug_dir = debugfs_create_dir(bus->bus_name, - fotg210_debug_root); - if (!fotg210->debug_dir) - return; - - if (!debugfs_create_file("async", S_IRUGO, fotg210->debug_dir, bus, - &debug_async_fops)) - goto file_error; - - if (!debugfs_create_file("periodic", S_IRUGO, fotg210->debug_dir, bus, - &debug_periodic_fops)) - goto file_error; - - if (!debugfs_create_file("registers", S_IRUGO, fotg210->debug_dir, bus, - &debug_registers_fops)) - goto file_error; - - return; - -file_error: - debugfs_remove_recursive(fotg210->debug_dir); -} - -static inline void remove_debug_files(struct fotg210_hcd *fotg210) -{ - debugfs_remove_recursive(fotg210->debug_dir); -} - -#endif /* STUB_DEBUG_FILES */ -/*-------------------------------------------------------------------------*/ - -/* - * handshake - spin reading hc until handshake completes or fails - * @ptr: address of hc register to be read - * @mask: bits to look at in result of read - * @done: value of those bits when handshake succeeds - * @usec: timeout in microseconds - * - * Returns negative errno, or zero on success - * - * Success happens when the "mask" bits have the specified value (hardware - * handshake done). There are two failure modes: "usec" have passed (major - * hardware flakeout), or the register reads as all-ones (hardware removed). - * - * That last failure should_only happen in cases like physical cardbus eject - * before driver shutdown. But it also seems to be caused by bugs in cardbus - * bridge shutdown: shutting down the bridge before the devices using it. - */ -static int handshake(struct fotg210_hcd *fotg210, void __iomem *ptr, - u32 mask, u32 done, int usec) -{ - u32 result; - - do { - result = fotg210_readl(fotg210, ptr); - if (result == ~(u32)0) /* card removed */ - return -ENODEV; - result &= mask; - if (result == done) - return 0; - udelay(1); - usec--; - } while (usec > 0); - return -ETIMEDOUT; -} - -/* - * Force HC to halt state from unknown (EHCI spec section 2.3). - * Must be called with interrupts enabled and the lock not held. - */ -static int fotg210_halt(struct fotg210_hcd *fotg210) -{ - u32 temp; - - spin_lock_irq(&fotg210->lock); - - /* disable any irqs left enabled by previous code */ - fotg210_writel(fotg210, 0, &fotg210->regs->intr_enable); - - /* - * This routine gets called during probe before fotg210->command - * has been initialized, so we can't rely on its value. - */ - fotg210->command &= ~CMD_RUN; - temp = fotg210_readl(fotg210, &fotg210->regs->command); - temp &= ~(CMD_RUN | CMD_IAAD); - fotg210_writel(fotg210, temp, &fotg210->regs->command); - - spin_unlock_irq(&fotg210->lock); - synchronize_irq(fotg210_to_hcd(fotg210)->irq); - - return handshake(fotg210, &fotg210->regs->status, - STS_HALT, STS_HALT, 16 * 125); -} - -/* - * Reset a non-running (STS_HALT == 1) controller. - * Must be called with interrupts enabled and the lock not held. - */ -static int fotg210_reset(struct fotg210_hcd *fotg210) -{ - int retval; - u32 command = fotg210_readl(fotg210, &fotg210->regs->command); - - /* If the EHCI debug controller is active, special care must be - * taken before and after a host controller reset */ - if (fotg210->debug && !dbgp_reset_prep(fotg210_to_hcd(fotg210))) - fotg210->debug = NULL; - - command |= CMD_RESET; - dbg_cmd(fotg210, "reset", command); - fotg210_writel(fotg210, command, &fotg210->regs->command); - fotg210->rh_state = FOTG210_RH_HALTED; - fotg210->next_statechange = jiffies; - retval = handshake(fotg210, &fotg210->regs->command, - CMD_RESET, 0, 250 * 1000); - - if (retval) - return retval; - - if (fotg210->debug) - dbgp_external_startup(fotg210_to_hcd(fotg210)); - - fotg210->port_c_suspend = fotg210->suspended_ports = - fotg210->resuming_ports = 0; - return retval; -} - -/* - * Idle the controller (turn off the schedules). - * Must be called with interrupts enabled and the lock not held. - */ -static void fotg210_quiesce(struct fotg210_hcd *fotg210) -{ - u32 temp; - - if (fotg210->rh_state != FOTG210_RH_RUNNING) - return; - - /* wait for any schedule enables/disables to take effect */ - temp = (fotg210->command << 10) & (STS_ASS | STS_PSS); - handshake(fotg210, &fotg210->regs->status, STS_ASS | STS_PSS, temp, - 16 * 125); - - /* then disable anything that's still active */ - spin_lock_irq(&fotg210->lock); - fotg210->command &= ~(CMD_ASE | CMD_PSE); - fotg210_writel(fotg210, fotg210->command, &fotg210->regs->command); - spin_unlock_irq(&fotg210->lock); - - /* hardware can take 16 microframes to turn off ... */ - handshake(fotg210, &fotg210->regs->status, STS_ASS | STS_PSS, 0, - 16 * 125); -} - -/*-------------------------------------------------------------------------*/ - -static void end_unlink_async(struct fotg210_hcd *fotg210); -static void unlink_empty_async(struct fotg210_hcd *fotg210); -static void fotg210_work(struct fotg210_hcd *fotg210); -static void start_unlink_intr(struct fotg210_hcd *fotg210, - struct fotg210_qh *qh); -static void end_unlink_intr(struct fotg210_hcd *fotg210, struct fotg210_qh *qh); - -/*-------------------------------------------------------------------------*/ - -/* Set a bit in the USBCMD register */ -static void fotg210_set_command_bit(struct fotg210_hcd *fotg210, u32 bit) -{ - fotg210->command |= bit; - fotg210_writel(fotg210, fotg210->command, &fotg210->regs->command); - - /* unblock posted write */ - fotg210_readl(fotg210, &fotg210->regs->command); -} - -/* Clear a bit in the USBCMD register */ -static void fotg210_clear_command_bit(struct fotg210_hcd *fotg210, u32 bit) -{ - fotg210->command &= ~bit; - fotg210_writel(fotg210, fotg210->command, &fotg210->regs->command); - - /* unblock posted write */ - fotg210_readl(fotg210, &fotg210->regs->command); -} - -/*-------------------------------------------------------------------------*/ - -/* - * EHCI timer support... Now using hrtimers. - * - * Lots of different events are triggered from fotg210->hrtimer. Whenever - * the timer routine runs, it checks each possible event; events that are - * currently enabled and whose expiration time has passed get handled. - * The set of enabled events is stored as a collection of bitflags in - * fotg210->enabled_hrtimer_events, and they are numbered in order of - * increasing delay values (ranging between 1 ms and 100 ms). - * - * Rather than implementing a sorted list or tree of all pending events, - * we keep track only of the lowest-numbered pending event, in - * fotg210->next_hrtimer_event. Whenever fotg210->hrtimer gets restarted, its - * expiration time is set to the timeout value for this event. - * - * As a result, events might not get handled right away; the actual delay - * could be anywhere up to twice the requested delay. This doesn't - * matter, because none of the events are especially time-critical. The - * ones that matter most all have a delay of 1 ms, so they will be - * handled after 2 ms at most, which is okay. In addition to this, we - * allow for an expiration range of 1 ms. - */ - -/* - * Delay lengths for the hrtimer event types. - * Keep this list sorted by delay length, in the same order as - * the event types indexed by enum fotg210_hrtimer_event in fotg210.h. - */ -static unsigned event_delays_ns[] = { - 1 * NSEC_PER_MSEC, /* FOTG210_HRTIMER_POLL_ASS */ - 1 * NSEC_PER_MSEC, /* FOTG210_HRTIMER_POLL_PSS */ - 1 * NSEC_PER_MSEC, /* FOTG210_HRTIMER_POLL_DEAD */ - 1125 * NSEC_PER_USEC, /* FOTG210_HRTIMER_UNLINK_INTR */ - 2 * NSEC_PER_MSEC, /* FOTG210_HRTIMER_FREE_ITDS */ - 6 * NSEC_PER_MSEC, /* FOTG210_HRTIMER_ASYNC_UNLINKS */ - 10 * NSEC_PER_MSEC, /* FOTG210_HRTIMER_IAA_WATCHDOG */ - 10 * NSEC_PER_MSEC, /* FOTG210_HRTIMER_DISABLE_PERIODIC */ - 15 * NSEC_PER_MSEC, /* FOTG210_HRTIMER_DISABLE_ASYNC */ - 100 * NSEC_PER_MSEC, /* FOTG210_HRTIMER_IO_WATCHDOG */ -}; - -/* Enable a pending hrtimer event */ -static void fotg210_enable_event(struct fotg210_hcd *fotg210, unsigned event, - bool resched) -{ - ktime_t *timeout = &fotg210->hr_timeouts[event]; - - if (resched) - *timeout = ktime_add(ktime_get(), - ktime_set(0, event_delays_ns[event])); - fotg210->enabled_hrtimer_events |= (1 << event); - - /* Track only the lowest-numbered pending event */ - if (event < fotg210->next_hrtimer_event) { - fotg210->next_hrtimer_event = event; - hrtimer_start_range_ns(&fotg210->hrtimer, *timeout, - NSEC_PER_MSEC, HRTIMER_MODE_ABS); - } -} - - -/* Poll the STS_ASS status bit; see when it agrees with CMD_ASE */ -static void fotg210_poll_ASS(struct fotg210_hcd *fotg210) -{ - unsigned actual, want; - - /* Don't enable anything if the controller isn't running (e.g., died) */ - if (fotg210->rh_state != FOTG210_RH_RUNNING) - return; - - want = (fotg210->command & CMD_ASE) ? STS_ASS : 0; - actual = fotg210_readl(fotg210, &fotg210->regs->status) & STS_ASS; - - if (want != actual) { - - /* Poll again later, but give up after about 20 ms */ - if (fotg210->ASS_poll_count++ < 20) { - fotg210_enable_event(fotg210, FOTG210_HRTIMER_POLL_ASS, - true); - return; - } - fotg210_dbg(fotg210, "Waited too long for the async schedule status (%x/%x), giving up\n", - want, actual); - } - fotg210->ASS_poll_count = 0; - - /* The status is up-to-date; restart or stop the schedule as needed */ - if (want == 0) { /* Stopped */ - if (fotg210->async_count > 0) - fotg210_set_command_bit(fotg210, CMD_ASE); - - } else { /* Running */ - if (fotg210->async_count == 0) { - - /* Turn off the schedule after a while */ - fotg210_enable_event(fotg210, - FOTG210_HRTIMER_DISABLE_ASYNC, - true); - } - } -} - -/* Turn off the async schedule after a brief delay */ -static void fotg210_disable_ASE(struct fotg210_hcd *fotg210) -{ - fotg210_clear_command_bit(fotg210, CMD_ASE); -} - - -/* Poll the STS_PSS status bit; see when it agrees with CMD_PSE */ -static void fotg210_poll_PSS(struct fotg210_hcd *fotg210) -{ - unsigned actual, want; - - /* Don't do anything if the controller isn't running (e.g., died) */ - if (fotg210->rh_state != FOTG210_RH_RUNNING) - return; - - want = (fotg210->command & CMD_PSE) ? STS_PSS : 0; - actual = fotg210_readl(fotg210, &fotg210->regs->status) & STS_PSS; - - if (want != actual) { - - /* Poll again later, but give up after about 20 ms */ - if (fotg210->PSS_poll_count++ < 20) { - fotg210_enable_event(fotg210, FOTG210_HRTIMER_POLL_PSS, - true); - return; - } - fotg210_dbg(fotg210, "Waited too long for the periodic schedule status (%x/%x), giving up\n", - want, actual); - } - fotg210->PSS_poll_count = 0; - - /* The status is up-to-date; restart or stop the schedule as needed */ - if (want == 0) { /* Stopped */ - if (fotg210->periodic_count > 0) - fotg210_set_command_bit(fotg210, CMD_PSE); - - } else { /* Running */ - if (fotg210->periodic_count == 0) { - - /* Turn off the schedule after a while */ - fotg210_enable_event(fotg210, - FOTG210_HRTIMER_DISABLE_PERIODIC, - true); - } - } -} - -/* Turn off the periodic schedule after a brief delay */ -static void fotg210_disable_PSE(struct fotg210_hcd *fotg210) -{ - fotg210_clear_command_bit(fotg210, CMD_PSE); -} - - -/* Poll the STS_HALT status bit; see when a dead controller stops */ -static void fotg210_handle_controller_death(struct fotg210_hcd *fotg210) -{ - if (!(fotg210_readl(fotg210, &fotg210->regs->status) & STS_HALT)) { - - /* Give up after a few milliseconds */ - if (fotg210->died_poll_count++ < 5) { - /* Try again later */ - fotg210_enable_event(fotg210, - FOTG210_HRTIMER_POLL_DEAD, true); - return; - } - fotg210_warn(fotg210, "Waited too long for the controller to stop, giving up\n"); - } - - /* Clean up the mess */ - fotg210->rh_state = FOTG210_RH_HALTED; - fotg210_writel(fotg210, 0, &fotg210->regs->intr_enable); - fotg210_work(fotg210); - end_unlink_async(fotg210); - - /* Not in process context, so don't try to reset the controller */ -} - - -/* Handle unlinked interrupt QHs once they are gone from the hardware */ -static void fotg210_handle_intr_unlinks(struct fotg210_hcd *fotg210) -{ - bool stopped = (fotg210->rh_state < FOTG210_RH_RUNNING); - - /* - * Process all the QHs on the intr_unlink list that were added - * before the current unlink cycle began. The list is in - * temporal order, so stop when we reach the first entry in the - * current cycle. But if the root hub isn't running then - * process all the QHs on the list. - */ - fotg210->intr_unlinking = true; - while (fotg210->intr_unlink) { - struct fotg210_qh *qh = fotg210->intr_unlink; - - if (!stopped && qh->unlink_cycle == fotg210->intr_unlink_cycle) - break; - fotg210->intr_unlink = qh->unlink_next; - qh->unlink_next = NULL; - end_unlink_intr(fotg210, qh); - } - - /* Handle remaining entries later */ - if (fotg210->intr_unlink) { - fotg210_enable_event(fotg210, FOTG210_HRTIMER_UNLINK_INTR, - true); - ++fotg210->intr_unlink_cycle; - } - fotg210->intr_unlinking = false; -} - - -/* Start another free-iTDs/siTDs cycle */ -static void start_free_itds(struct fotg210_hcd *fotg210) -{ - if (!(fotg210->enabled_hrtimer_events & - BIT(FOTG210_HRTIMER_FREE_ITDS))) { - fotg210->last_itd_to_free = list_entry( - fotg210->cached_itd_list.prev, - struct fotg210_itd, itd_list); - fotg210_enable_event(fotg210, FOTG210_HRTIMER_FREE_ITDS, true); - } -} - -/* Wait for controller to stop using old iTDs and siTDs */ -static void end_free_itds(struct fotg210_hcd *fotg210) -{ - struct fotg210_itd *itd, *n; - - if (fotg210->rh_state < FOTG210_RH_RUNNING) - fotg210->last_itd_to_free = NULL; - - list_for_each_entry_safe(itd, n, &fotg210->cached_itd_list, itd_list) { - list_del(&itd->itd_list); - dma_pool_free(fotg210->itd_pool, itd, itd->itd_dma); - if (itd == fotg210->last_itd_to_free) - break; - } - - if (!list_empty(&fotg210->cached_itd_list)) - start_free_itds(fotg210); -} - - -/* Handle lost (or very late) IAA interrupts */ -static void fotg210_iaa_watchdog(struct fotg210_hcd *fotg210) -{ - if (fotg210->rh_state != FOTG210_RH_RUNNING) - return; - - /* - * Lost IAA irqs wedge things badly; seen first with a vt8235. - * So we need this watchdog, but must protect it against both - * (a) SMP races against real IAA firing and retriggering, and - * (b) clean HC shutdown, when IAA watchdog was pending. - */ - if (fotg210->async_iaa) { - u32 cmd, status; - - /* If we get here, IAA is *REALLY* late. It's barely - * conceivable that the system is so busy that CMD_IAAD - * is still legitimately set, so let's be sure it's - * clear before we read STS_IAA. (The HC should clear - * CMD_IAAD when it sets STS_IAA.) - */ - cmd = fotg210_readl(fotg210, &fotg210->regs->command); - - /* - * If IAA is set here it either legitimately triggered - * after the watchdog timer expired (_way_ late, so we'll - * still count it as lost) ... or a silicon erratum: - * - VIA seems to set IAA without triggering the IRQ; - * - IAAD potentially cleared without setting IAA. - */ - status = fotg210_readl(fotg210, &fotg210->regs->status); - if ((status & STS_IAA) || !(cmd & CMD_IAAD)) { - COUNT(fotg210->stats.lost_iaa); - fotg210_writel(fotg210, STS_IAA, - &fotg210->regs->status); - } - - fotg210_vdbg(fotg210, "IAA watchdog: status %x cmd %x\n", - status, cmd); - end_unlink_async(fotg210); - } -} - - -/* Enable the I/O watchdog, if appropriate */ -static void turn_on_io_watchdog(struct fotg210_hcd *fotg210) -{ - /* Not needed if the controller isn't running or it's already enabled */ - if (fotg210->rh_state != FOTG210_RH_RUNNING || - (fotg210->enabled_hrtimer_events & - BIT(FOTG210_HRTIMER_IO_WATCHDOG))) - return; - - /* - * Isochronous transfers always need the watchdog. - * For other sorts we use it only if the flag is set. - */ - if (fotg210->isoc_count > 0 || (fotg210->need_io_watchdog && - fotg210->async_count + fotg210->intr_count > 0)) - fotg210_enable_event(fotg210, FOTG210_HRTIMER_IO_WATCHDOG, - true); -} - - -/* - * Handler functions for the hrtimer event types. - * Keep this array in the same order as the event types indexed by - * enum fotg210_hrtimer_event in fotg210.h. - */ -static void (*event_handlers[])(struct fotg210_hcd *) = { - fotg210_poll_ASS, /* FOTG210_HRTIMER_POLL_ASS */ - fotg210_poll_PSS, /* FOTG210_HRTIMER_POLL_PSS */ - fotg210_handle_controller_death, /* FOTG210_HRTIMER_POLL_DEAD */ - fotg210_handle_intr_unlinks, /* FOTG210_HRTIMER_UNLINK_INTR */ - end_free_itds, /* FOTG210_HRTIMER_FREE_ITDS */ - unlink_empty_async, /* FOTG210_HRTIMER_ASYNC_UNLINKS */ - fotg210_iaa_watchdog, /* FOTG210_HRTIMER_IAA_WATCHDOG */ - fotg210_disable_PSE, /* FOTG210_HRTIMER_DISABLE_PERIODIC */ - fotg210_disable_ASE, /* FOTG210_HRTIMER_DISABLE_ASYNC */ - fotg210_work, /* FOTG210_HRTIMER_IO_WATCHDOG */ -}; - -static enum hrtimer_restart fotg210_hrtimer_func(struct hrtimer *t) -{ - struct fotg210_hcd *fotg210 = - container_of(t, struct fotg210_hcd, hrtimer); - ktime_t now; - unsigned long events; - unsigned long flags; - unsigned e; - - spin_lock_irqsave(&fotg210->lock, flags); - - events = fotg210->enabled_hrtimer_events; - fotg210->enabled_hrtimer_events = 0; - fotg210->next_hrtimer_event = FOTG210_HRTIMER_NO_EVENT; - - /* - * Check each pending event. If its time has expired, handle - * the event; otherwise re-enable it. - */ - now = ktime_get(); - for_each_set_bit(e, &events, FOTG210_HRTIMER_NUM_EVENTS) { - if (now.tv64 >= fotg210->hr_timeouts[e].tv64) - event_handlers[e](fotg210); - else - fotg210_enable_event(fotg210, e, false); - } - - spin_unlock_irqrestore(&fotg210->lock, flags); - return HRTIMER_NORESTART; -} - -/*-------------------------------------------------------------------------*/ - -#define fotg210_bus_suspend NULL -#define fotg210_bus_resume NULL - -/*-------------------------------------------------------------------------*/ - -static int check_reset_complete( - struct fotg210_hcd *fotg210, - int index, - u32 __iomem *status_reg, - int port_status -) { - if (!(port_status & PORT_CONNECT)) - return port_status; - - /* if reset finished and it's still not enabled -- handoff */ - if (!(port_status & PORT_PE)) { - /* with integrated TT, there's nobody to hand it to! */ - fotg210_dbg(fotg210, - "Failed to enable port %d on root hub TT\n", - index+1); - return port_status; - } else { - fotg210_dbg(fotg210, "port %d reset complete, port enabled\n", - index + 1); - } - - return port_status; -} - -/*-------------------------------------------------------------------------*/ - - -/* build "status change" packet (one or two bytes) from HC registers */ - -static int -fotg210_hub_status_data(struct usb_hcd *hcd, char *buf) -{ - struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); - u32 temp, status; - u32 mask; - int retval = 1; - unsigned long flags; - - /* init status to no-changes */ - buf[0] = 0; - - /* Inform the core about resumes-in-progress by returning - * a non-zero value even if there are no status changes. - */ - status = fotg210->resuming_ports; - - mask = PORT_CSC | PORT_PEC; - /* PORT_RESUME from hardware ~= PORT_STAT_C_SUSPEND */ - - /* no hub change reports (bit 0) for now (power, ...) */ - - /* port N changes (bit N)? */ - spin_lock_irqsave(&fotg210->lock, flags); - - temp = fotg210_readl(fotg210, &fotg210->regs->port_status); - - /* - * Return status information even for ports with OWNER set. - * Otherwise khubd wouldn't see the disconnect event when a - * high-speed device is switched over to the companion - * controller by the user. - */ - - if ((temp & mask) != 0 || test_bit(0, &fotg210->port_c_suspend) - || (fotg210->reset_done[0] && time_after_eq( - jiffies, fotg210->reset_done[0]))) { - buf[0] |= 1 << 1; - status = STS_PCD; - } - /* FIXME autosuspend idle root hubs */ - spin_unlock_irqrestore(&fotg210->lock, flags); - return status ? retval : 0; -} - -/*-------------------------------------------------------------------------*/ - -static void -fotg210_hub_descriptor( - struct fotg210_hcd *fotg210, - struct usb_hub_descriptor *desc -) { - int ports = HCS_N_PORTS(fotg210->hcs_params); - u16 temp; - - desc->bDescriptorType = 0x29; - desc->bPwrOn2PwrGood = 10; /* fotg210 1.0, 2.3.9 says 20ms max */ - desc->bHubContrCurrent = 0; - - desc->bNbrPorts = ports; - temp = 1 + (ports / 8); - desc->bDescLength = 7 + 2 * temp; - - /* two bitmaps: ports removable, and usb 1.0 legacy PortPwrCtrlMask */ - memset(&desc->u.hs.DeviceRemovable[0], 0, temp); - memset(&desc->u.hs.DeviceRemovable[temp], 0xff, temp); - - temp = 0x0008; /* per-port overcurrent reporting */ - temp |= 0x0002; /* no power switching */ - desc->wHubCharacteristics = cpu_to_le16(temp); -} - -/*-------------------------------------------------------------------------*/ - -static int fotg210_hub_control( - struct usb_hcd *hcd, - u16 typeReq, - u16 wValue, - u16 wIndex, - char *buf, - u16 wLength -) { - struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); - int ports = HCS_N_PORTS(fotg210->hcs_params); - u32 __iomem *status_reg = &fotg210->regs->port_status; - u32 temp, temp1, status; - unsigned long flags; - int retval = 0; - unsigned selector; - - /* - * FIXME: support SetPortFeatures USB_PORT_FEAT_INDICATOR. - * HCS_INDICATOR may say we can change LEDs to off/amber/green. - * (track current state ourselves) ... blink for diagnostics, - * power, "this is the one", etc. EHCI spec supports this. - */ - - spin_lock_irqsave(&fotg210->lock, flags); - switch (typeReq) { - case ClearHubFeature: - switch (wValue) { - case C_HUB_LOCAL_POWER: - case C_HUB_OVER_CURRENT: - /* no hub-wide feature/status flags */ - break; - default: - goto error; - } - break; - case ClearPortFeature: - if (!wIndex || wIndex > ports) - goto error; - wIndex--; - temp = fotg210_readl(fotg210, status_reg); - temp &= ~PORT_RWC_BITS; - - /* - * Even if OWNER is set, so the port is owned by the - * companion controller, khubd needs to be able to clear - * the port-change status bits (especially - * USB_PORT_STAT_C_CONNECTION). - */ - - switch (wValue) { - case USB_PORT_FEAT_ENABLE: - fotg210_writel(fotg210, temp & ~PORT_PE, status_reg); - break; - case USB_PORT_FEAT_C_ENABLE: - fotg210_writel(fotg210, temp | PORT_PEC, status_reg); - break; - case USB_PORT_FEAT_SUSPEND: - if (temp & PORT_RESET) - goto error; - if (!(temp & PORT_SUSPEND)) - break; - if ((temp & PORT_PE) == 0) - goto error; - - /* resume signaling for 20 msec */ - fotg210_writel(fotg210, temp | PORT_RESUME, status_reg); - fotg210->reset_done[wIndex] = jiffies - + msecs_to_jiffies(20); - break; - case USB_PORT_FEAT_C_SUSPEND: - clear_bit(wIndex, &fotg210->port_c_suspend); - break; - case USB_PORT_FEAT_C_CONNECTION: - fotg210_writel(fotg210, temp | PORT_CSC, status_reg); - break; - case USB_PORT_FEAT_C_OVER_CURRENT: - fotg210_writel(fotg210, temp | OTGISR_OVC, - &fotg210->regs->otgisr); - break; - case USB_PORT_FEAT_C_RESET: - /* GetPortStatus clears reset */ - break; - default: - goto error; - } - fotg210_readl(fotg210, &fotg210->regs->command); - break; - case GetHubDescriptor: - fotg210_hub_descriptor(fotg210, (struct usb_hub_descriptor *) - buf); - break; - case GetHubStatus: - /* no hub-wide feature/status flags */ - memset(buf, 0, 4); - /*cpu_to_le32s ((u32 *) buf); */ - break; - case GetPortStatus: - if (!wIndex || wIndex > ports) - goto error; - wIndex--; - status = 0; - temp = fotg210_readl(fotg210, status_reg); - - /* wPortChange bits */ - if (temp & PORT_CSC) - status |= USB_PORT_STAT_C_CONNECTION << 16; - if (temp & PORT_PEC) - status |= USB_PORT_STAT_C_ENABLE << 16; - - temp1 = fotg210_readl(fotg210, &fotg210->regs->otgisr); - if (temp1 & OTGISR_OVC) - status |= USB_PORT_STAT_C_OVERCURRENT << 16; - - /* whoever resumes must GetPortStatus to complete it!! */ - if (temp & PORT_RESUME) { - - /* Remote Wakeup received? */ - if (!fotg210->reset_done[wIndex]) { - /* resume signaling for 20 msec */ - fotg210->reset_done[wIndex] = jiffies - + msecs_to_jiffies(20); - /* check the port again */ - mod_timer(&fotg210_to_hcd(fotg210)->rh_timer, - fotg210->reset_done[wIndex]); - } - - /* resume completed? */ - else if (time_after_eq(jiffies, - fotg210->reset_done[wIndex])) { - clear_bit(wIndex, &fotg210->suspended_ports); - set_bit(wIndex, &fotg210->port_c_suspend); - fotg210->reset_done[wIndex] = 0; - - /* stop resume signaling */ - temp = fotg210_readl(fotg210, status_reg); - fotg210_writel(fotg210, - temp & ~(PORT_RWC_BITS | PORT_RESUME), - status_reg); - clear_bit(wIndex, &fotg210->resuming_ports); - retval = handshake(fotg210, status_reg, - PORT_RESUME, 0, 2000 /* 2msec */); - if (retval != 0) { - fotg210_err(fotg210, - "port %d resume error %d\n", - wIndex + 1, retval); - goto error; - } - temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10)); - } - } - - /* whoever resets must GetPortStatus to complete it!! */ - if ((temp & PORT_RESET) - && time_after_eq(jiffies, - fotg210->reset_done[wIndex])) { - status |= USB_PORT_STAT_C_RESET << 16; - fotg210->reset_done[wIndex] = 0; - clear_bit(wIndex, &fotg210->resuming_ports); - - /* force reset to complete */ - fotg210_writel(fotg210, - temp & ~(PORT_RWC_BITS | PORT_RESET), - status_reg); - /* REVISIT: some hardware needs 550+ usec to clear - * this bit; seems too long to spin routinely... - */ - retval = handshake(fotg210, status_reg, - PORT_RESET, 0, 1000); - if (retval != 0) { - fotg210_err(fotg210, "port %d reset error %d\n", - wIndex + 1, retval); - goto error; - } - - /* see what we found out */ - temp = check_reset_complete(fotg210, wIndex, status_reg, - fotg210_readl(fotg210, status_reg)); - } - - if (!(temp & (PORT_RESUME|PORT_RESET))) { - fotg210->reset_done[wIndex] = 0; - clear_bit(wIndex, &fotg210->resuming_ports); - } - - /* transfer dedicated ports to the companion hc */ - if ((temp & PORT_CONNECT) && - test_bit(wIndex, &fotg210->companion_ports)) { - temp &= ~PORT_RWC_BITS; - fotg210_writel(fotg210, temp, status_reg); - fotg210_dbg(fotg210, "port %d --> companion\n", - wIndex + 1); - temp = fotg210_readl(fotg210, status_reg); - } - - /* - * Even if OWNER is set, there's no harm letting khubd - * see the wPortStatus values (they should all be 0 except - * for PORT_POWER anyway). - */ - - if (temp & PORT_CONNECT) { - status |= USB_PORT_STAT_CONNECTION; - status |= fotg210_port_speed(fotg210, temp); - } - if (temp & PORT_PE) - status |= USB_PORT_STAT_ENABLE; - - /* maybe the port was unsuspended without our knowledge */ - if (temp & (PORT_SUSPEND|PORT_RESUME)) { - status |= USB_PORT_STAT_SUSPEND; - } else if (test_bit(wIndex, &fotg210->suspended_ports)) { - clear_bit(wIndex, &fotg210->suspended_ports); - clear_bit(wIndex, &fotg210->resuming_ports); - fotg210->reset_done[wIndex] = 0; - if (temp & PORT_PE) - set_bit(wIndex, &fotg210->port_c_suspend); - } - - temp1 = fotg210_readl(fotg210, &fotg210->regs->otgisr); - if (temp1 & OTGISR_OVC) - status |= USB_PORT_STAT_OVERCURRENT; - if (temp & PORT_RESET) - status |= USB_PORT_STAT_RESET; - if (test_bit(wIndex, &fotg210->port_c_suspend)) - status |= USB_PORT_STAT_C_SUSPEND << 16; - -#ifndef VERBOSE_DEBUG - if (status & ~0xffff) /* only if wPortChange is interesting */ -#endif - dbg_port(fotg210, "GetStatus", wIndex + 1, temp); - put_unaligned_le32(status, buf); - break; - case SetHubFeature: - switch (wValue) { - case C_HUB_LOCAL_POWER: - case C_HUB_OVER_CURRENT: - /* no hub-wide feature/status flags */ - break; - default: - goto error; - } - break; - case SetPortFeature: - selector = wIndex >> 8; - wIndex &= 0xff; - - if (!wIndex || wIndex > ports) - goto error; - wIndex--; - temp = fotg210_readl(fotg210, status_reg); - temp &= ~PORT_RWC_BITS; - switch (wValue) { - case USB_PORT_FEAT_SUSPEND: - if ((temp & PORT_PE) == 0 - || (temp & PORT_RESET) != 0) - goto error; - - /* After above check the port must be connected. - * Set appropriate bit thus could put phy into low power - * mode if we have hostpc feature - */ - fotg210_writel(fotg210, temp | PORT_SUSPEND, - status_reg); - set_bit(wIndex, &fotg210->suspended_ports); - break; - case USB_PORT_FEAT_RESET: - if (temp & PORT_RESUME) - goto error; - /* line status bits may report this as low speed, - * which can be fine if this root hub has a - * transaction translator built in. - */ - fotg210_vdbg(fotg210, "port %d reset\n", wIndex + 1); - temp |= PORT_RESET; - temp &= ~PORT_PE; - - /* - * caller must wait, then call GetPortStatus - * usb 2.0 spec says 50 ms resets on root - */ - fotg210->reset_done[wIndex] = jiffies - + msecs_to_jiffies(50); - fotg210_writel(fotg210, temp, status_reg); - break; - - /* For downstream facing ports (these): one hub port is put - * into test mode according to USB2 11.24.2.13, then the hub - * must be reset (which for root hub now means rmmod+modprobe, - * or else system reboot). See EHCI 2.3.9 and 4.14 for info - * about the EHCI-specific stuff. - */ - case USB_PORT_FEAT_TEST: - if (!selector || selector > 5) - goto error; - spin_unlock_irqrestore(&fotg210->lock, flags); - fotg210_quiesce(fotg210); - spin_lock_irqsave(&fotg210->lock, flags); - - /* Put all enabled ports into suspend */ - temp = fotg210_readl(fotg210, status_reg) & - ~PORT_RWC_BITS; - if (temp & PORT_PE) - fotg210_writel(fotg210, temp | PORT_SUSPEND, - status_reg); - - spin_unlock_irqrestore(&fotg210->lock, flags); - fotg210_halt(fotg210); - spin_lock_irqsave(&fotg210->lock, flags); - - temp = fotg210_readl(fotg210, status_reg); - temp |= selector << 16; - fotg210_writel(fotg210, temp, status_reg); - break; - - default: - goto error; - } - fotg210_readl(fotg210, &fotg210->regs->command); - break; - - default: -error: - /* "stall" on error */ - retval = -EPIPE; - } - spin_unlock_irqrestore(&fotg210->lock, flags); - return retval; -} - -static void __maybe_unused fotg210_relinquish_port(struct usb_hcd *hcd, - int portnum) -{ - return; -} - -static int __maybe_unused fotg210_port_handed_over(struct usb_hcd *hcd, - int portnum) -{ - return 0; -} -/*-------------------------------------------------------------------------*/ -/* - * There's basically three types of memory: - * - data used only by the HCD ... kmalloc is fine - * - async and periodic schedules, shared by HC and HCD ... these - * need to use dma_pool or dma_alloc_coherent - * - driver buffers, read/written by HC ... single shot DMA mapped - * - * There's also "register" data (e.g. PCI or SOC), which is memory mapped. - * No memory seen by this driver is pageable. - */ - -/*-------------------------------------------------------------------------*/ - -/* Allocate the key transfer structures from the previously allocated pool */ - -static inline void fotg210_qtd_init(struct fotg210_hcd *fotg210, - struct fotg210_qtd *qtd, dma_addr_t dma) -{ - memset(qtd, 0, sizeof(*qtd)); - qtd->qtd_dma = dma; - qtd->hw_token = cpu_to_hc32(fotg210, QTD_STS_HALT); - qtd->hw_next = FOTG210_LIST_END(fotg210); - qtd->hw_alt_next = FOTG210_LIST_END(fotg210); - INIT_LIST_HEAD(&qtd->qtd_list); -} - -static struct fotg210_qtd *fotg210_qtd_alloc(struct fotg210_hcd *fotg210, - gfp_t flags) -{ - struct fotg210_qtd *qtd; - dma_addr_t dma; - - qtd = dma_pool_alloc(fotg210->qtd_pool, flags, &dma); - if (qtd != NULL) - fotg210_qtd_init(fotg210, qtd, dma); - - return qtd; -} - -static inline void fotg210_qtd_free(struct fotg210_hcd *fotg210, - struct fotg210_qtd *qtd) -{ - dma_pool_free(fotg210->qtd_pool, qtd, qtd->qtd_dma); -} - - -static void qh_destroy(struct fotg210_hcd *fotg210, struct fotg210_qh *qh) -{ - /* clean qtds first, and know this is not linked */ - if (!list_empty(&qh->qtd_list) || qh->qh_next.ptr) { - fotg210_dbg(fotg210, "unused qh not empty!\n"); - BUG(); - } - if (qh->dummy) - fotg210_qtd_free(fotg210, qh->dummy); - dma_pool_free(fotg210->qh_pool, qh->hw, qh->qh_dma); - kfree(qh); -} - -static struct fotg210_qh *fotg210_qh_alloc(struct fotg210_hcd *fotg210, - gfp_t flags) -{ - struct fotg210_qh *qh; - dma_addr_t dma; - - qh = kzalloc(sizeof(*qh), GFP_ATOMIC); - if (!qh) - goto done; - qh->hw = (struct fotg210_qh_hw *) - dma_pool_alloc(fotg210->qh_pool, flags, &dma); - if (!qh->hw) - goto fail; - memset(qh->hw, 0, sizeof(*qh->hw)); - qh->qh_dma = dma; - INIT_LIST_HEAD(&qh->qtd_list); - - /* dummy td enables safe urb queuing */ - qh->dummy = fotg210_qtd_alloc(fotg210, flags); - if (qh->dummy == NULL) { - fotg210_dbg(fotg210, "no dummy td\n"); - goto fail1; - } -done: - return qh; -fail1: - dma_pool_free(fotg210->qh_pool, qh->hw, qh->qh_dma); -fail: - kfree(qh); - return NULL; -} - -/*-------------------------------------------------------------------------*/ - -/* The queue heads and transfer descriptors are managed from pools tied - * to each of the "per device" structures. - * This is the initialisation and cleanup code. - */ - -static void fotg210_mem_cleanup(struct fotg210_hcd *fotg210) -{ - if (fotg210->async) - qh_destroy(fotg210, fotg210->async); - fotg210->async = NULL; - - if (fotg210->dummy) - qh_destroy(fotg210, fotg210->dummy); - fotg210->dummy = NULL; - - /* DMA consistent memory and pools */ - if (fotg210->qtd_pool) - dma_pool_destroy(fotg210->qtd_pool); - fotg210->qtd_pool = NULL; - - if (fotg210->qh_pool) { - dma_pool_destroy(fotg210->qh_pool); - fotg210->qh_pool = NULL; - } - - if (fotg210->itd_pool) - dma_pool_destroy(fotg210->itd_pool); - fotg210->itd_pool = NULL; - - if (fotg210->periodic) - dma_free_coherent(fotg210_to_hcd(fotg210)->self.controller, - fotg210->periodic_size * sizeof(u32), - fotg210->periodic, fotg210->periodic_dma); - fotg210->periodic = NULL; - - /* shadow periodic table */ - kfree(fotg210->pshadow); - fotg210->pshadow = NULL; -} - -/* remember to add cleanup code (above) if you add anything here */ -static int fotg210_mem_init(struct fotg210_hcd *fotg210, gfp_t flags) -{ - int i; - - /* QTDs for control/bulk/intr transfers */ - fotg210->qtd_pool = dma_pool_create("fotg210_qtd", - fotg210_to_hcd(fotg210)->self.controller, - sizeof(struct fotg210_qtd), - 32 /* byte alignment (for hw parts) */, - 4096 /* can't cross 4K */); - if (!fotg210->qtd_pool) - goto fail; - - /* QHs for control/bulk/intr transfers */ - fotg210->qh_pool = dma_pool_create("fotg210_qh", - fotg210_to_hcd(fotg210)->self.controller, - sizeof(struct fotg210_qh_hw), - 32 /* byte alignment (for hw parts) */, - 4096 /* can't cross 4K */); - if (!fotg210->qh_pool) - goto fail; - - fotg210->async = fotg210_qh_alloc(fotg210, flags); - if (!fotg210->async) - goto fail; - - /* ITD for high speed ISO transfers */ - fotg210->itd_pool = dma_pool_create("fotg210_itd", - fotg210_to_hcd(fotg210)->self.controller, - sizeof(struct fotg210_itd), - 64 /* byte alignment (for hw parts) */, - 4096 /* can't cross 4K */); - if (!fotg210->itd_pool) - goto fail; - - /* Hardware periodic table */ - fotg210->periodic = (__le32 *) - dma_alloc_coherent(fotg210_to_hcd(fotg210)->self.controller, - fotg210->periodic_size * sizeof(__le32), - &fotg210->periodic_dma, 0); - if (fotg210->periodic == NULL) - goto fail; - - for (i = 0; i < fotg210->periodic_size; i++) - fotg210->periodic[i] = FOTG210_LIST_END(fotg210); - - /* software shadow of hardware table */ - fotg210->pshadow = kcalloc(fotg210->periodic_size, sizeof(void *), - flags); - if (fotg210->pshadow != NULL) - return 0; - -fail: - fotg210_dbg(fotg210, "couldn't init memory\n"); - fotg210_mem_cleanup(fotg210); - return -ENOMEM; -} -/*-------------------------------------------------------------------------*/ -/* - * EHCI hardware queue manipulation ... the core. QH/QTD manipulation. - * - * Control, bulk, and interrupt traffic all use "qh" lists. They list "qtd" - * entries describing USB transactions, max 16-20kB/entry (with 4kB-aligned - * buffers needed for the larger number). We use one QH per endpoint, queue - * multiple urbs (all three types) per endpoint. URBs may need several qtds. - * - * ISO traffic uses "ISO TD" (itd) records, and (along with - * interrupts) needs careful scheduling. Performance improvements can be - * an ongoing challenge. That's in "ehci-sched.c". - * - * USB 1.1 devices are handled (a) by "companion" OHCI or UHCI root hubs, - * or otherwise through transaction translators (TTs) in USB 2.0 hubs using - * (b) special fields in qh entries or (c) split iso entries. TTs will - * buffer low/full speed data so the host collects it at high speed. - */ - -/*-------------------------------------------------------------------------*/ - -/* fill a qtd, returning how much of the buffer we were able to queue up */ - -static int -qtd_fill(struct fotg210_hcd *fotg210, struct fotg210_qtd *qtd, dma_addr_t buf, - size_t len, int token, int maxpacket) -{ - int i, count; - u64 addr = buf; - - /* one buffer entry per 4K ... first might be short or unaligned */ - qtd->hw_buf[0] = cpu_to_hc32(fotg210, (u32)addr); - qtd->hw_buf_hi[0] = cpu_to_hc32(fotg210, (u32)(addr >> 32)); - count = 0x1000 - (buf & 0x0fff); /* rest of that page */ - if (likely(len < count)) /* ... iff needed */ - count = len; - else { - buf += 0x1000; - buf &= ~0x0fff; - - /* per-qtd limit: from 16K to 20K (best alignment) */ - for (i = 1; count < len && i < 5; i++) { - addr = buf; - qtd->hw_buf[i] = cpu_to_hc32(fotg210, (u32)addr); - qtd->hw_buf_hi[i] = cpu_to_hc32(fotg210, - (u32)(addr >> 32)); - buf += 0x1000; - if ((count + 0x1000) < len) - count += 0x1000; - else - count = len; - } - - /* short packets may only terminate transfers */ - if (count != len) - count -= (count % maxpacket); - } - qtd->hw_token = cpu_to_hc32(fotg210, (count << 16) | token); - qtd->length = count; - - return count; -} - -/*-------------------------------------------------------------------------*/ - -static inline void -qh_update(struct fotg210_hcd *fotg210, struct fotg210_qh *qh, - struct fotg210_qtd *qtd) -{ - struct fotg210_qh_hw *hw = qh->hw; - - /* writes to an active overlay are unsafe */ - BUG_ON(qh->qh_state != QH_STATE_IDLE); - - hw->hw_qtd_next = QTD_NEXT(fotg210, qtd->qtd_dma); - hw->hw_alt_next = FOTG210_LIST_END(fotg210); - - /* Except for control endpoints, we make hardware maintain data - * toggle (like OHCI) ... here (re)initialize the toggle in the QH, - * and set the pseudo-toggle in udev. Only usb_clear_halt() will - * ever clear it. - */ - if (!(hw->hw_info1 & cpu_to_hc32(fotg210, QH_TOGGLE_CTL))) { - unsigned is_out, epnum; - - is_out = qh->is_out; - epnum = (hc32_to_cpup(fotg210, &hw->hw_info1) >> 8) & 0x0f; - if (unlikely(!usb_gettoggle(qh->dev, epnum, is_out))) { - hw->hw_token &= ~cpu_to_hc32(fotg210, QTD_TOGGLE); - usb_settoggle(qh->dev, epnum, is_out, 1); - } - } - - hw->hw_token &= cpu_to_hc32(fotg210, QTD_TOGGLE | QTD_STS_PING); -} - -/* if it weren't for a common silicon quirk (writing the dummy into the qh - * overlay, so qh->hw_token wrongly becomes inactive/halted), only fault - * recovery (including urb dequeue) would need software changes to a QH... - */ -static void -qh_refresh(struct fotg210_hcd *fotg210, struct fotg210_qh *qh) -{ - struct fotg210_qtd *qtd; - - if (list_empty(&qh->qtd_list)) - qtd = qh->dummy; - else { - qtd = list_entry(qh->qtd_list.next, - struct fotg210_qtd, qtd_list); - /* - * first qtd may already be partially processed. - * If we come here during unlink, the QH overlay region - * might have reference to the just unlinked qtd. The - * qtd is updated in qh_completions(). Update the QH - * overlay here. - */ - if (cpu_to_hc32(fotg210, qtd->qtd_dma) == qh->hw->hw_current) { - qh->hw->hw_qtd_next = qtd->hw_next; - qtd = NULL; - } - } - - if (qtd) - qh_update(fotg210, qh, qtd); -} - -/*-------------------------------------------------------------------------*/ - -static void qh_link_async(struct fotg210_hcd *fotg210, struct fotg210_qh *qh); - -static void fotg210_clear_tt_buffer_complete(struct usb_hcd *hcd, - struct usb_host_endpoint *ep) -{ - struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); - struct fotg210_qh *qh = ep->hcpriv; - unsigned long flags; - - spin_lock_irqsave(&fotg210->lock, flags); - qh->clearing_tt = 0; - if (qh->qh_state == QH_STATE_IDLE && !list_empty(&qh->qtd_list) - && fotg210->rh_state == FOTG210_RH_RUNNING) - qh_link_async(fotg210, qh); - spin_unlock_irqrestore(&fotg210->lock, flags); -} - -static void fotg210_clear_tt_buffer(struct fotg210_hcd *fotg210, - struct fotg210_qh *qh, - struct urb *urb, u32 token) -{ - - /* If an async split transaction gets an error or is unlinked, - * the TT buffer may be left in an indeterminate state. We - * have to clear the TT buffer. - * - * Note: this routine is never called for Isochronous transfers. - */ - if (urb->dev->tt && !usb_pipeint(urb->pipe) && !qh->clearing_tt) { -#ifdef DEBUG - struct usb_device *tt = urb->dev->tt->hub; - dev_dbg(&tt->dev, - "clear tt buffer port %d, a%d ep%d t%08x\n", - urb->dev->ttport, urb->dev->devnum, - usb_pipeendpoint(urb->pipe), token); -#endif /* DEBUG */ - if (urb->dev->tt->hub != - fotg210_to_hcd(fotg210)->self.root_hub) { - if (usb_hub_clear_tt_buffer(urb) == 0) - qh->clearing_tt = 1; - } - } -} - -static int qtd_copy_status( - struct fotg210_hcd *fotg210, - struct urb *urb, - size_t length, - u32 token -) -{ - int status = -EINPROGRESS; - - /* count IN/OUT bytes, not SETUP (even short packets) */ - if (likely(QTD_PID(token) != 2)) - urb->actual_length += length - QTD_LENGTH(token); - - /* don't modify error codes */ - if (unlikely(urb->unlinked)) - return status; - - /* force cleanup after short read; not always an error */ - if (unlikely(IS_SHORT_READ(token))) - status = -EREMOTEIO; - - /* serious "can't proceed" faults reported by the hardware */ - if (token & QTD_STS_HALT) { - if (token & QTD_STS_BABBLE) { - /* FIXME "must" disable babbling device's port too */ - status = -EOVERFLOW; - /* CERR nonzero + halt --> stall */ - } else if (QTD_CERR(token)) { - status = -EPIPE; - - /* In theory, more than one of the following bits can be set - * since they are sticky and the transaction is retried. - * Which to test first is rather arbitrary. - */ - } else if (token & QTD_STS_MMF) { - /* fs/ls interrupt xfer missed the complete-split */ - status = -EPROTO; - } else if (token & QTD_STS_DBE) { - status = (QTD_PID(token) == 1) /* IN ? */ - ? -ENOSR /* hc couldn't read data */ - : -ECOMM; /* hc couldn't write data */ - } else if (token & QTD_STS_XACT) { - /* timeout, bad CRC, wrong PID, etc */ - fotg210_dbg(fotg210, "devpath %s ep%d%s 3strikes\n", - urb->dev->devpath, - usb_pipeendpoint(urb->pipe), - usb_pipein(urb->pipe) ? "in" : "out"); - status = -EPROTO; - } else { /* unknown */ - status = -EPROTO; - } - - fotg210_vdbg(fotg210, - "dev%d ep%d%s qtd token %08x --> status %d\n", - usb_pipedevice(urb->pipe), - usb_pipeendpoint(urb->pipe), - usb_pipein(urb->pipe) ? "in" : "out", - token, status); - } - - return status; -} - -static void -fotg210_urb_done(struct fotg210_hcd *fotg210, struct urb *urb, int status) -__releases(fotg210->lock) -__acquires(fotg210->lock) -{ - if (likely(urb->hcpriv != NULL)) { - struct fotg210_qh *qh = (struct fotg210_qh *) urb->hcpriv; - - /* S-mask in a QH means it's an interrupt urb */ - if ((qh->hw->hw_info2 & cpu_to_hc32(fotg210, QH_SMASK)) != 0) { - - /* ... update hc-wide periodic stats (for usbfs) */ - fotg210_to_hcd(fotg210)->self.bandwidth_int_reqs--; - } - } - - if (unlikely(urb->unlinked)) { - COUNT(fotg210->stats.unlink); - } else { - /* report non-error and short read status as zero */ - if (status == -EINPROGRESS || status == -EREMOTEIO) - status = 0; - COUNT(fotg210->stats.complete); - } - -#ifdef FOTG210_URB_TRACE - fotg210_dbg(fotg210, - "%s %s urb %p ep%d%s status %d len %d/%d\n", - __func__, urb->dev->devpath, urb, - usb_pipeendpoint(urb->pipe), - usb_pipein(urb->pipe) ? "in" : "out", - status, - urb->actual_length, urb->transfer_buffer_length); -#endif - - /* complete() can reenter this HCD */ - usb_hcd_unlink_urb_from_ep(fotg210_to_hcd(fotg210), urb); - spin_unlock(&fotg210->lock); - usb_hcd_giveback_urb(fotg210_to_hcd(fotg210), urb, status); - spin_lock(&fotg210->lock); -} - -static int qh_schedule(struct fotg210_hcd *fotg210, struct fotg210_qh *qh); - -/* - * Process and free completed qtds for a qh, returning URBs to drivers. - * Chases up to qh->hw_current. Returns number of completions called, - * indicating how much "real" work we did. - */ -static unsigned -qh_completions(struct fotg210_hcd *fotg210, struct fotg210_qh *qh) -{ - struct fotg210_qtd *last, *end = qh->dummy; - struct list_head *entry, *tmp; - int last_status; - int stopped; - unsigned count = 0; - u8 state; - struct fotg210_qh_hw *hw = qh->hw; - - if (unlikely(list_empty(&qh->qtd_list))) - return count; - - /* completions (or tasks on other cpus) must never clobber HALT - * till we've gone through and cleaned everything up, even when - * they add urbs to this qh's queue or mark them for unlinking. - * - * NOTE: unlinking expects to be done in queue order. - * - * It's a bug for qh->qh_state to be anything other than - * QH_STATE_IDLE, unless our caller is scan_async() or - * scan_intr(). - */ - state = qh->qh_state; - qh->qh_state = QH_STATE_COMPLETING; - stopped = (state == QH_STATE_IDLE); - - rescan: - last = NULL; - last_status = -EINPROGRESS; - qh->needs_rescan = 0; - - /* remove de-activated QTDs from front of queue. - * after faults (including short reads), cleanup this urb - * then let the queue advance. - * if queue is stopped, handles unlinks. - */ - list_for_each_safe(entry, tmp, &qh->qtd_list) { - struct fotg210_qtd *qtd; - struct urb *urb; - u32 token = 0; - - qtd = list_entry(entry, struct fotg210_qtd, qtd_list); - urb = qtd->urb; - - /* clean up any state from previous QTD ...*/ - if (last) { - if (likely(last->urb != urb)) { - fotg210_urb_done(fotg210, last->urb, - last_status); - count++; - last_status = -EINPROGRESS; - } - fotg210_qtd_free(fotg210, last); - last = NULL; - } - - /* ignore urbs submitted during completions we reported */ - if (qtd == end) - break; - - /* hardware copies qtd out of qh overlay */ - rmb(); - token = hc32_to_cpu(fotg210, qtd->hw_token); - - /* always clean up qtds the hc de-activated */ - retry_xacterr: - if ((token & QTD_STS_ACTIVE) == 0) { - - /* Report Data Buffer Error: non-fatal but useful */ - if (token & QTD_STS_DBE) - fotg210_dbg(fotg210, - "detected DataBufferErr for urb %p ep%d%s len %d, qtd %p [qh %p]\n", - urb, - usb_endpoint_num(&urb->ep->desc), - usb_endpoint_dir_in(&urb->ep->desc) - ? "in" : "out", - urb->transfer_buffer_length, - qtd, - qh); - - /* 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 < QH_XACTERR_MAX && - !urb->unlinked) { - fotg210_dbg(fotg210, - "detected XactErr len %zu/%zu retry %d\n", - qtd->length - QTD_LENGTH(token), qtd->length, 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 | - (FOTG210_TUNE_CERR << 10); - qtd->hw_token = cpu_to_hc32(fotg210, - token); - wmb(); - hw->hw_token = cpu_to_hc32(fotg210, - token); - goto retry_xacterr; - } - stopped = 1; - - /* magic dummy for some short reads; qh won't advance. - * that silicon quirk can kick in with this dummy too. - * - * other short reads won't stop the queue, including - * control transfers (status stage handles that) or - * most other single-qtd reads ... the queue stops if - * URB_SHORT_NOT_OK was set so the driver submitting - * the urbs could clean it up. - */ - } else if (IS_SHORT_READ(token) - && !(qtd->hw_alt_next - & FOTG210_LIST_END(fotg210))) { - stopped = 1; - } - - /* stop scanning when we reach qtds the hc is using */ - } else if (likely(!stopped - && fotg210->rh_state >= FOTG210_RH_RUNNING)) { - break; - - /* scan the whole queue for unlinks whenever it stops */ - } else { - stopped = 1; - - /* cancel everything if we halt, suspend, etc */ - if (fotg210->rh_state < FOTG210_RH_RUNNING) - last_status = -ESHUTDOWN; - - /* this qtd is active; skip it unless a previous qtd - * for its urb faulted, or its urb was canceled. - */ - else if (last_status == -EINPROGRESS && !urb->unlinked) - continue; - - /* qh unlinked; token in overlay may be most current */ - if (state == QH_STATE_IDLE - && cpu_to_hc32(fotg210, qtd->qtd_dma) - == hw->hw_current) { - token = hc32_to_cpu(fotg210, hw->hw_token); - - /* An unlink may leave an incomplete - * async transaction in the TT buffer. - * We have to clear it. - */ - fotg210_clear_tt_buffer(fotg210, qh, urb, - token); - } - } - - /* unless we already know the urb's status, collect qtd status - * and update count of bytes transferred. in common short read - * cases with only one data qtd (including control transfers), - * queue processing won't halt. but with two or more qtds (for - * example, with a 32 KB transfer), when the first qtd gets a - * short read the second must be removed by hand. - */ - if (last_status == -EINPROGRESS) { - last_status = qtd_copy_status(fotg210, urb, - qtd->length, token); - if (last_status == -EREMOTEIO - && (qtd->hw_alt_next - & FOTG210_LIST_END(fotg210))) - last_status = -EINPROGRESS; - - /* As part of low/full-speed endpoint-halt processing - * we must clear the TT buffer (11.17.5). - */ - if (unlikely(last_status != -EINPROGRESS && - last_status != -EREMOTEIO)) { - /* The TT's in some hubs malfunction when they - * receive this request following a STALL (they - * stop sending isochronous packets). Since a - * STALL can't leave the TT buffer in a busy - * state (if you believe Figures 11-48 - 11-51 - * in the USB 2.0 spec), we won't clear the TT - * buffer in this case. Strictly speaking this - * is a violation of the spec. - */ - if (last_status != -EPIPE) - fotg210_clear_tt_buffer(fotg210, qh, - urb, token); - } - } - - /* if we're removing something not at the queue head, - * patch the hardware queue pointer. - */ - if (stopped && qtd->qtd_list.prev != &qh->qtd_list) { - last = list_entry(qtd->qtd_list.prev, - struct fotg210_qtd, qtd_list); - last->hw_next = qtd->hw_next; - } - - /* 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 = 0; - } - - /* last urb's completion might still need calling */ - if (likely(last != NULL)) { - fotg210_urb_done(fotg210, last->urb, last_status); - count++; - fotg210_qtd_free(fotg210, last); - } - - /* Do we need to rescan for URBs dequeued during a giveback? */ - if (unlikely(qh->needs_rescan)) { - /* If the QH is already unlinked, do the rescan now. */ - if (state == QH_STATE_IDLE) - goto rescan; - - /* Otherwise we have to wait until the QH is fully unlinked. - * Our caller will start an unlink if qh->needs_rescan is - * set. But if an unlink has already started, nothing needs - * to be done. - */ - if (state != QH_STATE_LINKED) - qh->needs_rescan = 0; - } - - /* restore original state; caller must unlink or relink */ - qh->qh_state = state; - - /* be sure the hardware's done with the qh before refreshing - * it after fault cleanup, or recovering from silicon wrongly - * overlaying the dummy qtd (which reduces DMA chatter). - */ - if (stopped != 0 || hw->hw_qtd_next == FOTG210_LIST_END(fotg210)) { - switch (state) { - case QH_STATE_IDLE: - qh_refresh(fotg210, qh); - break; - case QH_STATE_LINKED: - /* We won't refresh a QH that's linked (after the HC - * stopped the queue). That avoids a race: - * - HC reads first part of QH; - * - CPU updates that first part and the token; - * - HC reads rest of that QH, including token - * Result: HC gets an inconsistent image, and then - * DMAs to/from the wrong memory (corrupting it). - * - * That should be rare for interrupt transfers, - * except maybe high bandwidth ... - */ - - /* Tell the caller to start an unlink */ - qh->needs_rescan = 1; - break; - /* otherwise, unlink already started */ - } - } - - return count; -} - -/*-------------------------------------------------------------------------*/ - -/* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */ -#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03)) -/* ... and packet size, for any kind of endpoint descriptor */ -#define max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff) - -/* - * reverse of qh_urb_transaction: free a list of TDs. - * used for cleanup after errors, before HC sees an URB's TDs. - */ -static void qtd_list_free( - struct fotg210_hcd *fotg210, - struct urb *urb, - struct list_head *qtd_list -) { - struct list_head *entry, *temp; - - list_for_each_safe(entry, temp, qtd_list) { - struct fotg210_qtd *qtd; - - qtd = list_entry(entry, struct fotg210_qtd, qtd_list); - list_del(&qtd->qtd_list); - fotg210_qtd_free(fotg210, qtd); - } -} - -/* - * create a list of filled qtds for this URB; won't link into qh. - */ -static struct list_head * -qh_urb_transaction( - struct fotg210_hcd *fotg210, - struct urb *urb, - struct list_head *head, - gfp_t flags -) { - struct fotg210_qtd *qtd, *qtd_prev; - dma_addr_t buf; - int len, this_sg_len, maxpacket; - int is_input; - u32 token; - int i; - struct scatterlist *sg; - - /* - * URBs map to sequences of QTDs: one logical transaction - */ - qtd = fotg210_qtd_alloc(fotg210, flags); - if (unlikely(!qtd)) - return NULL; - list_add_tail(&qtd->qtd_list, head); - qtd->urb = urb; - - token = QTD_STS_ACTIVE; - token |= (FOTG210_TUNE_CERR << 10); - /* for split transactions, SplitXState initialized to zero */ - - len = urb->transfer_buffer_length; - is_input = usb_pipein(urb->pipe); - if (usb_pipecontrol(urb->pipe)) { - /* SETUP pid */ - qtd_fill(fotg210, qtd, urb->setup_dma, - sizeof(struct usb_ctrlrequest), - token | (2 /* "setup" */ << 8), 8); - - /* ... and always at least one more pid */ - token ^= QTD_TOGGLE; - qtd_prev = qtd; - qtd = fotg210_qtd_alloc(fotg210, flags); - if (unlikely(!qtd)) - goto cleanup; - qtd->urb = urb; - qtd_prev->hw_next = QTD_NEXT(fotg210, qtd->qtd_dma); - list_add_tail(&qtd->qtd_list, head); - - /* for zero length DATA stages, STATUS is always IN */ - if (len == 0) - token |= (1 /* "in" */ << 8); - } - - /* - * data transfer stage: buffer setup - */ - i = urb->num_mapped_sgs; - if (len > 0 && i > 0) { - sg = urb->sg; - buf = sg_dma_address(sg); - - /* urb->transfer_buffer_length may be smaller than the - * size of the scatterlist (or vice versa) - */ - this_sg_len = min_t(int, sg_dma_len(sg), len); - } else { - sg = NULL; - buf = urb->transfer_dma; - this_sg_len = len; - } - - if (is_input) - token |= (1 /* "in" */ << 8); - /* else it's already initted to "out" pid (0 << 8) */ - - maxpacket = max_packet(usb_maxpacket(urb->dev, urb->pipe, !is_input)); - - /* - * buffer gets wrapped in one or more qtds; - * last one may be "short" (including zero len) - * and may serve as a control status ack - */ - for (;;) { - int this_qtd_len; - - this_qtd_len = qtd_fill(fotg210, qtd, buf, this_sg_len, token, - maxpacket); - this_sg_len -= this_qtd_len; - len -= this_qtd_len; - buf += this_qtd_len; - - /* - * short reads advance to a "magic" dummy instead of the next - * qtd ... that forces the queue to stop, for manual cleanup. - * (this will usually be overridden later.) - */ - if (is_input) - qtd->hw_alt_next = fotg210->async->hw->hw_alt_next; - - /* qh makes control packets use qtd toggle; maybe switch it */ - if ((maxpacket & (this_qtd_len + (maxpacket - 1))) == 0) - token ^= QTD_TOGGLE; - - if (likely(this_sg_len <= 0)) { - if (--i <= 0 || len <= 0) - break; - sg = sg_next(sg); - buf = sg_dma_address(sg); - this_sg_len = min_t(int, sg_dma_len(sg), len); - } - - qtd_prev = qtd; - qtd = fotg210_qtd_alloc(fotg210, flags); - if (unlikely(!qtd)) - goto cleanup; - qtd->urb = urb; - qtd_prev->hw_next = QTD_NEXT(fotg210, qtd->qtd_dma); - list_add_tail(&qtd->qtd_list, head); - } - - /* - * unless the caller requires manual cleanup after short reads, - * have the alt_next mechanism keep the queue running after the - * last data qtd (the only one, for control and most other cases). - */ - if (likely((urb->transfer_flags & URB_SHORT_NOT_OK) == 0 - || usb_pipecontrol(urb->pipe))) - qtd->hw_alt_next = FOTG210_LIST_END(fotg210); - - /* - * control requests may need a terminating data "status" ack; - * other OUT ones may need a terminating short packet - * (zero length). - */ - if (likely(urb->transfer_buffer_length != 0)) { - int one_more = 0; - - if (usb_pipecontrol(urb->pipe)) { - one_more = 1; - token ^= 0x0100; /* "in" <--> "out" */ - token |= QTD_TOGGLE; /* force DATA1 */ - } else if (usb_pipeout(urb->pipe) - && (urb->transfer_flags & URB_ZERO_PACKET) - && !(urb->transfer_buffer_length % maxpacket)) { - one_more = 1; - } - if (one_more) { - qtd_prev = qtd; - qtd = fotg210_qtd_alloc(fotg210, flags); - if (unlikely(!qtd)) - goto cleanup; - qtd->urb = urb; - qtd_prev->hw_next = QTD_NEXT(fotg210, qtd->qtd_dma); - list_add_tail(&qtd->qtd_list, head); - - /* never any data in such packets */ - qtd_fill(fotg210, qtd, 0, 0, token, 0); - } - } - - /* by default, enable interrupt on urb completion */ - if (likely(!(urb->transfer_flags & URB_NO_INTERRUPT))) - qtd->hw_token |= cpu_to_hc32(fotg210, QTD_IOC); - return head; - -cleanup: - qtd_list_free(fotg210, urb, head); - return NULL; -} - -/*-------------------------------------------------------------------------*/ -/* - * Would be best to create all qh's from config descriptors, - * when each interface/altsetting is established. Unlink - * any previous qh and cancel its urbs first; endpoints are - * implicitly reset then (data toggle too). - * That'd mean updating how usbcore talks to HCDs. (2.7?) -*/ - - -/* - * Each QH holds a qtd list; a QH is used for everything except iso. - * - * For interrupt urbs, the scheduler must set the microframe scheduling - * mask(s) each time the QH gets scheduled. For highspeed, that's - * just one microframe in the s-mask. For split interrupt transactions - * there are additional complications: c-mask, maybe FSTNs. - */ -static struct fotg210_qh * -qh_make( - struct fotg210_hcd *fotg210, - struct urb *urb, - gfp_t flags -) { - struct fotg210_qh *qh = fotg210_qh_alloc(fotg210, flags); - u32 info1 = 0, info2 = 0; - int is_input, type; - int maxp = 0; - struct usb_tt *tt = urb->dev->tt; - struct fotg210_qh_hw *hw; - - if (!qh) - return qh; - - /* - * init endpoint/device data for this QH - */ - info1 |= usb_pipeendpoint(urb->pipe) << 8; - info1 |= usb_pipedevice(urb->pipe) << 0; - - is_input = usb_pipein(urb->pipe); - type = usb_pipetype(urb->pipe); - maxp = usb_maxpacket(urb->dev, urb->pipe, !is_input); - - /* 1024 byte maxpacket is a hardware ceiling. High bandwidth - * acts like up to 3KB, but is built from smaller packets. - */ - if (max_packet(maxp) > 1024) { - fotg210_dbg(fotg210, "bogus qh maxpacket %d\n", - max_packet(maxp)); - goto done; - } - - /* Compute interrupt scheduling parameters just once, and save. - * - allowing for high bandwidth, how many nsec/uframe are used? - * - split transactions need a second CSPLIT uframe; same question - * - splits also need a schedule gap (for full/low speed I/O) - * - qh has a polling interval - * - * For control/bulk requests, the HC or TT handles these. - */ - if (type == PIPE_INTERRUPT) { - qh->usecs = NS_TO_US(usb_calc_bus_time(USB_SPEED_HIGH, - is_input, 0, - hb_mult(maxp) * max_packet(maxp))); - qh->start = NO_FRAME; - - if (urb->dev->speed == USB_SPEED_HIGH) { - qh->c_usecs = 0; - qh->gap_uf = 0; - - qh->period = urb->interval >> 3; - if (qh->period == 0 && urb->interval != 1) { - /* NOTE interval 2 or 4 uframes could work. - * But interval 1 scheduling is simpler, and - * includes high bandwidth. - */ - urb->interval = 1; - } else if (qh->period > fotg210->periodic_size) { - qh->period = fotg210->periodic_size; - urb->interval = qh->period << 3; - } - } else { - int think_time; - - /* gap is f(FS/LS transfer times) */ - qh->gap_uf = 1 + usb_calc_bus_time(urb->dev->speed, - is_input, 0, maxp) / (125 * 1000); - - /* FIXME this just approximates SPLIT/CSPLIT times */ - if (is_input) { /* SPLIT, gap, CSPLIT+DATA */ - qh->c_usecs = qh->usecs + HS_USECS(0); - qh->usecs = HS_USECS(1); - } else { /* SPLIT+DATA, gap, CSPLIT */ - qh->usecs += HS_USECS(1); - qh->c_usecs = HS_USECS(0); - } - - think_time = tt ? tt->think_time : 0; - qh->tt_usecs = NS_TO_US(think_time + - usb_calc_bus_time(urb->dev->speed, - is_input, 0, max_packet(maxp))); - qh->period = urb->interval; - if (qh->period > fotg210->periodic_size) { - qh->period = fotg210->periodic_size; - urb->interval = qh->period; - } - } - } - - /* support for tt scheduling, and access to toggles */ - qh->dev = urb->dev; - - /* using TT? */ - switch (urb->dev->speed) { - case USB_SPEED_LOW: - info1 |= QH_LOW_SPEED; - /* FALL THROUGH */ - - case USB_SPEED_FULL: - /* EPS 0 means "full" */ - if (type != PIPE_INTERRUPT) - info1 |= (FOTG210_TUNE_RL_TT << 28); - if (type == PIPE_CONTROL) { - info1 |= QH_CONTROL_EP; /* for TT */ - info1 |= QH_TOGGLE_CTL; /* toggle from qtd */ - } - info1 |= maxp << 16; - - info2 |= (FOTG210_TUNE_MULT_TT << 30); - - /* Some Freescale processors have an erratum in which the - * port number in the queue head was 0..N-1 instead of 1..N. - */ - if (fotg210_has_fsl_portno_bug(fotg210)) - info2 |= (urb->dev->ttport-1) << 23; - else - info2 |= urb->dev->ttport << 23; - - /* set the address of the TT; for TDI's integrated - * root hub tt, leave it zeroed. - */ - if (tt && tt->hub != fotg210_to_hcd(fotg210)->self.root_hub) - info2 |= tt->hub->devnum << 16; - - /* NOTE: if (PIPE_INTERRUPT) { scheduler sets c-mask } */ - - break; - - case USB_SPEED_HIGH: /* no TT involved */ - info1 |= QH_HIGH_SPEED; - if (type == PIPE_CONTROL) { - info1 |= (FOTG210_TUNE_RL_HS << 28); - info1 |= 64 << 16; /* usb2 fixed maxpacket */ - info1 |= QH_TOGGLE_CTL; /* toggle from qtd */ - info2 |= (FOTG210_TUNE_MULT_HS << 30); - } else if (type == PIPE_BULK) { - info1 |= (FOTG210_TUNE_RL_HS << 28); - /* The USB spec says that high speed bulk endpoints - * always use 512 byte maxpacket. But some device - * vendors decided to ignore that, and MSFT is happy - * to help them do so. So now people expect to use - * such nonconformant devices with Linux too; sigh. - */ - info1 |= max_packet(maxp) << 16; - info2 |= (FOTG210_TUNE_MULT_HS << 30); - } else { /* PIPE_INTERRUPT */ - info1 |= max_packet(maxp) << 16; - info2 |= hb_mult(maxp) << 30; - } - break; - default: - fotg210_dbg(fotg210, "bogus dev %p speed %d\n", urb->dev, - urb->dev->speed); -done: - qh_destroy(fotg210, qh); - return NULL; - } - - /* NOTE: if (PIPE_INTERRUPT) { scheduler sets s-mask } */ - - /* init as live, toggle clear, advance to dummy */ - qh->qh_state = QH_STATE_IDLE; - hw = qh->hw; - hw->hw_info1 = cpu_to_hc32(fotg210, info1); - hw->hw_info2 = cpu_to_hc32(fotg210, info2); - qh->is_out = !is_input; - usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), !is_input, 1); - qh_refresh(fotg210, qh); - return qh; -} - -/*-------------------------------------------------------------------------*/ - -static void enable_async(struct fotg210_hcd *fotg210) -{ - if (fotg210->async_count++) - return; - - /* Stop waiting to turn off the async schedule */ - fotg210->enabled_hrtimer_events &= ~BIT(FOTG210_HRTIMER_DISABLE_ASYNC); - - /* Don't start the schedule until ASS is 0 */ - fotg210_poll_ASS(fotg210); - turn_on_io_watchdog(fotg210); -} - -static void disable_async(struct fotg210_hcd *fotg210) -{ - if (--fotg210->async_count) - return; - - /* The async schedule and async_unlink list are supposed to be empty */ - WARN_ON(fotg210->async->qh_next.qh || fotg210->async_unlink); - - /* Don't turn off the schedule until ASS is 1 */ - fotg210_poll_ASS(fotg210); -} - -/* move qh (and its qtds) onto async queue; maybe enable queue. */ - -static void qh_link_async(struct fotg210_hcd *fotg210, struct fotg210_qh *qh) -{ - __hc32 dma = QH_NEXT(fotg210, qh->qh_dma); - struct fotg210_qh *head; - - /* Don't link a QH if there's a Clear-TT-Buffer pending */ - if (unlikely(qh->clearing_tt)) - return; - - WARN_ON(qh->qh_state != QH_STATE_IDLE); - - /* clear halt and/or toggle; and maybe recover from silicon quirk */ - qh_refresh(fotg210, qh); - - /* splice right after start */ - head = fotg210->async; - qh->qh_next = head->qh_next; - qh->hw->hw_next = head->hw->hw_next; - wmb(); - - head->qh_next.qh = qh; - head->hw->hw_next = dma; - - qh->xacterrs = 0; - qh->qh_state = QH_STATE_LINKED; - /* qtd completions reported later by interrupt */ - - enable_async(fotg210); -} - -/*-------------------------------------------------------------------------*/ - -/* - * For control/bulk/interrupt, return QH with these TDs appended. - * Allocates and initializes the QH if necessary. - * Returns null if it can't allocate a QH it needs to. - * If the QH has TDs (urbs) already, that's great. - */ -static struct fotg210_qh *qh_append_tds( - struct fotg210_hcd *fotg210, - struct urb *urb, - struct list_head *qtd_list, - int epnum, - void **ptr -) -{ - struct fotg210_qh *qh = NULL; - __hc32 qh_addr_mask = cpu_to_hc32(fotg210, 0x7f); - - qh = (struct fotg210_qh *) *ptr; - if (unlikely(qh == NULL)) { - /* can't sleep here, we have fotg210->lock... */ - qh = qh_make(fotg210, urb, GFP_ATOMIC); - *ptr = qh; - } - if (likely(qh != NULL)) { - struct fotg210_qtd *qtd; - - if (unlikely(list_empty(qtd_list))) - qtd = NULL; - else - qtd = list_entry(qtd_list->next, struct fotg210_qtd, - qtd_list); - - /* control qh may need patching ... */ - if (unlikely(epnum == 0)) { - /* usb_reset_device() briefly reverts to address 0 */ - if (usb_pipedevice(urb->pipe) == 0) - qh->hw->hw_info1 &= ~qh_addr_mask; - } - - /* just one way to queue requests: swap with the dummy qtd. - * only hc or qh_refresh() ever modify the overlay. - */ - if (likely(qtd != NULL)) { - struct fotg210_qtd *dummy; - dma_addr_t dma; - __hc32 token; - - /* to avoid racing the HC, use the dummy td instead of - * the first td of our list (becomes new dummy). both - * tds stay deactivated until we're done, when the - * HC is allowed to fetch the old dummy (4.10.2). - */ - token = qtd->hw_token; - qtd->hw_token = HALT_BIT(fotg210); - - dummy = qh->dummy; - - dma = dummy->qtd_dma; - *dummy = *qtd; - dummy->qtd_dma = dma; - - list_del(&qtd->qtd_list); - list_add(&dummy->qtd_list, qtd_list); - list_splice_tail(qtd_list, &qh->qtd_list); - - fotg210_qtd_init(fotg210, qtd, qtd->qtd_dma); - qh->dummy = qtd; - - /* hc must see the new dummy at list end */ - dma = qtd->qtd_dma; - qtd = list_entry(qh->qtd_list.prev, - struct fotg210_qtd, qtd_list); - qtd->hw_next = QTD_NEXT(fotg210, dma); - - /* let the hc process these next qtds */ - wmb(); - dummy->hw_token = token; - - urb->hcpriv = qh; - } - } - return qh; -} - -/*-------------------------------------------------------------------------*/ - -static int -submit_async( - struct fotg210_hcd *fotg210, - struct urb *urb, - struct list_head *qtd_list, - gfp_t mem_flags -) { - int epnum; - unsigned long flags; - struct fotg210_qh *qh = NULL; - int rc; - - epnum = urb->ep->desc.bEndpointAddress; - -#ifdef FOTG210_URB_TRACE - { - struct fotg210_qtd *qtd; - qtd = list_entry(qtd_list->next, struct fotg210_qtd, qtd_list); - fotg210_dbg(fotg210, - "%s %s urb %p ep%d%s len %d, qtd %p [qh %p]\n", - __func__, urb->dev->devpath, urb, - epnum & 0x0f, (epnum & USB_DIR_IN) ? "in" : "out", - urb->transfer_buffer_length, - qtd, urb->ep->hcpriv); - } -#endif - - spin_lock_irqsave(&fotg210->lock, flags); - if (unlikely(!HCD_HW_ACCESSIBLE(fotg210_to_hcd(fotg210)))) { - rc = -ESHUTDOWN; - goto done; - } - rc = usb_hcd_link_urb_to_ep(fotg210_to_hcd(fotg210), urb); - if (unlikely(rc)) - goto done; - - qh = qh_append_tds(fotg210, urb, qtd_list, epnum, &urb->ep->hcpriv); - if (unlikely(qh == NULL)) { - usb_hcd_unlink_urb_from_ep(fotg210_to_hcd(fotg210), urb); - rc = -ENOMEM; - goto done; - } - - /* Control/bulk operations through TTs don't need scheduling, - * the HC and TT handle it when the TT has a buffer ready. - */ - if (likely(qh->qh_state == QH_STATE_IDLE)) - qh_link_async(fotg210, qh); - done: - spin_unlock_irqrestore(&fotg210->lock, flags); - if (unlikely(qh == NULL)) - qtd_list_free(fotg210, urb, qtd_list); - return rc; -} - -/*-------------------------------------------------------------------------*/ - -static void single_unlink_async(struct fotg210_hcd *fotg210, - struct fotg210_qh *qh) -{ - struct fotg210_qh *prev; - - /* Add to the end of the list of QHs waiting for the next IAAD */ - qh->qh_state = QH_STATE_UNLINK; - if (fotg210->async_unlink) - fotg210->async_unlink_last->unlink_next = qh; - else - fotg210->async_unlink = qh; - fotg210->async_unlink_last = qh; - - /* Unlink it from the schedule */ - prev = fotg210->async; - while (prev->qh_next.qh != qh) - prev = prev->qh_next.qh; - - prev->hw->hw_next = qh->hw->hw_next; - prev->qh_next = qh->qh_next; - if (fotg210->qh_scan_next == qh) - fotg210->qh_scan_next = qh->qh_next.qh; -} - -static void start_iaa_cycle(struct fotg210_hcd *fotg210, bool nested) -{ - /* - * Do nothing if an IAA cycle is already running or - * if one will be started shortly. - */ - if (fotg210->async_iaa || fotg210->async_unlinking) - return; - - /* Do all the waiting QHs at once */ - fotg210->async_iaa = fotg210->async_unlink; - fotg210->async_unlink = NULL; - - /* If the controller isn't running, we don't have to wait for it */ - if (unlikely(fotg210->rh_state < FOTG210_RH_RUNNING)) { - if (!nested) /* Avoid recursion */ - end_unlink_async(fotg210); - - /* Otherwise start a new IAA cycle */ - } else if (likely(fotg210->rh_state == FOTG210_RH_RUNNING)) { - /* Make sure the unlinks are all visible to the hardware */ - wmb(); - - fotg210_writel(fotg210, fotg210->command | CMD_IAAD, - &fotg210->regs->command); - fotg210_readl(fotg210, &fotg210->regs->command); - fotg210_enable_event(fotg210, FOTG210_HRTIMER_IAA_WATCHDOG, - true); - } -} - -/* the async qh for the qtds being unlinked are now gone from the HC */ - -static void end_unlink_async(struct fotg210_hcd *fotg210) -{ - struct fotg210_qh *qh; - - /* Process the idle QHs */ - restart: - fotg210->async_unlinking = true; - while (fotg210->async_iaa) { - qh = fotg210->async_iaa; - fotg210->async_iaa = qh->unlink_next; - qh->unlink_next = NULL; - - qh->qh_state = QH_STATE_IDLE; - qh->qh_next.qh = NULL; - - qh_completions(fotg210, qh); - if (!list_empty(&qh->qtd_list) && - fotg210->rh_state == FOTG210_RH_RUNNING) - qh_link_async(fotg210, qh); - disable_async(fotg210); - } - fotg210->async_unlinking = false; - - /* Start a new IAA cycle if any QHs are waiting for it */ - if (fotg210->async_unlink) { - start_iaa_cycle(fotg210, true); - if (unlikely(fotg210->rh_state < FOTG210_RH_RUNNING)) - goto restart; - } -} - -static void unlink_empty_async(struct fotg210_hcd *fotg210) -{ - struct fotg210_qh *qh, *next; - bool stopped = (fotg210->rh_state < FOTG210_RH_RUNNING); - bool check_unlinks_later = false; - - /* Unlink all the async QHs that have been empty for a timer cycle */ - next = fotg210->async->qh_next.qh; - while (next) { - qh = next; - next = qh->qh_next.qh; - - if (list_empty(&qh->qtd_list) && - qh->qh_state == QH_STATE_LINKED) { - if (!stopped && qh->unlink_cycle == - fotg210->async_unlink_cycle) - check_unlinks_later = true; - else - single_unlink_async(fotg210, qh); - } - } - - /* Start a new IAA cycle if any QHs are waiting for it */ - if (fotg210->async_unlink) - start_iaa_cycle(fotg210, false); - - /* QHs that haven't been empty for long enough will be handled later */ - if (check_unlinks_later) { - fotg210_enable_event(fotg210, FOTG210_HRTIMER_ASYNC_UNLINKS, - true); - ++fotg210->async_unlink_cycle; - } -} - -/* makes sure the async qh will become idle */ -/* caller must own fotg210->lock */ - -static void start_unlink_async(struct fotg210_hcd *fotg210, - struct fotg210_qh *qh) -{ - /* - * If the QH isn't linked then there's nothing we can do - * unless we were called during a giveback, in which case - * qh_completions() has to deal with it. - */ - if (qh->qh_state != QH_STATE_LINKED) { - if (qh->qh_state == QH_STATE_COMPLETING) - qh->needs_rescan = 1; - return; - } - - single_unlink_async(fotg210, qh); - start_iaa_cycle(fotg210, false); -} - -/*-------------------------------------------------------------------------*/ - -static void scan_async(struct fotg210_hcd *fotg210) -{ - struct fotg210_qh *qh; - bool check_unlinks_later = false; - - fotg210->qh_scan_next = fotg210->async->qh_next.qh; - while (fotg210->qh_scan_next) { - qh = fotg210->qh_scan_next; - fotg210->qh_scan_next = qh->qh_next.qh; - rescan: - /* clean any finished work for this qh */ - if (!list_empty(&qh->qtd_list)) { - int temp; - - /* - * Unlinks could happen here; completion reporting - * drops the lock. That's why fotg210->qh_scan_next - * always holds the next qh to scan; if the next qh - * gets unlinked then fotg210->qh_scan_next is adjusted - * in single_unlink_async(). - */ - temp = qh_completions(fotg210, qh); - if (qh->needs_rescan) { - start_unlink_async(fotg210, qh); - } else if (list_empty(&qh->qtd_list) - && qh->qh_state == QH_STATE_LINKED) { - qh->unlink_cycle = fotg210->async_unlink_cycle; - check_unlinks_later = true; - } else if (temp != 0) - goto rescan; - } - } - - /* - * Unlink empty entries, reducing DMA usage as well - * as HCD schedule-scanning costs. Delay for any qh - * we just scanned, there's a not-unusual case that it - * doesn't stay idle for long. - */ - if (check_unlinks_later && fotg210->rh_state == FOTG210_RH_RUNNING && - !(fotg210->enabled_hrtimer_events & - BIT(FOTG210_HRTIMER_ASYNC_UNLINKS))) { - fotg210_enable_event(fotg210, - FOTG210_HRTIMER_ASYNC_UNLINKS, true); - ++fotg210->async_unlink_cycle; - } -} -/*-------------------------------------------------------------------------*/ -/* - * EHCI scheduled transaction support: interrupt, iso, split iso - * These are called "periodic" transactions in the EHCI spec. - * - * Note that for interrupt transfers, the QH/QTD manipulation is shared - * with the "asynchronous" transaction support (control/bulk transfers). - * The only real difference is in how interrupt transfers are scheduled. - * - * For ISO, we make an "iso_stream" head to serve the same role as a QH. - * It keeps track of every ITD (or SITD) that's linked, and holds enough - * pre-calculated schedule data to make appending to the queue be quick. - */ - -static int fotg210_get_frame(struct usb_hcd *hcd); - -/*-------------------------------------------------------------------------*/ - -/* - * periodic_next_shadow - return "next" pointer on shadow list - * @periodic: host pointer to qh/itd - * @tag: hardware tag for type of this record - */ -static union fotg210_shadow * -periodic_next_shadow(struct fotg210_hcd *fotg210, - union fotg210_shadow *periodic, __hc32 tag) -{ - switch (hc32_to_cpu(fotg210, tag)) { - case Q_TYPE_QH: - return &periodic->qh->qh_next; - case Q_TYPE_FSTN: - return &periodic->fstn->fstn_next; - default: - return &periodic->itd->itd_next; - } -} - -static __hc32 * -shadow_next_periodic(struct fotg210_hcd *fotg210, - union fotg210_shadow *periodic, __hc32 tag) -{ - switch (hc32_to_cpu(fotg210, tag)) { - /* our fotg210_shadow.qh is actually software part */ - case Q_TYPE_QH: - return &periodic->qh->hw->hw_next; - /* others are hw parts */ - default: - return periodic->hw_next; - } -} - -/* caller must hold fotg210->lock */ -static void periodic_unlink(struct fotg210_hcd *fotg210, unsigned frame, - void *ptr) -{ - union fotg210_shadow *prev_p = &fotg210->pshadow[frame]; - __hc32 *hw_p = &fotg210->periodic[frame]; - union fotg210_shadow here = *prev_p; - - /* find predecessor of "ptr"; hw and shadow lists are in sync */ - while (here.ptr && here.ptr != ptr) { - prev_p = periodic_next_shadow(fotg210, prev_p, - Q_NEXT_TYPE(fotg210, *hw_p)); - hw_p = shadow_next_periodic(fotg210, &here, - Q_NEXT_TYPE(fotg210, *hw_p)); - here = *prev_p; - } - /* an interrupt entry (at list end) could have been shared */ - if (!here.ptr) - return; - - /* update shadow and hardware lists ... the old "next" pointers - * from ptr may still be in use, the caller updates them. - */ - *prev_p = *periodic_next_shadow(fotg210, &here, - Q_NEXT_TYPE(fotg210, *hw_p)); - - *hw_p = *shadow_next_periodic(fotg210, &here, - Q_NEXT_TYPE(fotg210, *hw_p)); -} - -/* how many of the uframe's 125 usecs are allocated? */ -static unsigned short -periodic_usecs(struct fotg210_hcd *fotg210, unsigned frame, unsigned uframe) -{ - __hc32 *hw_p = &fotg210->periodic[frame]; - union fotg210_shadow *q = &fotg210->pshadow[frame]; - unsigned usecs = 0; - struct fotg210_qh_hw *hw; - - while (q->ptr) { - switch (hc32_to_cpu(fotg210, Q_NEXT_TYPE(fotg210, *hw_p))) { - case Q_TYPE_QH: - hw = q->qh->hw; - /* is it in the S-mask? */ - if (hw->hw_info2 & cpu_to_hc32(fotg210, 1 << uframe)) - usecs += q->qh->usecs; - /* ... or C-mask? */ - if (hw->hw_info2 & cpu_to_hc32(fotg210, - 1 << (8 + uframe))) - usecs += q->qh->c_usecs; - hw_p = &hw->hw_next; - q = &q->qh->qh_next; - break; - /* case Q_TYPE_FSTN: */ - default: - /* for "save place" FSTNs, count the relevant INTR - * bandwidth from the previous frame - */ - if (q->fstn->hw_prev != FOTG210_LIST_END(fotg210)) - fotg210_dbg(fotg210, "ignoring FSTN cost ...\n"); - - hw_p = &q->fstn->hw_next; - q = &q->fstn->fstn_next; - break; - case Q_TYPE_ITD: - if (q->itd->hw_transaction[uframe]) - usecs += q->itd->stream->usecs; - hw_p = &q->itd->hw_next; - q = &q->itd->itd_next; - break; - } - } -#ifdef DEBUG - if (usecs > fotg210->uframe_periodic_max) - fotg210_err(fotg210, "uframe %d sched overrun: %d usecs\n", - frame * 8 + uframe, usecs); -#endif - return usecs; -} - -/*-------------------------------------------------------------------------*/ - -static int same_tt(struct usb_device *dev1, struct usb_device *dev2) -{ - if (!dev1->tt || !dev2->tt) - return 0; - if (dev1->tt != dev2->tt) - return 0; - if (dev1->tt->multi) - return dev1->ttport == dev2->ttport; - else - return 1; -} - -/* return true iff the device's transaction translator is available - * for a periodic transfer starting at the specified frame, using - * all the uframes in the mask. - */ -static int tt_no_collision( - struct fotg210_hcd *fotg210, - unsigned period, - struct usb_device *dev, - unsigned frame, - u32 uf_mask -) -{ - if (period == 0) /* error */ - return 0; - - /* note bandwidth wastage: split never follows csplit - * (different dev or endpoint) until the next uframe. - * calling convention doesn't make that distinction. - */ - for (; frame < fotg210->periodic_size; frame += period) { - union fotg210_shadow here; - __hc32 type; - struct fotg210_qh_hw *hw; - - here = fotg210->pshadow[frame]; - type = Q_NEXT_TYPE(fotg210, fotg210->periodic[frame]); - while (here.ptr) { - switch (hc32_to_cpu(fotg210, type)) { - case Q_TYPE_ITD: - type = Q_NEXT_TYPE(fotg210, here.itd->hw_next); - here = here.itd->itd_next; - continue; - case Q_TYPE_QH: - hw = here.qh->hw; - if (same_tt(dev, here.qh->dev)) { - u32 mask; - - mask = hc32_to_cpu(fotg210, - hw->hw_info2); - /* "knows" no gap is needed */ - mask |= mask >> 8; - if (mask & uf_mask) - break; - } - type = Q_NEXT_TYPE(fotg210, hw->hw_next); - here = here.qh->qh_next; - continue; - /* case Q_TYPE_FSTN: */ - default: - fotg210_dbg(fotg210, - "periodic frame %d bogus type %d\n", - frame, type); - } - - /* collision or error */ - return 0; - } - } - - /* no collision */ - return 1; -} - -/*-------------------------------------------------------------------------*/ - -static void enable_periodic(struct fotg210_hcd *fotg210) -{ - if (fotg210->periodic_count++) - return; - - /* Stop waiting to turn off the periodic schedule */ - fotg210->enabled_hrtimer_events &= - ~BIT(FOTG210_HRTIMER_DISABLE_PERIODIC); - - /* Don't start the schedule until PSS is 0 */ - fotg210_poll_PSS(fotg210); - turn_on_io_watchdog(fotg210); -} - -static void disable_periodic(struct fotg210_hcd *fotg210) -{ - if (--fotg210->periodic_count) - return; - - /* Don't turn off the schedule until PSS is 1 */ - fotg210_poll_PSS(fotg210); -} - -/*-------------------------------------------------------------------------*/ - -/* periodic schedule slots have iso tds (normal or split) first, then a - * sparse tree for active interrupt transfers. - * - * this just links in a qh; caller guarantees uframe masks are set right. - * no FSTN support (yet; fotg210 0.96+) - */ -static void qh_link_periodic(struct fotg210_hcd *fotg210, struct fotg210_qh *qh) -{ - unsigned i; - unsigned period = qh->period; - - dev_dbg(&qh->dev->dev, - "link qh%d-%04x/%p start %d [%d/%d us]\n", - period, hc32_to_cpup(fotg210, &qh->hw->hw_info2) - & (QH_CMASK | QH_SMASK), - qh, qh->start, qh->usecs, qh->c_usecs); - - /* high bandwidth, or otherwise every microframe */ - if (period == 0) - period = 1; - - for (i = qh->start; i < fotg210->periodic_size; i += period) { - union fotg210_shadow *prev = &fotg210->pshadow[i]; - __hc32 *hw_p = &fotg210->periodic[i]; - union fotg210_shadow here = *prev; - __hc32 type = 0; - - /* skip the iso nodes at list head */ - while (here.ptr) { - type = Q_NEXT_TYPE(fotg210, *hw_p); - if (type == cpu_to_hc32(fotg210, Q_TYPE_QH)) - break; - prev = periodic_next_shadow(fotg210, prev, type); - hw_p = shadow_next_periodic(fotg210, &here, type); - here = *prev; - } - - /* sorting each branch by period (slow-->fast) - * enables sharing interior tree nodes - */ - while (here.ptr && qh != here.qh) { - if (qh->period > here.qh->period) - break; - prev = &here.qh->qh_next; - hw_p = &here.qh->hw->hw_next; - here = *prev; - } - /* link in this qh, unless some earlier pass did that */ - if (qh != here.qh) { - qh->qh_next = here; - if (here.qh) - qh->hw->hw_next = *hw_p; - wmb(); - prev->qh = qh; - *hw_p = QH_NEXT(fotg210, qh->qh_dma); - } - } - qh->qh_state = QH_STATE_LINKED; - qh->xacterrs = 0; - - /* update per-qh bandwidth for usbfs */ - fotg210_to_hcd(fotg210)->self.bandwidth_allocated += qh->period - ? ((qh->usecs + qh->c_usecs) / qh->period) - : (qh->usecs * 8); - - list_add(&qh->intr_node, &fotg210->intr_qh_list); - - /* maybe enable periodic schedule processing */ - ++fotg210->intr_count; - enable_periodic(fotg210); -} - -static void qh_unlink_periodic(struct fotg210_hcd *fotg210, - struct fotg210_qh *qh) -{ - unsigned i; - unsigned period; - - /* - * If qh is for a low/full-speed device, simply unlinking it - * could interfere with an ongoing split transaction. To unlink - * it safely would require setting the QH_INACTIVATE bit and - * waiting at least one frame, as described in EHCI 4.12.2.5. - * - * We won't bother with any of this. Instead, we assume that the - * only reason for unlinking an interrupt QH while the current URB - * is still active is to dequeue all the URBs (flush the whole - * endpoint queue). - * - * If rebalancing the periodic schedule is ever implemented, this - * approach will no longer be valid. - */ - - /* high bandwidth, or otherwise part of every microframe */ - period = qh->period; - if (!period) - period = 1; - - for (i = qh->start; i < fotg210->periodic_size; i += period) - periodic_unlink(fotg210, i, qh); - - /* update per-qh bandwidth for usbfs */ - fotg210_to_hcd(fotg210)->self.bandwidth_allocated -= qh->period - ? ((qh->usecs + qh->c_usecs) / qh->period) - : (qh->usecs * 8); - - dev_dbg(&qh->dev->dev, - "unlink qh%d-%04x/%p start %d [%d/%d us]\n", - qh->period, - hc32_to_cpup(fotg210, &qh->hw->hw_info2) & - (QH_CMASK | QH_SMASK), qh, qh->start, qh->usecs, qh->c_usecs); - - /* qh->qh_next still "live" to HC */ - qh->qh_state = QH_STATE_UNLINK; - qh->qh_next.ptr = NULL; - - if (fotg210->qh_scan_next == qh) - fotg210->qh_scan_next = list_entry(qh->intr_node.next, - struct fotg210_qh, intr_node); - list_del(&qh->intr_node); -} - -static void start_unlink_intr(struct fotg210_hcd *fotg210, - struct fotg210_qh *qh) -{ - /* If the QH isn't linked then there's nothing we can do - * unless we were called during a giveback, in which case - * qh_completions() has to deal with it. - */ - if (qh->qh_state != QH_STATE_LINKED) { - if (qh->qh_state == QH_STATE_COMPLETING) - qh->needs_rescan = 1; - return; - } - - qh_unlink_periodic(fotg210, qh); - - /* Make sure the unlinks are visible before starting the timer */ - wmb(); - - /* - * The EHCI spec doesn't say how long it takes the controller to - * stop accessing an unlinked interrupt QH. The timer delay is - * 9 uframes; presumably that will be long enough. - */ - qh->unlink_cycle = fotg210->intr_unlink_cycle; - - /* New entries go at the end of the intr_unlink list */ - if (fotg210->intr_unlink) - fotg210->intr_unlink_last->unlink_next = qh; - else - fotg210->intr_unlink = qh; - fotg210->intr_unlink_last = qh; - - if (fotg210->intr_unlinking) - ; /* Avoid recursive calls */ - else if (fotg210->rh_state < FOTG210_RH_RUNNING) - fotg210_handle_intr_unlinks(fotg210); - else if (fotg210->intr_unlink == qh) { - fotg210_enable_event(fotg210, FOTG210_HRTIMER_UNLINK_INTR, - true); - ++fotg210->intr_unlink_cycle; - } -} - -static void end_unlink_intr(struct fotg210_hcd *fotg210, struct fotg210_qh *qh) -{ - struct fotg210_qh_hw *hw = qh->hw; - int rc; - - qh->qh_state = QH_STATE_IDLE; - hw->hw_next = FOTG210_LIST_END(fotg210); - - qh_completions(fotg210, qh); - - /* reschedule QH iff another request is queued */ - if (!list_empty(&qh->qtd_list) && - fotg210->rh_state == FOTG210_RH_RUNNING) { - rc = qh_schedule(fotg210, qh); - - /* An error here likely indicates handshake failure - * or no space left in the schedule. Neither fault - * should happen often ... - * - * FIXME kill the now-dysfunctional queued urbs - */ - if (rc != 0) - fotg210_err(fotg210, "can't reschedule qh %p, err %d\n", - qh, rc); - } - - /* maybe turn off periodic schedule */ - --fotg210->intr_count; - disable_periodic(fotg210); -} - -/*-------------------------------------------------------------------------*/ - -static int check_period( - struct fotg210_hcd *fotg210, - unsigned frame, - unsigned uframe, - unsigned period, - unsigned usecs -) { - int claimed; - - /* complete split running into next frame? - * given FSTN support, we could sometimes check... - */ - if (uframe >= 8) - return 0; - - /* convert "usecs we need" to "max already claimed" */ - usecs = fotg210->uframe_periodic_max - usecs; - - /* we "know" 2 and 4 uframe intervals were rejected; so - * for period 0, check _every_ microframe in the schedule. - */ - if (unlikely(period == 0)) { - do { - for (uframe = 0; uframe < 7; uframe++) { - claimed = periodic_usecs(fotg210, frame, - uframe); - if (claimed > usecs) - return 0; - } - } while ((frame += 1) < fotg210->periodic_size); - - /* just check the specified uframe, at that period */ - } else { - do { - claimed = periodic_usecs(fotg210, frame, uframe); - if (claimed > usecs) - return 0; - } while ((frame += period) < fotg210->periodic_size); - } - - /* success! */ - return 1; -} - -static int check_intr_schedule( - struct fotg210_hcd *fotg210, - unsigned frame, - unsigned uframe, - const struct fotg210_qh *qh, - __hc32 *c_maskp -) -{ - int retval = -ENOSPC; - u8 mask = 0; - - if (qh->c_usecs && uframe >= 6) /* FSTN territory? */ - goto done; - - if (!check_period(fotg210, frame, uframe, qh->period, qh->usecs)) - goto done; - if (!qh->c_usecs) { - retval = 0; - *c_maskp = 0; - goto done; - } - - /* Make sure this tt's buffer is also available for CSPLITs. - * We pessimize a bit; probably the typical full speed case - * doesn't need the second CSPLIT. - * - * NOTE: both SPLIT and CSPLIT could be checked in just - * one smart pass... - */ - mask = 0x03 << (uframe + qh->gap_uf); - *c_maskp = cpu_to_hc32(fotg210, mask << 8); - - mask |= 1 << uframe; - if (tt_no_collision(fotg210, qh->period, qh->dev, frame, mask)) { - if (!check_period(fotg210, frame, uframe + qh->gap_uf + 1, - qh->period, qh->c_usecs)) - goto done; - if (!check_period(fotg210, frame, uframe + qh->gap_uf, - qh->period, qh->c_usecs)) - goto done; - retval = 0; - } -done: - return retval; -} - -/* "first fit" scheduling policy used the first time through, - * or when the previous schedule slot can't be re-used. - */ -static int qh_schedule(struct fotg210_hcd *fotg210, struct fotg210_qh *qh) -{ - int status; - unsigned uframe; - __hc32 c_mask; - unsigned frame; /* 0..(qh->period - 1), or NO_FRAME */ - struct fotg210_qh_hw *hw = qh->hw; - - qh_refresh(fotg210, qh); - hw->hw_next = FOTG210_LIST_END(fotg210); - frame = qh->start; - - /* reuse the previous schedule slots, if we can */ - if (frame < qh->period) { - uframe = ffs(hc32_to_cpup(fotg210, &hw->hw_info2) & QH_SMASK); - status = check_intr_schedule(fotg210, frame, --uframe, - qh, &c_mask); - } else { - uframe = 0; - c_mask = 0; - status = -ENOSPC; - } - - /* else scan the schedule to find a group of slots such that all - * uframes have enough periodic bandwidth available. - */ - if (status) { - /* "normal" case, uframing flexible except with splits */ - if (qh->period) { - int i; - - for (i = qh->period; status && i > 0; --i) { - frame = ++fotg210->random_frame % qh->period; - for (uframe = 0; uframe < 8; uframe++) { - status = check_intr_schedule(fotg210, - frame, uframe, qh, - &c_mask); - if (status == 0) - break; - } - } - - /* qh->period == 0 means every uframe */ - } else { - frame = 0; - status = check_intr_schedule(fotg210, 0, 0, qh, - &c_mask); - } - if (status) - goto done; - qh->start = frame; - - /* reset S-frame and (maybe) C-frame masks */ - hw->hw_info2 &= cpu_to_hc32(fotg210, ~(QH_CMASK | QH_SMASK)); - hw->hw_info2 |= qh->period - ? cpu_to_hc32(fotg210, 1 << uframe) - : cpu_to_hc32(fotg210, QH_SMASK); - hw->hw_info2 |= c_mask; - } else - fotg210_dbg(fotg210, "reused qh %p schedule\n", qh); - - /* stuff into the periodic schedule */ - qh_link_periodic(fotg210, qh); -done: - return status; -} - -static int intr_submit( - struct fotg210_hcd *fotg210, - struct urb *urb, - struct list_head *qtd_list, - gfp_t mem_flags -) { - unsigned epnum; - unsigned long flags; - struct fotg210_qh *qh; - int status; - struct list_head empty; - - /* get endpoint and transfer/schedule data */ - epnum = urb->ep->desc.bEndpointAddress; - - spin_lock_irqsave(&fotg210->lock, flags); - - if (unlikely(!HCD_HW_ACCESSIBLE(fotg210_to_hcd(fotg210)))) { - status = -ESHUTDOWN; - goto done_not_linked; - } - status = usb_hcd_link_urb_to_ep(fotg210_to_hcd(fotg210), urb); - if (unlikely(status)) - goto done_not_linked; - - /* get qh and force any scheduling errors */ - INIT_LIST_HEAD(&empty); - qh = qh_append_tds(fotg210, urb, &empty, epnum, &urb->ep->hcpriv); - if (qh == NULL) { - status = -ENOMEM; - goto done; - } - if (qh->qh_state == QH_STATE_IDLE) { - status = qh_schedule(fotg210, qh); - if (status) - goto done; - } - - /* then queue the urb's tds to the qh */ - qh = qh_append_tds(fotg210, urb, qtd_list, epnum, &urb->ep->hcpriv); - BUG_ON(qh == NULL); - - /* ... update usbfs periodic stats */ - fotg210_to_hcd(fotg210)->self.bandwidth_int_reqs++; - -done: - if (unlikely(status)) - usb_hcd_unlink_urb_from_ep(fotg210_to_hcd(fotg210), urb); -done_not_linked: - spin_unlock_irqrestore(&fotg210->lock, flags); - if (status) - qtd_list_free(fotg210, urb, qtd_list); - - return status; -} - -static void scan_intr(struct fotg210_hcd *fotg210) -{ - struct fotg210_qh *qh; - - list_for_each_entry_safe(qh, fotg210->qh_scan_next, - &fotg210->intr_qh_list, intr_node) { - rescan: - /* clean any finished work for this qh */ - if (!list_empty(&qh->qtd_list)) { - int temp; - - /* - * Unlinks could happen here; completion reporting - * drops the lock. That's why fotg210->qh_scan_next - * always holds the next qh to scan; if the next qh - * gets unlinked then fotg210->qh_scan_next is adjusted - * in qh_unlink_periodic(). - */ - temp = qh_completions(fotg210, qh); - if (unlikely(qh->needs_rescan || - (list_empty(&qh->qtd_list) && - qh->qh_state == QH_STATE_LINKED))) - start_unlink_intr(fotg210, qh); - else if (temp != 0) - goto rescan; - } - } -} - -/*-------------------------------------------------------------------------*/ - -/* fotg210_iso_stream ops work with both ITD and SITD */ - -static struct fotg210_iso_stream * -iso_stream_alloc(gfp_t mem_flags) -{ - struct fotg210_iso_stream *stream; - - stream = kzalloc(sizeof(*stream), mem_flags); - if (likely(stream != NULL)) { - INIT_LIST_HEAD(&stream->td_list); - INIT_LIST_HEAD(&stream->free_list); - stream->next_uframe = -1; - } - return stream; -} - -static void -iso_stream_init( - struct fotg210_hcd *fotg210, - struct fotg210_iso_stream *stream, - struct usb_device *dev, - int pipe, - unsigned interval -) -{ - u32 buf1; - unsigned epnum, maxp; - int is_input; - long bandwidth; - unsigned multi; - - /* - * this might be a "high bandwidth" highspeed endpoint, - * as encoded in the ep descriptor's wMaxPacket field - */ - epnum = usb_pipeendpoint(pipe); - is_input = usb_pipein(pipe) ? USB_DIR_IN : 0; - maxp = usb_maxpacket(dev, pipe, !is_input); - if (is_input) - buf1 = (1 << 11); - else - buf1 = 0; - - maxp = max_packet(maxp); - multi = hb_mult(maxp); - buf1 |= maxp; - maxp *= multi; - - stream->buf0 = cpu_to_hc32(fotg210, (epnum << 8) | dev->devnum); - stream->buf1 = cpu_to_hc32(fotg210, buf1); - stream->buf2 = cpu_to_hc32(fotg210, multi); - - /* usbfs wants to report the average usecs per frame tied up - * when transfers on this endpoint are scheduled ... - */ - if (dev->speed == USB_SPEED_FULL) { - interval <<= 3; - stream->usecs = NS_TO_US(usb_calc_bus_time(dev->speed, - is_input, 1, maxp)); - stream->usecs /= 8; - } else { - stream->highspeed = 1; - stream->usecs = HS_USECS_ISO(maxp); - } - bandwidth = stream->usecs * 8; - bandwidth /= interval; - - stream->bandwidth = bandwidth; - stream->udev = dev; - stream->bEndpointAddress = is_input | epnum; - stream->interval = interval; - stream->maxp = maxp; -} - -static struct fotg210_iso_stream * -iso_stream_find(struct fotg210_hcd *fotg210, struct urb *urb) -{ - unsigned epnum; - struct fotg210_iso_stream *stream; - struct usb_host_endpoint *ep; - unsigned long flags; - - epnum = usb_pipeendpoint(urb->pipe); - if (usb_pipein(urb->pipe)) - ep = urb->dev->ep_in[epnum]; - else - ep = urb->dev->ep_out[epnum]; - - spin_lock_irqsave(&fotg210->lock, flags); - stream = ep->hcpriv; - - if (unlikely(stream == NULL)) { - stream = iso_stream_alloc(GFP_ATOMIC); - if (likely(stream != NULL)) { - ep->hcpriv = stream; - stream->ep = ep; - iso_stream_init(fotg210, stream, urb->dev, urb->pipe, - urb->interval); - } - - /* if dev->ep[epnum] is a QH, hw is set */ - } else if (unlikely(stream->hw != NULL)) { - fotg210_dbg(fotg210, "dev %s ep%d%s, not iso??\n", - urb->dev->devpath, epnum, - usb_pipein(urb->pipe) ? "in" : "out"); - stream = NULL; - } - - spin_unlock_irqrestore(&fotg210->lock, flags); - return stream; -} - -/*-------------------------------------------------------------------------*/ - -/* fotg210_iso_sched ops can be ITD-only or SITD-only */ - -static struct fotg210_iso_sched * -iso_sched_alloc(unsigned packets, gfp_t mem_flags) -{ - struct fotg210_iso_sched *iso_sched; - int size = sizeof(*iso_sched); - - size += packets * sizeof(struct fotg210_iso_packet); - iso_sched = kzalloc(size, mem_flags); - if (likely(iso_sched != NULL)) - INIT_LIST_HEAD(&iso_sched->td_list); - - return iso_sched; -} - -static inline void -itd_sched_init( - struct fotg210_hcd *fotg210, - struct fotg210_iso_sched *iso_sched, - struct fotg210_iso_stream *stream, - struct urb *urb -) -{ - unsigned i; - dma_addr_t dma = urb->transfer_dma; - - /* how many uframes are needed for these transfers */ - iso_sched->span = urb->number_of_packets * stream->interval; - - /* figure out per-uframe itd fields that we'll need later - * when we fit new itds into the schedule. - */ - for (i = 0; i < urb->number_of_packets; i++) { - struct fotg210_iso_packet *uframe = &iso_sched->packet[i]; - unsigned length; - dma_addr_t buf; - u32 trans; - - length = urb->iso_frame_desc[i].length; - buf = dma + urb->iso_frame_desc[i].offset; - - trans = FOTG210_ISOC_ACTIVE; - trans |= buf & 0x0fff; - if (unlikely(((i + 1) == urb->number_of_packets)) - && !(urb->transfer_flags & URB_NO_INTERRUPT)) - trans |= FOTG210_ITD_IOC; - trans |= length << 16; - uframe->transaction = cpu_to_hc32(fotg210, trans); - - /* might need to cross a buffer page within a uframe */ - uframe->bufp = (buf & ~(u64)0x0fff); - buf += length; - if (unlikely((uframe->bufp != (buf & ~(u64)0x0fff)))) - uframe->cross = 1; - } -} - -static void -iso_sched_free( - struct fotg210_iso_stream *stream, - struct fotg210_iso_sched *iso_sched -) -{ - if (!iso_sched) - return; - /* caller must hold fotg210->lock!*/ - list_splice(&iso_sched->td_list, &stream->free_list); - kfree(iso_sched); -} - -static int -itd_urb_transaction( - struct fotg210_iso_stream *stream, - struct fotg210_hcd *fotg210, - struct urb *urb, - gfp_t mem_flags -) -{ - struct fotg210_itd *itd; - dma_addr_t itd_dma; - int i; - unsigned num_itds; - struct fotg210_iso_sched *sched; - unsigned long flags; - - sched = iso_sched_alloc(urb->number_of_packets, mem_flags); - if (unlikely(sched == NULL)) - return -ENOMEM; - - itd_sched_init(fotg210, sched, stream, urb); - - if (urb->interval < 8) - num_itds = 1 + (sched->span + 7) / 8; - else - num_itds = urb->number_of_packets; - - /* allocate/init ITDs */ - spin_lock_irqsave(&fotg210->lock, flags); - for (i = 0; i < num_itds; i++) { - - /* - * Use iTDs from the free list, but not iTDs that may - * still be in use by the hardware. - */ - if (likely(!list_empty(&stream->free_list))) { - itd = list_first_entry(&stream->free_list, - struct fotg210_itd, itd_list); - if (itd->frame == fotg210->now_frame) - goto alloc_itd; - list_del(&itd->itd_list); - itd_dma = itd->itd_dma; - } else { - alloc_itd: - spin_unlock_irqrestore(&fotg210->lock, flags); - itd = dma_pool_alloc(fotg210->itd_pool, mem_flags, - &itd_dma); - spin_lock_irqsave(&fotg210->lock, flags); - if (!itd) { - iso_sched_free(stream, sched); - spin_unlock_irqrestore(&fotg210->lock, flags); - return -ENOMEM; - } - } - - memset(itd, 0, sizeof(*itd)); - itd->itd_dma = itd_dma; - list_add(&itd->itd_list, &sched->td_list); - } - spin_unlock_irqrestore(&fotg210->lock, flags); - - /* temporarily store schedule info in hcpriv */ - urb->hcpriv = sched; - urb->error_count = 0; - return 0; -} - -/*-------------------------------------------------------------------------*/ - -static inline int -itd_slot_ok( - struct fotg210_hcd *fotg210, - u32 mod, - u32 uframe, - u8 usecs, - u32 period -) -{ - uframe %= period; - do { - /* can't commit more than uframe_periodic_max usec */ - if (periodic_usecs(fotg210, uframe >> 3, uframe & 0x7) - > (fotg210->uframe_periodic_max - usecs)) - return 0; - - /* we know urb->interval is 2^N uframes */ - uframe += period; - } while (uframe < mod); - return 1; -} - -/* - * This scheduler plans almost as far into the future as it has actual - * periodic schedule slots. (Affected by TUNE_FLS, which defaults to - * "as small as possible" to be cache-friendlier.) That limits the size - * transfers you can stream reliably; avoid more than 64 msec per urb. - * Also avoid queue depths of less than fotg210's worst irq latency (affected - * by the per-urb URB_NO_INTERRUPT hint, the log2_irq_thresh module parameter, - * and other factors); or more than about 230 msec total (for portability, - * given FOTG210_TUNE_FLS and the slop). Or, write a smarter scheduler! - */ - -#define SCHEDULE_SLOP 80 /* microframes */ - -static int -iso_stream_schedule( - struct fotg210_hcd *fotg210, - struct urb *urb, - struct fotg210_iso_stream *stream -) -{ - u32 now, next, start, period, span; - int status; - unsigned mod = fotg210->periodic_size << 3; - struct fotg210_iso_sched *sched = urb->hcpriv; - - period = urb->interval; - span = sched->span; - - if (span > mod - SCHEDULE_SLOP) { - fotg210_dbg(fotg210, "iso request %p too long\n", urb); - status = -EFBIG; - goto fail; - } - - now = fotg210_read_frame_index(fotg210) & (mod - 1); - - /* Typical case: reuse current schedule, stream is still active. - * Hopefully there are no gaps from the host falling behind - * (irq delays etc), but if there are we'll take the next - * slot in the schedule, implicitly assuming URB_ISO_ASAP. - */ - if (likely(!list_empty(&stream->td_list))) { - u32 excess; - - /* For high speed devices, allow scheduling within the - * isochronous scheduling threshold. For full speed devices - * and Intel PCI-based controllers, don't (work around for - * Intel ICH9 bug). - */ - if (!stream->highspeed && fotg210->fs_i_thresh) - next = now + fotg210->i_thresh; - else - next = now; - - /* Fell behind (by up to twice the slop amount)? - * We decide based on the time of the last currently-scheduled - * slot, not the time of the next available slot. - */ - excess = (stream->next_uframe - period - next) & (mod - 1); - if (excess >= mod - 2 * SCHEDULE_SLOP) - start = next + excess - mod + period * - DIV_ROUND_UP(mod - excess, period); - else - start = next + excess + period; - if (start - now >= mod) { - fotg210_dbg(fotg210, "request %p would overflow (%d+%d >= %d)\n", - urb, start - now - period, period, - mod); - status = -EFBIG; - goto fail; - } - } - - /* need to schedule; when's the next (u)frame we could start? - * this is bigger than fotg210->i_thresh allows; scheduling itself - * isn't free, the slop should handle reasonably slow cpus. it - * can also help high bandwidth if the dma and irq loads don't - * jump until after the queue is primed. - */ - else { - int done = 0; - start = SCHEDULE_SLOP + (now & ~0x07); - - /* NOTE: assumes URB_ISO_ASAP, to limit complexity/bugs */ - - /* find a uframe slot with enough bandwidth. - * Early uframes are more precious because full-speed - * iso IN transfers can't use late uframes, - * and therefore they should be allocated last. - */ - next = start; - start += period; - do { - start--; - /* check schedule: enough space? */ - if (itd_slot_ok(fotg210, mod, start, - stream->usecs, period)) - done = 1; - } while (start > next && !done); - - /* no room in the schedule */ - if (!done) { - fotg210_dbg(fotg210, "iso resched full %p (now %d max %d)\n", - urb, now, now + mod); - status = -ENOSPC; - goto fail; - } - } - - /* Tried to schedule too far into the future? */ - if (unlikely(start - now + span - period - >= mod - 2 * SCHEDULE_SLOP)) { - fotg210_dbg(fotg210, "request %p would overflow (%d+%d >= %d)\n", - urb, start - now, span - period, - mod - 2 * SCHEDULE_SLOP); - status = -EFBIG; - goto fail; - } - - stream->next_uframe = start & (mod - 1); - - /* report high speed start in uframes; full speed, in frames */ - urb->start_frame = stream->next_uframe; - if (!stream->highspeed) - urb->start_frame >>= 3; - - /* Make sure scan_isoc() sees these */ - if (fotg210->isoc_count == 0) - fotg210->next_frame = now >> 3; - return 0; - - fail: - iso_sched_free(stream, sched); - urb->hcpriv = NULL; - return status; -} - -/*-------------------------------------------------------------------------*/ - -static inline void -itd_init(struct fotg210_hcd *fotg210, struct fotg210_iso_stream *stream, - struct fotg210_itd *itd) -{ - int i; - - /* it's been recently zeroed */ - itd->hw_next = FOTG210_LIST_END(fotg210); - itd->hw_bufp[0] = stream->buf0; - itd->hw_bufp[1] = stream->buf1; - itd->hw_bufp[2] = stream->buf2; - - for (i = 0; i < 8; i++) - itd->index[i] = -1; - - /* All other fields are filled when scheduling */ -} - -static inline void -itd_patch( - struct fotg210_hcd *fotg210, - struct fotg210_itd *itd, - struct fotg210_iso_sched *iso_sched, - unsigned index, - u16 uframe -) -{ - struct fotg210_iso_packet *uf = &iso_sched->packet[index]; - unsigned pg = itd->pg; - - uframe &= 0x07; - itd->index[uframe] = index; - - itd->hw_transaction[uframe] = uf->transaction; - itd->hw_transaction[uframe] |= cpu_to_hc32(fotg210, pg << 12); - itd->hw_bufp[pg] |= cpu_to_hc32(fotg210, uf->bufp & ~(u32)0); - itd->hw_bufp_hi[pg] |= cpu_to_hc32(fotg210, (u32)(uf->bufp >> 32)); - - /* iso_frame_desc[].offset must be strictly increasing */ - if (unlikely(uf->cross)) { - u64 bufp = uf->bufp + 4096; - - itd->pg = ++pg; - itd->hw_bufp[pg] |= cpu_to_hc32(fotg210, bufp & ~(u32)0); - itd->hw_bufp_hi[pg] |= cpu_to_hc32(fotg210, (u32)(bufp >> 32)); - } -} - -static inline void -itd_link(struct fotg210_hcd *fotg210, unsigned frame, struct fotg210_itd *itd) -{ - union fotg210_shadow *prev = &fotg210->pshadow[frame]; - __hc32 *hw_p = &fotg210->periodic[frame]; - union fotg210_shadow here = *prev; - __hc32 type = 0; - - /* skip any iso nodes which might belong to previous microframes */ - while (here.ptr) { - type = Q_NEXT_TYPE(fotg210, *hw_p); - if (type == cpu_to_hc32(fotg210, Q_TYPE_QH)) - break; - prev = periodic_next_shadow(fotg210, prev, type); - hw_p = shadow_next_periodic(fotg210, &here, type); - here = *prev; - } - - itd->itd_next = here; - itd->hw_next = *hw_p; - prev->itd = itd; - itd->frame = frame; - wmb(); - *hw_p = cpu_to_hc32(fotg210, itd->itd_dma | Q_TYPE_ITD); -} - -/* fit urb's itds into the selected schedule slot; activate as needed */ -static void itd_link_urb( - struct fotg210_hcd *fotg210, - struct urb *urb, - unsigned mod, - struct fotg210_iso_stream *stream -) -{ - int packet; - unsigned next_uframe, uframe, frame; - struct fotg210_iso_sched *iso_sched = urb->hcpriv; - struct fotg210_itd *itd; - - next_uframe = stream->next_uframe & (mod - 1); - - if (unlikely(list_empty(&stream->td_list))) { - fotg210_to_hcd(fotg210)->self.bandwidth_allocated - += stream->bandwidth; - fotg210_vdbg(fotg210, - "schedule devp %s ep%d%s-iso period %d start %d.%d\n", - urb->dev->devpath, stream->bEndpointAddress & 0x0f, - (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out", - urb->interval, - next_uframe >> 3, next_uframe & 0x7); - } - - /* fill iTDs uframe by uframe */ - for (packet = 0, itd = NULL; packet < urb->number_of_packets;) { - if (itd == NULL) { - /* ASSERT: we have all necessary itds */ - - /* ASSERT: no itds for this endpoint in this uframe */ - - itd = list_entry(iso_sched->td_list.next, - struct fotg210_itd, itd_list); - list_move_tail(&itd->itd_list, &stream->td_list); - itd->stream = stream; - itd->urb = urb; - itd_init(fotg210, stream, itd); - } - - uframe = next_uframe & 0x07; - frame = next_uframe >> 3; - - itd_patch(fotg210, itd, iso_sched, packet, uframe); - - next_uframe += stream->interval; - next_uframe &= mod - 1; - packet++; - - /* link completed itds into the schedule */ - if (((next_uframe >> 3) != frame) - || packet == urb->number_of_packets) { - itd_link(fotg210, frame & (fotg210->periodic_size - 1), - itd); - itd = NULL; - } - } - stream->next_uframe = next_uframe; - - /* don't need that schedule data any more */ - iso_sched_free(stream, iso_sched); - urb->hcpriv = NULL; - - ++fotg210->isoc_count; - enable_periodic(fotg210); -} - -#define ISO_ERRS (FOTG210_ISOC_BUF_ERR | FOTG210_ISOC_BABBLE |\ - FOTG210_ISOC_XACTERR) - -/* Process and recycle a completed ITD. Return true iff its urb completed, - * and hence its completion callback probably added things to the hardware - * schedule. - * - * Note that we carefully avoid recycling this descriptor until after any - * completion callback runs, so that it won't be reused quickly. That is, - * assuming (a) no more than two urbs per frame on this endpoint, and also - * (b) only this endpoint's completions submit URBs. It seems some silicon - * corrupts things if you reuse completed descriptors very quickly... - */ -static bool itd_complete(struct fotg210_hcd *fotg210, struct fotg210_itd *itd) -{ - struct urb *urb = itd->urb; - struct usb_iso_packet_descriptor *desc; - u32 t; - unsigned uframe; - int urb_index = -1; - struct fotg210_iso_stream *stream = itd->stream; - struct usb_device *dev; - bool retval = false; - - /* for each uframe with a packet */ - for (uframe = 0; uframe < 8; uframe++) { - if (likely(itd->index[uframe] == -1)) - continue; - urb_index = itd->index[uframe]; - desc = &urb->iso_frame_desc[urb_index]; - - t = hc32_to_cpup(fotg210, &itd->hw_transaction[uframe]); - itd->hw_transaction[uframe] = 0; - - /* report transfer status */ - if (unlikely(t & ISO_ERRS)) { - urb->error_count++; - if (t & FOTG210_ISOC_BUF_ERR) - desc->status = usb_pipein(urb->pipe) - ? -ENOSR /* hc couldn't read */ - : -ECOMM; /* hc couldn't write */ - else if (t & FOTG210_ISOC_BABBLE) - desc->status = -EOVERFLOW; - else /* (t & FOTG210_ISOC_XACTERR) */ - desc->status = -EPROTO; - - /* HC need not update length with this error */ - if (!(t & FOTG210_ISOC_BABBLE)) { - desc->actual_length = - fotg210_itdlen(urb, desc, t); - urb->actual_length += desc->actual_length; - } - } else if (likely((t & FOTG210_ISOC_ACTIVE) == 0)) { - desc->status = 0; - desc->actual_length = fotg210_itdlen(urb, desc, t); - urb->actual_length += desc->actual_length; - } else { - /* URB was too late */ - desc->status = -EXDEV; - } - } - - /* handle completion now? */ - if (likely((urb_index + 1) != urb->number_of_packets)) - goto done; - - /* ASSERT: it's really the last itd for this urb - list_for_each_entry (itd, &stream->td_list, itd_list) - BUG_ON (itd->urb == urb); - */ - - /* give urb back to the driver; completion often (re)submits */ - dev = urb->dev; - fotg210_urb_done(fotg210, urb, 0); - retval = true; - urb = NULL; - - --fotg210->isoc_count; - disable_periodic(fotg210); - - if (unlikely(list_is_singular(&stream->td_list))) { - fotg210_to_hcd(fotg210)->self.bandwidth_allocated - -= stream->bandwidth; - fotg210_vdbg(fotg210, - "deschedule devp %s ep%d%s-iso\n", - dev->devpath, stream->bEndpointAddress & 0x0f, - (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out"); - } - -done: - itd->urb = NULL; - - /* Add to the end of the free list for later reuse */ - list_move_tail(&itd->itd_list, &stream->free_list); - - /* Recycle the iTDs when the pipeline is empty (ep no longer in use) */ - if (list_empty(&stream->td_list)) { - list_splice_tail_init(&stream->free_list, - &fotg210->cached_itd_list); - start_free_itds(fotg210); - } - - return retval; -} - -/*-------------------------------------------------------------------------*/ - -static int itd_submit(struct fotg210_hcd *fotg210, struct urb *urb, - gfp_t mem_flags) -{ - int status = -EINVAL; - unsigned long flags; - struct fotg210_iso_stream *stream; - - /* Get iso_stream head */ - stream = iso_stream_find(fotg210, urb); - if (unlikely(stream == NULL)) { - fotg210_dbg(fotg210, "can't get iso stream\n"); - return -ENOMEM; - } - if (unlikely(urb->interval != stream->interval && - fotg210_port_speed(fotg210, 0) == - USB_PORT_STAT_HIGH_SPEED)) { - fotg210_dbg(fotg210, "can't change iso interval %d --> %d\n", - stream->interval, urb->interval); - goto done; - } - -#ifdef FOTG210_URB_TRACE - fotg210_dbg(fotg210, - "%s %s urb %p ep%d%s len %d, %d pkts %d uframes[%p]\n", - __func__, urb->dev->devpath, urb, - usb_pipeendpoint(urb->pipe), - usb_pipein(urb->pipe) ? "in" : "out", - urb->transfer_buffer_length, - urb->number_of_packets, urb->interval, - stream); -#endif - - /* allocate ITDs w/o locking anything */ - status = itd_urb_transaction(stream, fotg210, urb, mem_flags); - if (unlikely(status < 0)) { - fotg210_dbg(fotg210, "can't init itds\n"); - goto done; - } - - /* schedule ... need to lock */ - spin_lock_irqsave(&fotg210->lock, flags); - if (unlikely(!HCD_HW_ACCESSIBLE(fotg210_to_hcd(fotg210)))) { - status = -ESHUTDOWN; - goto done_not_linked; - } - status = usb_hcd_link_urb_to_ep(fotg210_to_hcd(fotg210), urb); - if (unlikely(status)) - goto done_not_linked; - status = iso_stream_schedule(fotg210, urb, stream); - if (likely(status == 0)) - itd_link_urb(fotg210, urb, fotg210->periodic_size << 3, stream); - else - usb_hcd_unlink_urb_from_ep(fotg210_to_hcd(fotg210), urb); - done_not_linked: - spin_unlock_irqrestore(&fotg210->lock, flags); - done: - return status; -} - -/*-------------------------------------------------------------------------*/ - -static void scan_isoc(struct fotg210_hcd *fotg210) -{ - unsigned uf, now_frame, frame; - unsigned fmask = fotg210->periodic_size - 1; - bool modified, live; - - /* - * When running, scan from last scan point up to "now" - * else clean up by scanning everything that's left. - * Touches as few pages as possible: cache-friendly. - */ - if (fotg210->rh_state >= FOTG210_RH_RUNNING) { - uf = fotg210_read_frame_index(fotg210); - now_frame = (uf >> 3) & fmask; - live = true; - } else { - now_frame = (fotg210->next_frame - 1) & fmask; - live = false; - } - fotg210->now_frame = now_frame; - - frame = fotg210->next_frame; - for (;;) { - union fotg210_shadow q, *q_p; - __hc32 type, *hw_p; - -restart: - /* scan each element in frame's queue for completions */ - q_p = &fotg210->pshadow[frame]; - hw_p = &fotg210->periodic[frame]; - q.ptr = q_p->ptr; - type = Q_NEXT_TYPE(fotg210, *hw_p); - modified = false; - - while (q.ptr != NULL) { - switch (hc32_to_cpu(fotg210, type)) { - case Q_TYPE_ITD: - /* If this ITD is still active, leave it for - * later processing ... check the next entry. - * No need to check for activity unless the - * frame is current. - */ - if (frame == now_frame && live) { - rmb(); - for (uf = 0; uf < 8; uf++) { - if (q.itd->hw_transaction[uf] & - ITD_ACTIVE(fotg210)) - break; - } - if (uf < 8) { - q_p = &q.itd->itd_next; - hw_p = &q.itd->hw_next; - type = Q_NEXT_TYPE(fotg210, - q.itd->hw_next); - q = *q_p; - break; - } - } - - /* Take finished ITDs out of the schedule - * and process them: recycle, maybe report - * URB completion. HC won't cache the - * pointer for much longer, if at all. - */ - *q_p = q.itd->itd_next; - *hw_p = q.itd->hw_next; - type = Q_NEXT_TYPE(fotg210, q.itd->hw_next); - wmb(); - modified = itd_complete(fotg210, q.itd); - q = *q_p; - break; - default: - fotg210_dbg(fotg210, "corrupt type %d frame %d shadow %p\n", - type, frame, q.ptr); - /* FALL THROUGH */ - case Q_TYPE_QH: - case Q_TYPE_FSTN: - /* End of the iTDs and siTDs */ - q.ptr = NULL; - break; - } - - /* assume completion callbacks modify the queue */ - if (unlikely(modified && fotg210->isoc_count > 0)) - goto restart; - } - - /* Stop when we have reached the current frame */ - if (frame == now_frame) - break; - frame = (frame + 1) & fmask; - } - fotg210->next_frame = now_frame; -} -/*-------------------------------------------------------------------------*/ -/* - * Display / Set uframe_periodic_max - */ -static ssize_t show_uframe_periodic_max(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct fotg210_hcd *fotg210; - int n; - - fotg210 = hcd_to_fotg210(bus_to_hcd(dev_get_drvdata(dev))); - n = scnprintf(buf, PAGE_SIZE, "%d\n", fotg210->uframe_periodic_max); - return n; -} - - -static ssize_t store_uframe_periodic_max(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct fotg210_hcd *fotg210; - unsigned uframe_periodic_max; - unsigned frame, uframe; - unsigned short allocated_max; - unsigned long flags; - ssize_t ret; - - fotg210 = hcd_to_fotg210(bus_to_hcd(dev_get_drvdata(dev))); - if (kstrtouint(buf, 0, &uframe_periodic_max) < 0) - return -EINVAL; - - if (uframe_periodic_max < 100 || uframe_periodic_max >= 125) { - fotg210_info(fotg210, "rejecting invalid request for uframe_periodic_max=%u\n", - uframe_periodic_max); - return -EINVAL; - } - - ret = -EINVAL; - - /* - * lock, so that our checking does not race with possible periodic - * bandwidth allocation through submitting new urbs. - */ - spin_lock_irqsave(&fotg210->lock, flags); - - /* - * for request to decrease max periodic bandwidth, we have to check - * every microframe in the schedule to see whether the decrease is - * possible. - */ - if (uframe_periodic_max < fotg210->uframe_periodic_max) { - allocated_max = 0; - - for (frame = 0; frame < fotg210->periodic_size; ++frame) - for (uframe = 0; uframe < 7; ++uframe) - allocated_max = max(allocated_max, - periodic_usecs(fotg210, frame, uframe)); - - if (allocated_max > uframe_periodic_max) { - fotg210_info(fotg210, - "cannot decrease uframe_periodic_max becase " - "periodic bandwidth is already allocated " - "(%u > %u)\n", - allocated_max, uframe_periodic_max); - goto out_unlock; - } - } - - /* increasing is always ok */ - - fotg210_info(fotg210, "setting max periodic bandwidth to %u%% (== %u usec/uframe)\n", - 100 * uframe_periodic_max/125, uframe_periodic_max); - - if (uframe_periodic_max != 100) - fotg210_warn(fotg210, "max periodic bandwidth set is non-standard\n"); - - fotg210->uframe_periodic_max = uframe_periodic_max; - ret = count; - -out_unlock: - spin_unlock_irqrestore(&fotg210->lock, flags); - return ret; -} - -static DEVICE_ATTR(uframe_periodic_max, 0644, show_uframe_periodic_max, - store_uframe_periodic_max); - -static inline int create_sysfs_files(struct fotg210_hcd *fotg210) -{ - struct device *controller = fotg210_to_hcd(fotg210)->self.controller; - int i = 0; - - if (i) - goto out; - - i = device_create_file(controller, &dev_attr_uframe_periodic_max); -out: - return i; -} - -static inline void remove_sysfs_files(struct fotg210_hcd *fotg210) -{ - struct device *controller = fotg210_to_hcd(fotg210)->self.controller; - - device_remove_file(controller, &dev_attr_uframe_periodic_max); -} -/*-------------------------------------------------------------------------*/ - -/* On some systems, leaving remote wakeup enabled prevents system shutdown. - * The firmware seems to think that powering off is a wakeup event! - * This routine turns off remote wakeup and everything else, on all ports. - */ -static void fotg210_turn_off_all_ports(struct fotg210_hcd *fotg210) -{ - u32 __iomem *status_reg = &fotg210->regs->port_status; - - fotg210_writel(fotg210, PORT_RWC_BITS, status_reg); -} - -/* - * Halt HC, turn off all ports, and let the BIOS use the companion controllers. - * Must be called with interrupts enabled and the lock not held. - */ -static void fotg210_silence_controller(struct fotg210_hcd *fotg210) -{ - fotg210_halt(fotg210); - - spin_lock_irq(&fotg210->lock); - fotg210->rh_state = FOTG210_RH_HALTED; - fotg210_turn_off_all_ports(fotg210); - spin_unlock_irq(&fotg210->lock); -} - -/* fotg210_shutdown kick in for silicon on any bus (not just pci, etc). - * This forcibly disables dma and IRQs, helping kexec and other cases - * where the next system software may expect clean state. - */ -static void fotg210_shutdown(struct usb_hcd *hcd) -{ - struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); - - spin_lock_irq(&fotg210->lock); - fotg210->shutdown = true; - fotg210->rh_state = FOTG210_RH_STOPPING; - fotg210->enabled_hrtimer_events = 0; - spin_unlock_irq(&fotg210->lock); - - fotg210_silence_controller(fotg210); - - hrtimer_cancel(&fotg210->hrtimer); -} - -/*-------------------------------------------------------------------------*/ - -/* - * fotg210_work is called from some interrupts, timers, and so on. - * it calls driver completion functions, after dropping fotg210->lock. - */ -static void fotg210_work(struct fotg210_hcd *fotg210) -{ - /* another CPU may drop fotg210->lock during a schedule scan while - * it reports urb completions. this flag guards against bogus - * attempts at re-entrant schedule scanning. - */ - if (fotg210->scanning) { - fotg210->need_rescan = true; - return; - } - fotg210->scanning = true; - - rescan: - fotg210->need_rescan = false; - if (fotg210->async_count) - scan_async(fotg210); - if (fotg210->intr_count > 0) - scan_intr(fotg210); - if (fotg210->isoc_count > 0) - scan_isoc(fotg210); - if (fotg210->need_rescan) - goto rescan; - fotg210->scanning = false; - - /* the IO watchdog guards against hardware or driver bugs that - * misplace IRQs, and should let us run completely without IRQs. - * such lossage has been observed on both VT6202 and VT8235. - */ - turn_on_io_watchdog(fotg210); -} - -/* - * Called when the fotg210_hcd module is removed. - */ -static void fotg210_stop(struct usb_hcd *hcd) -{ - struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); - - fotg210_dbg(fotg210, "stop\n"); - - /* no more interrupts ... */ - - spin_lock_irq(&fotg210->lock); - fotg210->enabled_hrtimer_events = 0; - spin_unlock_irq(&fotg210->lock); - - fotg210_quiesce(fotg210); - fotg210_silence_controller(fotg210); - fotg210_reset(fotg210); - - hrtimer_cancel(&fotg210->hrtimer); - remove_sysfs_files(fotg210); - remove_debug_files(fotg210); - - /* root hub is shut down separately (first, when possible) */ - spin_lock_irq(&fotg210->lock); - end_free_itds(fotg210); - spin_unlock_irq(&fotg210->lock); - fotg210_mem_cleanup(fotg210); - -#ifdef FOTG210_STATS - fotg210_dbg(fotg210, "irq normal %ld err %ld iaa %ld (lost %ld)\n", - fotg210->stats.normal, fotg210->stats.error, fotg210->stats.iaa, - fotg210->stats.lost_iaa); - fotg210_dbg(fotg210, "complete %ld unlink %ld\n", - fotg210->stats.complete, fotg210->stats.unlink); -#endif - - dbg_status(fotg210, "fotg210_stop completed", - fotg210_readl(fotg210, &fotg210->regs->status)); -} - -/* one-time init, only for memory state */ -static int hcd_fotg210_init(struct usb_hcd *hcd) -{ - struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); - u32 temp; - int retval; - u32 hcc_params; - struct fotg210_qh_hw *hw; - - spin_lock_init(&fotg210->lock); - - /* - * keep io watchdog by default, those good HCDs could turn off it later - */ - fotg210->need_io_watchdog = 1; - - hrtimer_init(&fotg210->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); - fotg210->hrtimer.function = fotg210_hrtimer_func; - fotg210->next_hrtimer_event = FOTG210_HRTIMER_NO_EVENT; - - hcc_params = fotg210_readl(fotg210, &fotg210->caps->hcc_params); - - /* - * by default set standard 80% (== 100 usec/uframe) max periodic - * bandwidth as required by USB 2.0 - */ - fotg210->uframe_periodic_max = 100; - - /* - * hw default: 1K periodic list heads, one per frame. - * periodic_size can shrink by USBCMD update if hcc_params allows. - */ - fotg210->periodic_size = DEFAULT_I_TDPS; - INIT_LIST_HEAD(&fotg210->intr_qh_list); - INIT_LIST_HEAD(&fotg210->cached_itd_list); - - if (HCC_PGM_FRAMELISTLEN(hcc_params)) { - /* periodic schedule size can be smaller than default */ - switch (FOTG210_TUNE_FLS) { - case 0: - fotg210->periodic_size = 1024; - break; - case 1: - fotg210->periodic_size = 512; - break; - case 2: - fotg210->periodic_size = 256; - break; - default: - BUG(); - } - } - retval = fotg210_mem_init(fotg210, GFP_KERNEL); - if (retval < 0) - return retval; - - /* controllers may cache some of the periodic schedule ... */ - fotg210->i_thresh = 2; - - /* - * dedicate a qh for the async ring head, since we couldn't unlink - * a 'real' qh without stopping the async schedule [4.8]. use it - * as the 'reclamation list head' too. - * its dummy is used in hw_alt_next of many tds, to prevent the qh - * from automatically advancing to the next td after short reads. - */ - fotg210->async->qh_next.qh = NULL; - hw = fotg210->async->hw; - hw->hw_next = QH_NEXT(fotg210, fotg210->async->qh_dma); - hw->hw_info1 = cpu_to_hc32(fotg210, QH_HEAD); - hw->hw_token = cpu_to_hc32(fotg210, QTD_STS_HALT); - hw->hw_qtd_next = FOTG210_LIST_END(fotg210); - fotg210->async->qh_state = QH_STATE_LINKED; - hw->hw_alt_next = QTD_NEXT(fotg210, fotg210->async->dummy->qtd_dma); - - /* clear interrupt enables, set irq latency */ - if (log2_irq_thresh < 0 || log2_irq_thresh > 6) - log2_irq_thresh = 0; - temp = 1 << (16 + log2_irq_thresh); - if (HCC_CANPARK(hcc_params)) { - /* HW default park == 3, on hardware that supports it (like - * NVidia and ALI silicon), maximizes throughput on the async - * schedule by avoiding QH fetches between transfers. - * - * With fast usb storage devices and NForce2, "park" seems to - * make problems: throughput reduction (!), data errors... - */ - if (park) { - park = min_t(unsigned, park, 3); - temp |= CMD_PARK; - temp |= park << 8; - } - fotg210_dbg(fotg210, "park %d\n", park); - } - if (HCC_PGM_FRAMELISTLEN(hcc_params)) { - /* periodic schedule size can be smaller than default */ - temp &= ~(3 << 2); - temp |= (FOTG210_TUNE_FLS << 2); - } - fotg210->command = temp; - - /* Accept arbitrarily long scatter-gather lists */ - if (!(hcd->driver->flags & HCD_LOCAL_MEM)) - hcd->self.sg_tablesize = ~0; - return 0; -} - -/* start HC running; it's halted, hcd_fotg210_init() has been run (once) */ -static int fotg210_run(struct usb_hcd *hcd) -{ - struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); - u32 temp; - u32 hcc_params; - - hcd->uses_new_polling = 1; - - /* EHCI spec section 4.1 */ - - fotg210_writel(fotg210, fotg210->periodic_dma, - &fotg210->regs->frame_list); - fotg210_writel(fotg210, (u32)fotg210->async->qh_dma, - &fotg210->regs->async_next); - - /* - * hcc_params controls whether fotg210->regs->segment must (!!!) - * be used; it constrains QH/ITD/SITD and QTD locations. - * pci_pool consistent memory always uses segment zero. - * streaming mappings for I/O buffers, like pci_map_single(), - * can return segments above 4GB, if the device allows. - * - * NOTE: the dma mask is visible through dma_supported(), so - * drivers can pass this info along ... like NETIF_F_HIGHDMA, - * Scsi_Host.highmem_io, and so forth. It's readonly to all - * host side drivers though. - */ - hcc_params = fotg210_readl(fotg210, &fotg210->caps->hcc_params); - - /* - * Philips, Intel, and maybe others need CMD_RUN before the - * root hub will detect new devices (why?); NEC doesn't - */ - fotg210->command &= ~(CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET); - fotg210->command |= CMD_RUN; - fotg210_writel(fotg210, fotg210->command, &fotg210->regs->command); - dbg_cmd(fotg210, "init", fotg210->command); - - /* - * Start, enabling full USB 2.0 functionality ... usb 1.1 devices - * are explicitly handed to companion controller(s), so no TT is - * involved with the root hub. (Except where one is integrated, - * and there's no companion controller unless maybe for USB OTG.) - * - * Turning on the CF flag will transfer ownership of all ports - * from the companions to the EHCI controller. If any of the - * companions are in the middle of a port reset at the time, it - * could cause trouble. Write-locking ehci_cf_port_reset_rwsem - * guarantees that no resets are in progress. After we set CF, - * a short delay lets the hardware catch up; new resets shouldn't - * be started before the port switching actions could complete. - */ - down_write(&ehci_cf_port_reset_rwsem); - fotg210->rh_state = FOTG210_RH_RUNNING; - /* unblock posted writes */ - fotg210_readl(fotg210, &fotg210->regs->command); - msleep(5); - up_write(&ehci_cf_port_reset_rwsem); - fotg210->last_periodic_enable = ktime_get_real(); - - temp = HC_VERSION(fotg210, - fotg210_readl(fotg210, &fotg210->caps->hc_capbase)); - fotg210_info(fotg210, - "USB %x.%x started, EHCI %x.%02x\n", - ((fotg210->sbrn & 0xf0)>>4), (fotg210->sbrn & 0x0f), - temp >> 8, temp & 0xff); - - fotg210_writel(fotg210, INTR_MASK, - &fotg210->regs->intr_enable); /* Turn On Interrupts */ - - /* GRR this is run-once init(), being done every time the HC starts. - * So long as they're part of class devices, we can't do it init() - * since the class device isn't created that early. - */ - create_debug_files(fotg210); - create_sysfs_files(fotg210); - - return 0; -} - -static int fotg210_setup(struct usb_hcd *hcd) -{ - struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); - int retval; - - fotg210->regs = (void __iomem *)fotg210->caps + - HC_LENGTH(fotg210, - fotg210_readl(fotg210, &fotg210->caps->hc_capbase)); - dbg_hcs_params(fotg210, "reset"); - dbg_hcc_params(fotg210, "reset"); - - /* cache this readonly data; minimize chip reads */ - fotg210->hcs_params = fotg210_readl(fotg210, - &fotg210->caps->hcs_params); - - fotg210->sbrn = HCD_USB2; - - /* data structure init */ - retval = hcd_fotg210_init(hcd); - if (retval) - return retval; - - retval = fotg210_halt(fotg210); - if (retval) - return retval; - - fotg210_reset(fotg210); - - return 0; -} - -/*-------------------------------------------------------------------------*/ - -static irqreturn_t fotg210_irq(struct usb_hcd *hcd) -{ - struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); - u32 status, masked_status, pcd_status = 0, cmd; - int bh; - - spin_lock(&fotg210->lock); - - status = fotg210_readl(fotg210, &fotg210->regs->status); - - /* e.g. cardbus physical eject */ - if (status == ~(u32) 0) { - fotg210_dbg(fotg210, "device removed\n"); - goto dead; - } - - /* - * We don't use STS_FLR, but some controllers don't like it to - * remain on, so mask it out along with the other status bits. - */ - masked_status = status & (INTR_MASK | STS_FLR); - - /* Shared IRQ? */ - if (!masked_status || - unlikely(fotg210->rh_state == FOTG210_RH_HALTED)) { - spin_unlock(&fotg210->lock); - return IRQ_NONE; - } - - /* clear (just) interrupts */ - fotg210_writel(fotg210, masked_status, &fotg210->regs->status); - cmd = fotg210_readl(fotg210, &fotg210->regs->command); - bh = 0; - -#ifdef VERBOSE_DEBUG - /* unrequested/ignored: Frame List Rollover */ - dbg_status(fotg210, "irq", status); -#endif - - /* INT, ERR, and IAA interrupt rates can be throttled */ - - /* normal [4.15.1.2] or error [4.15.1.1] completion */ - if (likely((status & (STS_INT|STS_ERR)) != 0)) { - if (likely((status & STS_ERR) == 0)) - COUNT(fotg210->stats.normal); - else - COUNT(fotg210->stats.error); - bh = 1; - } - - /* complete the unlinking of some qh [4.15.2.3] */ - if (status & STS_IAA) { - - /* Turn off the IAA watchdog */ - fotg210->enabled_hrtimer_events &= - ~BIT(FOTG210_HRTIMER_IAA_WATCHDOG); - - /* - * Mild optimization: Allow another IAAD to reset the - * hrtimer, if one occurs before the next expiration. - * In theory we could always cancel the hrtimer, but - * tests show that about half the time it will be reset - * for some other event anyway. - */ - if (fotg210->next_hrtimer_event == FOTG210_HRTIMER_IAA_WATCHDOG) - ++fotg210->next_hrtimer_event; - - /* guard against (alleged) silicon errata */ - if (cmd & CMD_IAAD) - fotg210_dbg(fotg210, "IAA with IAAD still set?\n"); - if (fotg210->async_iaa) { - COUNT(fotg210->stats.iaa); - end_unlink_async(fotg210); - } else - fotg210_dbg(fotg210, "IAA with nothing unlinked?\n"); - } - - /* remote wakeup [4.3.1] */ - if (status & STS_PCD) { - int pstatus; - u32 __iomem *status_reg = &fotg210->regs->port_status; - - /* kick root hub later */ - pcd_status = status; - - /* resume root hub? */ - if (fotg210->rh_state == FOTG210_RH_SUSPENDED) - usb_hcd_resume_root_hub(hcd); - - pstatus = fotg210_readl(fotg210, status_reg); - - if (test_bit(0, &fotg210->suspended_ports) && - ((pstatus & PORT_RESUME) || - !(pstatus & PORT_SUSPEND)) && - (pstatus & PORT_PE) && - fotg210->reset_done[0] == 0) { - - /* start 20 msec resume signaling from this port, - * and make khubd collect PORT_STAT_C_SUSPEND to - * stop that signaling. Use 5 ms extra for safety, - * like usb_port_resume() does. - */ - fotg210->reset_done[0] = jiffies + msecs_to_jiffies(25); - set_bit(0, &fotg210->resuming_ports); - fotg210_dbg(fotg210, "port 1 remote wakeup\n"); - mod_timer(&hcd->rh_timer, fotg210->reset_done[0]); - } - } - - /* PCI errors [4.15.2.4] */ - if (unlikely((status & STS_FATAL) != 0)) { - fotg210_err(fotg210, "fatal error\n"); - dbg_cmd(fotg210, "fatal", cmd); - dbg_status(fotg210, "fatal", status); -dead: - usb_hc_died(hcd); - - /* Don't let the controller do anything more */ - fotg210->shutdown = true; - fotg210->rh_state = FOTG210_RH_STOPPING; - fotg210->command &= ~(CMD_RUN | CMD_ASE | CMD_PSE); - fotg210_writel(fotg210, fotg210->command, - &fotg210->regs->command); - fotg210_writel(fotg210, 0, &fotg210->regs->intr_enable); - fotg210_handle_controller_death(fotg210); - - /* Handle completions when the controller stops */ - bh = 0; - } - - if (bh) - fotg210_work(fotg210); - spin_unlock(&fotg210->lock); - if (pcd_status) - usb_hcd_poll_rh_status(hcd); - return IRQ_HANDLED; -} - -/*-------------------------------------------------------------------------*/ - -/* - * non-error returns are a promise to giveback() the urb later - * we drop ownership so next owner (or urb unlink) can get it - * - * urb + dev is in hcd.self.controller.urb_list - * we're queueing TDs onto software and hardware lists - * - * hcd-specific init for hcpriv hasn't been done yet - * - * NOTE: control, bulk, and interrupt share the same code to append TDs - * to a (possibly active) QH, and the same QH scanning code. - */ -static int fotg210_urb_enqueue( - struct usb_hcd *hcd, - struct urb *urb, - gfp_t mem_flags -) { - struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); - struct list_head qtd_list; - - INIT_LIST_HEAD(&qtd_list); - - switch (usb_pipetype(urb->pipe)) { - case PIPE_CONTROL: - /* qh_completions() code doesn't handle all the fault cases - * in multi-TD control transfers. Even 1KB is rare anyway. - */ - if (urb->transfer_buffer_length > (16 * 1024)) - return -EMSGSIZE; - /* FALLTHROUGH */ - /* case PIPE_BULK: */ - default: - if (!qh_urb_transaction(fotg210, urb, &qtd_list, mem_flags)) - return -ENOMEM; - return submit_async(fotg210, urb, &qtd_list, mem_flags); - - case PIPE_INTERRUPT: - if (!qh_urb_transaction(fotg210, urb, &qtd_list, mem_flags)) - return -ENOMEM; - return intr_submit(fotg210, urb, &qtd_list, mem_flags); - - case PIPE_ISOCHRONOUS: - return itd_submit(fotg210, urb, mem_flags); - } -} - -/* remove from hardware lists - * completions normally happen asynchronously - */ - -static int fotg210_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) -{ - struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); - struct fotg210_qh *qh; - unsigned long flags; - int rc; - - spin_lock_irqsave(&fotg210->lock, flags); - rc = usb_hcd_check_unlink_urb(hcd, urb, status); - if (rc) - goto done; - - switch (usb_pipetype(urb->pipe)) { - /* case PIPE_CONTROL: */ - /* case PIPE_BULK:*/ - default: - qh = (struct fotg210_qh *) urb->hcpriv; - if (!qh) - break; - switch (qh->qh_state) { - case QH_STATE_LINKED: - case QH_STATE_COMPLETING: - start_unlink_async(fotg210, qh); - break; - case QH_STATE_UNLINK: - case QH_STATE_UNLINK_WAIT: - /* already started */ - break; - case QH_STATE_IDLE: - /* QH might be waiting for a Clear-TT-Buffer */ - qh_completions(fotg210, qh); - break; - } - break; - - case PIPE_INTERRUPT: - qh = (struct fotg210_qh *) urb->hcpriv; - if (!qh) - break; - switch (qh->qh_state) { - case QH_STATE_LINKED: - case QH_STATE_COMPLETING: - start_unlink_intr(fotg210, qh); - break; - case QH_STATE_IDLE: - qh_completions(fotg210, qh); - break; - default: - fotg210_dbg(fotg210, "bogus qh %p state %d\n", - qh, qh->qh_state); - goto done; - } - break; - - case PIPE_ISOCHRONOUS: - /* itd... */ - - /* wait till next completion, do it then. */ - /* completion irqs can wait up to 1024 msec, */ - break; - } -done: - spin_unlock_irqrestore(&fotg210->lock, flags); - return rc; -} - -/*-------------------------------------------------------------------------*/ - -/* bulk qh holds the data toggle */ - -static void -fotg210_endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep) -{ - struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); - unsigned long flags; - struct fotg210_qh *qh, *tmp; - - /* ASSERT: any requests/urbs are being unlinked */ - /* ASSERT: nobody can be submitting urbs for this any more */ - -rescan: - spin_lock_irqsave(&fotg210->lock, flags); - qh = ep->hcpriv; - if (!qh) - goto done; - - /* endpoints can be iso streams. for now, we don't - * accelerate iso completions ... so spin a while. - */ - if (qh->hw == NULL) { - struct fotg210_iso_stream *stream = ep->hcpriv; - - if (!list_empty(&stream->td_list)) - goto idle_timeout; - - /* BUG_ON(!list_empty(&stream->free_list)); */ - kfree(stream); - goto done; - } - - if (fotg210->rh_state < FOTG210_RH_RUNNING) - qh->qh_state = QH_STATE_IDLE; - switch (qh->qh_state) { - case QH_STATE_LINKED: - case QH_STATE_COMPLETING: - for (tmp = fotg210->async->qh_next.qh; - tmp && tmp != qh; - tmp = tmp->qh_next.qh) - continue; - /* periodic qh self-unlinks on empty, and a COMPLETING qh - * may already be unlinked. - */ - if (tmp) - start_unlink_async(fotg210, qh); - /* FALL THROUGH */ - case QH_STATE_UNLINK: /* wait for hw to finish? */ - case QH_STATE_UNLINK_WAIT: -idle_timeout: - spin_unlock_irqrestore(&fotg210->lock, flags); - schedule_timeout_uninterruptible(1); - goto rescan; - case QH_STATE_IDLE: /* fully unlinked */ - if (qh->clearing_tt) - goto idle_timeout; - if (list_empty(&qh->qtd_list)) { - qh_destroy(fotg210, qh); - break; - } - /* else FALL THROUGH */ - default: - /* caller was supposed to have unlinked any requests; - * that's not our job. just leak this memory. - */ - fotg210_err(fotg210, "qh %p (#%02x) state %d%s\n", - qh, ep->desc.bEndpointAddress, qh->qh_state, - list_empty(&qh->qtd_list) ? "" : "(has tds)"); - break; - } - done: - ep->hcpriv = NULL; - spin_unlock_irqrestore(&fotg210->lock, flags); -} - -static void -fotg210_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep) -{ - struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); - struct fotg210_qh *qh; - int eptype = usb_endpoint_type(&ep->desc); - int epnum = usb_endpoint_num(&ep->desc); - int is_out = usb_endpoint_dir_out(&ep->desc); - unsigned long flags; - - if (eptype != USB_ENDPOINT_XFER_BULK && eptype != USB_ENDPOINT_XFER_INT) - return; - - spin_lock_irqsave(&fotg210->lock, flags); - qh = ep->hcpriv; - - /* For Bulk and Interrupt endpoints we maintain the toggle state - * in the hardware; the toggle bits in udev aren't used at all. - * When an endpoint is reset by usb_clear_halt() we must reset - * the toggle bit in the QH. - */ - if (qh) { - usb_settoggle(qh->dev, epnum, is_out, 0); - if (!list_empty(&qh->qtd_list)) { - WARN_ONCE(1, "clear_halt for a busy endpoint\n"); - } else if (qh->qh_state == QH_STATE_LINKED || - qh->qh_state == QH_STATE_COMPLETING) { - - /* The toggle value in the QH can't be updated - * while the QH is active. Unlink it now; - * re-linking will call qh_refresh(). - */ - if (eptype == USB_ENDPOINT_XFER_BULK) - start_unlink_async(fotg210, qh); - else - start_unlink_intr(fotg210, qh); - } - } - spin_unlock_irqrestore(&fotg210->lock, flags); -} - -static int fotg210_get_frame(struct usb_hcd *hcd) -{ - struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); - return (fotg210_read_frame_index(fotg210) >> 3) % - fotg210->periodic_size; -} - -/*-------------------------------------------------------------------------*/ - -/* - * The EHCI in ChipIdea HDRC cannot be a separate module or device, - * because its registers (and irq) are shared between host/gadget/otg - * functions and in order to facilitate role switching we cannot - * give the fotg210 driver exclusive access to those. - */ -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_LICENSE("GPL"); - -static const struct hc_driver fotg210_fotg210_hc_driver = { - .description = hcd_name, - .product_desc = "Faraday USB2.0 Host Controller", - .hcd_priv_size = sizeof(struct fotg210_hcd), - - /* - * generic hardware linkage - */ - .irq = fotg210_irq, - .flags = HCD_MEMORY | HCD_USB2, - - /* - * basic lifecycle operations - */ - .reset = hcd_fotg210_init, - .start = fotg210_run, - .stop = fotg210_stop, - .shutdown = fotg210_shutdown, - - /* - * managing i/o requests and associated device resources - */ - .urb_enqueue = fotg210_urb_enqueue, - .urb_dequeue = fotg210_urb_dequeue, - .endpoint_disable = fotg210_endpoint_disable, - .endpoint_reset = fotg210_endpoint_reset, - - /* - * scheduling support - */ - .get_frame_number = fotg210_get_frame, - - /* - * root hub support - */ - .hub_status_data = fotg210_hub_status_data, - .hub_control = fotg210_hub_control, - .bus_suspend = fotg210_bus_suspend, - .bus_resume = fotg210_bus_resume, - - .relinquish_port = fotg210_relinquish_port, - .port_handed_over = fotg210_port_handed_over, - - .clear_tt_buffer_complete = fotg210_clear_tt_buffer_complete, -}; - -static void fotg210_init(struct fotg210_hcd *fotg210) -{ - u32 value; - - iowrite32(GMIR_MDEV_INT | GMIR_MOTG_INT | GMIR_INT_POLARITY, - &fotg210->regs->gmir); - - value = ioread32(&fotg210->regs->otgcsr); - value &= ~OTGCSR_A_BUS_DROP; - value |= OTGCSR_A_BUS_REQ; - iowrite32(value, &fotg210->regs->otgcsr); -} - -/** - * fotg210_hcd_probe - initialize faraday FOTG210 HCDs - * - * Allocates basic resources for this USB host controller, and - * then invokes the start() method for the HCD associated with it - * through the hotplug entry's driver_data. - */ -static int fotg210_hcd_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct usb_hcd *hcd; - struct resource *res; - int irq; - int retval = -ENODEV; - struct fotg210_hcd *fotg210; - - if (usb_disabled()) - return -ENODEV; - - pdev->dev.power.power_state = PMSG_ON; - - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!res) { - dev_err(dev, - "Found HC with no IRQ. Check %s setup!\n", - dev_name(dev)); - return -ENODEV; - } - - irq = res->start; - - hcd = usb_create_hcd(&fotg210_fotg210_hc_driver, dev, - dev_name(dev)); - if (!hcd) { - dev_err(dev, "failed to create hcd with err %d\n", retval); - retval = -ENOMEM; - goto fail_create_hcd; - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(dev, - "Found HC with no register addr. Check %s setup!\n", - dev_name(dev)); - retval = -ENODEV; - goto fail_request_resource; - } - - hcd->rsrc_start = res->start; - hcd->rsrc_len = resource_size(res); - hcd->has_tt = 1; - - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, - fotg210_fotg210_hc_driver.description)) { - dev_dbg(dev, "controller already in use\n"); - retval = -EBUSY; - goto fail_request_resource; - } - - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - if (!res) { - dev_err(dev, - "Found HC with no register addr. Check %s setup!\n", - dev_name(dev)); - retval = -ENODEV; - goto fail_request_resource; - } - - hcd->regs = ioremap_nocache(res->start, resource_size(res)); - if (hcd->regs == NULL) { - dev_dbg(dev, "error mapping memory\n"); - retval = -EFAULT; - goto fail_ioremap; - } - - fotg210 = hcd_to_fotg210(hcd); - - fotg210->caps = hcd->regs; - - retval = fotg210_setup(hcd); - if (retval) - goto fail_add_hcd; - - fotg210_init(fotg210); - - retval = usb_add_hcd(hcd, irq, IRQF_SHARED); - if (retval) { - dev_err(dev, "failed to add hcd with err %d\n", retval); - goto fail_add_hcd; - } - - return retval; - -fail_add_hcd: - iounmap(hcd->regs); -fail_ioremap: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -fail_request_resource: - usb_put_hcd(hcd); -fail_create_hcd: - dev_err(dev, "init %s fail, %d\n", dev_name(dev), retval); - return retval; -} - -/** - * fotg210_hcd_remove - shutdown processing for EHCI HCDs - * @dev: USB Host Controller being removed - * - */ -static int fotg210_hcd_remove(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct usb_hcd *hcd = dev_get_drvdata(dev); - - if (!hcd) - return 0; - - usb_remove_hcd(hcd); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); - usb_put_hcd(hcd); - - return 0; -} - -static struct platform_driver fotg210_hcd_driver = { - .driver = { - .name = "fotg210-hcd", - }, - .probe = fotg210_hcd_probe, - .remove = fotg210_hcd_remove, -}; - -static int __init fotg210_hcd_init(void) -{ - int retval = 0; - - if (usb_disabled()) - return -ENODEV; - - pr_info("%s: " DRIVER_DESC "\n", hcd_name); - set_bit(USB_EHCI_LOADED, &usb_hcds_loaded); - if (test_bit(USB_UHCI_LOADED, &usb_hcds_loaded) || - test_bit(USB_OHCI_LOADED, &usb_hcds_loaded)) - pr_warn(KERN_WARNING "Warning! fotg210_hcd should always be loaded before uhci_hcd and ohci_hcd, not after\n"); - - pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd\n", - hcd_name, - sizeof(struct fotg210_qh), sizeof(struct fotg210_qtd), - sizeof(struct fotg210_itd)); - -#ifdef DEBUG - fotg210_debug_root = debugfs_create_dir("fotg210", usb_debug_root); - if (!fotg210_debug_root) { - retval = -ENOENT; - goto err_debug; - } -#endif - - retval = platform_driver_register(&fotg210_hcd_driver); - if (retval < 0) - goto clean; - return retval; - - platform_driver_unregister(&fotg210_hcd_driver); -clean: -#ifdef DEBUG - debugfs_remove(fotg210_debug_root); - fotg210_debug_root = NULL; -err_debug: -#endif - clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded); - return retval; -} -module_init(fotg210_hcd_init); - -static void __exit fotg210_hcd_cleanup(void) -{ - platform_driver_unregister(&fotg210_hcd_driver); -#ifdef DEBUG - debugfs_remove(fotg210_debug_root); -#endif - clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded); -} -module_exit(fotg210_hcd_cleanup); diff --git a/drivers/usb/host/fotg210.h b/drivers/usb/host/fotg210.h deleted file mode 100644 index 8920f9d32564..000000000000 --- a/drivers/usb/host/fotg210.h +++ /dev/null @@ -1,750 +0,0 @@ -#ifndef __LINUX_FOTG210_H -#define __LINUX_FOTG210_H - -/* definitions used for the EHCI driver */ - -/* - * __hc32 and __hc16 are "Host Controller" types, they may be equivalent to - * __leXX (normally) or __beXX (given FOTG210_BIG_ENDIAN_DESC), depending on - * the host controller implementation. - * - * To facilitate the strongest possible byte-order checking from "sparse" - * and so on, we use __leXX unless that's not practical. - */ -#define __hc32 __le32 -#define __hc16 __le16 - -/* statistics can be kept for tuning/monitoring */ -struct fotg210_stats { - /* irq usage */ - unsigned long normal; - unsigned long error; - unsigned long iaa; - unsigned long lost_iaa; - - /* termination of urbs from core */ - unsigned long complete; - unsigned long unlink; -}; - -/* fotg210_hcd->lock guards shared data against other CPUs: - * fotg210_hcd: async, unlink, periodic (and shadow), ... - * usb_host_endpoint: hcpriv - * fotg210_qh: qh_next, qtd_list - * fotg210_qtd: qtd_list - * - * Also, hold this lock when talking to HC registers or - * when updating hw_* fields in shared qh/qtd/... structures. - */ - -#define FOTG210_MAX_ROOT_PORTS 1 /* see HCS_N_PORTS */ - -/* - * fotg210_rh_state values of FOTG210_RH_RUNNING or above mean that the - * controller may be doing DMA. Lower values mean there's no DMA. - */ -enum fotg210_rh_state { - FOTG210_RH_HALTED, - FOTG210_RH_SUSPENDED, - FOTG210_RH_RUNNING, - FOTG210_RH_STOPPING -}; - -/* - * Timer events, ordered by increasing delay length. - * Always update event_delays_ns[] and event_handlers[] (defined in - * ehci-timer.c) in parallel with this list. - */ -enum fotg210_hrtimer_event { - FOTG210_HRTIMER_POLL_ASS, /* Poll for async schedule off */ - FOTG210_HRTIMER_POLL_PSS, /* Poll for periodic schedule off */ - FOTG210_HRTIMER_POLL_DEAD, /* Wait for dead controller to stop */ - FOTG210_HRTIMER_UNLINK_INTR, /* Wait for interrupt QH unlink */ - FOTG210_HRTIMER_FREE_ITDS, /* Wait for unused iTDs and siTDs */ - FOTG210_HRTIMER_ASYNC_UNLINKS, /* Unlink empty async QHs */ - FOTG210_HRTIMER_IAA_WATCHDOG, /* Handle lost IAA interrupts */ - FOTG210_HRTIMER_DISABLE_PERIODIC, /* Wait to disable periodic sched */ - FOTG210_HRTIMER_DISABLE_ASYNC, /* Wait to disable async sched */ - FOTG210_HRTIMER_IO_WATCHDOG, /* Check for missing IRQs */ - FOTG210_HRTIMER_NUM_EVENTS /* Must come last */ -}; -#define FOTG210_HRTIMER_NO_EVENT 99 - -struct fotg210_hcd { /* one per controller */ - /* timing support */ - enum fotg210_hrtimer_event next_hrtimer_event; - unsigned enabled_hrtimer_events; - ktime_t hr_timeouts[FOTG210_HRTIMER_NUM_EVENTS]; - struct hrtimer hrtimer; - - int PSS_poll_count; - int ASS_poll_count; - int died_poll_count; - - /* glue to PCI and HCD framework */ - struct fotg210_caps __iomem *caps; - struct fotg210_regs __iomem *regs; - struct fotg210_dbg_port __iomem *debug; - - __u32 hcs_params; /* cached register copy */ - spinlock_t lock; - enum fotg210_rh_state rh_state; - - /* general schedule support */ - bool scanning:1; - bool need_rescan:1; - bool intr_unlinking:1; - bool async_unlinking:1; - bool shutdown:1; - struct fotg210_qh *qh_scan_next; - - /* async schedule support */ - struct fotg210_qh *async; - struct fotg210_qh *dummy; /* For AMD quirk use */ - struct fotg210_qh *async_unlink; - struct fotg210_qh *async_unlink_last; - struct fotg210_qh *async_iaa; - unsigned async_unlink_cycle; - unsigned async_count; /* async activity count */ - - /* periodic schedule support */ -#define DEFAULT_I_TDPS 1024 /* some HCs can do less */ - unsigned periodic_size; - __hc32 *periodic; /* hw periodic table */ - dma_addr_t periodic_dma; - struct list_head intr_qh_list; - unsigned i_thresh; /* uframes HC might cache */ - - union fotg210_shadow *pshadow; /* mirror hw periodic table */ - struct fotg210_qh *intr_unlink; - struct fotg210_qh *intr_unlink_last; - unsigned intr_unlink_cycle; - unsigned now_frame; /* frame from HC hardware */ - unsigned next_frame; /* scan periodic, start here */ - unsigned intr_count; /* intr activity count */ - unsigned isoc_count; /* isoc activity count */ - unsigned periodic_count; /* periodic activity count */ - /* max periodic time per uframe */ - unsigned uframe_periodic_max; - - - /* list of itds completed while now_frame was still active */ - struct list_head cached_itd_list; - struct fotg210_itd *last_itd_to_free; - - /* per root hub port */ - unsigned long reset_done[FOTG210_MAX_ROOT_PORTS]; - - /* bit vectors (one bit per port) */ - unsigned long bus_suspended; /* which ports were - already suspended at the start of a bus suspend */ - unsigned long companion_ports; /* which ports are - dedicated to the companion controller */ - unsigned long owned_ports; /* which ports are - owned by the companion during a bus suspend */ - unsigned long port_c_suspend; /* which ports have - the change-suspend feature turned on */ - unsigned long suspended_ports; /* which ports are - suspended */ - unsigned long resuming_ports; /* which ports have - started to resume */ - - /* per-HC memory pools (could be per-bus, but ...) */ - struct dma_pool *qh_pool; /* qh per active urb */ - struct dma_pool *qtd_pool; /* one or more per qh */ - struct dma_pool *itd_pool; /* itd per iso urb */ - - unsigned random_frame; - unsigned long next_statechange; - ktime_t last_periodic_enable; - u32 command; - - /* SILICON QUIRKS */ - unsigned need_io_watchdog:1; - unsigned fs_i_thresh:1; /* Intel iso scheduling */ - - u8 sbrn; /* packed release number */ - - /* irq statistics */ -#ifdef FOTG210_STATS - struct fotg210_stats stats; -# define COUNT(x) ((x)++) -#else -# define COUNT(x) -#endif - - /* debug files */ -#ifdef DEBUG - struct dentry *debug_dir; -#endif -}; - -/* convert between an HCD pointer and the corresponding FOTG210_HCD */ -static inline struct fotg210_hcd *hcd_to_fotg210(struct usb_hcd *hcd) -{ - return (struct fotg210_hcd *)(hcd->hcd_priv); -} -static inline struct usb_hcd *fotg210_to_hcd(struct fotg210_hcd *fotg210) -{ - return container_of((void *) fotg210, struct usb_hcd, hcd_priv); -} - -/*-------------------------------------------------------------------------*/ - -/* EHCI register interface, corresponds to EHCI Revision 0.95 specification */ - -/* Section 2.2 Host Controller Capability Registers */ -struct fotg210_caps { - /* these fields are specified as 8 and 16 bit registers, - * but some hosts can't perform 8 or 16 bit PCI accesses. - * some hosts treat caplength and hciversion as parts of a 32-bit - * register, others treat them as two separate registers, this - * affects the memory map for big endian controllers. - */ - u32 hc_capbase; -#define HC_LENGTH(fotg210, p) (0x00ff&((p) >> /* bits 7:0 / offset 00h */ \ - (fotg210_big_endian_capbase(fotg210) ? 24 : 0))) -#define HC_VERSION(fotg210, p) (0xffff&((p) >> /* bits 31:16 / offset 02h */ \ - (fotg210_big_endian_capbase(fotg210) ? 0 : 16))) - u32 hcs_params; /* HCSPARAMS - offset 0x4 */ -#define HCS_N_PORTS(p) (((p)>>0)&0xf) /* bits 3:0, ports on HC */ - - u32 hcc_params; /* HCCPARAMS - offset 0x8 */ -#define HCC_CANPARK(p) ((p)&(1 << 2)) /* true: can park on async qh */ -#define HCC_PGM_FRAMELISTLEN(p) ((p)&(1 << 1)) /* true: periodic_size changes*/ - u8 portroute[8]; /* nibbles for routing - offset 0xC */ -}; - - -/* Section 2.3 Host Controller Operational Registers */ -struct fotg210_regs { - - /* USBCMD: offset 0x00 */ - u32 command; - -/* EHCI 1.1 addendum */ -/* 23:16 is r/w intr rate, in microframes; default "8" == 1/msec */ -#define CMD_PARK (1<<11) /* enable "park" on async qh */ -#define CMD_PARK_CNT(c) (((c)>>8)&3) /* how many transfers to park for */ -#define CMD_IAAD (1<<6) /* "doorbell" interrupt async advance */ -#define CMD_ASE (1<<5) /* async schedule enable */ -#define CMD_PSE (1<<4) /* periodic schedule enable */ -/* 3:2 is periodic frame list size */ -#define CMD_RESET (1<<1) /* reset HC not bus */ -#define CMD_RUN (1<<0) /* start/stop HC */ - - /* USBSTS: offset 0x04 */ - u32 status; -#define STS_ASS (1<<15) /* Async Schedule Status */ -#define STS_PSS (1<<14) /* Periodic Schedule Status */ -#define STS_RECL (1<<13) /* Reclamation */ -#define STS_HALT (1<<12) /* Not running (any reason) */ -/* some bits reserved */ - /* these STS_* flags are also intr_enable bits (USBINTR) */ -#define STS_IAA (1<<5) /* Interrupted on async advance */ -#define STS_FATAL (1<<4) /* such as some PCI access errors */ -#define STS_FLR (1<<3) /* frame list rolled over */ -#define STS_PCD (1<<2) /* port change detect */ -#define STS_ERR (1<<1) /* "error" completion (overflow, ...) */ -#define STS_INT (1<<0) /* "normal" completion (short, ...) */ - - /* USBINTR: offset 0x08 */ - u32 intr_enable; - - /* FRINDEX: offset 0x0C */ - u32 frame_index; /* current microframe number */ - /* CTRLDSSEGMENT: offset 0x10 */ - u32 segment; /* address bits 63:32 if needed */ - /* PERIODICLISTBASE: offset 0x14 */ - u32 frame_list; /* points to periodic list */ - /* ASYNCLISTADDR: offset 0x18 */ - u32 async_next; /* address of next async queue head */ - - u32 reserved1; - /* PORTSC: offset 0x20 */ - u32 port_status; -/* 31:23 reserved */ -#define PORT_USB11(x) (((x)&(3<<10)) == (1<<10)) /* USB 1.1 device */ -#define PORT_RESET (1<<8) /* reset port */ -#define PORT_SUSPEND (1<<7) /* suspend port */ -#define PORT_RESUME (1<<6) /* resume it */ -#define PORT_PEC (1<<3) /* port enable change */ -#define PORT_PE (1<<2) /* port enable */ -#define PORT_CSC (1<<1) /* connect status change */ -#define PORT_CONNECT (1<<0) /* device connected */ -#define PORT_RWC_BITS (PORT_CSC | PORT_PEC) - u32 reserved2[19]; - - /* OTGCSR: offet 0x70 */ - u32 otgcsr; -#define OTGCSR_HOST_SPD_TYP (3 << 22) -#define OTGCSR_A_BUS_DROP (1 << 5) -#define OTGCSR_A_BUS_REQ (1 << 4) - - /* OTGISR: offset 0x74 */ - u32 otgisr; -#define OTGISR_OVC (1 << 10) - - u32 reserved3[15]; - - /* GMIR: offset 0xB4 */ - u32 gmir; -#define GMIR_INT_POLARITY (1 << 3) /*Active High*/ -#define GMIR_MHC_INT (1 << 2) -#define GMIR_MOTG_INT (1 << 1) -#define GMIR_MDEV_INT (1 << 0) -}; - -/* Appendix C, Debug port ... intended for use with special "debug devices" - * that can help if there's no serial console. (nonstandard enumeration.) - */ -struct fotg210_dbg_port { - u32 control; -#define DBGP_OWNER (1<<30) -#define DBGP_ENABLED (1<<28) -#define DBGP_DONE (1<<16) -#define DBGP_INUSE (1<<10) -#define DBGP_ERRCODE(x) (((x)>>7)&0x07) -# define DBGP_ERR_BAD 1 -# define DBGP_ERR_SIGNAL 2 -#define DBGP_ERROR (1<<6) -#define DBGP_GO (1<<5) -#define DBGP_OUT (1<<4) -#define DBGP_LEN(x) (((x)>>0)&0x0f) - u32 pids; -#define DBGP_PID_GET(x) (((x)>>16)&0xff) -#define DBGP_PID_SET(data, tok) (((data)<<8)|(tok)) - u32 data03; - u32 data47; - u32 address; -#define DBGP_EPADDR(dev, ep) (((dev)<<8)|(ep)) -}; - -#ifdef CONFIG_EARLY_PRINTK_DBGP -#include -extern int __init early_dbgp_init(char *s); -extern struct console early_dbgp_console; -#endif /* CONFIG_EARLY_PRINTK_DBGP */ - -struct usb_hcd; - -static inline int xen_dbgp_reset_prep(struct usb_hcd *hcd) -{ - return 1; /* Shouldn't this be 0? */ -} - -static inline int xen_dbgp_external_startup(struct usb_hcd *hcd) -{ - return -1; -} - -#ifdef CONFIG_EARLY_PRINTK_DBGP -/* Call backs from fotg210 host driver to fotg210 debug driver */ -extern int dbgp_external_startup(struct usb_hcd *); -extern int dbgp_reset_prep(struct usb_hcd *hcd); -#else -static inline int dbgp_reset_prep(struct usb_hcd *hcd) -{ - return xen_dbgp_reset_prep(hcd); -} -static inline int dbgp_external_startup(struct usb_hcd *hcd) -{ - return xen_dbgp_external_startup(hcd); -} -#endif - -/*-------------------------------------------------------------------------*/ - -#define QTD_NEXT(fotg210, dma) cpu_to_hc32(fotg210, (u32)dma) - -/* - * EHCI Specification 0.95 Section 3.5 - * QTD: describe data transfer components (buffer, direction, ...) - * See Fig 3-6 "Queue Element Transfer Descriptor Block Diagram". - * - * These are associated only with "QH" (Queue Head) structures, - * used with control, bulk, and interrupt transfers. - */ -struct fotg210_qtd { - /* first part defined by EHCI spec */ - __hc32 hw_next; /* see EHCI 3.5.1 */ - __hc32 hw_alt_next; /* see EHCI 3.5.2 */ - __hc32 hw_token; /* see EHCI 3.5.3 */ -#define QTD_TOGGLE (1 << 31) /* data toggle */ -#define QTD_LENGTH(tok) (((tok)>>16) & 0x7fff) -#define QTD_IOC (1 << 15) /* interrupt on complete */ -#define QTD_CERR(tok) (((tok)>>10) & 0x3) -#define QTD_PID(tok) (((tok)>>8) & 0x3) -#define QTD_STS_ACTIVE (1 << 7) /* HC may execute this */ -#define QTD_STS_HALT (1 << 6) /* halted on error */ -#define QTD_STS_DBE (1 << 5) /* data buffer error (in HC) */ -#define QTD_STS_BABBLE (1 << 4) /* device was babbling (qtd halted) */ -#define QTD_STS_XACT (1 << 3) /* device gave illegal response */ -#define QTD_STS_MMF (1 << 2) /* incomplete split transaction */ -#define QTD_STS_STS (1 << 1) /* split transaction state */ -#define QTD_STS_PING (1 << 0) /* issue PING? */ - -#define ACTIVE_BIT(fotg210) cpu_to_hc32(fotg210, QTD_STS_ACTIVE) -#define HALT_BIT(fotg210) cpu_to_hc32(fotg210, QTD_STS_HALT) -#define STATUS_BIT(fotg210) cpu_to_hc32(fotg210, QTD_STS_STS) - - __hc32 hw_buf[5]; /* see EHCI 3.5.4 */ - __hc32 hw_buf_hi[5]; /* Appendix B */ - - /* the rest is HCD-private */ - dma_addr_t qtd_dma; /* qtd address */ - struct list_head qtd_list; /* sw qtd list */ - struct urb *urb; /* qtd's urb */ - size_t length; /* length of buffer */ -} __aligned(32); - -/* mask NakCnt+T in qh->hw_alt_next */ -#define QTD_MASK(fotg210) cpu_to_hc32(fotg210, ~0x1f) - -#define IS_SHORT_READ(token) (QTD_LENGTH(token) != 0 && QTD_PID(token) == 1) - -/*-------------------------------------------------------------------------*/ - -/* type tag from {qh,itd,fstn}->hw_next */ -#define Q_NEXT_TYPE(fotg210, dma) ((dma) & cpu_to_hc32(fotg210, 3 << 1)) - -/* - * Now the following defines are not converted using the - * 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. - */ -/* values for that type tag */ -#define Q_TYPE_ITD (0 << 1) -#define Q_TYPE_QH (1 << 1) -#define Q_TYPE_SITD (2 << 1) -#define Q_TYPE_FSTN (3 << 1) - -/* next async queue entry, or pointer to interrupt/periodic QH */ -#define QH_NEXT(fotg210, dma) \ - (cpu_to_hc32(fotg210, (((u32)dma)&~0x01f)|Q_TYPE_QH)) - -/* for periodic/async schedules and qtd lists, mark end of list */ -#define FOTG210_LIST_END(fotg210) \ - cpu_to_hc32(fotg210, 1) /* "null pointer" to hw */ - -/* - * Entries in periodic shadow table are pointers to one of four kinds - * of data structure. That's dictated by the hardware; a type tag is - * encoded in the low bits of the hardware's periodic schedule. Use - * Q_NEXT_TYPE to get the tag. - * - * For entries in the async schedule, the type tag always says "qh". - */ -union fotg210_shadow { - struct fotg210_qh *qh; /* Q_TYPE_QH */ - struct fotg210_itd *itd; /* Q_TYPE_ITD */ - struct fotg210_fstn *fstn; /* Q_TYPE_FSTN */ - __hc32 *hw_next; /* (all types) */ - void *ptr; -}; - -/*-------------------------------------------------------------------------*/ - -/* - * EHCI Specification 0.95 Section 3.6 - * QH: describes control/bulk/interrupt endpoints - * See Fig 3-7 "Queue Head Structure Layout". - * - * These appear in both the async and (for interrupt) periodic schedules. - */ - -/* first part defined by EHCI spec */ -struct fotg210_qh_hw { - __hc32 hw_next; /* see EHCI 3.6.1 */ - __hc32 hw_info1; /* see EHCI 3.6.2 */ -#define QH_CONTROL_EP (1 << 27) /* FS/LS control endpoint */ -#define QH_HEAD (1 << 15) /* Head of async reclamation list */ -#define QH_TOGGLE_CTL (1 << 14) /* Data toggle control */ -#define QH_HIGH_SPEED (2 << 12) /* Endpoint speed */ -#define QH_LOW_SPEED (1 << 12) -#define QH_FULL_SPEED (0 << 12) -#define QH_INACTIVATE (1 << 7) /* Inactivate on next transaction */ - __hc32 hw_info2; /* see EHCI 3.6.2 */ -#define QH_SMASK 0x000000ff -#define QH_CMASK 0x0000ff00 -#define QH_HUBADDR 0x007f0000 -#define QH_HUBPORT 0x3f800000 -#define QH_MULT 0xc0000000 - __hc32 hw_current; /* qtd list - see EHCI 3.6.4 */ - - /* qtd overlay (hardware parts of a struct fotg210_qtd) */ - __hc32 hw_qtd_next; - __hc32 hw_alt_next; - __hc32 hw_token; - __hc32 hw_buf[5]; - __hc32 hw_buf_hi[5]; -} __aligned(32); - -struct fotg210_qh { - struct fotg210_qh_hw *hw; /* Must come first */ - /* the rest is HCD-private */ - dma_addr_t qh_dma; /* address of qh */ - union fotg210_shadow qh_next; /* ptr to qh; or periodic */ - struct list_head qtd_list; /* sw qtd list */ - struct list_head intr_node; /* list of intr QHs */ - struct fotg210_qtd *dummy; - struct fotg210_qh *unlink_next; /* next on unlink list */ - - unsigned unlink_cycle; - - u8 needs_rescan; /* Dequeue during giveback */ - u8 qh_state; -#define QH_STATE_LINKED 1 /* HC sees this */ -#define QH_STATE_UNLINK 2 /* HC may still see this */ -#define QH_STATE_IDLE 3 /* HC doesn't see this */ -#define QH_STATE_UNLINK_WAIT 4 /* LINKED and on unlink 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 */ - u8 c_usecs; /* ... split completion bw */ - u16 tt_usecs; /* tt downstream bandwidth */ - unsigned short period; /* polling interval */ - unsigned short start; /* where polling starts */ -#define NO_FRAME ((unsigned short)~0) /* pick new start */ - - struct usb_device *dev; /* access to TT */ - unsigned is_out:1; /* bulk or intr OUT */ - unsigned clearing_tt:1; /* Clear-TT-Buf in progress */ -}; - -/*-------------------------------------------------------------------------*/ - -/* description of one iso transaction (up to 3 KB data if highspeed) */ -struct fotg210_iso_packet { - /* These will be copied to iTD when scheduling */ - u64 bufp; /* itd->hw_bufp{,_hi}[pg] |= */ - __hc32 transaction; /* itd->hw_transaction[i] |= */ - u8 cross; /* buf crosses pages */ - /* for full speed OUT splits */ - u32 buf1; -}; - -/* temporary schedule data for packets from iso urbs (both speeds) - * each packet is one logical usb transaction to the device (not TT), - * beginning at stream->next_uframe - */ -struct fotg210_iso_sched { - struct list_head td_list; - unsigned span; - struct fotg210_iso_packet packet[0]; -}; - -/* - * fotg210_iso_stream - groups all (s)itds for this endpoint. - * acts like a qh would, if EHCI had them for ISO. - */ -struct fotg210_iso_stream { - /* first field matches fotg210_hq, but is NULL */ - struct fotg210_qh_hw *hw; - - u8 bEndpointAddress; - u8 highspeed; - struct list_head td_list; /* queued itds */ - struct list_head free_list; /* list of unused itds */ - struct usb_device *udev; - struct usb_host_endpoint *ep; - - /* output of (re)scheduling */ - int next_uframe; - __hc32 splits; - - /* the rest is derived from the endpoint descriptor, - * trusting urb->interval == f(epdesc->bInterval) and - * including the extra info for hw_bufp[0..2] - */ - u8 usecs, c_usecs; - u16 interval; - u16 tt_usecs; - u16 maxp; - u16 raw_mask; - unsigned bandwidth; - - /* This is used to initialize iTD's hw_bufp fields */ - __hc32 buf0; - __hc32 buf1; - __hc32 buf2; - - /* this is used to initialize sITD's tt info */ - __hc32 address; -}; - -/*-------------------------------------------------------------------------*/ - -/* - * EHCI Specification 0.95 Section 3.3 - * Fig 3-4 "Isochronous Transaction Descriptor (iTD)" - * - * Schedule records for high speed iso xfers - */ -struct fotg210_itd { - /* first part defined by EHCI spec */ - __hc32 hw_next; /* see EHCI 3.3.1 */ - __hc32 hw_transaction[8]; /* see EHCI 3.3.2 */ -#define FOTG210_ISOC_ACTIVE (1<<31) /* activate transfer this slot */ -#define FOTG210_ISOC_BUF_ERR (1<<30) /* Data buffer error */ -#define FOTG210_ISOC_BABBLE (1<<29) /* babble detected */ -#define FOTG210_ISOC_XACTERR (1<<28) /* XactErr - transaction error */ -#define FOTG210_ITD_LENGTH(tok) (((tok)>>16) & 0x0fff) -#define FOTG210_ITD_IOC (1 << 15) /* interrupt on complete */ - -#define ITD_ACTIVE(fotg210) cpu_to_hc32(fotg210, FOTG210_ISOC_ACTIVE) - - __hc32 hw_bufp[7]; /* see EHCI 3.3.3 */ - __hc32 hw_bufp_hi[7]; /* Appendix B */ - - /* the rest is HCD-private */ - dma_addr_t itd_dma; /* for this itd */ - union fotg210_shadow itd_next; /* ptr to periodic q entry */ - - struct urb *urb; - struct fotg210_iso_stream *stream; /* endpoint's queue */ - struct list_head itd_list; /* list of stream's itds */ - - /* any/all hw_transactions here may be used by that urb */ - unsigned frame; /* where scheduled */ - unsigned pg; - unsigned index[8]; /* in urb->iso_frame_desc */ -} __aligned(32); - -/*-------------------------------------------------------------------------*/ - -/* - * EHCI Specification 0.96 Section 3.7 - * Periodic Frame Span Traversal Node (FSTN) - * - * Manages split interrupt transactions (using TT) that span frame boundaries - * into uframes 0/1; see 4.12.2.2. In those uframes, a "save place" FSTN - * makes the HC jump (back) to a QH to scan for fs/ls QH completions until - * it hits a "restore" FSTN; then it returns to finish other uframe 0/1 work. - */ -struct fotg210_fstn { - __hc32 hw_next; /* any periodic q entry */ - __hc32 hw_prev; /* qh or FOTG210_LIST_END */ - - /* the rest is HCD-private */ - dma_addr_t fstn_dma; - union fotg210_shadow fstn_next; /* ptr to periodic q entry */ -} __aligned(32); - -/*-------------------------------------------------------------------------*/ - -/* Prepare the PORTSC wakeup flags during controller suspend/resume */ - -#define fotg210_prepare_ports_for_controller_suspend(fotg210, do_wakeup) \ - fotg210_adjust_port_wakeup_flags(fotg210, true, do_wakeup); - -#define fotg210_prepare_ports_for_controller_resume(fotg210) \ - fotg210_adjust_port_wakeup_flags(fotg210, false, false); - -/*-------------------------------------------------------------------------*/ - -/* - * Some EHCI controllers have a Transaction Translator built into the - * root hub. This is a non-standard feature. Each controller will need - * to add code to the following inline functions, and call them as - * needed (mostly in root hub code). - */ - -static inline unsigned int -fotg210_get_speed(struct fotg210_hcd *fotg210, unsigned int portsc) -{ - return (readl(&fotg210->regs->otgcsr) - & OTGCSR_HOST_SPD_TYP) >> 22; -} - -/* Returns the speed of a device attached to a port on the root hub. */ -static inline unsigned int -fotg210_port_speed(struct fotg210_hcd *fotg210, unsigned int portsc) -{ - switch (fotg210_get_speed(fotg210, portsc)) { - case 0: - return 0; - case 1: - return USB_PORT_STAT_LOW_SPEED; - case 2: - default: - return USB_PORT_STAT_HIGH_SPEED; - } -} - -/*-------------------------------------------------------------------------*/ - -#define fotg210_has_fsl_portno_bug(e) (0) - -/* - * While most USB host controllers implement their registers in - * little-endian format, a minority (celleb companion chip) implement - * them in big endian format. - * - * This attempts to support either format at compile time without a - * runtime penalty, or both formats with the additional overhead - * of checking a flag bit. - * - */ - -#define fotg210_big_endian_mmio(e) 0 -#define fotg210_big_endian_capbase(e) 0 - -static inline unsigned int fotg210_readl(const struct fotg210_hcd *fotg210, - __u32 __iomem *regs) -{ - return readl(regs); -} - -static inline void fotg210_writel(const struct fotg210_hcd *fotg210, - const unsigned int val, __u32 __iomem *regs) -{ - writel(val, regs); -} - -/* cpu to fotg210 */ -static inline __hc32 cpu_to_hc32(const struct fotg210_hcd *fotg210, const u32 x) -{ - return cpu_to_le32(x); -} - -/* fotg210 to cpu */ -static inline u32 hc32_to_cpu(const struct fotg210_hcd *fotg210, const __hc32 x) -{ - return le32_to_cpu(x); -} - -static inline u32 hc32_to_cpup(const struct fotg210_hcd *fotg210, - const __hc32 *x) -{ - return le32_to_cpup(x); -} - -/*-------------------------------------------------------------------------*/ - -static inline unsigned fotg210_read_frame_index(struct fotg210_hcd *fotg210) -{ - return fotg210_readl(fotg210, &fotg210->regs->frame_index); -} - -#define fotg210_itdlen(urb, desc, t) ({ \ - usb_pipein((urb)->pipe) ? \ - (desc)->length - FOTG210_ITD_LENGTH(t) : \ - FOTG210_ITD_LENGTH(t); \ -}) -/*-------------------------------------------------------------------------*/ - -#ifndef DEBUG -#define STUB_DEBUG_FILES -#endif /* DEBUG */ - -/*-------------------------------------------------------------------------*/ - -#endif /* __LINUX_FOTG210_H */ From fc2db2c84e33c4f6c3f0a85540728045eb678dfb Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Jul 2013 22:01:43 -0700 Subject: [PATCH 0635/3400] staging: gdm724x: prevent module from being built in There are global symbols here that conflict with the rest of the kernel, preventing it from being built, so do not allow this module to be built in. Reported-by: Stephen Rothwell Cc: Won Kang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gdm724x/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/gdm724x/Kconfig b/drivers/staging/gdm724x/Kconfig index 10f7be10305d..8749e907d994 100644 --- a/drivers/staging/gdm724x/Kconfig +++ b/drivers/staging/gdm724x/Kconfig @@ -4,7 +4,7 @@ config LTE_GDM724X tristate "GCT GDM724x LTE support" - depends on NET && USB + depends on NET && USB && m help This driver supports GCT GDM724x LTE chip based USB modem devices. It exposes 4 network devices to be used per PDN and 2 tty devices to be From 16b551dd22cc7edacb952f7a2e175f36c3aa4bdb Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 24 Jul 2013 17:50:50 -0700 Subject: [PATCH 0636/3400] ARM: shmobile: armadillo800eva: Don't request GPIO 166 in board code 89ae7b5bbd3e65bc6ab7a577ca5ec18569589c8c (ARM: shmobile: armadillo800eva: Register pinctrl mapping for INTC) mistakenly requests GPIO 166 in board code, most probably due to a wrong merge conflict resolution. As the GPIO is passed to the st1232 driver through platform data and requested by the driver, there's no need to request it in board code. Fix it. Tested by: Cao Minh Hiep Acked-by: Laurent Pinchart Signed-off-by: Kuninori Morimoto Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/board-armadillo800eva.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c index e115f6742107..c5be60d85e4b 100644 --- a/arch/arm/mach-shmobile/board-armadillo800eva.c +++ b/arch/arm/mach-shmobile/board-armadillo800eva.c @@ -1162,9 +1162,6 @@ static void __init eva_init(void) gpio_request_one(61, GPIOF_OUT_INIT_HIGH, NULL); /* LCDDON */ gpio_request_one(202, GPIOF_OUT_INIT_LOW, NULL); /* LCD0_LED_CONT */ - /* Touchscreen */ - gpio_request_one(166, GPIOF_OUT_INIT_HIGH, NULL); /* TP_RST_B */ - /* GETHER */ gpio_request_one(18, GPIOF_OUT_INIT_HIGH, NULL); /* PHY_RST */ From 4f198289747f0391bc5a5574279b1791a8ca2d06 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Mon, 8 Jul 2013 10:01:30 -0700 Subject: [PATCH 0637/3400] lkdtm: fix stack protector trigger The -fstack-protector compiler flag will only build stack protections if a character array is seen. Additionally, the offset to the saved instruction pointer changes based on architecture, so stomp much harder (64 bytes) when corrupting the stack. Signed-off-by: Kees Cook Signed-off-by: Greg Kroah-Hartman --- drivers/misc/lkdtm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c index 08aad69c8da4..adb6bde2ecc2 100644 --- a/drivers/misc/lkdtm.c +++ b/drivers/misc/lkdtm.c @@ -295,10 +295,10 @@ static void lkdtm_do_action(enum ctype which) (void) recursive_loop(0); break; case CT_CORRUPT_STACK: { - volatile u32 data[8]; - volatile u32 *p = data; + /* Make sure the compiler creates and uses an 8 char array. */ + volatile char data[8]; - p[12] = 0x12345678; + memset((void *)data, 0, 64); break; } case CT_UNALIGNED_LOAD_STORE_WRITE: { From 65892723c386d658234ffffa35789e68e0601982 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Mon, 8 Jul 2013 10:01:31 -0700 Subject: [PATCH 0638/3400] lkdtm: add "WARNING" trigger For additional testing, add "WARNING" as a trigger that calls WARN_ON(1). Signed-off-by: Kees Cook Signed-off-by: Greg Kroah-Hartman --- drivers/misc/lkdtm.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c index adb6bde2ecc2..b1323fc881b1 100644 --- a/drivers/misc/lkdtm.c +++ b/drivers/misc/lkdtm.c @@ -68,6 +68,7 @@ enum ctype { CT_NONE, CT_PANIC, CT_BUG, + CT_WARNING, CT_EXCEPTION, CT_LOOP, CT_OVERFLOW, @@ -95,6 +96,7 @@ static char* cp_name[] = { static char* cp_type[] = { "PANIC", "BUG", + "WARNING", "EXCEPTION", "LOOP", "OVERFLOW", @@ -284,6 +286,9 @@ static void lkdtm_do_action(enum ctype which) case CT_BUG: BUG(); break; + case CT_WARNING: + WARN_ON(1); + break; case CT_EXCEPTION: *((int *) 0) = 0; break; From 274a5855c034800b8e9a6ca32bbf81298ae917d8 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Mon, 8 Jul 2013 10:01:32 -0700 Subject: [PATCH 0639/3400] lkdtm: add "SPINLOCKUP" trigger For additional lockup testing, add "SPINLOCKUP" to trigger a spinlock deadlock when triggered twice. Signed-off-by: Kees Cook Signed-off-by: Greg Kroah-Hartman --- drivers/misc/lkdtm.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c index b1323fc881b1..8bc7f0bcd945 100644 --- a/drivers/misc/lkdtm.c +++ b/drivers/misc/lkdtm.c @@ -78,6 +78,7 @@ enum ctype { CT_WRITE_AFTER_FREE, CT_SOFTLOCKUP, CT_HARDLOCKUP, + CT_SPINLOCKUP, CT_HUNG_TASK, }; @@ -106,6 +107,7 @@ static char* cp_type[] = { "WRITE_AFTER_FREE", "SOFTLOCKUP", "HARDLOCKUP", + "SPINLOCKUP", "HUNG_TASK", }; @@ -123,6 +125,7 @@ static enum cname cpoint = CN_INVALID; static enum ctype cptype = CT_NONE; static int count = DEFAULT_COUNT; static DEFINE_SPINLOCK(count_lock); +static DEFINE_SPINLOCK(lock_me_up); module_param(recur_count, int, 0644); MODULE_PARM_DESC(recur_count, " Recursion level for the stack overflow test, "\ @@ -345,6 +348,10 @@ static void lkdtm_do_action(enum ctype which) for (;;) cpu_relax(); break; + case CT_SPINLOCKUP: + /* Must be called twice to trigger. */ + spin_lock(&lock_me_up); + break; case CT_HUNG_TASK: set_current_state(TASK_UNINTERRUPTIBLE); schedule(); From cc33c537c12f36e9ce753c308999cc2e93195112 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Mon, 8 Jul 2013 10:01:33 -0700 Subject: [PATCH 0640/3400] lkdtm: add "EXEC_*" triggers Add new crash locations that attempt to execute non-executable memory regions (data segment, stack, kmalloc, vmalloc). Signed-off-by: Kees Cook Signed-off-by: Greg Kroah-Hartman --- drivers/misc/lkdtm.c | 45 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c index 8bc7f0bcd945..2fc0586ce3bb 100644 --- a/drivers/misc/lkdtm.c +++ b/drivers/misc/lkdtm.c @@ -43,6 +43,7 @@ #include #include #include +#include #ifdef CONFIG_IDE #include @@ -50,6 +51,7 @@ #define DEFAULT_COUNT 10 #define REC_NUM_DEFAULT 10 +#define EXEC_SIZE 64 enum cname { CN_INVALID, @@ -80,6 +82,10 @@ enum ctype { CT_HARDLOCKUP, CT_SPINLOCKUP, CT_HUNG_TASK, + CT_EXEC_DATA, + CT_EXEC_STACK, + CT_EXEC_KMALLOC, + CT_EXEC_VMALLOC, }; static char* cp_name[] = { @@ -109,6 +115,10 @@ static char* cp_type[] = { "HARDLOCKUP", "SPINLOCKUP", "HUNG_TASK", + "EXEC_DATA", + "EXEC_STACK", + "EXEC_KMALLOC", + "EXEC_VMALLOC", }; static struct jprobe lkdtm; @@ -127,6 +137,8 @@ static int count = DEFAULT_COUNT; static DEFINE_SPINLOCK(count_lock); static DEFINE_SPINLOCK(lock_me_up); +static u8 data_area[EXEC_SIZE]; + module_param(recur_count, int, 0644); MODULE_PARM_DESC(recur_count, " Recursion level for the stack overflow test, "\ "default is 10"); @@ -280,6 +292,19 @@ static int recursive_loop(int a) return recursive_loop(a); } +static void do_nothing(void) +{ + return; +} + +static void execute_location(void *dst) +{ + void (*func)(void) = dst; + + memcpy(dst, do_nothing, EXEC_SIZE); + func(); +} + static void lkdtm_do_action(enum ctype which) { switch (which) { @@ -356,6 +381,26 @@ static void lkdtm_do_action(enum ctype which) set_current_state(TASK_UNINTERRUPTIBLE); schedule(); break; + case CT_EXEC_DATA: + execute_location(data_area); + break; + case CT_EXEC_STACK: { + u8 stack_area[EXEC_SIZE]; + execute_location(stack_area); + break; + } + case CT_EXEC_KMALLOC: { + u32 *kmalloc_area = kmalloc(EXEC_SIZE, GFP_KERNEL); + execute_location(kmalloc_area); + kfree(kmalloc_area); + break; + } + case CT_EXEC_VMALLOC: { + u32 *vmalloc_area = vmalloc(EXEC_SIZE); + execute_location(vmalloc_area); + vfree(vmalloc_area); + break; + } case CT_NONE: default: break; From 5290801c23231c8e192943d3beb01fdbeb536395 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 24 Jul 2013 16:22:57 +0300 Subject: [PATCH 0641/3400] mei: wake also writers on reset wake writers otherwise might have processes waiting endlessly on wait_tx during reset Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/client.c | 10 +++++++--- drivers/misc/mei/client.h | 2 +- drivers/misc/mei/init.c | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 21d3f5aa8353..af1e60205140 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -892,18 +892,22 @@ void mei_cl_all_disconnect(struct mei_device *dev) /** - * mei_cl_all_read_wakeup - wake up all readings so they can be interrupted + * mei_cl_all_wakeup - wake up all readers and writers they can be interrupted * * @dev - mei device */ -void mei_cl_all_read_wakeup(struct mei_device *dev) +void mei_cl_all_wakeup(struct mei_device *dev) { struct mei_cl *cl, *next; list_for_each_entry_safe(cl, next, &dev->file_list, link) { if (waitqueue_active(&cl->rx_wait)) { - dev_dbg(&dev->pdev->dev, "Waking up client!\n"); + dev_dbg(&dev->pdev->dev, "Waking up reading client!\n"); wake_up_interruptible(&cl->rx_wait); } + if (waitqueue_active(&cl->tx_wait)) { + dev_dbg(&dev->pdev->dev, "Waking up writing client!\n"); + wake_up_interruptible(&cl->tx_wait); + } } } diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h index 26b157d8bad5..9bae4c724603 100644 --- a/drivers/misc/mei/client.h +++ b/drivers/misc/mei/client.h @@ -99,7 +99,7 @@ void mei_host_client_init(struct work_struct *work); void mei_cl_all_disconnect(struct mei_device *dev); -void mei_cl_all_read_wakeup(struct mei_device *dev); +void mei_cl_all_wakeup(struct mei_device *dev); void mei_cl_all_write_clear(struct mei_device *dev); #endif /* _MEI_CLIENT_H_ */ diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index ed1d75203af6..7929e14627ba 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c @@ -196,7 +196,7 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) mei_hbm_start_req(dev); /* wake up all readings so they can be interrupted */ - mei_cl_all_read_wakeup(dev); + mei_cl_all_wakeup(dev); /* remove all waiting requests */ mei_cl_all_write_clear(dev); From 8b613bb86a3d4a106c9a8f6de3d8a4c3628ea998 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 24 Jul 2013 16:22:59 +0300 Subject: [PATCH 0642/3400] mei: bus: do not overflow the device name buffer 1. use strncmp for comparsion strncpy was used for copying which may omit the final %NUL terminator 2. id->name is statically defined so we can use sizeof Acked-by: Samuel Ortiz Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/bus.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index 9ecd49a7be1b..a150a42ed4af 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -47,7 +47,7 @@ static int mei_cl_device_match(struct device *dev, struct device_driver *drv) id = driver->id_table; while (id->name[0]) { - if (!strcmp(dev_name(dev), id->name)) + if (!strncmp(dev_name(dev), id->name, sizeof(id->name))) return 1; id++; @@ -71,7 +71,7 @@ static int mei_cl_device_probe(struct device *dev) dev_dbg(dev, "Device probe\n"); - strncpy(id.name, dev_name(dev), MEI_CL_NAME_SIZE); + strncpy(id.name, dev_name(dev), sizeof(id.name)); return driver->probe(device, &id); } From 78049a00ceeb1453cedcd109bb5487986ab46928 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 10 Jul 2013 16:57:38 +0100 Subject: [PATCH 0643/3400] drivers/misc: don't use devm_pinctrl_get_select_default() in probe Since commit ab78029 (drivers/pinctrl: grab default handles from device core), we can rely on device core for setting the default pins. Compile tested only. Acked-by: Linus Walleij (personally at LCE13) Signed-off-by: Wolfram Sang Acked-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/misc/atmel-ssc.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c index f7b90661e321..551ddde63c57 100644 --- a/drivers/misc/atmel-ssc.c +++ b/drivers/misc/atmel-ssc.c @@ -19,7 +19,6 @@ #include #include -#include /* Serialize access to ssc_list and user count */ static DEFINE_SPINLOCK(user_lock); @@ -132,13 +131,6 @@ static int ssc_probe(struct platform_device *pdev) struct resource *regs; struct ssc_device *ssc; const struct atmel_ssc_platform_data *plat_dat; - struct pinctrl *pinctrl; - - pinctrl = devm_pinctrl_get_select_default(&pdev->dev); - if (IS_ERR(pinctrl)) { - dev_err(&pdev->dev, "Failed to request pinctrl\n"); - return PTR_ERR(pinctrl); - } ssc = devm_kzalloc(&pdev->dev, sizeof(struct ssc_device), GFP_KERNEL); if (!ssc) { From 5f90b9b484938f7466e25cd5506e86ebf9dbcd17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heiko=20St=C3=BCbner?= Date: Fri, 5 Jul 2013 14:40:53 +0200 Subject: [PATCH 0644/3400] misc: sram: fix error path in sram_probe The pool is created thru devm_gen_pool_create, so the call to gen_pool_destroy is not necessary. Instead the sram-clock must be turned off again if it exists. Signed-off-by: Heiko Stuebner Tested-by: Ulrich Prinz Acked-by: Philipp Zabel Signed-off-by: Greg Kroah-Hartman --- drivers/misc/sram.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/misc/sram.c b/drivers/misc/sram.c index d87cc91bc016..afe66571ce0b 100644 --- a/drivers/misc/sram.c +++ b/drivers/misc/sram.c @@ -68,7 +68,8 @@ static int sram_probe(struct platform_device *pdev) ret = gen_pool_add_virt(sram->pool, (unsigned long)virt_base, res->start, size, -1); if (ret < 0) { - gen_pool_destroy(sram->pool); + if (sram->clk) + clk_disable_unprepare(sram->clk); return ret; } From 783c2fb1b8ba2f057a26f881aa452d4aa8e4b3f4 Mon Sep 17 00:00:00 2001 From: Alessandro Rubini Date: Tue, 16 Jul 2013 12:58:01 +0200 Subject: [PATCH 0645/3400] FMC: fix locking in sample chardev driver The fmc-chardev module was over-locking, by calling misc register/unregister while holding its spinlock. This reported a "scheduling while atomic" error. Since the misc driver already serializes operations internally, this commit downgrades the fmc-chardev lock to just cover its own list. Reported-by: Sasha Levin Reported-by: Fengguang Wu Signed-off-by: Alessandro Rubini Signed-off-by: Greg Kroah-Hartman --- drivers/fmc/fmc-chardev.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/fmc/fmc-chardev.c b/drivers/fmc/fmc-chardev.c index cc031db2d2a3..ace6ef24d15e 100644 --- a/drivers/fmc/fmc-chardev.c +++ b/drivers/fmc/fmc-chardev.c @@ -143,18 +143,17 @@ static int fc_probe(struct fmc_device *fmc) fc->misc.fops = &fc_fops; fc->misc.name = kstrdup(dev_name(&fmc->dev), GFP_KERNEL); - spin_lock(&fc_lock); ret = misc_register(&fc->misc); if (ret < 0) - goto err_unlock; + goto out; + spin_lock(&fc_lock); list_add(&fc->list, &fc_devices); spin_unlock(&fc_lock); dev_info(&fc->fmc->dev, "Created misc device \"%s\"\n", fc->misc.name); return 0; -err_unlock: - spin_unlock(&fc_lock); +out: kfree(fc->misc.name); kfree(fc); return ret; @@ -174,10 +173,10 @@ static int fc_remove(struct fmc_device *fmc) spin_lock(&fc_lock); list_del(&fc->list); + spin_unlock(&fc_lock); misc_deregister(&fc->misc); kfree(fc->misc.name); kfree(fc); - spin_unlock(&fc_lock); return 0; } From 788489145be4300cd9a6672723d0d15c6e2cf097 Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Wed, 24 Jul 2013 20:31:37 -0400 Subject: [PATCH 0646/3400] spi: davinci: Update configs to make it selectable on Keystone Keystone2 SOCs share the SPI IP block with DaVinci based SOCs. Update the config bits so that its usable on Keystone2 based SOCs. Signed-off-by: Santosh Shilimkar Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 89cbbabaff44..3858d6605518 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -151,7 +151,7 @@ config SPI_COLDFIRE_QSPI config SPI_DAVINCI tristate "Texas Instruments DaVinci/DA8x/OMAP-L/AM1x SoC SPI controller" - depends on ARCH_DAVINCI + depends on ARCH_DAVINCI || ARCH_KEYSTONE select SPI_BITBANG select TI_EDMA help From 587cea27e4feee7365b22935b3e19e1e8906e9cb Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Jul 2013 15:05:21 -0700 Subject: [PATCH 0647/3400] regulator: core: convert class code to use dev_groups The dev_attrs field of struct class is going away soon, dev_groups should be used instead. This converts the regulator class code to use the correct field. Signed-off-by: Greg Kroah-Hartman Signed-off-by: Mark Brown --- drivers/regulator/core.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index f49c6615dc37..101f7cb14be6 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -323,13 +323,14 @@ static ssize_t regulator_uA_show(struct device *dev, } static DEVICE_ATTR(microamps, 0444, regulator_uA_show, NULL); -static ssize_t regulator_name_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t name_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct regulator_dev *rdev = dev_get_drvdata(dev); return sprintf(buf, "%s\n", rdev_get_name(rdev)); } +static DEVICE_ATTR_RO(name); static ssize_t regulator_print_opmode(char *buf, int mode) { @@ -489,15 +490,16 @@ static ssize_t regulator_total_uA_show(struct device *dev, } static DEVICE_ATTR(requested_microamps, 0444, regulator_total_uA_show, NULL); -static ssize_t regulator_num_users_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t num_users_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct regulator_dev *rdev = dev_get_drvdata(dev); return sprintf(buf, "%d\n", rdev->use_count); } +static DEVICE_ATTR_RO(num_users); -static ssize_t regulator_type_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t type_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct regulator_dev *rdev = dev_get_drvdata(dev); @@ -509,6 +511,7 @@ static ssize_t regulator_type_show(struct device *dev, } return sprintf(buf, "unknown\n"); } +static DEVICE_ATTR_RO(type); static ssize_t regulator_suspend_mem_uV_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -632,12 +635,13 @@ static DEVICE_ATTR(bypass, 0444, * These are the only attributes are present for all regulators. * Other attributes are a function of regulator functionality. */ -static struct device_attribute regulator_dev_attrs[] = { - __ATTR(name, 0444, regulator_name_show, NULL), - __ATTR(num_users, 0444, regulator_num_users_show, NULL), - __ATTR(type, 0444, regulator_type_show, NULL), - __ATTR_NULL, +static struct attribute *regulator_dev_attrs[] = { + &dev_attr_name.attr, + &dev_attr_num_users.attr, + &dev_attr_type.attr, + NULL, }; +ATTRIBUTE_GROUPS(regulator_dev); static void regulator_dev_release(struct device *dev) { @@ -648,7 +652,7 @@ static void regulator_dev_release(struct device *dev) static struct class regulator_class = { .name = "regulator", .dev_release = regulator_dev_release, - .dev_attrs = regulator_dev_attrs, + .dev_groups = regulator_dev_groups, }; /* Calculate the new optimum regulator operating mode based on the new total From 3784b6d64dc52ed3fbebad61a85ab9b7a687a167 Mon Sep 17 00:00:00 2001 From: Robin Gong Date: Thu, 25 Jul 2013 11:33:18 +0800 Subject: [PATCH 0648/3400] regulator: pfuze100: add pfuze100 regulator driver Add pfuze100 regulator driver. Signed-off-by: Robin Gong Tested-by: Steffen Trumtrar Signed-off-by: Mark Brown --- .../bindings/regulator/pfuze100.txt | 113 +++++ drivers/regulator/Kconfig | 7 + drivers/regulator/Makefile | 1 + drivers/regulator/pfuze100-regulator.c | 454 ++++++++++++++++++ include/linux/regulator/pfuze100.h | 44 ++ 5 files changed, 619 insertions(+) create mode 100644 Documentation/devicetree/bindings/regulator/pfuze100.txt create mode 100644 drivers/regulator/pfuze100-regulator.c create mode 100644 include/linux/regulator/pfuze100.h diff --git a/Documentation/devicetree/bindings/regulator/pfuze100.txt b/Documentation/devicetree/bindings/regulator/pfuze100.txt new file mode 100644 index 000000000000..22e1a48f7e83 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/pfuze100.txt @@ -0,0 +1,113 @@ +PFUZE100 family of regulators + +Required properties: +- compatible: "fsl,pfuze100" +- reg: I2C slave address +- regulators: This is the list of child nodes that specify the regulator + initialization data for defined regulators. Please refer to below doc + Documentation/devicetree/bindings/regulator/regulator.txt. + + The valid names for regulators are: + sw1ab,sw1c,sw2,sw3a,sw3b,sw4,swbst,vsnvs,vrefddr,vgen1~vgen6 + +Each regulator is defined using the standard binding for regulators. + +Example: + + pmic: pfuze100@08 { + compatible = "fsl,pfuze100"; + reg = <0x08>; + + regulators { + sw1a_reg: sw1ab { + regulator-min-microvolt = <300000>; + regulator-max-microvolt = <1875000>; + regulator-boot-on; + regulator-always-on; + regulator-ramp-delay = <6250>; + }; + + sw1c_reg: sw1c { + regulator-min-microvolt = <300000>; + regulator-max-microvolt = <1875000>; + regulator-boot-on; + regulator-always-on; + }; + + sw2_reg: sw2 { + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + regulator-always-on; + }; + + sw3a_reg: sw3a { + regulator-min-microvolt = <400000>; + regulator-max-microvolt = <1975000>; + regulator-boot-on; + regulator-always-on; + }; + + sw3b_reg: sw3b { + regulator-min-microvolt = <400000>; + regulator-max-microvolt = <1975000>; + regulator-boot-on; + regulator-always-on; + }; + + sw4_reg: sw4 { + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3300000>; + }; + + swbst_reg: swbst { + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5150000>; + }; + + snvs_reg: vsnvs { + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <3000000>; + regulator-boot-on; + regulator-always-on; + }; + + vref_reg: vrefddr { + regulator-boot-on; + regulator-always-on; + }; + + vgen1_reg: vgen1 { + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1550000>; + }; + + vgen2_reg: vgen2 { + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1550000>; + }; + + vgen3_reg: vgen3 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + }; + + vgen4_reg: vgen4 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vgen5_reg: vgen5 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vgen6_reg: vgen6 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + }; + }; diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 759b601b54ef..f9d02aabe306 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -355,6 +355,13 @@ config REGULATOR_PCF50633 Say Y here to support the voltage regulators and convertors on PCF50633 +config REGULATOR_PFUZE100 + tristate "Support regulators on Freescale PFUZE100 PMIC" + depends on I2C + help + Say y here to support the regulators found on the Freescale PFUZE100 + PMIC. + config REGULATOR_RC5T583 tristate "RICOH RC5T583 Power regulators" depends on MFD_RC5T583 diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index d240772d90ee..57838e2b0b8a 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -46,6 +46,7 @@ obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o +obj-$(CONFIG_REGULATOR_PFUZE100) += pfuze100-regulator.o obj-$(CONFIG_REGULATOR_TPS51632) += tps51632-regulator.o obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c new file mode 100644 index 000000000000..fcc7cd0d25cc --- /dev/null +++ b/drivers/regulator/pfuze100-regulator.c @@ -0,0 +1,454 @@ +/* + * Copyright (C) 2011-2013 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 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 + +#define PFUZE_NUMREGS 128 +#define PFUZE100_VOL_OFFSET 0 +#define PFUZE100_STANDBY_OFFSET 1 +#define PFUZE100_MODE_OFFSET 3 +#define PFUZE100_CONF_OFFSET 4 + +#define PFUZE100_DEVICEID 0x0 +#define PFUZE100_REVID 0x3 +#define PFUZE100_FABID 0x3 + +#define PFUZE100_SW1ABVOL 0x20 +#define PFUZE100_SW1CVOL 0x2e +#define PFUZE100_SW2VOL 0x35 +#define PFUZE100_SW3AVOL 0x3c +#define PFUZE100_SW3BVOL 0x43 +#define PFUZE100_SW4VOL 0x4a +#define PFUZE100_SWBSTCON1 0x66 +#define PFUZE100_VREFDDRCON 0x6a +#define PFUZE100_VSNVSVOL 0x6b +#define PFUZE100_VGEN1VOL 0x6c +#define PFUZE100_VGEN2VOL 0x6d +#define PFUZE100_VGEN3VOL 0x6e +#define PFUZE100_VGEN4VOL 0x6f +#define PFUZE100_VGEN5VOL 0x70 +#define PFUZE100_VGEN6VOL 0x71 + +struct pfuze_regulator { + struct regulator_desc desc; + unsigned char stby_reg; + unsigned char stby_mask; +}; + +struct pfuze_chip { + struct regmap *regmap; + struct device *dev; + struct pfuze_regulator regulator_descs[PFUZE100_MAX_REGULATOR]; + struct regulator_dev *regulators[PFUZE100_MAX_REGULATOR]; +}; + +static const int pfuze100_swbst[] = { + 5000000, 5050000, 5100000, 5150000, +}; + +static const int pfuze100_vsnvs[] = { + 1000000, 1100000, 1200000, 1300000, 1500000, 1800000, 3000000, +}; + +static const struct i2c_device_id pfuze_device_id[] = { + {.name = "pfuze100"}, + {}, +}; +MODULE_DEVICE_TABLE(i2c, pfuze_device_id); + +static const struct of_device_id pfuze_dt_ids[] = { + { .compatible = "fsl,pfuze100" }, + {}, +}; +MODULE_DEVICE_TABLE(of, pfuze_dt_ids); + +static int pfuze100_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) +{ + struct pfuze_chip *pfuze100 = rdev_get_drvdata(rdev); + int id = rdev->desc->id; + unsigned int val, ramp_bits, reg; + int ret; + + if (id < PFUZE100_SWBST) { + if (id == PFUZE100_SW1AB) + reg = PFUZE100_SW1ABVOL; + else + reg = PFUZE100_SW1CVOL + (id - PFUZE100_SW1C) * 7; + regmap_read(pfuze100->regmap, reg, &val); + + if (id <= PFUZE100_SW1C) + ramp_delay = 25000 / (2 * ramp_delay); + else if (val & 0x40) + ramp_delay = 50000 / (4 * ramp_delay); + else + ramp_delay = 25000 / (2 * ramp_delay); + + ramp_bits = (ramp_delay >> 1) - (ramp_delay >> 3); + ret = regmap_update_bits(pfuze100->regmap, reg + 4 , 0xc0, + ramp_bits << 6); + if (ret < 0) + dev_err(pfuze100->dev, "ramp failed, err %d\n", ret); + } else + ret = -EACCES; + + return ret; +} + +static struct regulator_ops pfuze100_ldo_regulator_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .list_voltage = regulator_list_voltage_linear, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, +}; + +static struct regulator_ops pfuze100_fixed_regulator_ops = { + .list_voltage = regulator_list_voltage_linear, +}; + +static struct regulator_ops pfuze100_sw_regulator_ops = { + .list_voltage = regulator_list_voltage_linear, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .set_ramp_delay = pfuze100_set_ramp_delay, +}; + +static struct regulator_ops pfuze100_swb_regulator_ops = { + .list_voltage = regulator_list_voltage_table, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + +}; + +#define PFUZE100_FIXED_REG(_name, base, voltage) \ + [PFUZE100_ ## _name] = { \ + .desc = { \ + .name = #_name, \ + .n_voltages = 1, \ + .ops = &pfuze100_fixed_regulator_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = PFUZE100_ ## _name, \ + .owner = THIS_MODULE, \ + .min_uV = (voltage), \ + .enable_reg = (base), \ + .enable_mask = 0x10, \ + }, \ + } + +#define PFUZE100_SW_REG(_name, base, min, max, step) \ + [PFUZE100_ ## _name] = { \ + .desc = { \ + .name = #_name,\ + .n_voltages = ((max) - (min)) / (step) + 1, \ + .ops = &pfuze100_sw_regulator_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = PFUZE100_ ## _name, \ + .owner = THIS_MODULE, \ + .min_uV = (min), \ + .uV_step = (step), \ + .vsel_reg = (base) + PFUZE100_VOL_OFFSET, \ + .vsel_mask = 0x3f, \ + }, \ + .stby_reg = (base) + PFUZE100_STANDBY_OFFSET, \ + .stby_mask = 0x3f, \ + } + +#define PFUZE100_SWB_REG(_name, base, mask, voltages) \ + [PFUZE100_ ## _name] = { \ + .desc = { \ + .name = #_name, \ + .n_voltages = ARRAY_SIZE(voltages), \ + .ops = &pfuze100_swb_regulator_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = PFUZE100_ ## _name, \ + .owner = THIS_MODULE, \ + .volt_table = voltages, \ + .vsel_reg = (base), \ + .vsel_mask = (mask), \ + }, \ + } + +#define PFUZE100_VGEN_REG(_name, base, min, max, step) \ + [PFUZE100_ ## _name] = { \ + .desc = { \ + .name = #_name, \ + .n_voltages = ((max) - (min)) / (step) + 1, \ + .ops = &pfuze100_ldo_regulator_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = PFUZE100_ ## _name, \ + .owner = THIS_MODULE, \ + .min_uV = (min), \ + .uV_step = (step), \ + .vsel_reg = (base), \ + .vsel_mask = 0xf, \ + .enable_reg = (base), \ + .enable_mask = 0x10, \ + }, \ + .stby_reg = (base), \ + .stby_mask = 0x20, \ + } + +static struct pfuze_regulator pfuze100_regulators[] = { + PFUZE100_SW_REG(SW1AB, PFUZE100_SW1ABVOL, 300000, 1875000, 25000), + PFUZE100_SW_REG(SW1C, PFUZE100_SW1CVOL, 300000, 1875000, 25000), + PFUZE100_SW_REG(SW2, PFUZE100_SW2VOL, 400000, 1975000, 25000), + PFUZE100_SW_REG(SW3A, PFUZE100_SW3AVOL, 400000, 1975000, 25000), + PFUZE100_SW_REG(SW3B, PFUZE100_SW3BVOL, 400000, 1975000, 25000), + PFUZE100_SW_REG(SW4, PFUZE100_SW4VOL, 400000, 1975000, 25000), + PFUZE100_SWB_REG(SWBST, PFUZE100_SWBSTCON1, 0x3 , pfuze100_swbst), + PFUZE100_SWB_REG(VSNVS, PFUZE100_VSNVSVOL, 0x7, pfuze100_vsnvs), + PFUZE100_FIXED_REG(VREFDDR, PFUZE100_VREFDDRCON, 750000), + PFUZE100_VGEN_REG(VGEN1, PFUZE100_VGEN1VOL, 800000, 1550000, 50000), + PFUZE100_VGEN_REG(VGEN2, PFUZE100_VGEN2VOL, 800000, 1550000, 50000), + PFUZE100_VGEN_REG(VGEN3, PFUZE100_VGEN3VOL, 1800000, 3300000, 100000), + PFUZE100_VGEN_REG(VGEN4, PFUZE100_VGEN4VOL, 1800000, 3300000, 100000), + PFUZE100_VGEN_REG(VGEN5, PFUZE100_VGEN5VOL, 1800000, 3300000, 100000), + PFUZE100_VGEN_REG(VGEN6, PFUZE100_VGEN6VOL, 1800000, 3300000, 100000), +}; + +#ifdef CONFIG_OF +static struct of_regulator_match pfuze100_matches[] = { + { .name = "sw1ab", }, + { .name = "sw1c", }, + { .name = "sw2", }, + { .name = "sw3a", }, + { .name = "sw3b", }, + { .name = "sw4", }, + { .name = "swbst", }, + { .name = "vsnvs", }, + { .name = "vrefddr", }, + { .name = "vgen1", }, + { .name = "vgen2", }, + { .name = "vgen3", }, + { .name = "vgen4", }, + { .name = "vgen5", }, + { .name = "vgen6", }, +}; + +static int pfuze_parse_regulators_dt(struct pfuze_chip *chip) +{ + struct device *dev = chip->dev; + struct device_node *np, *parent; + int ret; + + np = of_node_get(dev->parent->of_node); + if (!np) + return 0; + + parent = of_find_node_by_name(np, "regulators"); + if (!parent) { + dev_err(dev, "regulators node not found\n"); + return -EINVAL; + } + + ret = of_regulator_match(dev, parent, pfuze100_matches, + ARRAY_SIZE(pfuze100_matches)); + + of_node_put(parent); + if (ret < 0) { + dev_err(dev, "Error parsing regulator init data: %d\n", + ret); + return ret; + } + + return 0; +} + +static inline struct regulator_init_data *match_init_data(int index) +{ + return pfuze100_matches[index].init_data; +} + +static inline struct device_node *match_of_node(int index) +{ + return pfuze100_matches[index].of_node; +} +#else +static int pfuze_parse_regulators_dt(struct pfuze_chip *chip) +{ + return NULL; +} + +static inline struct regulator_init_data *match_init_data(int index) +{ + return NULL; +} + +static inline struct device_node *match_of_node(int index) +{ + return NULL; +} +#endif + +static int pfuze_identify(struct pfuze_chip *pfuze_chip) +{ + unsigned int value; + int ret; + + ret = regmap_read(pfuze_chip->regmap, PFUZE100_DEVICEID, &value); + if (ret) + return ret; + + if (value & 0x0f) { + dev_warn(pfuze_chip->dev, "Illegal ID: %x\n", value); + return -ENODEV; + } + + ret = regmap_read(pfuze_chip->regmap, PFUZE100_REVID, &value); + if (ret) + return ret; + dev_info(pfuze_chip->dev, + "Full lay: %x, Metal lay: %x\n", + (value & 0xf0) >> 4, value & 0x0f); + + ret = regmap_read(pfuze_chip->regmap, PFUZE100_FABID, &value); + if (ret) + return ret; + dev_info(pfuze_chip->dev, "FAB: %x, FIN: %x\n", + (value & 0xc) >> 2, value & 0x3); + + return 0; +} + +static const struct regmap_config pfuze_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = PFUZE_NUMREGS, + .cache_type = REGCACHE_RBTREE, +}; + +static int pfuze100_regulator_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct pfuze_chip *pfuze_chip; + struct pfuze_regulator_platform_data *pdata = + dev_get_platdata(&client->dev); + struct regulator_config config = { }; + int i, ret; + + pfuze_chip = devm_kzalloc(&client->dev, sizeof(*pfuze_chip), + GFP_KERNEL); + if (!pfuze_chip) + return -ENOMEM; + + dev_set_drvdata(&client->dev, pfuze_chip); + + memcpy(pfuze_chip->regulator_descs, pfuze100_regulators, + sizeof(pfuze_chip->regulator_descs)); + + pfuze_chip->dev = &client->dev; + + pfuze_chip->regmap = devm_regmap_init_i2c(client, &pfuze_regmap_config); + if (IS_ERR(pfuze_chip->regmap)) { + ret = PTR_ERR(pfuze_chip->regmap); + dev_err(&client->dev, + "regmap allocation failed with err %d\n", ret); + return ret; + } + + ret = pfuze_identify(pfuze_chip); + if (ret) { + dev_err(&client->dev, "unrecognized pfuze chip ID!\n"); + return ret; + } + + ret = pfuze_parse_regulators_dt(pfuze_chip); + if (ret) + return ret; + + for (i = 0; i < PFUZE100_MAX_REGULATOR; i++) { + struct regulator_init_data *init_data; + int val; + + if (pdata) + init_data = pdata->init_data[i]; + else + init_data = match_init_data(i); + + /* SW2~SW4 high bit check and modify the voltage value table */ + if (i > PFUZE100_SW1C && i < PFUZE100_SWBST) { + regmap_read(pfuze_chip->regmap, PFUZE100_SW2VOL + + (i - PFUZE100_SW2) * 7, &val); + if (val & 0x40) { + pfuze_chip->regulator_descs[i].desc.min_uV + = 800000; + pfuze_chip->regulator_descs[i].desc.uV_step + = 50000; + } + } + + config.dev = &client->dev; + config.init_data = init_data; + config.driver_data = pfuze_chip; + config.of_node = match_of_node(i); + + pfuze_chip->regulators[i] = regulator_register(&pfuze_chip + ->regulator_descs[i].desc, &config); + if (IS_ERR(pfuze_chip->regulators[i])) { + dev_err(&client->dev, "register regulator%s failed\n", + pfuze100_regulators[i].desc.name); + ret = PTR_ERR(pfuze_chip->regulators[i]); + while (--i >= 0) + regulator_unregister(pfuze_chip->regulators[i]); + return ret; + } + } + + return 0; +} + +static int pfuze100_regulator_remove(struct i2c_client *client) +{ + int i; + struct pfuze_chip *pfuze_chip = dev_get_drvdata(&client->dev); + + for (i = 0; i < PFUZE100_MAX_REGULATOR; i++) + regulator_unregister(pfuze_chip->regulators[i]); + + return 0; +} + +static struct i2c_driver pfuze_driver = { + .id_table = pfuze_device_id, + .driver = { + .name = "pfuze100-regulator", + .owner = THIS_MODULE, + .of_match_table = pfuze_dt_ids, + }, + .probe = pfuze100_regulator_probe, + .remove = pfuze100_regulator_remove, +}; +module_i2c_driver(pfuze_driver); + +MODULE_AUTHOR("Robin Gong "); +MODULE_DESCRIPTION("Regulator Driver for Freescale PFUZE100 PMIC"); +MODULE_ALIAS("pfuze100-regulator"); diff --git a/include/linux/regulator/pfuze100.h b/include/linux/regulator/pfuze100.h new file mode 100644 index 000000000000..65d550bf3954 --- /dev/null +++ b/include/linux/regulator/pfuze100.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2011-2013 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 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 __LINUX_REG_PFUZE100_H +#define __LINUX_REG_PFUZE100_H + +#define PFUZE100_SW1AB 0 +#define PFUZE100_SW1C 1 +#define PFUZE100_SW2 2 +#define PFUZE100_SW3A 3 +#define PFUZE100_SW3B 4 +#define PFUZE100_SW4 5 +#define PFUZE100_SWBST 6 +#define PFUZE100_VSNVS 7 +#define PFUZE100_VREFDDR 8 +#define PFUZE100_VGEN1 9 +#define PFUZE100_VGEN2 10 +#define PFUZE100_VGEN3 11 +#define PFUZE100_VGEN4 12 +#define PFUZE100_VGEN5 13 +#define PFUZE100_VGEN6 14 +#define PFUZE100_MAX_REGULATOR 15 + +struct regulator_init_data; + +struct pfuze_regulator_platform_data { + struct regulator_init_data *init_data[PFUZE100_MAX_REGULATOR]; +}; + +#endif /* __LINUX_REG_PFUZE100_H */ From 88ba5478837098b71573bb7d6002be33156ea7e4 Mon Sep 17 00:00:00 2001 From: Aaron Lu Date: Thu, 25 Jul 2013 13:47:02 +0800 Subject: [PATCH 0649/3400] libata: acpi: remove dead code for ata_acpi_(un)bind Commit 7381fe737 "libata-acpi: remove redundent code for power resource handling" removed ata_acpi_(un)bind but left their prototypes in libata.h, so remove them. Signed-off-by: Aaron Lu Signed-off-by: Tejun Heo --- drivers/ata/libata.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 577d902bc4de..cc8a6e879dfb 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -120,8 +120,6 @@ extern void ata_acpi_on_disable(struct ata_device *dev); extern void ata_acpi_set_state(struct ata_port *ap, pm_message_t state); extern int ata_acpi_register(void); extern void ata_acpi_unregister(void); -extern void ata_acpi_bind(struct ata_device *dev); -extern void ata_acpi_unbind(struct ata_device *dev); extern void ata_acpi_hotplug_init(struct ata_host *host); #else static inline void ata_acpi_dissociate(struct ata_host *host) { } @@ -133,8 +131,6 @@ static inline void ata_acpi_set_state(struct ata_port *ap, pm_message_t state) { } static inline int ata_acpi_register(void) { return 0; } static inline void ata_acpi_unregister(void) { } -static inline void ata_acpi_bind(struct ata_device *dev) { } -static inline void ata_acpi_unbind(struct ata_device *dev) { } static inline void ata_acpi_hotplug_init(struct ata_host *host) {} #endif From 8e24a32ed15759640516ecd92668197e2f4d686d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 25 Jul 2013 09:37:21 -0700 Subject: [PATCH 0650/3400] staging: gdm724x: remove ioctl call This isn't needed, userspace can trigger off of the device id if they need to do something "special" for different devices in special modes depending on the device's endian issues. Reported-by: Dan Carpenter Cc: Won Kang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gdm724x/gdm_lte.c | 38 ------------------- drivers/staging/gdm724x/lte_ioctl.h | 58 ----------------------------- 2 files changed, 96 deletions(-) delete mode 100644 drivers/staging/gdm724x/lte_ioctl.h diff --git a/drivers/staging/gdm724x/gdm_lte.c b/drivers/staging/gdm724x/gdm_lte.c index 0c336345f946..557822fdc966 100644 --- a/drivers/staging/gdm724x/gdm_lte.c +++ b/drivers/staging/gdm724x/gdm_lte.c @@ -36,7 +36,6 @@ #include "hci.h" #include "hci_packet.h" #include "gdm_endian.h" -#include "lte_ioctl.h" /* * Netlink protocol number @@ -498,42 +497,6 @@ static struct net_device_stats *gdm_lte_stats(struct net_device *dev) return &nic->stats; } -static void get_dev_endian(struct data_t *data, struct net_device *dev) -{ - struct nic *nic = netdev_priv(dev); - unsigned long ret; - - ret = copy_to_user(data->buf, gdm_dev_endian(nic), sizeof(struct dev_endian_t)); - if (ret) - netdev_info(dev, "state - failed to copy\n"); -} - -static int gdm_lte_ioctl_get_data(struct wm_req_t *req, struct net_device *dev) -{ - u16 id = req->data_id; - - switch (id) { - case GET_ENDIAN_INFO: - /* required for the user space application to find out device endian */ - get_dev_endian(&req->data, dev); - break; - default: - netdev_err(dev, "ioctl - unknown type %d\n", id); - break; - } - return 0; -} - -static int gdm_lte_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - struct wm_req_t *req = (struct wm_req_t *)ifr; - - if (cmd != SIOCLTEIOCTL || req->cmd != SIOCG_DATA || req->data_id >= 100) - return -EOPNOTSUPP; - - return gdm_lte_ioctl_get_data(req, dev); -} - static int gdm_lte_event_send(struct net_device *dev, char *buf, int len) { struct nic *nic = netdev_priv(dev); @@ -811,7 +774,6 @@ static struct net_device_ops gdm_netdev_ops = { .ndo_set_config = gdm_lte_set_config, .ndo_start_xmit = gdm_lte_tx, .ndo_get_stats = gdm_lte_stats, - .ndo_do_ioctl = gdm_lte_ioctl, }; static u8 gdm_lte_macaddr[ETH_ALEN] = {0x00, 0x0a, 0x3b, 0x00, 0x00, 0x00}; diff --git a/drivers/staging/gdm724x/lte_ioctl.h b/drivers/staging/gdm724x/lte_ioctl.h deleted file mode 100644 index 4f890e50add9..000000000000 --- a/drivers/staging/gdm724x/lte_ioctl.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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. - */ - -#ifndef _LTE_IOCTL_H_ -#define _LTE_IOCTL_H_ - -#define SIOCLTEIOCTL SIOCDEVPRIVATE -#define SIOCG_DATA 0x8D10 -#define SIOCS_DATA 0x8D11 - -/* - * For historical reason, ioctl number and structure must be maintained - */ -enum { - LINK_ON, - LINK_OFF, - GET_NETWORK_STATICS, - RX_STOP, - RX_RESUME, - GET_DRV_VER, - GET_SDIO_DEVICE_STATUS, - GET_ENDIAN_INFO, -}; - -struct dev_endian_t { - unsigned char dev_endian; - unsigned char host_endian; -} __packed; - -struct data_t { - long len; - void *buf; -} __packed; - -struct wm_req_t { - union { - char ifrn_name[IFNAMSIZ]; - } ifr_ifrn; - unsigned short cmd; - unsigned short data_id; - struct data_t data; -} __packed; - -#ifndef ifr_name -#define ifr_name (ifr_ifrn.ifrm_name) -#endif - -#endif /* _LTE_IOCTL_H_ */ From ddc191f529be25fd8bfdadab2472d3446c17ae05 Mon Sep 17 00:00:00 2001 From: Jonghwan Choi Date: Mon, 8 Jul 2013 14:02:43 -0600 Subject: [PATCH 0651/3400] PCI: Fix comment typo in iov.c "Devic3" should be "device." Signed-off-by: Jonghwan Choi Signed-off-by: Bjorn Helgaas --- drivers/pci/iov.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index de8ffacf9c9b..de4034ee0efa 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c @@ -786,7 +786,7 @@ int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs) EXPORT_SYMBOL_GPL(pci_sriov_set_totalvfs); /** - * pci_sriov_get_totalvfs -- get total VFs supported on this devic3 + * pci_sriov_get_totalvfs -- get total VFs supported on this device * @dev: the PCI PF device * * For a PCIe device with SRIOV support, return the PCIe From d47af0bcc1d6b0f10ffb7af41d216e4d7710afc2 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Thu, 4 Jul 2013 17:45:20 -0300 Subject: [PATCH 0652/3400] PCI: Rename "PCI Express support" kconfig title The previous option title "PCI Express support" is confusing. The name seems to imply this option is required to get PCIe support, which is not true. Fix it to "PCI Express Port Bus support" which is more accurate. Signed-off-by: Ezequiel Garcia Signed-off-by: Bjorn Helgaas --- drivers/pci/pcie/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig index 569f82fc9e22..a82e70a41039 100644 --- a/drivers/pci/pcie/Kconfig +++ b/drivers/pci/pcie/Kconfig @@ -2,7 +2,7 @@ # PCI Express Port Bus Configuration # config PCIEPORTBUS - bool "PCI Express support" + bool "PCI Express Port Bus support" depends on PCI help This automatically enables PCI Express Port Bus support. Users can From 7cc24e12bd0ee011caa840c1324f613f00d3fc27 Mon Sep 17 00:00:00 2001 From: Valentina Manea Date: Mon, 15 Jul 2013 10:40:48 +0300 Subject: [PATCH 0653/3400] x86/pci/mrst: Cleanup checkpatch.pl warnings This patch fixes warning and errors found by checkpatch.pl: * replace asm/acpi.h, asm/io.h and asm/smp.h with linux/acpi.h, linux/io.h and linux/smp.h respectively * remove explicit initialization to 0 of a static global variable * replace printk(KERN_INFO ...) with pr_info * use tabs instead of spaces for indentation * arrange comments so that they adhere to Documentation/CodingStyle [bhelgaas: capitalize "PCI", "Langwell", "Lincroft" consistently] Signed-off-by: Valentina Manea Signed-off-by: Bjorn Helgaas Acked-by: Ingo Molnar --- arch/x86/pci/mrst.c | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/arch/x86/pci/mrst.c b/arch/x86/pci/mrst.c index 6eb18c42a28a..903fded50786 100644 --- a/arch/x86/pci/mrst.c +++ b/arch/x86/pci/mrst.c @@ -23,11 +23,11 @@ #include #include #include +#include +#include +#include -#include #include -#include -#include #include #include #include @@ -43,7 +43,7 @@ #define PCI_FIXED_BAR_4_SIZE 0x14 #define PCI_FIXED_BAR_5_SIZE 0x1c -static int pci_soc_mode = 0; +static int pci_soc_mode; /** * fixed_bar_cap - return the offset of the fixed BAR cap if found @@ -141,7 +141,8 @@ static int pci_device_update_fixed(struct pci_bus *bus, unsigned int devfn, */ static bool type1_access_ok(unsigned int bus, unsigned int devfn, int reg) { - /* This is a workaround for A0 LNC bug where PCI status register does + /* + * This is a workaround for A0 LNC bug where PCI status register does * not have new CAP bit set. can not be written by SW either. * * PCI header type in real LNC indicates a single function device, this @@ -154,7 +155,7 @@ static bool type1_access_ok(unsigned int bus, unsigned int devfn, int reg) || devfn == PCI_DEVFN(0, 0) || devfn == PCI_DEVFN(3, 0))) return 1; - return 0; /* langwell on others */ + return 0; /* Langwell on others */ } static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, @@ -172,7 +173,8 @@ static int pci_write(struct pci_bus *bus, unsigned int devfn, int where, { int offset; - /* On MRST, there is no PCI ROM BAR, this will cause a subsequent read + /* + * On MRST, there is no PCI ROM BAR, this will cause a subsequent read * to ROM BAR return 0 then being ignored. */ if (where == PCI_ROM_ADDRESS) @@ -210,7 +212,8 @@ static int mrst_pci_irq_enable(struct pci_dev *dev) pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); - /* MRST only have IOAPIC, the PCI irq lines are 1:1 mapped to + /* + * MRST only have IOAPIC, the PCI irq lines are 1:1 mapped to * IOAPIC RTE entries, so we just enable RTE for the device. */ irq_attr.ioapic = mp_find_ioapic(dev->irq); @@ -235,7 +238,7 @@ struct pci_ops pci_mrst_ops = { */ int __init pci_mrst_init(void) { - printk(KERN_INFO "Intel MID platform detected, using MID PCI ops\n"); + pr_info("Intel MID platform detected, using MID PCI ops\n"); pci_mmcfg_late_init(); pcibios_enable_irq = mrst_pci_irq_enable; pci_root_ops = pci_mrst_ops; @@ -244,17 +247,21 @@ int __init pci_mrst_init(void) return 1; } -/* Langwell devices are not true pci devices, they are not subject to 10 ms - * d3 to d0 delay required by pci spec. +/* + * Langwell devices are not true PCI devices; they are not subject to 10 ms + * d3 to d0 delay required by PCI spec. */ static void pci_d3delay_fixup(struct pci_dev *dev) { - /* PCI fixups are effectively decided compile time. If we have a dual - SoC/non-SoC kernel we don't want to mangle d3 on non SoC devices */ - if (!pci_soc_mode) - return; - /* true pci devices in lincroft should allow type 1 access, the rest - * are langwell fake pci devices. + /* + * PCI fixups are effectively decided compile time. If we have a dual + * SoC/non-SoC kernel we don't want to mangle d3 on non-SoC devices. + */ + if (!pci_soc_mode) + return; + /* + * True PCI devices in Lincroft should allow type 1 access, the rest + * are Langwell fake PCI devices. */ if (type1_access_ok(dev->bus->number, dev->devfn, PCI_DEVICE_ID)) return; From 24336a61e699c33154001eb4d65d3a1bb01a1b3a Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 5 Jul 2013 15:17:27 -0600 Subject: [PATCH 0654/3400] frv/PCI: Mark pcibios_fixup_bus() as non-init pcibios_fixup_bus() is called by pci_scan_child_bus(), which is not marked __init. Therefore, pcibios_fixup_bus() cannot be marked __init either. Signed-off-by: Bjorn Helgaas --- arch/frv/mb93090-mb00/pci-vdk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/frv/mb93090-mb00/pci-vdk.c b/arch/frv/mb93090-mb00/pci-vdk.c index 0aa35f0eb0db..deb67843693c 100644 --- a/arch/frv/mb93090-mb00/pci-vdk.c +++ b/arch/frv/mb93090-mb00/pci-vdk.c @@ -320,7 +320,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases); * are examined. */ -void __init pcibios_fixup_bus(struct pci_bus *bus) +void pcibios_fixup_bus(struct pci_bus *bus) { #if 0 printk("### PCIBIOS_FIXUP_BUS(%d)\n",bus->number); From 56039e658cc902fe6e3d1276bb78f7e69768cd35 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Jul 2013 15:05:17 -0700 Subject: [PATCH 0655/3400] PCI: Convert class code to use dev_groups The dev_attrs field of struct class is going away soon, dev_groups should be used instead. This converts the PCI class code to use the correct field. Signed-off-by: Greg Kroah-Hartman Signed-off-by: Bjorn Helgaas --- drivers/pci/pci-sysfs.c | 32 +++++++++++++++++++++----------- drivers/pci/pci.h | 2 +- drivers/pci/probe.c | 2 +- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index c0dbe1f61362..7128cfdd64aa 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -131,19 +131,19 @@ static ssize_t pci_bus_show_cpuaffinity(struct device *dev, return ret; } -static inline ssize_t pci_bus_show_cpumaskaffinity(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t cpuaffinity_show(struct device *dev, + struct device_attribute *attr, char *buf) { return pci_bus_show_cpuaffinity(dev, 0, attr, buf); } +static DEVICE_ATTR_RO(cpuaffinity); -static inline ssize_t pci_bus_show_cpulistaffinity(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t cpulistaffinity_show(struct device *dev, + struct device_attribute *attr, char *buf) { return pci_bus_show_cpuaffinity(dev, 1, attr, buf); } +static DEVICE_ATTR_RO(cpulistaffinity); /* show resources */ static ssize_t @@ -379,6 +379,7 @@ dev_bus_rescan_store(struct device *dev, struct device_attribute *attr, } return count; } +static DEVICE_ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, dev_bus_rescan_store); #if defined(CONFIG_PM_RUNTIME) && defined(CONFIG_ACPI) static ssize_t d3cold_allowed_store(struct device *dev, @@ -514,11 +515,20 @@ struct device_attribute pci_dev_attrs[] = { __ATTR_NULL, }; -struct device_attribute pcibus_dev_attrs[] = { - __ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, dev_bus_rescan_store), - __ATTR(cpuaffinity, S_IRUGO, pci_bus_show_cpumaskaffinity, NULL), - __ATTR(cpulistaffinity, S_IRUGO, pci_bus_show_cpulistaffinity, NULL), - __ATTR_NULL, +static struct attribute *pcibus_attrs[] = { + &dev_attr_rescan.attr, + &dev_attr_cpuaffinity.attr, + &dev_attr_cpulistaffinity.attr, + NULL, +}; + +static const struct attribute_group pcibus_group = { + .attrs = pcibus_attrs, +}; + +const struct attribute_group *pcibus_groups[] = { + &pcibus_group, + NULL, }; static ssize_t diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index d1182c4a754e..816c297f170c 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -151,7 +151,7 @@ static inline int pci_no_d1d2(struct pci_dev *dev) } extern struct device_attribute pci_dev_attrs[]; -extern struct device_attribute pcibus_dev_attrs[]; +extern const struct attribute_group *pcibus_groups[]; extern struct device_type pci_dev_type; extern struct bus_attribute pci_bus_attrs[]; diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 46ada5c098eb..cf57fe79450a 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -96,7 +96,7 @@ static void release_pcibus_dev(struct device *dev) static struct class pcibus_class = { .name = "pci_bus", .dev_release = &release_pcibus_dev, - .dev_attrs = pcibus_dev_attrs, + .dev_groups = pcibus_groups, }; static int __init pcibus_class_init(void) From 0a67119fce8e0246ce7c448e3db12afd57857ac0 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Thu, 27 Jun 2013 16:39:48 -0600 Subject: [PATCH 0656/3400] PCI: Check all ACS features for multifunction downstream ports The multifunction ACS rules do not apply to downstream ports. Those should be tested regardless of whether they are single function or multifunction. The PCIe spec also fully specifies which PCIe types are subject to the multifunction rules and excludes event collectors and PCIe-to-PCI bridges entirely. Document each rule to the section of the PCIe spec and provide overall documentation of the function. Signed-off-by: Alex Williamson Signed-off-by: Bjorn Helgaas Acked-by: Donald Dutile --- drivers/pci/pci.c | 84 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 70 insertions(+), 14 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index e37fea6e178d..3c1ff63aa56d 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -2359,6 +2359,19 @@ void pci_enable_acs(struct pci_dev *dev) pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl); } +static bool pci_acs_flags_enabled(struct pci_dev *pdev, u16 acs_flags) +{ + int pos; + u16 ctrl; + + pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ACS); + if (!pos) + return false; + + pci_read_config_word(pdev, pos + PCI_ACS_CTRL, &ctrl); + return (ctrl & acs_flags) == acs_flags; +} + /** * pci_acs_enabled - test ACS against required flags for a given device * @pdev: device to test @@ -2366,36 +2379,79 @@ void pci_enable_acs(struct pci_dev *dev) * * Return true if the device supports the provided flags. Automatically * filters out flags that are not implemented on multifunction devices. + * + * Note that this interface checks the effective ACS capabilities of the + * device rather than the actual capabilities. For instance, most single + * function endpoints are not required to support ACS because they have no + * opportunity for peer-to-peer access. We therefore return 'true' + * regardless of whether the device exposes an ACS capability. This makes + * it much easier for callers of this function to ignore the actual type + * or topology of the device when testing ACS support. */ bool pci_acs_enabled(struct pci_dev *pdev, u16 acs_flags) { - int pos, ret; - u16 ctrl; + int ret; ret = pci_dev_specific_acs_enabled(pdev, acs_flags); if (ret >= 0) return ret > 0; + /* + * Conventional PCI and PCI-X devices never support ACS, either + * effectively or actually. The shared bus topology implies that + * any device on the bus can receive or snoop DMA. + */ if (!pci_is_pcie(pdev)) return false; - /* Filter out flags not applicable to multifunction */ - if (pdev->multifunction) + switch (pci_pcie_type(pdev)) { + /* + * PCI/X-to-PCIe bridges are not specifically mentioned by the spec, + * but since their primary inteface is PCI/X, we conservatively + * handle them as we would a non-PCIe device. + */ + case PCI_EXP_TYPE_PCIE_BRIDGE: + /* + * PCIe 3.0, 6.12.1 excludes ACS on these devices. "ACS is never + * applicable... must never implement an ACS Extended Capability...". + * This seems arbitrary, but we take a conservative interpretation + * of this statement. + */ + case PCI_EXP_TYPE_PCI_BRIDGE: + case PCI_EXP_TYPE_RC_EC: + return false; + /* + * PCIe 3.0, 6.12.1.1 specifies that downstream and root ports should + * implement ACS in order to indicate their peer-to-peer capabilities, + * regardless of whether they are single- or multi-function devices. + */ + case PCI_EXP_TYPE_DOWNSTREAM: + case PCI_EXP_TYPE_ROOT_PORT: + return pci_acs_flags_enabled(pdev, acs_flags); + /* + * PCIe 3.0, 6.12.1.2 specifies ACS capabilities that should be + * implemented by the remaining PCIe types to indicate peer-to-peer + * capabilities, but only when they are part of a multifunciton + * device. The footnote for section 6.12 indicates the specific + * PCIe types included here. + */ + case PCI_EXP_TYPE_ENDPOINT: + case PCI_EXP_TYPE_UPSTREAM: + case PCI_EXP_TYPE_LEG_END: + case PCI_EXP_TYPE_RC_END: + if (!pdev->multifunction) + break; + acs_flags &= (PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_EC | PCI_ACS_DT); - if (pci_pcie_type(pdev) == PCI_EXP_TYPE_DOWNSTREAM || - pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT || - pdev->multifunction) { - pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ACS); - if (!pos) - return false; - - pci_read_config_word(pdev, pos + PCI_ACS_CTRL, &ctrl); - if ((ctrl & acs_flags) != acs_flags) - return false; + return pci_acs_flags_enabled(pdev, acs_flags); } + /* + * PCIe 3.0, 6.12.1.3 specifies no ACS capabilties are applicable + * to single function devices with the exception of downstream ports. + */ return true; } From 83db7e0bdb70a9bb93cd000fefc3fbac3394f516 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Thu, 27 Jun 2013 16:39:54 -0600 Subject: [PATCH 0657/3400] PCI: Differentiate ACS controllable from enabled We currently misinterpret that in order for an ACS feature to be enabled it must be set in the control field. In reality, this means that the feature is not only enabled, but controllable. Many of the ACS capability bits are not required if the device behaves by default in the way specified when both the capability and control bit are set and does not support or allow the alternate mode. We therefore need to check the capabilities and mask out flags that are enabled but not controllable. Egress control seems to be the only flag which is purely optional. Signed-off-by: Alex Williamson Signed-off-by: Bjorn Helgaas Acked-by: Donald Dutile --- drivers/pci/pci.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 3c1ff63aa56d..a599a6bbdf37 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -2362,12 +2362,20 @@ void pci_enable_acs(struct pci_dev *dev) static bool pci_acs_flags_enabled(struct pci_dev *pdev, u16 acs_flags) { int pos; - u16 ctrl; + u16 cap, ctrl; pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ACS); if (!pos) return false; + /* + * Except for egress control, capabilities are either required + * or only required if controllable. Features missing from the + * capability field can therefore be assumed as hard-wired enabled. + */ + pci_read_config_word(pdev, pos + PCI_ACS_CAP, &cap); + acs_flags &= (cap | PCI_ACS_EC); + pci_read_config_word(pdev, pos + PCI_ACS_CTRL, &ctrl); return (ctrl & acs_flags) == acs_flags; } @@ -2442,9 +2450,6 @@ bool pci_acs_enabled(struct pci_dev *pdev, u16 acs_flags) if (!pdev->multifunction) break; - acs_flags &= (PCI_ACS_RR | PCI_ACS_CR | - PCI_ACS_EC | PCI_ACS_DT); - return pci_acs_flags_enabled(pdev, acs_flags); } From 15b100dfd1c9f7558d2fba4e3d13591dab50667f Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Thu, 27 Jun 2013 16:40:00 -0600 Subject: [PATCH 0658/3400] PCI: Claim ACS support for AMD southbridge devices AMD confirmed that peer-to-peer between these devices is not possible. We can therefore claim that they support a subset of ACS. Signed-off-by: Alex Williamson Signed-off-by: Bjorn Helgaas Acked-by: Donald Dutile --- drivers/pci/quirks.c | 50 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index e85d23044ae0..2e2ea2208f2e 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -3295,11 +3295,61 @@ struct pci_dev *pci_get_dma_source(struct pci_dev *dev) return pci_dev_get(dev); } +/* + * AMD has indicated that the devices below do not support peer-to-peer + * in any system where they are found in the southbridge with an AMD + * IOMMU in the system. Multifunction devices that do not support + * peer-to-peer between functions can claim to support a subset of ACS. + * Such devices effectively enable request redirect (RR) and completion + * redirect (CR) since all transactions are redirected to the upstream + * root complex. + * + * http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/94086 + * http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/94102 + * http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/99402 + * + * 1002:4385 SBx00 SMBus Controller + * 1002:439c SB7x0/SB8x0/SB9x0 IDE Controller + * 1002:4383 SBx00 Azalia (Intel HDA) + * 1002:439d SB7x0/SB8x0/SB9x0 LPC host controller + * 1002:4384 SBx00 PCI to PCI Bridge + * 1002:4399 SB7x0/SB8x0/SB9x0 USB OHCI2 Controller + */ +static int pci_quirk_amd_sb_acs(struct pci_dev *dev, u16 acs_flags) +{ +#ifdef CONFIG_ACPI + struct acpi_table_header *header = NULL; + acpi_status status; + + /* Targeting multifunction devices on the SB (appears on root bus) */ + if (!dev->multifunction || !pci_is_root_bus(dev->bus)) + return -ENODEV; + + /* The IVRS table describes the AMD IOMMU */ + status = acpi_get_table("IVRS", 0, &header); + if (ACPI_FAILURE(status)) + return -ENODEV; + + /* Filter out flags not applicable to multifunction */ + acs_flags &= (PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_EC | PCI_ACS_DT); + + return acs_flags & ~(PCI_ACS_RR | PCI_ACS_CR) ? 0 : 1; +#else + return -ENODEV; +#endif +} + static const struct pci_dev_acs_enabled { u16 vendor; u16 device; int (*acs_enabled)(struct pci_dev *dev, u16 acs_flags); } pci_dev_acs_enabled[] = { + { PCI_VENDOR_ID_ATI, 0x4385, pci_quirk_amd_sb_acs }, + { PCI_VENDOR_ID_ATI, 0x439c, pci_quirk_amd_sb_acs }, + { PCI_VENDOR_ID_ATI, 0x4383, pci_quirk_amd_sb_acs }, + { PCI_VENDOR_ID_ATI, 0x439d, pci_quirk_amd_sb_acs }, + { PCI_VENDOR_ID_ATI, 0x4384, pci_quirk_amd_sb_acs }, + { PCI_VENDOR_ID_ATI, 0x4399, pci_quirk_amd_sb_acs }, { 0 } }; From 61e83cdde15f8850087d6c57c8576e25b671db59 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Mon, 22 Jul 2013 14:37:12 -0700 Subject: [PATCH 0659/3400] PCI: Drop temporary variable in pci_assign_unassigned_resources() Drop the "bus" temporary variable. No functional change, but simplifies later patch slightly. [bhelgaas: changelog, make same change in pci_assign_unassigned_bridge_resources() to keep it parallel with pci_assign_unassigned_resources()] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/setup-bus.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index d254e2379533..cb6bcbb26226 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1458,12 +1458,11 @@ again: * Try to release leaf bridge's resources that doesn't fit resource of * child device under that bridge */ - list_for_each_entry(fail_res, &fail_head, list) { - bus = fail_res->dev->bus; - pci_bus_release_bridge_resources(bus, + list_for_each_entry(fail_res, &fail_head, list) + pci_bus_release_bridge_resources(fail_res->dev->bus, fail_res->flags & type_mask, rel_type); - } + /* restore size and flags */ list_for_each_entry(fail_res, &fail_head, list) { struct resource *res = fail_res->res; @@ -1522,13 +1521,11 @@ again: * Try to release leaf bridge's resources that doesn't fit resource of * child device under that bridge */ - list_for_each_entry(fail_res, &fail_head, list) { - struct pci_bus *bus = fail_res->dev->bus; - unsigned long flags = fail_res->flags; - - pci_bus_release_bridge_resources(bus, flags & type_mask, + list_for_each_entry(fail_res, &fail_head, list) + pci_bus_release_bridge_resources(fail_res->dev->bus, + fail_res->flags & type_mask, whole_subtree); - } + /* restore size and flags */ list_for_each_entry(fail_res, &fail_head, list) { struct resource *res = fail_res->res; From 223d96fc3249b0ffdc30bf77fd90c93f857e9a6e Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Mon, 22 Jul 2013 14:37:13 -0700 Subject: [PATCH 0660/3400] PCI: Look for unassigned resources on per-bus basis When CONFIG_PCI_REALLOC_ENABLE_AUTO=y, pci_realloc_detect() looks at PCI devices to see if any have SR-IOV resources that need to be assigned. If it finds any, it turns on automatic resource reallocation. This patch changes pci_realloc_detect() so it uses pci_walk_bus() on each root bus instead of using for_each_pci_dev(). This is a step toward doing reallocation on a per-bus basis, so we can do it for a hot-added host bridge. [bhelgaas: changelog, rename callback to iov_resources_unassigned(), use boolean for "unassigned"] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/setup-bus.c | 46 +++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index cb6bcbb26226..20c09bd652db 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1359,30 +1359,44 @@ static bool __init pci_realloc_enabled(void) return pci_realloc_enable >= user_enabled; } -static void __init pci_realloc_detect(void) -{ #if defined(CONFIG_PCI_IOV) && defined(CONFIG_PCI_REALLOC_ENABLE_AUTO) - struct pci_dev *dev = NULL; +static int __init iov_resources_unassigned(struct pci_dev *dev, void *data) +{ + int i; + bool *unassigned = data; + + for (i = PCI_IOV_RESOURCES; i <= PCI_IOV_RESOURCE_END; i++) { + struct resource *r = &dev->resource[i]; + + /* Not assigned or rejected by kernel? */ + if (r->flags && !r->start) { + *unassigned = true; + return 1; /* return early from pci_walk_bus() */ + } + } + + return 0; +} + +static void __init pci_realloc_detect(void) +{ + bool unassigned = false; + struct pci_bus *bus; if (pci_realloc_enable != undefined) return; - for_each_pci_dev(dev) { - int i; - - for (i = PCI_IOV_RESOURCES; i <= PCI_IOV_RESOURCE_END; i++) { - struct resource *r = &dev->resource[i]; - - /* Not assigned, or rejected by kernel ? */ - if (r->flags && !r->start) { - pci_realloc_enable = auto_enabled; - - return; - } + list_for_each_entry(bus, &pci_root_buses, node) { + pci_walk_bus(bus, iov_resources_unassigned, &unassigned); + if (unassigned) { + pci_realloc_enable = auto_enabled; + return; } } -#endif } +#else +static void __init pci_realloc_detect(void) { } +#endif /* * first try will not touch pci bridge res From fa216bf4dbe35e15044b90e7b51509768bab3d9a Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Mon, 22 Jul 2013 14:37:14 -0700 Subject: [PATCH 0661/3400] PCI: Turn on reallocation for unassigned resources with host bridge offset Previously we did not turn on automatic PCI resource reallocation for unassigned IOV resources behind a host bridge with address offset. This patch fixes that bug. The intent was that "!r->start" would check for a BAR containing zero. But that check is incorrect for host bridges that apply an offset, because in that case the resource address is not the same as the bus address. This patch fixes that by converting the resource address back to a bus address before checking for zero. [bhelgaas: changelog] Suggested-by: Benjamin Herrenschmidt Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/setup-bus.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 20c09bd652db..ed1bd0cdf521 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1367,9 +1367,14 @@ static int __init iov_resources_unassigned(struct pci_dev *dev, void *data) for (i = PCI_IOV_RESOURCES; i <= PCI_IOV_RESOURCE_END; i++) { struct resource *r = &dev->resource[i]; + struct pci_bus_region region; /* Not assigned or rejected by kernel? */ - if (r->flags && !r->start) { + if (!r->flags) + continue; + + pcibios_resource_to_bus(dev, ®ion, r); + if (!region.start) { *unassigned = true; return 1; /* return early from pci_walk_bus() */ } From 967260cdb13f9c0de3cf56e305b34eb363e41d5b Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Mon, 22 Jul 2013 14:37:15 -0700 Subject: [PATCH 0662/3400] PCI: Enable unassigned resource reallocation on per-bus basis pci_realloc_detect() turns on automatic resource allocation when it finds unassigned SR-IOV resources. Previously it did this on a global basis, so we enabled reallocation if any PCI device anywhere had an unassigned SR-IOV resource. This patch changes pci_realloc_detect() so it looks at a single bus, so we can do this when a host bridge is hot-added. [bhelgaas: changelog] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/setup-bus.c | 42 ++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index ed1bd0cdf521..4aaa8d57443f 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1354,9 +1354,9 @@ void __init pci_realloc_get_opt(char *str) else if (!strncmp(str, "on", 2)) pci_realloc_enable = user_enabled; } -static bool __init pci_realloc_enabled(void) +static bool __init pci_realloc_enabled(enum enable_type enable) { - return pci_realloc_enable >= user_enabled; + return enable >= user_enabled; } #if defined(CONFIG_PCI_IOV) && defined(CONFIG_PCI_REALLOC_ENABLE_AUTO) @@ -1383,24 +1383,26 @@ static int __init iov_resources_unassigned(struct pci_dev *dev, void *data) return 0; } -static void __init pci_realloc_detect(void) +static enum enable_type __init pci_realloc_detect(struct pci_bus *bus, + enum enable_type enable_local) { bool unassigned = false; - struct pci_bus *bus; - if (pci_realloc_enable != undefined) - return; + if (enable_local != undefined) + return enable_local; - list_for_each_entry(bus, &pci_root_buses, node) { - pci_walk_bus(bus, iov_resources_unassigned, &unassigned); - if (unassigned) { - pci_realloc_enable = auto_enabled; - return; - } - } + pci_walk_bus(bus, iov_resources_unassigned, &unassigned); + if (unassigned) + return auto_enabled; + + return enable_local; } #else -static void __init pci_realloc_detect(void) { } +static enum enable_type __init pci_realloc_detect(struct pci_bus *bus, + enum enable_type enable_local) +{ + return enable_local; +} #endif /* @@ -1422,10 +1424,12 @@ pci_assign_unassigned_resources(void) unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH; int pci_try_num = 1; + enum enable_type enable_local = pci_realloc_enable; - /* don't realloc if asked to do so */ - pci_realloc_detect(); - if (pci_realloc_enabled()) { + list_for_each_entry(bus, &pci_root_buses, node) + enable_local = pci_realloc_detect(bus, enable_local); + + if (pci_realloc_enabled(enable_local)) { int max_depth = pci_get_max_depth(); pci_try_num = max_depth + 1; @@ -1457,9 +1461,9 @@ again: goto enable_and_dump; if (tried_times >= pci_try_num) { - if (pci_realloc_enable == undefined) + if (enable_local == undefined) printk(KERN_INFO "Some PCI device resources are unassigned, try booting with pci=realloc\n"); - else if (pci_realloc_enable == auto_enabled) + else if (enable_local == auto_enabled) printk(KERN_INFO "Automatically enabled pci realloc, if you have problem, try booting with pci=realloc=off\n"); free_list(&fail_head); From 55ed83a615730c2578da155bc99b68f4417ffe20 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Mon, 22 Jul 2013 14:37:16 -0700 Subject: [PATCH 0663/3400] PCI: Assign resources on a per-bus basis Previously, we did resource assignment globally. This patch splits up pci_assign_unassigned_resources() so assignment is done for each root bus in turn. We check each root bus individually to see whether it needs any reassignment, and if it does, we assign resources for just that bus. [bhelgaas: changelog] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/setup-bus.c | 62 +++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 37 deletions(-) diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 4aaa8d57443f..4d9ebb4ce015 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1315,21 +1315,6 @@ static int __init pci_bus_get_depth(struct pci_bus *bus) return depth; } -static int __init pci_get_max_depth(void) -{ - int depth = 0; - struct pci_bus *bus; - - list_for_each_entry(bus, &pci_root_buses, node) { - int ret; - - ret = pci_bus_get_depth(bus); - if (ret > depth) - depth = ret; - } - - return depth; -} /* * -1: undefined, will auto detect later @@ -1410,10 +1395,9 @@ static enum enable_type __init pci_realloc_detect(struct pci_bus *bus, * second and later try will clear small leaf bridge res * will stop till to the max deepth if can not find good one */ -void __init -pci_assign_unassigned_resources(void) +static void __init +pci_assign_unassigned_root_bus_resources(struct pci_bus *bus) { - struct pci_bus *bus; LIST_HEAD(realloc_head); /* list of resources that want additional resources */ struct list_head *add_list = NULL; @@ -1424,17 +1408,17 @@ pci_assign_unassigned_resources(void) unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH; int pci_try_num = 1; - enum enable_type enable_local = pci_realloc_enable; - - list_for_each_entry(bus, &pci_root_buses, node) - enable_local = pci_realloc_detect(bus, enable_local); + enum enable_type enable_local; + /* don't realloc if asked to do so */ + enable_local = pci_realloc_detect(bus, pci_realloc_enable); if (pci_realloc_enabled(enable_local)) { - int max_depth = pci_get_max_depth(); + int max_depth = pci_bus_get_depth(bus); pci_try_num = max_depth + 1; - printk(KERN_DEBUG "PCI: max bus depth: %d pci_try_num: %d\n", - max_depth, pci_try_num); + dev_printk(KERN_DEBUG, &bus->dev, + "max bus depth: %d pci_try_num: %d\n", + max_depth, pci_try_num); } again: @@ -1446,12 +1430,10 @@ again: add_list = &realloc_head; /* Depth first, calculate sizes and alignments of all subordinate buses. */ - list_for_each_entry(bus, &pci_root_buses, node) - __pci_bus_size_bridges(bus, add_list); + __pci_bus_size_bridges(bus, add_list); /* Depth last, allocate resources and update the hardware. */ - list_for_each_entry(bus, &pci_root_buses, node) - __pci_bus_assign_resources(bus, add_list, &fail_head); + __pci_bus_assign_resources(bus, add_list, &fail_head); if (add_list) BUG_ON(!list_empty(add_list)); tried_times++; @@ -1462,16 +1444,16 @@ again: if (tried_times >= pci_try_num) { if (enable_local == undefined) - printk(KERN_INFO "Some PCI device resources are unassigned, try booting with pci=realloc\n"); + dev_info(&bus->dev, "Some PCI device resources are unassigned, try booting with pci=realloc\n"); else if (enable_local == auto_enabled) - printk(KERN_INFO "Automatically enabled pci realloc, if you have problem, try booting with pci=realloc=off\n"); + dev_info(&bus->dev, "Automatically enabled pci realloc, if you have problem, try booting with pci=realloc=off\n"); free_list(&fail_head); goto enable_and_dump; } - printk(KERN_DEBUG "PCI: No. %d try to assign unassigned res\n", - tried_times + 1); + dev_printk(KERN_DEBUG, &bus->dev, + "No. %d try to assign unassigned res\n", tried_times + 1); /* third times and later will not check if it is leaf */ if ((tried_times + 1) > 2) @@ -1502,12 +1484,18 @@ again: enable_and_dump: /* Depth last, update the hardware. */ - list_for_each_entry(bus, &pci_root_buses, node) - pci_enable_bridges(bus); + pci_enable_bridges(bus); /* dump the resource on buses */ - list_for_each_entry(bus, &pci_root_buses, node) - pci_bus_dump_resources(bus); + pci_bus_dump_resources(bus); +} + +void __init pci_assign_unassigned_resources(void) +{ + struct pci_bus *root_bus; + + list_for_each_entry(root_bus, &pci_root_buses, node) + pci_assign_unassigned_root_bus_resources(root_bus); } void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge) From 928bea964827d7824b548c1f8e06eccbbc4d0d7d Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Mon, 22 Jul 2013 14:37:17 -0700 Subject: [PATCH 0664/3400] PCI: Delay enabling bridges until they're needed We currently enable PCI bridges after scanning a bus and assigning resources. This is often done in arch code. This patch changes this so we don't enable a bridge until necessary, i.e., until we enable a PCI device behind the bridge. We do this in the generic pci_enable_device() path, so this also removes the arch-specific code to enable bridges. [bhelgaas: changelog] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- arch/arm/kernel/bios32.c | 5 ----- arch/m68k/platform/coldfire/pci.c | 1 - arch/mips/pci/pci.c | 1 - arch/sh/drivers/pci/pci.c | 1 - drivers/acpi/pci_root.c | 3 --- drivers/parisc/lba_pci.c | 1 - drivers/pci/bus.c | 19 ------------------- drivers/pci/hotplug/acpiphp_glue.c | 1 - drivers/pci/pci.c | 20 ++++++++++++++++++++ drivers/pci/probe.c | 1 - drivers/pci/setup-bus.c | 10 +++------- drivers/pcmcia/cardbus.c | 1 - include/linux/pci.h | 1 - 13 files changed, 23 insertions(+), 42 deletions(-) diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index 261fcc826169..88e14d74b6de 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c @@ -525,11 +525,6 @@ void pci_common_init_dev(struct device *parent, struct hw_pci *hw) * Assign resources. */ pci_bus_assign_resources(bus); - - /* - * Enable bridges - */ - pci_enable_bridges(bus); } /* diff --git a/arch/m68k/platform/coldfire/pci.c b/arch/m68k/platform/coldfire/pci.c index b33f97a13e6d..df9679238b6d 100644 --- a/arch/m68k/platform/coldfire/pci.c +++ b/arch/m68k/platform/coldfire/pci.c @@ -319,7 +319,6 @@ static int __init mcf_pci_init(void) pci_fixup_irqs(pci_common_swizzle, mcf_pci_map_irq); pci_bus_size_bridges(rootbus); pci_bus_assign_resources(rootbus); - pci_enable_bridges(rootbus); return 0; } diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c index 594e60d6a43b..33e7aa52d9c4 100644 --- a/arch/mips/pci/pci.c +++ b/arch/mips/pci/pci.c @@ -113,7 +113,6 @@ static void pcibios_scanbus(struct pci_controller *hose) if (!pci_has_flag(PCI_PROBE_ONLY)) { pci_bus_size_bridges(bus); pci_bus_assign_resources(bus); - pci_enable_bridges(bus); } } } diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c index 102f5d58b037..60ed3e1c4b75 100644 --- a/arch/sh/drivers/pci/pci.c +++ b/arch/sh/drivers/pci/pci.c @@ -69,7 +69,6 @@ static void pcibios_scanbus(struct pci_channel *hose) pci_bus_size_bridges(bus); pci_bus_assign_resources(bus); - pci_enable_bridges(bus); } else { pci_free_resource_list(&resources); } diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 5917839321b8..faa1d29c0261 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -527,9 +527,6 @@ static int acpi_pci_root_add(struct acpi_device *device, if (system_state != SYSTEM_BOOTING) { pcibios_resource_survey_bus(root->bus); pci_assign_unassigned_bus_resources(root->bus); - - /* need to after hot-added ioapic is registered */ - pci_enable_bridges(root->bus); } pci_bus_add_devices(root->bus); diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index 19f6f70c67d3..37e71ff6408d 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c @@ -1590,7 +1590,6 @@ lba_driver_probe(struct parisc_device *dev) lba_dump_res(&lba_dev->hba.lmmio_space, 2); #endif } - pci_enable_bridges(lba_bus); /* ** Once PCI register ops has walked the bus, access to config diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index b1ff02ab4f13..fc1b74013743 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -216,24 +216,6 @@ void pci_bus_add_devices(const struct pci_bus *bus) } } -void pci_enable_bridges(struct pci_bus *bus) -{ - struct pci_dev *dev; - int retval; - - list_for_each_entry(dev, &bus->devices, bus_list) { - if (dev->subordinate) { - if (!pci_is_enabled(dev)) { - retval = pci_enable_device(dev); - if (retval) - dev_err(&dev->dev, "Error enabling bridge (%d), continuing\n", retval); - pci_set_master(dev); - } - pci_enable_bridges(dev->subordinate); - } - } -} - /** pci_walk_bus - walk devices on/under bus, calling callback. * @top bus whose devices should be walked * @cb callback to be called for each device found @@ -301,4 +283,3 @@ EXPORT_SYMBOL(pci_bus_put); EXPORT_SYMBOL(pci_bus_alloc_resource); EXPORT_SYMBOL_GPL(pci_bus_add_device); EXPORT_SYMBOL(pci_bus_add_devices); -EXPORT_SYMBOL(pci_enable_bridges); diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 59df8575a48c..52dee9d31e1c 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -723,7 +723,6 @@ static int __ref enable_device(struct acpiphp_slot *slot) acpiphp_sanitize_bus(bus); acpiphp_set_hpp_values(bus); acpiphp_set_acpi_region(slot); - pci_enable_bridges(bus); list_for_each_entry(dev, &bus->devices, bus_list) { /* Assume that newly added devices are powered on already. */ diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index e37fea6e178d..44a1a8a0ad7b 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1145,6 +1145,24 @@ int pci_reenable_device(struct pci_dev *dev) return 0; } +static void pci_enable_bridge(struct pci_dev *dev) +{ + int retval; + + if (!dev) + return; + + pci_enable_bridge(dev->bus->self); + + if (pci_is_enabled(dev)) + return; + retval = pci_enable_device(dev); + if (retval) + dev_err(&dev->dev, "Error enabling bridge (%d), continuing\n", + retval); + pci_set_master(dev); +} + static int pci_enable_device_flags(struct pci_dev *dev, unsigned long flags) { int err; @@ -1165,6 +1183,8 @@ static int pci_enable_device_flags(struct pci_dev *dev, unsigned long flags) if (atomic_inc_return(&dev->enable_cnt) > 1) return 0; /* already enabled */ + pci_enable_bridge(dev->bus->self); + /* only skip sriov related */ for (i = 0; i <= PCI_ROM_RESOURCE; i++) if (dev->resource[i].flags & flags) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 46ada5c098eb..85c114cd91cc 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1979,7 +1979,6 @@ unsigned int __ref pci_rescan_bus(struct pci_bus *bus) max = pci_scan_child_bus(bus); pci_assign_unassigned_bus_resources(bus); - pci_enable_bridges(bus); pci_bus_add_devices(bus); return max; diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 4d9ebb4ce015..8f86be13678f 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1440,7 +1440,7 @@ again: /* any device complain? */ if (list_empty(&fail_head)) - goto enable_and_dump; + goto dump; if (tried_times >= pci_try_num) { if (enable_local == undefined) @@ -1449,7 +1449,7 @@ again: dev_info(&bus->dev, "Automatically enabled pci realloc, if you have problem, try booting with pci=realloc=off\n"); free_list(&fail_head); - goto enable_and_dump; + goto dump; } dev_printk(KERN_DEBUG, &bus->dev, @@ -1482,10 +1482,7 @@ again: goto again; -enable_and_dump: - /* Depth last, update the hardware. */ - pci_enable_bridges(bus); - +dump: /* dump the resource on buses */ pci_bus_dump_resources(bus); } @@ -1556,7 +1553,6 @@ enable_all: if (retval) dev_err(&bridge->dev, "Error reenabling bridge (%d)\n", retval); pci_set_master(bridge); - pci_enable_bridges(parent); } EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources); diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c index 9d3ac998fc1f..b2a98cdbd0d2 100644 --- a/drivers/pcmcia/cardbus.c +++ b/drivers/pcmcia/cardbus.c @@ -91,7 +91,6 @@ int __ref cb_alloc(struct pcmcia_socket *s) if (s->tune_bridge) s->tune_bridge(s, bus); - pci_enable_bridges(bus); pci_bus_add_devices(bus); return 0; diff --git a/include/linux/pci.h b/include/linux/pci.h index 0fd1f1582fa1..8cd1e6f30acd 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1043,7 +1043,6 @@ int __must_check pci_bus_alloc_resource(struct pci_bus *bus, resource_size_t, resource_size_t), void *alignf_data); -void pci_enable_bridges(struct pci_bus *bus); /* Proper probing supporting hot-pluggable devices */ int __must_check __pci_register_driver(struct pci_driver *, struct module *, From ff35147cf15814e13c62831f6910f8663e4dc91e Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Wed, 24 Jul 2013 15:37:13 -0600 Subject: [PATCH 0665/3400] PCI: Move resource reallocation code to non-__init Resource reallocation is currently done only at boot-time, but will soon be done when host bridge is hot-added. This patch removes the __init annotations so the code will still be present after boot. [bhelgaas: split __init changes out] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/setup-bus.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 8f86be13678f..8d1e654256a8 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1297,7 +1297,7 @@ static void pci_bus_dump_resources(struct pci_bus *bus) } } -static int __init pci_bus_get_depth(struct pci_bus *bus) +static int pci_bus_get_depth(struct pci_bus *bus) { int depth = 0; struct pci_dev *dev; @@ -1331,7 +1331,7 @@ enum enable_type { auto_enabled, }; -static enum enable_type pci_realloc_enable __initdata = undefined; +static enum enable_type pci_realloc_enable = undefined; void __init pci_realloc_get_opt(char *str) { if (!strncmp(str, "off", 3)) @@ -1339,13 +1339,13 @@ void __init pci_realloc_get_opt(char *str) else if (!strncmp(str, "on", 2)) pci_realloc_enable = user_enabled; } -static bool __init pci_realloc_enabled(enum enable_type enable) +static bool pci_realloc_enabled(enum enable_type enable) { return enable >= user_enabled; } #if defined(CONFIG_PCI_IOV) && defined(CONFIG_PCI_REALLOC_ENABLE_AUTO) -static int __init iov_resources_unassigned(struct pci_dev *dev, void *data) +static int iov_resources_unassigned(struct pci_dev *dev, void *data) { int i; bool *unassigned = data; @@ -1368,7 +1368,7 @@ static int __init iov_resources_unassigned(struct pci_dev *dev, void *data) return 0; } -static enum enable_type __init pci_realloc_detect(struct pci_bus *bus, +static enum enable_type pci_realloc_detect(struct pci_bus *bus, enum enable_type enable_local) { bool unassigned = false; @@ -1383,7 +1383,7 @@ static enum enable_type __init pci_realloc_detect(struct pci_bus *bus, return enable_local; } #else -static enum enable_type __init pci_realloc_detect(struct pci_bus *bus, +static enum enable_type pci_realloc_detect(struct pci_bus *bus, enum enable_type enable_local) { return enable_local; @@ -1395,8 +1395,7 @@ static enum enable_type __init pci_realloc_detect(struct pci_bus *bus, * second and later try will clear small leaf bridge res * will stop till to the max deepth if can not find good one */ -static void __init -pci_assign_unassigned_root_bus_resources(struct pci_bus *bus) +static void pci_assign_unassigned_root_bus_resources(struct pci_bus *bus) { LIST_HEAD(realloc_head); /* list of resources that want additional resources */ From 39772038ea93e85ea4f1307ec9c1f48a063d89a0 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Mon, 22 Jul 2013 14:37:18 -0700 Subject: [PATCH 0666/3400] PCI: Assign resources for hot-added host bridge more aggressively When hot-adding an ACPI host bridge, use pci_assign_unassigned_root_bus_resources() instead of pci_assign_unassigned_bus_resources(). The former is more aggressive and will release and reassign existing resources if necessary. This is safe at hot-add time because no drivers are bound to devices below the new host bridge yet. [bhelgaas: changelog, split __init changes out for reviewability] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/acpi/pci_root.c | 2 +- drivers/pci/setup-bus.c | 2 +- include/linux/pci.h | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index faa1d29c0261..ce04eb28e029 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -526,7 +526,7 @@ static int acpi_pci_root_add(struct acpi_device *device, if (system_state != SYSTEM_BOOTING) { pcibios_resource_survey_bus(root->bus); - pci_assign_unassigned_bus_resources(root->bus); + pci_assign_unassigned_root_bus_resources(root->bus); } pci_bus_add_devices(root->bus); diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 8d1e654256a8..94b777d108bb 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1395,7 +1395,7 @@ static enum enable_type pci_realloc_detect(struct pci_bus *bus, * second and later try will clear small leaf bridge res * will stop till to the max deepth if can not find good one */ -static void pci_assign_unassigned_root_bus_resources(struct pci_bus *bus) +void pci_assign_unassigned_root_bus_resources(struct pci_bus *bus) { LIST_HEAD(realloc_head); /* list of resources that want additional resources */ diff --git a/include/linux/pci.h b/include/linux/pci.h index 8cd1e6f30acd..e494c90a00d1 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1003,6 +1003,7 @@ int pci_claim_resource(struct pci_dev *, int); void pci_assign_unassigned_resources(void); void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge); void pci_assign_unassigned_bus_resources(struct pci_bus *bus); +void pci_assign_unassigned_root_bus_resources(struct pci_bus *bus); void pdev_enable_device(struct pci_dev *); int pci_enable_resources(struct pci_dev *, int mask); void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *), From d102e78f7035f2d6896ced598122b878afd1c352 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 1 Jul 2013 11:23:24 +0300 Subject: [PATCH 0667/3400] usb: class: cdc-acm: be careful with bInterval bInterval must be on the range 1 - 16, if we want to pass the maximum allowed, we should be passing 16 Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 9f49bfe4c6f4..3e7560f004f8 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1295,7 +1295,7 @@ skip_countries: usb_rcvintpipe(usb_dev, epctrl->bEndpointAddress), acm->ctrl_buffer, ctrlsize, acm_ctrl_irq, acm, /* works around buggy devices */ - epctrl->bInterval ? epctrl->bInterval : 0xff); + epctrl->bInterval ? epctrl->bInterval : 16); acm->ctrlurb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; acm->ctrlurb->transfer_dma = acm->ctrl_dma; From afb8aae89890e65bd4b828de38bd430d4f31caa8 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 1 Jul 2013 11:23:23 +0300 Subject: [PATCH 0668/3400] usb: atm: speedtch: be careful with bInterval bInterval must be on the range 1 - 16, if we want to pass the maximum allowed, we should be passing 16. Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/speedtch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c index 807627b36cc8..69461d653972 100644 --- a/drivers/usb/atm/speedtch.c +++ b/drivers/usb/atm/speedtch.c @@ -888,7 +888,7 @@ static int speedtch_bind(struct usbatm_data *usbatm, usb_fill_int_urb(instance->int_urb, usb_dev, usb_rcvintpipe(usb_dev, ENDPOINT_INT), instance->int_data, sizeof(instance->int_data), - speedtch_handle_int, instance, 50); + speedtch_handle_int, instance, 16); else usb_dbg(usbatm, "%s: no memory for interrupt urb!\n", __func__); From 42189d854f174e7b29e0fdb4da9984ba63126a92 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 2 Jul 2013 10:50:15 +0300 Subject: [PATCH 0669/3400] usb: clamp bInterval to allowed range bInterval must be within the range 1 - 16 when running at High/Super speed, and within the range 1 - 255 when running at Full/Low speed. In order to catch drivers passing a too large bInterval on Super/High speed scenarios (thus overflowing urb->interval), let's clamp() the argument to the allowed ranges. Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- include/linux/usb.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/include/linux/usb.h b/include/linux/usb.h index e99b2a114af4..eb4252a0da7e 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -1547,10 +1547,16 @@ static inline void usb_fill_int_urb(struct urb *urb, urb->transfer_buffer_length = buffer_length; urb->complete = complete_fn; urb->context = context; - if (dev->speed == USB_SPEED_HIGH || dev->speed == USB_SPEED_SUPER) + + if (dev->speed == USB_SPEED_HIGH || dev->speed == USB_SPEED_SUPER) { + /* make sure interval is within allowed range */ + interval = clamp(interval, 1, 16); + urb->interval = 1 << (interval - 1); - else + } else { urb->interval = interval; + } + urb->start_frame = -1; } From 1353aa53851e3bc7f2c6365753d9c2783c34f882 Mon Sep 17 00:00:00 2001 From: Manu Gautam Date: Tue, 2 Jul 2013 20:13:51 -0700 Subject: [PATCH 0670/3400] usb: misc: EHSET Test Fixture device driver for host compliance An Embedded Host High-Speed Electrical Test (EHSET) test fixture is used to initiate test modes on a host controller in order to perform the high speed electrical testing procedure for USB-IF compliance. When this test fixture is connected to a host, it can enumerate as one of several selectable VID/PID pairs, each corresponding to one of the following test modes: * TEST_SE0_NAK * TEST_J * TEST_K * TEST_PACKET * HS_HOST_PORT_SUSPEND_RESUME * SINGLE_STEP_GET_DEV_DESC * SINGLE_STEP_SET_FEATURE The USB EHSET procedure can be found here: http://www.usb.org/developers/onthego/EHSET_v1.01.pdf Signed-off-by: Manu Gautam [jackp@codeaurora.org: imported from commit 073c9409 on codeaurora.org; minor cleanup and updated author email] Signed-off-by: Jack Pham Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/Kconfig | 13 ++++ drivers/usb/misc/Makefile | 1 + drivers/usb/misc/ehset.c | 134 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 148 insertions(+) create mode 100644 drivers/usb/misc/ehset.c diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index a51e7d6afda9..ca91420f5c21 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -200,6 +200,19 @@ config USB_TEST See for more information, including sample test device firmware and "how to use it". +config USB_EHSET_TEST_FIXTURE + tristate "USB EHSET Test Fixture driver" + help + Say Y here if you want to support the special test fixture device + used for the USB-IF Embedded Host High-Speed Electrical Test procedure. + + When the test fixture is connected, it can enumerate as one of several + VID/PID pairs. This driver then initiates a corresponding test mode on + the downstream port to which the test fixture is attached. + + See for more + information. + config USB_ISIGHTFW tristate "iSight firmware loading support" select FW_LOADER diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile index 5a896f319118..e748fd5dbe94 100644 --- a/drivers/usb/misc/Makefile +++ b/drivers/usb/misc/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_USB_LED) += usbled.o obj-$(CONFIG_USB_LEGOTOWER) += legousbtower.o obj-$(CONFIG_USB_RIO500) += rio500.o obj-$(CONFIG_USB_TEST) += usbtest.o +obj-$(CONFIG_USB_EHSET_TEST_FIXTURE) += ehset.o obj-$(CONFIG_USB_TRANCEVIBRATOR) += trancevibrator.o obj-$(CONFIG_USB_USS720) += uss720.o obj-$(CONFIG_USB_SEVSEG) += usbsevseg.o diff --git a/drivers/usb/misc/ehset.c b/drivers/usb/misc/ehset.c new file mode 100644 index 000000000000..d2864b3f41fe --- /dev/null +++ b/drivers/usb/misc/ehset.c @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2010-2013, The Linux Foundation. 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 and + * only 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. + */ + +#include +#include +#include +#include +#include +#include + +#define TEST_SE0_NAK_PID 0x0101 +#define TEST_J_PID 0x0102 +#define TEST_K_PID 0x0103 +#define TEST_PACKET_PID 0x0104 +#define TEST_HS_HOST_PORT_SUSPEND_RESUME 0x0106 +#define TEST_SINGLE_STEP_GET_DEV_DESC 0x0107 +#define TEST_SINGLE_STEP_SET_FEATURE 0x0108 + +static int ehset_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + int ret = -EINVAL; + struct usb_device *dev = interface_to_usbdev(intf); + struct usb_device *hub_udev = dev->parent; + struct usb_device_descriptor *buf; + u8 portnum = dev->portnum; + u16 test_pid = le16_to_cpu(dev->descriptor.idProduct); + + switch (test_pid) { + case TEST_SE0_NAK_PID: + ret = usb_control_msg(hub_udev, usb_sndctrlpipe(hub_udev, 0), + USB_REQ_SET_FEATURE, USB_RT_PORT, + USB_PORT_FEAT_TEST, + (TEST_SE0_NAK << 8) | portnum, + NULL, 0, 1000); + break; + case TEST_J_PID: + ret = usb_control_msg(hub_udev, usb_sndctrlpipe(hub_udev, 0), + USB_REQ_SET_FEATURE, USB_RT_PORT, + USB_PORT_FEAT_TEST, + (TEST_J << 8) | portnum, + NULL, 0, 1000); + break; + case TEST_K_PID: + ret = usb_control_msg(hub_udev, usb_sndctrlpipe(hub_udev, 0), + USB_REQ_SET_FEATURE, USB_RT_PORT, + USB_PORT_FEAT_TEST, + (TEST_K << 8) | portnum, + NULL, 0, 1000); + break; + case TEST_PACKET_PID: + ret = usb_control_msg(hub_udev, usb_sndctrlpipe(hub_udev, 0), + USB_REQ_SET_FEATURE, USB_RT_PORT, + USB_PORT_FEAT_TEST, + (TEST_PACKET << 8) | portnum, + NULL, 0, 1000); + break; + case TEST_HS_HOST_PORT_SUSPEND_RESUME: + /* Test: wait for 15secs -> suspend -> 15secs delay -> resume */ + msleep(15 * 1000); + ret = usb_control_msg(hub_udev, usb_sndctrlpipe(hub_udev, 0), + USB_REQ_SET_FEATURE, USB_RT_PORT, + USB_PORT_FEAT_SUSPEND, portnum, + NULL, 0, 1000); + if (ret < 0) + break; + + msleep(15 * 1000); + ret = usb_control_msg(hub_udev, usb_sndctrlpipe(hub_udev, 0), + USB_REQ_CLEAR_FEATURE, USB_RT_PORT, + USB_PORT_FEAT_SUSPEND, portnum, + NULL, 0, 1000); + break; + case TEST_SINGLE_STEP_GET_DEV_DESC: + /* Test: wait for 15secs -> GetDescriptor request */ + msleep(15 * 1000); + buf = kmalloc(USB_DT_DEVICE_SIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, + USB_DT_DEVICE << 8, 0, + buf, USB_DT_DEVICE_SIZE, + USB_CTRL_GET_TIMEOUT); + kfree(buf); + break; + case TEST_SINGLE_STEP_SET_FEATURE: + /* unsupported for now */ + default: + dev_err(&intf->dev, "%s: unsupported PID: 0x%x\n", + __func__, test_pid); + } + + return (ret < 0) ? ret : 0; +} + +static void ehset_disconnect(struct usb_interface *intf) +{ +} + +static const struct usb_device_id ehset_id_table[] = { + { USB_DEVICE(0x1a0a, TEST_SE0_NAK_PID) }, + { USB_DEVICE(0x1a0a, TEST_J_PID) }, + { USB_DEVICE(0x1a0a, TEST_K_PID) }, + { USB_DEVICE(0x1a0a, TEST_PACKET_PID) }, + { USB_DEVICE(0x1a0a, TEST_HS_HOST_PORT_SUSPEND_RESUME) }, + { USB_DEVICE(0x1a0a, TEST_SINGLE_STEP_GET_DEV_DESC) }, + { USB_DEVICE(0x1a0a, TEST_SINGLE_STEP_SET_FEATURE) }, + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, ehset_id_table); + +static struct usb_driver ehset_driver = { + .name = "usb_ehset_test", + .probe = ehset_probe, + .disconnect = ehset_disconnect, + .id_table = ehset_id_table, +}; + +module_usb_driver(ehset_driver); + +MODULE_DESCRIPTION("USB Driver for EHSET Test Fixture"); +MODULE_LICENSE("GPL v2"); From c4b51a431561f0bacc1740aa27f080bf95c4d6c7 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 11 Jul 2013 14:58:23 -0400 Subject: [PATCH 0671/3400] USB: remove redundant "#if" This patch removes a redundant nested "#ifdef CONFIG_PM" from the hub driver. It also adds a label to the "#endif" line corresponding to the outer "#ifdef CONFIG_PM". Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 4191db32f12c..f735f6bc929c 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2829,7 +2829,6 @@ void usb_enable_ltm(struct usb_device *udev) } EXPORT_SYMBOL_GPL(usb_enable_ltm); -#ifdef CONFIG_PM /* * usb_disable_function_remotewakeup - disable usb3.0 * device's function remote wakeup @@ -3249,8 +3248,6 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) return status; } -#endif /* CONFIG_PM */ - #ifdef CONFIG_PM_RUNTIME /* caller has locked udev */ @@ -3811,7 +3808,8 @@ EXPORT_SYMBOL_GPL(usb_disable_ltm); void usb_enable_ltm(struct usb_device *udev) { } EXPORT_SYMBOL_GPL(usb_enable_ltm); -#endif + +#endif /* CONFIG_PM */ /* USB 2.0 spec, 7.1.7.3 / fig 7-29: From aaf6b52d50f85ed792c9c8987f5169f3dce2adea Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Mon, 22 Jul 2013 15:04:50 +0300 Subject: [PATCH 0672/3400] USB: host: Use usb_hcd_platform_shutdown() wherever possible Most HCD drivers are doing the same thing in their ".shutdown" callback so it makes sense to use the generic usb_hcd_platform_shutdown() handler there. Signed-off-by: Roger Quadros Reviewed-by: Felipe Balbi Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-grlib.c | 11 +---------- drivers/usb/host/ehci-mxc.c | 10 +--------- drivers/usb/host/ehci-omap.c | 10 +--------- drivers/usb/host/ehci-ppc-of.c | 11 +---------- drivers/usb/host/ehci-s5p.c | 10 +--------- drivers/usb/host/ehci-xilinx-of.c | 17 +---------------- drivers/usb/host/ohci-omap3.c | 10 +--------- drivers/usb/host/ohci-ppc-of.c | 11 +---------- 8 files changed, 8 insertions(+), 82 deletions(-) diff --git a/drivers/usb/host/ehci-grlib.c b/drivers/usb/host/ehci-grlib.c index a77bd8dc33f4..83ab51af250f 100644 --- a/drivers/usb/host/ehci-grlib.c +++ b/drivers/usb/host/ehci-grlib.c @@ -167,15 +167,6 @@ static int ehci_hcd_grlib_remove(struct platform_device *op) } -static void ehci_hcd_grlib_shutdown(struct platform_device *op) -{ - struct usb_hcd *hcd = platform_get_drvdata(op); - - if (hcd->driver->shutdown) - hcd->driver->shutdown(hcd); -} - - static const struct of_device_id ehci_hcd_grlib_of_match[] = { { .name = "GAISLER_EHCI", @@ -191,7 +182,7 @@ MODULE_DEVICE_TABLE(of, ehci_hcd_grlib_of_match); static struct platform_driver ehci_grlib_driver = { .probe = ehci_hcd_grlib_probe, .remove = ehci_hcd_grlib_remove, - .shutdown = ehci_hcd_grlib_shutdown, + .shutdown = usb_hcd_platform_shutdown, .driver = { .name = "grlib-ehci", .owner = THIS_MODULE, diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c index e4c34ac386c0..030b53958845 100644 --- a/drivers/usb/host/ehci-mxc.c +++ b/drivers/usb/host/ehci-mxc.c @@ -197,20 +197,12 @@ static int ehci_mxc_drv_remove(struct platform_device *pdev) return 0; } -static void ehci_mxc_drv_shutdown(struct platform_device *pdev) -{ - struct usb_hcd *hcd = platform_get_drvdata(pdev); - - if (hcd->driver->shutdown) - hcd->driver->shutdown(hcd); -} - MODULE_ALIAS("platform:mxc-ehci"); static struct platform_driver ehci_mxc_driver = { .probe = ehci_mxc_drv_probe, .remove = ehci_mxc_drv_remove, - .shutdown = ehci_mxc_drv_shutdown, + .shutdown = usb_hcd_platform_shutdown, .driver = { .name = "mxc-ehci", }, diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index 9bd7dfe3315b..4384d07115d1 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -278,14 +278,6 @@ static int ehci_hcd_omap_remove(struct platform_device *pdev) return 0; } -static void ehci_hcd_omap_shutdown(struct platform_device *pdev) -{ - struct usb_hcd *hcd = dev_get_drvdata(&pdev->dev); - - if (hcd->driver->shutdown) - hcd->driver->shutdown(hcd); -} - static const struct of_device_id omap_ehci_dt_ids[] = { { .compatible = "ti,ehci-omap" }, { } @@ -296,7 +288,7 @@ MODULE_DEVICE_TABLE(of, omap_ehci_dt_ids); static struct platform_driver ehci_hcd_omap_driver = { .probe = ehci_hcd_omap_probe, .remove = ehci_hcd_omap_remove, - .shutdown = ehci_hcd_omap_shutdown, + .shutdown = usb_hcd_platform_shutdown, /*.suspend = ehci_hcd_omap_suspend, */ /*.resume = ehci_hcd_omap_resume, */ .driver = { diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c index 86da09c0f8d0..932293fa32de 100644 --- a/drivers/usb/host/ehci-ppc-of.c +++ b/drivers/usb/host/ehci-ppc-of.c @@ -215,15 +215,6 @@ static int ehci_hcd_ppc_of_remove(struct platform_device *op) } -static void ehci_hcd_ppc_of_shutdown(struct platform_device *op) -{ - struct usb_hcd *hcd = platform_get_drvdata(op); - - if (hcd->driver->shutdown) - hcd->driver->shutdown(hcd); -} - - static const struct of_device_id ehci_hcd_ppc_of_match[] = { { .compatible = "usb-ehci", @@ -236,7 +227,7 @@ MODULE_DEVICE_TABLE(of, ehci_hcd_ppc_of_match); static struct platform_driver ehci_hcd_ppc_of_driver = { .probe = ehci_hcd_ppc_of_probe, .remove = ehci_hcd_ppc_of_remove, - .shutdown = ehci_hcd_ppc_of_shutdown, + .shutdown = usb_hcd_platform_shutdown, .driver = { .name = "ppc-of-ehci", .owner = THIS_MODULE, diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c index 7cc26e621aa7..aba645bd4866 100644 --- a/drivers/usb/host/ehci-s5p.c +++ b/drivers/usb/host/ehci-s5p.c @@ -220,14 +220,6 @@ static int s5p_ehci_remove(struct platform_device *pdev) return 0; } -static void s5p_ehci_shutdown(struct platform_device *pdev) -{ - struct usb_hcd *hcd = platform_get_drvdata(pdev); - - if (hcd->driver->shutdown) - hcd->driver->shutdown(hcd); -} - #ifdef CONFIG_PM static int s5p_ehci_suspend(struct device *dev) { @@ -297,7 +289,7 @@ MODULE_DEVICE_TABLE(of, exynos_ehci_match); static struct platform_driver s5p_ehci_driver = { .probe = s5p_ehci_probe, .remove = s5p_ehci_remove, - .shutdown = s5p_ehci_shutdown, + .shutdown = usb_hcd_platform_shutdown, .driver = { .name = "s5p-ehci", .owner = THIS_MODULE, diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c index 35c7f90384a6..eba962e6ebfb 100644 --- a/drivers/usb/host/ehci-xilinx-of.c +++ b/drivers/usb/host/ehci-xilinx-of.c @@ -220,21 +220,6 @@ static int ehci_hcd_xilinx_of_remove(struct platform_device *op) return 0; } -/** - * ehci_hcd_xilinx_of_shutdown - shutdown the hcd - * @op: pointer to platform_device structure that is to be removed - * - * Properly shutdown the hcd, call driver's shutdown routine. - */ -static void ehci_hcd_xilinx_of_shutdown(struct platform_device *op) -{ - struct usb_hcd *hcd = platform_get_drvdata(op); - - if (hcd->driver->shutdown) - hcd->driver->shutdown(hcd); -} - - static const struct of_device_id ehci_hcd_xilinx_of_match[] = { {.compatible = "xlnx,xps-usb-host-1.00.a",}, {}, @@ -244,7 +229,7 @@ MODULE_DEVICE_TABLE(of, ehci_hcd_xilinx_of_match); static struct platform_driver ehci_hcd_xilinx_of_driver = { .probe = ehci_hcd_xilinx_of_probe, .remove = ehci_hcd_xilinx_of_remove, - .shutdown = ehci_hcd_xilinx_of_shutdown, + .shutdown = usb_hcd_platform_shutdown, .driver = { .name = "xilinx-of-ehci", .owner = THIS_MODULE, diff --git a/drivers/usb/host/ohci-omap3.c b/drivers/usb/host/ohci-omap3.c index 8f713571a0b7..a09af26f69ed 100644 --- a/drivers/usb/host/ohci-omap3.c +++ b/drivers/usb/host/ohci-omap3.c @@ -231,14 +231,6 @@ static int ohci_hcd_omap3_remove(struct platform_device *pdev) return 0; } -static void ohci_hcd_omap3_shutdown(struct platform_device *pdev) -{ - struct usb_hcd *hcd = dev_get_drvdata(&pdev->dev); - - if (hcd->driver->shutdown) - hcd->driver->shutdown(hcd); -} - static const struct of_device_id omap_ohci_dt_ids[] = { { .compatible = "ti,ohci-omap3" }, { } @@ -249,7 +241,7 @@ MODULE_DEVICE_TABLE(of, omap_ohci_dt_ids); static struct platform_driver ohci_hcd_omap3_driver = { .probe = ohci_hcd_omap3_probe, .remove = ohci_hcd_omap3_remove, - .shutdown = ohci_hcd_omap3_shutdown, + .shutdown = usb_hcd_platform_shutdown, .driver = { .name = "ohci-omap3", .of_match_table = omap_ohci_dt_ids, diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c index 8294e2fcc2f6..75f5a1e2f01e 100644 --- a/drivers/usb/host/ohci-ppc-of.c +++ b/drivers/usb/host/ohci-ppc-of.c @@ -200,15 +200,6 @@ static int ohci_hcd_ppc_of_remove(struct platform_device *op) return 0; } -static void ohci_hcd_ppc_of_shutdown(struct platform_device *op) -{ - struct usb_hcd *hcd = platform_get_drvdata(op); - - if (hcd->driver->shutdown) - hcd->driver->shutdown(hcd); -} - - static const struct of_device_id ohci_hcd_ppc_of_match[] = { #ifdef CONFIG_USB_OHCI_HCD_PPC_OF_BE { @@ -243,7 +234,7 @@ MODULE_DEVICE_TABLE(of, ohci_hcd_ppc_of_match); static struct platform_driver ohci_hcd_ppc_of_driver = { .probe = ohci_hcd_ppc_of_probe, .remove = ohci_hcd_ppc_of_remove, - .shutdown = ohci_hcd_ppc_of_shutdown, + .shutdown = usb_hcd_platform_shutdown, .driver = { .name = "ppc-of-ohci", .owner = THIS_MODULE, From 5dc50c357d5ce8f78e148d20a38e4e66b12d550f Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 12 Jul 2013 10:04:18 +0200 Subject: [PATCH 0673/3400] usbfs: Allow printer class 'get_device_id' without needing to claim the intf For certain (HP) printers the printer device_id does not only contain a static part identifying the printer, but it also contains a dynamic part giving printer status, ink level, etc. To get to this info various userspace utilities need to be able to make a printer class 'get_device_id' request without first claiming the interface (as that is in use for the actual printer driver). Since the printer class 'get_device_id' request does not change interface settings in anyway, allowing this without claiming the interface should not cause any issues. CC: Sanjay Kumar CC: Alan Stern Signed-off-by: Hans de Goede Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 05986507b585..737e3c19967b 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -725,15 +725,15 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, /* * check for the special corner case 'get_device_id' in the printer - * class specification, where wIndex is (interface << 8 | altsetting) - * instead of just interface + * class specification, which we always want to allow as it is used + * to query things like ink level, etc. */ if (requesttype == 0xa1 && request == 0) { alt_setting = usb_find_alt_setting(ps->dev->actconfig, index >> 8, index & 0xff); if (alt_setting && alt_setting->desc.bInterfaceClass == USB_CLASS_PRINTER) - index >>= 8; + return 0; } index &= 0xff; From 92f78ddb10eab664c8934f0f3a9f284167ac45f9 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 15 Jul 2013 11:59:40 +0300 Subject: [PATCH 0674/3400] usbtmc: remove trailing spaces Recent patch series introduces few trailing spaces. This patch removes them. No functional change. Signed-off-by: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usbtmc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 609dbc2f7151..92eaf9d6de8b 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -554,14 +554,14 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, if (remaining > n_characters) remaining = n_characters; /* Remove padding if it exists */ - if (actual > remaining) + if (actual > remaining) actual = remaining; } else { if (this_part > n_characters) this_part = n_characters; /* Remove padding if it exists */ - if (actual > this_part) + if (actual > this_part) actual = this_part; } @@ -585,7 +585,7 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, done += actual; } else { - if (actual > remaining) + if (actual > remaining) actual = remaining; remaining -= actual; From f4d844cb6c073998db0c7fe3d76c6c070333054e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 15 Jul 2013 11:59:42 +0300 Subject: [PATCH 0675/3400] usbtmc: call pr_err instead of plain printk Additionally remove useless label. Signed-off-by: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usbtmc.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 92eaf9d6de8b..21114ab99d96 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -19,6 +19,8 @@ * http://www.gnu.org/copyleft/gpl.html. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -130,10 +132,8 @@ static int usbtmc_open(struct inode *inode, struct file *filp) 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; + pr_err("can not find device for minor %d", iminor(inode)); + return -ENODEV; } data = usb_get_intfdata(intf); @@ -142,7 +142,6 @@ static int usbtmc_open(struct inode *inode, struct file *filp) /* Store pointer in file structure's private data field */ filp->private_data = data; -exit: return retval; } From bbf4976e7715da4a3e3599a500eb20d6be8b5046 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 15 Jul 2013 11:59:43 +0300 Subject: [PATCH 0676/3400] usbtmc: remove redundant braces There is a few cases where braces are not needed. This patch removes unnecessary '& 255' pieces as well when lvalue type is u8. Signed-off-by: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usbtmc.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 21114ab99d96..d683f90a505b 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -393,12 +393,12 @@ static int send_request_dev_dep_msg_in(struct usbtmc_device_data *data, size_t t */ buffer[0] = 2; buffer[1] = data->bTag; - buffer[2] = ~(data->bTag); + buffer[2] = ~data->bTag; buffer[3] = 0; /* Reserved */ - buffer[4] = (transfer_size) & 255; - buffer[5] = ((transfer_size) >> 8) & 255; - buffer[6] = ((transfer_size) >> 16) & 255; - buffer[7] = ((transfer_size) >> 24) & 255; + buffer[4] = transfer_size >> 0; + buffer[5] = transfer_size >> 8; + buffer[6] = transfer_size >> 16; + buffer[7] = transfer_size >> 24; buffer[8] = data->TermCharEnabled * 2; /* Use term character? */ buffer[9] = data->TermChar; @@ -417,7 +417,7 @@ static int send_request_dev_dep_msg_in(struct usbtmc_device_data *data, size_t t /* Increment bTag -- and increment again if zero */ data->bTag++; if (!data->bTag) - (data->bTag)++; + data->bTag++; if (retval < 0) { dev_err(&data->intf->dev, "usb_bulk_msg in send_request_dev_dep_msg_in() returned %d\n", retval); @@ -472,7 +472,7 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, done = 0; while (remaining > 0) { - if (!(data->rigol_quirk)) { + if (!data->rigol_quirk) { dev_dbg(dev, "usb_bulk_msg_in: remaining(%zu), count(%zu)\n", remaining, count); if (remaining > USBTMC_SIZE_IOBUFFER - USBTMC_HEADER_SIZE - 3) @@ -509,7 +509,7 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, } /* Parse header in first packet */ - if ((done == 0) || (!(data->rigol_quirk))) { + if ((done == 0) || !data->rigol_quirk) { /* Sanity checks for the header */ if (actual < USBTMC_HEADER_SIZE) { dev_err(dev, "Device sent too small first packet: %u < %u\n", actual, USBTMC_HEADER_SIZE); @@ -569,7 +569,7 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, remaining -= actual; /* Terminate if end-of-message bit received from device */ - if ((buffer[8] & 0x01) && (actual >= n_characters)) + if ((buffer[8] & 0x01) && (actual >= n_characters)) remaining = 0; dev_dbg(dev, "Bulk-IN header: remaining(%zu), buf(%p), buffer(%p) done(%zu)\n", remaining,buf,buffer,done); @@ -650,12 +650,12 @@ static ssize_t usbtmc_write(struct file *filp, const char __user *buf, /* Setup IO buffer for DEV_DEP_MSG_OUT message */ buffer[0] = 1; buffer[1] = data->bTag; - buffer[2] = ~(data->bTag); + buffer[2] = ~data->bTag; buffer[3] = 0; /* Reserved */ - buffer[4] = this_part & 255; - buffer[5] = (this_part >> 8) & 255; - buffer[6] = (this_part >> 16) & 255; - buffer[7] = (this_part >> 24) & 255; + buffer[4] = this_part >> 0; + buffer[5] = this_part >> 8; + buffer[6] = this_part >> 16; + buffer[7] = this_part >> 24; /* buffer[8] is set above... */ buffer[9] = 0; /* Reserved */ buffer[10] = 0; /* Reserved */ From e6c7efdcb76f11b04e3d3f71c8d764ab75c9423b Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 15 Jul 2013 11:59:41 +0300 Subject: [PATCH 0677/3400] usbtmc: convert to devm_kzalloc kfree(data) will be called implicitly. Signed-off-by: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usbtmc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index d683f90a505b..60dd8918aeb9 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -121,7 +121,6 @@ static void usbtmc_delete(struct kref *kref) struct usbtmc_device_data *data = to_usbtmc_data(kref); usb_put_dev(data->usb_dev); - kfree(data); } static int usbtmc_open(struct inode *inode, struct file *filp) @@ -1101,7 +1100,7 @@ static int usbtmc_probe(struct usb_interface *intf, dev_dbg(&intf->dev, "%s called\n", __func__); - data = kmalloc(sizeof(struct usbtmc_device_data), GFP_KERNEL); + data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL); if (!data) { dev_err(&intf->dev, "Unable to allocate kernel memory\n"); return -ENOMEM; From 140983c283b302167b387646218a97f112cc0c03 Mon Sep 17 00:00:00 2001 From: Chen Wang Date: Fri, 19 Jul 2013 10:15:18 +0800 Subject: [PATCH 0678/3400] USB: usb-skeleton.c: add retry for nonblocking read Updated skel_read() in usb-skeleton.c. When there is no data in the buffer, we would allow retry for both blocking and nonblocking cases. Original logic give retry only for blocking case. Actually we can also allow retry for nonblocking case. This will reuse the existing retry logic and handle the return of -EAGAIN in one place. Also if the data to be read is short and can be retrieved in quick time, we can also give a chance for nonblocking case and may catch the data and copy it back to userspace in one read() call too. Signed-off-by: Chen Wang Signed-off-by: Greg Kroah-Hartman --- drivers/usb/usb-skeleton.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c index 7ed3b039dbe8..ff97652343a3 100644 --- a/drivers/usb/usb-skeleton.c +++ b/drivers/usb/usb-skeleton.c @@ -325,9 +325,8 @@ retry: rv = skel_do_read_io(dev, count); if (rv < 0) goto exit; - else if (!(file->f_flags & O_NONBLOCK)) + else goto retry; - rv = -EAGAIN; } exit: mutex_unlock(&dev->io_mutex); From a772bbeeea8bc8b5218b8c2171c23a331b730ac9 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 25 Jul 2013 12:27:12 +0530 Subject: [PATCH 0679/3400] staging: lustre: o2iblnd: Remove duplicate inclusion of header file Removed the header files included twice. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h index e4626bf82fc7..938df0cf8c64 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h @@ -53,7 +53,6 @@ #include #include #include -#include #include #include #include From 34d739605e13ac129628e3cd0129184303e07262 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 25 Jul 2013 12:27:13 +0530 Subject: [PATCH 0680/3400] staging: lustre: socklnd: Remove duplicate inclusion of header files Removed the header files included twice. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.h b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.h index 384eb7ca1c82..1cfc1b168bed 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.h +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.h @@ -57,11 +57,9 @@ #include #include #include -#include #include #include #include -#include #include #include From 86664eb13e8fef0a4b2c712a21e854335f22bb3f Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 25 Jul 2013 12:27:14 +0530 Subject: [PATCH 0681/3400] staging: lustre: obd: Remove duplicate inclusion of header file Removed the header file included twice. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/obd.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 094eb96515dc..003466498afe 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -52,7 +52,6 @@ #include #include #include -#include #include #include #include From 6a4b8447cfae56bef3e3c4cc1b50d8b3c17e4b26 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 25 Jul 2013 12:27:15 +0530 Subject: [PATCH 0682/3400] staging: lustre: linux-debug: Remove duplicate inclusion of header file Removed the header files included twice. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c index 0069b5ea1c28..6afb35073141 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c @@ -48,11 +48,8 @@ #include #include #include -#include #include - #include -#include #include #include From 03f278994c04e0ed4e7c975565e8057835eb037a Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 25 Jul 2013 12:27:16 +0530 Subject: [PATCH 0683/3400] staging: lustre: libcfs: Remove duplicate inclusion of header file Removed the header files included twice. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c index 522b28e99e41..80a9fab9b9c1 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-proc.c @@ -54,9 +54,7 @@ #include #include -#include #include -#include #include #include From 66270ce4e1dc2f129b79db0107eec09c5b37d302 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 25 Jul 2013 12:27:17 +0530 Subject: [PATCH 0684/3400] staging: lustre: linux-tcpip: Remove duplicate header file inclusion Removed the header files included twice. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/libcfs/linux/linux-tcpip.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-tcpip.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-tcpip.c index f5e78b54b3e7..e6069d78af6b 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-tcpip.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-tcpip.c @@ -35,7 +35,6 @@ */ #define DEBUG_SUBSYSTEM S_LNET -#include #include #include From 2950b2416fd2f38545dde9444878c7982d8fca19 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 25 Jul 2013 12:27:18 +0530 Subject: [PATCH 0685/3400] staging: lustre: Remove duplicate header file inclusion in dir.c Removed the header files included twice. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/dir.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 002b37448682..2ca8c4534bd5 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -48,7 +48,6 @@ #define DEBUG_SUBSYSTEM S_LLITE -#include #include #include #include From 0ad531db6c83e277a86bdf6e5392a297cbeedb73 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 25 Jul 2013 12:27:19 +0530 Subject: [PATCH 0686/3400] staging: lustre: Remove duplicate header file inclusion in llite_mmap.c Removed the header files included twice. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/llite_mmap.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/llite_mmap.c b/drivers/staging/lustre/lustre/llite/llite_mmap.c index a4061ee15b62..b59cbd704ab6 100644 --- a/drivers/staging/lustre/lustre/llite/llite_mmap.c +++ b/drivers/staging/lustre/lustre/llite/llite_mmap.c @@ -43,9 +43,6 @@ #include #include -#include -#include -#include #include #define DEBUG_SUBSYSTEM S_LLITE From f75b7d2d6901a8c03bfbbd3422c747ff6c53bdcc Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 25 Jul 2013 12:27:20 +0530 Subject: [PATCH 0687/3400] staging: lustre: Remove duplicate header file inclusion in lloop.c Removed the header files included twice. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/lloop.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/llite/lloop.c b/drivers/staging/lustre/lustre/llite/lloop.c index 9d4c17ea8808..e063efc23af9 100644 --- a/drivers/staging/lustre/lustre/llite/lloop.c +++ b/drivers/staging/lustre/lustre/llite/lloop.c @@ -99,7 +99,6 @@ #include #include #include -#include #include #include From ee49576196ac409ac87c36eee4fdc7f5de2ec269 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 25 Jul 2013 12:27:21 +0530 Subject: [PATCH 0688/3400] staging: lustre: Remove duplicate header file inclusion in rw.c Removed the header files included twice. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/rw.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/rw.c b/drivers/staging/lustre/lustre/llite/rw.c index 43b5f0d2b72a..ab4e95c63554 100644 --- a/drivers/staging/lustre/lustre/llite/rw.c +++ b/drivers/staging/lustre/lustre/llite/rw.c @@ -48,9 +48,6 @@ #include #include -#include -#include -#include #include /* current_is_kswapd() */ #include From 1fabbd6f65eada35e6bcb088ff8bba48c22e1e07 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 25 Jul 2013 12:27:22 +0530 Subject: [PATCH 0689/3400] staging: lustre: Remove duplicate header file inclusion in rw26.c Removed the header files included twice. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/rw26.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/rw26.c b/drivers/staging/lustre/lustre/llite/rw26.c index 97088e6ddea0..256ee6356b31 100644 --- a/drivers/staging/lustre/lustre/llite/rw26.c +++ b/drivers/staging/lustre/lustre/llite/rw26.c @@ -51,9 +51,6 @@ #include #include #include -#include -#include -#include #include #define DEBUG_SUBSYSTEM S_LLITE From 0c050588a26eac43b4e875f21eb3926fa1c1b5d7 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 25 Jul 2013 12:27:23 +0530 Subject: [PATCH 0690/3400] staging: lustre: Remove duplicate header file inclusion in lmv_fld.c Removed the header file included twice. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/lmv/lmv_fld.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/lmv/lmv_fld.c b/drivers/staging/lustre/lustre/lmv/lmv_fld.c index a4805aefa684..08a5b69dc90d 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_fld.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_fld.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include From c92b5ea0af2816e70f7e72b49c2a67868f20c015 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 25 Jul 2013 12:27:24 +0530 Subject: [PATCH 0691/3400] staging: lustre: Remove duplicate header file inclusion in lmv_intent.c Removed the header file included twice. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/lmv/lmv_intent.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/lmv/lmv_intent.c b/drivers/staging/lustre/lustre/lmv/lmv_intent.c index 7eefab5ef5d0..4bc8c6a5d6f2 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_intent.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_intent.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include From 713542a8cd156b06770ddbabb495bba38ea017fb Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 25 Jul 2013 12:27:25 +0530 Subject: [PATCH 0692/3400] staging: lustre: Remove duplicate header file inclusion in lmv_obd.c Removed the header file included twice. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/lmv/lmv_obd.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 11c8d644d5ea..1987d4bae9b4 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include From b9cb7fed5eef3cc21ef61aff66a16c4bd52a1c41 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 25 Jul 2013 12:27:26 +0530 Subject: [PATCH 0693/3400] staging: lustre: Remove duplicate header file inclusion in lvfs_linux.c Removed the header file included twice. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/lvfs/lvfs_linux.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c b/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c index 9d19d0a79be8..0f387913d6ff 100644 --- a/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c +++ b/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c @@ -46,7 +46,6 @@ #include #include #include -#include #include #include #include From af7c25588f45aeaeeaf7eaeadbd25524f4adc308 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 25 Jul 2013 12:27:27 +0530 Subject: [PATCH 0694/3400] staging: lustre: obdclass: Remove duplicate header file inclusion Removed the header file included twice. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c index 8fe6a019d1e3..c4a740286ad1 100644 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c +++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include From 7b117940f329729fc673f69661576e5699c91594 Mon Sep 17 00:00:00 2001 From: Xiong Zhou Date: Thu, 25 Jul 2013 15:06:13 +0800 Subject: [PATCH 0695/3400] staging/lustre: add BLOCK depends in Kconfig MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add BLOCK depends in Kconfig for LUSTRE to fix this: drivers/staging/lustre/lustre/fid/../include/linux/lustre_compat25.h:117:2: error: implicit declaration of function ‘unregister_blkdev’ Signed-off-by: Xiong Zhou Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/Kconfig b/drivers/staging/lustre/lustre/Kconfig index 9ae7fa86b5a8..0b45de0726f6 100644 --- a/drivers/staging/lustre/lustre/Kconfig +++ b/drivers/staging/lustre/lustre/Kconfig @@ -1,6 +1,6 @@ config LUSTRE_FS tristate "Lustre file system client support" - depends on STAGING && INET && m + depends on STAGING && INET && BLOCK && m select LNET select CRYPTO select CRYPTO_CRC32 From 1bf4d4860ed50cb9c0be6ee4fc6de5ffccf1d072 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 25 Jul 2013 11:36:49 +0530 Subject: [PATCH 0696/3400] staging: gdm724x: Remove version.h header inclusion in gdm_lte.c version.h header inclusion is not necessary as detected by versioncheck. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gdm724x/gdm_lte.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/gdm724x/gdm_lte.c b/drivers/staging/gdm724x/gdm_lte.c index 557822fdc966..68ebc7d1eae6 100644 --- a/drivers/staging/gdm724x/gdm_lte.c +++ b/drivers/staging/gdm724x/gdm_lte.c @@ -13,7 +13,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include #include #include #include From c1636ab01b5dc2f331c80ae32ce9416746edac65 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 25 Jul 2013 11:36:50 +0530 Subject: [PATCH 0697/3400] staging: gdm724x: Remove version.h header inclusion in gdm_lte.h version.h header inclusion is not necessary as detected by versioncheck. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gdm724x/gdm_lte.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/gdm724x/gdm_lte.h b/drivers/staging/gdm724x/gdm_lte.h index 90c9d51fcaf0..9287d310d8e2 100644 --- a/drivers/staging/gdm724x/gdm_lte.h +++ b/drivers/staging/gdm724x/gdm_lte.h @@ -15,7 +15,6 @@ #define _GDM_LTE_H_ #include -#include #include #include "gdm_endian.h" From 3d2bf0fa5f1ecce06bbc6e7f749e4f32e90854a6 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 25 Jul 2013 11:36:51 +0530 Subject: [PATCH 0698/3400] staging: gdm724x: Remove version.h header inclusion in gdm_mux.c version.h header inclusion is not necessary as detected by versioncheck. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gdm724x/gdm_mux.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/gdm724x/gdm_mux.c b/drivers/staging/gdm724x/gdm_mux.c index f570bc00c990..2e619d2e7ba1 100644 --- a/drivers/staging/gdm724x/gdm_mux.c +++ b/drivers/staging/gdm724x/gdm_mux.c @@ -14,7 +14,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -#include #include #include #include From c47a5863b66887b1667f8988cef1f0e020e29c8b Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 25 Jul 2013 11:36:52 +0530 Subject: [PATCH 0699/3400] staging: gdm724x: Remove version.h header inclusion in gdm_tty.c version.h header inclusion is not necessary as detected by versioncheck. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gdm724x/gdm_tty.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/gdm724x/gdm_tty.c b/drivers/staging/gdm724x/gdm_tty.c index 357daa80560f..912022b84c03 100644 --- a/drivers/staging/gdm724x/gdm_tty.c +++ b/drivers/staging/gdm724x/gdm_tty.c @@ -13,7 +13,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include #include #include #include From 8f0b54478acdece4a398f65ac76c70294158e33c Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 25 Jul 2013 11:36:53 +0530 Subject: [PATCH 0700/3400] staging: gdm724x: Remove version.h header inclusion in gdm_tty.h version.h header inclusion is not necessary as detected by versioncheck. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gdm724x/gdm_tty.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/gdm724x/gdm_tty.h b/drivers/staging/gdm724x/gdm_tty.h index faeaa412eca0..a75be1df0100 100644 --- a/drivers/staging/gdm724x/gdm_tty.h +++ b/drivers/staging/gdm724x/gdm_tty.h @@ -14,7 +14,6 @@ #ifndef _GDM_TTY_H_ #define _GDM_TTY_H_ -#include #include #include From 649bf7f98b281ffb0c7b1c4fc62334b0e86d527c Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 25 Jul 2013 11:36:54 +0530 Subject: [PATCH 0701/3400] staging: gdm724x: Remove version.h header inclusion in gdm_usb.c version.h header inclusion is not necessary as detected by versioncheck. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gdm724x/gdm_usb.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/gdm724x/gdm_usb.c b/drivers/staging/gdm724x/gdm_usb.c index 2e658f84486c..4b10f23845ad 100644 --- a/drivers/staging/gdm724x/gdm_usb.c +++ b/drivers/staging/gdm724x/gdm_usb.c @@ -14,7 +14,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -#include #include #include #include From 7382b5cde6fd5cdaf5d11e698ad9f9015c8e2e13 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 25 Jul 2013 11:36:55 +0530 Subject: [PATCH 0702/3400] staging: gdm724x: Remove version.h header inclusion in gdm_usb.h version.h header inclusion is not necessary as detected by versioncheck. Signed-off-by: Sachin Kamat Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gdm724x/gdm_usb.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/gdm724x/gdm_usb.h b/drivers/staging/gdm724x/gdm_usb.h index 38f6537dced0..e6486e71a428 100644 --- a/drivers/staging/gdm724x/gdm_usb.h +++ b/drivers/staging/gdm724x/gdm_usb.h @@ -14,7 +14,6 @@ #ifndef _GDM_USB_H_ #define _GDM_USB_H_ -#include #include #include #include From 323f54ed0f3ce20e9946c961fc928ccdb80d9345 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Thu, 25 Jul 2013 14:26:10 -0400 Subject: [PATCH 0703/3400] numa: Mark __node_set() as __always_inline It is posible for some compilers to decide that __node_set() does not need to be made turned into an inline function. When the compiler does this on an __init function calling it on __initdata we get a section mismatch warning now. Use __always_inline to ensure that we will be inlined. Reported-by: Paul Bolle Cc: Jianpeng Ma Cc: Rusty Russell Cc: Lai Jiangshan Cc: Yasuaki Ishimatsu Cc: Wen Congyang Cc: Jiang Liu Cc: KOSAKI Motohiro Cc: Minchan Kim Cc: Mel Gorman Cc: David Rientjes Cc: Yinghai Lu Cc: Greg KH Signed-off-by: Tom Rini Link: http://lkml.kernel.org/r/1374776770-32361-1-git-send-email-trini@ti.com Signed-off-by: Ingo Molnar --- include/linux/nodemask.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/include/linux/nodemask.h b/include/linux/nodemask.h index 4e2cbfa640b7..58b9a02c38d2 100644 --- a/include/linux/nodemask.h +++ b/include/linux/nodemask.h @@ -98,8 +98,17 @@ typedef struct { DECLARE_BITMAP(bits, MAX_NUMNODES); } nodemask_t; extern nodemask_t _unused_nodemask_arg_; +/* + * The inline keyword gives the compiler room to decide to inline, or + * not inline a function as it sees best. However, as these functions + * are called in both __init and non-__init functions, if they are not + * inlined we will end up with a section mis-match error (of the type of + * freeable items not being freed). So we must use __always_inline here + * to fix the problem. If other functions in the future also end up in + * this situation they will also need to be annotated as __always_inline + */ #define node_set(node, dst) __node_set((node), &(dst)) -static inline void __node_set(int node, volatile nodemask_t *dstp) +static __always_inline void __node_set(int node, volatile nodemask_t *dstp) { set_bit(node, dstp->bits); } From 40f1a5ab5e82ab7f15bee23db3db6c3ae957dde4 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 14:06:38 -0700 Subject: [PATCH 0704/3400] staging: comedi: usbdux: rename struct usbduxsub This struct is the comedi_device private data. For aesthetic reasons, rename it to usbdux_private. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 98 ++++++++++++------------- 1 file changed, 45 insertions(+), 53 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 279e5bd493fa..a64967684b68 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -228,15 +228,7 @@ static const struct comedi_lrange range_usbdux_ao_range = { 2, { } }; -/* - * private structure of one subdevice - */ - -/* - * This is the structure which holds all the data of - * this driver one sub device just now: A/D - */ -struct usbduxsub { +struct usbdux_private { /* attached? */ int attached; /* is it associated with a subdevice? */ @@ -305,7 +297,7 @@ struct usbduxsub { * _before_ any comedi command is issued. The usb subsystem must be initialised * before comedi can access it. */ -static struct usbduxsub usbduxsub[NUMUSBDUX]; +static struct usbdux_private usbduxsub[NUMUSBDUX]; static DEFINE_SEMAPHORE(start_stop_sem); @@ -313,7 +305,7 @@ static DEFINE_SEMAPHORE(start_stop_sem); * Stops the data acquision * It should be safe to call this function from any context */ -static int usbduxsub_unlink_inurbs(struct usbduxsub *usbduxsub_tmp) +static int usbduxsub_unlink_inurbs(struct usbdux_private *usbduxsub_tmp) { int i = 0; int err = 0; @@ -338,7 +330,7 @@ static int usbduxsub_unlink_inurbs(struct usbduxsub *usbduxsub_tmp) * Is called from within this driver from both the * interrupt context and from comedi */ -static int usbdux_ai_stop(struct usbduxsub *this_usbduxsub, int do_unlink) +static int usbdux_ai_stop(struct usbdux_private *this_usbduxsub, int do_unlink) { int ret = 0; @@ -365,7 +357,7 @@ static int usbdux_ai_stop(struct usbduxsub *this_usbduxsub, int do_unlink) static int usbdux_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { - struct usbduxsub *this_usbduxsub; + struct usbdux_private *this_usbduxsub; int res = 0; /* force unlink of all urbs */ @@ -391,13 +383,13 @@ static int usbdux_ai_cancel(struct comedi_device *dev, static void usbduxsub_ai_isoc_irq(struct urb *urb) { int i, err, n; - struct usbduxsub *this_usbduxsub; + struct usbdux_private *this_usbduxsub; struct comedi_device *this_comedidev; struct comedi_subdevice *s; /* the context variable points to the subdevice */ this_comedidev = urb->context; - /* the private structure of the subdevice is struct usbduxsub */ + /* the private structure of the subdevice is struct usbdux_private */ this_usbduxsub = this_comedidev->private; /* subdevice which is the AD converter */ s = &this_comedidev->subdevices[SUBDEV_AD]; @@ -528,7 +520,7 @@ static void usbduxsub_ai_isoc_irq(struct urb *urb) comedi_event(this_usbduxsub->comedidev, s); } -static int usbduxsub_unlink_outurbs(struct usbduxsub *usbduxsub_tmp) +static int usbduxsub_unlink_outurbs(struct usbdux_private *usbduxsub_tmp) { int i = 0; int err = 0; @@ -549,7 +541,7 @@ static int usbduxsub_unlink_outurbs(struct usbduxsub *usbduxsub_tmp) /* This will cancel a running acquisition operation * in any context. */ -static int usbdux_ao_stop(struct usbduxsub *this_usbduxsub, int do_unlink) +static int usbdux_ao_stop(struct usbdux_private *this_usbduxsub, int do_unlink) { int ret = 0; @@ -569,7 +561,7 @@ static int usbdux_ao_stop(struct usbduxsub *this_usbduxsub, int do_unlink) static int usbdux_ao_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { - struct usbduxsub *this_usbduxsub = dev->private; + struct usbdux_private *this_usbduxsub = dev->private; int res = 0; if (!this_usbduxsub) @@ -591,13 +583,13 @@ static void usbduxsub_ao_isoc_irq(struct urb *urb) { int i, ret; int8_t *datap; - struct usbduxsub *this_usbduxsub; + struct usbdux_private *this_usbduxsub; struct comedi_device *this_comedidev; struct comedi_subdevice *s; /* the context variable points to the subdevice */ this_comedidev = urb->context; - /* the private structure of the subdevice is struct usbduxsub */ + /* the private structure of the subdevice is struct usbdux_private */ this_usbduxsub = this_comedidev->private; s = &this_comedidev->subdevices[SUBDEV_DA]; @@ -727,7 +719,7 @@ static int usbdux_firmware_upload(struct comedi_device *dev, const u8 *data, size_t size, unsigned long context) { - struct usbduxsub *usbduxsub = dev->private; + struct usbdux_private *usbduxsub = dev->private; struct usb_device *usb = usbduxsub->usbdev; uint8_t *buf; uint8_t *tmp; @@ -799,7 +791,7 @@ done: return ret; } -static int usbduxsub_submit_inurbs(struct usbduxsub *usbduxsub) +static int usbduxsub_submit_inurbs(struct usbdux_private *usbduxsub) { int i, err_flag; @@ -831,7 +823,7 @@ static int usbduxsub_submit_inurbs(struct usbduxsub *usbduxsub) return 0; } -static int usbduxsub_submit_outurbs(struct usbduxsub *usbduxsub) +static int usbduxsub_submit_outurbs(struct usbdux_private *usbduxsub) { int i, err_flag; @@ -860,7 +852,7 @@ static int usbduxsub_submit_outurbs(struct usbduxsub *usbduxsub) static int usbdux_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { - struct usbduxsub *this_usbduxsub = dev->private; + struct usbdux_private *this_usbduxsub = dev->private; int err = 0, i; unsigned int tmp_timer; @@ -968,7 +960,7 @@ static int8_t create_adc_command(unsigned int chan, int range) #define SENDPWMON 7 #define SENDPWMOFF 8 -static int send_dux_commands(struct usbduxsub *this_usbduxsub, int cmd_type) +static int send_dux_commands(struct usbdux_private *this_usbduxsub, int cmd_type) { int result, nsent; @@ -993,7 +985,7 @@ static int send_dux_commands(struct usbduxsub *this_usbduxsub, int cmd_type) return result; } -static int receive_dux_commands(struct usbduxsub *this_usbduxsub, int command) +static int receive_dux_commands(struct usbdux_private *this_usbduxsub, int command) { int result = (-EFAULT); int nrec; @@ -1027,7 +1019,7 @@ static int usbdux_ai_inttrig(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int trignum) { int ret; - struct usbduxsub *this_usbduxsub = dev->private; + struct usbdux_private *this_usbduxsub = dev->private; if (!this_usbduxsub) return -EFAULT; @@ -1072,7 +1064,7 @@ static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) struct comedi_cmd *cmd = &s->async->cmd; unsigned int chan, range; int i, ret; - struct usbduxsub *this_usbduxsub = dev->private; + struct usbdux_private *this_usbduxsub = dev->private; int result; if (!this_usbduxsub) @@ -1192,7 +1184,7 @@ static int usbdux_ai_insn_read(struct comedi_device *dev, unsigned int one = 0; int chan, range; int err; - struct usbduxsub *this_usbduxsub = dev->private; + struct usbdux_private *this_usbduxsub = dev->private; if (!this_usbduxsub) return 0; @@ -1252,7 +1244,7 @@ static int usbdux_ao_insn_read(struct comedi_device *dev, { int i; int chan = CR_CHAN(insn->chanspec); - struct usbduxsub *this_usbduxsub = dev->private; + struct usbdux_private *this_usbduxsub = dev->private; if (!this_usbduxsub) return -EFAULT; @@ -1275,7 +1267,7 @@ static int usbdux_ao_insn_write(struct comedi_device *dev, { int i, err; int chan = CR_CHAN(insn->chanspec); - struct usbduxsub *this_usbduxsub = dev->private; + struct usbdux_private *this_usbduxsub = dev->private; if (!this_usbduxsub) return -EFAULT; @@ -1324,7 +1316,7 @@ static int usbdux_ao_inttrig(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int trignum) { int ret; - struct usbduxsub *this_usbduxsub = dev->private; + struct usbdux_private *this_usbduxsub = dev->private; if (!this_usbduxsub) return -EFAULT; @@ -1365,7 +1357,7 @@ static int usbdux_ao_inttrig(struct comedi_device *dev, static int usbdux_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { - struct usbduxsub *this_usbduxsub = dev->private; + struct usbdux_private *this_usbduxsub = dev->private; int err = 0; unsigned int flags; @@ -1454,7 +1446,7 @@ static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) struct comedi_cmd *cmd = &s->async->cmd; unsigned int chan, gain; int i, ret; - struct usbduxsub *this_usbduxsub = dev->private; + struct usbdux_private *this_usbduxsub = dev->private; if (!this_usbduxsub) return -EFAULT; @@ -1593,7 +1585,7 @@ static int usbdux_dio_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct usbduxsub *this_usbduxsub = dev->private; + struct usbdux_private *this_usbduxsub = dev->private; int err; if (!this_usbduxsub) @@ -1636,7 +1628,7 @@ static int usbdux_counter_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct usbduxsub *this_usbduxsub = dev->private; + struct usbdux_private *this_usbduxsub = dev->private; int chan = insn->chanspec; int err; @@ -1671,7 +1663,7 @@ static int usbdux_counter_write(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct usbduxsub *this_usbduxsub = dev->private; + struct usbdux_private *this_usbduxsub = dev->private; int err; if (!this_usbduxsub) @@ -1709,7 +1701,7 @@ static int usbdux_counter_config(struct comedi_device *dev, /***********************************/ /* PWM */ -static int usbduxsub_unlink_pwm_urbs(struct usbduxsub *usbduxsub_tmp) +static int usbduxsub_unlink_pwm_urbs(struct usbdux_private *usbduxsub_tmp) { int err = 0; @@ -1725,7 +1717,7 @@ static int usbduxsub_unlink_pwm_urbs(struct usbduxsub *usbduxsub_tmp) /* This cancels a running acquisition operation * in any context. */ -static int usbdux_pwm_stop(struct usbduxsub *this_usbduxsub, int do_unlink) +static int usbdux_pwm_stop(struct usbdux_private *this_usbduxsub, int do_unlink) { int ret = 0; @@ -1745,7 +1737,7 @@ static int usbdux_pwm_stop(struct usbduxsub *this_usbduxsub, int do_unlink) static int usbdux_pwm_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { - struct usbduxsub *this_usbduxsub = dev->private; + struct usbdux_private *this_usbduxsub = dev->private; int res = 0; /* unlink only if it is really running */ @@ -1761,7 +1753,7 @@ static int usbdux_pwm_cancel(struct comedi_device *dev, static void usbduxsub_pwm_irq(struct urb *urb) { int ret; - struct usbduxsub *this_usbduxsub; + struct usbdux_private *this_usbduxsub; struct comedi_device *this_comedidev; struct comedi_subdevice *s; @@ -1769,7 +1761,7 @@ static void usbduxsub_pwm_irq(struct urb *urb) /* the context variable points to the subdevice */ this_comedidev = urb->context; - /* the private structure of the subdevice is struct usbduxsub */ + /* the private structure of the subdevice is struct usbdux_private */ this_usbduxsub = this_comedidev->private; s = &this_comedidev->subdevices[SUBDEV_DA]; @@ -1827,7 +1819,7 @@ static void usbduxsub_pwm_irq(struct urb *urb) } } -static int usbduxsub_submit_pwm_urbs(struct usbduxsub *usbduxsub) +static int usbduxsub_submit_pwm_urbs(struct usbdux_private *usbduxsub) { int err_flag; @@ -1857,7 +1849,7 @@ static int usbduxsub_submit_pwm_urbs(struct usbduxsub *usbduxsub) static int usbdux_pwm_period(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int period) { - struct usbduxsub *this_usbduxsub = dev->private; + struct usbdux_private *this_usbduxsub = dev->private; int fx2delay = 255; if (period < MIN_PWM_PERIOD) { @@ -1886,7 +1878,7 @@ static int usbdux_pwm_start(struct comedi_device *dev, struct comedi_subdevice *s) { int ret, i; - struct usbduxsub *this_usbduxsub = dev->private; + struct usbdux_private *this_usbduxsub = dev->private; dev_dbg(&this_usbduxsub->interface->dev, "comedi%d: %s\n", dev->minor, __func__); @@ -1919,7 +1911,7 @@ static int usbdux_pwm_pattern(struct comedi_device *dev, struct comedi_subdevice *s, int channel, unsigned int value, unsigned int sign) { - struct usbduxsub *this_usbduxsub = dev->private; + struct usbdux_private *this_usbduxsub = dev->private; int i, szbuf; char *p_buf; char pwm_mask; @@ -1961,7 +1953,7 @@ static int usbdux_pwm_write(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct usbduxsub *this_usbduxsub = dev->private; + struct usbdux_private *this_usbduxsub = dev->private; if (!this_usbduxsub) return -EFAULT; @@ -1995,7 +1987,7 @@ static int usbdux_pwm_config(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct usbduxsub *this_usbduxsub = dev->private; + struct usbdux_private *this_usbduxsub = dev->private; switch (data[0]) { case INSN_CONFIG_ARM: /* switch it on */ @@ -2046,7 +2038,7 @@ static int usbdux_pwm_config(struct comedi_device *dev, /* end of PWM */ /*****************************************************************/ -static void tidy_up(struct usbduxsub *usbduxsub_tmp) +static void tidy_up(struct usbdux_private *usbduxsub_tmp) { int i; @@ -2119,7 +2111,7 @@ static void tidy_up(struct usbduxsub *usbduxsub_tmp) } static int usbdux_attach_common(struct comedi_device *dev, - struct usbduxsub *udev) + struct usbdux_private *udev) { int ret; struct comedi_subdevice *s = NULL; @@ -2250,7 +2242,7 @@ static int usbdux_auto_attach(struct comedi_device *dev, unsigned long context_unused) { struct usb_interface *uinterf = comedi_to_usb_interface(dev); - struct usbduxsub *this_usbduxsub = usb_get_intfdata(uinterf); + struct usbdux_private *this_usbduxsub = usb_get_intfdata(uinterf); struct usb_device *usb = usbduxsub->usbdev; int ret; @@ -2281,7 +2273,7 @@ static int usbdux_auto_attach(struct comedi_device *dev, static void usbdux_detach(struct comedi_device *dev) { - struct usbduxsub *usb = dev->private; + struct usbdux_private *usb = dev->private; if (usb) { down(&usb->sem); @@ -2527,7 +2519,7 @@ static int usbdux_usb_probe(struct usb_interface *uinterf, static void usbdux_usb_disconnect(struct usb_interface *intf) { - struct usbduxsub *usbduxsub_tmp = usb_get_intfdata(intf); + struct usbdux_private *usbduxsub_tmp = usb_get_intfdata(intf); struct usb_device *udev = interface_to_usbdev(intf); if (!usbduxsub_tmp) { From b0daed19f21f4199fb7e4ded5fc0cddd230c655f Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 14:06:58 -0700 Subject: [PATCH 0705/3400] staging: comedi: usbdux: remove the usb_driver (*probe) noise The dev_dbg() during the usb_driver (*probe) is just added noise. The dev_err() when a usb_alloc_urb() fails is not necessary. The allocation failure will have already output a message. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index a64967684b68..63e302847def 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -2299,9 +2299,6 @@ static int usbdux_usb_probe(struct usb_interface *uinterf, int i; int index; - dev_dbg(dev, "comedi_: usbdux_: " - "finding a free structure for the usb-device\n"); - down(&start_stop_sem); /* look for a free place in the usbdux array */ index = -1; @@ -2318,8 +2315,6 @@ static int usbdux_usb_probe(struct usb_interface *uinterf, up(&start_stop_sem); return -EMFILE; } - dev_dbg(dev, "comedi_: usbdux: " - "usbduxsub[%d] is ready to connect to comedi.\n", index); sema_init(&(usbduxsub[index].sem), 1); /* save a pointer to the usb device */ @@ -2333,8 +2328,6 @@ static int usbdux_usb_probe(struct usb_interface *uinterf, /* will be needed for disconnect */ usb_set_intfdata(uinterf, &(usbduxsub[index])); - dev_dbg(dev, "comedi_: usbdux: ifnum=%d\n", usbduxsub[index].ifnum); - /* test if it is high speed (USB 2.0) */ usbduxsub[index].high_speed = (usbduxsub[index].usbdev->speed == USB_SPEED_HIGH); @@ -2402,8 +2395,6 @@ static int usbdux_usb_probe(struct usb_interface *uinterf, /* one frame: 1ms */ usbduxsub[index].urb_in[i] = usb_alloc_urb(1, GFP_KERNEL); if (usbduxsub[index].urb_in[i] == NULL) { - dev_err(dev, "comedi_: usbdux%d: " - "Could not alloc. urb(%d)\n", index, i); tidy_up(&(usbduxsub[index])); up(&start_stop_sem); return -ENOMEM; @@ -2447,8 +2438,6 @@ static int usbdux_usb_probe(struct usb_interface *uinterf, /* one frame: 1ms */ usbduxsub[index].urb_out[i] = usb_alloc_urb(1, GFP_KERNEL); if (usbduxsub[index].urb_out[i] == NULL) { - dev_err(dev, "comedi_: usbdux%d: " - "Could not alloc. urb(%d)\n", index, i); tidy_up(&(usbduxsub[index])); up(&start_stop_sem); return -ENOMEM; @@ -2488,8 +2477,6 @@ static int usbdux_usb_probe(struct usb_interface *uinterf, usbduxsub[index].size_pwm_buf = 512; usbduxsub[index].urb_pwm = usb_alloc_urb(0, GFP_KERNEL); if (usbduxsub[index].urb_pwm == NULL) { - dev_err(dev, "comedi_: usbdux%d: " - "Could not alloc. pwm urb\n", index); tidy_up(&(usbduxsub[index])); up(&start_stop_sem); return -ENOMEM; From da9035908edc3e936a2912cf836fed3e9d965cf1 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 14:07:18 -0700 Subject: [PATCH 0706/3400] staging: comedi: usbdux: tidy up usbdux_usb_probe() Use a pointer to the struct usbdux_private data being configured in the probe. Also use a pointer to the struct urb being setup in the buffer allocations. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 221 +++++++++++------------- 1 file changed, 103 insertions(+), 118 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 63e302847def..d1651e2cdefe 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -2296,209 +2296,194 @@ static int usbdux_usb_probe(struct usb_interface *uinterf, { struct usb_device *udev = interface_to_usbdev(uinterf); struct device *dev = &uinterf->dev; + struct usbdux_private *devpriv = NULL; + struct urb *urb; int i; - int index; down(&start_stop_sem); - /* look for a free place in the usbdux array */ - index = -1; + for (i = 0; i < NUMUSBDUX; i++) { - if (!(usbduxsub[i].probed)) { - index = i; + if (!usbduxsub[i].probed) { + devpriv = &usbduxsub[i]; break; } } - - /* no more space */ - if (index == -1) { + if (!devpriv) { dev_err(dev, "Too many usbdux-devices connected.\n"); up(&start_stop_sem); return -EMFILE; } - sema_init(&(usbduxsub[index].sem), 1); - /* save a pointer to the usb device */ - usbduxsub[index].usbdev = udev; + sema_init(&devpriv->sem, 1); - /* 2.6: save the interface itself */ - usbduxsub[index].interface = uinterf; - /* get the interface number from the interface */ - usbduxsub[index].ifnum = uinterf->altsetting->desc.bInterfaceNumber; - /* hand the private data over to the usb subsystem */ - /* will be needed for disconnect */ - usb_set_intfdata(uinterf, &(usbduxsub[index])); + devpriv->usbdev = udev; + devpriv->interface = uinterf; + devpriv->ifnum = uinterf->altsetting->desc.bInterfaceNumber; + usb_set_intfdata(uinterf, devpriv); - /* test if it is high speed (USB 2.0) */ - usbduxsub[index].high_speed = - (usbduxsub[index].usbdev->speed == USB_SPEED_HIGH); + devpriv->high_speed = (devpriv->usbdev->speed == USB_SPEED_HIGH); /* create space for the commands of the DA converter */ - usbduxsub[index].dac_commands = kzalloc(NUMOUTCHANNELS, GFP_KERNEL); - if (!usbduxsub[index].dac_commands) { - tidy_up(&(usbduxsub[index])); + devpriv->dac_commands = kzalloc(NUMOUTCHANNELS, GFP_KERNEL); + if (!devpriv->dac_commands) { + tidy_up(devpriv); up(&start_stop_sem); return -ENOMEM; } /* create space for the commands going to the usb device */ - usbduxsub[index].dux_commands = kzalloc(SIZEOFDUXBUFFER, GFP_KERNEL); - if (!usbduxsub[index].dux_commands) { - tidy_up(&(usbduxsub[index])); + devpriv->dux_commands = kzalloc(SIZEOFDUXBUFFER, GFP_KERNEL); + if (!devpriv->dux_commands) { + tidy_up(devpriv); up(&start_stop_sem); return -ENOMEM; } /* create space for the in buffer and set it to zero */ - usbduxsub[index].in_buffer = kzalloc(SIZEINBUF, GFP_KERNEL); - if (!(usbduxsub[index].in_buffer)) { - tidy_up(&(usbduxsub[index])); + devpriv->in_buffer = kzalloc(SIZEINBUF, GFP_KERNEL); + if (!devpriv->in_buffer) { + tidy_up(devpriv); up(&start_stop_sem); return -ENOMEM; } /* create space of the instruction buffer */ - usbduxsub[index].insn_buffer = kzalloc(SIZEINSNBUF, GFP_KERNEL); - if (!(usbduxsub[index].insn_buffer)) { - tidy_up(&(usbduxsub[index])); + devpriv->insn_buffer = kzalloc(SIZEINSNBUF, GFP_KERNEL); + if (!devpriv->insn_buffer) { + tidy_up(devpriv); up(&start_stop_sem); return -ENOMEM; } /* create space for the outbuffer */ - usbduxsub[index].out_buffer = kzalloc(SIZEOUTBUF, GFP_KERNEL); - if (!(usbduxsub[index].out_buffer)) { - tidy_up(&(usbduxsub[index])); + devpriv->out_buffer = kzalloc(SIZEOUTBUF, GFP_KERNEL); + if (!devpriv->out_buffer) { + tidy_up(devpriv); up(&start_stop_sem); return -ENOMEM; } /* setting to alternate setting 3: enabling iso ep and bulk ep. */ - i = usb_set_interface(usbduxsub[index].usbdev, - usbduxsub[index].ifnum, 3); + i = usb_set_interface(devpriv->usbdev, devpriv->ifnum, 3); if (i < 0) { - dev_err(dev, "comedi_: usbdux%d: " - "could not set alternate setting 3 in high speed.\n", - index); - tidy_up(&(usbduxsub[index])); + dev_err(dev, + "could not set alternate setting 3 in high speed\n"); + tidy_up(devpriv); up(&start_stop_sem); return -ENODEV; } - if (usbduxsub[index].high_speed) - usbduxsub[index].num_in_buffers = NUMOFINBUFFERSHIGH; + if (devpriv->high_speed) + devpriv->num_in_buffers = NUMOFINBUFFERSHIGH; else - usbduxsub[index].num_in_buffers = NUMOFINBUFFERSFULL; + devpriv->num_in_buffers = NUMOFINBUFFERSFULL; - usbduxsub[index].urb_in = - kcalloc(usbduxsub[index].num_in_buffers, sizeof(struct urb *), - GFP_KERNEL); - if (!(usbduxsub[index].urb_in)) { - tidy_up(&(usbduxsub[index])); + devpriv->urb_in = kcalloc(devpriv->num_in_buffers, sizeof(*urb), + GFP_KERNEL); + if (!devpriv->urb_in) { + tidy_up(devpriv); up(&start_stop_sem); return -ENOMEM; } - for (i = 0; i < usbduxsub[index].num_in_buffers; i++) { + for (i = 0; i < devpriv->num_in_buffers; i++) { /* one frame: 1ms */ - usbduxsub[index].urb_in[i] = usb_alloc_urb(1, GFP_KERNEL); - if (usbduxsub[index].urb_in[i] == NULL) { - tidy_up(&(usbduxsub[index])); + urb = usb_alloc_urb(1, GFP_KERNEL); + if (!urb) { + tidy_up(devpriv); up(&start_stop_sem); return -ENOMEM; } - usbduxsub[index].urb_in[i]->dev = usbduxsub[index].usbdev; + devpriv->urb_in[i] = urb; + + urb->dev = devpriv->usbdev; /* will be filled later with a pointer to the comedi-device */ /* and ONLY then the urb should be submitted */ - usbduxsub[index].urb_in[i]->context = NULL; - usbduxsub[index].urb_in[i]->pipe = - usb_rcvisocpipe(usbduxsub[index].usbdev, ISOINEP); - usbduxsub[index].urb_in[i]->transfer_flags = URB_ISO_ASAP; - usbduxsub[index].urb_in[i]->transfer_buffer = - kzalloc(SIZEINBUF, GFP_KERNEL); - if (!(usbduxsub[index].urb_in[i]->transfer_buffer)) { - tidy_up(&(usbduxsub[index])); + urb->context = NULL; + urb->pipe = usb_rcvisocpipe(devpriv->usbdev, ISOINEP); + urb->transfer_flags = URB_ISO_ASAP; + urb->transfer_buffer = kzalloc(SIZEINBUF, GFP_KERNEL); + if (!urb->transfer_buffer) { + tidy_up(devpriv); up(&start_stop_sem); return -ENOMEM; } - usbduxsub[index].urb_in[i]->complete = usbduxsub_ai_isoc_irq; - usbduxsub[index].urb_in[i]->number_of_packets = 1; - usbduxsub[index].urb_in[i]->transfer_buffer_length = SIZEINBUF; - usbduxsub[index].urb_in[i]->iso_frame_desc[0].offset = 0; - usbduxsub[index].urb_in[i]->iso_frame_desc[0].length = SIZEINBUF; + urb->complete = usbduxsub_ai_isoc_irq; + urb->number_of_packets = 1; + urb->transfer_buffer_length = SIZEINBUF; + urb->iso_frame_desc[0].offset = 0; + urb->iso_frame_desc[0].length = SIZEINBUF; } /* out */ - if (usbduxsub[index].high_speed) - usbduxsub[index].num_out_buffers = NUMOFOUTBUFFERSHIGH; + if (devpriv->high_speed) + devpriv->num_out_buffers = NUMOFOUTBUFFERSHIGH; else - usbduxsub[index].num_out_buffers = NUMOFOUTBUFFERSFULL; + devpriv->num_out_buffers = NUMOFOUTBUFFERSFULL; - usbduxsub[index].urb_out = - kcalloc(usbduxsub[index].num_out_buffers, sizeof(struct urb *), - GFP_KERNEL); - if (!(usbduxsub[index].urb_out)) { - tidy_up(&(usbduxsub[index])); + devpriv->urb_out = kcalloc(devpriv->num_out_buffers, sizeof(*urb), + GFP_KERNEL); + if (!devpriv->urb_out) { + tidy_up(devpriv); up(&start_stop_sem); return -ENOMEM; } - for (i = 0; i < usbduxsub[index].num_out_buffers; i++) { + for (i = 0; i < devpriv->num_out_buffers; i++) { /* one frame: 1ms */ - usbduxsub[index].urb_out[i] = usb_alloc_urb(1, GFP_KERNEL); - if (usbduxsub[index].urb_out[i] == NULL) { - tidy_up(&(usbduxsub[index])); + urb = usb_alloc_urb(1, GFP_KERNEL); + if (!urb) { + tidy_up(devpriv); up(&start_stop_sem); return -ENOMEM; } - usbduxsub[index].urb_out[i]->dev = usbduxsub[index].usbdev; + devpriv->urb_out[i] = urb; + + urb->dev = devpriv->usbdev; /* will be filled later with a pointer to the comedi-device */ /* and ONLY then the urb should be submitted */ - usbduxsub[index].urb_out[i]->context = NULL; - usbduxsub[index].urb_out[i]->pipe = - usb_sndisocpipe(usbduxsub[index].usbdev, ISOOUTEP); - usbduxsub[index].urb_out[i]->transfer_flags = URB_ISO_ASAP; - usbduxsub[index].urb_out[i]->transfer_buffer = - kzalloc(SIZEOUTBUF, GFP_KERNEL); - if (!(usbduxsub[index].urb_out[i]->transfer_buffer)) { - tidy_up(&(usbduxsub[index])); + urb->context = NULL; + urb->pipe = usb_sndisocpipe(devpriv->usbdev, ISOOUTEP); + urb->transfer_flags = URB_ISO_ASAP; + urb->transfer_buffer = kzalloc(SIZEOUTBUF, GFP_KERNEL); + if (!(urb->transfer_buffer)) { + tidy_up(devpriv); up(&start_stop_sem); return -ENOMEM; } - usbduxsub[index].urb_out[i]->complete = usbduxsub_ao_isoc_irq; - usbduxsub[index].urb_out[i]->number_of_packets = 1; - usbduxsub[index].urb_out[i]->transfer_buffer_length = SIZEOUTBUF; - usbduxsub[index].urb_out[i]->iso_frame_desc[0].offset = 0; - usbduxsub[index].urb_out[i]->iso_frame_desc[0].length = - SIZEOUTBUF; - if (usbduxsub[index].high_speed) { - /* uframes */ - usbduxsub[index].urb_out[i]->interval = 8; - } else { - /* frames */ - usbduxsub[index].urb_out[i]->interval = 1; - } + urb->complete = usbduxsub_ao_isoc_irq; + urb->number_of_packets = 1; + urb->transfer_buffer_length = SIZEOUTBUF; + urb->iso_frame_desc[0].offset = 0; + urb->iso_frame_desc[0].length = SIZEOUTBUF; + if (devpriv->high_speed) + urb->interval = 8; /* uframes */ + else + urb->interval = 1; /* frames */ } /* pwm */ - if (usbduxsub[index].high_speed) { - /* max bulk ep size in high speed */ - usbduxsub[index].size_pwm_buf = 512; - usbduxsub[index].urb_pwm = usb_alloc_urb(0, GFP_KERNEL); - if (usbduxsub[index].urb_pwm == NULL) { - tidy_up(&(usbduxsub[index])); + if (devpriv->high_speed) { + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { + tidy_up(devpriv); up(&start_stop_sem); return -ENOMEM; } - usbduxsub[index].urb_pwm->transfer_buffer = - kzalloc(usbduxsub[index].size_pwm_buf, GFP_KERNEL); - if (!(usbduxsub[index].urb_pwm->transfer_buffer)) { - tidy_up(&(usbduxsub[index])); + devpriv->urb_pwm = urb; + + /* max bulk ep size in high speed */ + devpriv->size_pwm_buf = 512; + urb->transfer_buffer = kzalloc(devpriv->size_pwm_buf, + GFP_KERNEL); + if (!urb->transfer_buffer) { + tidy_up(devpriv); up(&start_stop_sem); return -ENOMEM; } } else { - usbduxsub[index].urb_pwm = NULL; - usbduxsub[index].size_pwm_buf = 0; + devpriv->urb_pwm = NULL; + devpriv->size_pwm_buf = 0; } - usbduxsub[index].ai_cmd_running = 0; - usbduxsub[index].ao_cmd_running = 0; - usbduxsub[index].pwm_cmd_running = 0; + devpriv->ai_cmd_running = 0; + devpriv->ao_cmd_running = 0; + devpriv->pwm_cmd_running = 0; /* we've reached the bottom of the function */ - usbduxsub[index].probed = 1; + devpriv->probed = 1; up(&start_stop_sem); return comedi_usb_auto_config(uinterf, &usbdux_driver, 0); From 080bcc188782d733500f8315d55bd1f403106e68 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 14:07:39 -0700 Subject: [PATCH 0707/3400] staging: comedi: usbdux: move usb buffer allocation into new function Move all the usb buffer allocation code in the usb_driver (*probe) into a new function, usbdux_alloc_usb_buffers(). This allows tidying up the error path in the (*probe). Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 274 +++++++++++------------- 1 file changed, 128 insertions(+), 146 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index d1651e2cdefe..892ecb53dbf5 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -2238,6 +2238,117 @@ static int usbdux_attach_common(struct comedi_device *dev, return 0; } +static int usbdux_alloc_usb_buffers(struct usbdux_private *devpriv) +{ + struct urb *urb; + int i; + + /* create space for the commands of the DA converter */ + devpriv->dac_commands = kzalloc(NUMOUTCHANNELS, GFP_KERNEL); + if (!devpriv->dac_commands) + return -ENOMEM; + + /* create space for the commands going to the usb device */ + devpriv->dux_commands = kzalloc(SIZEOFDUXBUFFER, GFP_KERNEL); + if (!devpriv->dux_commands) + return -ENOMEM; + + /* create space for the in buffer and set it to zero */ + devpriv->in_buffer = kzalloc(SIZEINBUF, GFP_KERNEL); + if (!devpriv->in_buffer) + return -ENOMEM; + + /* create space of the instruction buffer */ + devpriv->insn_buffer = kzalloc(SIZEINSNBUF, GFP_KERNEL); + if (!devpriv->insn_buffer) + return -ENOMEM; + + /* create space for the outbuffer */ + devpriv->out_buffer = kzalloc(SIZEOUTBUF, GFP_KERNEL); + if (!devpriv->out_buffer) + return -ENOMEM; + + /* in urbs */ + devpriv->urb_in = kcalloc(devpriv->num_in_buffers, sizeof(*urb), + GFP_KERNEL); + if (!devpriv->urb_in) + return -ENOMEM; + + for (i = 0; i < devpriv->num_in_buffers; i++) { + /* one frame: 1ms */ + urb = usb_alloc_urb(1, GFP_KERNEL); + if (!urb) + return -ENOMEM; + devpriv->urb_in[i] = urb; + + urb->dev = devpriv->usbdev; + /* will be filled later with a pointer to the comedi-device */ + /* and ONLY then the urb should be submitted */ + urb->context = NULL; + urb->pipe = usb_rcvisocpipe(devpriv->usbdev, ISOINEP); + urb->transfer_flags = URB_ISO_ASAP; + urb->transfer_buffer = kzalloc(SIZEINBUF, GFP_KERNEL); + if (!urb->transfer_buffer) + return -ENOMEM; + + urb->complete = usbduxsub_ai_isoc_irq; + urb->number_of_packets = 1; + urb->transfer_buffer_length = SIZEINBUF; + urb->iso_frame_desc[0].offset = 0; + urb->iso_frame_desc[0].length = SIZEINBUF; + } + + /* out urbs */ + devpriv->urb_out = kcalloc(devpriv->num_out_buffers, sizeof(*urb), + GFP_KERNEL); + if (!devpriv->urb_out) + return -ENOMEM; + + for (i = 0; i < devpriv->num_out_buffers; i++) { + /* one frame: 1ms */ + urb = usb_alloc_urb(1, GFP_KERNEL); + if (!urb) + return -ENOMEM; + devpriv->urb_out[i] = urb; + + urb->dev = devpriv->usbdev; + /* will be filled later with a pointer to the comedi-device */ + /* and ONLY then the urb should be submitted */ + urb->context = NULL; + urb->pipe = usb_sndisocpipe(devpriv->usbdev, ISOOUTEP); + urb->transfer_flags = URB_ISO_ASAP; + urb->transfer_buffer = kzalloc(SIZEOUTBUF, GFP_KERNEL); + if (!urb->transfer_buffer) + return -ENOMEM; + + urb->complete = usbduxsub_ao_isoc_irq; + urb->number_of_packets = 1; + urb->transfer_buffer_length = SIZEOUTBUF; + urb->iso_frame_desc[0].offset = 0; + urb->iso_frame_desc[0].length = SIZEOUTBUF; + if (devpriv->high_speed) + urb->interval = 8; /* uframes */ + else + urb->interval = 1; /* frames */ + } + + /* pwm */ + if (devpriv->size_pwm_buf) { + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) + return -ENOMEM; + devpriv->urb_pwm = urb; + + /* max bulk ep size in high speed */ + urb->transfer_buffer = kzalloc(devpriv->size_pwm_buf, + GFP_KERNEL); + if (!urb->transfer_buffer) + return -ENOMEM; + } + + return 0; +} + static int usbdux_auto_attach(struct comedi_device *dev, unsigned long context_unused) { @@ -2297,7 +2408,7 @@ static int usbdux_usb_probe(struct usb_interface *uinterf, struct usb_device *udev = interface_to_usbdev(uinterf); struct device *dev = &uinterf->dev; struct usbdux_private *devpriv = NULL; - struct urb *urb; + int ret; int i; down(&start_stop_sem); @@ -2322,160 +2433,31 @@ static int usbdux_usb_probe(struct usb_interface *uinterf, usb_set_intfdata(uinterf, devpriv); devpriv->high_speed = (devpriv->usbdev->speed == USB_SPEED_HIGH); + if (devpriv->high_speed) { + devpriv->num_in_buffers = NUMOFINBUFFERSHIGH; + devpriv->num_out_buffers = NUMOFOUTBUFFERSHIGH; + devpriv->size_pwm_buf = 512; + } else { + devpriv->num_in_buffers = NUMOFINBUFFERSFULL; + devpriv->num_out_buffers = NUMOFOUTBUFFERSFULL; + devpriv->size_pwm_buf = 0; + } - /* create space for the commands of the DA converter */ - devpriv->dac_commands = kzalloc(NUMOUTCHANNELS, GFP_KERNEL); - if (!devpriv->dac_commands) { + ret = usbdux_alloc_usb_buffers(devpriv); + if (ret) { tidy_up(devpriv); up(&start_stop_sem); - return -ENOMEM; - } - /* create space for the commands going to the usb device */ - devpriv->dux_commands = kzalloc(SIZEOFDUXBUFFER, GFP_KERNEL); - if (!devpriv->dux_commands) { - tidy_up(devpriv); - up(&start_stop_sem); - return -ENOMEM; - } - /* create space for the in buffer and set it to zero */ - devpriv->in_buffer = kzalloc(SIZEINBUF, GFP_KERNEL); - if (!devpriv->in_buffer) { - tidy_up(devpriv); - up(&start_stop_sem); - return -ENOMEM; - } - /* create space of the instruction buffer */ - devpriv->insn_buffer = kzalloc(SIZEINSNBUF, GFP_KERNEL); - if (!devpriv->insn_buffer) { - tidy_up(devpriv); - up(&start_stop_sem); - return -ENOMEM; - } - /* create space for the outbuffer */ - devpriv->out_buffer = kzalloc(SIZEOUTBUF, GFP_KERNEL); - if (!devpriv->out_buffer) { - tidy_up(devpriv); - up(&start_stop_sem); - return -ENOMEM; + return ret; } + /* setting to alternate setting 3: enabling iso ep and bulk ep. */ - i = usb_set_interface(devpriv->usbdev, devpriv->ifnum, 3); - if (i < 0) { + ret = usb_set_interface(devpriv->usbdev, devpriv->ifnum, 3); + if (ret < 0) { dev_err(dev, "could not set alternate setting 3 in high speed\n"); tidy_up(devpriv); up(&start_stop_sem); - return -ENODEV; - } - if (devpriv->high_speed) - devpriv->num_in_buffers = NUMOFINBUFFERSHIGH; - else - devpriv->num_in_buffers = NUMOFINBUFFERSFULL; - - devpriv->urb_in = kcalloc(devpriv->num_in_buffers, sizeof(*urb), - GFP_KERNEL); - if (!devpriv->urb_in) { - tidy_up(devpriv); - up(&start_stop_sem); - return -ENOMEM; - } - for (i = 0; i < devpriv->num_in_buffers; i++) { - /* one frame: 1ms */ - urb = usb_alloc_urb(1, GFP_KERNEL); - if (!urb) { - tidy_up(devpriv); - up(&start_stop_sem); - return -ENOMEM; - } - devpriv->urb_in[i] = urb; - - urb->dev = devpriv->usbdev; - /* will be filled later with a pointer to the comedi-device */ - /* and ONLY then the urb should be submitted */ - urb->context = NULL; - urb->pipe = usb_rcvisocpipe(devpriv->usbdev, ISOINEP); - urb->transfer_flags = URB_ISO_ASAP; - urb->transfer_buffer = kzalloc(SIZEINBUF, GFP_KERNEL); - if (!urb->transfer_buffer) { - tidy_up(devpriv); - up(&start_stop_sem); - return -ENOMEM; - } - urb->complete = usbduxsub_ai_isoc_irq; - urb->number_of_packets = 1; - urb->transfer_buffer_length = SIZEINBUF; - urb->iso_frame_desc[0].offset = 0; - urb->iso_frame_desc[0].length = SIZEINBUF; - } - - /* out */ - if (devpriv->high_speed) - devpriv->num_out_buffers = NUMOFOUTBUFFERSHIGH; - else - devpriv->num_out_buffers = NUMOFOUTBUFFERSFULL; - - devpriv->urb_out = kcalloc(devpriv->num_out_buffers, sizeof(*urb), - GFP_KERNEL); - if (!devpriv->urb_out) { - tidy_up(devpriv); - up(&start_stop_sem); - return -ENOMEM; - } - for (i = 0; i < devpriv->num_out_buffers; i++) { - /* one frame: 1ms */ - urb = usb_alloc_urb(1, GFP_KERNEL); - if (!urb) { - tidy_up(devpriv); - up(&start_stop_sem); - return -ENOMEM; - } - devpriv->urb_out[i] = urb; - - urb->dev = devpriv->usbdev; - /* will be filled later with a pointer to the comedi-device */ - /* and ONLY then the urb should be submitted */ - urb->context = NULL; - urb->pipe = usb_sndisocpipe(devpriv->usbdev, ISOOUTEP); - urb->transfer_flags = URB_ISO_ASAP; - urb->transfer_buffer = kzalloc(SIZEOUTBUF, GFP_KERNEL); - if (!(urb->transfer_buffer)) { - tidy_up(devpriv); - up(&start_stop_sem); - return -ENOMEM; - } - urb->complete = usbduxsub_ao_isoc_irq; - urb->number_of_packets = 1; - urb->transfer_buffer_length = SIZEOUTBUF; - urb->iso_frame_desc[0].offset = 0; - urb->iso_frame_desc[0].length = SIZEOUTBUF; - if (devpriv->high_speed) - urb->interval = 8; /* uframes */ - else - urb->interval = 1; /* frames */ - } - - /* pwm */ - if (devpriv->high_speed) { - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) { - tidy_up(devpriv); - up(&start_stop_sem); - return -ENOMEM; - } - devpriv->urb_pwm = urb; - - /* max bulk ep size in high speed */ - devpriv->size_pwm_buf = 512; - urb->transfer_buffer = kzalloc(devpriv->size_pwm_buf, - GFP_KERNEL); - if (!urb->transfer_buffer) { - tidy_up(devpriv); - up(&start_stop_sem); - return -ENOMEM; - } - } else { - devpriv->urb_pwm = NULL; - devpriv->size_pwm_buf = 0; + return ret; } devpriv->ai_cmd_running = 0; From a7dd65f57cc4bf07c3bcfb798577e275186a9c6f Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 14:08:02 -0700 Subject: [PATCH 0708/3400] staging: comedi: usbdux: push usb (*disconnect) into comedi (*detach) The usb_driver (*disconnect) calls comedi_usb_auto_unconfig() which will call the comedi_driver (*detach). Just move all the disconnect/detach into the comedi_driver and use comedi_usb_auto_unconfig() directly for the (*disconnect). Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 40 +++++++------------------ 1 file changed, 10 insertions(+), 30 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 892ecb53dbf5..204dfbb6de19 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -2384,15 +2384,18 @@ static int usbdux_auto_attach(struct comedi_device *dev, static void usbdux_detach(struct comedi_device *dev) { - struct usbdux_private *usb = dev->private; + struct usbdux_private *devpriv = dev->private; - if (usb) { - down(&usb->sem); + down(&start_stop_sem); + if (devpriv) { + down(&devpriv->sem); + tidy_up(devpriv); dev->private = NULL; - usb->attached = 0; - usb->comedidev = NULL; - up(&usb->sem); + devpriv->attached = 0; + devpriv->comedidev = NULL; + up(&devpriv->sem); } + up(&start_stop_sem); } static struct comedi_driver usbdux_driver = { @@ -2471,29 +2474,6 @@ static int usbdux_usb_probe(struct usb_interface *uinterf, return comedi_usb_auto_config(uinterf, &usbdux_driver, 0); } -static void usbdux_usb_disconnect(struct usb_interface *intf) -{ - struct usbdux_private *usbduxsub_tmp = usb_get_intfdata(intf); - struct usb_device *udev = interface_to_usbdev(intf); - - if (!usbduxsub_tmp) { - dev_err(&intf->dev, - "comedi_: disconnect called with null pointer.\n"); - return; - } - if (usbduxsub_tmp->usbdev != udev) { - dev_err(&intf->dev, "comedi_: BUG! called with wrong ptr!!!\n"); - return; - } - comedi_usb_auto_unconfig(intf); - down(&start_stop_sem); - down(&usbduxsub_tmp->sem); - tidy_up(usbduxsub_tmp); - up(&usbduxsub_tmp->sem); - up(&start_stop_sem); - dev_dbg(&intf->dev, "comedi_: disconnected from the usb\n"); -} - static const struct usb_device_id usbdux_usb_table[] = { { USB_DEVICE(0x13d8, 0x0001) }, { USB_DEVICE(0x13d8, 0x0002) }, @@ -2505,7 +2485,7 @@ MODULE_DEVICE_TABLE(usb, usbdux_usb_table); static struct usb_driver usbdux_usb_driver = { .name = "usbdux", .probe = usbdux_usb_probe, - .disconnect = usbdux_usb_disconnect, + .disconnect = comedi_usb_auto_unconfig, .id_table = usbdux_usb_table, }; module_comedi_usb_driver(usbdux_driver, usbdux_usb_driver); From ef1ee8cf126a84f5049c6dbf5dc3a350fdc84262 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 14:08:24 -0700 Subject: [PATCH 0709/3400] staging: comedi: usbdux: push usb (*probe) into comedi (*auto_attach) The usb_driver (*probe) calls comedi_usb_auto_config() after finding a free slot for the static private data and doind some initial allocation and setup. The comedi_usb_auto_config() will then call the comedi_driver (*auto_attach). Move all the probe/auto_attach into the comedi_driver and just have the usb_driver call comedi_usb_auto_config(). This allows the comedi_driver to allocate the private data and removes the need for the static array and the semaphore that protects it. Since all the probe/auto_attach is now handled by the comedi_driver, we can also remove the 'attached' and 'probed' information from the private data. The subdevice functions will only be hooked up if the usb device has been probed and the comedi device is attached. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 218 +++++------------------- 1 file changed, 42 insertions(+), 176 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 204dfbb6de19..8102efbced79 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -185,9 +185,6 @@ sampling rate. If you sample two channels you get 4kHz and so on. /* must have more buffers due to buggy USB ctr */ #define NUMOFOUTBUFFERSHIGH 10 -/* Total number of usbdux devices */ -#define NUMUSBDUX 16 - /* Analogue in subdevice */ #define SUBDEV_AD 0 @@ -229,10 +226,6 @@ static const struct comedi_lrange range_usbdux_ao_range = { 2, { }; struct usbdux_private { - /* attached? */ - int attached; - /* is it associated with a subdevice? */ - int probed; /* pointer to the usb-device */ struct usb_device *usbdev; /* actual number of in-buffers */ @@ -290,17 +283,6 @@ struct usbdux_private { struct semaphore sem; }; -/* - * The pointer to the private usb-data of the driver is also the private data - * for the comedi-device. This has to be global as the usb subsystem needs - * global variables. The other reason is that this structure must be there - * _before_ any comedi command is issued. The usb subsystem must be initialised - * before comedi can access it. - */ -static struct usbdux_private usbduxsub[NUMUSBDUX]; - -static DEFINE_SEMAPHORE(start_stop_sem); - /* * Stops the data acquision * It should be safe to call this function from any context @@ -369,10 +351,6 @@ static int usbdux_ai_cancel(struct comedi_device *dev, /* prevent other CPUs from submitting new commands just now */ down(&this_usbduxsub->sem); - if (!(this_usbduxsub->probed)) { - up(&this_usbduxsub->sem); - return -ENODEV; - } /* unlink only if the urb really has been submitted */ res = usbdux_ai_stop(this_usbduxsub, this_usbduxsub->ai_cmd_running); up(&this_usbduxsub->sem); @@ -569,10 +547,6 @@ static int usbdux_ao_cancel(struct comedi_device *dev, /* prevent other CPUs from submitting a command just now */ down(&this_usbduxsub->sem); - if (!(this_usbduxsub->probed)) { - up(&this_usbduxsub->sem); - return -ENODEV; - } /* unlink only if it is really running */ res = usbdux_ao_stop(this_usbduxsub, this_usbduxsub->ao_cmd_running); up(&this_usbduxsub->sem); @@ -856,9 +830,6 @@ static int usbdux_ai_cmdtest(struct comedi_device *dev, int err = 0, i; unsigned int tmp_timer; - if (!(this_usbduxsub->probed)) - return -ENODEV; - /* Step 1 : check if triggers are trivially valid */ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT); @@ -1024,10 +995,6 @@ static int usbdux_ai_inttrig(struct comedi_device *dev, return -EFAULT; down(&this_usbduxsub->sem); - if (!(this_usbduxsub->probed)) { - up(&this_usbduxsub->sem); - return -ENODEV; - } dev_dbg(&this_usbduxsub->interface->dev, "comedi%d: usbdux_ai_inttrig\n", dev->minor); @@ -1075,11 +1042,6 @@ static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* block other CPUs from starting an ai_cmd */ down(&this_usbduxsub->sem); - - if (!(this_usbduxsub->probed)) { - up(&this_usbduxsub->sem); - return -ENODEV; - } if (this_usbduxsub->ai_cmd_running) { dev_err(&this_usbduxsub->interface->dev, "comedi%d: " "ai_cmd not possible. Another ai_cmd is running.\n", @@ -1194,10 +1156,6 @@ static int usbdux_ai_insn_read(struct comedi_device *dev, dev->minor, insn->n, insn->subdev); down(&this_usbduxsub->sem); - if (!(this_usbduxsub->probed)) { - up(&this_usbduxsub->sem); - return -ENODEV; - } if (this_usbduxsub->ai_cmd_running) { dev_err(&this_usbduxsub->interface->dev, "comedi%d: ai_insn_read not possible. " @@ -1250,10 +1208,6 @@ static int usbdux_ao_insn_read(struct comedi_device *dev, return -EFAULT; down(&this_usbduxsub->sem); - if (!(this_usbduxsub->probed)) { - up(&this_usbduxsub->sem); - return -ENODEV; - } for (i = 0; i < insn->n; i++) data[i] = this_usbduxsub->out_buffer[chan]; @@ -1276,10 +1230,6 @@ static int usbdux_ao_insn_write(struct comedi_device *dev, "comedi%d: ao_insn_write\n", dev->minor); down(&this_usbduxsub->sem); - if (!(this_usbduxsub->probed)) { - up(&this_usbduxsub->sem); - return -ENODEV; - } if (this_usbduxsub->ao_cmd_running) { dev_err(&this_usbduxsub->interface->dev, "comedi%d: ao_insn_write: " @@ -1322,10 +1272,6 @@ static int usbdux_ao_inttrig(struct comedi_device *dev, return -EFAULT; down(&this_usbduxsub->sem); - if (!(this_usbduxsub->probed)) { - up(&this_usbduxsub->sem); - return -ENODEV; - } if (trignum != 0) { dev_err(&this_usbduxsub->interface->dev, "comedi%d: usbdux_ao_inttrig: invalid trignum\n", @@ -1364,9 +1310,6 @@ static int usbdux_ao_cmdtest(struct comedi_device *dev, if (!this_usbduxsub) return -EFAULT; - if (!(this_usbduxsub->probed)) - return -ENODEV; - /* Step 1 : check if triggers are trivially valid */ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT); @@ -1452,10 +1395,6 @@ static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) return -EFAULT; down(&this_usbduxsub->sem); - if (!(this_usbduxsub->probed)) { - up(&this_usbduxsub->sem); - return -ENODEV; - } dev_dbg(&this_usbduxsub->interface->dev, "comedi%d: %s\n", dev->minor, __func__); @@ -1593,11 +1532,6 @@ static int usbdux_dio_insn_bits(struct comedi_device *dev, down(&this_usbduxsub->sem); - if (!(this_usbduxsub->probed)) { - up(&this_usbduxsub->sem); - return -ENODEV; - } - /* The insn data is a mask in data[0] and the new data * in data[1], each channel cooresponding to a bit. */ s->state &= ~data[0]; @@ -1636,12 +1570,6 @@ static int usbdux_counter_read(struct comedi_device *dev, return -EFAULT; down(&this_usbduxsub->sem); - - if (!(this_usbduxsub->probed)) { - up(&this_usbduxsub->sem); - return -ENODEV; - } - err = send_dux_commands(this_usbduxsub, READCOUNTERCOMMAND); if (err < 0) { up(&this_usbduxsub->sem); @@ -1670,12 +1598,6 @@ static int usbdux_counter_write(struct comedi_device *dev, return -EFAULT; down(&this_usbduxsub->sem); - - if (!(this_usbduxsub->probed)) { - up(&this_usbduxsub->sem); - return -ENODEV; - } - this_usbduxsub->dux_commands[1] = insn->chanspec; *((int16_t *) (this_usbduxsub->dux_commands + 2)) = cpu_to_le16(*data); @@ -2050,8 +1972,6 @@ static void tidy_up(struct usbdux_private *usbduxsub_tmp) if (usbduxsub_tmp->interface) usb_set_intfdata(usbduxsub_tmp->interface, NULL); - usbduxsub_tmp->probed = 0; - if (usbduxsub_tmp->urb_in) { if (usbduxsub_tmp->ai_cmd_running) { usbduxsub_tmp->ai_cmd_running = 0; @@ -2110,9 +2030,9 @@ static void tidy_up(struct usbdux_private *usbduxsub_tmp) usbduxsub_tmp->pwm_cmd_running = 0; } -static int usbdux_attach_common(struct comedi_device *dev, - struct usbdux_private *udev) +static int usbdux_attach_common(struct comedi_device *dev) { + struct usbdux_private *udev = dev->private; int ret; struct comedi_subdevice *s = NULL; int n_subdevs; @@ -2136,9 +2056,6 @@ static int usbdux_attach_common(struct comedi_device *dev, return ret; } - /* private structure is also simply the usb-structure */ - dev->private = udev; - /* the first subdevice is the A/D converter */ s = &dev->subdevices[SUBDEV_AD]; /* the URBs get the comedi subdevice */ @@ -2227,8 +2144,6 @@ static int usbdux_attach_common(struct comedi_device *dev, s->insn_config = usbdux_pwm_config; usbdux_pwm_period(dev, s, PWM_DEFAULT_PERIOD); } - /* finally decide that it's attached */ - udev->attached = 1; up(&udev->sem); @@ -2352,88 +2267,21 @@ static int usbdux_alloc_usb_buffers(struct usbdux_private *devpriv) static int usbdux_auto_attach(struct comedi_device *dev, unsigned long context_unused) { - struct usb_interface *uinterf = comedi_to_usb_interface(dev); - struct usbdux_private *this_usbduxsub = usb_get_intfdata(uinterf); - struct usb_device *usb = usbduxsub->usbdev; + struct usb_interface *intf = comedi_to_usb_interface(dev); + struct usb_device *usb = comedi_to_usb_dev(dev); + struct usbdux_private *devpriv; int ret; - dev->private = this_usbduxsub; /* This is temporary... */ - ret = comedi_load_firmware(dev, &usb->dev, FIRMWARE, - usbdux_firmware_upload, 0); - if (ret < 0) { - dev->private = NULL; - return ret; - } - - dev->private = NULL; - - down(&start_stop_sem); - if (!this_usbduxsub || !this_usbduxsub->probed) { - dev_err(dev->class_dev, - "usbdux: error: auto_attach failed, not connected\n"); - ret = -ENODEV; - } else if (this_usbduxsub->attached) { - dev_err(dev->class_dev, - "error: auto_attach failed, already attached\n"); - ret = -ENODEV; - } else - ret = usbdux_attach_common(dev, this_usbduxsub); - up(&start_stop_sem); - return ret; -} - -static void usbdux_detach(struct comedi_device *dev) -{ - struct usbdux_private *devpriv = dev->private; - - down(&start_stop_sem); - if (devpriv) { - down(&devpriv->sem); - tidy_up(devpriv); - dev->private = NULL; - devpriv->attached = 0; - devpriv->comedidev = NULL; - up(&devpriv->sem); - } - up(&start_stop_sem); -} - -static struct comedi_driver usbdux_driver = { - .driver_name = "usbdux", - .module = THIS_MODULE, - .auto_attach = usbdux_auto_attach, - .detach = usbdux_detach, -}; - -static int usbdux_usb_probe(struct usb_interface *uinterf, - const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(uinterf); - struct device *dev = &uinterf->dev; - struct usbdux_private *devpriv = NULL; - int ret; - int i; - - down(&start_stop_sem); - - for (i = 0; i < NUMUSBDUX; i++) { - if (!usbduxsub[i].probed) { - devpriv = &usbduxsub[i]; - break; - } - } - if (!devpriv) { - dev_err(dev, "Too many usbdux-devices connected.\n"); - up(&start_stop_sem); - return -EMFILE; - } + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); + if (!devpriv) + return -ENOMEM; sema_init(&devpriv->sem, 1); - devpriv->usbdev = udev; - devpriv->interface = uinterf; - devpriv->ifnum = uinterf->altsetting->desc.bInterfaceNumber; - usb_set_intfdata(uinterf, devpriv); + devpriv->usbdev = usb; + devpriv->interface = intf; + devpriv->ifnum = intf->altsetting->desc.bInterfaceNumber; + usb_set_intfdata(intf, devpriv); devpriv->high_speed = (devpriv->usbdev->speed == USB_SPEED_HIGH); if (devpriv->high_speed) { @@ -2443,35 +2291,54 @@ static int usbdux_usb_probe(struct usb_interface *uinterf, } else { devpriv->num_in_buffers = NUMOFINBUFFERSFULL; devpriv->num_out_buffers = NUMOFOUTBUFFERSFULL; - devpriv->size_pwm_buf = 0; } ret = usbdux_alloc_usb_buffers(devpriv); if (ret) { tidy_up(devpriv); - up(&start_stop_sem); return ret; } /* setting to alternate setting 3: enabling iso ep and bulk ep. */ ret = usb_set_interface(devpriv->usbdev, devpriv->ifnum, 3); if (ret < 0) { - dev_err(dev, + dev_err(dev->class_dev, "could not set alternate setting 3 in high speed\n"); tidy_up(devpriv); - up(&start_stop_sem); return ret; } - devpriv->ai_cmd_running = 0; - devpriv->ao_cmd_running = 0; - devpriv->pwm_cmd_running = 0; + ret = comedi_load_firmware(dev, &usb->dev, FIRMWARE, + usbdux_firmware_upload, 0); + if (ret < 0) + return ret; - /* we've reached the bottom of the function */ - devpriv->probed = 1; - up(&start_stop_sem); + return usbdux_attach_common(dev); +} - return comedi_usb_auto_config(uinterf, &usbdux_driver, 0); +static void usbdux_detach(struct comedi_device *dev) +{ + struct usbdux_private *devpriv = dev->private; + + if (devpriv) { + down(&devpriv->sem); + tidy_up(devpriv); + devpriv->comedidev = NULL; + up(&devpriv->sem); + } +} + +static struct comedi_driver usbdux_driver = { + .driver_name = "usbdux", + .module = THIS_MODULE, + .auto_attach = usbdux_auto_attach, + .detach = usbdux_detach, +}; + +static int usbdux_usb_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + return comedi_usb_auto_config(intf, &usbdux_driver, 0); } static const struct usb_device_id usbdux_usb_table[] = { @@ -2479,7 +2346,6 @@ static const struct usb_device_id usbdux_usb_table[] = { { USB_DEVICE(0x13d8, 0x0002) }, { } }; - MODULE_DEVICE_TABLE(usb, usbdux_usb_table); static struct usb_driver usbdux_usb_driver = { From 29d0c07428d590ad93fd4721ff0e2f8f5ca8f264 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 14:08:43 -0700 Subject: [PATCH 0710/3400] staging: comedi: usbdux: remove unnecessary tidy_up() calls If the comedi_driver (*auto_attach) fails, the comedi core will call the (*detach) function to do any cleanup. It's not necessary to do the cleanup in the (*auto_attach). Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 8102efbced79..6a7d7f4aabec 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -2294,17 +2294,14 @@ static int usbdux_auto_attach(struct comedi_device *dev, } ret = usbdux_alloc_usb_buffers(devpriv); - if (ret) { - tidy_up(devpriv); + if (ret) return ret; - } /* setting to alternate setting 3: enabling iso ep and bulk ep. */ ret = usb_set_interface(devpriv->usbdev, devpriv->ifnum, 3); if (ret < 0) { dev_err(dev->class_dev, "could not set alternate setting 3 in high speed\n"); - tidy_up(devpriv); return ret; } From 8ff14ee8a6e4d9aca3098c47e876bc43f9e4cbe5 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 14:09:04 -0700 Subject: [PATCH 0711/3400] staging: comedi: usbdux: cleanup the (*detach) The tidy_up() function is only called by the (*detach). That function unlinks any running urbs and frees all the allocated urbs and buffers used by the driver. Rename tidy_up() to usbdux_free_usb_buffers() and move all the parts that don't deal with the freeing of the buffers directly into the (*detach). Also, remove all the unnecessary clearing of the pointers. The comedi core will kfree() the private data after calling the (*detach). Foe aesthetic reasons, do the kfree()'ing of the buffers and urbs in the reverse order that they were allocated. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 124 ++++++++++-------------- 1 file changed, 53 insertions(+), 71 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 6a7d7f4aabec..f7efc85e294e 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -1960,76 +1960,6 @@ static int usbdux_pwm_config(struct comedi_device *dev, /* end of PWM */ /*****************************************************************/ -static void tidy_up(struct usbdux_private *usbduxsub_tmp) -{ - int i; - - if (!usbduxsub_tmp) - return; - dev_dbg(&usbduxsub_tmp->interface->dev, "comedi_: tiding up\n"); - - /* shows the usb subsystem that the driver is down */ - if (usbduxsub_tmp->interface) - usb_set_intfdata(usbduxsub_tmp->interface, NULL); - - if (usbduxsub_tmp->urb_in) { - if (usbduxsub_tmp->ai_cmd_running) { - usbduxsub_tmp->ai_cmd_running = 0; - usbduxsub_unlink_inurbs(usbduxsub_tmp); - } - for (i = 0; i < usbduxsub_tmp->num_in_buffers; i++) { - kfree(usbduxsub_tmp->urb_in[i]->transfer_buffer); - usbduxsub_tmp->urb_in[i]->transfer_buffer = NULL; - usb_kill_urb(usbduxsub_tmp->urb_in[i]); - usb_free_urb(usbduxsub_tmp->urb_in[i]); - usbduxsub_tmp->urb_in[i] = NULL; - } - kfree(usbduxsub_tmp->urb_in); - usbduxsub_tmp->urb_in = NULL; - } - if (usbduxsub_tmp->urb_out) { - if (usbduxsub_tmp->ao_cmd_running) { - usbduxsub_tmp->ao_cmd_running = 0; - usbduxsub_unlink_outurbs(usbduxsub_tmp); - } - for (i = 0; i < usbduxsub_tmp->num_out_buffers; i++) { - kfree(usbduxsub_tmp->urb_out[i]->transfer_buffer); - usbduxsub_tmp->urb_out[i]->transfer_buffer = NULL; - if (usbduxsub_tmp->urb_out[i]) { - usb_kill_urb(usbduxsub_tmp->urb_out[i]); - usb_free_urb(usbduxsub_tmp->urb_out[i]); - usbduxsub_tmp->urb_out[i] = NULL; - } - } - kfree(usbduxsub_tmp->urb_out); - usbduxsub_tmp->urb_out = NULL; - } - if (usbduxsub_tmp->urb_pwm) { - if (usbduxsub_tmp->pwm_cmd_running) { - usbduxsub_tmp->pwm_cmd_running = 0; - usbduxsub_unlink_pwm_urbs(usbduxsub_tmp); - } - kfree(usbduxsub_tmp->urb_pwm->transfer_buffer); - usbduxsub_tmp->urb_pwm->transfer_buffer = NULL; - usb_kill_urb(usbduxsub_tmp->urb_pwm); - usb_free_urb(usbduxsub_tmp->urb_pwm); - usbduxsub_tmp->urb_pwm = NULL; - } - kfree(usbduxsub_tmp->in_buffer); - usbduxsub_tmp->in_buffer = NULL; - kfree(usbduxsub_tmp->insn_buffer); - usbduxsub_tmp->insn_buffer = NULL; - kfree(usbduxsub_tmp->out_buffer); - usbduxsub_tmp->out_buffer = NULL; - kfree(usbduxsub_tmp->dac_commands); - usbduxsub_tmp->dac_commands = NULL; - kfree(usbduxsub_tmp->dux_commands); - usbduxsub_tmp->dux_commands = NULL; - usbduxsub_tmp->ai_cmd_running = 0; - usbduxsub_tmp->ao_cmd_running = 0; - usbduxsub_tmp->pwm_cmd_running = 0; -} - static int usbdux_attach_common(struct comedi_device *dev) { struct usbdux_private *udev = dev->private; @@ -2264,6 +2194,46 @@ static int usbdux_alloc_usb_buffers(struct usbdux_private *devpriv) return 0; } +static void usbdux_free_usb_buffers(struct usbdux_private *devpriv) +{ + struct urb *urb; + int i; + + urb = devpriv->urb_pwm; + if (urb) { + kfree(urb->transfer_buffer); + usb_kill_urb(urb); + usb_free_urb(urb); + } + if (devpriv->urb_out) { + for (i = 0; i < devpriv->num_out_buffers; i++) { + urb = devpriv->urb_out[i]; + if (urb) { + kfree(urb->transfer_buffer); + usb_kill_urb(urb); + usb_free_urb(urb); + } + } + kfree(devpriv->urb_out); + } + if (devpriv->urb_in) { + for (i = 0; i < devpriv->num_in_buffers; i++) { + urb = devpriv->urb_in[i]; + if (urb) { + kfree(urb->transfer_buffer); + usb_kill_urb(urb); + usb_free_urb(urb); + } + } + kfree(devpriv->urb_in); + } + kfree(devpriv->out_buffer); + kfree(devpriv->insn_buffer); + kfree(devpriv->in_buffer); + kfree(devpriv->dux_commands); + kfree(devpriv->dac_commands); +} + static int usbdux_auto_attach(struct comedi_device *dev, unsigned long context_unused) { @@ -2319,8 +2289,20 @@ static void usbdux_detach(struct comedi_device *dev) if (devpriv) { down(&devpriv->sem); - tidy_up(devpriv); + + usb_set_intfdata(devpriv->interface, NULL); + + if (devpriv->pwm_cmd_running) + usbduxsub_unlink_pwm_urbs(devpriv); + if (devpriv->ao_cmd_running) + usbduxsub_unlink_outurbs(devpriv); + if (devpriv->ai_cmd_running) + usbduxsub_unlink_inurbs(devpriv); + + usbdux_free_usb_buffers(devpriv); + devpriv->comedidev = NULL; + up(&devpriv->sem); } } From ee9c2dd35c368c588018c3bad591717cf6bd373a Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 14:09:24 -0700 Subject: [PATCH 0712/3400] staging: comedi: usbdux: remove NOISY_DUX_DEBUGBUG This define enables printing of the 'dux_commands' that is sent to the usb device in send_dux_commands(). This type of development debug should not be left in the final driver. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index f7efc85e294e..f41b8361bee3 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -78,9 +78,6 @@ sampling rate. If you sample two channels you get 4kHz and so on. * */ -/* generates loads of debug info */ -/* #define NOISY_DUX_DEBUGBUG */ - #include #include #include @@ -936,13 +933,6 @@ static int send_dux_commands(struct usbdux_private *this_usbduxsub, int cmd_type int result, nsent; this_usbduxsub->dux_commands[0] = cmd_type; -#ifdef NOISY_DUX_DEBUGBUG - printk(KERN_DEBUG "comedi%d: usbdux: dux_commands: ", - this_usbduxsub->comedidev->minor); - for (result = 0; result < SIZEOFDUXBUFFER; result++) - printk(" %02x", this_usbduxsub->dux_commands[result]); - printk("\n"); -#endif result = usb_bulk_msg(this_usbduxsub->usbdev, usb_sndbulkpipe(this_usbduxsub->usbdev, COMMAND_OUT_EP), From 72db740fd9ddc5cf4fc487d42bbfbbb7dfc2e564 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 14:09:51 -0700 Subject: [PATCH 0713/3400] staging: comedi: usbdux: tidy up usbdux_attach_common() Rename the local variable used for the device private data. Move the setting of the device private data 'comedidev' to the (*auto_attach) where the other back pointers are set. Tidy up the subdevice init by removing the unnecessary comments and adding some whitespace. Remove the unnecessary dev_info() after a sucessful attach. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 152 +++++++++--------------- 1 file changed, 56 insertions(+), 96 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index f41b8361bee3..460c06683435 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -1952,123 +1952,82 @@ static int usbdux_pwm_config(struct comedi_device *dev, static int usbdux_attach_common(struct comedi_device *dev) { - struct usbdux_private *udev = dev->private; + struct usbdux_private *devpriv = dev->private; + struct comedi_subdevice *s; int ret; - struct comedi_subdevice *s = NULL; - int n_subdevs; - down(&udev->sem); - /* pointer back to the corresponding comedi device */ - udev->comedidev = dev; + down(&devpriv->sem); - /* set number of subdevices */ - if (udev->high_speed) { - /* with pwm */ - n_subdevs = 5; - } else { - /* without pwm */ - n_subdevs = 4; - } - - ret = comedi_alloc_subdevices(dev, n_subdevs); + ret = comedi_alloc_subdevices(dev, (devpriv->high_speed) ? 5 : 4); if (ret) { - up(&udev->sem); + up(&devpriv->sem); return ret; } - /* the first subdevice is the A/D converter */ + /* Analog Input subdevice */ s = &dev->subdevices[SUBDEV_AD]; - /* the URBs get the comedi subdevice */ - /* which is responsible for reading */ - /* this is the subdevice which reads data */ dev->read_subdev = s; - /* the subdevice receives as private structure the */ - /* usb-structure */ - s->private = NULL; - /* analog input */ - s->type = COMEDI_SUBD_AI; - /* readable and ref is to ground */ - s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ; - /* 8 channels */ - s->n_chan = 8; - /* length of the channellist */ - s->len_chanlist = 8; - /* callback functions */ - s->insn_read = usbdux_ai_insn_read; - s->do_cmdtest = usbdux_ai_cmdtest; - s->do_cmd = usbdux_ai_cmd; - s->cancel = usbdux_ai_cancel; - /* max value from the A/D converter (12bit) */ - s->maxdata = 0xfff; - /* range table to convert to physical units */ - s->range_table = (&range_usbdux_ai_range); + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ; + s->n_chan = 8; + s->maxdata = 0x0fff; + s->len_chanlist = 8; + s->range_table = &range_usbdux_ai_range; + s->insn_read = usbdux_ai_insn_read; + s->do_cmdtest = usbdux_ai_cmdtest; + s->do_cmd = usbdux_ai_cmd; + s->cancel = usbdux_ai_cancel; - /* analog out */ + /* Analog Output subdevice */ s = &dev->subdevices[SUBDEV_DA]; - /* analog out */ - s->type = COMEDI_SUBD_AO; - /* backward pointer */ dev->write_subdev = s; - /* the subdevice receives as private structure the */ - /* usb-structure */ - s->private = NULL; - /* are writable */ - s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE; - /* 4 channels */ - s->n_chan = 4; - /* length of the channellist */ - s->len_chanlist = 4; - /* 12 bit resolution */ - s->maxdata = 0x0fff; - /* bipolar range */ - s->range_table = (&range_usbdux_ao_range); - /* callback */ - s->do_cmdtest = usbdux_ao_cmdtest; - s->do_cmd = usbdux_ao_cmd; - s->cancel = usbdux_ao_cancel; - s->insn_read = usbdux_ao_insn_read; - s->insn_write = usbdux_ao_insn_write; + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE; + s->n_chan = 4; + s->maxdata = 0x0fff; + s->len_chanlist = 4; + s->range_table = &range_usbdux_ao_range; + s->do_cmdtest = usbdux_ao_cmdtest; + s->do_cmd = usbdux_ao_cmd; + s->cancel = usbdux_ao_cancel; + s->insn_read = usbdux_ao_insn_read; + s->insn_write = usbdux_ao_insn_write; - /* digital I/O */ + /* Digital I/O subdevice */ s = &dev->subdevices[SUBDEV_DIO]; - s->type = COMEDI_SUBD_DIO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = 8; - s->maxdata = 1; - s->range_table = (&range_digital); - s->insn_bits = usbdux_dio_insn_bits; - s->insn_config = usbdux_dio_insn_config; - /* we don't use it */ - s->private = NULL; + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 8; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = usbdux_dio_insn_bits; + s->insn_config = usbdux_dio_insn_config; - /* counter */ + /* Counter subdevice */ s = &dev->subdevices[SUBDEV_COUNTER]; - s->type = COMEDI_SUBD_COUNTER; - s->subdev_flags = SDF_WRITABLE | SDF_READABLE; - s->n_chan = 4; - s->maxdata = 0xFFFF; - s->insn_read = usbdux_counter_read; - s->insn_write = usbdux_counter_write; - s->insn_config = usbdux_counter_config; + s->type = COMEDI_SUBD_COUNTER; + s->subdev_flags = SDF_WRITABLE | SDF_READABLE; + s->n_chan = 4; + s->maxdata = 0xffff; + s->insn_read = usbdux_counter_read; + s->insn_write = usbdux_counter_write; + s->insn_config = usbdux_counter_config; - if (udev->high_speed) { - /* timer / pwm */ + if (devpriv->high_speed) { + /* PWM subdevice */ s = &dev->subdevices[SUBDEV_PWM]; - s->type = COMEDI_SUBD_PWM; - s->subdev_flags = SDF_WRITABLE | SDF_PWM_HBRIDGE; - s->n_chan = 8; - /* this defines the max duty cycle resolution */ - s->maxdata = udev->size_pwm_buf; - s->insn_write = usbdux_pwm_write; - s->insn_read = usbdux_pwm_read; - s->insn_config = usbdux_pwm_config; + s->type = COMEDI_SUBD_PWM; + s->subdev_flags = SDF_WRITABLE | SDF_PWM_HBRIDGE; + s->n_chan = 8; + s->maxdata = devpriv->size_pwm_buf; + s->insn_write = usbdux_pwm_write; + s->insn_read = usbdux_pwm_read; + s->insn_config = usbdux_pwm_config; + usbdux_pwm_period(dev, s, PWM_DEFAULT_PERIOD); } - up(&udev->sem); - - dev_info(&udev->interface->dev, "comedi%d: attached to usbdux.\n", - dev->minor); + up(&devpriv->sem); return 0; } @@ -2238,6 +2197,7 @@ static int usbdux_auto_attach(struct comedi_device *dev, sema_init(&devpriv->sem, 1); + devpriv->comedidev = dev; devpriv->usbdev = usb; devpriv->interface = intf; devpriv->ifnum = intf->altsetting->desc.bInterfaceNumber; From cc84f4f980449d5274ec38e33718f0cc76f66888 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 14:10:11 -0700 Subject: [PATCH 0714/3400] staging: comedi: usbdux: absorb usbdux_attach_common into caller This function is only called by usbdux_auto_attach(), absorb it. Also, there is no reason to down/up the semaphore during the attach. None of the subdevices are functioning yet so there are no commands being sent to the usb device. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 152 +++++++++++------------- 1 file changed, 69 insertions(+), 83 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 460c06683435..32021f03bda2 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -1950,88 +1950,6 @@ static int usbdux_pwm_config(struct comedi_device *dev, /* end of PWM */ /*****************************************************************/ -static int usbdux_attach_common(struct comedi_device *dev) -{ - struct usbdux_private *devpriv = dev->private; - struct comedi_subdevice *s; - int ret; - - down(&devpriv->sem); - - ret = comedi_alloc_subdevices(dev, (devpriv->high_speed) ? 5 : 4); - if (ret) { - up(&devpriv->sem); - return ret; - } - - /* Analog Input subdevice */ - s = &dev->subdevices[SUBDEV_AD]; - dev->read_subdev = s; - s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ; - s->n_chan = 8; - s->maxdata = 0x0fff; - s->len_chanlist = 8; - s->range_table = &range_usbdux_ai_range; - s->insn_read = usbdux_ai_insn_read; - s->do_cmdtest = usbdux_ai_cmdtest; - s->do_cmd = usbdux_ai_cmd; - s->cancel = usbdux_ai_cancel; - - /* Analog Output subdevice */ - s = &dev->subdevices[SUBDEV_DA]; - dev->write_subdev = s; - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE; - s->n_chan = 4; - s->maxdata = 0x0fff; - s->len_chanlist = 4; - s->range_table = &range_usbdux_ao_range; - s->do_cmdtest = usbdux_ao_cmdtest; - s->do_cmd = usbdux_ao_cmd; - s->cancel = usbdux_ao_cancel; - s->insn_read = usbdux_ao_insn_read; - s->insn_write = usbdux_ao_insn_write; - - /* Digital I/O subdevice */ - s = &dev->subdevices[SUBDEV_DIO]; - s->type = COMEDI_SUBD_DIO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = 8; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = usbdux_dio_insn_bits; - s->insn_config = usbdux_dio_insn_config; - - /* Counter subdevice */ - s = &dev->subdevices[SUBDEV_COUNTER]; - s->type = COMEDI_SUBD_COUNTER; - s->subdev_flags = SDF_WRITABLE | SDF_READABLE; - s->n_chan = 4; - s->maxdata = 0xffff; - s->insn_read = usbdux_counter_read; - s->insn_write = usbdux_counter_write; - s->insn_config = usbdux_counter_config; - - if (devpriv->high_speed) { - /* PWM subdevice */ - s = &dev->subdevices[SUBDEV_PWM]; - s->type = COMEDI_SUBD_PWM; - s->subdev_flags = SDF_WRITABLE | SDF_PWM_HBRIDGE; - s->n_chan = 8; - s->maxdata = devpriv->size_pwm_buf; - s->insn_write = usbdux_pwm_write; - s->insn_read = usbdux_pwm_read; - s->insn_config = usbdux_pwm_config; - - usbdux_pwm_period(dev, s, PWM_DEFAULT_PERIOD); - } - - up(&devpriv->sem); - - return 0; -} - static int usbdux_alloc_usb_buffers(struct usbdux_private *devpriv) { struct urb *urb; @@ -2189,6 +2107,7 @@ static int usbdux_auto_attach(struct comedi_device *dev, struct usb_interface *intf = comedi_to_usb_interface(dev); struct usb_device *usb = comedi_to_usb_dev(dev); struct usbdux_private *devpriv; + struct comedi_subdevice *s; int ret; devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); @@ -2230,7 +2149,74 @@ static int usbdux_auto_attach(struct comedi_device *dev, if (ret < 0) return ret; - return usbdux_attach_common(dev); + ret = comedi_alloc_subdevices(dev, (devpriv->high_speed) ? 5 : 4); + if (ret) + return ret; + + /* Analog Input subdevice */ + s = &dev->subdevices[SUBDEV_AD]; + dev->read_subdev = s; + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ; + s->n_chan = 8; + s->maxdata = 0x0fff; + s->len_chanlist = 8; + s->range_table = &range_usbdux_ai_range; + s->insn_read = usbdux_ai_insn_read; + s->do_cmdtest = usbdux_ai_cmdtest; + s->do_cmd = usbdux_ai_cmd; + s->cancel = usbdux_ai_cancel; + + /* Analog Output subdevice */ + s = &dev->subdevices[SUBDEV_DA]; + dev->write_subdev = s; + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE; + s->n_chan = 4; + s->maxdata = 0x0fff; + s->len_chanlist = 4; + s->range_table = &range_usbdux_ao_range; + s->do_cmdtest = usbdux_ao_cmdtest; + s->do_cmd = usbdux_ao_cmd; + s->cancel = usbdux_ao_cancel; + s->insn_read = usbdux_ao_insn_read; + s->insn_write = usbdux_ao_insn_write; + + /* Digital I/O subdevice */ + s = &dev->subdevices[SUBDEV_DIO]; + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 8; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = usbdux_dio_insn_bits; + s->insn_config = usbdux_dio_insn_config; + + /* Counter subdevice */ + s = &dev->subdevices[SUBDEV_COUNTER]; + s->type = COMEDI_SUBD_COUNTER; + s->subdev_flags = SDF_WRITABLE | SDF_READABLE; + s->n_chan = 4; + s->maxdata = 0xffff; + s->insn_read = usbdux_counter_read; + s->insn_write = usbdux_counter_write; + s->insn_config = usbdux_counter_config; + + if (devpriv->high_speed) { + /* PWM subdevice */ + s = &dev->subdevices[SUBDEV_PWM]; + s->type = COMEDI_SUBD_PWM; + s->subdev_flags = SDF_WRITABLE | SDF_PWM_HBRIDGE; + s->n_chan = 8; + s->maxdata = devpriv->size_pwm_buf; + s->insn_write = usbdux_pwm_write; + s->insn_read = usbdux_pwm_read; + s->insn_config = usbdux_pwm_config; + + usbdux_pwm_period(dev, s, PWM_DEFAULT_PERIOD); + } + + return 0; } static void usbdux_detach(struct comedi_device *dev) From 0a9502f2c36539b6ad7fc5b9230ee2d9d34b6777 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 14:10:32 -0700 Subject: [PATCH 0715/3400] staging: comedi: usbdux: tidy up usbduxsub_ai_isoc_irq() Rename the local variables to the comedi "norm". The comedi_subdevice in this function is actually the dev->read_subdev that was initialized in the attach. Use that instead of accessing the dev->subdevices array directly. Use dev->class_dev as the device for all dev_printk() messages. Instead of using the 'comedidev' back pointer in the private data, use the comedi_device 'dev' that we already have. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 89 ++++++++++--------------- 1 file changed, 36 insertions(+), 53 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 32021f03bda2..d93d10950abd 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -357,33 +357,22 @@ static int usbdux_ai_cancel(struct comedi_device *dev, /* analogue IN - interrupt service routine */ static void usbduxsub_ai_isoc_irq(struct urb *urb) { + struct comedi_device *dev = urb->context; + struct comedi_subdevice *s = dev->read_subdev; + struct usbdux_private *devpriv = dev->private; int i, err, n; - struct usbdux_private *this_usbduxsub; - struct comedi_device *this_comedidev; - struct comedi_subdevice *s; - - /* the context variable points to the subdevice */ - this_comedidev = urb->context; - /* the private structure of the subdevice is struct usbdux_private */ - this_usbduxsub = this_comedidev->private; - /* subdevice which is the AD converter */ - s = &this_comedidev->subdevices[SUBDEV_AD]; /* first we test if something unusual has just happened */ switch (urb->status) { case 0: /* copy the result in the transfer buffer */ - memcpy(this_usbduxsub->in_buffer, - urb->transfer_buffer, SIZEINBUF); + memcpy(devpriv->in_buffer, urb->transfer_buffer, SIZEINBUF); break; case -EILSEQ: /* error in the ISOchronous data */ /* we don't copy the data into the transfer buffer */ /* and recycle the last data byte */ - dev_dbg(&urb->dev->dev, - "comedi%d: usbdux: CRC error in ISO IN stream.\n", - this_usbduxsub->comedidev->minor); - + dev_dbg(dev->class_dev, "CRC error in ISO IN stream\n"); break; case -ECONNRESET: @@ -391,29 +380,27 @@ static void usbduxsub_ai_isoc_irq(struct urb *urb) case -ESHUTDOWN: case -ECONNABORTED: /* happens after an unlink command */ - if (this_usbduxsub->ai_cmd_running) { - /* we are still running a command */ - /* tell this comedi */ + if (devpriv->ai_cmd_running) { s->async->events |= COMEDI_CB_EOA; s->async->events |= COMEDI_CB_ERROR; - comedi_event(this_usbduxsub->comedidev, s); + comedi_event(dev, s); /* stop the transfer w/o unlink */ - usbdux_ai_stop(this_usbduxsub, 0); + usbdux_ai_stop(devpriv, 0); } return; default: /* a real error on the bus */ /* pass error to comedi if we are really running a command */ - if (this_usbduxsub->ai_cmd_running) { - dev_err(&urb->dev->dev, - "Non-zero urb status received in ai intr " - "context: %d\n", urb->status); + if (devpriv->ai_cmd_running) { + dev_err(dev->class_dev, + "Non-zero urb status received in ai intr context: %d\n", + urb->status); s->async->events |= COMEDI_CB_EOA; s->async->events |= COMEDI_CB_ERROR; - comedi_event(this_usbduxsub->comedidev, s); + comedi_event(dev, s); /* don't do an unlink here */ - usbdux_ai_stop(this_usbduxsub, 0); + usbdux_ai_stop(devpriv, 0); } return; } @@ -422,7 +409,7 @@ static void usbduxsub_ai_isoc_irq(struct urb *urb) * at this point we are reasonably sure that nothing dodgy has happened * are we running a command? */ - if (unlikely((!(this_usbduxsub->ai_cmd_running)))) { + if (unlikely(!devpriv->ai_cmd_running)) { /* * not running a command, do not continue execution if no * asynchronous command is running in particular not resubmit @@ -430,44 +417,42 @@ static void usbduxsub_ai_isoc_irq(struct urb *urb) return; } - urb->dev = this_usbduxsub->usbdev; + urb->dev = devpriv->usbdev; /* resubmit the urb */ err = usb_submit_urb(urb, GFP_ATOMIC); if (unlikely(err < 0)) { - dev_err(&urb->dev->dev, - "comedi_: urb resubmit failed in int-context! err=%d\n", - err); + dev_err(dev->class_dev, + "urb resubmit failed in int-context! err=%d\n", err); if (err == -EL2NSYNC) - dev_err(&urb->dev->dev, - "buggy USB host controller or bug in IRQ " - "handler!\n"); + dev_err(dev->class_dev, + "buggy USB host controller or bug in IRQ handler!\n"); s->async->events |= COMEDI_CB_EOA; s->async->events |= COMEDI_CB_ERROR; - comedi_event(this_usbduxsub->comedidev, s); + comedi_event(dev, s); /* don't do an unlink here */ - usbdux_ai_stop(this_usbduxsub, 0); + usbdux_ai_stop(devpriv, 0); return; } - this_usbduxsub->ai_counter--; - if (likely(this_usbduxsub->ai_counter > 0)) + devpriv->ai_counter--; + if (likely(devpriv->ai_counter > 0)) return; /* timer zero, transfer measurements to comedi */ - this_usbduxsub->ai_counter = this_usbduxsub->ai_timer; + devpriv->ai_counter = devpriv->ai_timer; /* test, if we transmit only a fixed number of samples */ - if (!(this_usbduxsub->ai_continous)) { + if (!devpriv->ai_continous) { /* not continuous, fixed number of samples */ - this_usbduxsub->ai_sample_count--; + devpriv->ai_sample_count--; /* all samples received? */ - if (this_usbduxsub->ai_sample_count < 0) { + if (devpriv->ai_sample_count < 0) { /* prevent a resubmit next time */ - usbdux_ai_stop(this_usbduxsub, 0); + usbdux_ai_stop(devpriv, 0); /* say comedi that the acquistion is over */ s->async->events |= COMEDI_CB_EOA; - comedi_event(this_usbduxsub->comedidev, s); + comedi_event(dev, s); return; } } @@ -476,23 +461,21 @@ static void usbduxsub_ai_isoc_irq(struct urb *urb) for (i = 0; i < n; i++) { /* transfer data */ if (CR_RANGE(s->async->cmd.chanlist[i]) <= 1) { - err = comedi_buf_put - (s->async, - le16_to_cpu(this_usbduxsub->in_buffer[i]) ^ 0x800); + err = comedi_buf_put(s->async, + le16_to_cpu(devpriv->in_buffer[i]) ^ 0x800); } else { - err = comedi_buf_put - (s->async, - le16_to_cpu(this_usbduxsub->in_buffer[i])); + err = comedi_buf_put(s->async, + le16_to_cpu(devpriv->in_buffer[i])); } if (unlikely(err == 0)) { /* buffer overflow */ - usbdux_ai_stop(this_usbduxsub, 0); + usbdux_ai_stop(devpriv, 0); return; } } /* tell comedi that data is there */ s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS; - comedi_event(this_usbduxsub->comedidev, s); + comedi_event(dev, s); } static int usbduxsub_unlink_outurbs(struct usbdux_private *usbduxsub_tmp) From e057288ffd62ae63536d1f37dad4a22d2b84148b Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 14:10:54 -0700 Subject: [PATCH 0716/3400] staging: comedi: usbdux: tidy up usbduxsub_ao_isoc_irq() Rename the local variables to the comedi "norm". The comedi_subdevice in this function is actually the dev->write_subdev that was initialized in the attach. Use that instead of accessing the dev->subdevices array directly. Use dev->class_dev as the device for all dev_printk() messages. Instead of using the 'comedidev' back pointer in the private data, use the comedi_device 'dev' that we already have. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 85 +++++++++++-------------- 1 file changed, 36 insertions(+), 49 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index d93d10950abd..292832b2b5e9 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -535,18 +535,11 @@ static int usbdux_ao_cancel(struct comedi_device *dev, static void usbduxsub_ao_isoc_irq(struct urb *urb) { + struct comedi_device *dev = urb->context; + struct comedi_subdevice *s = dev->write_subdev; + struct usbdux_private *devpriv = dev->private; int i, ret; int8_t *datap; - struct usbdux_private *this_usbduxsub; - struct comedi_device *this_comedidev; - struct comedi_subdevice *s; - - /* the context variable points to the subdevice */ - this_comedidev = urb->context; - /* the private structure of the subdevice is struct usbdux_private */ - this_usbduxsub = this_comedidev->private; - - s = &this_comedidev->subdevices[SUBDEV_DA]; switch (urb->status) { case 0: @@ -559,47 +552,47 @@ static void usbduxsub_ao_isoc_irq(struct urb *urb) case -ECONNABORTED: /* after an unlink command, unplug, ... etc */ /* no unlink needed here. Already shutting down. */ - if (this_usbduxsub->ao_cmd_running) { + if (devpriv->ao_cmd_running) { s->async->events |= COMEDI_CB_EOA; - comedi_event(this_usbduxsub->comedidev, s); - usbdux_ao_stop(this_usbduxsub, 0); + comedi_event(dev, s); + usbdux_ao_stop(devpriv, 0); } return; default: /* a real error */ - if (this_usbduxsub->ao_cmd_running) { - dev_err(&urb->dev->dev, - "comedi_: Non-zero urb status received in ao " - "intr context: %d\n", urb->status); + if (devpriv->ao_cmd_running) { + dev_err(dev->class_dev, + "Non-zero urb status received in ao intr context: %d\n", + urb->status); s->async->events |= COMEDI_CB_ERROR; s->async->events |= COMEDI_CB_EOA; - comedi_event(this_usbduxsub->comedidev, s); + comedi_event(dev, s); /* we do an unlink if we are in the high speed mode */ - usbdux_ao_stop(this_usbduxsub, 0); + usbdux_ao_stop(devpriv, 0); } return; } /* are we actually running? */ - if (!(this_usbduxsub->ao_cmd_running)) + if (!devpriv->ao_cmd_running) return; /* normal operation: executing a command in this subdevice */ - this_usbduxsub->ao_counter--; - if ((int)this_usbduxsub->ao_counter <= 0) { + devpriv->ao_counter--; + if ((int)devpriv->ao_counter <= 0) { /* timer zero */ - this_usbduxsub->ao_counter = this_usbduxsub->ao_timer; + devpriv->ao_counter = devpriv->ao_timer; /* handle non continous acquisition */ - if (!(this_usbduxsub->ao_continous)) { + if (!devpriv->ao_continous) { /* fixed number of samples */ - this_usbduxsub->ao_sample_count--; - if (this_usbduxsub->ao_sample_count < 0) { + devpriv->ao_sample_count--; + if (devpriv->ao_sample_count < 0) { /* all samples transmitted */ - usbdux_ao_stop(this_usbduxsub, 0); + usbdux_ao_stop(devpriv, 0); s->async->events |= COMEDI_CB_EOA; - comedi_event(this_usbduxsub->comedidev, s); + comedi_event(dev, s); /* no resubmit of the urb */ return; } @@ -619,9 +612,7 @@ static void usbduxsub_ao_isoc_irq(struct urb *urb) ret = comedi_buf_get(s->async, &temp); datap[0] = temp; datap[1] = temp >> 8; - datap[2] = this_usbduxsub->dac_commands[i]; - /* printk("data[0]=%x, data[1]=%x, data[2]=%x\n", */ - /* datap[0],datap[1],datap[2]); */ + datap[2] = devpriv->dac_commands[i]; if (ret < 0) { dev_err(&urb->dev->dev, "comedi: buffer underflow\n"); @@ -630,39 +621,35 @@ static void usbduxsub_ao_isoc_irq(struct urb *urb) } /* transmit data to comedi */ s->async->events |= COMEDI_CB_BLOCK; - comedi_event(this_usbduxsub->comedidev, s); + comedi_event(dev, s); } } urb->transfer_buffer_length = SIZEOUTBUF; - urb->dev = this_usbduxsub->usbdev; + urb->dev = devpriv->usbdev; urb->status = 0; - if (this_usbduxsub->ao_cmd_running) { - if (this_usbduxsub->high_speed) { - /* uframes */ - urb->interval = 8; - } else { - /* frames */ - urb->interval = 1; - } + if (devpriv->ao_cmd_running) { + if (devpriv->high_speed) + urb->interval = 8; /* uframes */ + else + urb->interval = 1; /* frames */ urb->number_of_packets = 1; urb->iso_frame_desc[0].offset = 0; urb->iso_frame_desc[0].length = SIZEOUTBUF; urb->iso_frame_desc[0].status = 0; ret = usb_submit_urb(urb, GFP_ATOMIC); if (ret < 0) { - dev_err(&urb->dev->dev, - "comedi_: ao urb resubm failed in int-cont. " - "ret=%d", ret); + dev_err(dev->class_dev, + "ao urb resubm failed in int-cont. ret=%d", + ret); if (ret == EL2NSYNC) - dev_err(&urb->dev->dev, - "buggy USB host controller or bug in " - "IRQ handling!\n"); + dev_err(dev->class_dev, + "buggy USB host controller or bug in IRQ handling!\n"); s->async->events |= COMEDI_CB_EOA; s->async->events |= COMEDI_CB_ERROR; - comedi_event(this_usbduxsub->comedidev, s); + comedi_event(dev, s); /* don't do an unlink here */ - usbdux_ao_stop(this_usbduxsub, 0); + usbdux_ao_stop(devpriv, 0); } } } From c9f3363a301844bbb2fa2d35e4baf4d9fd025df8 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 14:11:14 -0700 Subject: [PATCH 0717/3400] staging: comedi: usbdux: tidy up usbduxsub_pwm_irq() Rename the local variables to the comedi "norm". Use dev->class_dev as the device for all dev_printk() messages. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 49 ++++++++++--------------- 1 file changed, 19 insertions(+), 30 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 292832b2b5e9..9f1da8eb150d 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -1634,19 +1634,9 @@ static int usbdux_pwm_cancel(struct comedi_device *dev, static void usbduxsub_pwm_irq(struct urb *urb) { + struct comedi_device *dev = urb->context; + struct usbdux_private *devpriv = dev->private; int ret; - struct usbdux_private *this_usbduxsub; - struct comedi_device *this_comedidev; - struct comedi_subdevice *s; - - /* printk(KERN_DEBUG "PWM: IRQ\n"); */ - - /* the context variable points to the subdevice */ - this_comedidev = urb->context; - /* the private structure of the subdevice is struct usbdux_private */ - this_usbduxsub = this_comedidev->private; - - s = &this_comedidev->subdevices[SUBDEV_DA]; switch (urb->status) { case 0: @@ -1661,42 +1651,41 @@ static void usbduxsub_pwm_irq(struct urb *urb) * after an unlink command, unplug, ... etc * no unlink needed here. Already shutting down. */ - if (this_usbduxsub->pwm_cmd_running) - usbdux_pwm_stop(this_usbduxsub, 0); + if (devpriv->pwm_cmd_running) + usbdux_pwm_stop(devpriv, 0); return; default: /* a real error */ - if (this_usbduxsub->pwm_cmd_running) { - dev_err(&this_usbduxsub->interface->dev, - "comedi_: Non-zero urb status received in " - "pwm intr context: %d\n", urb->status); - usbdux_pwm_stop(this_usbduxsub, 0); + if (devpriv->pwm_cmd_running) { + dev_err(dev->class_dev, + "Non-zero urb status received in pwm intr context: %d\n", + urb->status); + usbdux_pwm_stop(devpriv, 0); } return; } /* are we actually running? */ - if (!(this_usbduxsub->pwm_cmd_running)) + if (!devpriv->pwm_cmd_running) return; - urb->transfer_buffer_length = this_usbduxsub->size_pwm_buf; - urb->dev = this_usbduxsub->usbdev; + urb->transfer_buffer_length = devpriv->size_pwm_buf; + urb->dev = devpriv->usbdev; urb->status = 0; - if (this_usbduxsub->pwm_cmd_running) { + if (devpriv->pwm_cmd_running) { ret = usb_submit_urb(urb, GFP_ATOMIC); if (ret < 0) { - dev_err(&this_usbduxsub->interface->dev, - "comedi_: pwm urb resubm failed in int-cont. " - "ret=%d", ret); + dev_err(dev->class_dev, + "pwm urb resubm failed in int-cont. ret=%d", + ret); if (ret == EL2NSYNC) - dev_err(&this_usbduxsub->interface->dev, - "buggy USB host controller or bug in " - "IRQ handling!\n"); + dev_err(dev->class_dev, + "buggy USB host controller or bug in IRQ handling!\n"); /* don't do an unlink here */ - usbdux_pwm_stop(this_usbduxsub, 0); + usbdux_pwm_stop(devpriv, 0); } } } From e5acdc3561b14a73f5de6bca8a703d9faa7d191c Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 14:11:33 -0700 Subject: [PATCH 0718/3400] staging: comedi: usbdux: remove the SUBDEV_* defines These defines are only used to index the dev->subdevices array during the attach. It's cleaner to just open-code the values. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 9f1da8eb150d..226b2945cd1f 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -182,21 +182,6 @@ sampling rate. If you sample two channels you get 4kHz and so on. /* must have more buffers due to buggy USB ctr */ #define NUMOFOUTBUFFERSHIGH 10 -/* Analogue in subdevice */ -#define SUBDEV_AD 0 - -/* Analogue out subdevice */ -#define SUBDEV_DA 1 - -/* Digital I/O */ -#define SUBDEV_DIO 2 - -/* counter */ -#define SUBDEV_COUNTER 3 - -/* timer aka pwm output */ -#define SUBDEV_PWM 4 - /* number of retries to get the right dux command */ #define RETRIES 10 @@ -2113,7 +2098,7 @@ static int usbdux_auto_attach(struct comedi_device *dev, return ret; /* Analog Input subdevice */ - s = &dev->subdevices[SUBDEV_AD]; + s = &dev->subdevices[0]; dev->read_subdev = s; s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ; @@ -2127,7 +2112,7 @@ static int usbdux_auto_attach(struct comedi_device *dev, s->cancel = usbdux_ai_cancel; /* Analog Output subdevice */ - s = &dev->subdevices[SUBDEV_DA]; + s = &dev->subdevices[1]; dev->write_subdev = s; s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE; @@ -2142,7 +2127,7 @@ static int usbdux_auto_attach(struct comedi_device *dev, s->insn_write = usbdux_ao_insn_write; /* Digital I/O subdevice */ - s = &dev->subdevices[SUBDEV_DIO]; + s = &dev->subdevices[2]; s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; s->n_chan = 8; @@ -2152,7 +2137,7 @@ static int usbdux_auto_attach(struct comedi_device *dev, s->insn_config = usbdux_dio_insn_config; /* Counter subdevice */ - s = &dev->subdevices[SUBDEV_COUNTER]; + s = &dev->subdevices[3]; s->type = COMEDI_SUBD_COUNTER; s->subdev_flags = SDF_WRITABLE | SDF_READABLE; s->n_chan = 4; @@ -2163,7 +2148,7 @@ static int usbdux_auto_attach(struct comedi_device *dev, if (devpriv->high_speed) { /* PWM subdevice */ - s = &dev->subdevices[SUBDEV_PWM]; + s = &dev->subdevices[4]; s->type = COMEDI_SUBD_PWM; s->subdev_flags = SDF_WRITABLE | SDF_PWM_HBRIDGE; s->n_chan = 8; From 38691ec1106b2c4345f271746c1fcd7174d1130d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 14:11:53 -0700 Subject: [PATCH 0719/3400] staging: comedi: usbdux: tidy up the comedi_lrange tables Cleanup the whitespace in the tables. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 30 ++++++++++--------------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 226b2945cd1f..6707950e8bdf 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -185,26 +185,20 @@ sampling rate. If you sample two channels you get 4kHz and so on. /* number of retries to get the right dux command */ #define RETRIES 10 -/**************************************************/ -/* comedi constants */ -static const struct comedi_lrange range_usbdux_ai_range = { 4, { - BIP_RANGE - (4.096), - BIP_RANGE(4.096 - / 2), - UNI_RANGE - (4.096), - UNI_RANGE(4.096 - / 2) - } +static const struct comedi_lrange range_usbdux_ai_range = { + 4, { + BIP_RANGE(4.096), + BIP_RANGE(4.096 / 2), + UNI_RANGE(4.096), + UNI_RANGE(4.096 / 2) + } }; -static const struct comedi_lrange range_usbdux_ao_range = { 2, { - BIP_RANGE - (4.096), - UNI_RANGE - (4.096), - } +static const struct comedi_lrange range_usbdux_ao_range = { + 2, { + BIP_RANGE(4.096), + UNI_RANGE(4.096) + } }; struct usbdux_private { From 91aa6b2193a178dd409ac78a5b909881db8f829c Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 14:12:14 -0700 Subject: [PATCH 0720/3400] staging: comedi: usbdux: remove dev_printk() noise Most of these are just function trace noise. The rest report errors that the user can't do anything about so they amount to added noise. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 182 ++---------------------- 1 file changed, 15 insertions(+), 167 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 6707950e8bdf..7b2e072aad1b 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -275,9 +275,6 @@ static int usbduxsub_unlink_inurbs(struct usbdux_private *usbduxsub_tmp) * cancelled. */ usb_kill_urb(usbduxsub_tmp->urb_in[i]); } - dev_dbg(&usbduxsub_tmp->interface->dev, - "comedi: usbdux: unlinked InURB %d, err=%d\n", - i, err); } } return err; @@ -292,11 +289,8 @@ static int usbdux_ai_stop(struct usbdux_private *this_usbduxsub, int do_unlink) { int ret = 0; - if (!this_usbduxsub) { - pr_err("comedi?: usbdux_ai_stop: this_usbduxsub=NULL!\n"); + if (!this_usbduxsub) return -EFAULT; - } - dev_dbg(&this_usbduxsub->interface->dev, "comedi: usbdux_ai_stop\n"); if (do_unlink) { /* stop aquistion */ @@ -323,8 +317,6 @@ static int usbdux_ai_cancel(struct comedi_device *dev, if (!this_usbduxsub) return -EFAULT; - dev_dbg(&this_usbduxsub->interface->dev, "comedi: usbdux_ai_cancel\n"); - /* prevent other CPUs from submitting new commands just now */ down(&this_usbduxsub->sem); /* unlink only if the urb really has been submitted */ @@ -466,10 +458,6 @@ static int usbduxsub_unlink_outurbs(struct usbdux_private *usbduxsub_tmp) for (i = 0; i < usbduxsub_tmp->num_out_buffers; i++) { if (usbduxsub_tmp->urb_out[i]) usb_kill_urb(usbduxsub_tmp->urb_out[i]); - - dev_dbg(&usbduxsub_tmp->interface->dev, - "comedi: usbdux: unlinked OutURB %d: res=%d\n", - i, err); } } return err; @@ -484,7 +472,6 @@ static int usbdux_ao_stop(struct usbdux_private *this_usbduxsub, int do_unlink) if (!this_usbduxsub) return -EFAULT; - dev_dbg(&this_usbduxsub->interface->dev, "comedi: usbdux_ao_cancel\n"); if (do_unlink) ret = usbduxsub_unlink_outurbs(this_usbduxsub); @@ -726,19 +713,9 @@ static int usbduxsub_submit_inurbs(struct usbdux_private *usbduxsub) usbduxsub->urb_in[i]->dev = usbduxsub->usbdev; usbduxsub->urb_in[i]->status = 0; usbduxsub->urb_in[i]->transfer_flags = URB_ISO_ASAP; - dev_dbg(&usbduxsub->interface->dev, - "comedi%d: submitting in-urb[%d]: %p,%p intv=%d\n", - usbduxsub->comedidev->minor, i, - (usbduxsub->urb_in[i]->context), - (usbduxsub->urb_in[i]->dev), - (usbduxsub->urb_in[i]->interval)); err_flag = usb_submit_urb(usbduxsub->urb_in[i], GFP_ATOMIC); - if (err_flag) { - dev_err(&usbduxsub->interface->dev, - "comedi_: ai: usb_submit_urb(%d) error %d\n", - i, err_flag); + if (err_flag) return err_flag; - } } return 0; } @@ -751,20 +728,14 @@ static int usbduxsub_submit_outurbs(struct usbdux_private *usbduxsub) return -EFAULT; for (i = 0; i < usbduxsub->num_out_buffers; i++) { - dev_dbg(&usbduxsub->interface->dev, - "comedi_: submitting out-urb[%d]\n", i); /* in case of a resubmission after an unlink... */ usbduxsub->urb_out[i]->context = usbduxsub->comedidev; usbduxsub->urb_out[i]->dev = usbduxsub->usbdev; usbduxsub->urb_out[i]->status = 0; usbduxsub->urb_out[i]->transfer_flags = URB_ISO_ASAP; err_flag = usb_submit_urb(usbduxsub->urb_out[i], GFP_ATOMIC); - if (err_flag) { - dev_err(&usbduxsub->interface->dev, - "comedi_: ao: usb_submit_urb(%d) error %d\n", - i, err_flag); + if (err_flag) return err_flag; - } } return 0; } @@ -879,20 +850,15 @@ static int8_t create_adc_command(unsigned int chan, int range) static int send_dux_commands(struct usbdux_private *this_usbduxsub, int cmd_type) { - int result, nsent; + int nsent; this_usbduxsub->dux_commands[0] = cmd_type; - result = usb_bulk_msg(this_usbduxsub->usbdev, - usb_sndbulkpipe(this_usbduxsub->usbdev, - COMMAND_OUT_EP), - this_usbduxsub->dux_commands, SIZEOFDUXBUFFER, - &nsent, BULK_TIMEOUT); - if (result < 0) - dev_err(&this_usbduxsub->interface->dev, "comedi%d: " - "could not transmit dux_command to the usb-device, " - "err=%d\n", this_usbduxsub->comedidev->minor, result); - return result; + return usb_bulk_msg(this_usbduxsub->usbdev, + usb_sndbulkpipe(this_usbduxsub->usbdev, + COMMAND_OUT_EP), + this_usbduxsub->dux_commands, SIZEOFDUXBUFFER, + &nsent, BULK_TIMEOUT); } static int receive_dux_commands(struct usbdux_private *this_usbduxsub, int command) @@ -907,21 +873,13 @@ static int receive_dux_commands(struct usbdux_private *this_usbduxsub, int comma COMMAND_IN_EP), this_usbduxsub->insn_buffer, SIZEINSNBUF, &nrec, BULK_TIMEOUT); - if (result < 0) { - dev_err(&this_usbduxsub->interface->dev, "comedi%d: " - "insn: USB error %d while receiving DUX command" - "\n", this_usbduxsub->comedidev->minor, result); + if (result < 0) return result; - } if (le16_to_cpu(this_usbduxsub->insn_buffer[0]) == command) return result; } /* this is only reached if the data has been requested a couple of * times */ - dev_err(&this_usbduxsub->interface->dev, "comedi%d: insn: " - "wrong data returned from firmware: want cmd %d, got cmd %d.\n", - this_usbduxsub->comedidev->minor, command, - le16_to_cpu(this_usbduxsub->insn_buffer[0])); return -EFAULT; } @@ -934,13 +892,8 @@ static int usbdux_ai_inttrig(struct comedi_device *dev, return -EFAULT; down(&this_usbduxsub->sem); - dev_dbg(&this_usbduxsub->interface->dev, - "comedi%d: usbdux_ai_inttrig\n", dev->minor); if (trignum != 0) { - dev_err(&this_usbduxsub->interface->dev, - "comedi%d: usbdux_ai_inttrig: invalid trignum\n", - dev->minor); up(&this_usbduxsub->sem); return -EINVAL; } @@ -948,18 +901,11 @@ static int usbdux_ai_inttrig(struct comedi_device *dev, this_usbduxsub->ai_cmd_running = 1; ret = usbduxsub_submit_inurbs(this_usbduxsub); if (ret < 0) { - dev_err(&this_usbduxsub->interface->dev, - "comedi%d: usbdux_ai_inttrig: " - "urbSubmit: err=%d\n", dev->minor, ret); this_usbduxsub->ai_cmd_running = 0; up(&this_usbduxsub->sem); return ret; } s->async->inttrig = NULL; - } else { - dev_err(&this_usbduxsub->interface->dev, - "comedi%d: ai_inttrig but acqu is already running\n", - dev->minor); } up(&this_usbduxsub->sem); return 1; @@ -976,15 +922,9 @@ static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) if (!this_usbduxsub) return -EFAULT; - dev_dbg(&this_usbduxsub->interface->dev, - "comedi%d: usbdux_ai_cmd\n", dev->minor); - /* block other CPUs from starting an ai_cmd */ down(&this_usbduxsub->sem); if (this_usbduxsub->ai_cmd_running) { - dev_err(&this_usbduxsub->interface->dev, "comedi%d: " - "ai_cmd not possible. Another ai_cmd is running.\n", - dev->minor); up(&this_usbduxsub->sem); return -EBUSY; } @@ -995,20 +935,12 @@ static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) for (i = 0; i < cmd->chanlist_len; ++i) { chan = CR_CHAN(cmd->chanlist[i]); range = CR_RANGE(cmd->chanlist[i]); - if (i >= NUMCHANNELS) { - dev_err(&this_usbduxsub->interface->dev, - "comedi%d: channel list too long\n", - dev->minor); + if (i >= NUMCHANNELS) break; - } this_usbduxsub->dux_commands[i + 2] = create_adc_command(chan, range); } - dev_dbg(&this_usbduxsub->interface->dev, - "comedi %d: sending commands to the usb device: size=%u\n", - dev->minor, NUMCHANNELS); - result = send_dux_commands(this_usbduxsub, SENDADCOMMANDS); if (result < 0) { up(&this_usbduxsub->sem); @@ -1036,10 +968,6 @@ static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) this_usbduxsub->ai_timer = cmd->scan_begin_arg / 1000000; } if (this_usbduxsub->ai_timer < 1) { - dev_err(&this_usbduxsub->interface->dev, "comedi%d: ai_cmd: " - "timer=%d, scan_begin_arg=%d. " - "Not properly tested by cmdtest?\n", dev->minor, - this_usbduxsub->ai_timer, cmd->scan_begin_arg); up(&this_usbduxsub->sem); return -EINVAL; } @@ -1090,15 +1018,8 @@ static int usbdux_ai_insn_read(struct comedi_device *dev, if (!this_usbduxsub) return 0; - dev_dbg(&this_usbduxsub->interface->dev, - "comedi%d: ai_insn_read, insn->n=%d, insn->subdev=%d\n", - dev->minor, insn->n, insn->subdev); - down(&this_usbduxsub->sem); if (this_usbduxsub->ai_cmd_running) { - dev_err(&this_usbduxsub->interface->dev, - "comedi%d: ai_insn_read not possible. " - "Async Command is running.\n", dev->minor); up(&this_usbduxsub->sem); return 0; } @@ -1165,23 +1086,13 @@ static int usbdux_ao_insn_write(struct comedi_device *dev, if (!this_usbduxsub) return -EFAULT; - dev_dbg(&this_usbduxsub->interface->dev, - "comedi%d: ao_insn_write\n", dev->minor); - down(&this_usbduxsub->sem); if (this_usbduxsub->ao_cmd_running) { - dev_err(&this_usbduxsub->interface->dev, - "comedi%d: ao_insn_write: " - "ERROR: asynchronous ao_cmd is running\n", dev->minor); up(&this_usbduxsub->sem); return 0; } for (i = 0; i < insn->n; i++) { - dev_dbg(&this_usbduxsub->interface->dev, - "comedi%d: ao_insn_write: data[chan=%d,i=%d]=%d\n", - dev->minor, chan, i, data[i]); - /* number of channels: 1 */ this_usbduxsub->dux_commands[1] = 1; /* one 16 bit value */ @@ -1212,9 +1123,6 @@ static int usbdux_ao_inttrig(struct comedi_device *dev, down(&this_usbduxsub->sem); if (trignum != 0) { - dev_err(&this_usbduxsub->interface->dev, - "comedi%d: usbdux_ao_inttrig: invalid trignum\n", - dev->minor); up(&this_usbduxsub->sem); return -EINVAL; } @@ -1222,18 +1130,11 @@ static int usbdux_ao_inttrig(struct comedi_device *dev, this_usbduxsub->ao_cmd_running = 1; ret = usbduxsub_submit_outurbs(this_usbduxsub); if (ret < 0) { - dev_err(&this_usbduxsub->interface->dev, - "comedi%d: usbdux_ao_inttrig: submitURB: " - "err=%d\n", dev->minor, ret); this_usbduxsub->ao_cmd_running = 0; up(&this_usbduxsub->sem); return ret; } s->async->inttrig = NULL; - } else { - dev_err(&this_usbduxsub->interface->dev, - "comedi%d: ao_inttrig but acqu is already running.\n", - dev->minor); } up(&this_usbduxsub->sem); return 1; @@ -1334,24 +1235,15 @@ static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) return -EFAULT; down(&this_usbduxsub->sem); - dev_dbg(&this_usbduxsub->interface->dev, - "comedi%d: %s\n", dev->minor, __func__); /* set current channel of the running acquisition to zero */ s->async->cur_chan = 0; for (i = 0; i < cmd->chanlist_len; ++i) { chan = CR_CHAN(cmd->chanlist[i]); gain = CR_RANGE(cmd->chanlist[i]); - if (i >= NUMOUTCHANNELS) { - dev_err(&this_usbduxsub->interface->dev, - "comedi%d: %s: channel list too long\n", - dev->minor, __func__); + if (i >= NUMOUTCHANNELS) break; - } this_usbduxsub->dac_commands[i] = (chan << 6); - dev_dbg(&this_usbduxsub->interface->dev, - "comedi%d: dac command for ch %d is %x\n", - dev->minor, i, this_usbduxsub->dac_commands[i]); } /* we count in steps of 1ms (125us) */ @@ -1364,21 +1256,7 @@ static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* 1ms */ /* timing of the scan: we get all channels at once */ this_usbduxsub->ao_timer = cmd->scan_begin_arg / 1000000; - dev_dbg(&this_usbduxsub->interface->dev, - "comedi%d: scan_begin_src=%d, scan_begin_arg=%d, " - "convert_src=%d, convert_arg=%d\n", dev->minor, - cmd->scan_begin_src, cmd->scan_begin_arg, - cmd->convert_src, cmd->convert_arg); - dev_dbg(&this_usbduxsub->interface->dev, - "comedi%d: ao_timer=%d (ms)\n", - dev->minor, this_usbduxsub->ao_timer); if (this_usbduxsub->ao_timer < 1) { - dev_err(&this_usbduxsub->interface->dev, - "comedi%d: usbdux: ao_timer=%d, " - "scan_begin_arg=%d. " - "Not properly tested by cmdtest?\n", - dev->minor, this_usbduxsub->ao_timer, - cmd->scan_begin_arg); up(&this_usbduxsub->sem); return -EINVAL; } @@ -1569,8 +1447,6 @@ static int usbduxsub_unlink_pwm_urbs(struct usbdux_private *usbduxsub_tmp) if (usbduxsub_tmp && usbduxsub_tmp->urb_pwm) { if (usbduxsub_tmp->urb_pwm) usb_kill_urb(usbduxsub_tmp->urb_pwm); - dev_dbg(&usbduxsub_tmp->interface->dev, - "comedi: unlinked PwmURB: res=%d\n", err); } return err; } @@ -1585,7 +1461,6 @@ static int usbdux_pwm_stop(struct usbdux_private *this_usbduxsub, int do_unlink) if (!this_usbduxsub) return -EFAULT; - dev_dbg(&this_usbduxsub->interface->dev, "comedi: %s\n", __func__); if (do_unlink) ret = usbduxsub_unlink_pwm_urbs(this_usbduxsub); @@ -1604,10 +1479,6 @@ static int usbdux_pwm_cancel(struct comedi_device *dev, /* unlink only if it is really running */ res = usbdux_pwm_stop(this_usbduxsub, this_usbduxsub->pwm_cmd_running); - dev_dbg(&this_usbduxsub->interface->dev, - "comedi %d: sending pwm off command to the usb device.\n", - dev->minor); - return send_dux_commands(this_usbduxsub, SENDPWMOFF); } @@ -1676,8 +1547,6 @@ static int usbduxsub_submit_pwm_urbs(struct usbdux_private *usbduxsub) if (!usbduxsub) return -EFAULT; - dev_dbg(&usbduxsub->interface->dev, "comedi_: submitting pwm-urb\n"); - /* in case of a resubmission after an unlink... */ usb_fill_bulk_urb(usbduxsub->urb_pwm, usbduxsub->usbdev, @@ -1687,12 +1556,8 @@ static int usbduxsub_submit_pwm_urbs(struct usbdux_private *usbduxsub) usbduxsub->comedidev); err_flag = usb_submit_urb(usbduxsub->urb_pwm, GFP_ATOMIC); - if (err_flag) { - dev_err(&usbduxsub->interface->dev, - "comedi_: usbdux: pwm: usb_submit_urb error %d\n", - err_flag); + if (err_flag) return err_flag; - } return 0; } @@ -1703,23 +1568,15 @@ static int usbdux_pwm_period(struct comedi_device *dev, int fx2delay = 255; if (period < MIN_PWM_PERIOD) { - dev_err(&this_usbduxsub->interface->dev, - "comedi%d: illegal period setting for pwm.\n", - dev->minor); return -EAGAIN; } else { fx2delay = period / ((int)(6 * 512 * (1.0 / 0.033))) - 6; - if (fx2delay > 255) { - dev_err(&this_usbduxsub->interface->dev, - "comedi%d: period %d for pwm is too low.\n", - dev->minor, period); + if (fx2delay > 255) return -EAGAIN; - } } this_usbduxsub->pwn_delay = fx2delay; this_usbduxsub->pwm_period = period; - dev_dbg(&this_usbduxsub->interface->dev, "%s: frequ=%d, period=%d\n", - __func__, period, fx2delay); + return 0; } @@ -1730,9 +1587,6 @@ static int usbdux_pwm_start(struct comedi_device *dev, int ret, i; struct usbdux_private *this_usbduxsub = dev->private; - dev_dbg(&this_usbduxsub->interface->dev, "comedi%d: %s\n", - dev->minor, __func__); - if (this_usbduxsub->pwm_cmd_running) { /* already running */ return 0; @@ -1841,8 +1695,6 @@ static int usbdux_pwm_config(struct comedi_device *dev, switch (data[0]) { case INSN_CONFIG_ARM: /* switch it on */ - dev_dbg(&this_usbduxsub->interface->dev, - "comedi%d: %s: pwm on\n", dev->minor, __func__); /* * if not zero the PWM is limited to a certain time which is * not supported here @@ -1851,8 +1703,6 @@ static int usbdux_pwm_config(struct comedi_device *dev, return -EINVAL; return usbdux_pwm_start(dev, s); case INSN_CONFIG_DISARM: - dev_dbg(&this_usbduxsub->interface->dev, - "comedi%d: %s: pwm off\n", dev->minor, __func__); return usbdux_pwm_cancel(dev, s); case INSN_CONFIG_GET_PWM_STATUS: /* @@ -1862,8 +1712,6 @@ static int usbdux_pwm_config(struct comedi_device *dev, data[1] = this_usbduxsub->pwm_cmd_running; return 0; case INSN_CONFIG_PWM_SET_PERIOD: - dev_dbg(&this_usbduxsub->interface->dev, - "comedi%d: %s: setting period\n", dev->minor, __func__); return usbdux_pwm_period(dev, s, data[1]); case INSN_CONFIG_PWM_GET_PERIOD: data[1] = this_usbduxsub->pwm_period; From 865d9eedd12570f5f296bf876edc09df78095bfc Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 14:12:35 -0700 Subject: [PATCH 0721/3400] staging: comedi: usbdux: tidy up usbduxsub_submit_inurbs() Pass the comedi_device pointer (the urb context) to this function instead of the private data pointer. Use a local variable for the urb pointers that are setup and submitted. Remove the sanity check of the private data. This function can only get called if the allocation was successful during the attach. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 35 ++++++++++++++----------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 7b2e072aad1b..4d4ce3f184b7 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -698,24 +698,27 @@ done: return ret; } -static int usbduxsub_submit_inurbs(struct usbdux_private *usbduxsub) +static int usbduxsub_submit_inurbs(struct comedi_device *dev) { - int i, err_flag; - - if (!usbduxsub) - return -EFAULT; + struct usbdux_private *devpriv = dev->private; + struct urb *urb; + int ret; + int i; /* Submit all URBs and start the transfer on the bus */ - for (i = 0; i < usbduxsub->num_in_buffers; i++) { + for (i = 0; i < devpriv->num_in_buffers; i++) { + urb = devpriv->urb_in[i]; + /* in case of a resubmission after an unlink... */ - usbduxsub->urb_in[i]->interval = usbduxsub->ai_interval; - usbduxsub->urb_in[i]->context = usbduxsub->comedidev; - usbduxsub->urb_in[i]->dev = usbduxsub->usbdev; - usbduxsub->urb_in[i]->status = 0; - usbduxsub->urb_in[i]->transfer_flags = URB_ISO_ASAP; - err_flag = usb_submit_urb(usbduxsub->urb_in[i], GFP_ATOMIC); - if (err_flag) - return err_flag; + urb->interval = devpriv->ai_interval; + urb->context = dev; + urb->dev = devpriv->usbdev; + urb->status = 0; + urb->transfer_flags = URB_ISO_ASAP; + + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret) + return ret; } return 0; } @@ -899,7 +902,7 @@ static int usbdux_ai_inttrig(struct comedi_device *dev, } if (!(this_usbduxsub->ai_cmd_running)) { this_usbduxsub->ai_cmd_running = 1; - ret = usbduxsub_submit_inurbs(this_usbduxsub); + ret = usbduxsub_submit_inurbs(dev); if (ret < 0) { this_usbduxsub->ai_cmd_running = 0; up(&this_usbduxsub->sem); @@ -986,7 +989,7 @@ static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) if (cmd->start_src == TRIG_NOW) { /* enable this acquisition operation */ this_usbduxsub->ai_cmd_running = 1; - ret = usbduxsub_submit_inurbs(this_usbduxsub); + ret = usbduxsub_submit_inurbs(dev); if (ret < 0) { this_usbduxsub->ai_cmd_running = 0; /* fixme: unlink here?? */ From 6754698b6a19ad1eb9075b2a49dba85850840a3f Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 14:13:15 -0700 Subject: [PATCH 0722/3400] staging: comedi: usbdux: tidy up usbduxsub_submit_outurbs() Pass the comedi_device pointer (the urb context) to this function instead of the private data pointer. Use a local variable for the urb pointers that are setup and submitted. Remove the sanity check of the private data. This function can only get called if the allocation was successful during the attach. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 31 ++++++++++++++----------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 4d4ce3f184b7..7304ef0e2ded 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -723,22 +723,25 @@ static int usbduxsub_submit_inurbs(struct comedi_device *dev) return 0; } -static int usbduxsub_submit_outurbs(struct usbdux_private *usbduxsub) +static int usbduxsub_submit_outurbs(struct comedi_device *dev) { - int i, err_flag; + struct usbdux_private *devpriv = dev->private; + struct urb *urb; + int ret; + int i; - if (!usbduxsub) - return -EFAULT; + for (i = 0; i < devpriv->num_out_buffers; i++) { + urb = devpriv->urb_out[i]; - for (i = 0; i < usbduxsub->num_out_buffers; i++) { /* in case of a resubmission after an unlink... */ - usbduxsub->urb_out[i]->context = usbduxsub->comedidev; - usbduxsub->urb_out[i]->dev = usbduxsub->usbdev; - usbduxsub->urb_out[i]->status = 0; - usbduxsub->urb_out[i]->transfer_flags = URB_ISO_ASAP; - err_flag = usb_submit_urb(usbduxsub->urb_out[i], GFP_ATOMIC); - if (err_flag) - return err_flag; + urb->context = dev; + urb->dev = devpriv->usbdev; + urb->status = 0; + urb->transfer_flags = URB_ISO_ASAP; + + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret) + return ret; } return 0; } @@ -1131,7 +1134,7 @@ static int usbdux_ao_inttrig(struct comedi_device *dev, } if (!(this_usbduxsub->ao_cmd_running)) { this_usbduxsub->ao_cmd_running = 1; - ret = usbduxsub_submit_outurbs(this_usbduxsub); + ret = usbduxsub_submit_outurbs(dev); if (ret < 0) { this_usbduxsub->ao_cmd_running = 0; up(&this_usbduxsub->sem); @@ -1289,7 +1292,7 @@ static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) if (cmd->start_src == TRIG_NOW) { /* enable this acquisition operation */ this_usbduxsub->ao_cmd_running = 1; - ret = usbduxsub_submit_outurbs(this_usbduxsub); + ret = usbduxsub_submit_outurbs(dev); if (ret < 0) { this_usbduxsub->ao_cmd_running = 0; /* fixme: unlink here?? */ From 5a80fa0429b7b6e3b32813614178d4be302f5ea0 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 14:13:34 -0700 Subject: [PATCH 0723/3400] staging: comedi: usbdux: tidy up usbduxsub_submit_pwm_urbs() Pass the comedi_device pointer (the urb context) to this function instead of the private data pointer. Use a local variable for the urb pointer that is setup and submitted. Remove the sanity check of the private data. This function can only get called if the allocation was successful during the attach. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 27 ++++++++++--------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 7304ef0e2ded..ad537ed5fc40 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -1546,25 +1546,20 @@ static void usbduxsub_pwm_irq(struct urb *urb) } } -static int usbduxsub_submit_pwm_urbs(struct usbdux_private *usbduxsub) +static int usbduxsub_submit_pwm_urbs(struct comedi_device *dev) { - int err_flag; - - if (!usbduxsub) - return -EFAULT; + struct usbdux_private *devpriv = dev->private; + struct urb *urb = devpriv->urb_pwm; /* in case of a resubmission after an unlink... */ - usb_fill_bulk_urb(usbduxsub->urb_pwm, - usbduxsub->usbdev, - usb_sndbulkpipe(usbduxsub->usbdev, PWM_EP), - usbduxsub->urb_pwm->transfer_buffer, - usbduxsub->size_pwm_buf, usbduxsub_pwm_irq, - usbduxsub->comedidev); + usb_fill_bulk_urb(urb, devpriv->usbdev, + usb_sndbulkpipe(devpriv->usbdev, PWM_EP), + urb->transfer_buffer, + devpriv->size_pwm_buf, + usbduxsub_pwm_irq, + dev); - err_flag = usb_submit_urb(usbduxsub->urb_pwm, GFP_ATOMIC); - if (err_flag) - return err_flag; - return 0; + return usb_submit_urb(urb, GFP_ATOMIC); } static int usbdux_pwm_period(struct comedi_device *dev, @@ -1608,7 +1603,7 @@ static int usbdux_pwm_start(struct comedi_device *dev, ((char *)(this_usbduxsub->urb_pwm->transfer_buffer))[i] = 0; this_usbduxsub->pwm_cmd_running = 1; - ret = usbduxsub_submit_pwm_urbs(this_usbduxsub); + ret = usbduxsub_submit_pwm_urbs(dev); if (ret < 0) { this_usbduxsub->pwm_cmd_running = 0; return ret; From cc8cb3da9e0fdaca684089c97708210655b2f343 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 14:14:42 -0700 Subject: [PATCH 0724/3400] staging: comedi: usbdux: remove 'comedidev' from private data This back pointer is no longer needed by the driver. Remove it. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index ad537ed5fc40..8db118019a3c 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -229,8 +229,6 @@ struct usbdux_private { int ifnum; /* interface structure in 2.6 */ struct usb_interface *interface; - /* comedi device for the interrupt context */ - struct comedi_device *comedidev; /* is it USB_SPEED_HIGH or not? */ short int high_speed; /* asynchronous command is running */ @@ -1903,7 +1901,6 @@ static int usbdux_auto_attach(struct comedi_device *dev, sema_init(&devpriv->sem, 1); - devpriv->comedidev = dev; devpriv->usbdev = usb; devpriv->interface = intf; devpriv->ifnum = intf->altsetting->desc.bInterfaceNumber; @@ -2024,8 +2021,6 @@ static void usbdux_detach(struct comedi_device *dev) usbdux_free_usb_buffers(devpriv); - devpriv->comedidev = NULL; - up(&devpriv->sem); } } From 5d293d904c944894785f6a7be85acfc85ac4cfac Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 14:15:04 -0700 Subject: [PATCH 0725/3400] staging: comedi: usbdux: remove 'interface' from private data This back pointer is only used for a couple dev_printk() messages and during the detach. For the dev_printk() we can use the dev->class_dev. In the detach we can get the usb_interface from the comedi_device. Do that and remove the back pointer from the private data. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 8db118019a3c..6a757f754d5f 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -227,8 +227,6 @@ struct usbdux_private { int16_t *out_buffer; /* interface number */ int ifnum; - /* interface structure in 2.6 */ - struct usb_interface *interface; /* is it USB_SPEED_HIGH or not? */ short int high_speed; /* asynchronous command is running */ @@ -634,7 +632,7 @@ static int usbdux_firmware_upload(struct comedi_device *dev, return 0; if (size > FIRMWARE_MAX_LEN) { - dev_err(&usbduxsub->interface->dev, + dev_err(dev->class_dev, "usbdux firmware binary it too large for FX2.\n"); return -ENOMEM; } @@ -660,8 +658,7 @@ static int usbdux_firmware_upload(struct comedi_device *dev, tmp, 1, BULK_TIMEOUT); if (ret < 0) { - dev_err(&usbduxsub->interface->dev, - "comedi_: can not stop firmware\n"); + dev_err(dev->class_dev, "can not stop firmware\n"); goto done; } @@ -673,8 +670,7 @@ static int usbdux_firmware_upload(struct comedi_device *dev, buf, size, BULK_TIMEOUT); if (ret < 0) { - dev_err(&usbduxsub->interface->dev, - "comedi_: firmware upload failed\n"); + dev_err(dev->class_dev, "firmware upload failed\n"); goto done; } @@ -687,8 +683,7 @@ static int usbdux_firmware_upload(struct comedi_device *dev, tmp, 1, BULK_TIMEOUT); if (ret < 0) - dev_err(&usbduxsub->interface->dev, - "comedi_: can not start firmware\n"); + dev_err(dev->class_dev, "can not start firmware\n"); done: kfree(tmp); @@ -1902,7 +1897,6 @@ static int usbdux_auto_attach(struct comedi_device *dev, sema_init(&devpriv->sem, 1); devpriv->usbdev = usb; - devpriv->interface = intf; devpriv->ifnum = intf->altsetting->desc.bInterfaceNumber; usb_set_intfdata(intf, devpriv); @@ -2005,12 +1999,13 @@ static int usbdux_auto_attach(struct comedi_device *dev, static void usbdux_detach(struct comedi_device *dev) { + struct usb_interface *intf = comedi_to_usb_interface(dev); struct usbdux_private *devpriv = dev->private; if (devpriv) { down(&devpriv->sem); - usb_set_intfdata(devpriv->interface, NULL); + usb_set_intfdata(intf, NULL); if (devpriv->pwm_cmd_running) usbduxsub_unlink_pwm_urbs(devpriv); From 49cc49dd9e36c7154fc9da528b85db0eb7605969 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 14:15:22 -0700 Subject: [PATCH 0726/3400] staging: comedi: usbdux: tidy up send_dux_commands() For aesthetic reasons, pass the comedi_device pointer to this function instead of the private data pointer. Rename the local variable used for the private data pointer to the comedi "norm". Add a local variable for the usb_device pointer to tidy up the usb_bulk_msg() call. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 28 ++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 6a757f754d5f..d2a3a1accb85 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -847,16 +847,16 @@ static int8_t create_adc_command(unsigned int chan, int range) #define SENDPWMON 7 #define SENDPWMOFF 8 -static int send_dux_commands(struct usbdux_private *this_usbduxsub, int cmd_type) +static int send_dux_commands(struct comedi_device *dev, int cmd_type) { + struct usbdux_private *devpriv = dev->private; + struct usb_device *usb = devpriv->usbdev; int nsent; - this_usbduxsub->dux_commands[0] = cmd_type; + devpriv->dux_commands[0] = cmd_type; - return usb_bulk_msg(this_usbduxsub->usbdev, - usb_sndbulkpipe(this_usbduxsub->usbdev, - COMMAND_OUT_EP), - this_usbduxsub->dux_commands, SIZEOFDUXBUFFER, + return usb_bulk_msg(usb, usb_sndbulkpipe(usb, COMMAND_OUT_EP), + devpriv->dux_commands, SIZEOFDUXBUFFER, &nsent, BULK_TIMEOUT); } @@ -940,7 +940,7 @@ static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) create_adc_command(chan, range); } - result = send_dux_commands(this_usbduxsub, SENDADCOMMANDS); + result = send_dux_commands(dev, SENDADCOMMANDS); if (result < 0) { up(&this_usbduxsub->sem); return result; @@ -1030,7 +1030,7 @@ static int usbdux_ai_insn_read(struct comedi_device *dev, this_usbduxsub->dux_commands[1] = create_adc_command(chan, range); /* adc commands */ - err = send_dux_commands(this_usbduxsub, SENDSINGLEAD); + err = send_dux_commands(dev, SENDSINGLEAD); if (err < 0) { up(&this_usbduxsub->sem); return err; @@ -1100,7 +1100,7 @@ static int usbdux_ao_insn_write(struct comedi_device *dev, this_usbduxsub->out_buffer[chan] = data[i]; /* channel number */ this_usbduxsub->dux_commands[4] = (chan << 6); - err = send_dux_commands(this_usbduxsub, SENDDACOMMANDS); + err = send_dux_commands(dev, SENDDACOMMANDS); if (err < 0) { up(&this_usbduxsub->sem); return err; @@ -1357,7 +1357,7 @@ static int usbdux_dio_insn_bits(struct comedi_device *dev, /* This command also tells the firmware to return */ /* the digital input lines */ - err = send_dux_commands(this_usbduxsub, SENDDIOBITSCOMMAND); + err = send_dux_commands(dev, SENDDIOBITSCOMMAND); if (err < 0) { up(&this_usbduxsub->sem); return err; @@ -1386,7 +1386,7 @@ static int usbdux_counter_read(struct comedi_device *dev, return -EFAULT; down(&this_usbduxsub->sem); - err = send_dux_commands(this_usbduxsub, READCOUNTERCOMMAND); + err = send_dux_commands(dev, READCOUNTERCOMMAND); if (err < 0) { up(&this_usbduxsub->sem); return err; @@ -1417,7 +1417,7 @@ static int usbdux_counter_write(struct comedi_device *dev, this_usbduxsub->dux_commands[1] = insn->chanspec; *((int16_t *) (this_usbduxsub->dux_commands + 2)) = cpu_to_le16(*data); - err = send_dux_commands(this_usbduxsub, WRITECOUNTERCOMMAND); + err = send_dux_commands(dev, WRITECOUNTERCOMMAND); if (err < 0) { up(&this_usbduxsub->sem); return err; @@ -1478,7 +1478,7 @@ static int usbdux_pwm_cancel(struct comedi_device *dev, /* unlink only if it is really running */ res = usbdux_pwm_stop(this_usbduxsub, this_usbduxsub->pwm_cmd_running); - return send_dux_commands(this_usbduxsub, SENDPWMOFF); + return send_dux_commands(dev, SENDPWMOFF); } static void usbduxsub_pwm_irq(struct urb *urb) @@ -1587,7 +1587,7 @@ static int usbdux_pwm_start(struct comedi_device *dev, } this_usbduxsub->dux_commands[1] = ((int8_t) this_usbduxsub->pwn_delay); - ret = send_dux_commands(this_usbduxsub, SENDPWMON); + ret = send_dux_commands(dev, SENDPWMON); if (ret < 0) return ret; From fb90856828064ee5195a2b5b0f9c1fa430a3fbb9 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 14:15:43 -0700 Subject: [PATCH 0727/3400] staging: comedi: usbdux: tidy up receive_dux_commands() For aesthetic reasons, pass the comedi_device pointer to this function instead of the private data pointer. Rename the local variable used for the private data pointer to the comedi "norm". Add a local variable for the usb_device pointer to tidy up the usb_bulk_msg() call. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 29 ++++++++++++------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index d2a3a1accb85..5980b8e36694 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -860,25 +860,24 @@ static int send_dux_commands(struct comedi_device *dev, int cmd_type) &nsent, BULK_TIMEOUT); } -static int receive_dux_commands(struct usbdux_private *this_usbduxsub, int command) +static int receive_dux_commands(struct comedi_device *dev, int command) { - int result = (-EFAULT); + struct usbdux_private *devpriv = dev->private; + struct usb_device *usb = devpriv->usbdev; + int ret; int nrec; int i; for (i = 0; i < RETRIES; i++) { - result = usb_bulk_msg(this_usbduxsub->usbdev, - usb_rcvbulkpipe(this_usbduxsub->usbdev, - COMMAND_IN_EP), - this_usbduxsub->insn_buffer, SIZEINSNBUF, + ret = usb_bulk_msg(usb, usb_rcvbulkpipe(usb, COMMAND_IN_EP), + devpriv->insn_buffer, SIZEINSNBUF, &nrec, BULK_TIMEOUT); - if (result < 0) - return result; - if (le16_to_cpu(this_usbduxsub->insn_buffer[0]) == command) - return result; + if (ret < 0) + return ret; + if (le16_to_cpu(devpriv->insn_buffer[0]) == command) + return ret; } - /* this is only reached if the data has been requested a couple of - * times */ + /* command not received */ return -EFAULT; } @@ -1037,7 +1036,7 @@ static int usbdux_ai_insn_read(struct comedi_device *dev, } for (i = 0; i < insn->n; i++) { - err = receive_dux_commands(this_usbduxsub, SENDSINGLEAD); + err = receive_dux_commands(dev, SENDSINGLEAD); if (err < 0) { up(&this_usbduxsub->sem); return 0; @@ -1362,7 +1361,7 @@ static int usbdux_dio_insn_bits(struct comedi_device *dev, up(&this_usbduxsub->sem); return err; } - err = receive_dux_commands(this_usbduxsub, SENDDIOBITSCOMMAND); + err = receive_dux_commands(dev, SENDDIOBITSCOMMAND); if (err < 0) { up(&this_usbduxsub->sem); return err; @@ -1392,7 +1391,7 @@ static int usbdux_counter_read(struct comedi_device *dev, return err; } - err = receive_dux_commands(this_usbduxsub, READCOUNTERCOMMAND); + err = receive_dux_commands(dev, READCOUNTERCOMMAND); if (err < 0) { up(&this_usbduxsub->sem); return err; From 11642c658ff0e8bb13e68ac59593427a482e8c9a Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 14:16:04 -0700 Subject: [PATCH 0728/3400] staging: comedi: usbdux: pass comedi_device pointer to usbdux_alloc_usb_buffers() For aesthetic reasons, pass the comedi_device pointer to this function instead of the private data pointer. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 5980b8e36694..c3fbfdc6fc5c 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -1729,8 +1729,9 @@ static int usbdux_pwm_config(struct comedi_device *dev, /* end of PWM */ /*****************************************************************/ -static int usbdux_alloc_usb_buffers(struct usbdux_private *devpriv) +static int usbdux_alloc_usb_buffers(struct comedi_device *dev) { + struct usbdux_private *devpriv = dev->private; struct urb *urb; int i; @@ -1909,7 +1910,7 @@ static int usbdux_auto_attach(struct comedi_device *dev, devpriv->num_out_buffers = NUMOFOUTBUFFERSFULL; } - ret = usbdux_alloc_usb_buffers(devpriv); + ret = usbdux_alloc_usb_buffers(dev); if (ret) return ret; From 0b20d613afd0e1ba394c2b209a5f459c5f43e1ff Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 14:16:24 -0700 Subject: [PATCH 0729/3400] staging: comedi: usbdux: remove usb_device back pointer from private data The usb_device can be found when needed using the comedi_to_usb_dev() helper. Use that instead the remove the back pointer from the private data. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 39 ++++++++++++------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index c3fbfdc6fc5c..88419444497f 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -202,8 +202,6 @@ static const struct comedi_lrange range_usbdux_ao_range = { }; struct usbdux_private { - /* pointer to the usb-device */ - struct usb_device *usbdev; /* actual number of in-buffers */ int num_in_buffers; /* actual number of out-buffers */ @@ -384,7 +382,7 @@ static void usbduxsub_ai_isoc_irq(struct urb *urb) return; } - urb->dev = devpriv->usbdev; + urb->dev = comedi_to_usb_dev(dev); /* resubmit the urb */ err = usb_submit_urb(urb, GFP_ATOMIC); @@ -587,7 +585,7 @@ static void usbduxsub_ao_isoc_irq(struct urb *urb) } } urb->transfer_buffer_length = SIZEOUTBUF; - urb->dev = devpriv->usbdev; + urb->dev = comedi_to_usb_dev(dev); urb->status = 0; if (devpriv->ao_cmd_running) { if (devpriv->high_speed) @@ -622,8 +620,7 @@ static int usbdux_firmware_upload(struct comedi_device *dev, const u8 *data, size_t size, unsigned long context) { - struct usbdux_private *usbduxsub = dev->private; - struct usb_device *usb = usbduxsub->usbdev; + struct usb_device *usb = comedi_to_usb_dev(dev); uint8_t *buf; uint8_t *tmp; int ret; @@ -693,6 +690,7 @@ done: static int usbduxsub_submit_inurbs(struct comedi_device *dev) { + struct usb_device *usb = comedi_to_usb_dev(dev); struct usbdux_private *devpriv = dev->private; struct urb *urb; int ret; @@ -705,7 +703,7 @@ static int usbduxsub_submit_inurbs(struct comedi_device *dev) /* in case of a resubmission after an unlink... */ urb->interval = devpriv->ai_interval; urb->context = dev; - urb->dev = devpriv->usbdev; + urb->dev = usb; urb->status = 0; urb->transfer_flags = URB_ISO_ASAP; @@ -718,6 +716,7 @@ static int usbduxsub_submit_inurbs(struct comedi_device *dev) static int usbduxsub_submit_outurbs(struct comedi_device *dev) { + struct usb_device *usb = comedi_to_usb_dev(dev); struct usbdux_private *devpriv = dev->private; struct urb *urb; int ret; @@ -728,7 +727,7 @@ static int usbduxsub_submit_outurbs(struct comedi_device *dev) /* in case of a resubmission after an unlink... */ urb->context = dev; - urb->dev = devpriv->usbdev; + urb->dev = usb; urb->status = 0; urb->transfer_flags = URB_ISO_ASAP; @@ -849,8 +848,8 @@ static int8_t create_adc_command(unsigned int chan, int range) static int send_dux_commands(struct comedi_device *dev, int cmd_type) { + struct usb_device *usb = comedi_to_usb_dev(dev); struct usbdux_private *devpriv = dev->private; - struct usb_device *usb = devpriv->usbdev; int nsent; devpriv->dux_commands[0] = cmd_type; @@ -862,8 +861,8 @@ static int send_dux_commands(struct comedi_device *dev, int cmd_type) static int receive_dux_commands(struct comedi_device *dev, int command) { + struct usb_device *usb = comedi_to_usb_dev(dev); struct usbdux_private *devpriv = dev->private; - struct usb_device *usb = devpriv->usbdev; int ret; int nrec; int i; @@ -1520,7 +1519,7 @@ static void usbduxsub_pwm_irq(struct urb *urb) return; urb->transfer_buffer_length = devpriv->size_pwm_buf; - urb->dev = devpriv->usbdev; + urb->dev = comedi_to_usb_dev(dev); urb->status = 0; if (devpriv->pwm_cmd_running) { ret = usb_submit_urb(urb, GFP_ATOMIC); @@ -1540,12 +1539,12 @@ static void usbduxsub_pwm_irq(struct urb *urb) static int usbduxsub_submit_pwm_urbs(struct comedi_device *dev) { + struct usb_device *usb = comedi_to_usb_dev(dev); struct usbdux_private *devpriv = dev->private; struct urb *urb = devpriv->urb_pwm; /* in case of a resubmission after an unlink... */ - usb_fill_bulk_urb(urb, devpriv->usbdev, - usb_sndbulkpipe(devpriv->usbdev, PWM_EP), + usb_fill_bulk_urb(urb, usb, usb_sndbulkpipe(usb, PWM_EP), urb->transfer_buffer, devpriv->size_pwm_buf, usbduxsub_pwm_irq, @@ -1731,6 +1730,7 @@ static int usbdux_pwm_config(struct comedi_device *dev, static int usbdux_alloc_usb_buffers(struct comedi_device *dev) { + struct usb_device *usb = comedi_to_usb_dev(dev); struct usbdux_private *devpriv = dev->private; struct urb *urb; int i; @@ -1773,11 +1773,11 @@ static int usbdux_alloc_usb_buffers(struct comedi_device *dev) return -ENOMEM; devpriv->urb_in[i] = urb; - urb->dev = devpriv->usbdev; + urb->dev = usb; /* will be filled later with a pointer to the comedi-device */ /* and ONLY then the urb should be submitted */ urb->context = NULL; - urb->pipe = usb_rcvisocpipe(devpriv->usbdev, ISOINEP); + urb->pipe = usb_rcvisocpipe(usb, ISOINEP); urb->transfer_flags = URB_ISO_ASAP; urb->transfer_buffer = kzalloc(SIZEINBUF, GFP_KERNEL); if (!urb->transfer_buffer) @@ -1803,11 +1803,11 @@ static int usbdux_alloc_usb_buffers(struct comedi_device *dev) return -ENOMEM; devpriv->urb_out[i] = urb; - urb->dev = devpriv->usbdev; + urb->dev = usb; /* will be filled later with a pointer to the comedi-device */ /* and ONLY then the urb should be submitted */ urb->context = NULL; - urb->pipe = usb_sndisocpipe(devpriv->usbdev, ISOOUTEP); + urb->pipe = usb_sndisocpipe(usb, ISOOUTEP); urb->transfer_flags = URB_ISO_ASAP; urb->transfer_buffer = kzalloc(SIZEOUTBUF, GFP_KERNEL); if (!urb->transfer_buffer) @@ -1896,11 +1896,10 @@ static int usbdux_auto_attach(struct comedi_device *dev, sema_init(&devpriv->sem, 1); - devpriv->usbdev = usb; devpriv->ifnum = intf->altsetting->desc.bInterfaceNumber; usb_set_intfdata(intf, devpriv); - devpriv->high_speed = (devpriv->usbdev->speed == USB_SPEED_HIGH); + devpriv->high_speed = (usb->speed == USB_SPEED_HIGH); if (devpriv->high_speed) { devpriv->num_in_buffers = NUMOFINBUFFERSHIGH; devpriv->num_out_buffers = NUMOFOUTBUFFERSHIGH; @@ -1915,7 +1914,7 @@ static int usbdux_auto_attach(struct comedi_device *dev, return ret; /* setting to alternate setting 3: enabling iso ep and bulk ep. */ - ret = usb_set_interface(devpriv->usbdev, devpriv->ifnum, 3); + ret = usb_set_interface(usb, devpriv->ifnum, 3); if (ret < 0) { dev_err(dev->class_dev, "could not set alternate setting 3 in high speed\n"); From 903f4fde801343eb95e3f30cab24c50c9fe367c6 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 14:16:44 -0700 Subject: [PATCH 0730/3400] staging: comedi: usbdux: remove 'ifnum' from the private data The 'ifnum' is only used during the attach of the device. Remove it from the private data. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 88419444497f..c0c4a2711664 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -223,8 +223,6 @@ struct usbdux_private { int16_t *insn_buffer; /* output buffer for single DA outputs */ int16_t *out_buffer; - /* interface number */ - int ifnum; /* is it USB_SPEED_HIGH or not? */ short int high_speed; /* asynchronous command is running */ @@ -1896,7 +1894,6 @@ static int usbdux_auto_attach(struct comedi_device *dev, sema_init(&devpriv->sem, 1); - devpriv->ifnum = intf->altsetting->desc.bInterfaceNumber; usb_set_intfdata(intf, devpriv); devpriv->high_speed = (usb->speed == USB_SPEED_HIGH); @@ -1914,7 +1911,8 @@ static int usbdux_auto_attach(struct comedi_device *dev, return ret; /* setting to alternate setting 3: enabling iso ep and bulk ep. */ - ret = usb_set_interface(usb, devpriv->ifnum, 3); + ret = usb_set_interface(usb, intf->altsetting->desc.bInterfaceNumber, + 3); if (ret < 0) { dev_err(dev->class_dev, "could not set alternate setting 3 in high speed\n"); From b8c162c961c47f0fa991cc8f4b2acd32e55ae589 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 14:17:05 -0700 Subject: [PATCH 0731/3400] staging: comedi: usbdux: make private data flags bit-fields Change the flags in the private data to bit-fields to save a bit of space. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index c0c4a2711664..0434674121e8 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -223,16 +223,14 @@ struct usbdux_private { int16_t *insn_buffer; /* output buffer for single DA outputs */ int16_t *out_buffer; - /* is it USB_SPEED_HIGH or not? */ - short int high_speed; - /* asynchronous command is running */ - short int ai_cmd_running; - short int ao_cmd_running; - /* pwm is running */ - short int pwm_cmd_running; - /* continous acquisition */ - short int ai_continous; - short int ao_continous; + + unsigned int high_speed:1; + unsigned int ai_cmd_running:1; + unsigned int ai_continous:1; + unsigned int ao_cmd_running:1; + unsigned int ao_continous:1; + unsigned int pwm_cmd_running:1; + /* number of samples to acquire */ int ai_sample_count; int ao_sample_count; From b3476e67c1afa634437a429673b75e735dcfbd6a Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 14:17:23 -0700 Subject: [PATCH 0732/3400] staging: comedi: usbdux: tidy up usbdux_ai_stop() For aesthetic reasons, pass the comedi_device pointer to this function instead of the private data pointer. Rename the local variable used for the private data pointer to the comedi "norm". Remove the unnecessary sanity check of the private data pointer. This function can only be called is the private data was allocated during the attach. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 31 +++++++++---------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 0434674121e8..c195ec6f8fb5 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -270,24 +270,15 @@ static int usbduxsub_unlink_inurbs(struct usbdux_private *usbduxsub_tmp) return err; } -/* - * This will stop a running acquisition operation - * Is called from within this driver from both the - * interrupt context and from comedi - */ -static int usbdux_ai_stop(struct usbdux_private *this_usbduxsub, int do_unlink) +static int usbdux_ai_stop(struct comedi_device *dev, int do_unlink) { + struct usbdux_private *devpriv = dev->private; int ret = 0; - if (!this_usbduxsub) - return -EFAULT; + if (do_unlink) + ret = usbduxsub_unlink_inurbs(devpriv); - if (do_unlink) { - /* stop aquistion */ - ret = usbduxsub_unlink_inurbs(this_usbduxsub); - } - - this_usbduxsub->ai_cmd_running = 0; + devpriv->ai_cmd_running = 0; return ret; } @@ -310,7 +301,7 @@ static int usbdux_ai_cancel(struct comedi_device *dev, /* prevent other CPUs from submitting new commands just now */ down(&this_usbduxsub->sem); /* unlink only if the urb really has been submitted */ - res = usbdux_ai_stop(this_usbduxsub, this_usbduxsub->ai_cmd_running); + res = usbdux_ai_stop(dev, this_usbduxsub->ai_cmd_running); up(&this_usbduxsub->sem); return res; } @@ -346,7 +337,7 @@ static void usbduxsub_ai_isoc_irq(struct urb *urb) s->async->events |= COMEDI_CB_ERROR; comedi_event(dev, s); /* stop the transfer w/o unlink */ - usbdux_ai_stop(devpriv, 0); + usbdux_ai_stop(dev, 0); } return; @@ -361,7 +352,7 @@ static void usbduxsub_ai_isoc_irq(struct urb *urb) s->async->events |= COMEDI_CB_ERROR; comedi_event(dev, s); /* don't do an unlink here */ - usbdux_ai_stop(devpriv, 0); + usbdux_ai_stop(dev, 0); } return; } @@ -392,7 +383,7 @@ static void usbduxsub_ai_isoc_irq(struct urb *urb) s->async->events |= COMEDI_CB_ERROR; comedi_event(dev, s); /* don't do an unlink here */ - usbdux_ai_stop(devpriv, 0); + usbdux_ai_stop(dev, 0); return; } @@ -410,7 +401,7 @@ static void usbduxsub_ai_isoc_irq(struct urb *urb) /* all samples received? */ if (devpriv->ai_sample_count < 0) { /* prevent a resubmit next time */ - usbdux_ai_stop(devpriv, 0); + usbdux_ai_stop(dev, 0); /* say comedi that the acquistion is over */ s->async->events |= COMEDI_CB_EOA; comedi_event(dev, s); @@ -430,7 +421,7 @@ static void usbduxsub_ai_isoc_irq(struct urb *urb) } if (unlikely(err == 0)) { /* buffer overflow */ - usbdux_ai_stop(devpriv, 0); + usbdux_ai_stop(dev, 0); return; } } From aa6081e5e0989f4df9ca35fa412e3ba8c23e38df Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 14:17:50 -0700 Subject: [PATCH 0733/3400] staging: comedi: usbdux: tidy up usbdux_ai_cancel() Rename the local variable used for the private data pointer to the comedi "norm". Remove the unnecessary sanity check of the private data pointer. This function can only be called is the private data was allocated during the attach. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index c195ec6f8fb5..edee14851d70 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -283,27 +283,19 @@ static int usbdux_ai_stop(struct comedi_device *dev, int do_unlink) return ret; } -/* - * This will cancel a running acquisition operation. - * This is called by comedi but never from inside the driver. - */ static int usbdux_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { - struct usbdux_private *this_usbduxsub; - int res = 0; - - /* force unlink of all urbs */ - this_usbduxsub = dev->private; - if (!this_usbduxsub) - return -EFAULT; + struct usbdux_private *devpriv = dev->private; + int ret = 0; /* prevent other CPUs from submitting new commands just now */ - down(&this_usbduxsub->sem); + down(&devpriv->sem); /* unlink only if the urb really has been submitted */ - res = usbdux_ai_stop(dev, this_usbduxsub->ai_cmd_running); - up(&this_usbduxsub->sem); - return res; + ret = usbdux_ai_stop(dev, devpriv->ai_cmd_running); + up(&devpriv->sem); + + return ret; } /* analogue IN - interrupt service routine */ From 7c8ed94eb8c0bae49f900085d5221529cf20378c Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 14:18:15 -0700 Subject: [PATCH 0734/3400] staging: comedi: usbdux: tidy up usbdux_ao_stop() For aesthetic reasons, pass the comedi_device pointer to this function instead of the private data pointer. Rename the local variable used for the private data pointer to the comedi "norm". Remove the unnecessary sanity check of the private data pointer. This function can only be called is the private data was allocated during the attach. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index edee14851d70..1f6750950a5d 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -436,20 +436,15 @@ static int usbduxsub_unlink_outurbs(struct usbdux_private *usbduxsub_tmp) return err; } -/* This will cancel a running acquisition operation - * in any context. - */ -static int usbdux_ao_stop(struct usbdux_private *this_usbduxsub, int do_unlink) +static int usbdux_ao_stop(struct comedi_device *dev, int do_unlink) { + struct usbdux_private *devpriv = dev->private; int ret = 0; - if (!this_usbduxsub) - return -EFAULT; - if (do_unlink) - ret = usbduxsub_unlink_outurbs(this_usbduxsub); + ret = usbduxsub_unlink_outurbs(devpriv); - this_usbduxsub->ao_cmd_running = 0; + devpriv->ao_cmd_running = 0; return ret; } @@ -467,7 +462,7 @@ static int usbdux_ao_cancel(struct comedi_device *dev, /* prevent other CPUs from submitting a command just now */ down(&this_usbduxsub->sem); /* unlink only if it is really running */ - res = usbdux_ao_stop(this_usbduxsub, this_usbduxsub->ao_cmd_running); + res = usbdux_ao_stop(dev, this_usbduxsub->ao_cmd_running); up(&this_usbduxsub->sem); return res; } @@ -494,7 +489,7 @@ static void usbduxsub_ao_isoc_irq(struct urb *urb) if (devpriv->ao_cmd_running) { s->async->events |= COMEDI_CB_EOA; comedi_event(dev, s); - usbdux_ao_stop(devpriv, 0); + usbdux_ao_stop(dev, 0); } return; @@ -508,7 +503,7 @@ static void usbduxsub_ao_isoc_irq(struct urb *urb) s->async->events |= COMEDI_CB_EOA; comedi_event(dev, s); /* we do an unlink if we are in the high speed mode */ - usbdux_ao_stop(devpriv, 0); + usbdux_ao_stop(dev, 0); } return; } @@ -529,7 +524,7 @@ static void usbduxsub_ao_isoc_irq(struct urb *urb) devpriv->ao_sample_count--; if (devpriv->ao_sample_count < 0) { /* all samples transmitted */ - usbdux_ao_stop(devpriv, 0); + usbdux_ao_stop(dev, 0); s->async->events |= COMEDI_CB_EOA; comedi_event(dev, s); /* no resubmit of the urb */ @@ -588,7 +583,7 @@ static void usbduxsub_ao_isoc_irq(struct urb *urb) s->async->events |= COMEDI_CB_ERROR; comedi_event(dev, s); /* don't do an unlink here */ - usbdux_ao_stop(devpriv, 0); + usbdux_ao_stop(dev, 0); } } } From eee7d9e9ef711abda2482af2d6b15d76e34b8db5 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 14:18:36 -0700 Subject: [PATCH 0735/3400] staging: comedi: usbdux: tidy up usbdux_ao_cancel() Rename the local variable used for the private data pointer to the comedi "norm". Remove the unnecessary sanity check of the private data pointer. This function can only be called is the private data was allocated during the attach. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 1f6750950a5d..d0d683bc83c2 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -449,22 +449,19 @@ static int usbdux_ao_stop(struct comedi_device *dev, int do_unlink) return ret; } -/* force unlink, is called by comedi */ static int usbdux_ao_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { - struct usbdux_private *this_usbduxsub = dev->private; - int res = 0; - - if (!this_usbduxsub) - return -EFAULT; + struct usbdux_private *devpriv = dev->private; + int ret = 0; /* prevent other CPUs from submitting a command just now */ - down(&this_usbduxsub->sem); + down(&devpriv->sem); /* unlink only if it is really running */ - res = usbdux_ao_stop(dev, this_usbduxsub->ao_cmd_running); - up(&this_usbduxsub->sem); - return res; + ret = usbdux_ao_stop(dev, devpriv->ao_cmd_running); + up(&devpriv->sem); + + return ret; } static void usbduxsub_ao_isoc_irq(struct urb *urb) From 065b09127057fa728c9290d62c2a2e1c4925132b Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 10:00:45 -0700 Subject: [PATCH 0736/3400] staging: comedi: range: tidy up comedi_check_chanlist() The only difference in the if() and else if() check of the chanlist is the source of the range table length. Consolidate the checks to make the function a bit more concise. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/range.c | 43 ++++++++++++++++------------------ 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/drivers/staging/comedi/range.c b/drivers/staging/comedi/range.c index 1f20332cc459..8fde55495d34 100644 --- a/drivers/staging/comedi/range.c +++ b/drivers/staging/comedi/range.c @@ -127,38 +127,35 @@ static int aref_invalid(struct comedi_subdevice *s, unsigned int chanspec) return 1; } -/* - This function checks each element in a channel/gain list to make - make sure it is valid. +/** + * comedi_check_chanlist() - Validate each element in a chanlist. + * @s: comedi_subdevice struct + * @n: number of elements in the chanlist + * @chanlist: the chanlist to validate */ int comedi_check_chanlist(struct comedi_subdevice *s, int n, unsigned int *chanlist) { struct comedi_device *dev = s->device; - int i; - int chan; + unsigned int chanspec; + int chan, range_len, i; - if (s->range_table) { - for (i = 0; i < n; i++) - if (CR_CHAN(chanlist[i]) >= s->n_chan || - CR_RANGE(chanlist[i]) >= s->range_table->length - || aref_invalid(s, chanlist[i])) { - dev_warn(dev->class_dev, - "bad chanlist[%d]=0x%08x in_chan=%d range length=%d\n", - i, chanlist[i], s->n_chan, - s->range_table->length); - return -EINVAL; - } - } else if (s->range_table_list) { + if (s->range_table || s->range_table_list) { for (i = 0; i < n; i++) { - chan = CR_CHAN(chanlist[i]); + chanspec = chanlist[i]; + chan = CR_CHAN(chanspec); + if (s->range_table) + range_len = s->range_table->length; + else if (s->range_table_list && chan < s->n_chan) + range_len = s->range_table_list[chan]->length; + else + range_len = 0; if (chan >= s->n_chan || - CR_RANGE(chanlist[i]) >= - s->range_table_list[chan]->length - || aref_invalid(s, chanlist[i])) { + CR_RANGE(chanspec) >= range_len || + aref_invalid(s, chanspec)) { dev_warn(dev->class_dev, - "bad chanlist[%d]=0x%08x\n", - i, chanlist[i]); + "bad chanlist[%d]=0x%08x chan=%d range length=%d\n", + i, chanspec, chan, range_len); return -EINVAL; } } From a2ec3dd32508857c09aea044510e28d5411533a9 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 10:03:50 -0700 Subject: [PATCH 0737/3400] staging: comedi: adv_pci1724: remove ao_range_list_1724 All the AO channels have the same ranges. Remove the subdevice s->range_table_list and just use the s->range_table to setup the ranges. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/adv_pci1724.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/staging/comedi/drivers/adv_pci1724.c b/drivers/staging/comedi/drivers/adv_pci1724.c index 84907c79ca2b..009a3039fc4f 100644 --- a/drivers/staging/comedi/drivers/adv_pci1724.c +++ b/drivers/staging/comedi/drivers/adv_pci1724.c @@ -125,10 +125,6 @@ static const struct comedi_lrange ao_ranges_1724 = { 4, } }; -static const struct comedi_lrange *const ao_range_list_1724[NUM_AO_CHANNELS] = { - [0 ... NUM_AO_CHANNELS - 1] = &ao_ranges_1724, -}; - /* this structure is for data unique to this hardware driver. */ struct adv_pci1724_private { int ao_value[NUM_AO_CHANNELS]; @@ -308,7 +304,7 @@ static int setup_subdevices(struct comedi_device *dev) s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND; s->n_chan = NUM_AO_CHANNELS; s->maxdata = 0x3fff; - s->range_table_list = ao_range_list_1724; + s->range_table = &ao_ranges_1724; s->insn_read = ao_readback_insn; s->insn_write = ao_winsn; From 32d6d4e00b32c056fce8adf9d36a61f3c4d8fc87 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 11:11:51 -0700 Subject: [PATCH 0738/3400] staging: comedi: addi_apci_1710: fix some compile errors/warnings Fix a couple comments within comments errors. Remove the #include of eddi_eeprom.c. This driver does not use it. Remove an unused local variable. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c | 2 +- drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c | 2 +- drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c | 2 +- drivers/staging/comedi/drivers/addi_apci_1710.c | 2 -- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c index d0702084caa2..a979abfc9121 100644 --- a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c +++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c @@ -444,7 +444,7 @@ int i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device *dev,struct come i_ReturnValue=insn->n; b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec); b_TimerNbr = (unsigned char) CR_CHAN(insn->chanspec); - b_ActionType = (unsigned char) data[0]; /* enable disable */ + b_ActionType = (unsigned char) data[0]; enable disable +----------------------------------------------------------------------------+ | Output Parameters : - | +----------------------------------------------------------------------------+ diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c index 27de18e79895..7d1883a0da28 100644 --- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c +++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c @@ -653,7 +653,7 @@ static int i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device *dev, * s_BoardInfos. ui_Address + (64 * b_ModulNbr), * dw_WriteValue); */ -*/ + outl(dw_WriteValue, devpriv->s_BoardInfos. ui_Address + (64 * b_ModulNbr)); diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c index fb56360444ee..c01497a8a457 100644 --- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c +++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c @@ -814,7 +814,7 @@ int i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device *dev,struct comedi b_ModulNbr = CR_AREF(insn->chanspec); b_OutputChannel= CR_CHAN(insn->chanspec); - ui_State = data[0]; /* ON or OFF */ + ui_State = data[0]; ON or OFF +----------------------------------------------------------------------------+ | Output Parameters : - | +----------------------------------------------------------------------------+ diff --git a/drivers/staging/comedi/drivers/addi_apci_1710.c b/drivers/staging/comedi/drivers/addi_apci_1710.c index e600c05c2ecc..3035b2aa20cb 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1710.c +++ b/drivers/staging/comedi/drivers/addi_apci_1710.c @@ -19,7 +19,6 @@ static void fpu_end(void) kernel_fpu_end(); } -#include "addi-data/addi_eeprom.c" #include "addi-data/hwdrv_APCI1710.c" static irqreturn_t v_ADDI_Interrupt(int irq, void *d) @@ -33,7 +32,6 @@ static int apci1710_auto_attach(struct comedi_device *dev, { struct pci_dev *pcidev = comedi_to_pci_dev(dev); struct addi_private *devpriv; - struct comedi_subdevice *s; int ret; devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); From c1f00be048c10763c7fad230bc6141b3538ef2d6 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 11:12:35 -0700 Subject: [PATCH 0739/3400] staging: comedi: addi_apci_1710: separate from addi_common.h Move the necessary bits from addi_common.h to remove it's dependency and make this driver standalone. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- .../staging/comedi/drivers/addi_apci_1710.c | 142 +++++++++++++++++- 1 file changed, 141 insertions(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/addi_apci_1710.c b/drivers/staging/comedi/drivers/addi_apci_1710.c index 3035b2aa20cb..9157ac50815e 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1710.c +++ b/drivers/staging/comedi/drivers/addi_apci_1710.c @@ -1,5 +1,6 @@ #include #include +#include #include @@ -7,7 +8,146 @@ #include "comedi_fc.h" #include "amcc_s5933.h" -#include "addi-data/addi_common.h" +#define APCI1710_SAVE_INTERRUPT 1 + +union str_ModuleInfo { + /* Incremental counter infos */ + struct { + union { + struct { + unsigned char b_ModeRegister1; + unsigned char b_ModeRegister2; + unsigned char b_ModeRegister3; + unsigned char b_ModeRegister4; + } s_ByteModeRegister; + unsigned int dw_ModeRegister1_2_3_4; + } s_ModeRegister; + + struct { + unsigned int b_IndexInit:1; + unsigned int b_CounterInit:1; + unsigned int b_ReferenceInit:1; + unsigned int b_IndexInterruptOccur:1; + unsigned int b_CompareLogicInit:1; + unsigned int b_FrequencyMeasurementInit:1; + unsigned int b_FrequencyMeasurementEnable:1; + } s_InitFlag; + + } s_SiemensCounterInfo; + + /* SSI infos */ + struct { + unsigned char b_SSIProfile; + unsigned char b_PositionTurnLength; + unsigned char b_TurnCptLength; + unsigned char b_SSIInit; + } s_SSICounterInfo; + + /* TTL I/O infos */ + struct { + unsigned char b_TTLInit; + unsigned char b_PortConfiguration[4]; + } s_TTLIOInfo; + + /* Digital I/O infos */ + struct { + unsigned char b_DigitalInit; + unsigned char b_ChannelAMode; + unsigned char b_ChannelBMode; + unsigned char b_OutputMemoryEnabled; + unsigned int dw_OutputMemory; + } s_DigitalIOInfo; + + /* 82X54 timer infos */ + struct { + struct { + unsigned char b_82X54Init; + unsigned char b_InputClockSelection; + unsigned char b_InputClockLevel; + unsigned char b_OutputLevel; + unsigned char b_HardwareGateLevel; + unsigned int dw_ConfigurationWord; + } s_82X54TimerInfo[3]; + unsigned char b_InterruptMask; + } s_82X54ModuleInfo; + + /* Chronometer infos */ + struct { + unsigned char b_ChronoInit; + unsigned char b_InterruptMask; + unsigned char b_PCIInputClock; + unsigned char b_TimingUnit; + unsigned char b_CycleMode; + double d_TimingInterval; + unsigned int dw_ConfigReg; + } s_ChronoModuleInfo; + + /* Pulse encoder infos */ + struct { + struct { + unsigned char b_PulseEncoderInit; + } s_PulseEncoderInfo[4]; + unsigned int dw_SetRegister; + unsigned int dw_ControlRegister; + unsigned int dw_StatusRegister; + } s_PulseEncoderModuleInfo; + + /* Tor conter infos */ + struct { + struct { + unsigned char b_TorCounterInit; + unsigned char b_TimingUnit; + unsigned char b_InterruptEnable; + double d_TimingInterval; + unsigned int ul_RealTimingInterval; + } s_TorCounterInfo[2]; + unsigned char b_PCIInputClock; + } s_TorCounterModuleInfo; + + /* PWM infos */ + struct { + struct { + unsigned char b_PWMInit; + unsigned char b_TimingUnit; + unsigned char b_InterruptEnable; + double d_LowTiming; + double d_HighTiming; + unsigned int ul_RealLowTiming; + unsigned int ul_RealHighTiming; + } s_PWMInfo[2]; + unsigned char b_ClockSelection; + } s_PWMModuleInfo; + + /* CDA infos */ + struct { + unsigned char b_CDAEnable; + unsigned char b_FctSelection; + } s_CDAModuleInfo; +}; + +struct addi_private { + /* Pointer to the current process */ + struct task_struct *tsk_Current; + + struct { + unsigned int ui_Address; + unsigned char b_BoardVersion; + unsigned int dw_MolduleConfiguration[4]; + } s_BoardInfos; + + struct { + unsigned int ul_InterruptOccur; + unsigned int ui_Read; + unsigned int ui_Write; + struct { + unsigned char b_OldModuleMask; + unsigned int ul_OldInterruptMask; + unsigned int ul_OldCounterLatchValue; + } s_FIFOInterruptParameters[APCI1710_SAVE_INTERRUPT]; + } s_InterruptParameters; + + union str_ModuleInfo s_ModuleInfo[4]; +}; static void fpu_begin(void) { From 3b4cb6717d816be3ee838920b1477d0e73101a09 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 11:13:53 -0700 Subject: [PATCH 0740/3400] staging: comedi: addi_apci_1710: delete driver This driver is seriously broken and most of it does not "work" with the comedi API. Just remove it. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- .../comedi/drivers/addi-data/APCI1710_82x54.c | 1068 ---- .../drivers/addi-data/APCI1710_Chrono.c | 2050 ------- .../drivers/addi-data/APCI1710_Dig_io.c | 1037 ---- .../drivers/addi-data/APCI1710_INCCPT.c | 5461 ----------------- .../drivers/addi-data/APCI1710_Inp_cpt.c | 866 --- .../comedi/drivers/addi-data/APCI1710_Pwm.c | 3582 ----------- .../comedi/drivers/addi-data/APCI1710_Ssi.c | 845 --- .../comedi/drivers/addi-data/APCI1710_Tor.c | 2065 ------- .../comedi/drivers/addi-data/APCI1710_Ttl.c | 1044 ---- .../comedi/drivers/addi-data/hwdrv_APCI1710.c | 1314 ---- .../staging/comedi/drivers/addi_apci_1710.c | 237 - 11 files changed, 19569 deletions(-) delete mode 100644 drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c delete mode 100644 drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c delete mode 100644 drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c delete mode 100644 drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c delete mode 100644 drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c delete mode 100644 drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c delete mode 100644 drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c delete mode 100644 drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c delete mode 100644 drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c delete mode 100644 drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c delete mode 100644 drivers/staging/comedi/drivers/addi_apci_1710.c diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c deleted file mode 100644 index a979abfc9121..000000000000 --- a/drivers/staging/comedi/drivers/addi-data/APCI1710_82x54.c +++ /dev/null @@ -1,1068 +0,0 @@ -/* - * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. - * - * ADDI-DATA GmbH - * Dieselstrasse 3 - * D-77833 Ottersweier - * Tel: +19(0)7223/9493-0 - * Fax: +49(0)7223/9493-92 - * http://www.addi-data.com - * info@addi-data.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. - */ -/* - | Description : APCI-1710 82X54 timer module | -*/ - -#define APCI1710_PCI_BUS_CLOCK 0 -#define APCI1710_FRONT_CONNECTOR_INPUT 1 -#define APCI1710_TIMER_READVALUE 0 -#define APCI1710_TIMER_GETOUTPUTLEVEL 1 -#define APCI1710_TIMER_GETPROGRESSSTATUS 2 -#define APCI1710_TIMER_WRITEVALUE 3 - -#define APCI1710_TIMER_READINTERRUPT 1 -#define APCI1710_TIMER_READALLTIMER 2 - -#ifndef APCI1710_10MHZ -#define APCI1710_10MHZ 10 -#endif - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_InitTimer | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_TimerNbr, | -| unsigned char_ b_TimerMode, | -| ULONG_ ul_ReloadValue, | -| unsigned char_ b_InputClockSelection, | -| unsigned char_ b_InputClockLevel, | -| unsigned char_ b_OutputLevel, | -| unsigned char_ b_HardwareGateLevel) -int i_InsnConfig_InitTimer(struct comedi_device *dev,struct comedi_subdevice *s, - struct comedi_insn *insn,unsigned int *data) -| -+----------------------------------------------------------------------------+ -| Task : Configure the Timer (b_TimerNbr) operating mode | -| (b_TimerMode) from selected module (b_ModulNbr). | -| You must calling this function be for you call any | -| other function witch access of the timer. | -| | -| | -| Timer mode description table | -| | -|+--------+-----------------------------+--------------+--------------------+| -||Selected+ Mode description +u_ReloadValue | Hardware gate input|| -|| mode | | description | action || -|+--------+-----------------------------+--------------+--------------------+| -|| |Mode 0 is typically used | | || -|| |for event counting. After | | || -|| |the initialisation, OUT | | || -|| |is initially low, and | | || -|| 0 |will remain low until the |Start counting| Hardware gate || -|| |counter reaches zero. | value | || -|| |OUT then goes high and | | || -|| |remains high until a new | | || -|| |count is written. See | | || -|| |"i_APCI1710_WriteTimerValue" | | || -|| |function. | | || -|+--------+-----------------------------+--------------+--------------------+| -|| |Mode 1 is similar to mode 0 | | || -|| |except for the gate input | | || -|| 1 |action. The gate input is not|Start counting| Hardware trigger || -|| |used for enabled or disabled | value | || -|| |the timer. | | || -|| |The gate input is used for | | || -|| |triggered the timer. | | || -|+--------+-----------------------------+--------------+--------------------+| -|| |This mode functions like a | | || -|| |divide-by-ul_ReloadValue | | || -|| |counter. It is typically used| | || -|| |to generate a real time clock| | || -|| |interrupt. OUT will initially| | || -|| 2 |be high after the | Division | Hardware gate || -|| |initialisation. When the | factor | || -|| |initial count has decremented| | || -|| |to 1, OUT goes low for one | | || -|| |CLK pule. OUT then goes high | | || -|| |again, the counter reloads | | || -|| |the initial count | | || -|| |(ul_ReloadValue) and the | | || -|| |process is repeated. | | || -|| |This action can generated a | | || -|| |interrupt. See function | | || -|| |"i_APCI1710_SetBoardInt- | | || -|| |RoutineX" | | || -|| |and "i_APCI1710_EnableTimer" | | || -|+--------+-----------------------------+--------------+--------------------+| -|| |Mode 3 is typically used for | | || -|| |baud rate generation. This | | || -|| |mode is similar to mode 2 | | || -|| |except for the duty cycle of | | || -|| 3 |OUT. OUT will initially be | Division | Hardware gate || -|| |high after the initialisation| factor | || -|| |When half the initial count | | || -|| |(ul_ReloadValue) has expired,| | || -|| |OUT goes low for the | | || -|| |remainder of the count. The | | || -|| |mode is periodic; the | | || -|| |sequence above is repeated | | || -|| |indefinitely. | | || -|+--------+-----------------------------+--------------+--------------------+| -|| |OUT will be initially high | | || -|| |after the initialisation. | | || -|| |When the initial count | | || -|| 4 |expires OUT will go low for |Start counting| Hardware gate || -|| |one CLK pulse and then go | value | || -|| |high again. | | || -|| |The counting sequences is | | || -|| |triggered by writing a new | | || -|| |value. See | | || -|| |"i_APCI1710_WriteTimerValue" | | || -|| |function. If a new count is | | || -|| |written during counting, | | || -|| |it will be loaded on the | | || -|| |next CLK pulse | | || -|+--------+-----------------------------+--------------+--------------------+| -|| |Mode 5 is similar to mode 4 | | || -|| |except for the gate input | | || -|| |action. The gate input is not| | || -|| 5 |used for enabled or disabled |Start counting| Hardware trigger || -|| |the timer. The gate input is | value | || -|| |used for triggered the timer.| | || -|+--------+-----------------------------+--------------+--------------------+| -| | -| | -| | -| Input clock selection table | -| | -| +--------------------------------+------------------------------------+ | -| | b_InputClockSelection | Description | | -| | parameter | | | -| +--------------------------------+------------------------------------+ | -| | APCI1710_PCI_BUS_CLOCK | For the timer input clock, the PCI | | -| | | bus clock / 4 is used. This PCI bus| | -| | | clock can be 30MHz or 33MHz. For | | -| | | Timer 0 only this selection are | | -| | | available. | | -| +--------------------------------+------------------------------------+ | -| | APCI1710_ FRONT_CONNECTOR_INPUT| Of the front connector you have the| | -| | | possibility to inject a input clock| | -| | | for Timer 1 or Timer 2. The source | | -| | | from this clock can eat the output | | -| | | clock from Timer 0 or any other | | -| | | clock source. | | -| +--------------------------------+------------------------------------+ | -| | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board | -| APCI-1710 | -| unsigned char_ b_ModulNbr : Module number to | -| configure (0 to 3) | -| unsigned char_ b_TimerNbr : Timer number to | -| configure (0 to 2) | -| unsigned char_ b_TimerMode : Timer mode selection | -| (0 to 5) | -| 0: Interrupt on terminal| -| count | -| 1: Hardware | -| retriggerable one- | -| shot | -| 2: Rate generator | -| 3: Square wave mode | -| 4: Software triggered | -| strobe | -| 5: Hardware triggered | -| strobe | -| See timer mode | -| description table. | -| ULONG_ ul_ReloadValue : Start counting value | -| or division factor | -| See timer mode | -| description table. | -| unsigned char_ b_InputClockSelection : Selection from input | -| timer clock. | -| See input clock | -| selection table. | -| unsigned char_ b_InputClockLevel : Selection from input | -| clock level. | -| 0 : Low active | -| (Input inverted) | -| 1 : High active | -| unsigned char_ b_OutputLevel, : Selection from output | -| clock level. | -| 0 : Low active | -| 1 : High active | -| (Output inverted) | -| unsigned char_ b_HardwareGateLevel : Selection from | -| hardware gate level. | -| 0 : Low active | -| (Input inverted) | -| 1 : High active | -| If you will not used | -| the hardware gate set | -| this value to 0. -|b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec); - b_TimerNbr = (unsigned char) CR_CHAN(insn->chanspec); - b_TimerMode = (unsigned char) data[0]; - ul_ReloadValue = (unsigned int) data[1]; - b_InputClockSelection =(unsigned char) data[2]; - b_InputClockLevel =(unsigned char) data[3]; - b_OutputLevel =(unsigned char) data[4]; - b_HardwareGateLevel =(unsigned char) data[5]; -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: Module selection wrong | -| -3: Timer selection wrong | -| -4: The module is not a TIMER module | -| -5: Timer mode selection is wrong | -| -6: Input timer clock selection is wrong | -| -7: Selection from input clock level is wrong | -| -8: Selection from output clock level is wrong | -| -9: Selection from hardware gate level is wrong | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_InsnConfigInitTimer(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned char b_ModulNbr; - unsigned char b_TimerNbr; - unsigned char b_TimerMode; - unsigned int ul_ReloadValue; - unsigned char b_InputClockSelection; - unsigned char b_InputClockLevel; - unsigned char b_OutputLevel; - unsigned char b_HardwareGateLevel; - - /* BEGIN JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz */ - unsigned int dw_Test = 0; - /* END JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz */ - - i_ReturnValue = insn->n; - b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec); - b_TimerNbr = (unsigned char) CR_CHAN(insn->chanspec); - b_TimerMode = (unsigned char) data[0]; - ul_ReloadValue = (unsigned int) data[1]; - b_InputClockSelection = (unsigned char) data[2]; - b_InputClockLevel = (unsigned char) data[3]; - b_OutputLevel = (unsigned char) data[4]; - b_HardwareGateLevel = (unsigned char) data[5]; - - /* Test the module number */ - if (b_ModulNbr < 4) { - /* Test if 82X54 timer */ - if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) { - /* Test the timer number */ - - if (b_TimerNbr <= 2) { - /* Test the timer mode */ - if (b_TimerMode <= 5) { - /* BEGIN JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz */ - /* Test te imput clock selection */ - /* - if (((b_TimerNbr == 0) && (b_InputClockSelection == 0)) || - ((b_TimerNbr != 0) && ((b_InputClockSelection == 0) || (b_InputClockSelection == 1)))) - */ - - if (((b_TimerNbr == 0) && - (b_InputClockSelection == APCI1710_PCI_BUS_CLOCK)) || - ((b_TimerNbr == 0) && - (b_InputClockSelection == APCI1710_10MHZ)) || - ((b_TimerNbr != 0) && - ((b_InputClockSelection == APCI1710_PCI_BUS_CLOCK) || - (b_InputClockSelection == APCI1710_FRONT_CONNECTOR_INPUT) || - (b_InputClockSelection == APCI1710_10MHZ)))) { - /* BEGIN JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz */ - if (((b_InputClockSelection == APCI1710_10MHZ) && - ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0x0000FFFFUL) >= 0x3131)) || - (b_InputClockSelection != APCI1710_10MHZ)) { - /* END JK 27.10.2003 : Add the possibility to use a 40 Mhz quartz */ - /* Test the input clock level selection */ - - if ((b_InputClockLevel == 0) || - (b_InputClockLevel == 1)) { - /* Test the output clock level selection */ - if ((b_OutputLevel == 0) || (b_OutputLevel == 1)) { - /* Test the hardware gate level selection */ - if ((b_HardwareGateLevel == 0) || (b_HardwareGateLevel == 1)) { - /* BEGIN JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */ - /* Test if version > 1.1 and clock selection = 10MHz */ - if ((b_InputClockSelection == APCI1710_10MHZ) && ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0x0000FFFFUL) > 0x3131)) { - /* Test if 40MHz quartz on board */ - dw_Test = inl(devpriv->s_BoardInfos.ui_Address + (16 + (b_TimerNbr * 4) + (64 * b_ModulNbr))); - - dw_Test = (dw_Test >> 16) & 1; - } else { - dw_Test = 1; - } - - /* Test if detection OK */ - if (dw_Test == 1) { - /* END JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */ - /* Initialisation OK */ - devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_82X54Init = 1; - - /* Save the input clock selection */ - devpriv-> s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_InputClockSelection = b_InputClockSelection; - - /* Save the input clock level */ - devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_InputClockLevel = ~b_InputClockLevel & 1; - - /* Save the output level */ - devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_OutputLevel = ~b_OutputLevel & 1; - - /* Save the gate level */ - devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_HardwareGateLevel = b_HardwareGateLevel; - - /* Set the configuration word and disable the timer */ - /* BEGIN JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */ - /* - devpriv->s_ModuleInfo [b_ModulNbr]. - s_82X54ModuleInfo. - s_82X54TimerInfo [b_TimerNbr]. - dw_ConfigurationWord = (unsigned int) (((b_HardwareGateLevel << 0) & 0x1) | - ((b_InputClockLevel << 1) & 0x2) | - (((~b_OutputLevel & 1) << 2) & 0x4) | - ((b_InputClockSelection << 4) & 0x10)); - */ - /* Test if 10MHz selected */ - if (b_InputClockSelection == APCI1710_10MHZ) { - b_InputClockSelection = 2; - } - - devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord = (unsigned int)(((b_HardwareGateLevel << 0) & 0x1) | ((b_InputClockLevel << 1) & 0x2) | (((~b_OutputLevel & 1) << 2) & 0x4) | ((b_InputClockSelection << 4) & 0x30)); - /* END JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */ - outl(devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord, devpriv->s_BoardInfos.ui_Address + 32 + (b_TimerNbr * 4) + (64 * b_ModulNbr)); - - /* Initialise the 82X54 Timer */ - outl((unsigned int) b_TimerMode, devpriv->s_BoardInfos.ui_Address + 16 + (b_TimerNbr * 4) + (64 * b_ModulNbr)); - - /* Write the reload value */ - outl(ul_ReloadValue, devpriv->s_BoardInfos.ui_Address + 0 + (b_TimerNbr * 4) + (64 * b_ModulNbr)); - /* BEGIN JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */ - } /* if (dw_Test == 1) */ - else { - /* Input timer clock selection is wrong */ - i_ReturnValue = -6; - } /* if (dw_Test == 1) */ - /* END JK 27.10.03 : Add the possibility to use a 40 Mhz quartz */ - } /* if ((b_HardwareGateLevel == 0) || (b_HardwareGateLevel == 1)) */ - else { - /* Selection from hardware gate level is wrong */ - DPRINTK("Selection from hardware gate level is wrong\n"); - i_ReturnValue = -9; - } /* if ((b_HardwareGateLevel == 0) || (b_HardwareGateLevel == 1)) */ - } /* if ((b_OutputLevel == 0) || (b_OutputLevel == 1)) */ - else { - /* Selection from output clock level is wrong */ - DPRINTK("Selection from output clock level is wrong\n"); - i_ReturnValue = -8; - } /* if ((b_OutputLevel == 0) || (b_OutputLevel == 1)) */ - } /* if ((b_InputClockLevel == 0) || (b_InputClockLevel == 1)) */ - else { - /* Selection from input clock level is wrong */ - DPRINTK("Selection from input clock level is wrong\n"); - i_ReturnValue = -7; - } /* if ((b_InputClockLevel == 0) || (b_InputClockLevel == 1)) */ - } else { - /* Input timer clock selection is wrong */ - DPRINTK("Input timer clock selection is wrong\n"); - i_ReturnValue = -6; - } - } else { - /* Input timer clock selection is wrong */ - DPRINTK("Input timer clock selection is wrong\n"); - i_ReturnValue = -6; - } - } /* if ((b_TimerMode >= 0) && (b_TimerMode <= 5)) */ - else { - /* Timer mode selection is wrong */ - DPRINTK("Timer mode selection is wrong\n"); - i_ReturnValue = -5; - } /* if ((b_TimerMode >= 0) && (b_TimerMode <= 5)) */ - } /* if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */ - else { - /* Timer selection wrong */ - DPRINTK("Timer selection wrong\n"); - i_ReturnValue = -3; - } /* if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */ - } else { - /* The module is not a TIMER module */ - DPRINTK("The module is not a TIMER module\n"); - i_ReturnValue = -4; - } - } else { - /* Module number error */ - DPRINTK("Module number error\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_EnableTimer | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_TimerNbr, | -| unsigned char_ b_InterruptEnable) -int i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device *dev,struct comedi_subdevice *s, - struct comedi_insn *insn,unsigned int *data) | -+----------------------------------------------------------------------------+ -| Task : Enable OR Disable the Timer (b_TimerNbr) from selected module | -| (b_ModulNbr). You must calling the | -| "i_APCI1710_InitTimer" function be for you call this | -| function. If you enable the timer interrupt, the timer | -| generate a interrupt after the timer value reach | -| the zero. See function "i_APCI1710_SetBoardIntRoutineX"| -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board | -| APCI-1710 | -| unsigned char_ b_ModulNbr : Selected module number | -| (0 to 3) | -| unsigned char_ b_TimerNbr : Timer number to enable | -| (0 to 2) | -| unsigned char_ b_InterruptEnable : Enable or disable the | -| timer interrupt. | -| APCI1710_ENABLE : | -| Enable the timer interrupt | -| APCI1710_DISABLE : | -| Disable the timer interrupt| -i_ReturnValue=insn->n; - b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec); - b_TimerNbr = (unsigned char) CR_CHAN(insn->chanspec); - b_ActionType = (unsigned char) data[0]; enable disable -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: Module selection wrong | -| -3: Timer selection wrong | -| -4: The module is not a TIMER module | -| -5: Timer not initialised see function | -| "i_APCI1710_InitTimer" | -| -6: Interrupt parameter is wrong | -| -7: Interrupt function not initialised. | -| See function "i_APCI1710_SetBoardIntRoutineX" | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_InsnWriteEnableDisableTimer(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned int dw_DummyRead; - unsigned char b_ModulNbr; - unsigned char b_TimerNbr; - unsigned char b_ActionType; - unsigned char b_InterruptEnable; - - i_ReturnValue = insn->n; - b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec); - b_TimerNbr = (unsigned char) CR_CHAN(insn->chanspec); - b_ActionType = (unsigned char) data[0]; /* enable disable */ - - /* Test the module number */ - if (b_ModulNbr < 4) { - /* Test if 82X54 timer */ - if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) { - /* Test the timer number */ - if (b_TimerNbr <= 2) { - /* Test if timer initialised */ - if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_82X54Init == 1) { - - switch (b_ActionType) { - case APCI1710_ENABLE: - b_InterruptEnable = (unsigned char) data[1]; - /* Test the interrupt selection */ - if ((b_InterruptEnable == APCI1710_ENABLE) || - (b_InterruptEnable == APCI1710_DISABLE)) { - if (b_InterruptEnable == APCI1710_ENABLE) { - - dw_DummyRead = inl(devpriv->s_BoardInfos.ui_Address + 12 + (b_TimerNbr * 4) + (64 * b_ModulNbr)); - - /* Enable the interrupt */ - devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord = devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord | 0x8; - - outl(devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord, devpriv->s_BoardInfos.ui_Address + 32 + (b_TimerNbr * 4) + (64 * b_ModulNbr)); - devpriv->tsk_Current = current; /* Save the current process task structure */ - - } /* if (b_InterruptEnable == APCI1710_ENABLE) */ - else { - /* Disable the interrupt */ - devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord = devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord & 0xF7; - - outl(devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord, devpriv->s_BoardInfos.ui_Address + 32 + (b_TimerNbr * 4) + (64 * b_ModulNbr)); - - /* Save the interrupt flag */ - devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.b_InterruptMask = devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.b_InterruptMask & (0xFF - (1 << b_TimerNbr)); - } /* if (b_InterruptEnable == APCI1710_ENABLE) */ - - /* Test if error occur */ - if (i_ReturnValue >= 0) { - /* Save the interrupt flag */ - devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.b_InterruptMask = devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.b_InterruptMask | ((1 & b_InterruptEnable) << b_TimerNbr); - - /* Enable the timer */ - outl(1, devpriv->s_BoardInfos.ui_Address + 44 + (b_TimerNbr * 4) + (64 * b_ModulNbr)); - } - } else { - /* Interrupt parameter is wrong */ - DPRINTK("\n"); - i_ReturnValue = -6; - } - break; - case APCI1710_DISABLE: - /* Test the interrupt flag */ - if (((devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.b_InterruptMask >> b_TimerNbr) & 1) == 1) { - /* Disable the interrupt */ - - devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr]. dw_ConfigurationWord = devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord & 0xF7; - - outl(devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].dw_ConfigurationWord, devpriv->s_BoardInfos.ui_Address + 32 + (b_TimerNbr * 4) + (64 * b_ModulNbr)); - - /* Save the interrupt flag */ - devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.b_InterruptMask = devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.b_InterruptMask & (0xFF - (1 << b_TimerNbr)); - } - - /* Disable the timer */ - outl(0, devpriv->s_BoardInfos.ui_Address + 44 + (b_TimerNbr * 4) + (64 * b_ModulNbr)); - break; - } /* Switch end */ - } else { - /* Timer not initialised see function */ - DPRINTK ("Timer not initialised see function\n"); - i_ReturnValue = -5; - } - } else { - /* Timer selection wrong */ - DPRINTK("Timer selection wrong\n"); - i_ReturnValue = -3; - } /* if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */ - } else { - /* The module is not a TIMER module */ - DPRINTK("The module is not a TIMER module\n"); - i_ReturnValue = -4; - } - } else { - /* Module number error */ - DPRINTK("Module number error\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_ReadAllTimerValue | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| PULONG_ pul_TimerValueArray) -int i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev,struct comedi_subdevice *s, - struct comedi_insn *insn,unsigned int *data) | -+----------------------------------------------------------------------------+ -| Task : Return the all timer values from selected timer | -| module (b_ModulNbr). | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board | -| APCI-1710 | -| unsigned char_ b_ModulNbr : Selected module number | -| (0 to 3) | -+----------------------------------------------------------------------------+ -| Output Parameters : PULONG_ pul_TimerValueArray : Timer value array. | -| Element 0 contain the timer 0 value. | -| Element 1 contain the timer 1 value. | -| Element 2 contain the timer 2 value. | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: Module selection wrong | -| -3: The module is not a TIMER module | -| -4: Timer 0 not initialised see function | -| "i_APCI1710_InitTimer" | -| -5: Timer 1 not initialised see function | -| "i_APCI1710_InitTimer" | -| -6: Timer 2 not initialised see function | -| "i_APCI1710_InitTimer" | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_InsnReadAllTimerValue(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned char b_ModulNbr, b_ReadType; - unsigned int *pul_TimerValueArray; - - b_ModulNbr = CR_AREF(insn->chanspec); - b_ReadType = CR_CHAN(insn->chanspec); - pul_TimerValueArray = (unsigned int *) data; - i_ReturnValue = insn->n; - - switch (b_ReadType) { - case APCI1710_TIMER_READINTERRUPT: - - data[0] = devpriv->s_InterruptParameters.s_FIFOInterruptParameters[devpriv->s_InterruptParameters.ui_Read].b_OldModuleMask; - data[1] = devpriv->s_InterruptParameters.s_FIFOInterruptParameters[devpriv->s_InterruptParameters.ui_Read].ul_OldInterruptMask; - data[2] = devpriv->s_InterruptParameters.s_FIFOInterruptParameters[devpriv->s_InterruptParameters.ui_Read].ul_OldCounterLatchValue; - - /* Increment the read FIFO */ - devpriv->s_InterruptParameters.ui_Read = (devpriv->s_InterruptParameters.ui_Read + 1) % APCI1710_SAVE_INTERRUPT; - - break; - - case APCI1710_TIMER_READALLTIMER: - /* Test the module number */ - if (b_ModulNbr < 4) { - /* Test if 82X54 timer */ - if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) { - /* Test if timer 0 iniutialised */ - if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[0].b_82X54Init == 1) { - /* Test if timer 1 iniutialised */ - if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[1].b_82X54Init == 1) { - /* Test if timer 2 iniutialised */ - if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[2].b_82X54Init == 1) { - /* Latch all counter */ - outl(0x17, devpriv->s_BoardInfos.ui_Address + 12 + (64 * b_ModulNbr)); - - /* Read the timer 0 value */ - pul_TimerValueArray[0] = inl(devpriv->s_BoardInfos.ui_Address + 0 + (64 * b_ModulNbr)); - - /* Read the timer 1 value */ - pul_TimerValueArray[1] = inl(devpriv->s_BoardInfos.ui_Address + 4 + (64 * b_ModulNbr)); - - /* Read the timer 2 value */ - pul_TimerValueArray[2] = inl(devpriv->s_BoardInfos.ui_Address + 8 + (64 * b_ModulNbr)); - } else { - /* Timer 2 not initialised see function */ - DPRINTK("Timer 2 not initialised see function\n"); - i_ReturnValue = -6; - } - } else { - /* Timer 1 not initialised see function */ - DPRINTK("Timer 1 not initialised see function\n"); - i_ReturnValue = -5; - } - } else { - /* Timer 0 not initialised see function */ - DPRINTK("Timer 0 not initialised see function\n"); - i_ReturnValue = -4; - } - } else { - /* The module is not a TIMER module */ - DPRINTK("The module is not a TIMER module\n"); - i_ReturnValue = -3; - } - } else { - /* Module number error */ - DPRINTK("Module number error\n"); - i_ReturnValue = -2; - } - - } /* End of Switch */ - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_ReadTimerValue | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_TimerNbr, | -| PULONG_ pul_TimerValue) | -+----------------------------------------------------------------------------+ -| Task : Return the timer value from selected digital timer | -| (b_TimerNbr) from selected timer module (b_ModulNbr). | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board | -| APCI-1710 | -| unsigned char_ b_ModulNbr : Selected module number | -| (0 to 3) | -| unsigned char_ b_TimerNbr : Timer number to read | -| (0 to 2) | -+----------------------------------------------------------------------------+ -| Output Parameters : PULONG_ pul_TimerValue : Timer value | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: Module selection wrong | -| -3: Timer selection wrong | -| -4: The module is not a TIMER module | -| -5: Timer not initialised see function | -| "i_APCI1710_InitTimer" | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_ReadTimerValue(struct comedi_device *dev, - unsigned char b_ModulNbr, - unsigned char b_TimerNbr, - unsigned int *pul_TimerValue) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - - /* Test the module number */ - if (b_ModulNbr < 4) { - /* Test if 82X54 timer */ - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModulNbr] & - 0xFFFF0000UL) == APCI1710_82X54_TIMER) { - /* Test the timer number */ - if (b_TimerNbr <= 2) { - /* Test if timer initialised */ - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_82X54ModuleInfo. - s_82X54TimerInfo[b_TimerNbr]. - b_82X54Init == 1) { - /* Latch the timer value */ - outl((2 << b_TimerNbr) | 0xD0, - devpriv->s_BoardInfos. - ui_Address + 12 + - (64 * b_ModulNbr)); - - /* Read the counter value */ - *pul_TimerValue = - inl(devpriv->s_BoardInfos. - ui_Address + (b_TimerNbr * 4) + - (64 * b_ModulNbr)); - } else { - /* Timer not initialised see function */ - DPRINTK("Timer not initialised see function\n"); - i_ReturnValue = -5; - } - } else { - /* Timer selection wrong */ - DPRINTK("Timer selection wrong\n"); - i_ReturnValue = -3; - } /* if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */ - } else { - /* The module is not a TIMER module */ - DPRINTK("The module is not a TIMER module\n"); - i_ReturnValue = -4; - } - } else { - /* Module number error */ - DPRINTK("Module number error\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - - /* - +----------------------------------------------------------------------------+ - | Function Name : _INT_ i_APCI1710_GetTimerOutputLevel | - | (unsigned char_ b_BoardHandle, | - | unsigned char_ b_ModulNbr, | - | unsigned char_ b_TimerNbr, | - | unsigned char *_ pb_OutputLevel) | - +----------------------------------------------------------------------------+ - | Task : Return the output signal level (pb_OutputLevel) from | - | selected digital timer (b_TimerNbr) from selected timer| - | module (b_ModulNbr). | - +----------------------------------------------------------------------------+ - | Input Parameters : unsigned char_ b_BoardHandle : Handle of board | - | APCI-1710 | - | unsigned char_ b_ModulNbr : Selected module number | - | (0 to 3) | - | unsigned char_ b_TimerNbr : Timer number to test | - | (0 to 2) | - +----------------------------------------------------------------------------+ - | Output Parameters : unsigned char *_ pb_OutputLevel : Output signal level | - | 0 : The output is low | - | 1 : The output is high | - +----------------------------------------------------------------------------+ - | Return Value : 0: No error | - | -1: The handle parameter of the board is wrong | - | -2: Module selection wrong | - | -3: Timer selection wrong | - | -4: The module is not a TIMER module | - | -5: Timer not initialised see function | - | "i_APCI1710_InitTimer" | - +----------------------------------------------------------------------------+ - */ -static int i_APCI1710_GetTimerOutputLevel(struct comedi_device *dev, - unsigned char b_ModulNbr, - unsigned char b_TimerNbr, - unsigned char *pb_OutputLevel) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned int dw_TimerStatus; - - /* Test the module number */ - if (b_ModulNbr < 4) { - /* Test if 82X54 timer */ - if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) { - /* Test the timer number */ - if (b_TimerNbr <= 2) { - /* Test if timer initialised */ - if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_82X54Init == 1) { - /* Latch the timer value */ - outl((2 << b_TimerNbr) | 0xE0, devpriv->s_BoardInfos.ui_Address + 12 + (64 * b_ModulNbr)); - - /* Read the timer status */ - dw_TimerStatus = inl(devpriv->s_BoardInfos.ui_Address + 16 + (b_TimerNbr * 4) + (64 * b_ModulNbr)); - - *pb_OutputLevel = (unsigned char) (((dw_TimerStatus >> 7) & 1) ^ devpriv-> s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_OutputLevel); - } else { - /* Timer not initialised see function */ - DPRINTK("Timer not initialised see function\n"); - i_ReturnValue = -5; - } - } else { - /* Timer selection wrong */ - DPRINTK("Timer selection wrong\n"); - i_ReturnValue = -3; - } /* if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */ - } else { - /* The module is not a TIMER module */ - DPRINTK("The module is not a TIMER module\n"); - i_ReturnValue = -4; - } - } else { - /* Module number error */ - DPRINTK("Module number error\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_GetTimerProgressStatus | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_TimerNbr, | -| unsigned char *_ pb_TimerStatus) | -+----------------------------------------------------------------------------+ -| Task : Return the progress status (pb_TimerStatus) from | -| selected digital timer (b_TimerNbr) from selected timer| -| module (b_ModulNbr). | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board | -| APCI-1710 | -| unsigned char_ b_ModulNbr : Selected module number | -| (0 to 3) | -| unsigned char_ b_TimerNbr : Timer number to test | -| (0 to 2) | -+----------------------------------------------------------------------------+ -| Output Parameters : unsigned char *_ pb_TimerStatus : Output signal level | -| 0 : Timer not in progress | -| 1 : Timer in progress | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: Module selection wrong | -| -3: Timer selection wrong | -| -4: The module is not a TIMER module | -| -5: Timer not initialised see function | -| "i_APCI1710_InitTimer" | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_GetTimerProgressStatus(struct comedi_device *dev, - unsigned char b_ModulNbr, - unsigned char b_TimerNbr, - unsigned char *pb_TimerStatus) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned int dw_TimerStatus; - - /* Test the module number */ - if (b_ModulNbr < 4) { - /* Test if 82X54 timer */ - - if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) { - /* Test the timer number */ - if (b_TimerNbr <= 2) { - /* Test if timer initialised */ - if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_82X54Init == 1) { - /* Latch the timer value */ - outl((2 << b_TimerNbr) | 0xE0, devpriv->s_BoardInfos.ui_Address + 12 + (64 * b_ModulNbr)); - - /* Read the timer status */ - dw_TimerStatus = inl(devpriv->s_BoardInfos.ui_Address + 16 + (b_TimerNbr * 4) + (64 * b_ModulNbr)); - - *pb_TimerStatus = (unsigned char) ((dw_TimerStatus) >> 8) & 1; - printk("ProgressStatus : %d", *pb_TimerStatus); - } else { - /* Timer not initialised see function */ - i_ReturnValue = -5; - } - } else { - /* Timer selection wrong */ - i_ReturnValue = -3; - } /* if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */ - } else { - /* The module is not a TIMER module */ - - i_ReturnValue = -4; - } - } else { - /* Module number error */ - - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_WriteTimerValue | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_TimerNbr, | -| ULONG_ ul_WriteValue) | -+----------------------------------------------------------------------------+ -| Task : Write the value (ul_WriteValue) into the selected timer| -| (b_TimerNbr) from selected timer module (b_ModulNbr). | -| The action in depend of the time mode selection. | -| See timer mode description table. | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board | -| APCI-1710 | -| unsigned char_ b_ModulNbr : Selected module number | -| (0 to 3) | -| unsigned char_ b_TimerNbr : Timer number to write | -| (0 to 2) | -| ULONG_ ul_WriteValue : Value to write | -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: Module selection wrong | -| -3: Timer selection wrong | -| -4: The module is not a TIMER module | -| -5: Timer not initialised see function | -| "i_APCI1710_InitTimer" | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_WriteTimerValue(struct comedi_device *dev, - unsigned char b_ModulNbr, - unsigned char b_TimerNbr, - unsigned int ul_WriteValue) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - - /* Test the module number */ - if (b_ModulNbr < 4) { - /* Test if 82X54 timer */ - if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == APCI1710_82X54_TIMER) { - /* Test the timer number */ - if (b_TimerNbr <= 2) { - /* Test if timer initialised */ - if (devpriv->s_ModuleInfo[b_ModulNbr].s_82X54ModuleInfo.s_82X54TimerInfo[b_TimerNbr].b_82X54Init == 1) { - /* Write the value */ - outl(ul_WriteValue, devpriv->s_BoardInfos.ui_Address + (b_TimerNbr * 4) + (64 * b_ModulNbr)); - } else { - /* Timer not initialised see function */ - DPRINTK("Timer not initialised see function\n"); - i_ReturnValue = -5; - } - } else { - /* Timer selection wrong */ - DPRINTK("Timer selection wrong\n"); - i_ReturnValue = -3; - } /* if ((b_TimerNbr >= 0) && (b_TimerNbr <= 2)) */ - } else { - /* The module is not a TIMER module */ - DPRINTK("The module is not a TIMER module\n"); - i_ReturnValue = -4; - } - } else { - /* Module number error */ - DPRINTK("Module number error\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name :INT i_APCI1710_InsnBitsTimer(struct comedi_device *dev, -struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) | -+----------------------------------------------------------------------------+ -| Task : Read write functions for Timer | -+----------------------------------------------------------------------------+ -| Input Parameters : -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_InsnBitsTimer(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - unsigned char b_BitsType; - int i_ReturnValue = 0; - b_BitsType = data[0]; - - printk("\n82X54"); - - switch (b_BitsType) { - case APCI1710_TIMER_READVALUE: - i_ReturnValue = i_APCI1710_ReadTimerValue(dev, - (unsigned char)CR_AREF(insn->chanspec), - (unsigned char)CR_CHAN(insn->chanspec), - (unsigned int *) &data[0]); - break; - - case APCI1710_TIMER_GETOUTPUTLEVEL: - i_ReturnValue = i_APCI1710_GetTimerOutputLevel(dev, - (unsigned char)CR_AREF(insn->chanspec), - (unsigned char)CR_CHAN(insn->chanspec), - (unsigned char *) &data[0]); - break; - - case APCI1710_TIMER_GETPROGRESSSTATUS: - i_ReturnValue = i_APCI1710_GetTimerProgressStatus(dev, - (unsigned char)CR_AREF(insn->chanspec), - (unsigned char)CR_CHAN(insn->chanspec), - (unsigned char *)&data[0]); - break; - - case APCI1710_TIMER_WRITEVALUE: - i_ReturnValue = i_APCI1710_WriteTimerValue(dev, - (unsigned char)CR_AREF(insn->chanspec), - (unsigned char)CR_CHAN(insn->chanspec), - (unsigned int)data[1]); - - break; - - default: - printk("Bits Config Parameter Wrong\n"); - i_ReturnValue = -1; - } - - if (i_ReturnValue >= 0) - i_ReturnValue = insn->n; - return i_ReturnValue; -} diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c deleted file mode 100644 index d91f586fdd26..000000000000 --- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c +++ /dev/null @@ -1,2050 +0,0 @@ -/** -@verbatim - -Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. - - ADDI-DATA GmbH - Dieselstrasse 3 - D-77833 Ottersweier - Tel: +19(0)7223/9493-0 - Fax: +49(0)7223/9493-92 - http://www.addi-data.com - info@addi-data.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. - -@endverbatim -*/ -/* - - +-----------------------------------------------------------------------+ - | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier | - +-----------------------------------------------------------------------+ - | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | - | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | - +-----------------------------------------------------------------------+ - | Project : API APCI1710 | Compiler : gcc | - | Module name : CHRONO.C | Version : 2.96 | - +-------------------------------+---------------------------------------+ - | Project manager: Eric Stolz | Date : 02/12/2002 | - +-----------------------------------------------------------------------+ - | Description : APCI-1710 chronometer module | - | | - | | - +-----------------------------------------------------------------------+ - | UPDATES | - +-----------------------------------------------------------------------+ - | Date | Author | Description of updates | - +----------+-----------+------------------------------------------------+ - | 29/06/98 | S. Weber | Digital input / output implementation | - |----------|-----------|------------------------------------------------| - | 08/05/00 | Guinot C | - 0400/0228 All Function in RING 0 | - | | | available | - +-----------------------------------------------------------------------+ - | | | | - | | | | - +-----------------------------------------------------------------------+ -*/ - -#define APCI1710_30MHZ 30 -#define APCI1710_33MHZ 33 -#define APCI1710_40MHZ 40 - -#define APCI1710_SINGLE 0 -#define APCI1710_CONTINUOUS 1 - -#define APCI1710_CHRONO_PROGRESS_STATUS 0 -#define APCI1710_CHRONO_READVALUE 1 -#define APCI1710_CHRONO_CONVERTVALUE 2 -#define APCI1710_CHRONO_READINTERRUPT 3 - -#define APCI1710_CHRONO_SET_CHANNELON 0 -#define APCI1710_CHRONO_SET_CHANNELOFF 1 -#define APCI1710_CHRONO_READ_CHANNEL 2 -#define APCI1710_CHRONO_READ_PORT 3 - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_InitChrono | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_ChronoMode, | -| unsigned char_ b_PCIInputClock, | -| unsigned char_ b_TimingUnit, | -| ULONG_ ul_TimingInterval, | -| PULONG_ pul_RealTimingInterval) - -+----------------------------------------------------------------------------+ -| Task : Configure the chronometer operating mode (b_ChronoMode)| -| from selected module (b_ModulNbr). | -| The ul_TimingInterval and ul_TimingUnit determine the | -| timing base for the measurement. | -| The pul_RealTimingInterval return the real timing | -| value. You must calling this function be for you call | -| any other function witch access of the chronometer. | -| | -| Witch this functionality from the APCI-1710 you have | -| the possibility to measure the timing witch two event. | -| | -| The mode 0 and 1 is appropriate for period measurement.| -| The mode 2 and 3 is appropriate for frequent | -| measurement. | -| The mode 4 to 7 is appropriate for measuring the timing| -| between two event. | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr CR_AREF(insn->chanspec) : Module number to configure | -| (0 to 3) | -| unsigned char_ b_ChronoMode data[0] : Chronometer action mode | -| (0 to 7). | -| unsigned char_ b_PCIInputClock data[1] : Selection from PCI bus clock| -| - APCI1710_30MHZ : | -| The PC have a PCI bus | -| clock from 30 MHz | -| - APCI1710_33MHZ : | -| The PC have a PCI bus | -| clock from 33 MHz | -| - APCI1710_40MHZ | -| The APCI-1710 have a | -| integrated 40Mhz | -| quartz. | -| unsigned char_ b_TimingUnit data[2] : Base timing unity (0 to 4) | -| 0 : ns | -| 1 : µs | -| 2 : ms | -| 3 : s | -| 4 : mn | -| ULONG_ ul_TimingInterval : data[3] Base timing value. | -+----------------------------------------------------------------------------+ -| Output Parameters : PULONG_ pul_RealTimingInterval : Real base timing | -| value. -| data[0] -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: Module selection wrong | -| -3: The module is not a Chronometer module | -| -4: Chronometer mode selection is wrong | -| -5: The selected PCI input clock is wrong | -| -6: Timing unity selection is wrong | -| -7: Base timing selection is wrong | -| -8: You can not used the 40MHz clock selection with | -| this board | -| -9: You can not used the 40MHz clock selection with | -| this CHRONOS version | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_InsnConfigInitChrono(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned int ul_TimerValue = 0; - unsigned int ul_TimingInterval = 0; - unsigned int ul_RealTimingInterval = 0; - double d_RealTimingInterval = 0; - unsigned int dw_ModeArray[8] = - { 0x01, 0x05, 0x00, 0x04, 0x02, 0x0E, 0x0A, 0x06 }; - unsigned char b_ModulNbr, b_ChronoMode, b_PCIInputClock, b_TimingUnit; - - b_ModulNbr = CR_AREF(insn->chanspec); - b_ChronoMode = (unsigned char) data[0]; - b_PCIInputClock = (unsigned char) data[1]; - b_TimingUnit = (unsigned char) data[2]; - ul_TimingInterval = (unsigned int) data[3]; - i_ReturnValue = insn->n; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /***********************/ - /* Test if chronometer */ - /***********************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModulNbr] & - 0xFFFF0000UL) == APCI1710_CHRONOMETER) { - /*****************************/ - /* Test the chronometer mode */ - /*****************************/ - - if (b_ChronoMode <= 7) { - /**************************/ - /* Test the PCI bus clock */ - /**************************/ - - if ((b_PCIInputClock == APCI1710_30MHZ) || - (b_PCIInputClock == APCI1710_33MHZ) || - (b_PCIInputClock == APCI1710_40MHZ)) { - /*************************/ - /* Test the timing unity */ - /*************************/ - - if (b_TimingUnit <= 4) { - /**********************************/ - /* Test the base timing selection */ - /**********************************/ - - if (((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 0) && (ul_TimingInterval >= 66) && (ul_TimingInterval <= 0xFFFFFFFFUL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 1) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 143165576UL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 2) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 143165UL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 3) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 143UL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 4) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 2UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 0) && (ul_TimingInterval >= 60) && (ul_TimingInterval <= 0xFFFFFFFFUL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 1) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 130150240UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 2) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 130150UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 3) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 130UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 4) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 2UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 0) && (ul_TimingInterval >= 50) && (ul_TimingInterval <= 0xFFFFFFFFUL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 1) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 107374182UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 2) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 107374UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 3) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 107UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 4) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 1UL))) { - /**************************/ - /* Test the board version */ - /**************************/ - - if (((b_PCIInputClock == APCI1710_40MHZ) && (devpriv->s_BoardInfos.b_BoardVersion > 0)) || (b_PCIInputClock != APCI1710_40MHZ)) { - /************************/ - /* Test the TOR version */ - /************************/ - - if (((b_PCIInputClock == APCI1710_40MHZ) && ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) >= 0x3131)) || (b_PCIInputClock != APCI1710_40MHZ)) { - fpu_begin - (); - - /****************************************/ - /* Calculate the timer 0 division fator */ - /****************************************/ - - switch (b_TimingUnit) { - /******/ - /* ns */ - /******/ - - case 0: - - /******************/ - /* Timer 0 factor */ - /******************/ - - ul_TimerValue - = - (unsigned int) - (ul_TimingInterval - * - (0.001 * b_PCIInputClock)); - - /*******************/ - /* Round the value */ - /*******************/ - - if ((double)((double)ul_TimingInterval * (0.001 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) { - ul_TimerValue - = - ul_TimerValue - + - 1; - } - - /*****************************/ - /* Calculate the real timing */ - /*****************************/ - - ul_RealTimingInterval - = - (unsigned int) - (ul_TimerValue - / - (0.001 * (double)b_PCIInputClock)); - d_RealTimingInterval - = - (double) - ul_TimerValue - / - (0.001 - * - (double) - b_PCIInputClock); - - if ((double)((double)ul_TimerValue / (0.001 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) { - ul_RealTimingInterval - = - ul_RealTimingInterval - + - 1; - } - - ul_TimingInterval - = - ul_TimingInterval - - - 1; - ul_TimerValue - = - ul_TimerValue - - - 2; - if (b_PCIInputClock != APCI1710_40MHZ) { - ul_TimerValue - = - (unsigned int) - ( - (double) - (ul_TimerValue) - * - 0.99392); - } - - break; - - /******/ - /* æs */ - /******/ - - case 1: - - /******************/ - /* Timer 0 factor */ - /******************/ - - ul_TimerValue - = - (unsigned int) - (ul_TimingInterval - * - (1.0 * b_PCIInputClock)); - - /*******************/ - /* Round the value */ - /*******************/ - - if ((double)((double)ul_TimingInterval * (1.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) { - ul_TimerValue - = - ul_TimerValue - + - 1; - } - - /*****************************/ - /* Calculate the real timing */ - /*****************************/ - - ul_RealTimingInterval - = - (unsigned int) - (ul_TimerValue - / - (1.0 * (double)b_PCIInputClock)); - d_RealTimingInterval - = - (double) - ul_TimerValue - / - ( - (double) - 1.0 - * - (double) - b_PCIInputClock); - - if ((double)((double)ul_TimerValue / (1.0 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) { - ul_RealTimingInterval - = - ul_RealTimingInterval - + - 1; - } - - ul_TimingInterval - = - ul_TimingInterval - - - 1; - ul_TimerValue - = - ul_TimerValue - - - 2; - if (b_PCIInputClock != APCI1710_40MHZ) { - ul_TimerValue - = - (unsigned int) - ( - (double) - (ul_TimerValue) - * - 0.99392); - } - - break; - - /******/ - /* ms */ - /******/ - - case 2: - - /******************/ - /* Timer 0 factor */ - /******************/ - - ul_TimerValue - = - ul_TimingInterval - * - (1000 - * - b_PCIInputClock); - - /*******************/ - /* Round the value */ - /*******************/ - - if ((double)((double)ul_TimingInterval * (1000.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) { - ul_TimerValue - = - ul_TimerValue - + - 1; - } - - /*****************************/ - /* Calculate the real timing */ - /*****************************/ - - ul_RealTimingInterval - = - (unsigned int) - (ul_TimerValue - / - (1000.0 * (double)b_PCIInputClock)); - d_RealTimingInterval - = - (double) - ul_TimerValue - / - (1000.0 - * - (double) - b_PCIInputClock); - - if ((double)((double)ul_TimerValue / (1000.0 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) { - ul_RealTimingInterval - = - ul_RealTimingInterval - + - 1; - } - - ul_TimingInterval - = - ul_TimingInterval - - - 1; - ul_TimerValue - = - ul_TimerValue - - - 2; - if (b_PCIInputClock != APCI1710_40MHZ) { - ul_TimerValue - = - (unsigned int) - ( - (double) - (ul_TimerValue) - * - 0.99392); - } - - break; - - /*****/ - /* s */ - /*****/ - - case 3: - - /******************/ - /* Timer 0 factor */ - /******************/ - - ul_TimerValue - = - (unsigned int) - (ul_TimingInterval - * - (1000000.0 - * - b_PCIInputClock)); - - /*******************/ - /* Round the value */ - /*******************/ - - if ((double)((double)ul_TimingInterval * (1000000.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) { - ul_TimerValue - = - ul_TimerValue - + - 1; - } - - /*****************************/ - /* Calculate the real timing */ - /*****************************/ - - ul_RealTimingInterval - = - (unsigned int) - (ul_TimerValue - / - (1000000.0 - * - (double) - b_PCIInputClock)); - d_RealTimingInterval - = - (double) - ul_TimerValue - / - (1000000.0 - * - (double) - b_PCIInputClock); - - if ((double)((double)ul_TimerValue / (1000000.0 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) { - ul_RealTimingInterval - = - ul_RealTimingInterval - + - 1; - } - - ul_TimingInterval - = - ul_TimingInterval - - - 1; - ul_TimerValue - = - ul_TimerValue - - - 2; - if (b_PCIInputClock != APCI1710_40MHZ) { - ul_TimerValue - = - (unsigned int) - ( - (double) - (ul_TimerValue) - * - 0.99392); - } - - break; - - /******/ - /* mn */ - /******/ - - case 4: - - /******************/ - /* Timer 0 factor */ - /******************/ - - ul_TimerValue - = - (unsigned int) - ( - (ul_TimingInterval - * - 60) - * - (1000000.0 - * - b_PCIInputClock)); - - /*******************/ - /* Round the value */ - /*******************/ - - if ((double)((double)(ul_TimingInterval * 60.0) * (1000000.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) { - ul_TimerValue - = - ul_TimerValue - + - 1; - } - - /*****************************/ - /* Calculate the real timing */ - /*****************************/ - - ul_RealTimingInterval - = - (unsigned int) - (ul_TimerValue - / - (1000000.0 - * - (double) - b_PCIInputClock)) - / - 60; - d_RealTimingInterval - = - ( - (double) - ul_TimerValue - / - (0.001 * (double)b_PCIInputClock)) / 60.0; - - if ((double)(((double)ul_TimerValue / (1000000.0 * (double)b_PCIInputClock)) / 60.0) >= (double)((double)ul_RealTimingInterval + 0.5)) { - ul_RealTimingInterval - = - ul_RealTimingInterval - + - 1; - } - - ul_TimingInterval - = - ul_TimingInterval - - - 1; - ul_TimerValue - = - ul_TimerValue - - - 2; - if (b_PCIInputClock != APCI1710_40MHZ) { - ul_TimerValue - = - (unsigned int) - ( - (double) - (ul_TimerValue) - * - 0.99392); - } - - break; - } - - fpu_end(); - - /****************************/ - /* Save the PCI input clock */ - /****************************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_ChronoModuleInfo. - b_PCIInputClock - = - b_PCIInputClock; - - /*************************/ - /* Save the timing unity */ - /*************************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_ChronoModuleInfo. - b_TimingUnit - = - b_TimingUnit; - - /************************/ - /* Save the base timing */ - /************************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_ChronoModuleInfo. - d_TimingInterval - = - d_RealTimingInterval; - - /****************************/ - /* Set the chronometer mode */ - /****************************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_ChronoModuleInfo. - dw_ConfigReg - = - dw_ModeArray - [b_ChronoMode]; - - /***********************/ - /* Test if 40 MHz used */ - /***********************/ - - if (b_PCIInputClock == APCI1710_40MHZ) { - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_ChronoModuleInfo. - dw_ConfigReg - = - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_ChronoModuleInfo. - dw_ConfigReg - | - 0x80; - } - - outl(devpriv->s_ModuleInfo[b_ModulNbr].s_ChronoModuleInfo.dw_ConfigReg, devpriv->s_BoardInfos.ui_Address + 16 + (64 * b_ModulNbr)); - - /***********************/ - /* Write timer 0 value */ - /***********************/ - - outl(ul_TimerValue, devpriv->s_BoardInfos.ui_Address + (64 * b_ModulNbr)); - - /*********************/ - /* Chronometer init. */ - /*********************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_ChronoModuleInfo. - b_ChronoInit - = - 1; - } else { - /***********************************************/ - /* TOR version error for 40MHz clock selection */ - /***********************************************/ - - DPRINTK("TOR version error for 40MHz clock selection\n"); - i_ReturnValue - = - -9; - } - } else { - /**************************************************************/ - /* You can not use the 40MHz clock selection with this board */ - /**************************************************************/ - - DPRINTK("You can not used the 40MHz clock selection with this board\n"); - i_ReturnValue = - -8; - } - } else { - /**********************************/ - /* Base timing selection is wrong */ - /**********************************/ - - DPRINTK("Base timing selection is wrong\n"); - i_ReturnValue = -7; - } - } /* if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) */ - else { - /***********************************/ - /* Timing unity selection is wrong */ - /***********************************/ - - DPRINTK("Timing unity selection is wrong\n"); - i_ReturnValue = -6; - } /* if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) */ - } /* if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ)) */ - else { - /*****************************************/ - /* The selected PCI input clock is wrong */ - /*****************************************/ - - DPRINTK("The selected PCI input clock is wrong\n"); - i_ReturnValue = -5; - } /* if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ)) */ - } /* if (b_ChronoMode >= 0 && b_ChronoMode <= 7) */ - else { - /***************************************/ - /* Chronometer mode selection is wrong */ - /***************************************/ - - DPRINTK("Chronometer mode selection is wrong\n"); - i_ReturnValue = -4; - } /* if (b_ChronoMode >= 0 && b_ChronoMode <= 7) */ - } else { - /******************************************/ - /* The module is not a Chronometer module */ - /******************************************/ - - DPRINTK("The module is not a Chronometer module\n"); - i_ReturnValue = -3; - } - } else { - /***********************/ - /* Module number error */ - /***********************/ - - DPRINTK("Module number error\n"); - i_ReturnValue = -2; - } - data[0] = ul_RealTimingInterval; - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_EnableChrono | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_CycleMode, | -| unsigned char_ b_InterruptEnable) -int i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device *dev, -struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) | -+----------------------------------------------------------------------------+ -| Task : Enable the chronometer from selected module | -| (b_ModulNbr). You must calling the | -| "i_APCI1710_InitChrono" function be for you call this | -| function. | -| If you enable the chronometer interrupt, the | -| chronometer generate a interrupt after the stop signal.| -| See function "i_APCI1710_SetBoardIntRoutineX" and the | -| Interrupt mask description chapter from this manual. | -| The b_CycleMode parameter determine if you will | -| measured a single or more cycle. - -| Disable the chronometer from selected module | -| (b_ModulNbr). If you disable the chronometer after a | -| start signal occur and you restart the chronometer | -| witch the " i_APCI1710_EnableChrono" function, if no | -| stop signal occur this start signal is ignored. -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr CR_AREF(chanspec) : Selected module number (0 to 3) | - data[0] ENABle/Disable chrono -| unsigned char_ b_CycleMode : Selected the chronometer | -| data[1] acquisition mode | -| unsigned char_ b_InterruptEnable : Enable or disable the | -| data[2] chronometer interrupt. | -| APCI1710_ENABLE: | -| Enable the chronometer | -| interrupt | -| APCI1710_DISABLE: | -| Disable the chronometer | -| interrupt | -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: Module selection wrong | -| -3: The module is not a Chronometer module | -| -4: Chronometer not initialised see function | -| "i_APCI1710_InitChrono" | -| -5: Chronometer acquisition mode cycle is wrong | -| -6: Interrupt parameter is wrong | -| -7: Interrupt function not initialised. | -| See function "i_APCI1710_SetBoardIntRoutineX" - -8: data[0] wrong input | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_InsnWriteEnableDisableChrono(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned char b_ModulNbr, b_CycleMode, b_InterruptEnable, b_Action; - b_ModulNbr = CR_AREF(insn->chanspec); - b_Action = (unsigned char) data[0]; - b_CycleMode = (unsigned char) data[1]; - b_InterruptEnable = (unsigned char) data[2]; - i_ReturnValue = insn->n; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /***********************/ - /* Test if chronometer */ - /***********************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModulNbr] & - 0xFFFF0000UL) == APCI1710_CHRONOMETER) { - /***********************************/ - /* Test if chronometer initialised */ - /***********************************/ - - if (devpriv->s_ModuleInfo[b_ModulNbr]. - s_ChronoModuleInfo.b_ChronoInit == 1) { - - switch (b_Action) { - - case APCI1710_ENABLE: - - /*********************************/ - /* Test the cycle mode parameter */ - /*********************************/ - - if ((b_CycleMode == APCI1710_SINGLE) - || (b_CycleMode == - APCI1710_CONTINUOUS)) { - /***************************/ - /* Test the interrupt flag */ - /***************************/ - - if ((b_InterruptEnable == - APCI1710_ENABLE) - || (b_InterruptEnable == - APCI1710_DISABLE)) - { - - /***************************/ - /* Save the interrupt flag */ - /***************************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_ChronoModuleInfo. - b_InterruptMask - = - b_InterruptEnable; - - /***********************/ - /* Save the cycle mode */ - /***********************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_ChronoModuleInfo. - b_CycleMode = - b_CycleMode; - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_ChronoModuleInfo. - dw_ConfigReg = - (devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_ChronoModuleInfo. - dw_ConfigReg & - 0x8F) | ((1 & - b_InterruptEnable) - << 5) | ((1 & - b_CycleMode) - << 6) | 0x10; - - /*****************************/ - /* Test if interrupt enabled */ - /*****************************/ - - if (b_InterruptEnable == - APCI1710_ENABLE) - { - /****************************/ - /* Clear the interrupt flag */ - /****************************/ - - outl(devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_ChronoModuleInfo. - dw_ConfigReg, - devpriv-> - s_BoardInfos. - ui_Address - + 32 + - (64 * b_ModulNbr)); - devpriv->tsk_Current = current; /* Save the current process task structure */ - } - - /***********************************/ - /* Enable or disable the interrupt */ - /* Enable the chronometer */ - /***********************************/ - - outl(devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_ChronoModuleInfo. - dw_ConfigReg, - devpriv-> - s_BoardInfos. - ui_Address + - 16 + - (64 * b_ModulNbr)); - - /*************************/ - /* Clear status register */ - /*************************/ - - outl(0, devpriv-> - s_BoardInfos. - ui_Address + - 36 + - (64 * b_ModulNbr)); - - } /* if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE)) */ - else { - /********************************/ - /* Interrupt parameter is wrong */ - /********************************/ - - DPRINTK("Interrupt parameter is wrong\n"); - i_ReturnValue = -6; - } /* if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE)) */ - } /* if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS)) */ - else { - /***********************************************/ - /* Chronometer acquisition mode cycle is wrong */ - /***********************************************/ - - DPRINTK("Chronometer acquisition mode cycle is wrong\n"); - i_ReturnValue = -5; - } /* if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS)) */ - break; - - case APCI1710_DISABLE: - - devpriv->s_ModuleInfo[b_ModulNbr]. - s_ChronoModuleInfo. - b_InterruptMask = 0; - - devpriv->s_ModuleInfo[b_ModulNbr]. - s_ChronoModuleInfo. - dw_ConfigReg = - devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_ChronoModuleInfo. - dw_ConfigReg & 0x2F; - - /***************************/ - /* Disable the interrupt */ - /* Disable the chronometer */ - /***************************/ - - outl(devpriv->s_ModuleInfo[b_ModulNbr]. - s_ChronoModuleInfo.dw_ConfigReg, - devpriv->s_BoardInfos. - ui_Address + 16 + - (64 * b_ModulNbr)); - - /***************************/ - /* Test if continuous mode */ - /***************************/ - - if (devpriv->s_ModuleInfo[b_ModulNbr]. - s_ChronoModuleInfo. - b_CycleMode == - APCI1710_CONTINUOUS) { - /*************************/ - /* Clear status register */ - /*************************/ - - outl(0, devpriv->s_BoardInfos. - ui_Address + 36 + - (64 * b_ModulNbr)); - } - break; - - default: - DPRINTK("Inputs wrong! Enable or Disable chrono\n"); - i_ReturnValue = -8; - } /* switch ENABLE/DISABLE */ - } else { - /*******************************/ - /* Chronometer not initialised */ - /*******************************/ - - DPRINTK("Chronometer not initialised\n"); - i_ReturnValue = -4; - } - } else { - /******************************************/ - /* The module is not a Chronometer module */ - /******************************************/ - - DPRINTK("The module is not a Chronometer module\n"); - i_ReturnValue = -3; - } - } else { - /***********************/ - /* Module number error */ - /***********************/ - - DPRINTK("Module number error\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_GetChronoProgressStatus | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char *_ pb_ChronoStatus) | -+----------------------------------------------------------------------------+ -| Task : Return the chronometer status (pb_ChronoStatus) from | -| selected chronometer module (b_ModulNbr). | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Selected module number (0 to 3) | -+----------------------------------------------------------------------------+ -| Output Parameters : PULONG_ pb_ChronoStatus : Return the chronometer | -| status. | -| 0 : Measurement not started.| -| No start signal occur. | -| 1 : Measurement started. | -| A start signal occur. | -| 2 : Measurement stopped. | -| A stop signal occur. | -| The measurement is | -| terminate. | -| 3: A overflow occur. You | -| must change the base | -| timing witch the | -| function | -| "i_APCI1710_InitChrono" | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: Module selection wrong | -| -3: The module is not a Chronometer module | -| -4: Chronometer not initialised see function | -| "i_APCI1710_InitChrono" | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_GetChronoProgressStatus(struct comedi_device *dev, - unsigned char b_ModulNbr, - unsigned char *pb_ChronoStatus) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned int dw_Status; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /***********************/ - /* Test if chronometer */ - /***********************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModulNbr] & - 0xFFFF0000UL) == APCI1710_CHRONOMETER) { - /***********************************/ - /* Test if chronometer initialised */ - /***********************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_ChronoModuleInfo.b_ChronoInit == 1) { - - dw_Status = inl(devpriv->s_BoardInfos. - ui_Address + 8 + (64 * b_ModulNbr)); - - /********************/ - /* Test if overflow */ - /********************/ - - if ((dw_Status & 8) == 8) { - /******************/ - /* Overflow occur */ - /******************/ - - *pb_ChronoStatus = 3; - } /* if ((dw_Status & 8) == 8) */ - else { - /*******************************/ - /* Test if measurement stopped */ - /*******************************/ - - if ((dw_Status & 2) == 2) { - /***********************/ - /* A stop signal occur */ - /***********************/ - - *pb_ChronoStatus = 2; - } /* if ((dw_Status & 2) == 2) */ - else { - /*******************************/ - /* Test if measurement started */ - /*******************************/ - - if ((dw_Status & 1) == 1) { - /************************/ - /* A start signal occur */ - /************************/ - - *pb_ChronoStatus = 1; - } /* if ((dw_Status & 1) == 1) */ - else { - /***************************/ - /* Measurement not started */ - /***************************/ - - *pb_ChronoStatus = 0; - } /* if ((dw_Status & 1) == 1) */ - } /* if ((dw_Status & 2) == 2) */ - } /* if ((dw_Status & 8) == 8) */ - } else { - /*******************************/ - /* Chronometer not initialised */ - /*******************************/ - DPRINTK("Chronometer not initialised\n"); - i_ReturnValue = -4; - } - } else { - /******************************************/ - /* The module is not a Chronometer module */ - /******************************************/ - DPRINTK("The module is not a Chronometer module\n"); - i_ReturnValue = -3; - } - } else { - /***********************/ - /* Module number error */ - /***********************/ - DPRINTK("Module number error\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_ReadChronoValue | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned int_ ui_TimeOut, | -| unsigned char *_ pb_ChronoStatus, | -| PULONG_ pul_ChronoValue) | -+----------------------------------------------------------------------------+ -| Task : Return the chronometer status (pb_ChronoStatus) and the| -| timing value (pul_ChronoValue) after a stop signal | -| occur from selected chronometer module (b_ModulNbr). | -| This function are only avaible if you have disabled | -| the interrupt functionality. See function | -| "i_APCI1710_EnableChrono" and the Interrupt mask | -| description chapter. | -| You can test the chronometer status witch the | -| "i_APCI1710_GetChronoProgressStatus" function. | -| | -| The returned value from pul_ChronoValue parameter is | -| not real measured timing. | -| You must used the "i_APCI1710_ConvertChronoValue" | -| function or make this operation for calculate the | -| timing: | -| | -| Timing = pul_ChronoValue * pul_RealTimingInterval. | -| | -| pul_RealTimingInterval is the returned parameter from | -| "i_APCI1710_InitChrono" function and the time unity is | -| the b_TimingUnit from "i_APCI1710_InitChrono" function| -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Selected module number (0 to 3) | -+----------------------------------------------------------------------------+ -| Output Parameters : PULONG_ pb_ChronoStatus : Return the chronometer | -| status. | -| 0 : Measurement not started.| -| No start signal occur. | -| 1 : Measurement started. | -| A start signal occur. | -| 2 : Measurement stopped. | -| A stop signal occur. | -| The measurement is | -| terminate. | -| 3: A overflow occur. You | -| must change the base | -| timing witch the | -| function | -| "i_APCI1710_InitChrono" | -| unsigned int * pul_ChronoValue : Chronometer timing value. | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: Module selection wrong | -| -3: The module is not a Chronometer module | -| -4: Chronometer not initialised see function | -| "i_APCI1710_InitChrono" | -| -5: Timeout parameter is wrong (0 to 65535) | -| -6: Interrupt routine installed. You can not read | -| directly the chronometer measured timing. | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_ReadChronoValue(struct comedi_device *dev, - unsigned char b_ModulNbr, - unsigned int ui_TimeOut, - unsigned char *pb_ChronoStatus, - unsigned int *pul_ChronoValue) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned int dw_Status; - unsigned int dw_TimeOut = 0; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /***********************/ - /* Test if chronometer */ - /***********************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModulNbr] & - 0xFFFF0000UL) == APCI1710_CHRONOMETER) { - /***********************************/ - /* Test if chronometer initialised */ - /***********************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_ChronoModuleInfo.b_ChronoInit == 1) { - /*****************************/ - /* Test the timout parameter */ - /*****************************/ - - if (ui_TimeOut <= 65535UL) { - - for (;;) { - /*******************/ - /* Read the status */ - /*******************/ - - dw_Status = - inl(devpriv-> - s_BoardInfos. - ui_Address + 8 + - (64 * b_ModulNbr)); - - /********************/ - /* Test if overflow */ - /********************/ - - if ((dw_Status & 8) == 8) { - /******************/ - /* Overflow occur */ - /******************/ - - *pb_ChronoStatus = 3; - - /***************************/ - /* Test if continuous mode */ - /***************************/ - - if (devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_ChronoModuleInfo. - b_CycleMode == - APCI1710_CONTINUOUS) - { - /*************************/ - /* Clear status register */ - /*************************/ - - outl(0, devpriv->s_BoardInfos.ui_Address + 36 + (64 * b_ModulNbr)); - } - - break; - } /* if ((dw_Status & 8) == 8) */ - else { - /*******************************/ - /* Test if measurement stopped */ - /*******************************/ - - if ((dw_Status & 2) == - 2) { - /***********************/ - /* A stop signal occur */ - /***********************/ - - *pb_ChronoStatus - = 2; - - /***************************/ - /* Test if continnous mode */ - /***************************/ - - if (devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_ChronoModuleInfo. - b_CycleMode - == - APCI1710_CONTINUOUS) - { - /*************************/ - /* Clear status register */ - /*************************/ - - outl(0, devpriv->s_BoardInfos.ui_Address + 36 + (64 * b_ModulNbr)); - } - break; - } /* if ((dw_Status & 2) == 2) */ - else { - /*******************************/ - /* Test if measurement started */ - /*******************************/ - - if ((dw_Status & 1) == 1) { - /************************/ - /* A start signal occur */ - /************************/ - - *pb_ChronoStatus - = - 1; - } /* if ((dw_Status & 1) == 1) */ - else { - /***************************/ - /* Measurement not started */ - /***************************/ - - *pb_ChronoStatus - = - 0; - } /* if ((dw_Status & 1) == 1) */ - } /* if ((dw_Status & 2) == 2) */ - } /* if ((dw_Status & 8) == 8) */ - - if (dw_TimeOut == ui_TimeOut) { - /*****************/ - /* Timeout occur */ - /*****************/ - - break; - } else { - /*************************/ - /* Increment the timeout */ - /*************************/ - - dw_TimeOut = - dw_TimeOut + 1; - mdelay(1000); - - } - } /* for (;;) */ - - /*****************************/ - /* Test if stop signal occur */ - /*****************************/ - - if (*pb_ChronoStatus == 2) { - /**********************************/ - /* Read the measured timing value */ - /**********************************/ - - *pul_ChronoValue = - inl(devpriv-> - s_BoardInfos. - ui_Address + 4 + - (64 * b_ModulNbr)); - - if (*pul_ChronoValue != 0) { - *pul_ChronoValue = - *pul_ChronoValue - - 1; - } - } else { - /*************************/ - /* Test if timeout occur */ - /*************************/ - - if ((*pb_ChronoStatus != 3) - && (dw_TimeOut == - ui_TimeOut) - && (ui_TimeOut != 0)) { - /*****************/ - /* Timeout occur */ - /*****************/ - - *pb_ChronoStatus = 4; - } - } - - } else { - /******************************/ - /* Timeout parameter is wrong */ - /******************************/ - DPRINTK("Timeout parameter is wrong\n"); - i_ReturnValue = -5; - } - } else { - /*******************************/ - /* Chronometer not initialised */ - /*******************************/ - DPRINTK("Chronometer not initialised\n"); - i_ReturnValue = -4; - } - } else { - /******************************************/ - /* The module is not a Chronometer module */ - /******************************************/ - DPRINTK("The module is not a Chronometer module\n"); - i_ReturnValue = -3; - } - } else { - /***********************/ - /* Module number error */ - /***********************/ - DPRINTK("Module number error\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_ConvertChronoValue | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| ULONG_ ul_ChronoValue, | -| PULONG_ pul_Hour, | -| unsigned char *_ pb_Minute, | -| unsigned char *_ pb_Second, | -| unsigned int *_ pui_MilliSecond, | -| unsigned int *_ pui_MicroSecond, | -| unsigned int *_ pui_NanoSecond) | -+----------------------------------------------------------------------------+ -| Task : Convert the chronometer measured timing | -| (ul_ChronoValue) in to h, mn, s, ms, µs, ns. | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Selected module number (0 to 3)| -| ULONG_ ul_ChronoValue : Measured chronometer timing | -| value. | -| See"i_APCI1710_ReadChronoValue"| -+----------------------------------------------------------------------------+ -| Output Parameters : PULONG_ pul_Hour : Chronometer timing hour | -| unsigned char *_ pb_Minute : Chronometer timing minute | -| unsigned char *_ pb_Second : Chronometer timing second | -| unsigned int *_ pui_MilliSecond : Chronometer timing mini | -| second | -| unsigned int *_ pui_MicroSecond : Chronometer timing micro | -| second | -| unsigned int *_ pui_NanoSecond : Chronometer timing nano | -| second | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: Module selection wrong | -| -3: The module is not a Chronometer module | -| -4: Chronometer not initialised see function | -| "i_APCI1710_InitChrono" | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_ConvertChronoValue(struct comedi_device *dev, - unsigned char b_ModulNbr, - unsigned int ul_ChronoValue, - unsigned int *pul_Hour, - unsigned char *pb_Minute, - unsigned char *pb_Second, - unsigned int *pui_MilliSecond, - unsigned int *pui_MicroSecond, - unsigned int *pui_NanoSecond) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - double d_Hour; - double d_Minute; - double d_Second; - double d_MilliSecond; - double d_MicroSecond; - double d_NanoSecond; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /***********************/ - /* Test if chronometer */ - /***********************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModulNbr] & - 0xFFFF0000UL) == APCI1710_CHRONOMETER) { - /***********************************/ - /* Test if chronometer initialised */ - /***********************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_ChronoModuleInfo.b_ChronoInit == 1) { - fpu_begin(); - - d_Hour = (double)ul_ChronoValue *(double) - devpriv->s_ModuleInfo[b_ModulNbr]. - s_ChronoModuleInfo.d_TimingInterval; - - switch (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_ChronoModuleInfo.b_TimingUnit) { - case 0: - d_Hour = d_Hour / (double)1000.0; - - case 1: - d_Hour = d_Hour / (double)1000.0; - - case 2: - d_Hour = d_Hour / (double)1000.0; - - case 3: - d_Hour = d_Hour / (double)60.0; - - case 4: - /**********************/ - /* Calculate the hour */ - /**********************/ - - d_Hour = d_Hour / (double)60.0; - *pul_Hour = (unsigned int) d_Hour; - - /************************/ - /* Calculate the minute */ - /************************/ - - d_Minute = d_Hour - *pul_Hour; - d_Minute = d_Minute * 60; - *pb_Minute = (unsigned char) d_Minute; - - /************************/ - /* Calculate the second */ - /************************/ - - d_Second = d_Minute - *pb_Minute; - d_Second = d_Second * 60; - *pb_Second = (unsigned char) d_Second; - - /*****************************/ - /* Calculate the mini second */ - /*****************************/ - - d_MilliSecond = d_Second - *pb_Second; - d_MilliSecond = d_MilliSecond * 1000; - *pui_MilliSecond = (unsigned int) d_MilliSecond; - - /******************************/ - /* Calculate the micro second */ - /******************************/ - - d_MicroSecond = - d_MilliSecond - - *pui_MilliSecond; - d_MicroSecond = d_MicroSecond * 1000; - *pui_MicroSecond = (unsigned int) d_MicroSecond; - - /******************************/ - /* Calculate the micro second */ - /******************************/ - - d_NanoSecond = - d_MicroSecond - - *pui_MicroSecond; - d_NanoSecond = d_NanoSecond * 1000; - *pui_NanoSecond = (unsigned int) d_NanoSecond; - break; - } - - fpu_end(); - } else { - /*******************************/ - /* Chronometer not initialised */ - /*******************************/ - DPRINTK("Chronometer not initialised\n"); - i_ReturnValue = -4; - } - } else { - /******************************************/ - /* The module is not a Chronometer module */ - /******************************************/ - DPRINTK("The module is not a Chronometer module\n"); - i_ReturnValue = -3; - } - } else { - /***********************/ - /* Module number error */ - /***********************/ - DPRINTK("Module number error\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name :INT i_APCI1710_InsnReadChrono(struct comedi_device *dev,struct comedi_subdevice *s, -struct comedi_insn *insn,unsigned int *data) | -+----------------------------------------------------------------------------+ -| Task : Read functions for Timer | -+----------------------------------------------------------------------------+ -| Input Parameters : -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_InsnReadChrono(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct addi_private *devpriv = dev->private; - unsigned char b_ReadType; - int i_ReturnValue = insn->n; - - b_ReadType = CR_CHAN(insn->chanspec); - - switch (b_ReadType) { - case APCI1710_CHRONO_PROGRESS_STATUS: - i_ReturnValue = i_APCI1710_GetChronoProgressStatus(dev, - (unsigned char) CR_AREF(insn->chanspec), (unsigned char *) &data[0]); - break; - - case APCI1710_CHRONO_READVALUE: - i_ReturnValue = i_APCI1710_ReadChronoValue(dev, - (unsigned char) CR_AREF(insn->chanspec), - (unsigned int) insn->unused[0], - (unsigned char *) &data[0], (unsigned int *) &data[1]); - break; - - case APCI1710_CHRONO_CONVERTVALUE: - i_ReturnValue = i_APCI1710_ConvertChronoValue(dev, - (unsigned char) CR_AREF(insn->chanspec), - (unsigned int) insn->unused[0], - (unsigned int *) &data[0], - (unsigned char *) &data[1], - (unsigned char *) &data[2], - (unsigned int *) &data[3], - (unsigned int *) &data[4], (unsigned int *) &data[5]); - break; - - case APCI1710_CHRONO_READINTERRUPT: - printk("In Chrono Read Interrupt\n"); - - data[0] = devpriv->s_InterruptParameters. - s_FIFOInterruptParameters[devpriv-> - s_InterruptParameters.ui_Read].b_OldModuleMask; - data[1] = devpriv->s_InterruptParameters. - s_FIFOInterruptParameters[devpriv-> - s_InterruptParameters.ui_Read].ul_OldInterruptMask; - data[2] = devpriv->s_InterruptParameters. - s_FIFOInterruptParameters[devpriv-> - s_InterruptParameters.ui_Read].ul_OldCounterLatchValue; - - /**************************/ - /* Increment the read FIFO */ - /***************************/ - - devpriv-> - s_InterruptParameters. - ui_Read = (devpriv-> - s_InterruptParameters. - ui_Read + 1) % APCI1710_SAVE_INTERRUPT; - break; - - default: - printk("ReadType Parameter wrong\n"); - } - - if (i_ReturnValue >= 0) - i_ReturnValue = insn->n; - return i_ReturnValue; - -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : int i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device *dev,struct comedi_subdevice *s, - struct comedi_insn *insn,unsigned int *data) | -+----------------------------------------------------------------------------+ -| Task : Sets the output witch has been passed with the | -| parameter b_Channel. Setting an output means setting an| -| output high. | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Selected module number (0 to 3)| -| unsigned char_ b_OutputChannel : Selection from digital output | -| CR_CHAN() channel (0 to 2) | -| 0 : Channel H | -| 1 : Channel A | -| 2 : Channel B | -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: Module selection wrong | -| -3: The module is not a Chronometer module | -| -4: The selected digital output is wrong | -| -5: Chronometer not initialised see function | -| "i_APCI1710_InitChrono" | -+----------------------------------------------------------------------------+ -*/ - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_SetChronoChlOff | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_OutputChannel) | -+----------------------------------------------------------------------------+ -| Task : Resets the output witch has been passed with the | -| parameter b_Channel. Resetting an output means setting | -| an output low. | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 - data[0] : Chl ON, Chl OFF , Chl Read , Port Read - -| unsigned char_ b_ModulNbr CR_AREF : Selected module number (0 to 3)| -| unsigned char_ b_OutputChannel CR_CHAN : Selection from digital output | -| channel (0 to 2) | -| 0 : Channel H | -| 1 : Channel A | -| 2 : Channel B | -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: Module selection wrong | -| -3: The module is not a Chronometer module | -| -4: The selected digital output is wrong | -| -5: Chronometer not initialised see function | -| "i_APCI1710_InitChrono" | -+----------------------------------------------------------------------------+ -*/ - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_ReadChronoChlValue | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_InputChannel, | -| unsigned char *_ pb_ChannelStatus) | -+----------------------------------------------------------------------------+ -| Task : Return the status from selected digital input | -| (b_InputChannel) from selected chronometer | -| module (b_ModulNbr). | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Selected module number (0 to 3)| -| unsigned char_ b_InputChannel : Selection from digital input | -| channel (0 to 2) | -| CR_CHAN() 0 : Channel E | -| 1 : Channel F | -| 2 : Channel G | -+----------------------------------------------------------------------------+ -| Output Parameters : unsigned char *_ pb_ChannelStatus : Digital input channel status.| -| data[0] 0 : Channel is not active | -| 1 : Channel is active | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: Module selection wrong | -| -3: The module is not a Chronometer module | -| -4: The selected digital input is wrong | -| -5: Chronometer not initialised see function | -| "i_APCI1710_InitChrono" | -+----------------------------------------------------------------------------+ -*/ - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_ReadChronoPortValue | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char *_ pb_PortValue) | -+----------------------------------------------------------------------------+ -| Task : Return the status from digital inputs port from | -| selected (b_ModulNbr) chronometer module. | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Selected module number (0 to 3)| -+----------------------------------------------------------------------------+ -| Output Parameters : unsigned char *_ pb_PortValue : Digital inputs port status. -| data[0] -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: Module selection wrong | -| -3: The module is not a Chronometer module | -| -4: Chronometer not initialised see function | -| "i_APCI1710_InitChrono" | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_InsnBitsChronoDigitalIO(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned char b_ModulNbr, b_OutputChannel, b_InputChannel, b_IOType; - unsigned int dw_Status; - unsigned char *pb_ChannelStatus; - unsigned char *pb_PortValue; - - b_ModulNbr = CR_AREF(insn->chanspec); - i_ReturnValue = insn->n; - b_IOType = (unsigned char) data[0]; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /***********************/ - /* Test if chronometer */ - /***********************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModulNbr] & - 0xFFFF0000UL) == APCI1710_CHRONOMETER) { - /***********************************/ - /* Test if chronometer initialised */ - /***********************************/ - - if (devpriv->s_ModuleInfo[b_ModulNbr]. - s_ChronoModuleInfo.b_ChronoInit == 1) { - /***********************************/ - /* Test the digital output channel */ - /***********************************/ - switch (b_IOType) { - - case APCI1710_CHRONO_SET_CHANNELOFF: - - b_OutputChannel = - (unsigned char) CR_CHAN(insn->chanspec); - if (b_OutputChannel <= 2) { - - outl(0, devpriv->s_BoardInfos. - ui_Address + 20 + - (b_OutputChannel * 4) + - (64 * b_ModulNbr)); - } /* if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2)) */ - else { - /****************************************/ - /* The selected digital output is wrong */ - /****************************************/ - - DPRINTK("The selected digital output is wrong\n"); - i_ReturnValue = -4; - - } /* if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2)) */ - - break; - - case APCI1710_CHRONO_SET_CHANNELON: - - b_OutputChannel = - (unsigned char) CR_CHAN(insn->chanspec); - if (b_OutputChannel <= 2) { - - outl(1, devpriv->s_BoardInfos. - ui_Address + 20 + - (b_OutputChannel * 4) + - (64 * b_ModulNbr)); - } /* if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2)) */ - else { - /****************************************/ - /* The selected digital output is wrong */ - /****************************************/ - - DPRINTK("The selected digital output is wrong\n"); - i_ReturnValue = -4; - - } /* if ((b_OutputChannel >= 0) && (b_OutputChannel <= 2)) */ - - break; - - case APCI1710_CHRONO_READ_CHANNEL: - /**********************************/ - /* Test the digital input channel */ - /**********************************/ - pb_ChannelStatus = (unsigned char *) &data[0]; - b_InputChannel = - (unsigned char) CR_CHAN(insn->chanspec); - - if (b_InputChannel <= 2) { - - dw_Status = - inl(devpriv-> - s_BoardInfos. - ui_Address + 12 + - (64 * b_ModulNbr)); - - *pb_ChannelStatus = - (unsigned char) (((dw_Status >> - b_InputChannel) - & 1) ^ 1); - } /* if ((b_InputChannel >= 0) && (b_InputChannel <= 2)) */ - else { - /***************************************/ - /* The selected digital input is wrong */ - /***************************************/ - - DPRINTK("The selected digital input is wrong\n"); - i_ReturnValue = -4; - } /* if ((b_InputChannel >= 0) && (b_InputChannel <= 2)) */ - - break; - - case APCI1710_CHRONO_READ_PORT: - - pb_PortValue = (unsigned char *) &data[0]; - - dw_Status = - inl(devpriv->s_BoardInfos. - ui_Address + 12 + - (64 * b_ModulNbr)); - - *pb_PortValue = - (unsigned char) ((dw_Status & 0x7) ^ 7); - break; - } - } else { - /*******************************/ - /* Chronometer not initialised */ - /*******************************/ - - DPRINTK("Chronometer not initialised\n"); - i_ReturnValue = -5; - } - } else { - /******************************************/ - /* The module is not a Chronometer module */ - /******************************************/ - - DPRINTK("The module is not a Chronometer module\n"); - i_ReturnValue = -3; - } - } else { - /***********************/ - /* Module number error */ - /***********************/ - - DPRINTK("Module number error\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c deleted file mode 100644 index 7d1883a0da28..000000000000 --- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c +++ /dev/null @@ -1,1037 +0,0 @@ -/** -@verbatim - -Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. - - ADDI-DATA GmbH - Dieselstrasse 3 - D-77833 Ottersweier - Tel: +19(0)7223/9493-0 - Fax: +49(0)7223/9493-92 - http://www.addi-data.com - info@addi-data.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. - -@endverbatim -*/ -/* - - +-----------------------------------------------------------------------+ - | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier | - +-----------------------------------------------------------------------+ - | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | - | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | - +-----------------------------------------------------------------------+ - | Project : API APCI1710 | Compiler : gcc | - | Module name : DIG_IO.C | Version : 2.96 | - +-------------------------------+---------------------------------------+ - | Project manager: Eric Stolz | Date : 02/12/2002 | - +-----------------------------------------------------------------------+ - | Description : APCI-1710 digital I/O module | - | | - | | - +-----------------------------------------------------------------------+ - | UPDATES | - +-----------------------------------------------------------------------+ - | Date | Author | Description of updates | - +----------+-----------+------------------------------------------------+ - | 16/06/98 | S. Weber | Digital input / output implementation | - |----------|-----------|------------------------------------------------| - | 08/05/00 | Guinot C | - 0400/0228 All Function in RING 0 | - | | | available | - +-----------------------------------------------------------------------+ - | | | | - | | | | - +-----------------------------------------------------------------------+ -*/ - -/* Digital Output ON or OFF */ -#define APCI1710_ON 1 -#define APCI1710_OFF 0 - -/* Digital I/O */ -#define APCI1710_INPUT 0 -#define APCI1710_OUTPUT 1 - -#define APCI1710_DIGIO_MEMORYONOFF 0x10 -#define APCI1710_DIGIO_INIT 0x11 - -/* -+----------------------------------------------------------------------------+ -| Function Name : int i_APCI1710_InsnConfigDigitalIO(struct comedi_device *dev, | -| struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data)| -+----------------------------------------------------------------------------+ -| Task : Configure the digital I/O operating mode from selected | -| module (b_ModulNbr). You must calling this function be| -| for you call any other function witch access of digital| -| I/O. | -+----------------------------------------------------------------------------+ -| Input Parameters : | -| unsigned char_ b_ModulNbr data[0]: Module number to | -| configure (0 to 3) | -| unsigned char_ b_ChannelAMode data[1] : Channel A mode selection | -| 0 : Channel used for digital | -| input | -| 1 : Channel used for digital | -| output | -| unsigned char_ b_ChannelBMode data[2] : Channel B mode selection | -| 0 : Channel used for digital | -| input | -| 1 : Channel used for digital | -| output | - data[0] memory on/off -Activates and deactivates the digital output memory. - After having | -| called up this function with memory on,the output you have previously| -| activated with the function are not reset -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: The module parameter is wrong | -| -3: The module is not a digital I/O module | -| -4: Bi-directional channel A configuration error | -| -5: Bi-directional channel B configuration error | -+----------------------------------------------------------------------------+ -*/ - -static int i_APCI1710_InsnConfigDigitalIO(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct addi_private *devpriv = dev->private; - unsigned char b_ModulNbr, b_ChannelAMode, b_ChannelBMode; - unsigned char b_MemoryOnOff, b_ConfigType; - int i_ReturnValue = 0; - unsigned int dw_WriteConfig = 0; - - b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec); - b_ConfigType = (unsigned char) data[0]; /* Memory or Init */ - b_ChannelAMode = (unsigned char) data[1]; - b_ChannelBMode = (unsigned char) data[2]; - b_MemoryOnOff = (unsigned char) data[1]; /* if memory operation */ - i_ReturnValue = insn->n; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr >= 4) { - DPRINTK("Module Number invalid\n"); - i_ReturnValue = -2; - return i_ReturnValue; - } - switch (b_ConfigType) { - case APCI1710_DIGIO_MEMORYONOFF: - - if (b_MemoryOnOff) /* If Memory ON */ - { - /****************************/ - /* Set the output memory on */ - /****************************/ - - devpriv->s_ModuleInfo[b_ModulNbr]. - s_DigitalIOInfo.b_OutputMemoryEnabled = 1; - - /***************************/ - /* Clear the output memory */ - /***************************/ - devpriv->s_ModuleInfo[b_ModulNbr]. - s_DigitalIOInfo.dw_OutputMemory = 0; - } else /* If memory off */ - { - /*****************************/ - /* Set the output memory off */ - /*****************************/ - - devpriv->s_ModuleInfo[b_ModulNbr]. - s_DigitalIOInfo.b_OutputMemoryEnabled = 0; - } - break; - - case APCI1710_DIGIO_INIT: - - /*******************************/ - /* Test if digital I/O counter */ - /*******************************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModulNbr] & - 0xFFFF0000UL) == APCI1710_DIGITAL_IO) { - - /***************************************************/ - /* Test the bi-directional channel A configuration */ - /***************************************************/ - - if ((b_ChannelAMode == 0) || (b_ChannelAMode == 1)) { - /***************************************************/ - /* Test the bi-directional channel B configuration */ - /***************************************************/ - - if ((b_ChannelBMode == 0) - || (b_ChannelBMode == 1)) { - devpriv->s_ModuleInfo[b_ModulNbr]. - s_DigitalIOInfo.b_DigitalInit = - 1; - - /********************************/ - /* Save channel A configuration */ - /********************************/ - - devpriv->s_ModuleInfo[b_ModulNbr]. - s_DigitalIOInfo. - b_ChannelAMode = b_ChannelAMode; - - /********************************/ - /* Save channel B configuration */ - /********************************/ - - devpriv->s_ModuleInfo[b_ModulNbr]. - s_DigitalIOInfo. - b_ChannelBMode = b_ChannelBMode; - - /*****************************************/ - /* Set the channel A and B configuration */ - /*****************************************/ - - dw_WriteConfig = - (unsigned int) (b_ChannelAMode | - (b_ChannelBMode * 2)); - - /***************************/ - /* Write the configuration */ - /***************************/ - - outl(dw_WriteConfig, - devpriv->s_BoardInfos. - ui_Address + 4 + - (64 * b_ModulNbr)); - - } else { - /************************************************/ - /* Bi-directional channel B configuration error */ - /************************************************/ - DPRINTK("Bi-directional channel B configuration error\n"); - i_ReturnValue = -5; - } - - } else { - /************************************************/ - /* Bi-directional channel A configuration error */ - /************************************************/ - DPRINTK("Bi-directional channel A configuration error\n"); - i_ReturnValue = -4; - - } - - } else { - /******************************************/ - /* The module is not a digital I/O module */ - /******************************************/ - DPRINTK("The module is not a digital I/O module\n"); - i_ReturnValue = -3; - } - } /* end of Switch */ - printk("Return Value %d\n", i_ReturnValue); - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| INPUT FUNCTIONS | -+----------------------------------------------------------------------------+ -*/ - -/* -+----------------------------------------------------------------------------+ - -|INT i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device *dev,comedi_subdevice -*s, struct comedi_insn *insn,unsigned int *data) - -+----------------------------------------------------------------------------+ -| Task : Read the status from selected digital I/O digital input| -| (b_InputChannel) | -+----------------------------------------------------------------------------| - - -| -| unsigned char_ b_ModulNbr CR_AREF(chanspec) : Selected module number | -| (0 to 3) | -| unsigned char_ b_InputChannel CR_CHAN(chanspec) : Selection from digital | -| input ( 0 to 6) | -| 0 : Channel C | -| 1 : Channel D | -| 2 : Channel E | -| 3 : Channel F | -| 4 : Channel G | -| 5 : Channel A | -| 6 : Channel B - - - | -+----------------------------------------------------------------------------+ -| Output Parameters : data[0] : Digital input channel | -| status | -| 0 : Channle is not active| -| 1 : Channle is active | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: The module parameter is wrong | -| -3: The module is not a digital I/O module | -| -4: The selected digital I/O digital input is wrong | -| -5: Digital I/O not initialised | -| -6: The digital channel A is used for output | -| -7: The digital channel B is used for output | -+----------------------------------------------------------------------------+ -*/ - -/* _INT_ i_APCI1710_ReadDigitalIOChlValue (unsigned char_ b_BoardHandle, */ -/* -* unsigned char_ b_ModulNbr, unsigned char_ b_InputChannel, -* unsigned char *_ pb_ChannelStatus) -*/ -static int i_APCI1710_InsnReadDigitalIOChlValue(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned int dw_StatusReg; - unsigned char b_ModulNbr, b_InputChannel; - unsigned char *pb_ChannelStatus; - b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec); - b_InputChannel = (unsigned char) CR_CHAN(insn->chanspec); - data[0] = 0; - pb_ChannelStatus = (unsigned char *) &data[0]; - i_ReturnValue = insn->n; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /*******************************/ - /* Test if digital I/O counter */ - /*******************************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModulNbr] & - 0xFFFF0000UL) == APCI1710_DIGITAL_IO) { - /******************************************/ - /* Test the digital imnput channel number */ - /******************************************/ - - if (b_InputChannel <= 6) { - /**********************************************/ - /* Test if the digital I/O module initialised */ - /**********************************************/ - - if (devpriv->s_ModuleInfo[b_ModulNbr]. - s_DigitalIOInfo.b_DigitalInit == 1) { - /**********************************/ - /* Test if channel A or channel B */ - /**********************************/ - - if (b_InputChannel > 4) { - /*********************/ - /* Test if channel A */ - /*********************/ - - if (b_InputChannel == 5) { - /***************************/ - /* Test the channel A mode */ - /***************************/ - - if (devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_DigitalIOInfo. - b_ChannelAMode - != 0) { - /********************************************/ - /* The digital channel A is used for output */ - /********************************************/ - - i_ReturnValue = - -6; - } - } /* if (b_InputChannel == 5) */ - else { - /***************************/ - /* Test the channel B mode */ - /***************************/ - - if (devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_DigitalIOInfo. - b_ChannelBMode - != 0) { - /********************************************/ - /* The digital channel B is used for output */ - /********************************************/ - - i_ReturnValue = - -7; - } - } /* if (b_InputChannel == 5) */ - } /* if (b_InputChannel > 4) */ - - /***********************/ - /* Test if error occur */ - /***********************/ - - if (i_ReturnValue >= 0) { - /**************************/ - /* Read all digital input */ - /**************************/ - -/* -* INPDW (ps_APCI1710Variable-> s_Board [b_BoardHandle]. -* s_BoardInfos. ui_Address + (64 * b_ModulNbr), &dw_StatusReg); -*/ - - dw_StatusReg = - inl(devpriv-> - s_BoardInfos. - ui_Address + - (64 * b_ModulNbr)); - - *pb_ChannelStatus = - (unsigned char) ((dw_StatusReg ^ - 0x1C) >> - b_InputChannel) & 1; - - } /* if (i_ReturnValue == 0) */ - } else { - /*******************************/ - /* Digital I/O not initialised */ - /*******************************/ - DPRINTK("Digital I/O not initialised\n"); - i_ReturnValue = -5; - } - } else { - /********************************/ - /* Selected digital input error */ - /********************************/ - DPRINTK("Selected digital input error\n"); - i_ReturnValue = -4; - } - } else { - /******************************************/ - /* The module is not a digital I/O module */ - /******************************************/ - DPRINTK("The module is not a digital I/O module\n"); - i_ReturnValue = -3; - } - } else { - /***********************/ - /* Module number error */ - /***********************/ - DPRINTK("Module number error\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| OUTPUT FUNCTIONS | -+----------------------------------------------------------------------------+ -*/ - -/* -+----------------------------------------------------------------------------+ -| Function Name : int i_APCI1710_InsnWriteDigitalIOChlOnOff(comedi_device -|*dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) - -+----------------------------------------------------------------------------+ -| Task : Sets or resets the output witch has been passed with the | -| parameter b_Channel. Setting an output means setting | -| an ouput high. | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr (aref ) : Selected module number (0 to 3)| -| unsigned char_ b_OutputChannel (CR_CHAN) : Selection from digital output | -| channel (0 to 2) | -| 0 : Channel H | -| 1 : Channel A | -| 2 : Channel B | -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: The module parameter is wrong | -| -3: The module is not a digital I/O module | -| -4: The selected digital output is wrong | -| -5: digital I/O not initialised see function | -| " i_APCI1710_InitDigitalIO" | -| -6: The digital channel A is used for input | -| -7: The digital channel B is used for input - -8: Digital Output Memory OFF. | -| Use previously the function | -| "i_APCI1710_SetDigitalIOMemoryOn". | -+----------------------------------------------------------------------------+ -*/ - -/* -* _INT_ i_APCI1710_SetDigitalIOChlOn (unsigned char_ b_BoardHandle, -* unsigned char_ b_ModulNbr, unsigned char_ b_OutputChannel) -*/ -static int i_APCI1710_InsnWriteDigitalIOChlOnOff(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned int dw_WriteValue = 0; - unsigned char b_ModulNbr, b_OutputChannel; - i_ReturnValue = insn->n; - b_ModulNbr = CR_AREF(insn->chanspec); - b_OutputChannel = CR_CHAN(insn->chanspec); - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /*******************************/ - /* Test if digital I/O counter */ - /*******************************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModulNbr] & - 0xFFFF0000UL) == APCI1710_DIGITAL_IO) { - /**********************************************/ - /* Test if the digital I/O module initialised */ - /**********************************************/ - - if (devpriv->s_ModuleInfo[b_ModulNbr]. - s_DigitalIOInfo.b_DigitalInit == 1) { - /******************************************/ - /* Test the digital output channel number */ - /******************************************/ - - switch (b_OutputChannel) { - /*************/ - /* Channel H */ - /*************/ - - case 0: - break; - - /*************/ - /* Channel A */ - /*************/ - - case 1: - if (devpriv->s_ModuleInfo[b_ModulNbr]. - s_DigitalIOInfo. - b_ChannelAMode != 1) { - /*******************************************/ - /* The digital channel A is used for input */ - /*******************************************/ - - i_ReturnValue = -6; - } - break; - - /*************/ - /* Channel B */ - /*************/ - - case 2: - if (devpriv->s_ModuleInfo[b_ModulNbr]. - s_DigitalIOInfo. - b_ChannelBMode != 1) { - /*******************************************/ - /* The digital channel B is used for input */ - /*******************************************/ - - i_ReturnValue = -7; - } - break; - - default: - /****************************************/ - /* The selected digital output is wrong */ - /****************************************/ - - i_ReturnValue = -4; - break; - } - - /***********************/ - /* Test if error occur */ - /***********************/ - - if (i_ReturnValue >= 0) { - - /*********************************/ - /* Test if set channel ON */ - /*********************************/ - if (data[0]) { - /*********************************/ - /* Test if output memory enabled */ - /*********************************/ - - if (devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_DigitalIOInfo. - b_OutputMemoryEnabled == - 1) { - dw_WriteValue = - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_DigitalIOInfo. - dw_OutputMemory - | (1 << - b_OutputChannel); - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_DigitalIOInfo. - dw_OutputMemory - = dw_WriteValue; - } else { - dw_WriteValue = - 1 << - b_OutputChannel; - } - } /* set channel off */ - else { - if (devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_DigitalIOInfo. - b_OutputMemoryEnabled == - 1) { - dw_WriteValue = - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_DigitalIOInfo. - dw_OutputMemory - & (0xFFFFFFFFUL - - - (1 << b_OutputChannel)); - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_DigitalIOInfo. - dw_OutputMemory - = dw_WriteValue; - } else { - /*****************************/ - /* Digital Output Memory OFF */ - /*****************************/ - /* +Use previously the function "i_APCI1710_SetDigitalIOMemoryOn" */ - i_ReturnValue = -8; - } - - } - /*******************/ - /* Write the value */ - /*******************/ - - /* OUTPDW (ps_APCI1710Variable-> - * s_Board [b_BoardHandle]. - * s_BoardInfos. ui_Address + (64 * b_ModulNbr), - * dw_WriteValue); - */ - - outl(dw_WriteValue, - devpriv->s_BoardInfos. - ui_Address + (64 * b_ModulNbr)); - } - } else { - /*******************************/ - /* Digital I/O not initialised */ - /*******************************/ - - i_ReturnValue = -5; - } - } else { - /******************************************/ - /* The module is not a digital I/O module */ - /******************************************/ - - i_ReturnValue = -3; - } - } else { - /***********************/ - /* Module number error */ - /***********************/ - - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ - -|INT i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device *dev,comedi_subdevice - *s, struct comedi_insn *insn,unsigned int *data) -+----------------------------------------------------------------------------+ -| Task : write: - Sets or resets one or several outputs from port. | -| Setting an output means setting an output high. | -| If you have switched OFF the digital output memory | -| (OFF), all the other output are set to "0". - -| read: - Read the status from digital input port | -| from selected digital I/O module (b_ModulNbr) -+----------------------------------------------------------------------------+ -| Input Parameters : - unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr CR_AREF(aref) : Selected module number (0 to 3)| -| unsigned char_ b_PortValue CR_CHAN(chanspec) : Output Value ( 0 To 7 ) -| data[0] read or write port -| data[1] if write then indicate ON or OFF - -| if read : data[1] will return port status. -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : - -| INPUT : - - 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: The module parameter is wrong | -| -3: The module is not a digital I/O module | -| -4: Digital I/O not initialised - - OUTPUT: 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: The module parameter is wrong | -| -3: The module is not a digital I/O module | -| -4: Output value wrong | -| -5: digital I/O not initialised see function | -| " i_APCI1710_InitDigitalIO" | -| -6: The digital channel A is used for input | -| -7: The digital channel B is used for input - -8: Digital Output Memory OFF. | -| Use previously the function | -| "i_APCI1710_SetDigitalIOMemoryOn". | -+----------------------------------------------------------------------------+ -*/ - -/* - * _INT_ i_APCI1710_SetDigitalIOPortOn (unsigned char_ - * b_BoardHandle, unsigned char_ b_ModulNbr, unsigned char_ - * b_PortValue) -*/ -static int i_APCI1710_InsnBitsDigitalIOPortOnOff(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned int dw_WriteValue = 0; - unsigned int dw_StatusReg; - unsigned char b_ModulNbr, b_PortValue; - unsigned char b_PortOperation, b_PortOnOFF; - - unsigned char *pb_PortValue; - - b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec); - b_PortOperation = (unsigned char) data[0]; /* Input or output */ - b_PortOnOFF = (unsigned char) data[1]; /* if output then On or Off */ - b_PortValue = (unsigned char) data[2]; /* if out put then Value */ - i_ReturnValue = insn->n; - pb_PortValue = (unsigned char *) &data[0]; -/* if input then read value */ - - switch (b_PortOperation) { - case APCI1710_INPUT: - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /*******************************/ - /* Test if digital I/O counter */ - /*******************************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModulNbr] & - 0xFFFF0000UL) == APCI1710_DIGITAL_IO) { - /**********************************************/ - /* Test if the digital I/O module initialised */ - /**********************************************/ - - if (devpriv->s_ModuleInfo[b_ModulNbr]. - s_DigitalIOInfo.b_DigitalInit == 1) { - /**************************/ - /* Read all digital input */ - /**************************/ - - /* INPDW (ps_APCI1710Variable-> - * s_Board [b_BoardHandle]. - * s_BoardInfos. - * ui_Address + (64 * b_ModulNbr), - * &dw_StatusReg); - */ - - dw_StatusReg = - inl(devpriv->s_BoardInfos. - ui_Address + (64 * b_ModulNbr)); - *pb_PortValue = - (unsigned char) (dw_StatusReg ^ 0x1C); - - } else { - /*******************************/ - /* Digital I/O not initialised */ - /*******************************/ - - i_ReturnValue = -4; - } - } else { - /******************************************/ - /* The module is not a digital I/O module */ - /******************************************/ - - i_ReturnValue = -3; - } - } else { - /***********************/ - /* Module number error */ - /***********************/ - - i_ReturnValue = -2; - } - - break; - - case APCI1710_OUTPUT: - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /*******************************/ - /* Test if digital I/O counter */ - /*******************************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModulNbr] & - 0xFFFF0000UL) == APCI1710_DIGITAL_IO) { - /**********************************************/ - /* Test if the digital I/O module initialised */ - /**********************************************/ - - if (devpriv->s_ModuleInfo[b_ModulNbr]. - s_DigitalIOInfo.b_DigitalInit == 1) { - /***********************/ - /* Test the port value */ - /***********************/ - - if (b_PortValue <= 7) { - /***********************************/ - /* Test the digital output channel */ - /***********************************/ - - /**************************/ - /* Test if channel A used */ - /**************************/ - - if ((b_PortValue & 2) == 2) { - if (devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_DigitalIOInfo. - b_ChannelAMode - != 1) { - /*******************************************/ - /* The digital channel A is used for input */ - /*******************************************/ - - i_ReturnValue = - -6; - } - } /* if ((b_PortValue & 2) == 2) */ - - /**************************/ - /* Test if channel B used */ - /**************************/ - - if ((b_PortValue & 4) == 4) { - if (devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_DigitalIOInfo. - b_ChannelBMode - != 1) { - /*******************************************/ - /* The digital channel B is used for input */ - /*******************************************/ - - i_ReturnValue = - -7; - } - } /* if ((b_PortValue & 4) == 4) */ - - /***********************/ - /* Test if error occur */ - /***********************/ - - if (i_ReturnValue >= 0) { - - /* if(data[1]) { */ - - switch (b_PortOnOFF) { - /*********************************/ - /* Test if set Port ON */ - /*********************************/ - - case APCI1710_ON: - - /*********************************/ - /* Test if output memory enabled */ - /*********************************/ - - if (devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_DigitalIOInfo. - b_OutputMemoryEnabled - == 1) { - dw_WriteValue - = - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_DigitalIOInfo. - dw_OutputMemory - | - b_PortValue; - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_DigitalIOInfo. - dw_OutputMemory - = - dw_WriteValue; - } else { - dw_WriteValue - = - b_PortValue; - } - break; - - /* If Set PORT OFF */ - case APCI1710_OFF: - - /*********************************/ - /* Test if output memory enabled */ - /*********************************/ - - if (devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_DigitalIOInfo. - b_OutputMemoryEnabled - == 1) { - dw_WriteValue - = - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_DigitalIOInfo. - dw_OutputMemory - & - (0xFFFFFFFFUL - - - b_PortValue); - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_DigitalIOInfo. - dw_OutputMemory - = - dw_WriteValue; - } else { - /*****************************/ - /* Digital Output Memory OFF */ - /*****************************/ - - i_ReturnValue - = - -8; - } - } /* switch */ - - /*******************/ - /* Write the value */ - /*******************/ - - /* OUTPDW (ps_APCI1710Variable-> - * s_Board [b_BoardHandle]. - * s_BoardInfos. - * ui_Address + (64 * b_ModulNbr), - * dw_WriteValue); */ - - outl(dw_WriteValue, - devpriv-> - s_BoardInfos. - ui_Address + - (64 * b_ModulNbr)); - } - } else { - /**********************/ - /* Output value wrong */ - /**********************/ - - i_ReturnValue = -4; - } - } else { - /*******************************/ - /* Digital I/O not initialised */ - /*******************************/ - - i_ReturnValue = -5; - } - } else { - /******************************************/ - /* The module is not a digital I/O module */ - /******************************************/ - - i_ReturnValue = -3; - } - } else { - /***********************/ - /* Module number error */ - /***********************/ - - i_ReturnValue = -2; - } - break; - - default: - i_ReturnValue = -9; - DPRINTK("NO INPUT/OUTPUT specified\n"); - } /* switch INPUT / OUTPUT */ - return i_ReturnValue; -} diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c deleted file mode 100644 index c9db601da2c9..000000000000 --- a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c +++ /dev/null @@ -1,5461 +0,0 @@ -/** -@verbatim - -Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. - - ADDI-DATA GmbH - Dieselstrasse 3 - D-77833 Ottersweier - Tel: +19(0)7223/9493-0 - Fax: +49(0)7223/9493-92 - http://www.addi-data.com - info@addi-data.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. - -@endverbatim -*/ -/* - +-----------------------------------------------------------------------+ - | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier | - +-----------------------------------------------------------------------+ - | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | - | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | - +-----------------------------------------------------------------------+ - | Project : API APCI1710 | Compiler : gcc | - | Module name : INC_CPT.C | Version : 2.96 | - +-------------------------------+---------------------------------------+ - | Project manager: Eric Stolz | Date : 02/12/2002 | - +-----------------------------------------------------------------------+ - | Description : APCI-1710 incremental counter module | - | | - | | - +-----------------------------------------------------------------------+ - | UPDATES | - +-----------------------------------------------------------------------+ - | Date | Author | Description of updates | - +----------+-----------+------------------------------------------------+ - | | | | - |----------|-----------|------------------------------------------------| - | 08/05/00 | Guinot C | - 0400/0228 All Function in RING 0 | - | | | available | - +-----------------------------------------------------------------------+ - | 29/06/01 | Guinot C. | - 1100/0231 -> 0701/0232 | - | | | See i_APCI1710_DisableFrequencyMeasurement | - +-----------------------------------------------------------------------+ -*/ - -#define APCI1710_16BIT_COUNTER 0x10 -#define APCI1710_32BIT_COUNTER 0x0 -#define APCI1710_QUADRUPLE_MODE 0x0 -#define APCI1710_DOUBLE_MODE 0x3 -#define APCI1710_SIMPLE_MODE 0xF -#define APCI1710_DIRECT_MODE 0x80 -#define APCI1710_HYSTERESIS_ON 0x60 -#define APCI1710_HYSTERESIS_OFF 0x0 -#define APCI1710_INCREMENT 0x60 -#define APCI1710_DECREMENT 0x0 -#define APCI1710_LATCH_COUNTER 0x1 -#define APCI1710_CLEAR_COUNTER 0x0 -#define APCI1710_LOW 0x0 -#define APCI1710_HIGH 0x1 - -/*********************/ -/* Version 0600-0229 */ -/*********************/ -#define APCI1710_HIGH_EDGE_CLEAR_COUNTER 0x0 -#define APCI1710_HIGH_EDGE_LATCH_COUNTER 0x1 -#define APCI1710_LOW_EDGE_CLEAR_COUNTER 0x2 -#define APCI1710_LOW_EDGE_LATCH_COUNTER 0x3 -#define APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER 0x4 -#define APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER 0x5 -#define APCI1710_SOURCE_0 0x0 -#define APCI1710_SOURCE_1 0x1 - -#define APCI1710_30MHZ 30 -#define APCI1710_33MHZ 33 -#define APCI1710_40MHZ 40 - -#define APCI1710_ENABLE_LATCH_INT 0x80 -#define APCI1710_DISABLE_LATCH_INT (~APCI1710_ENABLE_LATCH_INT) - -#define APCI1710_INDEX_LATCH_COUNTER 0x10 -#define APCI1710_INDEX_AUTO_MODE 0x8 -#define APCI1710_ENABLE_INDEX 0x4 -#define APCI1710_DISABLE_INDEX (~APCI1710_ENABLE_INDEX) -#define APCI1710_ENABLE_LATCH_AND_CLEAR 0x8 -#define APCI1710_DISABLE_LATCH_AND_CLEAR (~APCI1710_ENABLE_LATCH_AND_CLEAR) -#define APCI1710_SET_LOW_INDEX_LEVEL 0x4 -#define APCI1710_SET_HIGH_INDEX_LEVEL (~APCI1710_SET_LOW_INDEX_LEVEL) -#define APCI1710_INVERT_INDEX_RFERENCE 0x2 -#define APCI1710_DEFAULT_INDEX_RFERENCE (~APCI1710_INVERT_INDEX_RFERENCE) - -#define APCI1710_ENABLE_INDEX_INT 0x1 -#define APCI1710_DISABLE_INDEX_INT (~APCI1710_ENABLE_INDEX_INT) - -#define APCI1710_ENABLE_FREQUENCY 0x4 -#define APCI1710_DISABLE_FREQUENCY (~APCI1710_ENABLE_FREQUENCY) - -#define APCI1710_ENABLE_FREQUENCY_INT 0x8 -#define APCI1710_DISABLE_FREQUENCY_INT (~APCI1710_ENABLE_FREQUENCY_INT) - -#define APCI1710_ENABLE_40MHZ_FREQUENCY 0x40 -#define APCI1710_DISABLE_40MHZ_FREQUENCY (~APCI1710_ENABLE_40MHZ_FREQUENCY) - -#define APCI1710_ENABLE_40MHZ_FILTER 0x80 -#define APCI1710_DISABLE_40MHZ_FILTER (~APCI1710_ENABLE_40MHZ_FILTER) - -#define APCI1710_ENABLE_COMPARE_INT 0x2 -#define APCI1710_DISABLE_COMPARE_INT (~APCI1710_ENABLE_COMPARE_INT) - -#define APCI1710_ENABLE_INDEX_ACTION 0x20 -#define APCI1710_DISABLE_INDEX_ACTION (~APCI1710_ENABLE_INDEX_ACTION) -#define APCI1710_REFERENCE_HIGH 0x40 -#define APCI1710_REFERENCE_LOW (~APCI1710_REFERENCE_HIGH) - -#define APCI1710_TOR_GATE_LOW 0x40 -#define APCI1710_TOR_GATE_HIGH (~APCI1710_TOR_GATE_LOW) - -/* INSN CONFIG */ -#define APCI1710_INCCPT_INITCOUNTER 100 -#define APCI1710_INCCPT_COUNTERAUTOTEST 101 -#define APCI1710_INCCPT_INITINDEX 102 -#define APCI1710_INCCPT_INITREFERENCE 103 -#define APCI1710_INCCPT_INITEXTERNALSTROBE 104 -#define APCI1710_INCCPT_INITCOMPARELOGIC 105 -#define APCI1710_INCCPT_INITFREQUENCYMEASUREMENT 106 - -/* INSN READ */ -#define APCI1710_INCCPT_READLATCHREGISTERSTATUS 200 -#define APCI1710_INCCPT_READLATCHREGISTERVALUE 201 -#define APCI1710_INCCPT_READ16BITCOUNTERVALUE 202 -#define APCI1710_INCCPT_READ32BITCOUNTERVALUE 203 -#define APCI1710_INCCPT_GETINDEXSTATUS 204 -#define APCI1710_INCCPT_GETREFERENCESTATUS 205 -#define APCI1710_INCCPT_GETUASSTATUS 206 -#define APCI1710_INCCPT_GETCBSTATUS 207 -#define APCI1710_INCCPT_GET16BITCBSTATUS 208 -#define APCI1710_INCCPT_GETUDSTATUS 209 -#define APCI1710_INCCPT_GETINTERRUPTUDLATCHEDSTATUS 210 -#define APCI1710_INCCPT_READFREQUENCYMEASUREMENT 211 -#define APCI1710_INCCPT_READINTERRUPT 212 - -/* INSN BITS */ -#define APCI1710_INCCPT_CLEARCOUNTERVALUE 300 -#define APCI1710_INCCPT_CLEARALLCOUNTERVALUE 301 -#define APCI1710_INCCPT_SETINPUTFILTER 302 -#define APCI1710_INCCPT_LATCHCOUNTER 303 -#define APCI1710_INCCPT_SETINDEXANDREFERENCESOURCE 304 -#define APCI1710_INCCPT_SETDIGITALCHLON 305 -#define APCI1710_INCCPT_SETDIGITALCHLOFF 306 - -/* INSN WRITE */ -#define APCI1710_INCCPT_ENABLELATCHINTERRUPT 400 -#define APCI1710_INCCPT_DISABLELATCHINTERRUPT 401 -#define APCI1710_INCCPT_WRITE16BITCOUNTERVALUE 402 -#define APCI1710_INCCPT_WRITE32BITCOUNTERVALUE 403 -#define APCI1710_INCCPT_ENABLEINDEX 404 -#define APCI1710_INCCPT_DISABLEINDEX 405 -#define APCI1710_INCCPT_ENABLECOMPARELOGIC 406 -#define APCI1710_INCCPT_DISABLECOMPARELOGIC 407 -#define APCI1710_INCCPT_ENABLEFREQUENCYMEASUREMENT 408 -#define APCI1710_INCCPT_DISABLEFREQUENCYMEASUREMENT 409 - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_InitCounter | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_CounterRange, | -| unsigned char_ b_FirstCounterModus, | -| unsigned char_ b_FirstCounterOption, | -| unsigned char_ b_SecondCounterModus, | -| unsigned char_ b_SecondCounterOption) | -+----------------------------------------------------------------------------+ -| Task : Configure the counter operating mode from selected | -| module (b_ModulNbr). You must calling this function be | -| for you call any other function witch access of | -| counters. | -| | -| Counter range | -| ------------- | -| +------------------------------------+-----------------------------------+ | -| | Parameter Passed value | Description | | -| |------------------------------------+-----------------------------------| | -| |b_ModulNbr APCI1710_16BIT_COUNTER | The module is configured for | | -| | | two 16-bit counter. | | -| | | - b_FirstCounterModus and | | -| | | b_FirstCounterOption | | -| | | configure the first 16 bit | | -| | | counter. | | -| | | - b_SecondCounterModus and | | -| | | b_SecondCounterOption | | -| | | configure the second 16 bit | | -| | | counter. | | -| |------------------------------------+-----------------------------------| | -| |b_ModulNbr APCI1710_32BIT_COUNTER | The module is configured for one | | -| | | 32-bit counter. | | -| | | - b_FirstCounterModus and | | -| | | b_FirstCounterOption | | -| | | configure the 32 bit counter. | | -| | | - b_SecondCounterModus and | | -| | | b_SecondCounterOption | | -| | | are not used and have no | | -| | | importance. | | -| +------------------------------------+-----------------------------------+ | -| | -| Counter operating mode | -| ---------------------- | -| | -| +--------------------+-------------------------+-------------------------+ | -| | Parameter | Passed value | Description | | -| |--------------------+-------------------------+-------------------------| | -| |b_FirstCounterModus | APCI1710_QUADRUPLE_MODE | In the quadruple mode, | | -| | or | | the edge analysis | | -| |b_SecondCounterModus| | circuit generates a | | -| | | | counting pulse from | | -| | | | each edge of 2 signals | | -| | | | which are phase shifted | | -| | | | in relation to each | | -| | | | other. | | -| |--------------------+-------------------------+-------------------------| | -| |b_FirstCounterModus | APCI1710_DOUBLE_MODE | Functions in the same | | -| | or | | way as the quadruple | | -| |b_SecondCounterModus| | mode, except that only | | -| | | | two of the four edges | | -| | | | are analysed per | | -| | | | period | | -| |--------------------+-------------------------+-------------------------| | -| |b_FirstCounterModus | APCI1710_SIMPLE_MODE | Functions in the same | | -| | or | | way as the quadruple | | -| |b_SecondCounterModus| | mode, except that only | | -| | | | one of the four edges | | -| | | | is analysed per | | -| | | | period. | | -| |--------------------+-------------------------+-------------------------| | -| |b_FirstCounterModus | APCI1710_DIRECT_MODE | In the direct mode the | | -| | or | | both edge analysis | | -| |b_SecondCounterModus| | circuits are inactive. | | -| | | | The inputs A, B in the | | -| | | | 32-bit mode or A, B and | | -| | | | C, D in the 16-bit mode | | -| | | | represent, each, one | | -| | | | clock pulse gate circuit| | -| | | | There by frequency and | | -| | | | pulse duration | | -| | | | measurements can be | | -| | | | performed. | | -| +--------------------+-------------------------+-------------------------+ | -| | -| | -| IMPORTANT! | -| If you have configured the module for two 16-bit counter, a mixed | -| mode with a counter in quadruple/double/single mode | -| and the other counter in direct mode is not possible! | -| | -| | -| Counter operating option for quadruple/double/simple mode | -| --------------------------------------------------------- | -| | -| +----------------------+-------------------------+------------------------+| -| | Parameter | Passed value | Description || -| |----------------------+-------------------------+------------------------|| -| |b_FirstCounterOption | APCI1710_HYSTERESIS_ON | In both edge analysis || -| | or | | circuits is available || -| |b_SecondCounterOption | | one hysteresis circuit.|| -| | | | It suppresses each || -| | | | time the first counting|| -| | | | pulse after a change || -| | | | of rotation. || -| |----------------------+-------------------------+------------------------|| -| |b_FirstCounterOption | APCI1710_HYSTERESIS_OFF | The first counting || -| | or | | pulse is not suppress || -| |b_SecondCounterOption | | after a change of || -| | | | rotation. || -| +----------------------+-------------------------+------------------------+| -| | -| | -| IMPORTANT! | -| This option are only avaible if you have selected the direct mode. | -| | -| | -| Counter operating option for direct mode | -| ---------------------------------------- | -| | -| +----------------------+--------------------+----------------------------+ | -| | Parameter | Passed value | Description | | -| |----------------------+--------------------+----------------------------| | -| |b_FirstCounterOption | APCI1710_INCREMENT | The counter increment for | | -| | or | | each counting pulse | | -| |b_SecondCounterOption | | | | -| |----------------------+--------------------+----------------------------| | -| |b_FirstCounterOption | APCI1710_DECREMENT | The counter decrement for | | -| | or | | each counting pulse | | -| |b_SecondCounterOption | | | | -| +----------------------+--------------------+----------------------------+ | -| | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710| -| unsigned char_ b_ModulNbr : Module number to | -| configure (0 to 3) | -| unsigned char_ b_CounterRange : Selection form counter | -| range. | -| unsigned char_ b_FirstCounterModus : First counter operating | -| mode. | -| unsigned char_ b_FirstCounterOption : First counter option. | -| unsigned char_ b_SecondCounterModus : Second counter operating | -| mode. | -| unsigned char_ b_SecondCounterOption : Second counter option. | -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: The module is not a counter module | -| -3: The selected counter range is wrong. | -| -4: The selected first counter operating mode is wrong. | -| -5: The selected first counter operating option is wrong| -| -6: The selected second counter operating mode is wrong.| -| -7: The selected second counter operating option is | -| wrong. | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_InitCounter(struct comedi_device *dev, - unsigned char b_ModulNbr, - unsigned char b_CounterRange, - unsigned char b_FirstCounterModus, - unsigned char b_FirstCounterOption, - unsigned char b_SecondCounterModus, - unsigned char b_SecondCounterOption) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - - /*******************************/ - /* Test if incremental counter */ - /*******************************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF0000UL) == - APCI1710_INCREMENTAL_COUNTER) { - /**************************/ - /* Test the counter range */ - /**************************/ - - if (b_CounterRange == APCI1710_16BIT_COUNTER - || b_CounterRange == APCI1710_32BIT_COUNTER) { - /********************************/ - /* Test the first counter modus */ - /********************************/ - - if (b_FirstCounterModus == APCI1710_QUADRUPLE_MODE || - b_FirstCounterModus == APCI1710_DOUBLE_MODE || - b_FirstCounterModus == APCI1710_SIMPLE_MODE || - b_FirstCounterModus == APCI1710_DIRECT_MODE) { - /*********************************/ - /* Test the first counter option */ - /*********************************/ - - if ((b_FirstCounterModus == APCI1710_DIRECT_MODE - && (b_FirstCounterOption == - APCI1710_INCREMENT - || b_FirstCounterOption - == APCI1710_DECREMENT)) - || (b_FirstCounterModus != - APCI1710_DIRECT_MODE - && (b_FirstCounterOption == - APCI1710_HYSTERESIS_ON - || b_FirstCounterOption - == - APCI1710_HYSTERESIS_OFF))) - { - /**************************/ - /* Test if 16-bit counter */ - /**************************/ - - if (b_CounterRange == - APCI1710_16BIT_COUNTER) { - /*********************************/ - /* Test the second counter modus */ - /*********************************/ - - if ((b_FirstCounterModus != - APCI1710_DIRECT_MODE - && - (b_SecondCounterModus - == - APCI1710_QUADRUPLE_MODE - || - b_SecondCounterModus - == - APCI1710_DOUBLE_MODE - || - b_SecondCounterModus - == - APCI1710_SIMPLE_MODE)) - || (b_FirstCounterModus - == - APCI1710_DIRECT_MODE - && - b_SecondCounterModus - == - APCI1710_DIRECT_MODE)) - { - /**********************************/ - /* Test the second counter option */ - /**********************************/ - - if ((b_SecondCounterModus == APCI1710_DIRECT_MODE && (b_SecondCounterOption == APCI1710_INCREMENT || b_SecondCounterOption == APCI1710_DECREMENT)) || (b_SecondCounterModus != APCI1710_DIRECT_MODE && (b_SecondCounterOption == APCI1710_HYSTERESIS_ON || b_SecondCounterOption == APCI1710_HYSTERESIS_OFF))) { - i_ReturnValue = - 0; - } else { - /*********************************************************/ - /* The selected second counter operating option is wrong */ - /*********************************************************/ - - DPRINTK("The selected second counter operating option is wrong\n"); - i_ReturnValue = - -7; - } - } else { - /*******************************************************/ - /* The selected second counter operating mode is wrong */ - /*******************************************************/ - - DPRINTK("The selected second counter operating mode is wrong\n"); - i_ReturnValue = -6; - } - } - } else { - /********************************************************/ - /* The selected first counter operating option is wrong */ - /********************************************************/ - - DPRINTK("The selected first counter operating option is wrong\n"); - i_ReturnValue = -5; - } - } else { - /******************************************************/ - /* The selected first counter operating mode is wrong */ - /******************************************************/ - DPRINTK("The selected first counter operating mode is wrong\n"); - i_ReturnValue = -4; - } - } else { - /***************************************/ - /* The selected counter range is wrong */ - /***************************************/ - - DPRINTK("The selected counter range is wrong\n"); - i_ReturnValue = -3; - } - - /*************************/ - /* Test if a error occur */ - /*************************/ - - if (i_ReturnValue == 0) { - /**************************/ - /* Test if 16-Bit counter */ - /**************************/ - - if (b_CounterRange == APCI1710_32BIT_COUNTER) { - devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister1 = b_CounterRange | - b_FirstCounterModus | - b_FirstCounterOption; - } else { - devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister1 = b_CounterRange | - (b_FirstCounterModus & 0x5) | - (b_FirstCounterOption & 0x20) | - (b_SecondCounterModus & 0xA) | - (b_SecondCounterOption & 0x40); - - /***********************/ - /* Test if direct mode */ - /***********************/ - - if (b_FirstCounterModus == APCI1710_DIRECT_MODE) { - devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister1 = devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister1 | - APCI1710_DIRECT_MODE; - } - } - - /***************************/ - /* Write the configuration */ - /***************************/ - - outl(devpriv->s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - dw_ModeRegister1_2_3_4, - devpriv->s_BoardInfos. - ui_Address + 20 + (64 * b_ModulNbr)); - - devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_InitFlag.b_CounterInit = 1; - } - } else { - /**************************************/ - /* The module is not a counter module */ - /**************************************/ - - DPRINTK("The module is not a counter module\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_CounterAutoTest | -| (unsigned char_ b_BoardHandle, | -| unsigned char *_ pb_TestStatus) | -+----------------------------------------------------------------------------+ -| Task : A test mode is intended for testing the component and | -| the connected periphery. All the 8-bit counter chains | -| are operated internally as down counters. | -| Independently from the external signals, | -| all the four 8-bit counter chains are decremented in | -| parallel by each negative clock pulse edge of CLKX. | -| | -| Counter auto test conclusion | -| ---------------------------- | -| +-----------------+-----------------------------+ | -| | pb_TestStatus | Error description | | -| | mask | | | -| |-----------------+-----------------------------| | -| | 0000 | No error detected | | -| |-----------------|-----------------------------| | -| | 0001 | Error detected of counter 0 | | -| |-----------------|-----------------------------| | -| | 0010 | Error detected of counter 1 | | -| |-----------------|-----------------------------| | -| | 0100 | Error detected of counter 2 | | -| |-----------------|-----------------------------| | -| | 1000 | Error detected of counter 3 | | -| +-----------------+-----------------------------+ | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | | -+----------------------------------------------------------------------------+ -| Output Parameters : unsigned char *_ pb_TestStatus : Auto test conclusion. See table| -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: No counter module found | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_CounterAutoTest(struct comedi_device *dev, - unsigned char *pb_TestStatus) -{ - struct addi_private *devpriv = dev->private; - unsigned char b_ModulCpt = 0; - int i_ReturnValue = 0; - unsigned int dw_LathchValue; - - *pb_TestStatus = 0; - - /********************************/ - /* Test if counter module found */ - /********************************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[0] & 0xFFFF0000UL) == - APCI1710_INCREMENTAL_COUNTER - || (devpriv->s_BoardInfos. - dw_MolduleConfiguration[1] & 0xFFFF0000UL) == - APCI1710_INCREMENTAL_COUNTER - || (devpriv->s_BoardInfos. - dw_MolduleConfiguration[2] & 0xFFFF0000UL) == - APCI1710_INCREMENTAL_COUNTER - || (devpriv->s_BoardInfos. - dw_MolduleConfiguration[3] & 0xFFFF0000UL) == - APCI1710_INCREMENTAL_COUNTER) { - for (b_ModulCpt = 0; b_ModulCpt < 4; b_ModulCpt++) { - /*******************************/ - /* Test if incremental counter */ - /*******************************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModulCpt] & - 0xFFFF0000UL) == - APCI1710_INCREMENTAL_COUNTER) { - /******************/ - /* Start the test */ - /******************/ - - outl(3, devpriv->s_BoardInfos. - ui_Address + 16 + (64 * b_ModulCpt)); - - /*********************/ - /* Tatch the counter */ - /*********************/ - - outl(1, devpriv->s_BoardInfos. - ui_Address + (64 * b_ModulCpt)); - - /************************/ - /* Read the latch value */ - /************************/ - - dw_LathchValue = inl(devpriv->s_BoardInfos. - ui_Address + 4 + (64 * b_ModulCpt)); - - if ((dw_LathchValue & 0xFF) != - ((dw_LathchValue >> 8) & 0xFF) - && (dw_LathchValue & 0xFF) != - ((dw_LathchValue >> 16) & 0xFF) - && (dw_LathchValue & 0xFF) != - ((dw_LathchValue >> 24) & 0xFF)) { - *pb_TestStatus = - *pb_TestStatus | (1 << - b_ModulCpt); - } - - /*****************/ - /* Stop the test */ - /*****************/ - - outl(0, devpriv->s_BoardInfos. - ui_Address + 16 + (64 * b_ModulCpt)); - } - } - } else { - /***************************/ - /* No counter module found */ - /***************************/ - - DPRINTK("No counter module found\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_InitIndex (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_ReferenceAction, | -| unsigned char_ b_IndexOperation, | -| unsigned char_ b_AutoMode, | -| unsigned char_ b_InterruptEnable) | -+----------------------------------------------------------------------------+ -| Task : Initialise the index corresponding to the selected | -| module (b_ModulNbr). If a INDEX flag occur, you have | -| the possibility to clear the 32-Bit counter or to latch| -| the current 32-Bit value in to the first latch | -| register. The b_IndexOperation parameter give the | -| possibility to choice the INDEX action. | -| If you have enabled the automatic mode, each INDEX | -| action is cleared automatically, else you must read | -| the index status ("i_APCI1710_ReadIndexStatus") | -| after each INDEX action. | -| | -| | -| Index action | -| ------------ | -| | -| +------------------------+------------------------------------+ | -| | b_IndexOperation | Operation | | -| |------------------------+------------------------------------| | -| |APCI1710_LATCH_COUNTER | After a index signal, the counter | | -| | | value (32-Bit) is latched in to | | -| | | the first latch register | | -| |------------------------|------------------------------------| | -| |APCI1710_CLEAR_COUNTER | After a index signal, the counter | | -| | | value is cleared (32-Bit) | | -| +------------------------+------------------------------------+ | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Module number to configure | -| (0 to 3) | -| unsigned char_ b_ReferenceAction : Determine if the reference | -| must set or no for the | -| acceptance from index | -| APCI1710_ENABLE : | -| Reference must be set for | -| accepted the index | -| APCI1710_DISABLE : | -| Reference have not | -| importance | -| unsigned char_ b_IndexOperation : Index operating mode. | -| See table. | -| unsigned char_ b_AutoMode : Enable or disable the | -| automatic index reset. | -| APCI1710_ENABLE : | -| Enable the automatic mode | -| APCI1710_DISABLE : | -| Disable the automatic mode | -| unsigned char_ b_InterruptEnable : Enable or disable the | -| interrupt. | -| APCI1710_ENABLE : | -| Enable the interrupt | -| APCI1710_DISABLE : | -| Disable the interrupt | -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: No counter module found | -| -3: Counter not initialised see function | -| "i_APCI1710_InitCounter" | -| -4 The reference action parameter is wrong | -| -5: The index operating mode parameter is wrong | -| -6: The auto mode parameter is wrong | -| -7: Interrupt parameter is wrong | -| -8: Interrupt function not initialised. | -| See function "i_APCI1710_SetBoardIntRoutineX" | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_InitIndex(struct comedi_device *dev, - unsigned char b_ModulNbr, - unsigned char b_ReferenceAction, - unsigned char b_IndexOperation, - unsigned char b_AutoMode, - unsigned char b_InterruptEnable) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /*******************************/ - /* Test if counter initialised */ - /*******************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { - /********************************/ - /* Test the reference parameter */ - /********************************/ - - if (b_ReferenceAction == APCI1710_ENABLE || - b_ReferenceAction == APCI1710_DISABLE) { - /****************************/ - /* Test the index parameter */ - /****************************/ - - if (b_IndexOperation == - APCI1710_HIGH_EDGE_LATCH_COUNTER - || b_IndexOperation == - APCI1710_LOW_EDGE_LATCH_COUNTER - || b_IndexOperation == - APCI1710_HIGH_EDGE_CLEAR_COUNTER - || b_IndexOperation == - APCI1710_LOW_EDGE_CLEAR_COUNTER - || b_IndexOperation == - APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER - || b_IndexOperation == - APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER) - { - /********************************/ - /* Test the auto mode parameter */ - /********************************/ - - if (b_AutoMode == APCI1710_ENABLE || - b_AutoMode == APCI1710_DISABLE) - { - /***************************/ - /* Test the interrupt mode */ - /***************************/ - - if (b_InterruptEnable == - APCI1710_ENABLE - || b_InterruptEnable == - APCI1710_DISABLE) { - - /************************************/ - /* Makte the configuration commando */ - /************************************/ - - if (b_ReferenceAction == - APCI1710_ENABLE) - { - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister2 - = - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister2 - | - APCI1710_ENABLE_INDEX_ACTION; - } else { - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister2 - = - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister2 - & - APCI1710_DISABLE_INDEX_ACTION; - } - - /****************************************/ - /* Test if low level latch or/and clear */ - /****************************************/ - - if (b_IndexOperation == - APCI1710_LOW_EDGE_LATCH_COUNTER - || - b_IndexOperation - == - APCI1710_LOW_EDGE_CLEAR_COUNTER - || - b_IndexOperation - == - APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER) - { - /*************************************/ - /* Set the index level to low (DQ26) */ - /*************************************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister4 - = - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister4 - | - APCI1710_SET_LOW_INDEX_LEVEL; - } else { - /**************************************/ - /* Set the index level to high (DQ26) */ - /**************************************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister4 - = - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister4 - & - APCI1710_SET_HIGH_INDEX_LEVEL; - } - - /***********************************/ - /* Test if latch and clear counter */ - /***********************************/ - - if (b_IndexOperation == - APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER - || - b_IndexOperation - == - APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER) - { - /***************************************/ - /* Set the latch and clear flag (DQ27) */ - /***************************************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister4 - = - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister4 - | - APCI1710_ENABLE_LATCH_AND_CLEAR; - } /* if (b_IndexOperation == APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER || b_IndexOperation == APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER) */ - else { - /*****************************************/ - /* Clear the latch and clear flag (DQ27) */ - /*****************************************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister4 - = - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister4 - & - APCI1710_DISABLE_LATCH_AND_CLEAR; - - /*************************/ - /* Test if latch counter */ - /*************************/ - - if (b_IndexOperation == APCI1710_HIGH_EDGE_LATCH_COUNTER || b_IndexOperation == APCI1710_LOW_EDGE_LATCH_COUNTER) { - /*********************************/ - /* Enable the latch from counter */ - /*********************************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister2 - = - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister2 - | - APCI1710_INDEX_LATCH_COUNTER; - } else { - /*********************************/ - /* Enable the clear from counter */ - /*********************************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister2 - = - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister2 - & - (~APCI1710_INDEX_LATCH_COUNTER); - } - } /* // if (b_IndexOperation == APCI1710_HIGH_EDGE_LATCH_AND_CLEAR_COUNTER || b_IndexOperation == APCI1710_LOW_EDGE_LATCH_AND_CLEAR_COUNTER) */ - - if (b_AutoMode == - APCI1710_DISABLE) - { - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister2 - = - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister2 - | - APCI1710_INDEX_AUTO_MODE; - } else { - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister2 - = - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister2 - & - (~APCI1710_INDEX_AUTO_MODE); - } - - if (b_InterruptEnable == - APCI1710_ENABLE) - { - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister3 - = - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister3 - | - APCI1710_ENABLE_INDEX_INT; - } else { - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister3 - = - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister3 - & - APCI1710_DISABLE_INDEX_INT; - } - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_InitFlag. - b_IndexInit = 1; - - } else { - /********************************/ - /* Interrupt parameter is wrong */ - /********************************/ - DPRINTK("Interrupt parameter is wrong\n"); - i_ReturnValue = -7; - } - } else { - /************************************/ - /* The auto mode parameter is wrong */ - /************************************/ - - DPRINTK("The auto mode parameter is wrong\n"); - i_ReturnValue = -6; - } - } else { - /***********************************************/ - /* The index operating mode parameter is wrong */ - /***********************************************/ - - DPRINTK("The index operating mode parameter is wrong\n"); - i_ReturnValue = -5; - } - } else { - /*******************************************/ - /* The reference action parameter is wrong */ - /*******************************************/ - - DPRINTK("The reference action parameter is wrong\n"); - i_ReturnValue = -4; - } - } else { - /****************************************/ - /* Counter not initialised see function */ - /* "i_APCI1710_InitCounter" */ - /****************************************/ - - DPRINTK("Counter not initialised\n"); - i_ReturnValue = -3; - } - } else { - /*************************************************/ - /* The selected module number parameter is wrong */ - /*************************************************/ - - DPRINTK("The selected module number parameter is wrong\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_InitReference | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_ReferenceLevel) | -+----------------------------------------------------------------------------+ -| Task : Initialise the reference corresponding to the selected | -| module (b_ModulNbr). | -| | -| Reference level | -| --------------- | -| +--------------------+-------------------------+ | -| | b_ReferenceLevel | Operation | | -| +--------------------+-------------------------+ | -| | APCI1710_LOW | Reference occur if "0" | | -| |--------------------|-------------------------| | -| | APCI1710_HIGH | Reference occur if "1" | | -| +--------------------+-------------------------+ | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Module number to configure | -| (0 to 3) | -| unsigned char_ b_ReferenceLevel : Reference level. | -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: The selected module number parameter is wrong | -| -3: Counter not initialised see function | -| "i_APCI1710_InitCounter" | -| -4: Reference level parameter is wrong | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_InitReference(struct comedi_device *dev, - unsigned char b_ModulNbr, - unsigned char b_ReferenceLevel) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /*******************************/ - /* Test if counter initialised */ - /*******************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { - /**************************************/ - /* Test the reference level parameter */ - /**************************************/ - - if (b_ReferenceLevel == 0 || b_ReferenceLevel == 1) { - if (b_ReferenceLevel == 1) { - devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister2 = devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister2 | - APCI1710_REFERENCE_HIGH; - } else { - devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister2 = devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister2 & - APCI1710_REFERENCE_LOW; - } - - outl(devpriv->s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - dw_ModeRegister1_2_3_4, - devpriv->s_BoardInfos.ui_Address + 20 + - (64 * b_ModulNbr)); - - devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_InitFlag.b_ReferenceInit = 1; - } else { - /**************************************/ - /* Reference level parameter is wrong */ - /**************************************/ - - DPRINTK("Reference level parameter is wrong\n"); - i_ReturnValue = -4; - } - } else { - /****************************************/ - /* Counter not initialised see function */ - /* "i_APCI1710_InitCounter" */ - /****************************************/ - - DPRINTK("Counter not initialised\n"); - i_ReturnValue = -3; - } - } else { - /*************************************************/ - /* The selected module number parameter is wrong */ - /*************************************************/ - - DPRINTK("The selected module number parameter is wrong\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_InitExternalStrobe | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_ExternalStrobe, | -| unsigned char_ b_ExternalStrobeLevel) | -+----------------------------------------------------------------------------+ -| Task : Initialises the external strobe level corresponding to | -| the selected module (b_ModulNbr). | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Module number to configure | -| (0 to 3) | -| unsigned char_ b_ExternalStrobe : External strobe selection | -| 0 : External strobe A | -| 1 : External strobe B | -| unsigned char_ b_ExternalStrobeLevel : External strobe level | -| APCI1710_LOW : | -| External latch occurs if "0" | -| APCI1710_HIGH : | -| External latch occurs if "1" | -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: The selected module number is wrong | -| -3: Counter not initialised. | -| See function "i_APCI1710_InitCounter" | -| -4: External strobe selection is wrong | -| -5: External strobe level parameter is wrong | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_InitExternalStrobe(struct comedi_device *dev, - unsigned char b_ModulNbr, - unsigned char b_ExternalStrobe, - unsigned char b_ExternalStrobeLevel) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /*******************************/ - /* Test if counter initialised */ - /*******************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { - /**************************************/ - /* Test the external strobe selection */ - /**************************************/ - - if (b_ExternalStrobe == 0 || b_ExternalStrobe == 1) { - /******************/ - /* Test the level */ - /******************/ - - if ((b_ExternalStrobeLevel == APCI1710_HIGH) || - ((b_ExternalStrobeLevel == APCI1710_LOW - && (devpriv-> - s_BoardInfos. - dw_MolduleConfiguration - [b_ModulNbr] & - 0xFFFF) >= - 0x3135))) { - /*****************/ - /* Set the level */ - /*****************/ - - devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister4 = (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister4 & (0xFF - - (0x10 << b_ExternalStrobe))) | ((b_ExternalStrobeLevel ^ 1) << (4 + b_ExternalStrobe)); - } else { - /********************************************/ - /* External strobe level parameter is wrong */ - /********************************************/ - - DPRINTK("External strobe level parameter is wrong\n"); - i_ReturnValue = -5; - } - } /* if (b_ExternalStrobe == 0 || b_ExternalStrobe == 1) */ - else { - /**************************************/ - /* External strobe selection is wrong */ - /**************************************/ - - DPRINTK("External strobe selection is wrong\n"); - i_ReturnValue = -4; - } /* if (b_ExternalStrobe == 0 || b_ExternalStrobe == 1) */ - } else { - /****************************************/ - /* Counter not initialised see function */ - /* "i_APCI1710_InitCounter" */ - /****************************************/ - - DPRINTK("Counter not initialised\n"); - i_ReturnValue = -3; - } - } else { - /*************************************************/ - /* The selected module number parameter is wrong */ - /*************************************************/ - - DPRINTK("The selected module number parameter is wrong\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - - /* - +----------------------------------------------------------------------------+ - | Function Name : _INT_ i_APCI1710_InitCompareLogic | - | (unsigned char_ b_BoardHandle, | - | unsigned char_ b_ModulNbr, | - | unsigned int_ ui_CompareValue) | - +----------------------------------------------------------------------------+ - | Task : Set the 32-Bit compare value. At that moment that the | - | incremental counter arrive to the compare value | - | (ui_CompareValue) a interrupt is generated. | - +----------------------------------------------------------------------------+ - | Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | - | unsigned char_ b_ModulNbr : Module number to configure | - | (0 to 3) | - | unsigned int_ ui_CompareValue : 32-Bit compare value | - +----------------------------------------------------------------------------+ - | Output Parameters : - - +----------------------------------------------------------------------------+ - | Return Value : 0: No error | - | -1: The handle parameter of the board is wrong | - | -2: No counter module found | - | -3: Counter not initialised see function | - | "i_APCI1710_InitCounter" | - +----------------------------------------------------------------------------+ - */ -static int i_APCI1710_InitCompareLogic(struct comedi_device *dev, - unsigned char b_ModulNbr, - unsigned int ui_CompareValue) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /*******************************/ - /* Test if counter initialised */ - /*******************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { - - outl(ui_CompareValue, devpriv->s_BoardInfos. - ui_Address + 28 + (64 * b_ModulNbr)); - - devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_InitFlag.b_CompareLogicInit = 1; - } else { - /****************************************/ - /* Counter not initialised see function */ - /* "i_APCI1710_InitCounter" */ - /****************************************/ - - DPRINTK("Counter not initialised\n"); - i_ReturnValue = -3; - } - } else { - /*************************************************/ - /* The selected module number parameter is wrong */ - /*************************************************/ - - DPRINTK("The selected module number parameter is wrong\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_InitFrequencyMeasurement | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_PCIInputClock, | -| unsigned char_ b_TimingUnity, | -| ULONG_ ul_TimingInterval, | -| PULONG_ pul_RealTimingInterval) | -+----------------------------------------------------------------------------+ -| Task : Sets the time for the frequency measurement. | -| Configures the selected TOR incremental counter of the | -| selected module (b_ModulNbr). The ul_TimingInterval and| -| ul_TimingUnity determine the time base for the | -| measurement. The pul_RealTimingInterval returns the | -| real time value. You must call up this function before | -| you call up any other function which gives access to | -| the frequency measurement. | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Number of the module to be | -| configured (0 to 3) | -| unsigned char_ b_PCIInputClock : Selection of the PCI bus | -| clock | -| - APCI1710_30MHZ : | -| The PC has a PCI bus clock | -| of 30 MHz | -| - APCI1710_33MHZ : | -| The PC has a PCI bus clock | -| of 33 MHz | -| unsigned char_ b_TimingUnity : Base time unit (0 to 2) | -| 0 : ns | -| 1 : æs | -| 2 : ms | -| ULONG_ ul_TimingInterval: Base time value. | -+----------------------------------------------------------------------------+ -| Output Parameters : PULONG_ pul_RealTimingInterval : Real base time value. | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: The selected module number is wrong | -| -3: Counter not initialised see function | -| "i_APCI1710_InitCounter" | -| -4: The selected PCI input clock is wrong | -| -5: Timing unity selection is wrong | -| -6: Base timing selection is wrong | -| -7: 40MHz quartz not on board | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_InitFrequencyMeasurement(struct comedi_device *dev, - unsigned char b_ModulNbr, - unsigned char b_PCIInputClock, - unsigned char b_TimingUnity, - unsigned int ul_TimingInterval, - unsigned int *pul_RealTimingInterval) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned int ul_TimerValue = 0; - double d_RealTimingInterval; - unsigned int dw_Status = 0; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /*******************************/ - /* Test if counter initialised */ - /*******************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { - /**************************/ - /* Test the PCI bus clock */ - /**************************/ - - if ((b_PCIInputClock == APCI1710_30MHZ) || - (b_PCIInputClock == APCI1710_33MHZ) || - (b_PCIInputClock == APCI1710_40MHZ)) { - /************************/ - /* Test the timing unit */ - /************************/ - - if (b_TimingUnity <= 2) { - /**********************************/ - /* Test the base timing selection */ - /**********************************/ - - if (((b_PCIInputClock == APCI1710_30MHZ) - && (b_TimingUnity == 0) - && (ul_TimingInterval >= - 266) - && (ul_TimingInterval <= - 8738133UL)) - || ((b_PCIInputClock == - APCI1710_30MHZ) - && (b_TimingUnity == 1) - && (ul_TimingInterval >= - 1) - && (ul_TimingInterval <= - 8738UL)) - || ((b_PCIInputClock == - APCI1710_30MHZ) - && (b_TimingUnity == 2) - && (ul_TimingInterval >= - 1) - && (ul_TimingInterval <= - 8UL)) - || ((b_PCIInputClock == - APCI1710_33MHZ) - && (b_TimingUnity == 0) - && (ul_TimingInterval >= - 242) - && (ul_TimingInterval <= - 7943757UL)) - || ((b_PCIInputClock == - APCI1710_33MHZ) - && (b_TimingUnity == 1) - && (ul_TimingInterval >= - 1) - && (ul_TimingInterval <= - 7943UL)) - || ((b_PCIInputClock == - APCI1710_33MHZ) - && (b_TimingUnity == 2) - && (ul_TimingInterval >= - 1) - && (ul_TimingInterval <= - 7UL)) - || ((b_PCIInputClock == - APCI1710_40MHZ) - && (b_TimingUnity == 0) - && (ul_TimingInterval >= - 200) - && (ul_TimingInterval <= - 6553500UL)) - || ((b_PCIInputClock == - APCI1710_40MHZ) - && (b_TimingUnity == 1) - && (ul_TimingInterval >= - 1) - && (ul_TimingInterval <= - 6553UL)) - || ((b_PCIInputClock == - APCI1710_40MHZ) - && (b_TimingUnity == 2) - && (ul_TimingInterval >= - 1) - && (ul_TimingInterval <= - 6UL))) { - /**********************/ - /* Test if 40MHz used */ - /**********************/ - - if (b_PCIInputClock == - APCI1710_40MHZ) { - /******************************/ - /* Test if firmware >= Rev1.5 */ - /******************************/ - - if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) >= 0x3135) { - /*********************************/ - /* Test if 40MHz quartz on board */ - /*********************************/ - - /*INPDW (ps_APCI1710Variable-> - s_Board [b_BoardHandle]. - s_BoardInfos. - ui_Address + 36 + (64 * b_ModulNbr), &dw_Status); */ - dw_Status = - inl - (devpriv-> - s_BoardInfos. - ui_Address - + 36 + - (64 * b_ModulNbr)); - - /******************************/ - /* Test the quartz flag (DQ0) */ - /******************************/ - - if ((dw_Status & 1) != 1) { - /*****************************/ - /* 40MHz quartz not on board */ - /*****************************/ - - DPRINTK("40MHz quartz not on board\n"); - i_ReturnValue - = - -7; - } - } else { - /*****************************/ - /* 40MHz quartz not on board */ - /*****************************/ - DPRINTK("40MHz quartz not on board\n"); - i_ReturnValue = - -7; - } - } /* if (b_PCIInputClock == APCI1710_40MHZ) */ - - /***************************/ - /* Test if not error occur */ - /***************************/ - - if (i_ReturnValue == 0) { - /****************************/ - /* Test the INC_CPT version */ - /****************************/ - - if ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) >= 0x3131) { - - /**********************/ - /* Test if 40MHz used */ - /**********************/ - - if (b_PCIInputClock == APCI1710_40MHZ) { - /*********************************/ - /* Enable the 40MHz quarz (DQ30) */ - /*********************************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister4 - = - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister4 - | - APCI1710_ENABLE_40MHZ_FREQUENCY; - } /* if (b_PCIInputClock == APCI1710_40MHZ) */ - else { - /**********************************/ - /* Disable the 40MHz quarz (DQ30) */ - /**********************************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister4 - = - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister4 - & - APCI1710_DISABLE_40MHZ_FREQUENCY; - - } /* if (b_PCIInputClock == APCI1710_40MHZ) */ - - /********************************/ - /* Calculate the division fator */ - /********************************/ - - fpu_begin(); - switch (b_TimingUnity) { - /******/ - /* ns */ - /******/ - - case 0: - - /******************/ - /* Timer 0 factor */ - /******************/ - - ul_TimerValue - = - (unsigned int) - (ul_TimingInterval - * - (0.00025 * b_PCIInputClock)); - - /*******************/ - /* Round the value */ - /*******************/ - - if ((double)((double)ul_TimingInterval * (0.00025 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) { - ul_TimerValue - = - ul_TimerValue - + - 1; - } - - /*****************************/ - /* Calculate the real timing */ - /*****************************/ - - *pul_RealTimingInterval - = - (unsigned int) - (ul_TimerValue - / - (0.00025 * (double)b_PCIInputClock)); - d_RealTimingInterval - = - (double) - ul_TimerValue - / - (0.00025 - * - (double) - b_PCIInputClock); - - if ((double)((double)ul_TimerValue / (0.00025 * (double)b_PCIInputClock)) >= (double)((double)*pul_RealTimingInterval + 0.5)) { - *pul_RealTimingInterval - = - *pul_RealTimingInterval - + - 1; - } - - ul_TimingInterval - = - ul_TimingInterval - - - 1; - ul_TimerValue - = - ul_TimerValue - - - 2; - - break; - - /******/ - /* æs */ - /******/ - - case 1: - - /******************/ - /* Timer 0 factor */ - /******************/ - - ul_TimerValue - = - (unsigned int) - (ul_TimingInterval - * - (0.25 * b_PCIInputClock)); - - /*******************/ - /* Round the value */ - /*******************/ - - if ((double)((double)ul_TimingInterval * (0.25 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) { - ul_TimerValue - = - ul_TimerValue - + - 1; - } - - /*****************************/ - /* Calculate the real timing */ - /*****************************/ - - *pul_RealTimingInterval - = - (unsigned int) - (ul_TimerValue - / - (0.25 * (double)b_PCIInputClock)); - d_RealTimingInterval - = - (double) - ul_TimerValue - / - ( - (double) - 0.25 - * - (double) - b_PCIInputClock); - - if ((double)((double)ul_TimerValue / (0.25 * (double)b_PCIInputClock)) >= (double)((double)*pul_RealTimingInterval + 0.5)) { - *pul_RealTimingInterval - = - *pul_RealTimingInterval - + - 1; - } - - ul_TimingInterval - = - ul_TimingInterval - - - 1; - ul_TimerValue - = - ul_TimerValue - - - 2; - - break; - - /******/ - /* ms */ - /******/ - - case 2: - - /******************/ - /* Timer 0 factor */ - /******************/ - - ul_TimerValue - = - ul_TimingInterval - * - (250.0 - * - b_PCIInputClock); - - /*******************/ - /* Round the value */ - /*******************/ - - if ((double)((double)ul_TimingInterval * (250.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) { - ul_TimerValue - = - ul_TimerValue - + - 1; - } - - /*****************************/ - /* Calculate the real timing */ - /*****************************/ - - *pul_RealTimingInterval - = - (unsigned int) - (ul_TimerValue - / - (250.0 * (double)b_PCIInputClock)); - d_RealTimingInterval - = - (double) - ul_TimerValue - / - (250.0 - * - (double) - b_PCIInputClock); - - if ((double)((double)ul_TimerValue / (250.0 * (double)b_PCIInputClock)) >= (double)((double)*pul_RealTimingInterval + 0.5)) { - *pul_RealTimingInterval - = - *pul_RealTimingInterval - + - 1; - } - - ul_TimingInterval - = - ul_TimingInterval - - - 1; - ul_TimerValue - = - ul_TimerValue - - - 2; - - break; - } - - fpu_end(); - /*************************/ - /* Write the timer value */ - /*************************/ - - outl(ul_TimerValue, devpriv->s_BoardInfos.ui_Address + 32 + (64 * b_ModulNbr)); - - /*******************************/ - /* Set the initialisation flag */ - /*******************************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_InitFlag. - b_FrequencyMeasurementInit - = 1; - } else { - /***************************/ - /* Counter not initialised */ - /***************************/ - - DPRINTK("Counter not initialised\n"); - i_ReturnValue = - -3; - } - } /* if (i_ReturnValue == 0) */ - } else { - /**********************************/ - /* Base timing selection is wrong */ - /**********************************/ - - DPRINTK("Base timing selection is wrong\n"); - i_ReturnValue = -6; - } - } else { - /***********************************/ - /* Timing unity selection is wrong */ - /***********************************/ - - DPRINTK("Timing unity selection is wrong\n"); - i_ReturnValue = -5; - } - } else { - /*****************************************/ - /* The selected PCI input clock is wrong */ - /*****************************************/ - - DPRINTK("The selected PCI input clock is wrong\n"); - i_ReturnValue = -4; - } - } else { - /****************************************/ - /* Counter not initialised see function */ - /* "i_APCI1710_InitCounter" */ - /****************************************/ - - DPRINTK("Counter not initialised\n"); - i_ReturnValue = -3; - } - } else { - /*************************************************/ - /* The selected module number parameter is wrong */ - /*************************************************/ - - DPRINTK("The selected module number parameter is wrong\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* - * Configuration function for INC_CPT - */ -static int i_APCI1710_InsnConfigINCCPT(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct addi_private *devpriv = dev->private; - unsigned int ui_ConfigType; - int i_ReturnValue = 0; - - ui_ConfigType = CR_CHAN(insn->chanspec); - - printk("\nINC_CPT"); - - devpriv->tsk_Current = current; /* Save the current process task structure */ - switch (ui_ConfigType) { - case APCI1710_INCCPT_INITCOUNTER: - i_ReturnValue = i_APCI1710_InitCounter(dev, - CR_AREF(insn->chanspec), - (unsigned char) data[0], - (unsigned char) data[1], - (unsigned char) data[2], (unsigned char) data[3], (unsigned char) data[4]); - break; - - case APCI1710_INCCPT_COUNTERAUTOTEST: - i_ReturnValue = i_APCI1710_CounterAutoTest(dev, - (unsigned char *) &data[0]); - break; - - case APCI1710_INCCPT_INITINDEX: - i_ReturnValue = i_APCI1710_InitIndex(dev, - CR_AREF(insn->chanspec), - (unsigned char) data[0], - (unsigned char) data[1], (unsigned char) data[2], (unsigned char) data[3]); - break; - - case APCI1710_INCCPT_INITREFERENCE: - i_ReturnValue = i_APCI1710_InitReference(dev, - CR_AREF(insn->chanspec), (unsigned char) data[0]); - break; - - case APCI1710_INCCPT_INITEXTERNALSTROBE: - i_ReturnValue = i_APCI1710_InitExternalStrobe(dev, - CR_AREF(insn->chanspec), - (unsigned char) data[0], (unsigned char) data[1]); - break; - - case APCI1710_INCCPT_INITCOMPARELOGIC: - i_ReturnValue = i_APCI1710_InitCompareLogic(dev, - CR_AREF(insn->chanspec), (unsigned int) data[0]); - break; - - case APCI1710_INCCPT_INITFREQUENCYMEASUREMENT: - i_ReturnValue = i_APCI1710_InitFrequencyMeasurement(dev, - CR_AREF(insn->chanspec), - (unsigned char) data[0], - (unsigned char) data[1], (unsigned int) data[2], (unsigned int *) &data[0]); - break; - - default: - printk("Insn Config : Config Parameter Wrong\n"); - - } - - if (i_ReturnValue >= 0) - i_ReturnValue = insn->n; - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_ClearCounterValue | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr) | -+----------------------------------------------------------------------------+ -| Task : Clear the counter value from selected module | -| (b_ModulNbr). | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Module number to configure | -| (0 to 3) | -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: The selected module number parameter is wrong | -| -3: Counter not initialised see function | -| "i_APCI1710_InitCounter" | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_ClearCounterValue(struct comedi_device *dev, - unsigned char b_ModulNbr) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /*******************************/ - /* Test if counter initialised */ - /*******************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { - /*********************/ - /* Clear the counter */ - /*********************/ - - outl(1, devpriv->s_BoardInfos. - ui_Address + 16 + (64 * b_ModulNbr)); - } else { - /****************************************/ - /* Counter not initialised see function */ - /* "i_APCI1710_InitCounter" */ - /****************************************/ - - DPRINTK("Counter not initialised\n"); - i_ReturnValue = -3; - } - } else { - /*************************************************/ - /* The selected module number parameter is wrong */ - /*************************************************/ - - DPRINTK("The selected module number parameter is wrong\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_ClearAllCounterValue | -| (unsigned char_ b_BoardHandle) | -+----------------------------------------------------------------------------+ -| Task : Clear all counter value. | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: No counter module found | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_ClearAllCounterValue(struct comedi_device *dev) -{ - struct addi_private *devpriv = dev->private; - unsigned char b_ModulCpt = 0; - int i_ReturnValue = 0; - - /********************************/ - /* Test if counter module found */ - /********************************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[0] & 0xFFFF0000UL) == - APCI1710_INCREMENTAL_COUNTER - || (devpriv->s_BoardInfos. - dw_MolduleConfiguration[1] & 0xFFFF0000UL) == - APCI1710_INCREMENTAL_COUNTER - || (devpriv->s_BoardInfos. - dw_MolduleConfiguration[2] & 0xFFFF0000UL) == - APCI1710_INCREMENTAL_COUNTER - || (devpriv->s_BoardInfos. - dw_MolduleConfiguration[3] & 0xFFFF0000UL) == - APCI1710_INCREMENTAL_COUNTER) { - for (b_ModulCpt = 0; b_ModulCpt < 4; b_ModulCpt++) { - /*******************************/ - /* Test if incremental counter */ - /*******************************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModulCpt] & - 0xFFFF0000UL) == - APCI1710_INCREMENTAL_COUNTER) { - /*********************/ - /* Clear the counter */ - /*********************/ - - outl(1, devpriv->s_BoardInfos. - ui_Address + 16 + (64 * b_ModulCpt)); - } - } - } else { - /***************************/ - /* No counter module found */ - /***************************/ - - DPRINTK("No counter module found\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_SetInputFilter | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_Module, | -| unsigned char_ b_PCIInputClock, | -| unsigned char_ b_Filter) | -+----------------------------------------------------------------------------+ -| Task : Disable or enable the software filter from selected | -| module (b_ModulNbr). b_Filter determine the filter time| -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Number of the module to be | -| configured (0 to 3) | -| unsigned char_ b_PCIInputClock : Selection of the PCI bus | -| clock | -| - APCI1710_30MHZ : | -| The PC has a PCI bus clock | -| of 30 MHz | -| - APCI1710_33MHZ : | -| The PC has a PCI bus clock | -| of 33 MHz | -| - APCI1710_40MHZ : | -| The APCI1710 has a 40MHz | -| quartz | -| unsigned char_ b_Filter : Filter selection | -| | -| 30 MHz | -| ------ | -| 0: Software filter not used | -| 1: Filter from 266ns (3.750000MHz) | -| 2: Filter from 400ns (2.500000MHz) | -| 3: Filter from 533ns (1.876170MHz) | -| 4: Filter from 666ns (1.501501MHz) | -| 5: Filter from 800ns (1.250000MHz) | -| 6: Filter from 933ns (1.071800MHz) | -| 7: Filter from 1066ns (0.938080MHz) | -| 8: Filter from 1200ns (0.833333MHz) | -| 9: Filter from 1333ns (0.750000MHz) | -| 10: Filter from 1466ns (0.682100MHz) | -| 11: Filter from 1600ns (0.625000MHz) | -| 12: Filter from 1733ns (0.577777MHz) | -| 13: Filter from 1866ns (0.535900MHz) | -| 14: Filter from 2000ns (0.500000MHz) | -| 15: Filter from 2133ns (0.468800MHz) | -| | -| 33 MHz | -| ------ | -| 0: Software filter not used | -| 1: Filter from 242ns (4.125000MHz) | -| 2: Filter from 363ns (2.754820MHz) | -| 3: Filter from 484ns (2.066115MHz) | -| 4: Filter from 605ns (1.652892MHz) | -| 5: Filter from 726ns (1.357741MHz) | -| 6: Filter from 847ns (1.180637MHz) | -| 7: Filter from 968ns (1.033055MHz) | -| 8: Filter from 1089ns (0.918273MHz) | -| 9: Filter from 1210ns (0.826446MHz) | -| 10: Filter from 1331ns (0.751314MHz) | -| 11: Filter from 1452ns (0.688705MHz) | -| 12: Filter from 1573ns (0.635727MHz) | -| 13: Filter from 1694ns (0.590318MHz) | -| 14: Filter from 1815ns (0.550964MHz) | -| 15: Filter from 1936ns (0.516528MHz) | -| | -| 40 MHz | -| ------ | -| 0: Software filter not used | -| 1: Filter from 200ns (5.000000MHz) | -| 2: Filter from 300ns (3.333333MHz) | -| 3: Filter from 400ns (2.500000MHz) | -| 4: Filter from 500ns (2.000000MHz) | -| 5: Filter from 600ns (1.666666MHz) | -| 6: Filter from 700ns (1.428500MHz) | -| 7: Filter from 800ns (1.250000MHz) | -| 8: Filter from 900ns (1.111111MHz) | -| 9: Filter from 1000ns (1.000000MHz) | -| 10: Filter from 1100ns (0.909090MHz) | -| 11: Filter from 1200ns (0.833333MHz) | -| 12: Filter from 1300ns (0.769200MHz) | -| 13: Filter from 1400ns (0.714200MHz) | -| 14: Filter from 1500ns (0.666666MHz) | -| 15: Filter from 1600ns (0.625000MHz) | -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: The selected module number is wrong | -| -3: The module is not a counter module | -| -4: The selected PCI input clock is wrong | -| -5: The selected filter value is wrong | -| -6: 40MHz quartz not on board | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_SetInputFilter(struct comedi_device *dev, - unsigned char b_ModulNbr, - unsigned char b_PCIInputClock, - unsigned char b_Filter) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned int dw_Status = 0; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /*******************************/ - /* Test if incremental counter */ - /*******************************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModulNbr] & - 0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER) { - /******************************/ - /* Test if firmware >= Rev1.5 */ - /******************************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModulNbr] & - 0xFFFF) >= 0x3135) { - /**************************/ - /* Test the PCI bus clock */ - /**************************/ - - if ((b_PCIInputClock == APCI1710_30MHZ) || - (b_PCIInputClock == APCI1710_33MHZ) || - (b_PCIInputClock == APCI1710_40MHZ)) { - /*************************/ - /* Test the filter value */ - /*************************/ - - if (b_Filter < 16) { - /**********************/ - /* Test if 40MHz used */ - /**********************/ - - if (b_PCIInputClock == - APCI1710_40MHZ) { - /*********************************/ - /* Test if 40MHz quartz on board */ - /*********************************/ - - dw_Status = - inl(devpriv-> - s_BoardInfos. - ui_Address + - 36 + - (64 * b_ModulNbr)); - - /******************************/ - /* Test the quartz flag (DQ0) */ - /******************************/ - - if ((dw_Status & 1) != - 1) { - /*****************************/ - /* 40MHz quartz not on board */ - /*****************************/ - - DPRINTK("40MHz quartz not on board\n"); - i_ReturnValue = - -6; - } - } /* if (b_PCIInputClock == APCI1710_40MHZ) */ - - /***************************/ - /* Test if error not occur */ - /***************************/ - - if (i_ReturnValue == 0) { - /**********************/ - /* Test if 40MHz used */ - /**********************/ - - if (b_PCIInputClock == - APCI1710_40MHZ) - { - /*********************************/ - /* Enable the 40MHz quarz (DQ31) */ - /*********************************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister4 - = - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister4 - | - APCI1710_ENABLE_40MHZ_FILTER; - - } /* if (b_PCIInputClock == APCI1710_40MHZ) */ - else { - /**********************************/ - /* Disable the 40MHz quarz (DQ31) */ - /**********************************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister4 - = - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister4 - & - APCI1710_DISABLE_40MHZ_FILTER; - - } /* if (b_PCIInputClock == APCI1710_40MHZ) */ - - /************************/ - /* Set the filter value */ - /************************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister3 - = - (devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister3 - & 0x1F) | - ((b_Filter & - 0x7) << - 5); - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister4 - = - (devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister4 - & 0xFE) | - ((b_Filter & - 0x8) >> - 3); - - /***************************/ - /* Write the configuration */ - /***************************/ - - outl(devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - dw_ModeRegister1_2_3_4, - devpriv-> - s_BoardInfos. - ui_Address + - 20 + - (64 * b_ModulNbr)); - } /* if (i_ReturnValue == 0) */ - } /* if (b_Filter < 16) */ - else { - /**************************************/ - /* The selected filter value is wrong */ - /**************************************/ - - DPRINTK("The selected filter value is wrong\n"); - i_ReturnValue = -5; - } /* if (b_Filter < 16) */ - } /* if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ) || (b_PCIInputClock == APCI1710_40MHZ)) */ - else { - /*****************************************/ - /* The selected PCI input clock is wrong */ - /*****************************************/ - - DPRINTK("The selected PCI input clock is wrong\n"); - i_ReturnValue = 4; - } /* if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ) || (b_PCIInputClock == APCI1710_40MHZ)) */ - } else { - /**************************************/ - /* The module is not a counter module */ - /**************************************/ - - DPRINTK("The module is not a counter module\n"); - i_ReturnValue = -3; - } - } else { - /**************************************/ - /* The module is not a counter module */ - /**************************************/ - - DPRINTK("The module is not a counter module\n"); - i_ReturnValue = -3; - } - } else { - /*************************************************/ - /* The selected module number parameter is wrong */ - /*************************************************/ - - DPRINTK("The selected module number parameter is wrong\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_LatchCounter (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_LatchReg) | -+----------------------------------------------------------------------------+ -| Task : Latch the courant value from selected module | -| (b_ModulNbr) in to the selected latch register | -| (b_LatchReg). | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Module number to configure | -| (0 to 3) | -| unsigned char_ b_LatchReg : Selected latch register | -| 0 : for the first latch register | -| 1 : for the second latch register | -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: No counter module found | -| -3: Counter not initialised see function | -| "i_APCI1710_InitCounter" | -| -4: The selected latch register parameter is wrong | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_LatchCounter(struct comedi_device *dev, - unsigned char b_ModulNbr, - unsigned char b_LatchReg) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /*******************************/ - /* Test if counter initialised */ - /*******************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { - /*************************************/ - /* Test the latch register parameter */ - /*************************************/ - - if (b_LatchReg < 2) { - /*********************/ - /* Tatch the counter */ - /*********************/ - - outl(1 << (b_LatchReg * 4), - devpriv->s_BoardInfos.ui_Address + - (64 * b_ModulNbr)); - } else { - /**************************************************/ - /* The selected latch register parameter is wrong */ - /**************************************************/ - - DPRINTK("The selected latch register parameter is wrong\n"); - i_ReturnValue = -4; - } - } else { - /****************************************/ - /* Counter not initialised see function */ - /* "i_APCI1710_InitCounter" */ - /****************************************/ - - DPRINTK("Counter not initialised\n"); - i_ReturnValue = -3; - } - } else { - /*************************************************/ - /* The selected module number parameter is wrong */ - /*************************************************/ - - DPRINTK("The selected module number parameter is wrong\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_SetIndexAndReferenceSource | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_SourceSelection) | -+----------------------------------------------------------------------------+ -| Task : Determine the hardware source for the index and the | -| reference logic. Per default the index logic is | -| connected to the difference input C and the reference | -| logic is connected to the 24V input E | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Module number to configure | -| (0 to 3) | -| unsigned char_ b_SourceSelection : APCI1710_SOURCE_0 : | -| The index logic is connected | -| to the difference input C and| -| the reference logic is | -| connected to the 24V input E.| -| This is the default | -| configuration. | -| APCI1710_SOURCE_1 : | -| The reference logic is | -| connected to the difference | -| input C and the index logic | -| is connected to the 24V | -| input E | -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: The selected module number is wrong | -| -3: The module is not a counter module. | -| -4: The source selection is wrong | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_SetIndexAndReferenceSource(struct comedi_device *dev, - unsigned char b_ModulNbr, - unsigned char b_SourceSelection) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /*******************************/ - /* Test if incremental counter */ - /*******************************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModulNbr] & - 0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER) { - /******************************/ - /* Test if firmware >= Rev1.5 */ - /******************************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModulNbr] & - 0xFFFF) >= 0x3135) { - /*****************************/ - /* Test the source selection */ - /*****************************/ - - if (b_SourceSelection == APCI1710_SOURCE_0 || - b_SourceSelection == APCI1710_SOURCE_1) - { - /******************************************/ - /* Test if invert the index and reference */ - /******************************************/ - - if (b_SourceSelection == - APCI1710_SOURCE_1) { - /********************************************/ - /* Invert index and reference source (DQ25) */ - /********************************************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister4 = - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister4 | - APCI1710_INVERT_INDEX_RFERENCE; - } else { - /****************************************/ - /* Set the default configuration (DQ25) */ - /****************************************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister4 = - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister4 & - APCI1710_DEFAULT_INDEX_RFERENCE; - } - } /* if (b_SourceSelection == APCI1710_SOURCE_0 ||b_SourceSelection == APCI1710_SOURCE_1) */ - else { - /*********************************/ - /* The source selection is wrong */ - /*********************************/ - - DPRINTK("The source selection is wrong\n"); - i_ReturnValue = -4; - } /* if (b_SourceSelection == APCI1710_SOURCE_0 ||b_SourceSelection == APCI1710_SOURCE_1) */ - } else { - /**************************************/ - /* The module is not a counter module */ - /**************************************/ - - DPRINTK("The module is not a counter module\n"); - i_ReturnValue = -3; - } - } else { - /**************************************/ - /* The module is not a counter module */ - /**************************************/ - - DPRINTK("The module is not a counter module\n"); - i_ReturnValue = -3; - } - } else { - /***************************************/ - /* The selected module number is wrong */ - /***************************************/ - - DPRINTK("The selected module number is wrong\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_SetDigitalChlOn | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr) | -+----------------------------------------------------------------------------+ -| Task : Sets the digital output H Setting an output means | -| setting an ouput high. | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Number of the module to be | -| configured (0 to 3) | -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: The selected module number is wrong | -| -3: Counter not initialised see function | -| "i_APCI1710_InitCounter" | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_SetDigitalChlOn(struct comedi_device *dev, - unsigned char b_ModulNbr) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /*******************************/ - /* Test if counter initialised */ - /*******************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { - devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister3 = devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister.b_ModeRegister3 | 0x10; - - /*********************/ - /* Set the output On */ - /*********************/ - - outl(devpriv->s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - dw_ModeRegister1_2_3_4, devpriv->s_BoardInfos. - ui_Address + 20 + (64 * b_ModulNbr)); - } else { - /****************************************/ - /* Counter not initialised see function */ - /* "i_APCI1710_InitCounter" */ - /****************************************/ - - DPRINTK("Counter not initialised\n"); - i_ReturnValue = -3; - } - } else { - /*************************************************/ - /* The selected module number parameter is wrong */ - /*************************************************/ - - DPRINTK("The selected module number parameter is wrong\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_SetDigitalChlOff | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr) | -+----------------------------------------------------------------------------+ -| Task : Resets the digital output H. Resetting an output means | -| setting an ouput low. | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Number of the module to be | -| configured (0 to 3) | -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: The selected module number is wrong | -| -3: Counter not initialised see function | -| "i_APCI1710_InitCounter" | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_SetDigitalChlOff(struct comedi_device *dev, - unsigned char b_ModulNbr) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /*******************************/ - /* Test if counter initialised */ - /*******************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { - devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister3 = devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister.b_ModeRegister3 & 0xEF; - - /**********************/ - /* Set the output Off */ - /**********************/ - - outl(devpriv->s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - dw_ModeRegister1_2_3_4, devpriv->s_BoardInfos. - ui_Address + 20 + (64 * b_ModulNbr)); - } else { - /****************************************/ - /* Counter not initialised see function */ - /* "i_APCI1710_InitCounter" */ - /****************************************/ - - DPRINTK("Counter not initialised\n"); - i_ReturnValue = -3; - } - } else { - /*************************************************/ - /* The selected module number parameter is wrong */ - /*************************************************/ - - DPRINTK("The selected module number parameter is wrong\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* - * Set & Clear Functions for INC_CPT - */ -static int i_APCI1710_InsnBitsINCCPT(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct addi_private *devpriv = dev->private; - unsigned int ui_BitsType; - int i_ReturnValue = 0; - - ui_BitsType = CR_CHAN(insn->chanspec); - devpriv->tsk_Current = current; /* Save the current process task structure */ - - switch (ui_BitsType) { - case APCI1710_INCCPT_CLEARCOUNTERVALUE: - i_ReturnValue = i_APCI1710_ClearCounterValue(dev, - (unsigned char) CR_AREF(insn->chanspec)); - break; - - case APCI1710_INCCPT_CLEARALLCOUNTERVALUE: - i_ReturnValue = i_APCI1710_ClearAllCounterValue(dev); - break; - - case APCI1710_INCCPT_SETINPUTFILTER: - i_ReturnValue = i_APCI1710_SetInputFilter(dev, - (unsigned char) CR_AREF(insn->chanspec), - (unsigned char) data[0], (unsigned char) data[1]); - break; - - case APCI1710_INCCPT_LATCHCOUNTER: - i_ReturnValue = i_APCI1710_LatchCounter(dev, - (unsigned char) CR_AREF(insn->chanspec), (unsigned char) data[0]); - break; - - case APCI1710_INCCPT_SETINDEXANDREFERENCESOURCE: - i_ReturnValue = i_APCI1710_SetIndexAndReferenceSource(dev, - (unsigned char) CR_AREF(insn->chanspec), (unsigned char) data[0]); - break; - - case APCI1710_INCCPT_SETDIGITALCHLON: - i_ReturnValue = i_APCI1710_SetDigitalChlOn(dev, - (unsigned char) CR_AREF(insn->chanspec)); - break; - - case APCI1710_INCCPT_SETDIGITALCHLOFF: - i_ReturnValue = i_APCI1710_SetDigitalChlOff(dev, - (unsigned char) CR_AREF(insn->chanspec)); - break; - - default: - printk("Bits Config Parameter Wrong\n"); - } - - if (i_ReturnValue >= 0) - i_ReturnValue = insn->n; - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_EnableLatchInterrupt | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr) | -+----------------------------------------------------------------------------+ -| Task : Enable the latch interrupt from selected module | -| (b_ModulNbr). Each software or hardware latch occur a | -| interrupt. | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Module number to configure | -| (0 to 3) | -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: No counter module found | -| -3: Counter not initialised see function | -| "i_APCI1710_InitCounter" | -| -4: Interrupt routine not installed see function | -| "i_APCI1710_SetBoardIntRoutine" | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_EnableLatchInterrupt(struct comedi_device *dev, - unsigned char b_ModulNbr) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /*******************************/ - /* Test if counter initialised */ - /*******************************/ - - if (devpriv->s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { - - /********************/ - /* Enable interrupt */ - /********************/ - - devpriv->s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister2 = devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister2 | APCI1710_ENABLE_LATCH_INT; - - /***************************/ - /* Write the configuration */ - /***************************/ - - outl(devpriv->s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - dw_ModeRegister1_2_3_4, devpriv->s_BoardInfos. - ui_Address + 20 + (64 * b_ModulNbr)); - } else { - /****************************************/ - /* Counter not initialised see function */ - /* "i_APCI1710_InitCounter" */ - /****************************************/ - - DPRINTK("Counter not initialised\n"); - i_ReturnValue = -3; - } - } else { - /*************************************************/ - /* The selected module number parameter is wrong */ - /*************************************************/ - - DPRINTK("The selected module number parameter is wrong\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_DisableLatchInterrupt | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr) | -+----------------------------------------------------------------------------+ -| Task : Disable the latch interrupt from selected module | -| (b_ModulNbr). | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Module number to configure | -| (0 to 3) | -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: No counter module found | -| -3: Counter not initialised see function | -| "i_APCI1710_InitCounter" | -| -4: Interrupt routine not installed see function | -| "i_APCI1710_SetBoardIntRoutine" | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_DisableLatchInterrupt(struct comedi_device *dev, - unsigned char b_ModulNbr) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /*******************************/ - /* Test if counter initialised */ - /*******************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { - - /***************************/ - /* Write the configuration */ - /***************************/ - - outl(devpriv->s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - dw_ModeRegister1_2_3_4 & - ((APCI1710_DISABLE_LATCH_INT << 8) | 0xFF), - devpriv->s_BoardInfos.ui_Address + 20 + - (64 * b_ModulNbr)); - - mdelay(1000); - - /*********************/ - /* Disable interrupt */ - /*********************/ - - devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister2 = devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister2 & APCI1710_DISABLE_LATCH_INT; - - } else { - /****************************************/ - /* Counter not initialised see function */ - /* "i_APCI1710_InitCounter" */ - /****************************************/ - - DPRINTK("Counter not initialised\n"); - i_ReturnValue = -3; - } - } else { - /*************************************************/ - /* The selected module number parameter is wrong */ - /*************************************************/ - - DPRINTK("The selected module number parameter is wrong\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_Write16BitCounterValue | -| (unsigned char_ b_BoardHandle | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_SelectedCounter, | -| unsigned int_ ui_WriteValue) | -+----------------------------------------------------------------------------+ -| Task : Write a 16-Bit value (ui_WriteValue) in to the selected| -| 16-Bit counter (b_SelectedCounter) from selected module| -| (b_ModulNbr). | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Module number to configure | -| (0 to 3) | -| unsigned char_ b_SelectedCounter : Selected 16-Bit counter | -| (0 or 1) | -| unsigned int_ ui_WriteValue : 16-Bit write value | -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: No counter module found | -| -3: Counter not initialised see function | -| "i_APCI1710_InitCounter" | -| -4: The selected 16-Bit counter parameter is wrong | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_Write16BitCounterValue(struct comedi_device *dev, - unsigned char b_ModulNbr, - unsigned char b_SelectedCounter, - unsigned int ui_WriteValue) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /*******************************/ - /* Test if counter initialised */ - /*******************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { - /******************************/ - /* Test the counter selection */ - /******************************/ - - if (b_SelectedCounter < 2) { - /*******************/ - /* Write the value */ - /*******************/ - - outl((unsigned int) ((unsigned int) (ui_WriteValue) << (16 * - b_SelectedCounter)), - devpriv->s_BoardInfos.ui_Address + 8 + - (b_SelectedCounter * 4) + - (64 * b_ModulNbr)); - } else { - /**************************************************/ - /* The selected 16-Bit counter parameter is wrong */ - /**************************************************/ - - DPRINTK("The selected 16-Bit counter parameter is wrong\n"); - i_ReturnValue = -4; - } - } else { - /****************************************/ - /* Counter not initialised see function */ - /* "i_APCI1710_InitCounter" */ - /****************************************/ - - DPRINTK("Counter not initialised\n"); - i_ReturnValue = -3; - } - } else { - /*************************************************/ - /* The selected module number parameter is wrong */ - /*************************************************/ - - DPRINTK("The selected module number parameter is wrong\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_Write32BitCounterValue | -| (unsigned char_ b_BoardHandle | -| unsigned char_ b_ModulNbr, | -| ULONG_ ul_WriteValue) | -+----------------------------------------------------------------------------+ -| Task : Write a 32-Bit value (ui_WriteValue) in to the selected| -| module (b_ModulNbr). | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Module number to configure | -| (0 to 3) | -| ULONG_ ul_WriteValue : 32-Bit write value | -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: No counter module found | -| -3: Counter not initialised see function | -| "i_APCI1710_InitCounter" | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_Write32BitCounterValue(struct comedi_device *dev, - unsigned char b_ModulNbr, - unsigned int ul_WriteValue) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /*******************************/ - /* Test if counter initialised */ - /*******************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { - /*******************/ - /* Write the value */ - /*******************/ - - outl(ul_WriteValue, devpriv->s_BoardInfos. - ui_Address + 4 + (64 * b_ModulNbr)); - } else { - /****************************************/ - /* Counter not initialised see function */ - /* "i_APCI1710_InitCounter" */ - /****************************************/ - - DPRINTK("Counter not initialised\n"); - i_ReturnValue = -3; - } - } else { - /*************************************************/ - /* The selected module number parameter is wrong */ - /*************************************************/ - - DPRINTK("The selected module number parameter is wrong\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_EnableIndex (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr) | -+----------------------------------------------------------------------------+ -| Task : Enable the INDEX actions | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Module number to configure | -| (0 to 3) | -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: No counter module found | -| -3: Counter not initialised see function | -| "i_APCI1710_InitCounter" | -| -4: Index not initialised see function | -| "i_APCI1710_InitIndex" | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_EnableIndex(struct comedi_device *dev, - unsigned char b_ModulNbr) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned int ul_InterruptLatchReg; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /*******************************/ - /* Test if counter initialised */ - /*******************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { - /*****************************/ - /* Test if index initialised */ - /*****************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo.s_InitFlag.b_IndexInit) { - devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister2 = devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister2 | APCI1710_ENABLE_INDEX; - - ul_InterruptLatchReg = - inl(devpriv->s_BoardInfos.ui_Address + - 24 + (64 * b_ModulNbr)); - - outl(devpriv->s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - dw_ModeRegister1_2_3_4, - devpriv->s_BoardInfos.ui_Address + 20 + - (64 * b_ModulNbr)); - } else { - /*************************************************************/ - /* Index not initialised see function "i_APCI1710_InitIndex" */ - /*************************************************************/ - - DPRINTK("Index not initialised \n"); - i_ReturnValue = -4; - } - } else { - /****************************************/ - /* Counter not initialised see function */ - /* "i_APCI1710_InitCounter" */ - /****************************************/ - - DPRINTK("Counter not initialised\n"); - i_ReturnValue = -3; - } - } else { - /*************************************************/ - /* The selected module number parameter is wrong */ - /*************************************************/ - - DPRINTK("The selected module number parameter is wrong\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_DisableIndex (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr) | -+----------------------------------------------------------------------------+ -| Task : Disable the INDEX actions | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Module number to configure | -| (0 to 3) | -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: No counter module found | -| -3: Counter not initialised see function | -| "i_APCI1710_InitCounter" | -| -4: Index not initialised see function | -| "i_APCI1710_InitIndex" | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_DisableIndex(struct comedi_device *dev, - unsigned char b_ModulNbr) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /*******************************/ - /* Test if counter initialised */ - /*******************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { - /*****************************/ - /* Test if index initialised */ - /*****************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo.s_InitFlag.b_IndexInit) { - devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister2 = devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister2 & - APCI1710_DISABLE_INDEX; - - outl(devpriv->s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - dw_ModeRegister1_2_3_4, - devpriv->s_BoardInfos.ui_Address + 20 + - (64 * b_ModulNbr)); - } else { - /*************************************************************/ - /* Index not initialised see function "i_APCI1710_InitIndex" */ - /*************************************************************/ - - DPRINTK("Index not initialised \n"); - i_ReturnValue = -4; - } - } else { - /****************************************/ - /* Counter not initialised see function */ - /* "i_APCI1710_InitCounter" */ - /****************************************/ - - DPRINTK("Counter not initialised\n"); - i_ReturnValue = -3; - } - } else { - /*************************************************/ - /* The selected module number parameter is wrong */ - /*************************************************/ - - DPRINTK("The selected module number parameter is wrong\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_EnableCompareLogic | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr) | -+----------------------------------------------------------------------------+ -| Task : Enable the 32-Bit compare logic. At that moment that | -| the incremental counter arrive to the compare value a | -| interrupt is generated. | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Module number to configure | -| (0 to 3) | -+----------------------------------------------------------------------------+ -| Output Parameters : - -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: No counter module found | -| -3: Counter not initialised see function | -| "i_APCI1710_InitCounter" | -| -4: Compare logic not initialised. | -| See function "i_APCI1710_InitCompareLogic" | -| -5: Interrupt function not initialised. | -| See function "i_APCI1710_SetBoardIntRoutineX" | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_EnableCompareLogic(struct comedi_device *dev, - unsigned char b_ModulNbr) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /*******************************/ - /* Test if counter initialised */ - /*******************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { - /*************************************/ - /* Test if compare logic initialised */ - /*************************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_InitFlag.b_CompareLogicInit == 1) { - devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister3 = devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister3 | - APCI1710_ENABLE_COMPARE_INT; - - /***************************/ - /* Write the configuration */ - /***************************/ - - outl(devpriv->s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - dw_ModeRegister1_2_3_4, - devpriv->s_BoardInfos.ui_Address + 20 + - (64 * b_ModulNbr)); - } else { - /*********************************/ - /* Compare logic not initialised */ - /*********************************/ - - DPRINTK("Compare logic not initialised\n"); - i_ReturnValue = -4; - } - } else { - /****************************************/ - /* Counter not initialised see function */ - /* "i_APCI1710_InitCounter" */ - /****************************************/ - - DPRINTK("Counter not initialised\n"); - i_ReturnValue = -3; - } - } else { - /*************************************************/ - /* The selected module number parameter is wrong */ - /*************************************************/ - - DPRINTK("The selected module number parameter is wrong\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_DisableCompareLogic | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr) | -+----------------------------------------------------------------------------+ -| Task : Disable the 32-Bit compare logic. -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Module number to configure | -| (0 to 3) | -+----------------------------------------------------------------------------+ -| Output Parameters : - -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: No counter module found | -| -3: Counter not initialised see function | -| "i_APCI1710_InitCounter" | -| -4: Compare logic not initialised. | -| See function "i_APCI1710_InitCompareLogic" | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_DisableCompareLogic(struct comedi_device *dev, - unsigned char b_ModulNbr) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /*******************************/ - /* Test if counter initialised */ - /*******************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { - /*************************************/ - /* Test if compare logic initialised */ - /*************************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_InitFlag.b_CompareLogicInit == 1) { - devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister3 = devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister3 & - APCI1710_DISABLE_COMPARE_INT; - - /***************************/ - /* Write the configuration */ - /***************************/ - - outl(devpriv->s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - dw_ModeRegister1_2_3_4, - devpriv->s_BoardInfos.ui_Address + 20 + - (64 * b_ModulNbr)); - } else { - /*********************************/ - /* Compare logic not initialised */ - /*********************************/ - - DPRINTK("Compare logic not initialised\n"); - i_ReturnValue = -4; - } - } else { - /****************************************/ - /* Counter not initialised see function */ - /* "i_APCI1710_InitCounter" */ - /****************************************/ - - DPRINTK("Counter not initialised\n"); - i_ReturnValue = -3; - } - } else { - /*************************************************/ - /* The selected module number parameter is wrong */ - /*************************************************/ - - DPRINTK("The selected module number parameter is wrong\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - - /* - +----------------------------------------------------------------------------+ - | Function Name : _INT_ i_APCI1710_EnableFrequencyMeasurement | - | (unsigned char_ b_BoardHandle, | - | unsigned char_ b_ModulNbr, | - | unsigned char_ b_InterruptEnable) | - +----------------------------------------------------------------------------+ - | Task : Enables the frequency measurement function | - +----------------------------------------------------------------------------+ - | Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | - | unsigned char_ b_ModulNbr : Number of the module to be | - | configured (0 to 3) | - | unsigned char_ b_InterruptEnable: Enable or disable the | - | interrupt. | - | APCI1710_ENABLE: | - | Enable the interrupt | - | APCI1710_DISABLE: | - | Disable the interrupt | - +----------------------------------------------------------------------------+ - | Output Parameters : - | - +----------------------------------------------------------------------------+ - | Return Value : 0: No error | - | -1: The handle parameter of the board is wrong | - | -2: The selected module number is wrong | - | -3: Counter not initialised see function | - | "i_APCI1710_InitCounter" | - | -4: Frequency measurement logic not initialised. | - | See function "i_APCI1710_InitFrequencyMeasurement" | - | -5: Interrupt parameter is wrong | - | -6: Interrupt function not initialised. | - +----------------------------------------------------------------------------+ - */ -static int i_APCI1710_EnableFrequencyMeasurement(struct comedi_device *dev, - unsigned char b_ModulNbr, - unsigned char b_InterruptEnable) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /*******************************/ - /* Test if counter initialised */ - /*******************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { - /********************************************/ - /* Test if frequency measurement initialised */ - /********************************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_InitFlag.b_FrequencyMeasurementInit == 1) { - /***************************/ - /* Test the interrupt mode */ - /***************************/ - - if ((b_InterruptEnable == APCI1710_DISABLE) || - (b_InterruptEnable == APCI1710_ENABLE)) - { - - /************************************/ - /* Enable the frequency measurement */ - /************************************/ - - devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister3 = devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister3 | - APCI1710_ENABLE_FREQUENCY; - - /*********************************************/ - /* Disable or enable the frequency interrupt */ - /*********************************************/ - - devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister3 = (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister3 & - APCI1710_DISABLE_FREQUENCY_INT) - | (b_InterruptEnable << 3); - - /***************************/ - /* Write the configuration */ - /***************************/ - - outl(devpriv->s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - dw_ModeRegister1_2_3_4, - devpriv->s_BoardInfos. - ui_Address + 20 + - (64 * b_ModulNbr)); - - devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_InitFlag. - b_FrequencyMeasurementEnable = - 1; - } else { - /********************************/ - /* Interrupt parameter is wrong */ - /********************************/ - - DPRINTK("Interrupt parameter is wrong\n"); - i_ReturnValue = -5; - } - } else { - /***********************************************/ - /* Frequency measurement logic not initialised */ - /***********************************************/ - - DPRINTK("Frequency measurement logic not initialised\n"); - i_ReturnValue = -4; - } - } else { - /****************************************/ - /* Counter not initialised see function */ - /* "i_APCI1710_InitCounter" */ - /****************************************/ - - DPRINTK("Counter not initialised\n"); - i_ReturnValue = -3; - } - } else { - /*************************************************/ - /* The selected module number parameter is wrong */ - /*************************************************/ - - DPRINTK("The selected module number parameter is wrong\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - - /* - +----------------------------------------------------------------------------+ - | Function Name : _INT_ i_APCI1710_DisableFrequencyMeasurement | - | (unsigned char_ b_BoardHandle, | - | unsigned char_ b_ModulNbr) | - +----------------------------------------------------------------------------+ - | Task : Disables the frequency measurement function | - +----------------------------------------------------------------------------+ - | Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | - | unsigned char_ b_ModulNbr : Number of the module to be | - | configured (0 to 3) | - +----------------------------------------------------------------------------+ - | Output Parameters : - | - +----------------------------------------------------------------------------+ - | Return Value : 0: No error | - | -1: The handle parameter of the board is wrong | - | -2: The selected module number is wrong | - | -3: Counter not initialised see function | - | "i_APCI1710_InitCounter" | - | -4: Frequency measurement logic not initialised. | - | See function "i_APCI1710_InitFrequencyMeasurement" | - +----------------------------------------------------------------------------+ - */ -static int i_APCI1710_DisableFrequencyMeasurement(struct comedi_device *dev, - unsigned char b_ModulNbr) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /*******************************/ - /* Test if counter initialised */ - /*******************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { - /********************************************/ - /* Test if frequency measurement initialised */ - /********************************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_InitFlag.b_FrequencyMeasurementInit == 1) { - /*************************************/ - /* Disable the frequency measurement */ - /*************************************/ - - devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister3 = devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister3 & - APCI1710_DISABLE_FREQUENCY - /* Begin CG 29/06/01 CG 1100/0231 -> 0701/0232 Frequence measure IRQ must be cleared */ - & APCI1710_DISABLE_FREQUENCY_INT; - /* End CG 29/06/01 CG 1100/0231 -> 0701/0232 Frequence measure IRQ must be cleared */ - - /***************************/ - /* Write the configuration */ - /***************************/ - - outl(devpriv->s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - dw_ModeRegister1_2_3_4, - devpriv->s_BoardInfos.ui_Address + 20 + - (64 * b_ModulNbr)); - - /*************************************/ - /* Disable the frequency measurement */ - /*************************************/ - - devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_InitFlag. - b_FrequencyMeasurementEnable = 0; - } else { - /***********************************************/ - /* Frequency measurement logic not initialised */ - /***********************************************/ - - DPRINTK("Frequency measurement logic not initialised\n"); - i_ReturnValue = -4; - } - } else { - /****************************************/ - /* Counter not initialised see function */ - /* "i_APCI1710_InitCounter" */ - /****************************************/ - - DPRINTK("Counter not initialised\n"); - i_ReturnValue = -3; - } - } else { - /*************************************************/ - /* The selected module number parameter is wrong */ - /*************************************************/ - - DPRINTK("The selected module number parameter is wrong\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* - * Enable Disable functions for INC_CPT - */ -static int i_APCI1710_InsnWriteINCCPT(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct addi_private *devpriv = dev->private; - unsigned int ui_WriteType; - int i_ReturnValue = 0; - - ui_WriteType = CR_CHAN(insn->chanspec); - devpriv->tsk_Current = current; /* Save the current process task structure */ - - switch (ui_WriteType) { - case APCI1710_INCCPT_ENABLELATCHINTERRUPT: - i_ReturnValue = i_APCI1710_EnableLatchInterrupt(dev, - (unsigned char) CR_AREF(insn->chanspec)); - break; - - case APCI1710_INCCPT_DISABLELATCHINTERRUPT: - i_ReturnValue = i_APCI1710_DisableLatchInterrupt(dev, - (unsigned char) CR_AREF(insn->chanspec)); - break; - - case APCI1710_INCCPT_WRITE16BITCOUNTERVALUE: - i_ReturnValue = i_APCI1710_Write16BitCounterValue(dev, - (unsigned char) CR_AREF(insn->chanspec), - (unsigned char) data[0], (unsigned int) data[1]); - break; - - case APCI1710_INCCPT_WRITE32BITCOUNTERVALUE: - i_ReturnValue = i_APCI1710_Write32BitCounterValue(dev, - (unsigned char) CR_AREF(insn->chanspec), (unsigned int) data[0]); - - break; - - case APCI1710_INCCPT_ENABLEINDEX: - i_APCI1710_EnableIndex(dev, (unsigned char) CR_AREF(insn->chanspec)); - break; - - case APCI1710_INCCPT_DISABLEINDEX: - i_ReturnValue = i_APCI1710_DisableIndex(dev, - (unsigned char) CR_AREF(insn->chanspec)); - break; - - case APCI1710_INCCPT_ENABLECOMPARELOGIC: - i_ReturnValue = i_APCI1710_EnableCompareLogic(dev, - (unsigned char) CR_AREF(insn->chanspec)); - break; - - case APCI1710_INCCPT_DISABLECOMPARELOGIC: - i_ReturnValue = i_APCI1710_DisableCompareLogic(dev, - (unsigned char) CR_AREF(insn->chanspec)); - break; - - case APCI1710_INCCPT_ENABLEFREQUENCYMEASUREMENT: - i_ReturnValue = i_APCI1710_EnableFrequencyMeasurement(dev, - (unsigned char) CR_AREF(insn->chanspec), (unsigned char) data[0]); - break; - - case APCI1710_INCCPT_DISABLEFREQUENCYMEASUREMENT: - i_ReturnValue = i_APCI1710_DisableFrequencyMeasurement(dev, - (unsigned char) CR_AREF(insn->chanspec)); - break; - - default: - printk("Write Config Parameter Wrong\n"); - } - - if (i_ReturnValue >= 0) - i_ReturnValue = insn->n; - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_ReadLatchRegisterStatus | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_LatchReg, | -| unsigned char *_ pb_LatchStatus) | -+----------------------------------------------------------------------------+ -| Task : Read the latch register status from selected module | -| (b_ModulNbr) and selected latch register (b_LatchReg). | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Module number to configure | -| (0 to 3) | -| unsigned char_ b_LatchReg : Selected latch register | -| 0 : for the first latch register | -| 1 : for the second latch register | -+----------------------------------------------------------------------------+ -| Output Parameters : unsigned char *_ pb_LatchStatus : Latch register status. | -| 0 : No latch occur | -| 1 : A software latch occur | -| 2 : A hardware latch occur | -| 3 : A software and hardware | -| latch occur | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: No counter module found | -| -3: Counter not initialised see function | -| "i_APCI1710_InitCounter" | -| -4: The selected latch register parameter is wrong | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_ReadLatchRegisterStatus(struct comedi_device *dev, - unsigned char b_ModulNbr, - unsigned char b_LatchReg, - unsigned char *pb_LatchStatus) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned int dw_LatchReg; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /*******************************/ - /* Test if counter initialised */ - /*******************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { - /*************************************/ - /* Test the latch register parameter */ - /*************************************/ - - if (b_LatchReg < 2) { - dw_LatchReg = inl(devpriv->s_BoardInfos. - ui_Address + (64 * b_ModulNbr)); - - *pb_LatchStatus = - (unsigned char) ((dw_LatchReg >> (b_LatchReg * - 4)) & 0x3); - } else { - /**************************************************/ - /* The selected latch register parameter is wrong */ - /**************************************************/ - - DPRINTK("The selected latch register parameter is wrong\n"); - i_ReturnValue = -4; - } - } else { - /****************************************/ - /* Counter not initialised see function */ - /* "i_APCI1710_InitCounter" */ - /****************************************/ - - DPRINTK("Counter not initialised\n"); - i_ReturnValue = -3; - } - } else { - /*************************************************/ - /* The selected module number parameter is wrong */ - /*************************************************/ - - DPRINTK("The selected module number parameter is wrong\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_ReadLatchRegisterValue | -| (unsigned char_ b_BoardHandle,| -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_LatchReg, | -| PULONG_ pul_LatchValue) | -+----------------------------------------------------------------------------+ -| Task : Read the latch register value from selected module | -| (b_ModulNbr) and selected latch register (b_LatchReg). | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Module number to configure | -| (0 to 3) | -| unsigned char_ b_LatchReg : Selected latch register | -| 0 : for the first latch register | -| 1 : for the second latch register | -+----------------------------------------------------------------------------+ -| Output Parameters : PULONG_ pul_LatchValue : Latch register value | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: No counter module found | -| -3: Counter not initialised see function | -| "i_APCI1710_InitCounter" | -| -4: The selected latch register parameter is wrong | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_ReadLatchRegisterValue(struct comedi_device *dev, - unsigned char b_ModulNbr, - unsigned char b_LatchReg, - unsigned int *pul_LatchValue) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /*******************************/ - /* Test if counter initialised */ - /*******************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { - /*************************************/ - /* Test the latch register parameter */ - /*************************************/ - - if (b_LatchReg < 2) { - *pul_LatchValue = inl(devpriv->s_BoardInfos. - ui_Address + ((b_LatchReg + 1) * 4) + - (64 * b_ModulNbr)); - - } else { - /**************************************************/ - /* The selected latch register parameter is wrong */ - /**************************************************/ - - DPRINTK("The selected latch register parameter is wrong\n"); - i_ReturnValue = -4; - } - } else { - /****************************************/ - /* Counter not initialised see function */ - /* "i_APCI1710_InitCounter" */ - /****************************************/ - - DPRINTK("Counter not initialised\n"); - i_ReturnValue = -3; - } - } else { - /*************************************************/ - /* The selected module number parameter is wrong */ - /*************************************************/ - - DPRINTK("The selected module number parameter is wrong\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_Read16BitCounterValue | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_SelectedCounter, | -| unsigned int *_ pui_CounterValue) | -+----------------------------------------------------------------------------+ -| Task : Latch the selected 16-Bit counter (b_SelectedCounter) | -| from selected module (b_ModulNbr) in to the first | -| latch register and return the latched value. | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Module number to configure | -| (0 to 3) | -| unsigned char_ b_SelectedCounter : Selected 16-Bit counter | -| (0 or 1) | -+----------------------------------------------------------------------------+ -| Output Parameters : unsigned int *_ pui_CounterValue : 16-Bit counter value | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: No counter module found | -| -3: Counter not initialised see function | -| "i_APCI1710_InitCounter" | -| -4: The selected 16-Bit counter parameter is wrong | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_Read16BitCounterValue(struct comedi_device *dev, - unsigned char b_ModulNbr, - unsigned char b_SelectedCounter, - unsigned int *pui_CounterValue) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned int dw_LathchValue = 0; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /*******************************/ - /* Test if counter initialised */ - /*******************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { - /******************************/ - /* Test the counter selection */ - /******************************/ - - if (b_SelectedCounter < 2) { - /*********************/ - /* Latch the counter */ - /*********************/ - - outl(1, devpriv->s_BoardInfos. - ui_Address + (64 * b_ModulNbr)); - - /************************/ - /* Read the latch value */ - /************************/ - - dw_LathchValue = inl(devpriv->s_BoardInfos. - ui_Address + 4 + (64 * b_ModulNbr)); - - *pui_CounterValue = - (unsigned int) ((dw_LathchValue >> (16 * - b_SelectedCounter)) & - 0xFFFFU); - } else { - /**************************************************/ - /* The selected 16-Bit counter parameter is wrong */ - /**************************************************/ - - DPRINTK("The selected 16-Bit counter parameter is wrong\n"); - i_ReturnValue = -4; - } - } else { - /****************************************/ - /* Counter not initialised see function */ - /* "i_APCI1710_InitCounter" */ - /****************************************/ - - DPRINTK("Counter not initialised\n"); - i_ReturnValue = -3; - } - } else { - /*************************************************/ - /* The selected module number parameter is wrong */ - /*************************************************/ - - DPRINTK("The selected module number parameter is wrong\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_Read32BitCounterValue | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| PULONG_ pul_CounterValue) | -+----------------------------------------------------------------------------+ -| Task : Latch the 32-Bit counter from selected module | -| (b_ModulNbr) in to the first latch register and return | -| the latched value. | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Module number to configure | -| (0 to 3) | -+----------------------------------------------------------------------------+ -| Output Parameters : PULONG_ pul_CounterValue : 32-Bit counter value | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: No counter module found | -| -3: Counter not initialised see function | -| "i_APCI1710_InitCounter" | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_Read32BitCounterValue(struct comedi_device *dev, - unsigned char b_ModulNbr, - unsigned int *pul_CounterValue) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /*******************************/ - /* Test if counter initialised */ - /*******************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { - /*********************/ - /* Tatch the counter */ - /*********************/ - - outl(1, devpriv->s_BoardInfos. - ui_Address + (64 * b_ModulNbr)); - - /************************/ - /* Read the latch value */ - /************************/ - - *pul_CounterValue = inl(devpriv->s_BoardInfos. - ui_Address + 4 + (64 * b_ModulNbr)); - } else { - /****************************************/ - /* Counter not initialised see function */ - /* "i_APCI1710_InitCounter" */ - /****************************************/ - - DPRINTK("Counter not initialised\n"); - i_ReturnValue = -3; - } - } else { - /*************************************************/ - /* The selected module number parameter is wrong */ - /*************************************************/ - - DPRINTK("The selected module number parameter is wrong\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_GetIndexStatus (unsigned char_ b_BoardHandle,| -| unsigned char_ b_ModulNbr, | -| unsigned char *_ pb_IndexStatus)| -+----------------------------------------------------------------------------+ -| Task : Return the index status | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Module number to configure | -| (0 to 3) | -+----------------------------------------------------------------------------+ -| Output Parameters : unsigned char *_ pb_IndexStatus : 0 : No INDEX occur | -| 1 : A INDEX occur | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: No counter module found | -| -3: Counter not initialised see function | -| "i_APCI1710_InitCounter" | -| -4: Index not initialised see function | -| "i_APCI1710_InitIndex" | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_GetIndexStatus(struct comedi_device *dev, - unsigned char b_ModulNbr, - unsigned char *pb_IndexStatus) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned int dw_StatusReg = 0; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /*******************************/ - /* Test if counter initialised */ - /*******************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { - /*****************************/ - /* Test if index initialised */ - /*****************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo.s_InitFlag.b_IndexInit) { - dw_StatusReg = inl(devpriv->s_BoardInfos. - ui_Address + 12 + (64 * b_ModulNbr)); - - *pb_IndexStatus = (unsigned char) (dw_StatusReg & 1); - } else { - /*************************************************************/ - /* Index not initialised see function "i_APCI1710_InitIndex" */ - /*************************************************************/ - - DPRINTK("Index not initialised\n"); - i_ReturnValue = -4; - } - } else { - /****************************************/ - /* Counter not initialised see function */ - /* "i_APCI1710_InitCounter" */ - /****************************************/ - - DPRINTK("Counter not initialised\n"); - i_ReturnValue = -3; - } - } else { - /*************************************************/ - /* The selected module number parameter is wrong */ - /*************************************************/ - - DPRINTK("The selected module number parameter is wrong\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_GetReferenceStatus | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char *_ pb_ReferenceStatus) | -+----------------------------------------------------------------------------+ -| Task : Return the reference status | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Module number to configure | -| (0 to 3) | -+----------------------------------------------------------------------------+ -| Output Parameters : unsigned char *_ pb_ReferenceStatus : 0 : No REFERENCE occur | -| 1 : A REFERENCE occur | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: No counter module found | -| -3: Counter not initialised see function | -| "i_APCI1710_InitCounter" | -| -4: Reference not initialised see function | -| "i_APCI1710_InitReference" | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_GetReferenceStatus(struct comedi_device *dev, - unsigned char b_ModulNbr, - unsigned char *pb_ReferenceStatus) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned int dw_StatusReg = 0; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /*******************************/ - /* Test if counter initialised */ - /*******************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { - /*********************************/ - /* Test if reference initialised */ - /*********************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_InitFlag.b_ReferenceInit) { - dw_StatusReg = inl(devpriv->s_BoardInfos. - ui_Address + 24 + (64 * b_ModulNbr)); - - *pb_ReferenceStatus = - (unsigned char) (~dw_StatusReg & 1); - } else { - /*********************************************************************/ - /* Reference not initialised see function "i_APCI1710_InitReference" */ - /*********************************************************************/ - - DPRINTK("Reference not initialised\n"); - i_ReturnValue = -4; - } - } else { - /****************************************/ - /* Counter not initialised see function */ - /* "i_APCI1710_InitCounter" */ - /****************************************/ - - DPRINTK("Counter not initialised\n"); - i_ReturnValue = -3; - } - } else { - /*************************************************/ - /* The selected module number parameter is wrong */ - /*************************************************/ - - DPRINTK("The selected module number parameter is wrong\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_GetUASStatus | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char *_ pb_UASStatus) | -+----------------------------------------------------------------------------+ -| Task : Return the error signal (UAS) status | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Module number to configure | -| (0 to 3) | -+----------------------------------------------------------------------------+ -| Output Parameters : unsigned char *_ pb_UASStatus : 0 : UAS is low "0" | -| 1 : UAS is high "1" | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: No counter module found | -| -3: Counter not initialised see function | -| "i_APCI1710_InitCounter" | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_GetUASStatus(struct comedi_device *dev, - unsigned char b_ModulNbr, - unsigned char *pb_UASStatus) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned int dw_StatusReg = 0; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /*******************************/ - /* Test if counter initialised */ - /*******************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { - dw_StatusReg = inl(devpriv->s_BoardInfos. - ui_Address + 24 + (64 * b_ModulNbr)); - - *pb_UASStatus = (unsigned char) ((dw_StatusReg >> 1) & 1); - } else { - /****************************************/ - /* Counter not initialised see function */ - /* "i_APCI1710_InitCounter" */ - /****************************************/ - - DPRINTK("Counter not initialised\n"); - i_ReturnValue = -3; - } - } else { - /*************************************************/ - /* The selected module number parameter is wrong */ - /*************************************************/ - - DPRINTK("The selected module number parameter is wrong\n"); - i_ReturnValue = -2; - - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_GetCBStatus | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char *_ pb_CBStatus) | -+----------------------------------------------------------------------------+ -| Task : Return the counter overflow status | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Module number to configure | -| (0 to 3) | -+----------------------------------------------------------------------------+ -| Output Parameters : unsigned char *_ pb_CBStatus : 0 : Counter no overflow | -| 1 : Counter overflow | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: No counter module found | -| -3: Counter not initialised see function | -| "i_APCI1710_InitCounter" | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_GetCBStatus(struct comedi_device *dev, - unsigned char b_ModulNbr, - unsigned char *pb_CBStatus) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned int dw_StatusReg = 0; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /*******************************/ - /* Test if counter initialised */ - /*******************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { - dw_StatusReg = inl(devpriv->s_BoardInfos. - ui_Address + 16 + (64 * b_ModulNbr)); - - *pb_CBStatus = (unsigned char) (dw_StatusReg & 1); - - } else { - /****************************************/ - /* Counter not initialised see function */ - /* "i_APCI1710_InitCounter" */ - /****************************************/ - - DPRINTK("Counter not initialised\n"); - i_ReturnValue = -3; - } - } else { - /*************************************************/ - /* The selected module number parameter is wrong */ - /*************************************************/ - - DPRINTK("The selected module number parameter is wrong\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_Get16BitCBStatus | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char *_ pb_CBStatusCounter0, | -| unsigned char *_ pb_CBStatusCounter1) | -+----------------------------------------------------------------------------+ -| Task : Returns the counter overflow (counter initialised to | -| 2*16-bit) status from selected incremental counter | -| module | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Module number to configure | -| (0 to 3) | -+----------------------------------------------------------------------------+ -| Output Parameters : unsigned char *_ pb_CBStatusCounter0 : 0 : No overflow occur for | -| the first 16-bit | -| counter | -| 1 : Overflow occur for the| -| first 16-bit counter | -| unsigned char *_ pb_CBStatusCounter1 : 0 : No overflow occur for | -| the second 16-bit | -| counter | -| 1 : Overflow occur for the| -| second 16-bit counter | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: No counter module found | -| -3: Counter not initialised see function | -| "i_APCI1710_InitCounter" | -| -4: Counter not initialised to 2*16-bit mode. | -| See function "i_APCI1710_InitCounter" | -| -5: Firmware revision error | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_Get16BitCBStatus(struct comedi_device *dev, - unsigned char b_ModulNbr, - unsigned char *pb_CBStatusCounter0, - unsigned char *pb_CBStatusCounter1) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned int dw_StatusReg = 0; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /*******************************/ - /* Test if counter initialised */ - /*******************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { - /*************************/ - /* Test if 2*16-Bit mode */ - /*************************/ - - if ((devpriv->s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister1 & 0x10) == 0x10) { - /*****************************/ - /* Test the Firmware version */ - /*****************************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration - [b_ModulNbr] & 0xFFFF) >= - 0x3136) { - dw_StatusReg = - inl(devpriv->s_BoardInfos. - ui_Address + 16 + - (64 * b_ModulNbr)); - - *pb_CBStatusCounter1 = - (unsigned char) ((dw_StatusReg >> 0) & - 1); - *pb_CBStatusCounter0 = - (unsigned char) ((dw_StatusReg >> 1) & - 1); - } /* if ((ps_APCI1710Variable->s_Board [b_BoardHandle].s_BoardInfos.dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3136) */ - else { - /****************************/ - /* Firmware revision error */ - /****************************/ - - i_ReturnValue = -5; - } /* if ((ps_APCI1710Variable->s_Board [b_BoardHandle].s_BoardInfos.dw_MolduleConfiguration [b_ModulNbr] & 0xFFFF) >= 0x3136) */ - } /* if ((ps_APCI1710Variable->s_Board [b_BoardHandle].s_ModuleInfo [b_ModulNbr].s_SiemensCounterInfo.s_ModeRegister.s_ByteModeRegister.b_ModeRegister1 & 0x10) == 0x10) */ - else { - /********************************************/ - /* Counter not initialised to 2*16-bit mode */ - /* "i_APCI1710_InitCounter" */ - /********************************************/ - - DPRINTK("Counter not initialised\n"); - i_ReturnValue = -4; - } /* if ((ps_APCI1710Variable->s_Board [b_BoardHandle].s_ModuleInfo [b_ModulNbr].s_SiemensCounterInfo.s_ModeRegister.s_ByteModeRegister.b_ModeRegister1 & 0x10) == 0x10) */ - } /* if (ps_APCI1710Variable->s_Board [b_BoardHandle].s_ModuleInfo [b_ModulNbr].s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) */ - else { - /****************************************/ - /* Counter not initialised see function */ - /* "i_APCI1710_InitCounter" */ - /****************************************/ - - DPRINTK("Counter not initialised\n"); - i_ReturnValue = -3; - } /* if (ps_APCI1710Variable->s_Board [b_BoardHandle].s_ModuleInfo [b_ModulNbr].s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) */ - } /* if (b_ModulNbr < 4) */ - else { - /*************************************************/ - /* The selected module number parameter is wrong */ - /*************************************************/ - - DPRINTK("The selected module number parameter is wrong\n"); - i_ReturnValue = -2; - } /* if (b_ModulNbr < 4) */ - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_GetUDStatus | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char *_ pb_UDStatus) | -+----------------------------------------------------------------------------+ -| Task : Return the counter progress status | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Module number to configure | -| (0 to 3) | -+----------------------------------------------------------------------------+ -| Output Parameters : unsigned char *_ pb_UDStatus : 0 : Counter progress in the | -| selected mode down | -| 1 : Counter progress in the | -| selected mode up | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: No counter module found | -| -3: Counter not initialised see function | -| "i_APCI1710_InitCounter" | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_GetUDStatus(struct comedi_device *dev, - unsigned char b_ModulNbr, - unsigned char *pb_UDStatus) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned int dw_StatusReg = 0; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /*******************************/ - /* Test if counter initialised */ - /*******************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { - dw_StatusReg = inl(devpriv->s_BoardInfos. - ui_Address + 24 + (64 * b_ModulNbr)); - - *pb_UDStatus = (unsigned char) ((dw_StatusReg >> 2) & 1); - - } else { - /****************************************/ - /* Counter not initialised see function */ - /* "i_APCI1710_InitCounter" */ - /****************************************/ - - DPRINTK("Counter not initialised\n"); - i_ReturnValue = -3; - } - } else { - /*************************************************/ - /* The selected module number parameter is wrong */ - /*************************************************/ - - DPRINTK("The selected module number parameter is wrong\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_GetInterruptUDLatchedStatus | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char *_ pb_UDStatus) | -+----------------------------------------------------------------------------+ -| Task : Return the counter progress latched status after a | -| index interrupt occur. | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Module number to configure | -| (0 to 3) | -+----------------------------------------------------------------------------+ -| Output Parameters : unsigned char *_ pb_UDStatus : 0 : Counter progress in the | -| selected mode down | -| 1 : Counter progress in the | -| selected mode up | -| 2 : No index interrupt occur | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: No counter module found | -| -3: Counter not initialised see function | -| "i_APCI1710_InitCounter" | -| -4: Interrupt function not initialised. | -| See function "i_APCI1710_SetBoardIntRoutineX" | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_GetInterruptUDLatchedStatus(struct comedi_device *dev, - unsigned char b_ModulNbr, - unsigned char *pb_UDStatus) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned int dw_StatusReg = 0; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /*******************************/ - /* Test if counter initialised */ - /*******************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { - /*********************************/ - /* Test if index interrupt occur */ - /*********************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_InitFlag.b_IndexInterruptOccur == 1) { - devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_InitFlag.b_IndexInterruptOccur = 0; - - dw_StatusReg = inl(devpriv->s_BoardInfos. - ui_Address + 12 + (64 * b_ModulNbr)); - - *pb_UDStatus = (unsigned char) ((dw_StatusReg >> 1) & 1); - } else { - /****************************/ - /* No index interrupt occur */ - /****************************/ - - *pb_UDStatus = 2; - } - } else { - /****************************************/ - /* Counter not initialised see function */ - /* "i_APCI1710_InitCounter" */ - /****************************************/ - - DPRINTK("Counter not initialised\n"); - i_ReturnValue = -3; - } - } else { - /*************************************************/ - /* The selected module number parameter is wrong */ - /*************************************************/ - - DPRINTK("The selected module number parameter is wrong\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - - /* - +----------------------------------------------------------------------------+ - | Function Name : _INT_ i_APCI1710_ReadFrequencyMeasurement | - | (unsigned char_ b_BoardHandle, | - | unsigned char_ b_ModulNbr, | - | unsigned char *_ pb_Status, | - | PULONG_ pul_ReadValue) | - +----------------------------------------------------------------------------+ - | Task : Returns the status (pb_Status) and the number of | - | increments in the set time. | - | See function " i_APCI1710_InitFrequencyMeasurement " | - +----------------------------------------------------------------------------+ - | Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | - | unsigned char_ b_ModulNbr : Number of the module to be | - | configured (0 to 3) | - +----------------------------------------------------------------------------+ - | Output Parameters : unsigned char *_ pb_Status : Returns the frequency | - | measurement status | - | 0 : Counting cycle not | - | started. | - | 1 : Counting cycle started. | - | 2 : Counting cycle stopped. | - | The measurement cycle is | - | completed. | - | unsigned char *_ pb_UDStatus : 0 : Counter progress in the | - | selected mode down | - | 1 : Counter progress in the | - | selected mode up | - | PULONG_ pul_ReadValue : Return the number of | - | increments in the defined | - | time base. | - +----------------------------------------------------------------------------+ - | Return Value : 0: No error | - | -1: The handle parameter of the board is wrong | - | -2: The selected module number is wrong | - | -3: Counter not initialised see function | - | "i_APCI1710_InitCounter" | - | -4: Frequency measurement logic not initialised. | - | See function "i_APCI1710_InitFrequencyMeasurement" | - +----------------------------------------------------------------------------+ - */ -static int i_APCI1710_ReadFrequencyMeasurement(struct comedi_device *dev, - unsigned char b_ModulNbr, - unsigned char *pb_Status, - unsigned char *pb_UDStatus, - unsigned int *pul_ReadValue) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned int ui_16BitValue; - unsigned int dw_StatusReg; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /*******************************/ - /* Test if counter initialised */ - /*******************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo.s_InitFlag.b_CounterInit == 1) { - /********************************************/ - /* Test if frequency measurement initialised */ - /********************************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_InitFlag.b_FrequencyMeasurementInit == 1) { - /******************/ - /* Test if enable */ - /******************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SiemensCounterInfo. - s_InitFlag. - b_FrequencyMeasurementEnable == 1) { - /*******************/ - /* Read the status */ - /*******************/ - - dw_StatusReg = - inl(devpriv->s_BoardInfos. - ui_Address + 32 + - (64 * b_ModulNbr)); - - /**************************/ - /* Test if frequency stop */ - /**************************/ - - if (dw_StatusReg & 1) { - *pb_Status = 2; - *pb_UDStatus = - (unsigned char) ((dw_StatusReg >> - 1) & 3); - - /******************/ - /* Read the value */ - /******************/ - - *pul_ReadValue = - inl(devpriv-> - s_BoardInfos. - ui_Address + 28 + - (64 * b_ModulNbr)); - - if (*pb_UDStatus == 0) { - /*************************/ - /* Test the counter mode */ - /*************************/ - - if ((devpriv->s_ModuleInfo[b_ModulNbr].s_SiemensCounterInfo.s_ModeRegister.s_ByteModeRegister.b_ModeRegister1 & APCI1710_16BIT_COUNTER) == APCI1710_16BIT_COUNTER) { - /****************************************/ - /* Test if 16-bit counter 1 pulse occur */ - /****************************************/ - - if ((*pul_ReadValue & 0xFFFFU) != 0) { - ui_16BitValue - = - (unsigned int) - * - pul_ReadValue - & - 0xFFFFU; - *pul_ReadValue - = - (*pul_ReadValue - & - 0xFFFF0000UL) - | - (0xFFFFU - - - ui_16BitValue); - } - - /****************************************/ - /* Test if 16-bit counter 2 pulse occur */ - /****************************************/ - - if ((*pul_ReadValue & 0xFFFF0000UL) != 0) { - ui_16BitValue - = - (unsigned int) - ( - (*pul_ReadValue - >> - 16) - & - 0xFFFFU); - *pul_ReadValue - = - (*pul_ReadValue - & - 0xFFFFUL) - | - ( - (0xFFFFU - ui_16BitValue) << 16); - } - } else { - if (*pul_ReadValue != 0) { - *pul_ReadValue - = - 0xFFFFFFFFUL - - - *pul_ReadValue; - } - } - } else { - if (*pb_UDStatus == 1) { - /****************************************/ - /* Test if 16-bit counter 2 pulse occur */ - /****************************************/ - - if ((*pul_ReadValue & 0xFFFF0000UL) != 0) { - ui_16BitValue - = - (unsigned int) - ( - (*pul_ReadValue - >> - 16) - & - 0xFFFFU); - *pul_ReadValue - = - (*pul_ReadValue - & - 0xFFFFUL) - | - ( - (0xFFFFU - ui_16BitValue) << 16); - } - } else { - if (*pb_UDStatus - == 2) { - /****************************************/ - /* Test if 16-bit counter 1 pulse occur */ - /****************************************/ - - if ((*pul_ReadValue & 0xFFFFU) != 0) { - ui_16BitValue - = - (unsigned int) - * - pul_ReadValue - & - 0xFFFFU; - *pul_ReadValue - = - (*pul_ReadValue - & - 0xFFFF0000UL) - | - (0xFFFFU - - - ui_16BitValue); - } - } - } - } - } else { - *pb_Status = 1; - *pb_UDStatus = 0; - } - } else { - *pb_Status = 0; - *pb_UDStatus = 0; - } - } else { - /***********************************************/ - /* Frequency measurement logic not initialised */ - /***********************************************/ - - DPRINTK("Frequency measurement logic not initialised\n"); - i_ReturnValue = -4; - } - } else { - /****************************************/ - /* Counter not initialised see function */ - /* "i_APCI1710_InitCounter" */ - /****************************************/ - - DPRINTK("Counter not initialised\n"); - i_ReturnValue = -3; - } - } else { - /*************************************************/ - /* The selected module number parameter is wrong */ - /*************************************************/ - - DPRINTK("The selected module number parameter is wrong\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} -/* - * Read and Get functions for INC_CPT - */ -static int i_APCI1710_InsnReadINCCPT(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct addi_private *devpriv = dev->private; - unsigned int ui_ReadType; - int i_ReturnValue = 0; - - ui_ReadType = CR_CHAN(insn->chanspec); - - devpriv->tsk_Current = current; /* Save the current process task structure */ - switch (ui_ReadType) { - case APCI1710_INCCPT_READLATCHREGISTERSTATUS: - i_ReturnValue = i_APCI1710_ReadLatchRegisterStatus(dev, - (unsigned char) CR_AREF(insn->chanspec), - (unsigned char) CR_RANGE(insn->chanspec), (unsigned char *) &data[0]); - break; - - case APCI1710_INCCPT_READLATCHREGISTERVALUE: - i_ReturnValue = i_APCI1710_ReadLatchRegisterValue(dev, - (unsigned char) CR_AREF(insn->chanspec), - (unsigned char) CR_RANGE(insn->chanspec), (unsigned int *) &data[0]); - printk("Latch Register Value %d\n", data[0]); - break; - - case APCI1710_INCCPT_READ16BITCOUNTERVALUE: - i_ReturnValue = i_APCI1710_Read16BitCounterValue(dev, - (unsigned char) CR_AREF(insn->chanspec), - (unsigned char) CR_RANGE(insn->chanspec), (unsigned int *) &data[0]); - break; - - case APCI1710_INCCPT_READ32BITCOUNTERVALUE: - i_ReturnValue = i_APCI1710_Read32BitCounterValue(dev, - (unsigned char) CR_AREF(insn->chanspec), (unsigned int *) &data[0]); - break; - - case APCI1710_INCCPT_GETINDEXSTATUS: - i_ReturnValue = i_APCI1710_GetIndexStatus(dev, - (unsigned char) CR_AREF(insn->chanspec), (unsigned char *) &data[0]); - break; - - case APCI1710_INCCPT_GETREFERENCESTATUS: - i_ReturnValue = i_APCI1710_GetReferenceStatus(dev, - (unsigned char) CR_AREF(insn->chanspec), (unsigned char *) &data[0]); - break; - - case APCI1710_INCCPT_GETUASSTATUS: - i_ReturnValue = i_APCI1710_GetUASStatus(dev, - (unsigned char) CR_AREF(insn->chanspec), (unsigned char *) &data[0]); - break; - - case APCI1710_INCCPT_GETCBSTATUS: - i_ReturnValue = i_APCI1710_GetCBStatus(dev, - (unsigned char) CR_AREF(insn->chanspec), (unsigned char *) &data[0]); - break; - - case APCI1710_INCCPT_GET16BITCBSTATUS: - i_ReturnValue = i_APCI1710_Get16BitCBStatus(dev, - (unsigned char) CR_AREF(insn->chanspec), - (unsigned char *) &data[0], (unsigned char *) &data[1]); - break; - - case APCI1710_INCCPT_GETUDSTATUS: - i_ReturnValue = i_APCI1710_GetUDStatus(dev, - (unsigned char) CR_AREF(insn->chanspec), (unsigned char *) &data[0]); - - break; - - case APCI1710_INCCPT_GETINTERRUPTUDLATCHEDSTATUS: - i_ReturnValue = i_APCI1710_GetInterruptUDLatchedStatus(dev, - (unsigned char) CR_AREF(insn->chanspec), (unsigned char *) &data[0]); - break; - - case APCI1710_INCCPT_READFREQUENCYMEASUREMENT: - i_ReturnValue = i_APCI1710_ReadFrequencyMeasurement(dev, - (unsigned char) CR_AREF(insn->chanspec), - (unsigned char *) &data[0], - (unsigned char *) &data[1], (unsigned int *) &data[2]); - break; - - case APCI1710_INCCPT_READINTERRUPT: - data[0] = devpriv->s_InterruptParameters. - s_FIFOInterruptParameters[devpriv-> - s_InterruptParameters.ui_Read].b_OldModuleMask; - data[1] = devpriv->s_InterruptParameters. - s_FIFOInterruptParameters[devpriv-> - s_InterruptParameters.ui_Read].ul_OldInterruptMask; - data[2] = devpriv->s_InterruptParameters. - s_FIFOInterruptParameters[devpriv-> - s_InterruptParameters.ui_Read].ul_OldCounterLatchValue; - - /**************************/ - /* Increment the read FIFO */ - /***************************/ - - devpriv-> - s_InterruptParameters. - ui_Read = (devpriv->s_InterruptParameters. - ui_Read + 1) % APCI1710_SAVE_INTERRUPT; - - break; - - default: - printk("ReadType Parameter wrong\n"); - } - - if (i_ReturnValue >= 0) - i_ReturnValue = insn->n; - return i_ReturnValue; - -} diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c deleted file mode 100644 index 6bbcb06cc279..000000000000 --- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c +++ /dev/null @@ -1,866 +0,0 @@ -/** -@verbatim - -Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. - - ADDI-DATA GmbH - Dieselstrasse 3 - D-77833 Ottersweier - Tel: +19(0)7223/9493-0 - Fax: +49(0)7223/9493-92 - http://www.addi-data.com - info@addi-data.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. - -@endverbatim -*/ -/* - - +-----------------------------------------------------------------------+ - | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier | - +-----------------------------------------------------------------------+ - | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | - | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | - +-----------------------------------------------------------------------+ - | Project : API APCI1710 | Compiler : gcc | - | Module name : Inp_CPT.C | Version : 2.96 | - +-------------------------------+---------------------------------------+ - | Project manager: Eric Stolz | Date : 02/12/2002 | - +-----------------------------------------------------------------------+ - | Description : APCI-1710 pulse encoder module | - | | - | | - +-----------------------------------------------------------------------+ - | UPDATES | - +-----------------------------------------------------------------------+ - | Date | Author | Description of updates | - +----------+-----------+------------------------------------------------+ - | | | | - |----------|-----------|------------------------------------------------| - | 08/05/00 | Guinot C | - 0400/0228 All Function in RING 0 | - | | | available | - +-----------------------------------------------------------------------+ -*/ - -#define APCI1710_SINGLE 0 -#define APCI1710_CONTINUOUS 1 - -#define APCI1710_PULSEENCODER_READ 0 -#define APCI1710_PULSEENCODER_WRITE 1 - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_InitPulseEncoder | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_PulseEncoderNbr, | -| unsigned char_ b_InputLevelSelection, | -| unsigned char_ b_TriggerOutputAction, | -| ULONG_ ul_StartValue) | -+----------------------------------------------------------------------------+ -| Task : Configure the pulse encoder operating mode selected via| -| b_ModulNbr and b_PulseEncoderNbr. The pulse encoder | -| after each pulse decrement the counter value from 1. | -| | -| You must calling this function be for you call any | -| other function witch access of pulse encoders. | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710| -| unsigned char_ b_ModulNbr : Module number to | -| configure (0 to 3) | -| unsigned char_ b_PulseEncoderNbr : Pulse encoder selection | -| (0 to 3) | -| unsigned char_ b_InputLevelSelection : Input level selection | -| (0 or 1) | -| 0 : Set pulse encoder| -| count the the low| -| level pulse. | -| 1 : Set pulse encoder| -| count the the | -| high level pulse.| -| unsigned char_ b_TriggerOutputAction : Digital TRIGGER output | -| action | -| 0 : No action | -| 1 : Set the trigger | -| output to "1" | -| (high) after the | -| passage from 1 to| -| 0 from pulse | -| encoder. | -| 2 : Set the trigger | -| output to "0" | -| (low) after the | -| passage from 1 to| -| 0 from pulse | -| encoder | -| ULONG_ ul_StartValue : Pulse encoder start value| -| (1 to 4294967295) - b_ModulNbr =(unsigned char) CR_AREF(insn->chanspec); - b_PulseEncoderNbr =(unsigned char) data[0]; - b_InputLevelSelection =(unsigned char) data[1]; - b_TriggerOutputAction =(unsigned char) data[2]; - ul_StartValue =(unsigned int) data[3]; - | -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: The module is not a pulse encoder module | -| -3: Pulse encoder selection is wrong | -| -4: Input level selection is wrong | -| -5: Digital TRIGGER output action selection is wrong | -| -6: Pulse encoder start value is wrong | -+----------------------------------------------------------------------------+ -*/ - -static int i_APCI1710_InsnConfigInitPulseEncoder(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned int dw_IntRegister; - unsigned char b_ModulNbr; - unsigned char b_PulseEncoderNbr; - unsigned char b_InputLevelSelection; - unsigned char b_TriggerOutputAction; - unsigned int ul_StartValue; - - b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec); - b_PulseEncoderNbr = (unsigned char) data[0]; - b_InputLevelSelection = (unsigned char) data[1]; - b_TriggerOutputAction = (unsigned char) data[2]; - ul_StartValue = (unsigned int) data[3]; - - i_ReturnValue = insn->n; - - /***********************************/ - /* Test the selected module number */ - /***********************************/ - - if (b_ModulNbr <= 3) { - /*************************/ - /* Test if pulse encoder */ - /*************************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModulNbr] & - APCI1710_PULSE_ENCODER) == - APCI1710_PULSE_ENCODER) { - /******************************************/ - /* Test the selected pulse encoder number */ - /******************************************/ - - if (b_PulseEncoderNbr <= 3) { - /************************/ - /* Test the input level */ - /************************/ - - if ((b_InputLevelSelection == 0) - || (b_InputLevelSelection == 1)) { - /*******************************************/ - /* Test the ouput TRIGGER action selection */ - /*******************************************/ - - if ((b_TriggerOutputAction <= 2) - || (b_PulseEncoderNbr > 0)) { - if (ul_StartValue > 1) { - - dw_IntRegister = - inl(devpriv-> - s_BoardInfos. - ui_Address + - 20 + - (64 * b_ModulNbr)); - - /***********************/ - /* Set the start value */ - /***********************/ - - outl(ul_StartValue, - devpriv-> - s_BoardInfos. - ui_Address + - (b_PulseEncoderNbr - * 4) + - (64 * b_ModulNbr)); - - /***********************/ - /* Set the input level */ - /***********************/ - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_PulseEncoderModuleInfo. - dw_SetRegister = - (devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_PulseEncoderModuleInfo. - dw_SetRegister & - (0xFFFFFFFFUL - - (1UL << (8 + b_PulseEncoderNbr)))) | ((1UL & (~b_InputLevelSelection)) << (8 + b_PulseEncoderNbr)); - - /*******************************/ - /* Test if output trigger used */ - /*******************************/ - - if ((b_TriggerOutputAction > 0) && (b_PulseEncoderNbr > 1)) { - /****************************/ - /* Enable the output action */ - /****************************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_PulseEncoderModuleInfo. - dw_SetRegister - = - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_PulseEncoderModuleInfo. - dw_SetRegister - | (1UL - << (4 + b_PulseEncoderNbr)); - - /*********************************/ - /* Set the output TRIGGER action */ - /*********************************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_PulseEncoderModuleInfo. - dw_SetRegister - = - (devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_PulseEncoderModuleInfo. - dw_SetRegister - & - (0xFFFFFFFFUL - - - (1UL << (12 + b_PulseEncoderNbr)))) | ((1UL & (b_TriggerOutputAction - 1)) << (12 + b_PulseEncoderNbr)); - } else { - /*****************************/ - /* Disable the output action */ - /*****************************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_PulseEncoderModuleInfo. - dw_SetRegister - = - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_PulseEncoderModuleInfo. - dw_SetRegister - & - (0xFFFFFFFFUL - - - (1UL << (4 + b_PulseEncoderNbr))); - } - - /*************************/ - /* Set the configuration */ - /*************************/ - - outl(devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_PulseEncoderModuleInfo. - dw_SetRegister, - devpriv-> - s_BoardInfos. - ui_Address + - 20 + - (64 * b_ModulNbr)); - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_PulseEncoderModuleInfo. - s_PulseEncoderInfo - [b_PulseEncoderNbr]. - b_PulseEncoderInit - = 1; - } else { - /**************************************/ - /* Pulse encoder start value is wrong */ - /**************************************/ - - DPRINTK("Pulse encoder start value is wrong\n"); - i_ReturnValue = -6; - } - } else { - /****************************************************/ - /* Digital TRIGGER output action selection is wrong */ - /****************************************************/ - - DPRINTK("Digital TRIGGER output action selection is wrong\n"); - i_ReturnValue = -5; - } - } else { - /**********************************/ - /* Input level selection is wrong */ - /**********************************/ - - DPRINTK("Input level selection is wrong\n"); - i_ReturnValue = -4; - } - } else { - /************************************/ - /* Pulse encoder selection is wrong */ - /************************************/ - - DPRINTK("Pulse encoder selection is wrong\n"); - i_ReturnValue = -3; - } - } else { - /********************************************/ - /* The module is not a pulse encoder module */ - /********************************************/ - - DPRINTK("The module is not a pulse encoder module\n"); - i_ReturnValue = -2; - } - } else { - /********************************************/ - /* The module is not a pulse encoder module */ - /********************************************/ - - DPRINTK("The module is not a pulse encoder module\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_EnablePulseEncoder | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_PulseEncoderNbr, | -| unsigned char_ b_CycleSelection, | -| unsigned char_ b_InterruptHandling) | -+----------------------------------------------------------------------------+ -| Task : Enableor disable the selected pulse encoder (b_PulseEncoderNbr) | -| from selected module (b_ModulNbr). Each input pulse | -| decrement the pulse encoder counter value from 1. | -| If you enabled the interrupt (b_InterruptHandling), a | -| interrupt is generated when the pulse encoder has run | -| down. | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710| -| unsigned char_ b_ModulNbr : Module number to | -| configure (0 to 3) | -| unsigned char_ b_PulseEncoderNbr : Pulse encoder selection | -| (0 to 3) | -| unsigned char_ b_CycleSelection : APCI1710_CONTINUOUS: | -| Each time the | -| counting value is set| -| on "0", the pulse | -| encoder load the | -| start value after | -| the next pulse. | -| APCI1710_SINGLE: | -| If the counter is set| -| on "0", the pulse | -| encoder is stopped. | -| unsigned char_ b_InterruptHandling : Interrupts can be | -| generated, when the pulse| -| encoder has run down. | -| With this parameter the | -| user decides if | -| interrupts are used or | -| not. | -| APCI1710_ENABLE: | -| Interrupts are enabled | -| APCI1710_DISABLE: | -| Interrupts are disabled - - b_ModulNbr =(unsigned char) CR_AREF(insn->chanspec); - b_Action =(unsigned char) data[0]; - b_PulseEncoderNbr =(unsigned char) data[1]; - b_CycleSelection =(unsigned char) data[2]; - b_InterruptHandling =(unsigned char) data[3];| -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: Module selection is wrong | -| -3: Pulse encoder selection is wrong | -| -4: Pulse encoder not initialised. | -| See function "i_APCI1710_InitPulseEncoder" | -| -5: Cycle selection mode is wrong | -| -6: Interrupt handling mode is wrong | -| -7: Interrupt routine not installed. | -| See function "i_APCI1710_SetBoardIntRoutineX" | -+----------------------------------------------------------------------------+ -*/ - -static int i_APCI1710_InsnWriteEnableDisablePulseEncoder(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned char b_ModulNbr; - unsigned char b_PulseEncoderNbr; - unsigned char b_CycleSelection; - unsigned char b_InterruptHandling; - unsigned char b_Action; - - i_ReturnValue = insn->n; - b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec); - b_Action = (unsigned char) data[0]; - b_PulseEncoderNbr = (unsigned char) data[1]; - b_CycleSelection = (unsigned char) data[2]; - b_InterruptHandling = (unsigned char) data[3]; - - /***********************************/ - /* Test the selected module number */ - /***********************************/ - - if (b_ModulNbr <= 3) { - /******************************************/ - /* Test the selected pulse encoder number */ - /******************************************/ - - if (b_PulseEncoderNbr <= 3) { - /*************************************/ - /* Test if pulse encoder initialised */ - /*************************************/ - - if (devpriv->s_ModuleInfo[b_ModulNbr]. - s_PulseEncoderModuleInfo. - s_PulseEncoderInfo[b_PulseEncoderNbr]. - b_PulseEncoderInit == 1) { - switch (b_Action) { - - case APCI1710_ENABLE: - /****************************/ - /* Test the cycle selection */ - /****************************/ - - if (b_CycleSelection == - APCI1710_CONTINUOUS - || b_CycleSelection == - APCI1710_SINGLE) { - /*******************************/ - /* Test the interrupt handling */ - /*******************************/ - - if (b_InterruptHandling == - APCI1710_ENABLE - || b_InterruptHandling - == APCI1710_DISABLE) { - /******************************/ - /* Test if interrupt not used */ - /******************************/ - - if (b_InterruptHandling - == - APCI1710_DISABLE) - { - /*************************/ - /* Disable the interrupt */ - /*************************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_PulseEncoderModuleInfo. - dw_SetRegister - = - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_PulseEncoderModuleInfo. - dw_SetRegister - & - (0xFFFFFFFFUL - - - (1UL << b_PulseEncoderNbr)); - } else { - - /************************/ - /* Enable the interrupt */ - /************************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_PulseEncoderModuleInfo. - dw_SetRegister - = - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_PulseEncoderModuleInfo. - dw_SetRegister - | (1UL - << - b_PulseEncoderNbr); - devpriv->tsk_Current = current; /* Save the current process task structure */ - - } - - if (i_ReturnValue >= 0) { - /***********************************/ - /* Enable or disable the interrupt */ - /***********************************/ - - outl(devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_PulseEncoderModuleInfo. - dw_SetRegister, - devpriv-> - s_BoardInfos. - ui_Address - + 20 + - (64 * b_ModulNbr)); - - /****************************/ - /* Enable the pulse encoder */ - /****************************/ - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_PulseEncoderModuleInfo. - dw_ControlRegister - = - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_PulseEncoderModuleInfo. - dw_ControlRegister - | (1UL - << - b_PulseEncoderNbr); - - /**********************/ - /* Set the cycle mode */ - /**********************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_PulseEncoderModuleInfo. - dw_ControlRegister - = - (devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_PulseEncoderModuleInfo. - dw_ControlRegister - & - (0xFFFFFFFFUL - - - (1 << (b_PulseEncoderNbr + 4)))) | ((b_CycleSelection & 1UL) << (4 + b_PulseEncoderNbr)); - - /****************************/ - /* Enable the pulse encoder */ - /****************************/ - - outl(devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_PulseEncoderModuleInfo. - dw_ControlRegister, - devpriv-> - s_BoardInfos. - ui_Address - + 16 + - (64 * b_ModulNbr)); - } - } else { - /************************************/ - /* Interrupt handling mode is wrong */ - /************************************/ - - DPRINTK("Interrupt handling mode is wrong\n"); - i_ReturnValue = -6; - } - } else { - /*********************************/ - /* Cycle selection mode is wrong */ - /*********************************/ - - DPRINTK("Cycle selection mode is wrong\n"); - i_ReturnValue = -5; - } - break; - - case APCI1710_DISABLE: - devpriv->s_ModuleInfo[b_ModulNbr]. - s_PulseEncoderModuleInfo. - dw_ControlRegister = - devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_PulseEncoderModuleInfo. - dw_ControlRegister & - (0xFFFFFFFFUL - - (1UL << b_PulseEncoderNbr)); - - /*****************************/ - /* Disable the pulse encoder */ - /*****************************/ - - outl(devpriv->s_ModuleInfo[b_ModulNbr]. - s_PulseEncoderModuleInfo. - dw_ControlRegister, - devpriv->s_BoardInfos. - ui_Address + 16 + - (64 * b_ModulNbr)); - - break; - } /* switch End */ - - } else { - /*********************************/ - /* Pulse encoder not initialised */ - /*********************************/ - - DPRINTK("Pulse encoder not initialised\n"); - i_ReturnValue = -4; - } - } else { - /************************************/ - /* Pulse encoder selection is wrong */ - /************************************/ - - DPRINTK("Pulse encoder selection is wrong\n"); - i_ReturnValue = -3; - } - } else { - /*****************************/ - /* Module selection is wrong */ - /*****************************/ - - DPRINTK("Module selection is wrong\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_ReadPulseEncoderStatus | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_PulseEncoderNbr, | -| unsigned char *_ pb_Status) | -+----------------------------------------------------------------------------+ -| Task APCI1710_PULSEENCODER_READ : Reads the pulse encoder status - and valuefrom selected pulse | -| encoder (b_PulseEncoderNbr) from selected module | -| (b_ModulNbr). | -+----------------------------------------------------------------------------+ - unsigned char b_Type; data[0] - APCI1710_PULSEENCODER_WRITE - Writes a 32-bit value (ul_WriteValue) into the selected| -| pulse encoder (b_PulseEncoderNbr) from selected module | -| (b_ModulNbr). This operation set the new start pulse | -| encoder value. - APCI1710_PULSEENCODER_READ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710| -| CRAREF() unsigned char_ b_ModulNbr : Module number to | -| configure (0 to 3) | -| data[1] unsigned char_ b_PulseEncoderNbr : Pulse encoder selection | -| (0 to 3) - APCI1710_PULSEENCODER_WRITE - data[2] ULONG_ ul_WriteValue : 32-bit value to be | -| written | -+----------------------------------------------------------------------------+ -| Output Parameters : unsigned char *_ pb_Status : Pulse encoder status. | -| 0 : No overflow occur| -| 1 : Overflow occur - PULONG_ pul_ReadValue : Pulse encoder value | | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: Module selection is wrong | -| -3: Pulse encoder selection is wrong | -| -4: Pulse encoder not initialised. | -| See function "i_APCI1710_InitPulseEncoder" | -+----------------------------------------------------------------------------+ -*/ - -/*_INT_ i_APCI1710_ReadPulseEncoderStatus (unsigned char_ b_BoardHandle, - unsigned char_ b_ModulNbr, - unsigned char_ b_PulseEncoderNbr, - - unsigned char *_ pb_Status) - */ -static int i_APCI1710_InsnBitsReadWritePulseEncoder(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned int dw_StatusRegister; - unsigned char b_ModulNbr; - unsigned char b_PulseEncoderNbr; - unsigned char *pb_Status; - unsigned char b_Type; - unsigned int *pul_ReadValue; - unsigned int ul_WriteValue; - - i_ReturnValue = insn->n; - b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec); - b_Type = (unsigned char) data[0]; - b_PulseEncoderNbr = (unsigned char) data[1]; - pb_Status = (unsigned char *) &data[0]; - pul_ReadValue = (unsigned int *) &data[1]; - - /***********************************/ - /* Test the selected module number */ - /***********************************/ - - if (b_ModulNbr <= 3) { - /******************************************/ - /* Test the selected pulse encoder number */ - /******************************************/ - - if (b_PulseEncoderNbr <= 3) { - /*************************************/ - /* Test if pulse encoder initialised */ - /*************************************/ - - if (devpriv->s_ModuleInfo[b_ModulNbr]. - s_PulseEncoderModuleInfo. - s_PulseEncoderInfo[b_PulseEncoderNbr]. - b_PulseEncoderInit == 1) { - - switch (b_Type) { - case APCI1710_PULSEENCODER_READ: - /****************************/ - /* Read the status register */ - /****************************/ - - dw_StatusRegister = - inl(devpriv->s_BoardInfos. - ui_Address + 16 + - (64 * b_ModulNbr)); - - devpriv->s_ModuleInfo[b_ModulNbr]. - s_PulseEncoderModuleInfo. - dw_StatusRegister = devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_PulseEncoderModuleInfo. - dw_StatusRegister | - dw_StatusRegister; - - *pb_Status = - (unsigned char) (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_PulseEncoderModuleInfo. - dw_StatusRegister >> (1 + - b_PulseEncoderNbr)) & 1; - - devpriv->s_ModuleInfo[b_ModulNbr]. - s_PulseEncoderModuleInfo. - dw_StatusRegister = - devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_PulseEncoderModuleInfo. - dw_StatusRegister & - (0xFFFFFFFFUL - (1 << (1 + - b_PulseEncoderNbr))); - - /******************/ - /* Read the value */ - /******************/ - - *pul_ReadValue = - inl(devpriv->s_BoardInfos. - ui_Address + - (4 * b_PulseEncoderNbr) + - (64 * b_ModulNbr)); - break; - - case APCI1710_PULSEENCODER_WRITE: - ul_WriteValue = (unsigned int) data[2]; - /*******************/ - /* Write the value */ - /*******************/ - - outl(ul_WriteValue, - devpriv->s_BoardInfos. - ui_Address + - (4 * b_PulseEncoderNbr) + - (64 * b_ModulNbr)); - - } /* end of switch */ - } else { - /*********************************/ - /* Pulse encoder not initialised */ - /*********************************/ - - DPRINTK("Pulse encoder not initialised\n"); - i_ReturnValue = -4; - } - } else { - /************************************/ - /* Pulse encoder selection is wrong */ - /************************************/ - - DPRINTK("Pulse encoder selection is wrong\n"); - i_ReturnValue = -3; - } - } else { - /*****************************/ - /* Module selection is wrong */ - /*****************************/ - - DPRINTK("Module selection is wrong\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -static int i_APCI1710_InsnReadInterruptPulseEncoder(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct addi_private *devpriv = dev->private; - - data[0] = devpriv->s_InterruptParameters. - s_FIFOInterruptParameters[devpriv-> - s_InterruptParameters.ui_Read].b_OldModuleMask; - data[1] = devpriv->s_InterruptParameters. - s_FIFOInterruptParameters[devpriv-> - s_InterruptParameters.ui_Read].ul_OldInterruptMask; - data[2] = devpriv->s_InterruptParameters. - s_FIFOInterruptParameters[devpriv-> - s_InterruptParameters.ui_Read].ul_OldCounterLatchValue; - - /***************************/ - /* Increment the read FIFO */ - /***************************/ - - devpriv->s_InterruptParameters. - ui_Read = (devpriv-> - s_InterruptParameters.ui_Read + 1) % APCI1710_SAVE_INTERRUPT; - - return insn->n; - -} diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c deleted file mode 100644 index 5c830337db85..000000000000 --- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c +++ /dev/null @@ -1,3582 +0,0 @@ -/** -@verbatim - -Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. - - ADDI-DATA GmbH - Dieselstrasse 3 - D-77833 Ottersweier - Tel: +19(0)7223/9493-0 - Fax: +49(0)7223/9493-92 - http://www.addi-data.com - info@addi-data.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. - -@endverbatim -*/ -/* - - +-----------------------------------------------------------------------+ - | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier | - +-----------------------------------------------------------------------+ - | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | - | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | - +-----------------------------------------------------------------------+ - | Project : API APCI1710 | Compiler : gcc | - | Module name : PWM.C | Version : 2.96 | - +-------------------------------+---------------------------------------+ - | Project manager: Eric Stolz | Date : 02/12/2002 | - +-----------------------------------------------------------------------+ - | Description : APCI-1710 Wulse wide modulation module | - | | - | | - +-----------------------------------------------------------------------+ - | UPDATES | - +-----------------------------------------------------------------------+ - | Date | Author | Description of updates | - +-----------------------------------------------------------------------+ - | 08/05/00 | Guinot C | - 0400/0228 All Function in RING 0 | - | | | available | - +-----------------------------------------------------------------------+ -*/ - -#define APCI1710_30MHZ 30 -#define APCI1710_33MHZ 33 -#define APCI1710_40MHZ 40 - -#define APCI1710_PWM_INIT 0 -#define APCI1710_PWM_GETINITDATA 1 - -#define APCI1710_PWM_DISABLE 0 -#define APCI1710_PWM_ENABLE 1 -#define APCI1710_PWM_NEWTIMING 2 - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_InitPWM | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_PWM, | -| unsigned char_ b_ClockSelection, | -| unsigned char_ b_TimingUnit, | -| ULONG_ ul_LowTiming, | -| ULONG_ ul_HighTiming, | -| PULONG_ pul_RealLowTiming, | -| PULONG_ pul_RealHighTiming) | -+----------------------------------------------------------------------------+ -| Task : Configure the selected PWM (b_PWM) from selected module| -| (b_ModulNbr). The ul_LowTiming, ul_HighTiming and | -| ul_TimingUnit determine the low/high timing base for | -| the period. pul_RealLowTiming, pul_RealHighTiming | -| return the real timing value. | -| You must calling this function be for you call any | -| other function witch access of the PWM. | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Module number to configure| -| (0 to 3) | -| unsigned char_ b_PWM : Selected PWM (0 or 1). | -| unsigned char_ b_ClockSelection : Selection from PCI bus | -| clock | -| - APCI1710_30MHZ : | -| The PC have a 30 MHz | -| PCI bus clock | -| - APCI1710_33MHZ : | -| The PC have a 33 MHz | -| PCI bus clock | -| - APCI1710_40MHZ | -| The APCI-1710 have a | -| integrated 40Mhz | -| quartz. | -| unsigned char_ b_TimingUnit : Base timing Unit (0 to 4) | -| 0 : ns | -| 1 : æs | -| 2 : ms | -| 3 : s | -| 4 : mn | -| ULONG_ ul_LowTiming : Low base timing value. | -| ULONG_ ul_HighTiming : High base timing value. | -+----------------------------------------------------------------------------+ -| Output Parameters : PULONG_ pul_RealLowTiming : Real low base timing | -| value. | -| PULONG_ pul_RealHighTiming : Real high base timing | -| value. | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: Module selection wrong | -| -3: The module is not a PWM module | -| -4: PWM selection is wrong | -| -5: The selected input clock is wrong | -| -6: Timing Unit selection is wrong | -| -7: Low base timing selection is wrong | -| -8: High base timing selection is wrong | -| -9: You can not used the 40MHz clock selection with | -| this board | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_InitPWM(struct comedi_device *dev, - unsigned char b_ModulNbr, - unsigned char b_PWM, - unsigned char b_ClockSelection, - unsigned char b_TimingUnit, - unsigned int ul_LowTiming, - unsigned int ul_HighTiming, - unsigned int *pul_RealLowTiming, - unsigned int *pul_RealHighTiming) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned int ul_LowTimerValue = 0; - unsigned int ul_HighTimerValue = 0; - unsigned int dw_Command; - double d_RealLowTiming = 0; - double d_RealHighTiming = 0; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /***************/ - /* Test if PWM */ - /***************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModulNbr] & - 0xFFFF0000UL) == APCI1710_PWM) { - /**************************/ - /* Test the PWM selection */ - /**************************/ - - if (b_PWM <= 1) { - /******************/ - /* Test the clock */ - /******************/ - - if ((b_ClockSelection == APCI1710_30MHZ) || - (b_ClockSelection == APCI1710_33MHZ) || - (b_ClockSelection == APCI1710_40MHZ)) { - /************************/ - /* Test the timing unit */ - /************************/ - - if (b_TimingUnit <= 4) { - /*********************************/ - /* Test the low timing selection */ - /*********************************/ - - if (((b_ClockSelection == - APCI1710_30MHZ) - && (b_TimingUnit - == 0) - && (ul_LowTiming - >= 266) - && (ul_LowTiming - <= - 0xFFFFFFFFUL)) - || ((b_ClockSelection == - APCI1710_30MHZ) - && (b_TimingUnit - == 1) - && (ul_LowTiming - >= 1) - && (ul_LowTiming - <= - 571230650UL)) - || ((b_ClockSelection == - APCI1710_30MHZ) - && (b_TimingUnit - == 2) - && (ul_LowTiming - >= 1) - && (ul_LowTiming - <= - 571230UL)) - || ((b_ClockSelection == - APCI1710_30MHZ) - && (b_TimingUnit - == 3) - && (ul_LowTiming - >= 1) - && (ul_LowTiming - <= - 571UL)) - || ((b_ClockSelection == - APCI1710_30MHZ) - && (b_TimingUnit - == 4) - && (ul_LowTiming - >= 1) - && (ul_LowTiming - <= 9UL)) - || ((b_ClockSelection == - APCI1710_33MHZ) - && (b_TimingUnit - == 0) - && (ul_LowTiming - >= 242) - && (ul_LowTiming - <= - 0xFFFFFFFFUL)) - || ((b_ClockSelection == - APCI1710_33MHZ) - && (b_TimingUnit - == 1) - && (ul_LowTiming - >= 1) - && (ul_LowTiming - <= - 519691043UL)) - || ((b_ClockSelection == - APCI1710_33MHZ) - && (b_TimingUnit - == 2) - && (ul_LowTiming - >= 1) - && (ul_LowTiming - <= - 519691UL)) - || ((b_ClockSelection == - APCI1710_33MHZ) - && (b_TimingUnit - == 3) - && (ul_LowTiming - >= 1) - && (ul_LowTiming - <= - 520UL)) - || ((b_ClockSelection == - APCI1710_33MHZ) - && (b_TimingUnit - == 4) - && (ul_LowTiming - >= 1) - && (ul_LowTiming - <= 8UL)) - || ((b_ClockSelection == - APCI1710_40MHZ) - && (b_TimingUnit - == 0) - && (ul_LowTiming - >= 200) - && (ul_LowTiming - <= - 0xFFFFFFFFUL)) - || ((b_ClockSelection == - APCI1710_40MHZ) - && (b_TimingUnit - == 1) - && (ul_LowTiming - >= 1) - && (ul_LowTiming - <= - 429496729UL)) - || ((b_ClockSelection == - APCI1710_40MHZ) - && (b_TimingUnit - == 2) - && (ul_LowTiming - >= 1) - && (ul_LowTiming - <= - 429496UL)) - || ((b_ClockSelection == - APCI1710_40MHZ) - && (b_TimingUnit - == 3) - && (ul_LowTiming - >= 1) - && (ul_LowTiming - <= - 429UL)) - || ((b_ClockSelection == - APCI1710_40MHZ) - && (b_TimingUnit - == 4) - && (ul_LowTiming - >= 1) - && (ul_LowTiming - <= - 7UL))) { - /**********************************/ - /* Test the High timing selection */ - /**********************************/ - - if (((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 266) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571230650UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571230UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 9UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 242) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 519691043UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 519691UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 520UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 8UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 200) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429496729UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429496UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 7UL))) { - /**************************/ - /* Test the board version */ - /**************************/ - - if (((b_ClockSelection == APCI1710_40MHZ) && (devpriv->s_BoardInfos.b_BoardVersion > 0)) || (b_ClockSelection != APCI1710_40MHZ)) { - - /************************************/ - /* Calculate the low division fator */ - /************************************/ - - fpu_begin - (); - - switch (b_TimingUnit) { - /******/ - /* ns */ - /******/ - - case 0: - - /******************/ - /* Timer 0 factor */ - /******************/ - - ul_LowTimerValue - = - (unsigned int) - (ul_LowTiming - * - (0.00025 * b_ClockSelection)); - - /*******************/ - /* Round the value */ - /*******************/ - - if ((double)((double)ul_LowTiming * (0.00025 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) { - ul_LowTimerValue - = - ul_LowTimerValue - + - 1; - } - - /*****************************/ - /* Calculate the real timing */ - /*****************************/ - - *pul_RealLowTiming - = - (unsigned int) - (ul_LowTimerValue - / - (0.00025 * (double)b_ClockSelection)); - d_RealLowTiming - = - (double) - ul_LowTimerValue - / - (0.00025 - * - (double) - b_ClockSelection); - - if ((double)((double)ul_LowTimerValue / (0.00025 * (double)b_ClockSelection)) >= (double)((double)*pul_RealLowTiming + 0.5)) { - *pul_RealLowTiming - = - *pul_RealLowTiming - + - 1; - } - - ul_LowTiming - = - ul_LowTiming - - - 1; - ul_LowTimerValue - = - ul_LowTimerValue - - - 2; - - if (b_ClockSelection != APCI1710_40MHZ) { - ul_LowTimerValue - = - (unsigned int) - ( - (double) - (ul_LowTimerValue) - * - 1.007752288); - } - - break; - - /******/ - /* æs */ - /******/ - - case 1: - - /******************/ - /* Timer 0 factor */ - /******************/ - - ul_LowTimerValue - = - (unsigned int) - (ul_LowTiming - * - (0.25 * b_ClockSelection)); - - /*******************/ - /* Round the value */ - /*******************/ - - if ((double)((double)ul_LowTiming * (0.25 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) { - ul_LowTimerValue - = - ul_LowTimerValue - + - 1; - } - - /*****************************/ - /* Calculate the real timing */ - /*****************************/ - - *pul_RealLowTiming - = - (unsigned int) - (ul_LowTimerValue - / - (0.25 * (double)b_ClockSelection)); - d_RealLowTiming - = - (double) - ul_LowTimerValue - / - ( - (double) - 0.25 - * - (double) - b_ClockSelection); - - if ((double)((double)ul_LowTimerValue / (0.25 * (double)b_ClockSelection)) >= (double)((double)*pul_RealLowTiming + 0.5)) { - *pul_RealLowTiming - = - *pul_RealLowTiming - + - 1; - } - - ul_LowTiming - = - ul_LowTiming - - - 1; - ul_LowTimerValue - = - ul_LowTimerValue - - - 2; - - if (b_ClockSelection != APCI1710_40MHZ) { - ul_LowTimerValue - = - (unsigned int) - ( - (double) - (ul_LowTimerValue) - * - 1.007752288); - } - - break; - - /******/ - /* ms */ - /******/ - - case 2: - - /******************/ - /* Timer 0 factor */ - /******************/ - - ul_LowTimerValue - = - ul_LowTiming - * - (250.0 - * - b_ClockSelection); - - /*******************/ - /* Round the value */ - /*******************/ - - if ((double)((double)ul_LowTiming * (250.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) { - ul_LowTimerValue - = - ul_LowTimerValue - + - 1; - } - - /*****************************/ - /* Calculate the real timing */ - /*****************************/ - - *pul_RealLowTiming - = - (unsigned int) - (ul_LowTimerValue - / - (250.0 * (double)b_ClockSelection)); - d_RealLowTiming - = - (double) - ul_LowTimerValue - / - (250.0 - * - (double) - b_ClockSelection); - - if ((double)((double)ul_LowTimerValue / (250.0 * (double)b_ClockSelection)) >= (double)((double)*pul_RealLowTiming + 0.5)) { - *pul_RealLowTiming - = - *pul_RealLowTiming - + - 1; - } - - ul_LowTiming - = - ul_LowTiming - - - 1; - ul_LowTimerValue - = - ul_LowTimerValue - - - 2; - - if (b_ClockSelection != APCI1710_40MHZ) { - ul_LowTimerValue - = - (unsigned int) - ( - (double) - (ul_LowTimerValue) - * - 1.007752288); - } - - break; - - /*****/ - /* s */ - /*****/ - - case 3: - /******************/ - /* Timer 0 factor */ - /******************/ - - ul_LowTimerValue - = - (unsigned int) - (ul_LowTiming - * - (250000.0 - * - b_ClockSelection)); - - /*******************/ - /* Round the value */ - /*******************/ - - if ((double)((double)ul_LowTiming * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) { - ul_LowTimerValue - = - ul_LowTimerValue - + - 1; - } - - /*****************************/ - /* Calculate the real timing */ - /*****************************/ - - *pul_RealLowTiming - = - (unsigned int) - (ul_LowTimerValue - / - (250000.0 - * - (double) - b_ClockSelection)); - d_RealLowTiming - = - (double) - ul_LowTimerValue - / - (250000.0 - * - (double) - b_ClockSelection); - - if ((double)((double)ul_LowTimerValue / (250000.0 * (double)b_ClockSelection)) >= (double)((double)*pul_RealLowTiming + 0.5)) { - *pul_RealLowTiming - = - *pul_RealLowTiming - + - 1; - } - - ul_LowTiming - = - ul_LowTiming - - - 1; - ul_LowTimerValue - = - ul_LowTimerValue - - - 2; - - if (b_ClockSelection != APCI1710_40MHZ) { - ul_LowTimerValue - = - (unsigned int) - ( - (double) - (ul_LowTimerValue) - * - 1.007752288); - } - - break; - - /******/ - /* mn */ - /******/ - - case 4: - - /******************/ - /* Timer 0 factor */ - /******************/ - - ul_LowTimerValue - = - (unsigned int) - ( - (ul_LowTiming - * - 60) - * - (250000.0 - * - b_ClockSelection)); - - /*******************/ - /* Round the value */ - /*******************/ - - if ((double)((double)(ul_LowTiming * 60.0) * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) { - ul_LowTimerValue - = - ul_LowTimerValue - + - 1; - } - - /*****************************/ - /* Calculate the real timing */ - /*****************************/ - - *pul_RealLowTiming - = - (unsigned int) - (ul_LowTimerValue - / - (250000.0 - * - (double) - b_ClockSelection)) - / - 60; - d_RealLowTiming - = - ( - (double) - ul_LowTimerValue - / - (250000.0 - * - (double) - b_ClockSelection)) - / - 60.0; - - if ((double)(((double)ul_LowTimerValue / (250000.0 * (double)b_ClockSelection)) / 60.0) >= (double)((double)*pul_RealLowTiming + 0.5)) { - *pul_RealLowTiming - = - *pul_RealLowTiming - + - 1; - } - - ul_LowTiming - = - ul_LowTiming - - - 1; - ul_LowTimerValue - = - ul_LowTimerValue - - - 2; - - if (b_ClockSelection != APCI1710_40MHZ) { - ul_LowTimerValue - = - (unsigned int) - ( - (double) - (ul_LowTimerValue) - * - 1.007752288); - } - - break; - } - - /*************************************/ - /* Calculate the high division fator */ - /*************************************/ - - switch (b_TimingUnit) { - /******/ - /* ns */ - /******/ - - case 0: - - /******************/ - /* Timer 0 factor */ - /******************/ - - ul_HighTimerValue - = - (unsigned int) - (ul_HighTiming - * - (0.00025 * b_ClockSelection)); - - /*******************/ - /* Round the value */ - /*******************/ - - if ((double)((double)ul_HighTiming * (0.00025 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) { - ul_HighTimerValue - = - ul_HighTimerValue - + - 1; - } - - /*****************************/ - /* Calculate the real timing */ - /*****************************/ - - *pul_RealHighTiming - = - (unsigned int) - (ul_HighTimerValue - / - (0.00025 * (double)b_ClockSelection)); - d_RealHighTiming - = - (double) - ul_HighTimerValue - / - (0.00025 - * - (double) - b_ClockSelection); - - if ((double)((double)ul_HighTimerValue / (0.00025 * (double)b_ClockSelection)) >= (double)((double)*pul_RealHighTiming + 0.5)) { - *pul_RealHighTiming - = - *pul_RealHighTiming - + - 1; - } - - ul_HighTiming - = - ul_HighTiming - - - 1; - ul_HighTimerValue - = - ul_HighTimerValue - - - 2; - - if (b_ClockSelection != APCI1710_40MHZ) { - ul_HighTimerValue - = - (unsigned int) - ( - (double) - (ul_HighTimerValue) - * - 1.007752288); - } - - break; - - /******/ - /* æs */ - /******/ - - case 1: - - /******************/ - /* Timer 0 factor */ - /******************/ - - ul_HighTimerValue - = - (unsigned int) - (ul_HighTiming - * - (0.25 * b_ClockSelection)); - - /*******************/ - /* Round the value */ - /*******************/ - - if ((double)((double)ul_HighTiming * (0.25 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) { - ul_HighTimerValue - = - ul_HighTimerValue - + - 1; - } - - /*****************************/ - /* Calculate the real timing */ - /*****************************/ - - *pul_RealHighTiming - = - (unsigned int) - (ul_HighTimerValue - / - (0.25 * (double)b_ClockSelection)); - d_RealHighTiming - = - (double) - ul_HighTimerValue - / - ( - (double) - 0.25 - * - (double) - b_ClockSelection); - - if ((double)((double)ul_HighTimerValue / (0.25 * (double)b_ClockSelection)) >= (double)((double)*pul_RealHighTiming + 0.5)) { - *pul_RealHighTiming - = - *pul_RealHighTiming - + - 1; - } - - ul_HighTiming - = - ul_HighTiming - - - 1; - ul_HighTimerValue - = - ul_HighTimerValue - - - 2; - - if (b_ClockSelection != APCI1710_40MHZ) { - ul_HighTimerValue - = - (unsigned int) - ( - (double) - (ul_HighTimerValue) - * - 1.007752288); - } - - break; - - /******/ - /* ms */ - /******/ - - case 2: - - /******************/ - /* Timer 0 factor */ - /******************/ - - ul_HighTimerValue - = - ul_HighTiming - * - (250.0 - * - b_ClockSelection); - - /*******************/ - /* Round the value */ - /*******************/ - - if ((double)((double)ul_HighTiming * (250.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) { - ul_HighTimerValue - = - ul_HighTimerValue - + - 1; - } - - /*****************************/ - /* Calculate the real timing */ - /*****************************/ - - *pul_RealHighTiming - = - (unsigned int) - (ul_HighTimerValue - / - (250.0 * (double)b_ClockSelection)); - d_RealHighTiming - = - (double) - ul_HighTimerValue - / - (250.0 - * - (double) - b_ClockSelection); - - if ((double)((double)ul_HighTimerValue / (250.0 * (double)b_ClockSelection)) >= (double)((double)*pul_RealHighTiming + 0.5)) { - *pul_RealHighTiming - = - *pul_RealHighTiming - + - 1; - } - - ul_HighTiming - = - ul_HighTiming - - - 1; - ul_HighTimerValue - = - ul_HighTimerValue - - - 2; - - if (b_ClockSelection != APCI1710_40MHZ) { - ul_HighTimerValue - = - (unsigned int) - ( - (double) - (ul_HighTimerValue) - * - 1.007752288); - } - - break; - - /*****/ - /* s */ - /*****/ - - case 3: - - /******************/ - /* Timer 0 factor */ - /******************/ - - ul_HighTimerValue - = - (unsigned int) - (ul_HighTiming - * - (250000.0 - * - b_ClockSelection)); - - /*******************/ - /* Round the value */ - /*******************/ - - if ((double)((double)ul_HighTiming * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) { - ul_HighTimerValue - = - ul_HighTimerValue - + - 1; - } - - /*****************************/ - /* Calculate the real timing */ - /*****************************/ - - *pul_RealHighTiming - = - (unsigned int) - (ul_HighTimerValue - / - (250000.0 - * - (double) - b_ClockSelection)); - d_RealHighTiming - = - (double) - ul_HighTimerValue - / - (250000.0 - * - (double) - b_ClockSelection); - - if ((double)((double)ul_HighTimerValue / (250000.0 * (double)b_ClockSelection)) >= (double)((double)*pul_RealHighTiming + 0.5)) { - *pul_RealHighTiming - = - *pul_RealHighTiming - + - 1; - } - - ul_HighTiming - = - ul_HighTiming - - - 1; - ul_HighTimerValue - = - ul_HighTimerValue - - - 2; - - if (b_ClockSelection != APCI1710_40MHZ) { - ul_HighTimerValue - = - (unsigned int) - ( - (double) - (ul_HighTimerValue) - * - 1.007752288); - } - - break; - - /******/ - /* mn */ - /******/ - - case 4: - - /******************/ - /* Timer 0 factor */ - /******************/ - - ul_HighTimerValue - = - (unsigned int) - ( - (ul_HighTiming - * - 60) - * - (250000.0 - * - b_ClockSelection)); - - /*******************/ - /* Round the value */ - /*******************/ - - if ((double)((double)(ul_HighTiming * 60.0) * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) { - ul_HighTimerValue - = - ul_HighTimerValue - + - 1; - } - - /*****************************/ - /* Calculate the real timing */ - /*****************************/ - - *pul_RealHighTiming - = - (unsigned int) - (ul_HighTimerValue - / - (250000.0 - * - (double) - b_ClockSelection)) - / - 60; - d_RealHighTiming - = - ( - (double) - ul_HighTimerValue - / - (250000.0 - * - (double) - b_ClockSelection)) - / - 60.0; - - if ((double)(((double)ul_HighTimerValue / (250000.0 * (double)b_ClockSelection)) / 60.0) >= (double)((double)*pul_RealHighTiming + 0.5)) { - *pul_RealHighTiming - = - *pul_RealHighTiming - + - 1; - } - - ul_HighTiming - = - ul_HighTiming - - - 1; - ul_HighTimerValue - = - ul_HighTimerValue - - - 2; - - if (b_ClockSelection != APCI1710_40MHZ) { - ul_HighTimerValue - = - (unsigned int) - ( - (double) - (ul_HighTimerValue) - * - 1.007752288); - } - - break; - } - - fpu_end(); - /****************************/ - /* Save the clock selection */ - /****************************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_PWMModuleInfo. - b_ClockSelection - = - b_ClockSelection; - - /************************/ - /* Save the timing unit */ - /************************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_PWMModuleInfo. - s_PWMInfo - [b_PWM]. - b_TimingUnit - = - b_TimingUnit; - - /****************************/ - /* Save the low base timing */ - /****************************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_PWMModuleInfo. - s_PWMInfo - [b_PWM]. - d_LowTiming - = - d_RealLowTiming; - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_PWMModuleInfo. - s_PWMInfo - [b_PWM]. - ul_RealLowTiming - = - *pul_RealLowTiming; - - /****************************/ - /* Save the high base timing */ - /****************************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_PWMModuleInfo. - s_PWMInfo - [b_PWM]. - d_HighTiming - = - d_RealHighTiming; - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_PWMModuleInfo. - s_PWMInfo - [b_PWM]. - ul_RealHighTiming - = - *pul_RealHighTiming; - - /************************/ - /* Write the low timing */ - /************************/ - - outl(ul_LowTimerValue, devpriv->s_BoardInfos.ui_Address + 0 + (20 * b_PWM) + (64 * b_ModulNbr)); - - /*************************/ - /* Write the high timing */ - /*************************/ - - outl(ul_HighTimerValue, devpriv->s_BoardInfos.ui_Address + 4 + (20 * b_PWM) + (64 * b_ModulNbr)); - - /***************************/ - /* Set the clock selection */ - /***************************/ - - dw_Command - = - inl - (devpriv-> - s_BoardInfos. - ui_Address - + - 8 - + - (20 * b_PWM) + (64 * b_ModulNbr)); - - dw_Command - = - dw_Command - & - 0x7F; - - if (b_ClockSelection == APCI1710_40MHZ) { - dw_Command - = - dw_Command - | - 0x80; - } - - /***************************/ - /* Set the clock selection */ - /***************************/ - - outl(dw_Command, devpriv->s_BoardInfos.ui_Address + 8 + (20 * b_PWM) + (64 * b_ModulNbr)); - - /*************/ - /* PWM init. */ - /*************/ - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_PWMModuleInfo. - s_PWMInfo - [b_PWM]. - b_PWMInit - = - 1; - } else { - /***************************************************/ - /* You can not used the 40MHz clock selection with */ - /* this board */ - /***************************************************/ - DPRINTK("You can not used the 40MHz clock selection with this board\n"); - i_ReturnValue - = - -9; - } - } else { - /***************************************/ - /* High base timing selection is wrong */ - /***************************************/ - DPRINTK("High base timing selection is wrong\n"); - i_ReturnValue = - -8; - } - } else { - /**************************************/ - /* Low base timing selection is wrong */ - /**************************************/ - DPRINTK("Low base timing selection is wrong\n"); - i_ReturnValue = -7; - } - } /* if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) */ - else { - /**********************************/ - /* Timing unit selection is wrong */ - /**********************************/ - DPRINTK("Timing unit selection is wrong\n"); - i_ReturnValue = -6; - } /* if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) */ - } /* if ((b_ClockSelection == APCI1710_30MHZ) || (b_ClockSelection == APCI1710_33MHZ) || (b_ClockSelection == APCI1710_40MHZ)) */ - else { - /*******************************/ - /* The selected clock is wrong */ - /*******************************/ - DPRINTK("The selected clock is wrong\n"); - i_ReturnValue = -5; - } /* if ((b_ClockSelection == APCI1710_30MHZ) || (b_ClockSelection == APCI1710_33MHZ) || (b_ClockSelection == APCI1710_40MHZ)) */ - } /* if (b_PWM >= 0 && b_PWM <= 1) */ - else { - /******************************/ - /* Tor PWM selection is wrong */ - /******************************/ - DPRINTK("Tor PWM selection is wrong\n"); - i_ReturnValue = -4; - } /* if (b_PWM >= 0 && b_PWM <= 1) */ - } else { - /**********************************/ - /* The module is not a PWM module */ - /**********************************/ - DPRINTK("The module is not a PWM module\n"); - i_ReturnValue = -3; - } - } else { - /***********************/ - /* Module number error */ - /***********************/ - DPRINTK("Module number error\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_GetPWMInitialisation | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_PWM, | -| unsigned char *_ pb_TimingUnit, | -| PULONG_ pul_LowTiming, | -| PULONG_ pul_HighTiming, | -| unsigned char *_ pb_StartLevel, | -| unsigned char *_ pb_StopMode, | -| unsigned char *_ pb_StopLevel, | -| unsigned char *_ pb_ExternGate, | -| unsigned char *_ pb_InterruptEnable, | -| unsigned char *_ pb_Enable) | -+----------------------------------------------------------------------------+ -| Task : Return the PWM (b_PWM) initialisation from selected | -| module (b_ModulNbr). You must calling the | -| "i_APCI1710_InitPWM" function be for you call this | -| function. | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Selected module number (0 to 3) | -| unsigned char_ b_PWM : Selected PWM (0 or 1) | -+----------------------------------------------------------------------------+ -| Output Parameters : unsigned char *_ pb_TimingUnit : Base timing Unit (0 to 4) | -| 0 : ns | -| 1 : æs | -| 2 : ms | -| 3 : s | -| 4 : mn | -| PULONG_ pul_LowTiming : Low base timing value. | -| PULONG_ pul_HighTiming : High base timing value. | -| unsigned char *_ pb_StartLevel : Start period level | -| selection | -| 0 : The period start | -| with a low level | -| 1 : The period start | -| with a high level| -| unsigned char *_ pb_StopMode : Stop mode selection | -| 0 : The PWM is stopped | -| directly after the | -| "i_APCI1710_DisablePWM"| -| function and break the| -| last period | -| 1 : After the | -| "i_APCI1710_DisablePWM"| -| function the PWM is | -| stopped at the end | -| from last period cycle| -| unsigned char *_ pb_StopLevel : Stop PWM level selection | -| 0 : The output signal | -| keep the level after| -| the | -| "i_APCI1710_DisablePWM"| -| function | -| 1 : The output signal is| -| set to low after the| -| "i_APCI1710_DisablePWM"| -| function | -| 2 : The output signal is| -| set to high after | -| the | -| "i_APCI1710_DisablePWM"| -| function | -| unsigned char *_ pb_ExternGate : Extern gate action | -| selection | -| 0 : Extern gate signal | -| not used. | -| 1 : Extern gate signal | -| used. | -| unsigned char *_ pb_InterruptEnable : Enable or disable the PWM | -| interrupt. | -| - APCI1710_ENABLE : | -| Enable the PWM interrupt| -| A interrupt occur after | -| each period | -| - APCI1710_DISABLE : | -| Disable the PWM | -| interrupt | -| unsigned char *_ pb_Enable : Indicate if the PWM is | -| enabled or no | -| 0 : PWM not enabled | -| 1 : PWM enabled | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: Module selection wrong | -| -3: The module is not a PWM module | -| -4: PWM selection is wrong | -| -5: PWM not initialised see function | -| "i_APCI1710_InitPWM" | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_GetPWMInitialisation(struct comedi_device *dev, - unsigned char b_ModulNbr, - unsigned char b_PWM, - unsigned char *pb_TimingUnit, - unsigned int *pul_LowTiming, - unsigned int *pul_HighTiming, - unsigned char *pb_StartLevel, - unsigned char *pb_StopMode, - unsigned char *pb_StopLevel, - unsigned char *pb_ExternGate, - unsigned char *pb_InterruptEnable, - unsigned char *pb_Enable) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned int dw_Status; - unsigned int dw_Command; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /***************/ - /* Test if PWM */ - /***************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModulNbr] & - 0xFFFF0000UL) == APCI1710_PWM) { - /**************************/ - /* Test the PWM selection */ - /**************************/ - - if (b_PWM <= 1) { - /***************************/ - /* Test if PWM initialised */ - /***************************/ - - dw_Status = inl(devpriv->s_BoardInfos. - ui_Address + 12 + (20 * b_PWM) + - (64 * b_ModulNbr)); - - if (dw_Status & 0x10) { - /***********************/ - /* Read the low timing */ - /***********************/ - - *pul_LowTiming = - inl(devpriv->s_BoardInfos. - ui_Address + 0 + (20 * b_PWM) + - (64 * b_ModulNbr)); - - /************************/ - /* Read the high timing */ - /************************/ - - *pul_HighTiming = - inl(devpriv->s_BoardInfos. - ui_Address + 4 + (20 * b_PWM) + - (64 * b_ModulNbr)); - - /********************/ - /* Read the command */ - /********************/ - - dw_Command = inl(devpriv->s_BoardInfos. - ui_Address + 8 + (20 * b_PWM) + - (64 * b_ModulNbr)); - - *pb_StartLevel = - (unsigned char) ((dw_Command >> 5) & 1); - *pb_StopMode = - (unsigned char) ((dw_Command >> 0) & 1); - *pb_StopLevel = - (unsigned char) ((dw_Command >> 1) & 1); - *pb_ExternGate = - (unsigned char) ((dw_Command >> 4) & 1); - *pb_InterruptEnable = - (unsigned char) ((dw_Command >> 3) & 1); - - if (*pb_StopLevel) { - *pb_StopLevel = - *pb_StopLevel + - (unsigned char) ((dw_Command >> - 2) & 1); - } - - /********************/ - /* Read the command */ - /********************/ - - dw_Command = inl(devpriv->s_BoardInfos. - ui_Address + 8 + (20 * b_PWM) + - (64 * b_ModulNbr)); - - *pb_Enable = - (unsigned char) ((dw_Command >> 0) & 1); - - *pb_TimingUnit = devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_PWMModuleInfo. - s_PWMInfo[b_PWM].b_TimingUnit; - } /* if (dw_Status & 0x10) */ - else { - /***********************/ - /* PWM not initialised */ - /***********************/ - DPRINTK("PWM not initialised\n"); - i_ReturnValue = -5; - } /* if (dw_Status & 0x10) */ - } /* if (b_PWM >= 0 && b_PWM <= 1) */ - else { - /******************************/ - /* Tor PWM selection is wrong */ - /******************************/ - DPRINTK("Tor PWM selection is wrong\n"); - i_ReturnValue = -4; - } /* if (b_PWM >= 0 && b_PWM <= 1) */ - } else { - /**********************************/ - /* The module is not a PWM module */ - /**********************************/ - DPRINTK("The module is not a PWM module\n"); - i_ReturnValue = -3; - } - } else { - /***********************/ - /* Module number error */ - /***********************/ - DPRINTK("Module number error\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* - * Pwm Init and Get Pwm Initialisation - */ -static int i_APCI1710_InsnConfigPWM(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - unsigned char b_ConfigType; - int i_ReturnValue = 0; - b_ConfigType = CR_CHAN(insn->chanspec); - - switch (b_ConfigType) { - case APCI1710_PWM_INIT: - i_ReturnValue = i_APCI1710_InitPWM(dev, (unsigned char) CR_AREF(insn->chanspec), /* b_ModulNbr */ - (unsigned char) data[0], /* b_PWM */ - (unsigned char) data[1], /* b_ClockSelection */ - (unsigned char) data[2], /* b_TimingUnit */ - (unsigned int) data[3], /* ul_LowTiming */ - (unsigned int) data[4], /* ul_HighTiming */ - (unsigned int *) &data[0], /* pul_RealLowTiming */ - (unsigned int *) &data[1] /* pul_RealHighTiming */ - ); - break; - - case APCI1710_PWM_GETINITDATA: - i_ReturnValue = i_APCI1710_GetPWMInitialisation(dev, (unsigned char) CR_AREF(insn->chanspec), /* b_ModulNbr */ - (unsigned char) data[0], /* b_PWM */ - (unsigned char *) &data[0], /* pb_TimingUnit */ - (unsigned int *) &data[1], /* pul_LowTiming */ - (unsigned int *) &data[2], /* pul_HighTiming */ - (unsigned char *) &data[3], /* pb_StartLevel */ - (unsigned char *) &data[4], /* pb_StopMode */ - (unsigned char *) &data[5], /* pb_StopLevel */ - (unsigned char *) &data[6], /* pb_ExternGate */ - (unsigned char *) &data[7], /* pb_InterruptEnable */ - (unsigned char *) &data[8] /* pb_Enable */ - ); - break; - - default: - printk(" Config Parameter Wrong\n"); - } - - if (i_ReturnValue >= 0) - i_ReturnValue = insn->n; - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_EnablePWM | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_PWM, | -| unsigned char_ b_StartLevel, | -| unsigned char_ b_StopMode, | -| unsigned char_ b_StopLevel, | -| unsigned char_ b_ExternGate, | -| unsigned char_ b_InterruptEnable) | -+----------------------------------------------------------------------------+ -| Task : Enable the selected PWM (b_PWM) from selected module | -| (b_ModulNbr). You must calling the "i_APCI1710_InitPWM"| -| function be for you call this function. | -| If you enable the PWM interrupt, the PWM generate a | -| interrupt after each period. | -| See function "i_APCI1710_SetBoardIntRoutineX" and the | -| Interrupt mask description chapter. | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Selected module number | -| (0 to 3) | -| unsigned char_ b_PWM : Selected PWM (0 or 1) | -| unsigned char_ b_StartLevel : Start period level selection | -| 0 : The period start with a | -| low level | -| 1 : The period start with a | -| high level | -| unsigned char_ b_StopMode : Stop mode selection | -| 0 : The PWM is stopped | -| directly after the | -| "i_APCI1710_DisablePWM" | -| function and break the | -| last period | -| 1 : After the | -| "i_APCI1710_DisablePWM" | -| function the PWM is | -| stopped at the end from| -| last period cycle. | -| unsigned char_ b_StopLevel : Stop PWM level selection | -| 0 : The output signal keep | -| the level after the | -| "i_APCI1710_DisablePWM" | -| function | -| 1 : The output signal is set| -| to low after the | -| "i_APCI1710_DisablePWM" | -| function | -| 2 : The output signal is set| -| to high after the | -| "i_APCI1710_DisablePWM" | -| function | -| unsigned char_ b_ExternGate : Extern gate action selection | -| 0 : Extern gate signal not | -| used. | -| 1 : Extern gate signal used.| -| unsigned char_ b_InterruptEnable : Enable or disable the PWM | -| interrupt. | -| - APCI1710_ENABLE : | -| Enable the PWM interrupt | -| A interrupt occur after | -| each period | -| - APCI1710_DISABLE : | -| Disable the PWM interrupt | -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: Module selection wrong | -| -3: The module is not a PWM module | -| -4: PWM selection is wrong | -| -5: PWM not initialised see function | -| "i_APCI1710_InitPWM" | -| -6: PWM start level selection is wrong | -| -7: PWM stop mode selection is wrong | -| -8: PWM stop level selection is wrong | -| -9: Extern gate signal selection is wrong | -| -10: Interrupt parameter is wrong | -| -11: Interrupt function not initialised. | -| See function "i_APCI1710_SetBoardIntRoutineX" | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_EnablePWM(struct comedi_device *dev, - unsigned char b_ModulNbr, - unsigned char b_PWM, - unsigned char b_StartLevel, - unsigned char b_StopMode, - unsigned char b_StopLevel, - unsigned char b_ExternGate, - unsigned char b_InterruptEnable) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned int dw_Status; - unsigned int dw_Command; - - devpriv->tsk_Current = current; /* Save the current process task structure */ - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /***************/ - /* Test if PWM */ - /***************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModulNbr] & - 0xFFFF0000UL) == APCI1710_PWM) { - /**************************/ - /* Test the PWM selection */ - /**************************/ - - if (b_PWM <= 1) { - /***************************/ - /* Test if PWM initialised */ - /***************************/ - - dw_Status = inl(devpriv->s_BoardInfos. - ui_Address + 12 + (20 * b_PWM) + - (64 * b_ModulNbr)); - - if (dw_Status & 0x10) { - /**********************************/ - /* Test the start level selection */ - /**********************************/ - - if (b_StartLevel <= 1) { - /**********************/ - /* Test the stop mode */ - /**********************/ - - if (b_StopMode <= 1) { - /***********************/ - /* Test the stop level */ - /***********************/ - - if (b_StopLevel <= 2) { - /*****************************/ - /* Test the extern gate mode */ - /*****************************/ - - if (b_ExternGate - <= 1) { - /*****************************/ - /* Test the interrupt action */ - /*****************************/ - - if (b_InterruptEnable == APCI1710_ENABLE || b_InterruptEnable == APCI1710_DISABLE) { - /******************************************/ - /* Test if interrupt function initialised */ - /******************************************/ - - /********************/ - /* Read the command */ - /********************/ - - dw_Command - = - inl - (devpriv-> - s_BoardInfos. - ui_Address - + - 8 - + - (20 * b_PWM) + (64 * b_ModulNbr)); - - dw_Command - = - dw_Command - & - 0x80; - - /********************/ - /* Make the command */ - /********************/ - - dw_Command - = - dw_Command - | - b_StopMode - | - (b_InterruptEnable - << - 3) - | - (b_ExternGate - << - 4) - | - (b_StartLevel - << - 5); - - if (b_StopLevel & 3) { - dw_Command - = - dw_Command - | - 2; - - if (b_StopLevel & 2) { - dw_Command - = - dw_Command - | - 4; - } - } - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_PWMModuleInfo. - s_PWMInfo - [b_PWM]. - b_InterruptEnable - = - b_InterruptEnable; - - /*******************/ - /* Set the command */ - /*******************/ - - outl(dw_Command, devpriv->s_BoardInfos.ui_Address + 8 + (20 * b_PWM) + (64 * b_ModulNbr)); - - /******************/ - /* Enable the PWM */ - /******************/ - outl(1, devpriv->s_BoardInfos.ui_Address + 12 + (20 * b_PWM) + (64 * b_ModulNbr)); - } /* if (b_InterruptEnable == APCI1710_ENABLE || b_InterruptEnable == APCI1710_DISABLE) */ - else { - /********************************/ - /* Interrupt parameter is wrong */ - /********************************/ - DPRINTK("Interrupt parameter is wrong\n"); - i_ReturnValue - = - -10; - } /* if (b_InterruptEnable == APCI1710_ENABLE || b_InterruptEnable == APCI1710_DISABLE) */ - } /* if (b_ExternGate >= 0 && b_ExternGate <= 1) */ - else { - /*****************************************/ - /* Extern gate signal selection is wrong */ - /*****************************************/ - DPRINTK("Extern gate signal selection is wrong\n"); - i_ReturnValue - = - -9; - } /* if (b_ExternGate >= 0 && b_ExternGate <= 1) */ - } /* if (b_StopLevel >= 0 && b_StopLevel <= 2) */ - else { - /*************************************/ - /* PWM stop level selection is wrong */ - /*************************************/ - DPRINTK("PWM stop level selection is wrong\n"); - i_ReturnValue = - -8; - } /* if (b_StopLevel >= 0 && b_StopLevel <= 2) */ - } /* if (b_StopMode >= 0 && b_StopMode <= 1) */ - else { - /************************************/ - /* PWM stop mode selection is wrong */ - /************************************/ - DPRINTK("PWM stop mode selection is wrong\n"); - i_ReturnValue = -7; - } /* if (b_StopMode >= 0 && b_StopMode <= 1) */ - } /* if (b_StartLevel >= 0 && b_StartLevel <= 1) */ - else { - /**************************************/ - /* PWM start level selection is wrong */ - /**************************************/ - DPRINTK("PWM start level selection is wrong\n"); - i_ReturnValue = -6; - } /* if (b_StartLevel >= 0 && b_StartLevel <= 1) */ - } /* if (dw_Status & 0x10) */ - else { - /***********************/ - /* PWM not initialised */ - /***********************/ - DPRINTK("PWM not initialised\n"); - i_ReturnValue = -5; - } /* if (dw_Status & 0x10) */ - } /* if (b_PWM >= 0 && b_PWM <= 1) */ - else { - /******************************/ - /* Tor PWM selection is wrong */ - /******************************/ - DPRINTK("Tor PWM selection is wrong\n"); - i_ReturnValue = -4; - } /* if (b_PWM >= 0 && b_PWM <= 1) */ - } else { - /**********************************/ - /* The module is not a PWM module */ - /**********************************/ - DPRINTK("The module is not a PWM module\n"); - i_ReturnValue = -3; - } - } else { - /***********************/ - /* Module number error */ - /***********************/ - DPRINTK("Module number error\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_DisablePWM (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_PWM) | -+----------------------------------------------------------------------------+ -| Task : Disable the selected PWM (b_PWM) from selected module | -| (b_ModulNbr). The output signal level depend of the | -| initialisation by the "i_APCI1710_EnablePWM". | -| See the b_StartLevel, b_StopMode and b_StopLevel | -| parameters from this function. | -+----------------------------------------------------------------------------+ -| Input Parameters :BYTE_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Selected module number (0 to 3) | -| unsigned char_ b_PWM : Selected PWM (0 or 1) | -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: Module selection wrong | -| -3: The module is not a PWM module | -| -4: PWM selection is wrong | -| -5: PWM not initialised see function | -| "i_APCI1710_InitPWM" | -| -6: PWM not enabled see function | -| "i_APCI1710_EnablePWM" | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_DisablePWM(struct comedi_device *dev, - unsigned char b_ModulNbr, - unsigned char b_PWM) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned int dw_Status; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /***************/ - /* Test if PWM */ - /***************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModulNbr] & - 0xFFFF0000UL) == APCI1710_PWM) { - /**************************/ - /* Test the PWM selection */ - /**************************/ - - if (b_PWM <= 1) { - /***************************/ - /* Test if PWM initialised */ - /***************************/ - - dw_Status = inl(devpriv->s_BoardInfos. - ui_Address + 12 + (20 * b_PWM) + - (64 * b_ModulNbr)); - - if (dw_Status & 0x10) { - /***********************/ - /* Test if PWM enabled */ - /***********************/ - - if (dw_Status & 0x1) { - /*******************/ - /* Disable the PWM */ - /*******************/ - outl(0, devpriv->s_BoardInfos. - ui_Address + 12 + - (20 * b_PWM) + - (64 * b_ModulNbr)); - } /* if (dw_Status & 0x1) */ - else { - /*******************/ - /* PWM not enabled */ - /*******************/ - DPRINTK("PWM not enabled\n"); - i_ReturnValue = -6; - } /* if (dw_Status & 0x1) */ - } /* if (dw_Status & 0x10) */ - else { - /***********************/ - /* PWM not initialised */ - /***********************/ - DPRINTK(" PWM not initialised\n"); - i_ReturnValue = -5; - } /* if (dw_Status & 0x10) */ - } /* if (b_PWM >= 0 && b_PWM <= 1) */ - else { - /******************************/ - /* Tor PWM selection is wrong */ - /******************************/ - DPRINTK("Tor PWM selection is wrong\n"); - i_ReturnValue = -4; - } /* if (b_PWM >= 0 && b_PWM <= 1) */ - } else { - /**********************************/ - /* The module is not a PWM module */ - /**********************************/ - DPRINTK("The module is not a PWM module\n"); - i_ReturnValue = -3; - } - } else { - /***********************/ - /* Module number error */ - /***********************/ - DPRINTK("Module number error\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_SetNewPWMTiming | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_PWM, | -| unsigned char_ b_ClockSelection, | -| unsigned char_ b_TimingUnit, | -| ULONG_ ul_LowTiming, | -| ULONG_ ul_HighTiming) | -+----------------------------------------------------------------------------+ -| Task : Set a new timing. The ul_LowTiming, ul_HighTiming and | -| ul_TimingUnit determine the low/high timing base for | -| the period. | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Module number to configure| -| (0 to 3) | -| unsigned char_ b_PWM : Selected PWM (0 or 1). | -| unsigned char_ b_TimingUnit : Base timing Unit (0 to 4) | -| 0 : ns | -| 1 : æs | -| 2 : ms | -| 3 : s | -| 4 : mn | -| ULONG_ ul_LowTiming : Low base timing value. | -| ULONG_ ul_HighTiming : High base timing value. | -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: Module selection wrong | -| -3: The module is not a PWM module | -| -4: PWM selection is wrong | -| -5: PWM not initialised | -| -6: Timing Unit selection is wrong | -| -7: Low base timing selection is wrong | -| -8: High base timing selection is wrong | -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_SetNewPWMTiming(struct comedi_device *dev, - unsigned char b_ModulNbr, - unsigned char b_PWM, - unsigned char b_TimingUnit, - unsigned int ul_LowTiming, - unsigned int ul_HighTiming) -{ - struct addi_private *devpriv = dev->private; - unsigned char b_ClockSelection; - int i_ReturnValue = 0; - unsigned int ul_LowTimerValue = 0; - unsigned int ul_HighTimerValue = 0; - unsigned int ul_RealLowTiming = 0; - unsigned int ul_RealHighTiming = 0; - unsigned int dw_Status; - unsigned int dw_Command; - double d_RealLowTiming = 0; - double d_RealHighTiming = 0; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /***************/ - /* Test if PWM */ - /***************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModulNbr] & - 0xFFFF0000UL) == APCI1710_PWM) { - /**************************/ - /* Test the PWM selection */ - /**************************/ - - if (b_PWM <= 1) { - /***************************/ - /* Test if PWM initialised */ - /***************************/ - - dw_Status = inl(devpriv->s_BoardInfos. - ui_Address + 12 + (20 * b_PWM) + - (64 * b_ModulNbr)); - - if (dw_Status & 0x10) { - b_ClockSelection = devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_PWMModuleInfo. - b_ClockSelection; - - /************************/ - /* Test the timing unit */ - /************************/ - - if (b_TimingUnit <= 4) { - /*********************************/ - /* Test the low timing selection */ - /*********************************/ - - if (((b_ClockSelection == - APCI1710_30MHZ) - && (b_TimingUnit - == 0) - && (ul_LowTiming - >= 266) - && (ul_LowTiming - <= - 0xFFFFFFFFUL)) - || ((b_ClockSelection == - APCI1710_30MHZ) - && (b_TimingUnit - == 1) - && (ul_LowTiming - >= 1) - && (ul_LowTiming - <= - 571230650UL)) - || ((b_ClockSelection == - APCI1710_30MHZ) - && (b_TimingUnit - == 2) - && (ul_LowTiming - >= 1) - && (ul_LowTiming - <= - 571230UL)) - || ((b_ClockSelection == - APCI1710_30MHZ) - && (b_TimingUnit - == 3) - && (ul_LowTiming - >= 1) - && (ul_LowTiming - <= - 571UL)) - || ((b_ClockSelection == - APCI1710_30MHZ) - && (b_TimingUnit - == 4) - && (ul_LowTiming - >= 1) - && (ul_LowTiming - <= 9UL)) - || ((b_ClockSelection == - APCI1710_33MHZ) - && (b_TimingUnit - == 0) - && (ul_LowTiming - >= 242) - && (ul_LowTiming - <= - 0xFFFFFFFFUL)) - || ((b_ClockSelection == - APCI1710_33MHZ) - && (b_TimingUnit - == 1) - && (ul_LowTiming - >= 1) - && (ul_LowTiming - <= - 519691043UL)) - || ((b_ClockSelection == - APCI1710_33MHZ) - && (b_TimingUnit - == 2) - && (ul_LowTiming - >= 1) - && (ul_LowTiming - <= - 519691UL)) - || ((b_ClockSelection == - APCI1710_33MHZ) - && (b_TimingUnit - == 3) - && (ul_LowTiming - >= 1) - && (ul_LowTiming - <= - 520UL)) - || ((b_ClockSelection == - APCI1710_33MHZ) - && (b_TimingUnit - == 4) - && (ul_LowTiming - >= 1) - && (ul_LowTiming - <= 8UL)) - || ((b_ClockSelection == - APCI1710_40MHZ) - && (b_TimingUnit - == 0) - && (ul_LowTiming - >= 200) - && (ul_LowTiming - <= - 0xFFFFFFFFUL)) - || ((b_ClockSelection == - APCI1710_40MHZ) - && (b_TimingUnit - == 1) - && (ul_LowTiming - >= 1) - && (ul_LowTiming - <= - 429496729UL)) - || ((b_ClockSelection == - APCI1710_40MHZ) - && (b_TimingUnit - == 2) - && (ul_LowTiming - >= 1) - && (ul_LowTiming - <= - 429496UL)) - || ((b_ClockSelection == - APCI1710_40MHZ) - && (b_TimingUnit - == 3) - && (ul_LowTiming - >= 1) - && (ul_LowTiming - <= - 429UL)) - || ((b_ClockSelection == - APCI1710_40MHZ) - && (b_TimingUnit - == 4) - && (ul_LowTiming - >= 1) - && (ul_LowTiming - <= - 7UL))) { - /**********************************/ - /* Test the High timing selection */ - /**********************************/ - - if (((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 266) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571230650UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571230UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 571UL)) || ((b_ClockSelection == APCI1710_30MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 9UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 242) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 519691043UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 519691UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 520UL)) || ((b_ClockSelection == APCI1710_33MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 8UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 0) && (ul_HighTiming >= 200) && (ul_HighTiming <= 0xFFFFFFFFUL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 1) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429496729UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 2) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429496UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 3) && (ul_HighTiming >= 1) && (ul_HighTiming <= 429UL)) || ((b_ClockSelection == APCI1710_40MHZ) && (b_TimingUnit == 4) && (ul_HighTiming >= 1) && (ul_HighTiming <= 7UL))) { - /************************************/ - /* Calculate the low division fator */ - /************************************/ - - fpu_begin(); - switch (b_TimingUnit) { - /******/ - /* ns */ - /******/ - - case 0: - - /******************/ - /* Timer 0 factor */ - /******************/ - - ul_LowTimerValue - = - (unsigned int) - (ul_LowTiming - * - (0.00025 * b_ClockSelection)); - - /*******************/ - /* Round the value */ - /*******************/ - - if ((double)((double)ul_LowTiming * (0.00025 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) { - ul_LowTimerValue - = - ul_LowTimerValue - + - 1; - } - - /*****************************/ - /* Calculate the real timing */ - /*****************************/ - - ul_RealLowTiming - = - (unsigned int) - (ul_LowTimerValue - / - (0.00025 * (double)b_ClockSelection)); - d_RealLowTiming - = - (double) - ul_LowTimerValue - / - (0.00025 - * - (double) - b_ClockSelection); - - if ((double)((double)ul_LowTimerValue / (0.00025 * (double)b_ClockSelection)) >= (double)((double)ul_RealLowTiming + 0.5)) { - ul_RealLowTiming - = - ul_RealLowTiming - + - 1; - } - - ul_LowTiming - = - ul_LowTiming - - - 1; - ul_LowTimerValue - = - ul_LowTimerValue - - - 2; - - if (b_ClockSelection != APCI1710_40MHZ) { - ul_LowTimerValue - = - (unsigned int) - ( - (double) - (ul_LowTimerValue) - * - 1.007752288); - } - - break; - - /******/ - /* æs */ - /******/ - - case 1: - - /******************/ - /* Timer 0 factor */ - /******************/ - - ul_LowTimerValue - = - (unsigned int) - (ul_LowTiming - * - (0.25 * b_ClockSelection)); - - /*******************/ - /* Round the value */ - /*******************/ - - if ((double)((double)ul_LowTiming * (0.25 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) { - ul_LowTimerValue - = - ul_LowTimerValue - + - 1; - } - - /*****************************/ - /* Calculate the real timing */ - /*****************************/ - - ul_RealLowTiming - = - (unsigned int) - (ul_LowTimerValue - / - (0.25 * (double)b_ClockSelection)); - d_RealLowTiming - = - (double) - ul_LowTimerValue - / - ( - (double) - 0.25 - * - (double) - b_ClockSelection); - - if ((double)((double)ul_LowTimerValue / (0.25 * (double)b_ClockSelection)) >= (double)((double)ul_RealLowTiming + 0.5)) { - ul_RealLowTiming - = - ul_RealLowTiming - + - 1; - } - - ul_LowTiming - = - ul_LowTiming - - - 1; - ul_LowTimerValue - = - ul_LowTimerValue - - - 2; - - if (b_ClockSelection != APCI1710_40MHZ) { - ul_LowTimerValue - = - (unsigned int) - ( - (double) - (ul_LowTimerValue) - * - 1.007752288); - } - - break; - - /******/ - /* ms */ - /******/ - - case 2: - - /******************/ - /* Timer 0 factor */ - /******************/ - - ul_LowTimerValue - = - ul_LowTiming - * - (250.0 - * - b_ClockSelection); - - /*******************/ - /* Round the value */ - /*******************/ - - if ((double)((double)ul_LowTiming * (250.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) { - ul_LowTimerValue - = - ul_LowTimerValue - + - 1; - } - - /*****************************/ - /* Calculate the real timing */ - /*****************************/ - - ul_RealLowTiming - = - (unsigned int) - (ul_LowTimerValue - / - (250.0 * (double)b_ClockSelection)); - d_RealLowTiming - = - (double) - ul_LowTimerValue - / - (250.0 - * - (double) - b_ClockSelection); - - if ((double)((double)ul_LowTimerValue / (250.0 * (double)b_ClockSelection)) >= (double)((double)ul_RealLowTiming + 0.5)) { - ul_RealLowTiming - = - ul_RealLowTiming - + - 1; - } - - ul_LowTiming - = - ul_LowTiming - - - 1; - ul_LowTimerValue - = - ul_LowTimerValue - - - 2; - - if (b_ClockSelection != APCI1710_40MHZ) { - ul_LowTimerValue - = - (unsigned int) - ( - (double) - (ul_LowTimerValue) - * - 1.007752288); - } - - break; - - /*****/ - /* s */ - /*****/ - - case 3: - - /******************/ - /* Timer 0 factor */ - /******************/ - - ul_LowTimerValue - = - (unsigned int) - (ul_LowTiming - * - (250000.0 - * - b_ClockSelection)); - - /*******************/ - /* Round the value */ - /*******************/ - - if ((double)((double)ul_LowTiming * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) { - ul_LowTimerValue - = - ul_LowTimerValue - + - 1; - } - - /*****************************/ - /* Calculate the real timing */ - /*****************************/ - - ul_RealLowTiming - = - (unsigned int) - (ul_LowTimerValue - / - (250000.0 - * - (double) - b_ClockSelection)); - d_RealLowTiming - = - (double) - ul_LowTimerValue - / - (250000.0 - * - (double) - b_ClockSelection); - - if ((double)((double)ul_LowTimerValue / (250000.0 * (double)b_ClockSelection)) >= (double)((double)ul_RealLowTiming + 0.5)) { - ul_RealLowTiming - = - ul_RealLowTiming - + - 1; - } - - ul_LowTiming - = - ul_LowTiming - - - 1; - ul_LowTimerValue - = - ul_LowTimerValue - - - 2; - - if (b_ClockSelection != APCI1710_40MHZ) { - ul_LowTimerValue - = - (unsigned int) - ( - (double) - (ul_LowTimerValue) - * - 1.007752288); - } - - break; - - /******/ - /* mn */ - /******/ - - case 4: - - /******************/ - /* Timer 0 factor */ - /******************/ - - ul_LowTimerValue - = - (unsigned int) - ( - (ul_LowTiming - * - 60) - * - (250000.0 - * - b_ClockSelection)); - - /*******************/ - /* Round the value */ - /*******************/ - - if ((double)((double)(ul_LowTiming * 60.0) * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_LowTimerValue + 0.5))) { - ul_LowTimerValue - = - ul_LowTimerValue - + - 1; - } - - /*****************************/ - /* Calculate the real timing */ - /*****************************/ - - ul_RealLowTiming - = - (unsigned int) - (ul_LowTimerValue - / - (250000.0 - * - (double) - b_ClockSelection)) - / - 60; - d_RealLowTiming - = - ( - (double) - ul_LowTimerValue - / - (250000.0 - * - (double) - b_ClockSelection)) - / - 60.0; - - if ((double)(((double)ul_LowTimerValue / (250000.0 * (double)b_ClockSelection)) / 60.0) >= (double)((double)ul_RealLowTiming + 0.5)) { - ul_RealLowTiming - = - ul_RealLowTiming - + - 1; - } - - ul_LowTiming - = - ul_LowTiming - - - 1; - ul_LowTimerValue - = - ul_LowTimerValue - - - 2; - - if (b_ClockSelection != APCI1710_40MHZ) { - ul_LowTimerValue - = - (unsigned int) - ( - (double) - (ul_LowTimerValue) - * - 1.007752288); - } - - break; - } - - /*************************************/ - /* Calculate the high division fator */ - /*************************************/ - - switch (b_TimingUnit) { - /******/ - /* ns */ - /******/ - - case 0: - - /******************/ - /* Timer 0 factor */ - /******************/ - - ul_HighTimerValue - = - (unsigned int) - (ul_HighTiming - * - (0.00025 * b_ClockSelection)); - - /*******************/ - /* Round the value */ - /*******************/ - - if ((double)((double)ul_HighTiming * (0.00025 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) { - ul_HighTimerValue - = - ul_HighTimerValue - + - 1; - } - - /*****************************/ - /* Calculate the real timing */ - /*****************************/ - - ul_RealHighTiming - = - (unsigned int) - (ul_HighTimerValue - / - (0.00025 * (double)b_ClockSelection)); - d_RealHighTiming - = - (double) - ul_HighTimerValue - / - (0.00025 - * - (double) - b_ClockSelection); - - if ((double)((double)ul_HighTimerValue / (0.00025 * (double)b_ClockSelection)) >= (double)((double)ul_RealHighTiming + 0.5)) { - ul_RealHighTiming - = - ul_RealHighTiming - + - 1; - } - - ul_HighTiming - = - ul_HighTiming - - - 1; - ul_HighTimerValue - = - ul_HighTimerValue - - - 2; - - if (b_ClockSelection != APCI1710_40MHZ) { - ul_HighTimerValue - = - (unsigned int) - ( - (double) - (ul_HighTimerValue) - * - 1.007752288); - } - - break; - - /******/ - /* æs */ - /******/ - - case 1: - - /******************/ - /* Timer 0 factor */ - /******************/ - - ul_HighTimerValue - = - (unsigned int) - (ul_HighTiming - * - (0.25 * b_ClockSelection)); - - /*******************/ - /* Round the value */ - /*******************/ - - if ((double)((double)ul_HighTiming * (0.25 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) { - ul_HighTimerValue - = - ul_HighTimerValue - + - 1; - } - - /*****************************/ - /* Calculate the real timing */ - /*****************************/ - - ul_RealHighTiming - = - (unsigned int) - (ul_HighTimerValue - / - (0.25 * (double)b_ClockSelection)); - d_RealHighTiming - = - (double) - ul_HighTimerValue - / - ( - (double) - 0.25 - * - (double) - b_ClockSelection); - - if ((double)((double)ul_HighTimerValue / (0.25 * (double)b_ClockSelection)) >= (double)((double)ul_RealHighTiming + 0.5)) { - ul_RealHighTiming - = - ul_RealHighTiming - + - 1; - } - - ul_HighTiming - = - ul_HighTiming - - - 1; - ul_HighTimerValue - = - ul_HighTimerValue - - - 2; - - if (b_ClockSelection != APCI1710_40MHZ) { - ul_HighTimerValue - = - (unsigned int) - ( - (double) - (ul_HighTimerValue) - * - 1.007752288); - } - - break; - - /******/ - /* ms */ - /******/ - - case 2: - - /******************/ - /* Timer 0 factor */ - /******************/ - - ul_HighTimerValue - = - ul_HighTiming - * - (250.0 - * - b_ClockSelection); - - /*******************/ - /* Round the value */ - /*******************/ - - if ((double)((double)ul_HighTiming * (250.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) { - ul_HighTimerValue - = - ul_HighTimerValue - + - 1; - } - - /*****************************/ - /* Calculate the real timing */ - /*****************************/ - - ul_RealHighTiming - = - (unsigned int) - (ul_HighTimerValue - / - (250.0 * (double)b_ClockSelection)); - d_RealHighTiming - = - (double) - ul_HighTimerValue - / - (250.0 - * - (double) - b_ClockSelection); - - if ((double)((double)ul_HighTimerValue / (250.0 * (double)b_ClockSelection)) >= (double)((double)ul_RealHighTiming + 0.5)) { - ul_RealHighTiming - = - ul_RealHighTiming - + - 1; - } - - ul_HighTiming - = - ul_HighTiming - - - 1; - ul_HighTimerValue - = - ul_HighTimerValue - - - 2; - - if (b_ClockSelection != APCI1710_40MHZ) { - ul_HighTimerValue - = - (unsigned int) - ( - (double) - (ul_HighTimerValue) - * - 1.007752288); - } - - break; - - /*****/ - /* s */ - /*****/ - - case 3: - - /******************/ - /* Timer 0 factor */ - /******************/ - - ul_HighTimerValue - = - (unsigned int) - (ul_HighTiming - * - (250000.0 - * - b_ClockSelection)); - - /*******************/ - /* Round the value */ - /*******************/ - - if ((double)((double)ul_HighTiming * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) { - ul_HighTimerValue - = - ul_HighTimerValue - + - 1; - } - - /*****************************/ - /* Calculate the real timing */ - /*****************************/ - - ul_RealHighTiming - = - (unsigned int) - (ul_HighTimerValue - / - (250000.0 - * - (double) - b_ClockSelection)); - d_RealHighTiming - = - (double) - ul_HighTimerValue - / - (250000.0 - * - (double) - b_ClockSelection); - - if ((double)((double)ul_HighTimerValue / (250000.0 * (double)b_ClockSelection)) >= (double)((double)ul_RealHighTiming + 0.5)) { - ul_RealHighTiming - = - ul_RealHighTiming - + - 1; - } - - ul_HighTiming - = - ul_HighTiming - - - 1; - ul_HighTimerValue - = - ul_HighTimerValue - - - 2; - - if (b_ClockSelection != APCI1710_40MHZ) { - ul_HighTimerValue - = - (unsigned int) - ( - (double) - (ul_HighTimerValue) - * - 1.007752288); - } - - break; - - /******/ - /* mn */ - /******/ - - case 4: - - /******************/ - /* Timer 0 factor */ - /******************/ - - ul_HighTimerValue - = - (unsigned int) - ( - (ul_HighTiming - * - 60) - * - (250000.0 - * - b_ClockSelection)); - - /*******************/ - /* Round the value */ - /*******************/ - - if ((double)((double)(ul_HighTiming * 60.0) * (250000.0 * (double)b_ClockSelection)) >= ((double)((double)ul_HighTimerValue + 0.5))) { - ul_HighTimerValue - = - ul_HighTimerValue - + - 1; - } - - /*****************************/ - /* Calculate the real timing */ - /*****************************/ - - ul_RealHighTiming - = - (unsigned int) - (ul_HighTimerValue - / - (250000.0 - * - (double) - b_ClockSelection)) - / - 60; - d_RealHighTiming - = - ( - (double) - ul_HighTimerValue - / - (250000.0 - * - (double) - b_ClockSelection)) - / - 60.0; - - if ((double)(((double)ul_HighTimerValue / (250000.0 * (double)b_ClockSelection)) / 60.0) >= (double)((double)ul_RealHighTiming + 0.5)) { - ul_RealHighTiming - = - ul_RealHighTiming - + - 1; - } - - ul_HighTiming - = - ul_HighTiming - - - 1; - ul_HighTimerValue - = - ul_HighTimerValue - - - 2; - - if (b_ClockSelection != APCI1710_40MHZ) { - ul_HighTimerValue - = - (unsigned int) - ( - (double) - (ul_HighTimerValue) - * - 1.007752288); - } - - break; - } - - fpu_end(); - - /************************/ - /* Save the timing unit */ - /************************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_PWMModuleInfo. - s_PWMInfo - [b_PWM]. - b_TimingUnit - = - b_TimingUnit; - - /****************************/ - /* Save the low base timing */ - /****************************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_PWMModuleInfo. - s_PWMInfo - [b_PWM]. - d_LowTiming - = - d_RealLowTiming; - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_PWMModuleInfo. - s_PWMInfo - [b_PWM]. - ul_RealLowTiming - = - ul_RealLowTiming; - - /****************************/ - /* Save the high base timing */ - /****************************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_PWMModuleInfo. - s_PWMInfo - [b_PWM]. - d_HighTiming - = - d_RealHighTiming; - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_PWMModuleInfo. - s_PWMInfo - [b_PWM]. - ul_RealHighTiming - = - ul_RealHighTiming; - - /************************/ - /* Write the low timing */ - /************************/ - - outl(ul_LowTimerValue, devpriv->s_BoardInfos.ui_Address + 0 + (20 * b_PWM) + (64 * b_ModulNbr)); - - /*************************/ - /* Write the high timing */ - /*************************/ - - outl(ul_HighTimerValue, devpriv->s_BoardInfos.ui_Address + 4 + (20 * b_PWM) + (64 * b_ModulNbr)); - - /***************************/ - /* Set the clock selection */ - /***************************/ - - dw_Command = - inl - (devpriv-> - s_BoardInfos. - ui_Address - + 8 + - (20 * b_PWM) + (64 * b_ModulNbr)); - - dw_Command = - dw_Command - & 0x7F; - - if (b_ClockSelection == APCI1710_40MHZ) { - dw_Command - = - dw_Command - | - 0x80; - } - - /***************************/ - /* Set the clock selection */ - /***************************/ - - outl(dw_Command, - devpriv-> - s_BoardInfos. - ui_Address - + 8 + - (20 * b_PWM) + (64 * b_ModulNbr)); - } else { - /***************************************/ - /* High base timing selection is wrong */ - /***************************************/ - DPRINTK("High base timing selection is wrong\n"); - i_ReturnValue = - -8; - } - } else { - /**************************************/ - /* Low base timing selection is wrong */ - /**************************************/ - DPRINTK("Low base timing selection is wrong\n"); - i_ReturnValue = -7; - } - } /* if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) */ - else { - /**********************************/ - /* Timing unit selection is wrong */ - /**********************************/ - DPRINTK("Timing unit selection is wrong\n"); - i_ReturnValue = -6; - } /* if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) */ - } /* if (dw_Status & 0x10) */ - else { - /***********************/ - /* PWM not initialised */ - /***********************/ - DPRINTK("PWM not initialised\n"); - i_ReturnValue = -5; - } /* if (dw_Status & 0x10) */ - } /* if (b_PWM >= 0 && b_PWM <= 1) */ - else { - /******************************/ - /* Tor PWM selection is wrong */ - /******************************/ - DPRINTK("Tor PWM selection is wrong\n"); - i_ReturnValue = -4; - } /* if (b_PWM >= 0 && b_PWM <= 1) */ - } else { - /**********************************/ - /* The module is not a PWM module */ - /**********************************/ - DPRINTK("The module is not a PWM module\n"); - i_ReturnValue = -3; - } - } else { - /***********************/ - /* Module number error */ - /***********************/ - DPRINTK("Module number error\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* - * Pwm Enable Disable and Set New Timing - */ -static int i_APCI1710_InsnWritePWM(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - unsigned char b_WriteType; - int i_ReturnValue = 0; - b_WriteType = CR_CHAN(insn->chanspec); - - switch (b_WriteType) { - case APCI1710_PWM_ENABLE: - i_ReturnValue = i_APCI1710_EnablePWM(dev, - (unsigned char) CR_AREF(insn->chanspec), - (unsigned char) data[0], - (unsigned char) data[1], - (unsigned char) data[2], - (unsigned char) data[3], (unsigned char) data[4], (unsigned char) data[5]); - break; - - case APCI1710_PWM_DISABLE: - i_ReturnValue = i_APCI1710_DisablePWM(dev, - (unsigned char) CR_AREF(insn->chanspec), (unsigned char) data[0]); - break; - - case APCI1710_PWM_NEWTIMING: - i_ReturnValue = i_APCI1710_SetNewPWMTiming(dev, - (unsigned char) CR_AREF(insn->chanspec), - (unsigned char) data[0], - (unsigned char) data[1], (unsigned int) data[2], (unsigned int) data[3]); - break; - - default: - printk("Write Config Parameter Wrong\n"); - } - - if (i_ReturnValue >= 0) - i_ReturnValue = insn->n; - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_GetPWMStatus | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_PWM, | -| unsigned char *_ pb_PWMOutputStatus, | -| unsigned char *_ pb_ExternGateStatus) | -+----------------------------------------------------------------------------+ -| Task : Return the status from selected PWM (b_PWM) from | -| selected module (b_ModulNbr). | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_PWM : Selected PWM (0 or 1) | -| unsigned char_ b_ModulNbr : Selected module number (0 to 3) - b_ModulNbr =(unsigned char) CR_AREF(insn->chanspec); - b_PWM =(unsigned char) data[0]; - - | -+----------------------------------------------------------------------------+ -| Output Parameters : unsigned char *_ pb_PWMOutputStatus : Return the PWM output | -| level status. | -| 0 : The PWM output level| -| is low. | -| 1 : The PWM output level| -| is high. | -| unsigned char *_ pb_ExternGateStatus : Return the extern gate | -| level status. | -| 0 : The extern gate is | -| low. | -| 1 : The extern gate is | -| high. - pb_PWMOutputStatus =(unsigned char *) data[0]; - pb_ExternGateStatus =(unsigned char *) data[1]; | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: Module selection wrong | -| -3: The module is not a PWM module | -| -4: PWM selection is wrong | -| -5: PWM not initialised see function | -| "i_APCI1710_InitPWM" | -| -6: PWM not enabled see function "i_APCI1710_EnablePWM"| -+----------------------------------------------------------------------------+ -*/ -static int i_APCI1710_InsnReadGetPWMStatus(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned int dw_Status; - unsigned char b_ModulNbr; - unsigned char b_PWM; - unsigned char *pb_PWMOutputStatus; - unsigned char *pb_ExternGateStatus; - - i_ReturnValue = insn->n; - b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec); - b_PWM = (unsigned char) CR_CHAN(insn->chanspec); - pb_PWMOutputStatus = (unsigned char *) &data[0]; - pb_ExternGateStatus = (unsigned char *) &data[1]; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /***************/ - /* Test if PWM */ - /***************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModulNbr] & - 0xFFFF0000UL) == APCI1710_PWM) { - /**************************/ - /* Test the PWM selection */ - /**************************/ - - if (b_PWM <= 1) { - /***************************/ - /* Test if PWM initialised */ - /***************************/ - - dw_Status = inl(devpriv->s_BoardInfos. - ui_Address + 12 + (20 * b_PWM) + - (64 * b_ModulNbr)); - - if (dw_Status & 0x10) { - /***********************/ - /* Test if PWM enabled */ - /***********************/ - - if (dw_Status & 0x1) { - *pb_PWMOutputStatus = - (unsigned char) ((dw_Status >> 7) - & 1); - *pb_ExternGateStatus = - (unsigned char) ((dw_Status >> 6) - & 1); - } /* if (dw_Status & 0x1) */ - else { - /*******************/ - /* PWM not enabled */ - /*******************/ - - DPRINTK("PWM not enabled \n"); - i_ReturnValue = -6; - } /* if (dw_Status & 0x1) */ - } /* if (dw_Status & 0x10) */ - else { - /***********************/ - /* PWM not initialised */ - /***********************/ - - DPRINTK("PWM not initialised\n"); - i_ReturnValue = -5; - } /* if (dw_Status & 0x10) */ - } /* if (b_PWM >= 0 && b_PWM <= 1) */ - else { - /******************************/ - /* Tor PWM selection is wrong */ - /******************************/ - - DPRINTK("Tor PWM selection is wrong\n"); - i_ReturnValue = -4; - } /* if (b_PWM >= 0 && b_PWM <= 1) */ - } else { - /**********************************/ - /* The module is not a PWM module */ - /**********************************/ - - DPRINTK("The module is not a PWM module\n"); - i_ReturnValue = -3; - } - } else { - /***********************/ - /* Module number error */ - /***********************/ - - DPRINTK("Module number error\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -static int i_APCI1710_InsnBitsReadPWMInterrupt(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct addi_private *devpriv = dev->private; - - data[0] = devpriv->s_InterruptParameters. - s_FIFOInterruptParameters[devpriv-> - s_InterruptParameters.ui_Read].b_OldModuleMask; - data[1] = devpriv->s_InterruptParameters. - s_FIFOInterruptParameters[devpriv-> - s_InterruptParameters.ui_Read].ul_OldInterruptMask; - data[2] = devpriv->s_InterruptParameters. - s_FIFOInterruptParameters[devpriv-> - s_InterruptParameters.ui_Read].ul_OldCounterLatchValue; - - /**************************/ - /* Increment the read FIFO */ - /***************************/ - - devpriv-> - s_InterruptParameters. - ui_Read = (devpriv-> - s_InterruptParameters.ui_Read + 1) % APCI1710_SAVE_INTERRUPT; - - return insn->n; - -} diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c deleted file mode 100644 index 6ef1d6a434d9..000000000000 --- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c +++ /dev/null @@ -1,845 +0,0 @@ -/** -@verbatim - -Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. - - ADDI-DATA GmbH - Dieselstrasse 3 - D-77833 Ottersweier - Tel: +19(0)7223/9493-0 - Fax: +49(0)7223/9493-92 - http://www.addi-data.com - info@addi-data.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. - -@endverbatim -*/ -/* - - +-----------------------------------------------------------------------+ - | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier | - +-----------------------------------------------------------------------+ - | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | - | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | - +-----------------------------------------------------------------------+ - | Project : API APCI1710 | Compiler : gcc | - | Module name : SSI.C | Version : 2.96 | - +-------------------------------+---------------------------------------+ - | Project manager: Eric Stolz | Date : 02/12/2002 | - +-----------------------------------------------------------------------+ - | Description : APCI-1710 SSI counter module | - +-----------------------------------------------------------------------+ - | several changes done by S. Weber in 1998 and C. Guinot in 2000 | - +-----------------------------------------------------------------------+ -*/ - -#define APCI1710_30MHZ 30 -#define APCI1710_33MHZ 33 -#define APCI1710_40MHZ 40 - -#define APCI1710_BINARY_MODE 0x1 -#define APCI1710_GRAY_MODE 0x0 - -#define APCI1710_SSI_READ1VALUE 1 -#define APCI1710_SSI_READALLVALUE 2 - -#define APCI1710_SSI_SET_CHANNELON 0 -#define APCI1710_SSI_SET_CHANNELOFF 1 -#define APCI1710_SSI_READ_1CHANNEL 2 -#define APCI1710_SSI_READ_ALLCHANNEL 3 - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_InitSSI | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_SSIProfile, | -| unsigned char_ b_PositionTurnLength, | -| unsigned char_ b_TurnCptLength, | -| unsigned char_ b_PCIInputClock, | -| ULONG_ ul_SSIOutputClock, | -| unsigned char_ b_SSICountingMode) | -+----------------------------------------------------------------------------+ -| Task : Configure the SSI operating mode from selected module | -| (b_ModulNbr). You must calling this function be for you| -| call any other function witch access of SSI. | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710| -| unsigned char_ b_ModulNbr : Module number to | -| configure (0 to 3) | -| unsigned char_ b_SSIProfile : Selection from SSI | -| profile length (2 to 32).| -| unsigned char_ b_PositionTurnLength : Selection from SSI | -| position data length | -| (1 to 31). | -| unsigned char_ b_TurnCptLength : Selection from SSI turn | -| counter data length | -| (1 to 31). | -| unsigned char b_PCIInputClock : Selection from PCI bus | -| clock | -| - APCI1710_30MHZ : | -| The PC have a PCI bus | -| clock from 30 MHz | -| - APCI1710_33MHZ : | -| The PC have a PCI bus | -| clock from 33 MHz | -| ULONG_ ul_SSIOutputClock : Selection from SSI output| -| clock. | -| From 229 to 5 000 000 Hz| -| for 30 MHz selection. | -| From 252 to 5 000 000 Hz| -| for 33 MHz selection. | -| unsigned char b_SSICountingMode : SSI counting mode | -| selection | -| - APCI1710_BINARY_MODE : | -| Binary counting mode. | -| - APCI1710_GRAY_MODE : | -| Gray counting mode. - - b_ModulNbr = CR_AREF(insn->chanspec); - b_SSIProfile = (unsigned char) data[0]; - b_PositionTurnLength= (unsigned char) data[1]; - b_TurnCptLength = (unsigned char) data[2]; - b_PCIInputClock = (unsigned char) data[3]; - ul_SSIOutputClock = (unsigned int) data[4]; - b_SSICountingMode = (unsigned char) data[5]; | -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: The module parameter is wrong | -| -3: The module is not a SSI module | -| -4: The selected SSI profile length is wrong | -| -5: The selected SSI position data length is wrong | -| -6: The selected SSI turn counter data length is wrong | -| -7: The selected PCI input clock is wrong | -| -8: The selected SSI output clock is wrong | -| -9: The selected SSI counting mode parameter is wrong | -+----------------------------------------------------------------------------+ -*/ - -static int i_APCI1710_InsnConfigInitSSI(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned int ui_TimerValue; - unsigned char b_ModulNbr, b_SSIProfile, b_PositionTurnLength, b_TurnCptLength, - b_PCIInputClock, b_SSICountingMode; - unsigned int ul_SSIOutputClock; - - b_ModulNbr = CR_AREF(insn->chanspec); - b_SSIProfile = (unsigned char) data[0]; - b_PositionTurnLength = (unsigned char) data[1]; - b_TurnCptLength = (unsigned char) data[2]; - b_PCIInputClock = (unsigned char) data[3]; - ul_SSIOutputClock = (unsigned int) data[4]; - b_SSICountingMode = (unsigned char) data[5]; - - i_ReturnValue = insn->n; - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /***********************/ - /* Test if SSI counter */ - /***********************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModulNbr] & - 0xFFFF0000UL) == APCI1710_SSI_COUNTER) { - /*******************************/ - /* Test the SSI profile length */ - /*******************************/ - - /* CG 22/03/00 b_SSIProfile >= 2 anstatt b_SSIProfile > 2 */ - if (b_SSIProfile >= 2 && b_SSIProfile < 33) { - /*************************************/ - /* Test the SSI position data length */ - /*************************************/ - - if (b_PositionTurnLength > 0 - && b_PositionTurnLength < 32) { - /*****************************************/ - /* Test the SSI turn counter data length */ - /*****************************************/ - - if (b_TurnCptLength > 0 - && b_TurnCptLength < 32) { - /***************************/ - /* Test the profile length */ - /***************************/ - - if ((b_TurnCptLength + - b_PositionTurnLength) - <= b_SSIProfile) { - /****************************/ - /* Test the PCI input clock */ - /****************************/ - - if (b_PCIInputClock == - APCI1710_30MHZ - || - b_PCIInputClock - == - APCI1710_33MHZ) - { - /*************************/ - /* Test the output clock */ - /*************************/ - - if ((b_PCIInputClock == APCI1710_30MHZ && (ul_SSIOutputClock > 228 && ul_SSIOutputClock <= 5000000UL)) || (b_PCIInputClock == APCI1710_33MHZ && (ul_SSIOutputClock > 251 && ul_SSIOutputClock <= 5000000UL))) { - if (b_SSICountingMode == APCI1710_BINARY_MODE || b_SSICountingMode == APCI1710_GRAY_MODE) { - /**********************/ - /* Save configuration */ - /**********************/ - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SSICounterInfo. - b_SSIProfile - = - b_SSIProfile; - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SSICounterInfo. - b_PositionTurnLength - = - b_PositionTurnLength; - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SSICounterInfo. - b_TurnCptLength - = - b_TurnCptLength; - - /*********************************/ - /* Initialise the profile length */ - /*********************************/ - - if (b_SSICountingMode == APCI1710_BINARY_MODE) { - - outl(b_SSIProfile + 1, devpriv->s_BoardInfos.ui_Address + 4 + (64 * b_ModulNbr)); - } else { - - outl(b_SSIProfile, devpriv->s_BoardInfos.ui_Address + 4 + (64 * b_ModulNbr)); - } - - /******************************/ - /* Calculate the output clock */ - /******************************/ - - ui_TimerValue - = - (unsigned int) - ( - ((unsigned int) (b_PCIInputClock) * 500000UL) / ul_SSIOutputClock); - - /************************/ - /* Initialise the timer */ - /************************/ - - outl(ui_TimerValue, devpriv->s_BoardInfos.ui_Address + (64 * b_ModulNbr)); - - /********************************/ - /* Initialise the counting mode */ - /********************************/ - - outl(7 * b_SSICountingMode, devpriv->s_BoardInfos.ui_Address + 12 + (64 * b_ModulNbr)); - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SSICounterInfo. - b_SSIInit - = - 1; - } else { - /*****************************************************/ - /* The selected SSI counting mode parameter is wrong */ - /*****************************************************/ - - DPRINTK("The selected SSI counting mode parameter is wrong\n"); - i_ReturnValue - = - -9; - } - } else { - /******************************************/ - /* The selected SSI output clock is wrong */ - /******************************************/ - - DPRINTK("The selected SSI output clock is wrong\n"); - i_ReturnValue - = - -8; - } - } else { - /*****************************************/ - /* The selected PCI input clock is wrong */ - /*****************************************/ - - DPRINTK("The selected PCI input clock is wrong\n"); - i_ReturnValue = - -7; - } - } else { - /********************************************/ - /* The selected SSI profile length is wrong */ - /********************************************/ - - DPRINTK("The selected SSI profile length is wrong\n"); - i_ReturnValue = -4; - } - } else { - /******************************************************/ - /* The selected SSI turn counter data length is wrong */ - /******************************************************/ - - DPRINTK("The selected SSI turn counter data length is wrong\n"); - i_ReturnValue = -6; - } - } else { - /**************************************************/ - /* The selected SSI position data length is wrong */ - /**************************************************/ - - DPRINTK("The selected SSI position data length is wrong\n"); - i_ReturnValue = -5; - } - } else { - /********************************************/ - /* The selected SSI profile length is wrong */ - /********************************************/ - - DPRINTK("The selected SSI profile length is wrong\n"); - i_ReturnValue = -4; - } - } else { - /**********************************/ - /* The module is not a SSI module */ - /**********************************/ - - DPRINTK("The module is not a SSI module\n"); - i_ReturnValue = -3; - } - } else { - /***********************/ - /* Module number error */ - /***********************/ - - DPRINTK("Module number error\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_Read1SSIValue | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_SelectedSSI, | -| PULONG_ pul_Position, | -| PULONG_ pul_TurnCpt) - int i_APCI1710_ReadSSIValue(struct comedi_device *dev,struct comedi_subdevice *s, - struct comedi_insn *insn,unsigned int *data) | -+----------------------------------------------------------------------------+ -| Task : - - - Read the selected SSI counter (b_SelectedSSI) from | -| selected module (b_ModulNbr). - or Read all SSI counter (b_SelectedSSI) from | -| selected module (b_ModulNbr). | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710| -| unsigned char_ b_ModulNbr : Module number to | -| configure (0 to 3) | -| unsigned char_ b_SelectedSSI : Selection from SSI | -| counter (0 to 2) - - b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec); - b_SelectedSSI = (unsigned char) CR_CHAN(insn->chanspec); (in case of single ssi) - b_ReadType = (unsigned char) CR_RANGE(insn->chanspec); -| -+----------------------------------------------------------------------------+ -| Output Parameters : PULONG_ pul_Position : SSI position in the turn | -| PULONG_ pul_TurnCpt : Number of turns - -pul_Position = (unsigned int *) &data[0]; - pul_TurnCpt = (unsigned int *) &data[1]; | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: The module parameter is wrong | -| -3: The module is not a SSI module | -| -4: SSI not initialised see function | -| "i_APCI1710_InitSSI" | -| -5: The selected SSI is wrong | -+----------------------------------------------------------------------------+ -*/ - -static int i_APCI1710_InsnReadSSIValue(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned char b_Cpt; - unsigned char b_Length; - unsigned char b_Schift; - unsigned char b_SSICpt; - unsigned int dw_And; - unsigned int dw_And1; - unsigned int dw_And2; - unsigned int dw_StatusReg; - unsigned int dw_CounterValue; - unsigned char b_ModulNbr; - unsigned char b_SelectedSSI; - unsigned char b_ReadType; - unsigned int *pul_Position; - unsigned int *pul_TurnCpt; - unsigned int *pul_Position1; - unsigned int *pul_TurnCpt1; - - i_ReturnValue = insn->n; - pul_Position1 = (unsigned int *) &data[0]; -/* For Read1 */ - pul_TurnCpt1 = (unsigned int *) &data[1]; -/* For Read all */ - pul_Position = (unsigned int *) &data[0]; /* 0-2 */ - pul_TurnCpt = (unsigned int *) &data[3]; /* 3-5 */ - b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec); - b_SelectedSSI = (unsigned char) CR_CHAN(insn->chanspec); - b_ReadType = (unsigned char) CR_RANGE(insn->chanspec); - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /***********************/ - /* Test if SSI counter */ - /***********************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModulNbr] & - 0xFFFF0000UL) == APCI1710_SSI_COUNTER) { - /***************************/ - /* Test if SSI initialised */ - /***************************/ - - if (devpriv->s_ModuleInfo[b_ModulNbr]. - s_SSICounterInfo.b_SSIInit == 1) { - - switch (b_ReadType) { - - case APCI1710_SSI_READ1VALUE: - /****************************************/ - /* Test the selected SSI counter number */ - /****************************************/ - - if (b_SelectedSSI < 3) { - /************************/ - /* Start the conversion */ - /************************/ - - outl(0, devpriv->s_BoardInfos. - ui_Address + 8 + - (64 * b_ModulNbr)); - - do { - /*******************/ - /* Read the status */ - /*******************/ - - dw_StatusReg = - inl(devpriv-> - s_BoardInfos. - ui_Address + - (64 * b_ModulNbr)); - } while ((dw_StatusReg & 0x1) - != 0); - - /******************************/ - /* Read the SSI counter value */ - /******************************/ - - dw_CounterValue = - inl(devpriv-> - s_BoardInfos. - ui_Address + 4 + - (b_SelectedSSI * 4) + - (64 * b_ModulNbr)); - - b_Length = - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SSICounterInfo. - b_SSIProfile / 2; - - if ((b_Length * 2) != - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SSICounterInfo. - b_SSIProfile) { - b_Length++; - } - - b_Schift = - b_Length - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SSICounterInfo. - b_PositionTurnLength; - - *pul_Position1 = - dw_CounterValue >> - b_Schift; - - dw_And = 1; - - for (b_Cpt = 0; - b_Cpt < - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SSICounterInfo. - b_PositionTurnLength; - b_Cpt++) { - dw_And = dw_And * 2; - } - - *pul_Position1 = - *pul_Position1 & - ((dw_And) - 1); - - *pul_TurnCpt1 = - dw_CounterValue >> - b_Length; - - dw_And = 1; - - for (b_Cpt = 0; - b_Cpt < - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SSICounterInfo. - b_TurnCptLength; - b_Cpt++) { - dw_And = dw_And * 2; - } - - *pul_TurnCpt1 = - *pul_TurnCpt1 & - ((dw_And) - 1); - } else { - /*****************************/ - /* The selected SSI is wrong */ - /*****************************/ - - DPRINTK("The selected SSI is wrong\n"); - i_ReturnValue = -5; - } - break; - - case APCI1710_SSI_READALLVALUE: - dw_And1 = 1; - - for (b_Cpt = 0; - b_Cpt < - devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SSICounterInfo. - b_PositionTurnLength; b_Cpt++) { - dw_And1 = dw_And1 * 2; - } - - dw_And2 = 1; - - for (b_Cpt = 0; - b_Cpt < - devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_SSICounterInfo. - b_TurnCptLength; b_Cpt++) { - dw_And2 = dw_And2 * 2; - } - - /************************/ - /* Start the conversion */ - /************************/ - - outl(0, devpriv->s_BoardInfos. - ui_Address + 8 + - (64 * b_ModulNbr)); - - do { - /*******************/ - /* Read the status */ - /*******************/ - - dw_StatusReg = - inl(devpriv-> - s_BoardInfos. - ui_Address + - (64 * b_ModulNbr)); - } while ((dw_StatusReg & 0x1) != 0); - - for (b_SSICpt = 0; b_SSICpt < 3; - b_SSICpt++) { - /******************************/ - /* Read the SSI counter value */ - /******************************/ - - dw_CounterValue = - inl(devpriv-> - s_BoardInfos. - ui_Address + 4 + - (b_SSICpt * 4) + - (64 * b_ModulNbr)); - - b_Length = - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SSICounterInfo. - b_SSIProfile / 2; - - if ((b_Length * 2) != - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SSICounterInfo. - b_SSIProfile) { - b_Length++; - } - - b_Schift = - b_Length - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_SSICounterInfo. - b_PositionTurnLength; - - pul_Position[b_SSICpt] = - dw_CounterValue >> - b_Schift; - pul_Position[b_SSICpt] = - pul_Position[b_SSICpt] & - ((dw_And1) - 1); - - pul_TurnCpt[b_SSICpt] = - dw_CounterValue >> - b_Length; - pul_TurnCpt[b_SSICpt] = - pul_TurnCpt[b_SSICpt] & - ((dw_And2) - 1); - } - break; - - default: - printk("Read Type Inputs Wrong\n"); - - } /* switch ending */ - - } else { - /***********************/ - /* SSI not initialised */ - /***********************/ - - DPRINTK("SSI not initialised\n"); - i_ReturnValue = -4; - } - } else { - /**********************************/ - /* The module is not a SSI module */ - /**********************************/ - - DPRINTK("The module is not a SSI module\n"); - i_ReturnValue = -3; - - } - } else { - /***********************/ - /* Module number error */ - /***********************/ - - DPRINTK("Module number error\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_ReadSSI1DigitalInput | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_InputChannel, | -| unsigned char *_ pb_ChannelStatus) | -+----------------------------------------------------------------------------+ -| Task : - (0) Set the digital output from selected SSI module | -| (b_ModuleNbr) ON - (1) Set the digital output from selected SSI module | -| (b_ModuleNbr) OFF - (2)Read the status from selected SSI digital input | -| (b_InputChannel) - (3)Read the status from all SSI digital inputs from | -| selected SSI module (b_ModulNbr) | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710| -| unsigned char_ b_ModulNbr CR_AREF : Module number to | -| configure (0 to 3) | -| unsigned char_ b_InputChannel CR_CHAN : Selection from digital | -| data[0] which IOTYPE input ( 0 to 2) | -+----------------------------------------------------------------------------+ -| Output Parameters : unsigned char *_ pb_ChannelStatus : Digital input channel | -| data[0] status | -| 0 : Channle is not active| -| 1 : Channle is active | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: The module parameter is wrong | -| -3: The module is not a SSI module | -| -4: The selected SSI digital input is wrong | -+----------------------------------------------------------------------------+ -*/ - -static int i_APCI1710_InsnBitsSSIDigitalIO(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned int dw_StatusReg; - unsigned char b_ModulNbr; - unsigned char b_InputChannel; - unsigned char *pb_ChannelStatus; - unsigned char *pb_InputStatus; - unsigned char b_IOType; - - i_ReturnValue = insn->n; - b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec); - b_IOType = (unsigned char) data[0]; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /***********************/ - /* Test if SSI counter */ - /***********************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModulNbr] & - 0xFFFF0000UL) == APCI1710_SSI_COUNTER) { - switch (b_IOType) { - case APCI1710_SSI_SET_CHANNELON: - /*****************************/ - /* Set the digital output ON */ - /*****************************/ - - outl(1, devpriv->s_BoardInfos.ui_Address + 16 + - (64 * b_ModulNbr)); - break; - - case APCI1710_SSI_SET_CHANNELOFF: - /******************************/ - /* Set the digital output OFF */ - /******************************/ - - outl(0, devpriv->s_BoardInfos.ui_Address + 16 + - (64 * b_ModulNbr)); - break; - - case APCI1710_SSI_READ_1CHANNEL: - /******************************************/ - /* Test the digital imnput channel number */ - /******************************************/ - - b_InputChannel = (unsigned char) CR_CHAN(insn->chanspec); - pb_ChannelStatus = (unsigned char *) &data[0]; - - if (b_InputChannel <= 2) { - /**************************/ - /* Read all digital input */ - /**************************/ - - dw_StatusReg = - inl(devpriv->s_BoardInfos. - ui_Address + (64 * b_ModulNbr)); - *pb_ChannelStatus = - (unsigned char) (((~dw_StatusReg) >> (4 + - b_InputChannel)) - & 1); - } else { - /********************************/ - /* Selected digital input error */ - /********************************/ - - DPRINTK("Selected digital input error\n"); - i_ReturnValue = -4; - } - break; - - case APCI1710_SSI_READ_ALLCHANNEL: - /**************************/ - /* Read all digital input */ - /**************************/ - pb_InputStatus = (unsigned char *) &data[0]; - - dw_StatusReg = - inl(devpriv->s_BoardInfos.ui_Address + - (64 * b_ModulNbr)); - *pb_InputStatus = - (unsigned char) (((~dw_StatusReg) >> 4) & 7); - break; - - default: - printk("IO type wrong\n"); - - } /* switch end */ - } else { - /**********************************/ - /* The module is not a SSI module */ - /**********************************/ - - DPRINTK("The module is not a SSI module\n"); - i_ReturnValue = -3; - } - } else { - /***********************/ - /* Module number error */ - /***********************/ - - DPRINTK("Module number error\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c deleted file mode 100644 index 0b79531ac24b..000000000000 --- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c +++ /dev/null @@ -1,2065 +0,0 @@ -/** -@verbatim - -Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. - - ADDI-DATA GmbH - Dieselstrasse 3 - D-77833 Ottersweier - Tel: +19(0)7223/9493-0 - Fax: +49(0)7223/9493-92 - http://www.addi-data.com - info@addi-data.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. - -@endverbatim -*/ -/* - - +-----------------------------------------------------------------------+ - | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier | - +-----------------------------------------------------------------------+ - | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | - | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | - +-----------------------------------------------------------------------+ - | Project : API APCI1710 | Compiler : gcc | - | Module name : TOR.C | Version : 2.96 | - +-------------------------------+---------------------------------------+ - | Project manager: Eric Stolz | Date : 02/12/2002 | - +-----------------------------------------------------------------------+ - | Description : APCI-1710 tor counter module | - | | - | | - +-----------------------------------------------------------------------+ - | UPDATES | - +-----------------------------------------------------------------------+ - | Date | Author | Description of updates | - +----------+-----------+------------------------------------------------+ - | 27/01/99 | S. Weber | 40 MHz implementation | - +-----------------------------------------------------------------------+ - | 28/04/00 | S. Weber | Simple,double and quadruple mode implementation| - | | | Extern clock implementation | - +-----------------------------------------------------------------------+ - | 08/05/00 | Guinot C | - 0400/0228 All Function in RING 0 | - | | | available | - +-----------------------------------------------------------------------+ -*/ - -#define APCI1710_30MHZ 30 -#define APCI1710_33MHZ 33 -#define APCI1710_40MHZ 40 - -#define APCI1710_GATE_INPUT 10 - -#define APCI1710_TOR_SIMPLE_MODE 2 -#define APCI1710_TOR_DOUBLE_MODE 3 -#define APCI1710_TOR_QUADRUPLE_MODE 4 - -#define APCI1710_SINGLE 0 -#define APCI1710_CONTINUOUS 1 - -#define APCI1710_TOR_GETPROGRESSSTATUS 0 -#define APCI1710_TOR_GETCOUNTERVALUE 1 -#define APCI1710_TOR_READINTERRUPT 2 - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_InitTorCounter | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_TorCounter, | -| unsigned char_ b_PCIInputClock, | -| unsigned char_ b_TimingUnit, | -| ULONG_ ul_TimingInterval, | -| PULONG_ pul_RealTimingInterval) | -+----------------------------------------------------------------------------+ -| Task : Configure the selected tor counter (b_TorCounter) | -| from selected module (b_ModulNbr). | -| The ul_TimingInterval and ul_TimingUnit determine the | -| timing base for the measurement. | -| The pul_RealTimingInterval return the real timing | -| value. You must calling this function be for you call | -| any other function witch access of the tor counter. | -| | -+----------------------------------------------------------------------------+ -| Input Parameters : | -| - CR_AREF unsigned char_ b_ModulNbr : Module number to configure | -| (0 to 3) | -| data[0] unsigned char_ b_TorCounter : Tor counter selection | -| (0 or 1). | -| data[1] unsigned char_ b_PCIInputClock : Selection from PCI bus clock| -| - APCI1710_30MHZ : | -| The PC have a PCI bus | -| clock from 30 MHz | -| - APCI1710_33MHZ : | -| The PC have a PCI bus | -| clock from 33 MHz | -| - APCI1710_40MHZ | -| The APCI-1710 have a | -| integrated 40Mhz | -| quartz. | -| - APCI1710_GATE_INPUT | -| Used the gate input for | -| the base clock. If you | -| have selected this option,| -| than it is not possibl to | -| used the gate input for | -| enabled the acquisition | -| data[2] unsigned char_ b_TimingUnit : Base timing unit (0 to 4) | -| 0 : ns | -| 1 : µs | -| 2 : ms | -| 3 : s | -| 4 : mn | -| data[3] ULONG_ ul_TimingInterval : Base timing value. | -+----------------------------------------------------------------------------+ -| Output Parameters : PULONG_ pul_RealTimingInterval : Real base timing | -| data[0] value. | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: Module selection wrong | -| -3: The module is not a tor counter module | -| -4: Tor counter selection is wrong | -| -5: The selected PCI input clock is wrong | -| -6: Timing unit selection is wrong | -| -7: Base timing selection is wrong | -| -8: You can not used the 40MHz clock selection wich | -| this board | -| -9: You can not used the 40MHz clock selection wich | -| this TOR version | -+----------------------------------------------------------------------------+ -*/ - -static int i_APCI1710_InsnConfigInitTorCounter(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned int ul_TimerValue = 0; - unsigned int dw_Command; - double d_RealTimingInterval = 0; - unsigned char b_ModulNbr; - unsigned char b_TorCounter; - unsigned char b_PCIInputClock; - unsigned char b_TimingUnit; - unsigned int ul_TimingInterval; - unsigned int ul_RealTimingInterval = 0; - - i_ReturnValue = insn->n; - b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec); - - b_TorCounter = (unsigned char) data[0]; - b_PCIInputClock = (unsigned char) data[1]; - b_TimingUnit = (unsigned char) data[2]; - ul_TimingInterval = (unsigned int) data[3]; - printk("INPUT clock %d\n", b_PCIInputClock); - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /***********************/ - /* Test if tor counter */ - /***********************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModulNbr] & - 0xFFFF0000UL) == APCI1710_TOR_COUNTER) { - /**********************************/ - /* Test the tor counter selection */ - /**********************************/ - - if (b_TorCounter <= 1) { - /**************************/ - /* Test the PCI bus clock */ - /**************************/ - - if ((b_PCIInputClock == APCI1710_30MHZ) || - (b_PCIInputClock == APCI1710_33MHZ) || - (b_PCIInputClock == APCI1710_40MHZ) || - (b_PCIInputClock == - APCI1710_GATE_INPUT)) { - /************************/ - /* Test the timing unit */ - /************************/ - - if ((b_TimingUnit <= 4) - || (b_PCIInputClock == - APCI1710_GATE_INPUT)) { - /**********************************/ - /* Test the base timing selection */ - /**********************************/ - - if (((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 0) && (ul_TimingInterval >= 133) && (ul_TimingInterval <= 0xFFFFFFFFUL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 1) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 571230650UL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 2) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 571230UL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 3) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 571UL)) || ((b_PCIInputClock == APCI1710_30MHZ) && (b_TimingUnit == 4) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 9UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 0) && (ul_TimingInterval >= 121) && (ul_TimingInterval <= 0xFFFFFFFFUL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 1) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 519691043UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 2) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 519691UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 3) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 520UL)) || ((b_PCIInputClock == APCI1710_33MHZ) && (b_TimingUnit == 4) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 8UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 0) && (ul_TimingInterval >= 100) && (ul_TimingInterval <= 0xFFFFFFFFUL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 1) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 429496729UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 2) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 429496UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 3) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 429UL)) || ((b_PCIInputClock == APCI1710_40MHZ) && (b_TimingUnit == 4) && (ul_TimingInterval >= 1) && (ul_TimingInterval <= 7UL)) || ((b_PCIInputClock == APCI1710_GATE_INPUT) && (ul_TimingInterval >= 2))) { - /**************************/ - /* Test the board version */ - /**************************/ - - if (((b_PCIInputClock == APCI1710_40MHZ) && (devpriv->s_BoardInfos.b_BoardVersion > 0)) || (b_PCIInputClock != APCI1710_40MHZ)) { - /************************/ - /* Test the TOR version */ - /************************/ - - if (((b_PCIInputClock == APCI1710_40MHZ) && ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) >= 0x3131)) || ((b_PCIInputClock == APCI1710_GATE_INPUT) && ((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) >= 0x3132)) || (b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ)) { - /*********************************/ - /* Test if not extern clock used */ - /*********************************/ - - if (b_PCIInputClock != APCI1710_GATE_INPUT) { - fpu_begin - (); - /****************************************/ - /* Calculate the timer 0 division fator */ - /****************************************/ - - switch (b_TimingUnit) { - /******/ - /* ns */ - /******/ - - case 0: - - /******************/ - /* Timer 0 factor */ - /******************/ - - ul_TimerValue - = - (unsigned int) - (ul_TimingInterval - * - (0.00025 * b_PCIInputClock)); - - /*******************/ - /* Round the value */ - /*******************/ - - if ((double)((double)ul_TimingInterval * (0.00025 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) { - ul_TimerValue - = - ul_TimerValue - + - 1; - } - - /*****************************/ - /* Calculate the real timing */ - /*****************************/ - - ul_RealTimingInterval - = - (unsigned int) - (ul_TimerValue - / - (0.00025 * (double)b_PCIInputClock)); - d_RealTimingInterval - = - (double) - ul_TimerValue - / - (0.00025 - * - (double) - b_PCIInputClock); - - if ((double)((double)ul_TimerValue / (0.00025 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) { - ul_RealTimingInterval - = - ul_RealTimingInterval - + - 1; - } - - ul_TimingInterval - = - ul_TimingInterval - - - 1; - ul_TimerValue - = - ul_TimerValue - - - 2; - - if (b_PCIInputClock != APCI1710_40MHZ) { - ul_TimerValue - = - (unsigned int) - ( - (double) - (ul_TimerValue) - * - 1.007752288); - } - - break; - - /******/ - /* æs */ - /******/ - - case 1: - - /******************/ - /* Timer 0 factor */ - /******************/ - - ul_TimerValue - = - (unsigned int) - (ul_TimingInterval - * - (0.25 * b_PCIInputClock)); - - /*******************/ - /* Round the value */ - /*******************/ - - if ((double)((double)ul_TimingInterval * (0.25 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) { - ul_TimerValue - = - ul_TimerValue - + - 1; - } - - /*****************************/ - /* Calculate the real timing */ - /*****************************/ - - ul_RealTimingInterval - = - (unsigned int) - (ul_TimerValue - / - (0.25 * (double)b_PCIInputClock)); - d_RealTimingInterval - = - (double) - ul_TimerValue - / - ( - (double) - 0.25 - * - (double) - b_PCIInputClock); - - if ((double)((double)ul_TimerValue / (0.25 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) { - ul_RealTimingInterval - = - ul_RealTimingInterval - + - 1; - } - - ul_TimingInterval - = - ul_TimingInterval - - - 1; - ul_TimerValue - = - ul_TimerValue - - - 2; - - if (b_PCIInputClock != APCI1710_40MHZ) { - ul_TimerValue - = - (unsigned int) - ( - (double) - (ul_TimerValue) - * - 1.007752288); - } - - break; - - /******/ - /* ms */ - /******/ - - case 2: - - /******************/ - /* Timer 0 factor */ - /******************/ - - ul_TimerValue - = - ul_TimingInterval - * - (250.0 - * - b_PCIInputClock); - - /*******************/ - /* Round the value */ - /*******************/ - - if ((double)((double)ul_TimingInterval * (250.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) { - ul_TimerValue - = - ul_TimerValue - + - 1; - } - - /*****************************/ - /* Calculate the real timing */ - /*****************************/ - - ul_RealTimingInterval - = - (unsigned int) - (ul_TimerValue - / - (250.0 * (double)b_PCIInputClock)); - d_RealTimingInterval - = - (double) - ul_TimerValue - / - (250.0 - * - (double) - b_PCIInputClock); - - if ((double)((double)ul_TimerValue / (250.0 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) { - ul_RealTimingInterval - = - ul_RealTimingInterval - + - 1; - } - - ul_TimingInterval - = - ul_TimingInterval - - - 1; - ul_TimerValue - = - ul_TimerValue - - - 2; - - if (b_PCIInputClock != APCI1710_40MHZ) { - ul_TimerValue - = - (unsigned int) - ( - (double) - (ul_TimerValue) - * - 1.007752288); - } - - break; - - /*****/ - /* s */ - /*****/ - - case 3: - - /******************/ - /* Timer 0 factor */ - /******************/ - - ul_TimerValue - = - (unsigned int) - (ul_TimingInterval - * - (250000.0 - * - b_PCIInputClock)); - - /*******************/ - /* Round the value */ - /*******************/ - - if ((double)((double)ul_TimingInterval * (250000.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) { - ul_TimerValue - = - ul_TimerValue - + - 1; - } - - /*****************************/ - /* Calculate the real timing */ - /*****************************/ - - ul_RealTimingInterval - = - (unsigned int) - (ul_TimerValue - / - (250000.0 - * - (double) - b_PCIInputClock)); - d_RealTimingInterval - = - (double) - ul_TimerValue - / - (250000.0 - * - (double) - b_PCIInputClock); - - if ((double)((double)ul_TimerValue / (250000.0 * (double)b_PCIInputClock)) >= (double)((double)ul_RealTimingInterval + 0.5)) { - ul_RealTimingInterval - = - ul_RealTimingInterval - + - 1; - } - - ul_TimingInterval - = - ul_TimingInterval - - - 1; - ul_TimerValue - = - ul_TimerValue - - - 2; - - if (b_PCIInputClock != APCI1710_40MHZ) { - ul_TimerValue - = - (unsigned int) - ( - (double) - (ul_TimerValue) - * - 1.007752288); - } - - break; - - /******/ - /* mn */ - /******/ - - case 4: - - /******************/ - /* Timer 0 factor */ - /******************/ - - ul_TimerValue - = - (unsigned int) - ( - (ul_TimingInterval - * - 60) - * - (250000.0 - * - b_PCIInputClock)); - - /*******************/ - /* Round the value */ - /*******************/ - - if ((double)((double)(ul_TimingInterval * 60.0) * (250000.0 * (double)b_PCIInputClock)) >= ((double)((double)ul_TimerValue + 0.5))) { - ul_TimerValue - = - ul_TimerValue - + - 1; - } - - /*****************************/ - /* Calculate the real timing */ - /*****************************/ - - ul_RealTimingInterval - = - (unsigned int) - (ul_TimerValue - / - (250000.0 - * - (double) - b_PCIInputClock)) - / - 60; - d_RealTimingInterval - = - ( - (double) - ul_TimerValue - / - (250000.0 - * - (double) - b_PCIInputClock)) - / - 60.0; - - if ((double)(((double)ul_TimerValue / (250000.0 * (double)b_PCIInputClock)) / 60.0) >= (double)((double)ul_RealTimingInterval + 0.5)) { - ul_RealTimingInterval - = - ul_RealTimingInterval - + - 1; - } - - ul_TimingInterval - = - ul_TimingInterval - - - 1; - ul_TimerValue - = - ul_TimerValue - - - 2; - - if (b_PCIInputClock != APCI1710_40MHZ) { - ul_TimerValue - = - (unsigned int) - ( - (double) - (ul_TimerValue) - * - 1.007752288); - } - - break; - } - - fpu_end(); - } /* if (b_PCIInputClock != APCI1710_GATE_INPUT) */ - else { - /*************************************************************/ - /* 2 Clock used for the overflow and the reload from counter */ - /*************************************************************/ - - ul_TimerValue - = - ul_TimingInterval - - - 2; - } /* if (b_PCIInputClock != APCI1710_GATE_INPUT) */ - - /****************************/ - /* Save the PCI input clock */ - /****************************/ - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_TorCounterModuleInfo. - b_PCIInputClock - = - b_PCIInputClock; - - /************************/ - /* Save the timing unit */ - /************************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_TorCounterModuleInfo. - s_TorCounterInfo - [b_TorCounter]. - b_TimingUnit - = - b_TimingUnit; - - /************************/ - /* Save the base timing */ - /************************/ - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_TorCounterModuleInfo. - s_TorCounterInfo - [b_TorCounter]. - d_TimingInterval - = - d_RealTimingInterval; - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_TorCounterModuleInfo. - s_TorCounterInfo - [b_TorCounter]. - ul_RealTimingInterval - = - ul_RealTimingInterval; - - /*******************/ - /* Get the command */ - /*******************/ - - dw_Command - = - inl - (devpriv-> - s_BoardInfos. - ui_Address - + - 4 - + - (16 * b_TorCounter) + (64 * b_ModulNbr)); - - dw_Command - = - (dw_Command - >> - 4) - & - 0xF; - - /******************/ - /* Test if 40 MHz */ - /******************/ - - if (b_PCIInputClock == APCI1710_40MHZ) { - /****************************/ - /* Set the 40 MHz selection */ - /****************************/ - - dw_Command - = - dw_Command - | - 0x10; - } - - /*****************************/ - /* Test if extern clock used */ - /*****************************/ - - if (b_PCIInputClock == APCI1710_GATE_INPUT) { - /****************************/ - /* Set the 40 MHz selection */ - /****************************/ - - dw_Command - = - dw_Command - | - 0x20; - } - - /*************************/ - /* Write the new command */ - /*************************/ - - outl(dw_Command, devpriv->s_BoardInfos.ui_Address + 4 + (16 * b_TorCounter) + (64 * b_ModulNbr)); - - /*******************/ - /* Disable the tor */ - /*******************/ - - outl(0, devpriv->s_BoardInfos.ui_Address + 8 + (16 * b_TorCounter) + (64 * b_ModulNbr)); - /*************************/ - /* Set the timer 1 value */ - /*************************/ - - outl(ul_TimerValue, devpriv->s_BoardInfos.ui_Address + 0 + (16 * b_TorCounter) + (64 * b_ModulNbr)); - - /*********************/ - /* Tor counter init. */ - /*********************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_TorCounterModuleInfo. - s_TorCounterInfo - [b_TorCounter]. - b_TorCounterInit - = - 1; - } else { - /***********************************************/ - /* TOR version error for 40MHz clock selection */ - /***********************************************/ - - DPRINTK("TOR version error for 40MHz clock selection\n"); - i_ReturnValue - = - -9; - } - } else { - /**************************************************************/ - /* You can not used the 40MHz clock selection wich this board */ - /**************************************************************/ - - DPRINTK("You can not used the 40MHz clock selection wich this board\n"); - i_ReturnValue = - -8; - } - } else { - /**********************************/ - /* Base timing selection is wrong */ - /**********************************/ - - DPRINTK("Base timing selection is wrong\n"); - i_ReturnValue = -7; - } - } /* if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) */ - else { - /**********************************/ - /* Timing unit selection is wrong */ - /**********************************/ - - DPRINTK("Timing unit selection is wrong\n"); - i_ReturnValue = -6; - } /* if ((b_TimingUnit >= 0) && (b_TimingUnit <= 4)) */ - } /* if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ)) */ - else { - /*****************************************/ - /* The selected PCI input clock is wrong */ - /*****************************************/ - - DPRINTK("The selected PCI input clock is wrong\n"); - i_ReturnValue = -5; - } /* if ((b_PCIInputClock == APCI1710_30MHZ) || (b_PCIInputClock == APCI1710_33MHZ)) */ - } /* if (b_TorCounterMode >= 0 && b_TorCounterMode <= 7) */ - else { - /**********************************/ - /* Tor Counter selection is wrong */ - /**********************************/ - - DPRINTK("Tor Counter selection is wrong\n"); - i_ReturnValue = -4; - } /* if (b_TorCounterMode >= 0 && b_TorCounterMode <= 7) */ - } else { - /******************************************/ - /* The module is not a tor counter module */ - /******************************************/ - - DPRINTK("The module is not a tor counter module\n"); - i_ReturnValue = -3; - } - } else { - /***********************/ - /* Module number error */ - /***********************/ - - DPRINTK("Module number error\n"); - i_ReturnValue = -2; - } - data[0] = (unsigned int) ul_RealTimingInterval; - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_EnableTorCounter | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_TorCounter, | -| unsigned char_ b_InputMode, | -| unsigned char_ b_ExternGate, | -| unsigned char_ b_CycleMode, | -| unsigned char_ b_InterruptEnable) | -+----------------------------------------------------------------------------+ -| Task : Enable the tor counter (b_TorCounter) from selected | -| module (b_ModulNbr). You must calling the | -| "i_APCI1710_InitTorCounter" function be for you call | -| this function. | -| If you enable the tor counter interrupt, the | -| tor counter generate a interrupt after the timing cycle| -| See function "i_APCI1710_SetBoardIntRoutineX" and the | -| Interrupt mask description chapter from this manual. | -| The b_CycleMode parameter determine if you will | -| measured a single or more cycle. | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Selected module number (0 to 3) | -| unsigned char_ b_TorCounter : Tor counter selection (0 or 1). | -| unsigned char_ b_InputMode : Input signal level selection | -| 0 : Tor count each low level | -| 1 : Tor count each high level| -| unsigned char_ b_ExternGate : Extern gate action selection | -| 0 : Extern gate signal not | -| used | -| 1 : Extern gate signal used. | -| If you selected the | -| single mode, each high | -| level signal start the | -| counter. | -| If you selected the | -| continuous mode, the | -| first high level signal | -| start the tor counter | -| | -| APCI1710_TOR_QUADRUPLE _MODE : | -| In the quadruple mode, the edge| -| analysis circuit generates a | -| counting pulse from each edge | -| of 2 signals which are phase | -| shifted in relation to each | -| other. | -| The gate input is used for the | -| signal B | -| | -| APCI1710_TOR_DOUBLE_MODE: | -| Functions in the same way as | -| the quadruple mode, except that| -| only two of the four edges are | -| analysed per period. | -| The gate input is used for the | -| signal B | -| | -| APCI1710_TOR_SIMPLE_MODE: | -| Functions in the same way as | -| the quadruple mode, except that| -| only one of the four edges is | -| analysed per period. | -| The gate input is used for the | -| signal B | -| | -| unsigned char_ b_CycleMode : Selected the tor counter | -| acquisition mode | -| unsigned char_ b_InterruptEnable : Enable or disable the | -| tor counter interrupt. | -| APCI1710_ENABLE: | -| Enable the tor counter | -| interrupt | -| APCI1710_DISABLE: | -| Disable the tor counter | -| interrupt | -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: Module selection wrong | -| -3: The module is not a tor counter module | -| -4: Tor counter selection is wrong | -| -5: Tor counter not initialised see function | -| "i_APCI1710_InitTorCounter" | -| -6: Tor input signal selection is wrong | -| -7: Extern gate signal mode is wrong | -| -8: Tor counter acquisition mode cycle is wrong | -| -9: Interrupt parameter is wrong | -| -10:Interrupt function not initialised. | -| See function "i_APCI1710_SetBoardIntRoutineX" | -+----------------------------------------------------------------------------+ -*/ -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_DisableTorCounter | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_TorCounter) | -+----------------------------------------------------------------------------+ -| Task : Disable the tor counter (b_TorCounter) from selected | -| module (b_ModulNbr). If you disable the tor counter | -| after a start cycle occur and you restart the tor | -| counter witch the " i_APCI1710_EnableTorCounter" | -| function, the status register is cleared | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Selected module number (0 to 3) | -| unsigned char_ b_TorCounter : Tor counter selection (0 or 1). | -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: Module selection wrong | -| -3: The module is not a tor counter module | -| -4: Tor counter selection is wrong | -| -5: Tor counter not initialised see function | -| "i_APCI1710_InitTorCounter" | -| -6: Tor counter not enabled see function | -| "i_APCI1710_EnableTorCounter" | -+----------------------------------------------------------------------------+ -*/ - -static int i_APCI1710_InsnWriteEnableDisableTorCounter(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned int dw_Status; - unsigned int dw_DummyRead; - unsigned int dw_ConfigReg; - unsigned char b_ModulNbr, b_Action; - unsigned char b_TorCounter; - unsigned char b_InputMode; - unsigned char b_ExternGate; - unsigned char b_CycleMode; - unsigned char b_InterruptEnable; - - b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec); - b_Action = (unsigned char) data[0]; /* enable or disable */ - b_TorCounter = (unsigned char) data[1]; - b_InputMode = (unsigned char) data[2]; - b_ExternGate = (unsigned char) data[3]; - b_CycleMode = (unsigned char) data[4]; - b_InterruptEnable = (unsigned char) data[5]; - i_ReturnValue = insn->n; - devpriv->tsk_Current = current; /* Save the current process task structure */ - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /***********************/ - /* Test if tor counter */ - /***********************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModulNbr] & - 0xFFFF0000UL) == APCI1710_TOR_COUNTER) { - /**********************************/ - /* Test the tor counter selection */ - /**********************************/ - - if (b_TorCounter <= 1) { - switch (b_Action) /* Enable or Disable */ - { - case APCI1710_ENABLE: - /***********************************/ - /* Test if tor counter initialised */ - /***********************************/ - - dw_Status = - inl(devpriv->s_BoardInfos. - ui_Address + 8 + - (16 * b_TorCounter) + - (64 * b_ModulNbr)); - - if (dw_Status & 0x10) { - /******************************/ - /* Test the input signal mode */ - /******************************/ - - if (b_InputMode == 0 || - b_InputMode == 1 || - b_InputMode == - APCI1710_TOR_SIMPLE_MODE - || b_InputMode == - APCI1710_TOR_DOUBLE_MODE - || b_InputMode == - APCI1710_TOR_QUADRUPLE_MODE) - { - /************************************/ - /* Test the extern gate signal mode */ - /************************************/ - - if (b_ExternGate == 0 - || b_ExternGate - == 1 - || b_InputMode > - 1) { - /*********************************/ - /* Test the cycle mode parameter */ - /*********************************/ - - if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS)) { - /***************************/ - /* Test the interrupt flag */ - /***************************/ - - if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE)) { - - /***************************/ - /* Save the interrupt mode */ - /***************************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_TorCounterModuleInfo. - s_TorCounterInfo - [b_TorCounter]. - b_InterruptEnable - = - b_InterruptEnable; - - /*******************/ - /* Get the command */ - /*******************/ - - dw_ConfigReg - = - inl - (devpriv-> - s_BoardInfos. - ui_Address - + - 4 - + - (16 * b_TorCounter) + (64 * b_ModulNbr)); - - dw_ConfigReg - = - (dw_ConfigReg - >> - 4) - & - 0x30; - - /********************************/ - /* Test if not direct mode used */ - /********************************/ - - if (b_InputMode > 1) { - /*******************************/ - /* Extern gate can not be used */ - /*******************************/ - - b_ExternGate - = - 0; - - /*******************************************/ - /* Enable the extern gate for the Signal B */ - /*******************************************/ - - dw_ConfigReg - = - dw_ConfigReg - | - 0x40; - - /***********************/ - /* Test if simple mode */ - /***********************/ - - if (b_InputMode == APCI1710_TOR_SIMPLE_MODE) { - /**************************/ - /* Enable the sinple mode */ - /**************************/ - - dw_ConfigReg - = - dw_ConfigReg - | - 0x780; - - } /* if (b_InputMode == APCI1710_TOR_SIMPLE_MODE) */ - - /***********************/ - /* Test if double mode */ - /***********************/ - - if (b_InputMode == APCI1710_TOR_DOUBLE_MODE) { - /**************************/ - /* Enable the double mode */ - /**************************/ - - dw_ConfigReg - = - dw_ConfigReg - | - 0x180; - - } /* if (b_InputMode == APCI1710_TOR_DOUBLE_MODE) */ - - b_InputMode - = - 0; - } /* if (b_InputMode > 1) */ - - /*******************/ - /* Set the command */ - /*******************/ - - dw_ConfigReg - = - dw_ConfigReg - | - b_CycleMode - | - (b_InterruptEnable - * - 2) - | - (b_InputMode - * - 4) - | - (b_ExternGate - * - 8); - - /*****************************/ - /* Clear the status register */ - /*****************************/ - - dw_DummyRead - = - inl - (devpriv-> - s_BoardInfos. - ui_Address - + - 0 - + - (16 * b_TorCounter) + (64 * b_ModulNbr)); - - /***************************************/ - /* Clear the interrupt status register */ - /***************************************/ - - dw_DummyRead - = - inl - (devpriv-> - s_BoardInfos. - ui_Address - + - 12 - + - (16 * b_TorCounter) + (64 * b_ModulNbr)); - - /********************/ - /* Set the commando */ - /********************/ - - outl(dw_ConfigReg, devpriv->s_BoardInfos.ui_Address + 4 + (16 * b_TorCounter) + (64 * b_ModulNbr)); - - /****************/ - /* Set the gate */ - /****************/ - - outl(1, devpriv->s_BoardInfos.ui_Address + 8 + (16 * b_TorCounter) + (64 * b_ModulNbr)); - - } /* if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE)) */ - else { - /********************************/ - /* Interrupt parameter is wrong */ - /********************************/ - - DPRINTK("Interrupt parameter is wrong\n"); - i_ReturnValue - = - -9; - } /* if ((b_InterruptEnable == APCI1710_ENABLE) || (b_InterruptEnable == APCI1710_DISABLE)) */ - } /* if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS)) */ - else { - /***********************************************/ - /* Tor counter acquisition mode cycle is wrong */ - /***********************************************/ - - DPRINTK("Tor counter acquisition mode cycle is wrong\n"); - i_ReturnValue - = - -8; - } /* if ((b_CycleMode == APCI1710_SINGLE) || (b_CycleMode == APCI1710_CONTINUOUS)) */ - } /* if (b_ExternGate >= 0 && b_ExternGate <= 1) */ - else { - /***********************************/ - /* Extern gate input mode is wrong */ - /***********************************/ - - DPRINTK("Extern gate input mode is wrong\n"); - i_ReturnValue = - -7; - } /* if (b_ExternGate >= 0 && b_ExternGate <= 1) */ - } /* if (b_InputMode >= 0 && b_InputMode <= 1) */ - else { - /***************************************/ - /* Tor input signal selection is wrong */ - /***************************************/ - - DPRINTK("Tor input signal selection is wrong\n"); - i_ReturnValue = -6; - } - } else { - /*******************************/ - /* Tor counter not initialised */ - /*******************************/ - - DPRINTK("Tor counter not initialised\n"); - i_ReturnValue = -5; - } - break; - - case APCI1710_DISABLE: - /***********************************/ - /* Test if tor counter initialised */ - /***********************************/ - - dw_Status = inl(devpriv->s_BoardInfos. - ui_Address + 8 + - (16 * b_TorCounter) + - (64 * b_ModulNbr)); - - /*******************************/ - /* Test if counter initialised */ - /*******************************/ - - if (dw_Status & 0x10) { - /***************************/ - /* Test if counter enabled */ - /***************************/ - - if (dw_Status & 0x1) { - /****************************/ - /* Clear the interrupt mode */ - /****************************/ - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_TorCounterModuleInfo. - s_TorCounterInfo - [b_TorCounter]. - b_InterruptEnable - = - APCI1710_DISABLE; - - /******************/ - /* Clear the gate */ - /******************/ - - outl(0, devpriv-> - s_BoardInfos. - ui_Address + 8 + - (16 * b_TorCounter) + (64 * b_ModulNbr)); - } /* if (dw_Status & 0x1) */ - else { - /***************************/ - /* Tor counter not enabled */ - /***************************/ - - DPRINTK("Tor counter not enabled \n"); - i_ReturnValue = -6; - } /* if (dw_Status & 0x1) */ - } /* if (dw_Status & 0x10) */ - else { - /*******************************/ - /* Tor counter not initialised */ - /*******************************/ - - DPRINTK("Tor counter not initialised\n"); - i_ReturnValue = -5; - } /* // if (dw_Status & 0x10) */ - - } /* switch */ - } /* if (b_TorCounter <= 1) */ - else { - /**********************************/ - /* Tor counter selection is wrong */ - /**********************************/ - - DPRINTK("Tor counter selection is wrong\n"); - i_ReturnValue = -4; - } /* if (b_TorCounter <= 1) */ - } else { - /******************************************/ - /* The module is not a tor counter module */ - /******************************************/ - - DPRINTK("The module is not a tor counter module \n"); - i_ReturnValue = -3; - } - } else { - /***********************/ - /* Module number error */ - /***********************/ - - DPRINTK("Module number error \n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_GetTorCounterInitialisation | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_TorCounter, | -| unsigned char *_ pb_TimingUnit, | -| PULONG_ pul_TimingInterval, | -| unsigned char *_ pb_InputMode, | -| unsigned char *_ pb_ExternGate, | -| unsigned char *_ pb_CycleMode, | -| unsigned char *_ pb_Enable, | -| unsigned char *_ pb_InterruptEnable)| -+----------------------------------------------------------------------------+ -| Task : Enable the tor counter (b_TorCounter) from selected | -| module (b_ModulNbr). You must calling the | -| "i_APCI1710_InitTorCounter" function be for you call | -| this function. | -| If you enable the tor counter interrupt, the | -| tor counter generate a interrupt after the timing cycle| -| See function "i_APCI1710_SetBoardIntRoutineX" and the | -| Interrupt mask description chapter from this manual. | -| The b_CycleMode parameter determine if you will | -| measured a single or more cycle. | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Selected module number (0 to 3) | -| unsigned char_ b_TorCounter : Tor counter selection (0 or 1) - - b_ModulNbr = CR_AREF(insn->chanspec); - b_TorCounter = CR_CHAN(insn->chanspec); -. | -+----------------------------------------------------------------------------+ -| Output Parameters : unsigned char *_ pb_TimingUnit : Base timing unit (0 to 4) | -| 0 : ns | -| 1 : µs | -| 2 : ms | -| 3 : s | -| 4 : mn | -| PULONG_ pul_TimingInterval : Base timing value. | -| unsigned char *_ pb_InputMode : Input signal level | -| selection | -| 0 : Tor count each low level | -| 1 : Tor count each high level| -| unsigned char *_ pb_ExternGate : Extern gate action | -| selection | -| 0 : Extern gate signal not | -| used | -| 1 : Extern gate signal used| -| unsigned char *_ pb_CycleMode : Tor counter acquisition | -| mode | -| unsigned char *_ pb_Enable : Indicate if the tor counter| -| is enabled or no | -| 0 : Tor counter disabled | -| 1 : Tor counter enabled | -| unsigned char *_ pb_InterruptEnable : Enable or disable the | -| tor counter interrupt. | -| APCI1710_ENABLE: | -| Enable the tor counter | -| interrupt | -| APCI1710_DISABLE: | -| Disable the tor counter | -| interrupt - pb_TimingUnit = (unsigned char *) &data[0]; - pul_TimingInterval = (unsigned int *) &data[1]; - pb_InputMode = (unsigned char *) &data[2]; - pb_ExternGate = (unsigned char *) &data[3]; - pb_CycleMode = (unsigned char *) &data[4]; - pb_Enable = (unsigned char *) &data[5]; - pb_InterruptEnable = (unsigned char *) &data[6]; - | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: Module selection wrong | -| -3: The module is not a tor counter module | -| -4: Tor counter selection is wrong | -| -5: Tor counter not initialised see function | -| "i_APCI1710_InitTorCounter" | -+----------------------------------------------------------------------------+ -*/ - -static int i_APCI1710_InsnReadGetTorCounterInitialisation(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned int dw_Status; - unsigned char b_ModulNbr; - unsigned char b_TorCounter; - unsigned char *pb_TimingUnit; - unsigned int *pul_TimingInterval; - unsigned char *pb_InputMode; - unsigned char *pb_ExternGate; - unsigned char *pb_CycleMode; - unsigned char *pb_Enable; - unsigned char *pb_InterruptEnable; - - i_ReturnValue = insn->n; - b_ModulNbr = CR_AREF(insn->chanspec); - b_TorCounter = CR_CHAN(insn->chanspec); - - pb_TimingUnit = (unsigned char *) &data[0]; - pul_TimingInterval = (unsigned int *) &data[1]; - pb_InputMode = (unsigned char *) &data[2]; - pb_ExternGate = (unsigned char *) &data[3]; - pb_CycleMode = (unsigned char *) &data[4]; - pb_Enable = (unsigned char *) &data[5]; - pb_InterruptEnable = (unsigned char *) &data[6]; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /***********************/ - /* Test if tor counter */ - /***********************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModulNbr] & - 0xFFFF0000UL) == APCI1710_TOR_COUNTER) { - /**********************************/ - /* Test the tor counter selection */ - /**********************************/ - - if (b_TorCounter <= 1) { - - /***********************************/ - /* Test if tor counter initialised */ - /***********************************/ - - dw_Status = inl(devpriv->s_BoardInfos. - ui_Address + 8 + (16 * b_TorCounter) + - (64 * b_ModulNbr)); - - if (dw_Status & 0x10) { - *pb_Enable = dw_Status & 1; - - /********************/ - /* Get the commando */ - /********************/ - - dw_Status = inl(devpriv->s_BoardInfos. - ui_Address + 4 + - (16 * b_TorCounter) + - (64 * b_ModulNbr)); - - *pb_CycleMode = - (unsigned char) ((dw_Status >> 4) & 1); - *pb_InterruptEnable = - (unsigned char) ((dw_Status >> 5) & 1); - - /******************************************************/ - /* Test if extern gate used for clock or for signal B */ - /******************************************************/ - - if (dw_Status & 0x600) { - /*****************************************/ - /* Test if extern gate used for signal B */ - /*****************************************/ - - if (dw_Status & 0x400) { - /***********************/ - /* Test if simple mode */ - /***********************/ - - if ((dw_Status & 0x7800) - == 0x7800) { - *pb_InputMode = - APCI1710_TOR_SIMPLE_MODE; - } - - /***********************/ - /* Test if double mode */ - /***********************/ - - if ((dw_Status & 0x7800) - == 0x1800) { - *pb_InputMode = - APCI1710_TOR_DOUBLE_MODE; - } - - /**************************/ - /* Test if quadruple mode */ - /**************************/ - - if ((dw_Status & 0x7800) - == 0x0000) { - *pb_InputMode = - APCI1710_TOR_QUADRUPLE_MODE; - } - } /* if (dw_Status & 0x400) */ - else { - *pb_InputMode = 1; - } /* // if (dw_Status & 0x400) */ - - /************************/ - /* Extern gate not used */ - /************************/ - - *pb_ExternGate = 0; - } /* if (dw_Status & 0x600) */ - else { - *pb_InputMode = - (unsigned char) ((dw_Status >> 6) - & 1); - *pb_ExternGate = - (unsigned char) ((dw_Status >> 7) - & 1); - } /* if (dw_Status & 0x600) */ - - *pb_TimingUnit = - devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_TorCounterModuleInfo. - s_TorCounterInfo[b_TorCounter]. - b_TimingUnit; - - *pul_TimingInterval = - devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_TorCounterModuleInfo. - s_TorCounterInfo[b_TorCounter]. - ul_RealTimingInterval; - } else { - /*******************************/ - /* Tor counter not initialised */ - /*******************************/ - - DPRINTK("Tor counter not initialised\n"); - i_ReturnValue = -5; - } - - } /* if (b_TorCounter <= 1) */ - else { - /**********************************/ - /* Tor counter selection is wrong */ - /**********************************/ - - DPRINTK("Tor counter selection is wrong \n"); - i_ReturnValue = -4; - } /* if (b_TorCounter <= 1) */ - } else { - /******************************************/ - /* The module is not a tor counter module */ - /******************************************/ - - DPRINTK("The module is not a tor counter module\n"); - i_ReturnValue = -3; - } - } else { - /***********************/ - /* Module number error */ - /***********************/ - - DPRINTK("Module number error\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_ReadTorCounterValue | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_TorCounter, | -| unsigned int_ ui_TimeOut, | -| unsigned char *_ pb_TorCounterStatus, | -| PULONG_ pul_TorCounterValue) | -+----------------------------------------------------------------------------+ -| Task case APCI1710_TOR_GETPROGRESSSTATUS: Return the tor counter -(b_TorCounter) status (pb_TorCounterStatus) from selected tor counter | -| module (b_ModulNbr). - - case APCI1710_TOR_GETCOUNTERVALUE : - Return the tor counter (b_TorCounter) status | -| (pb_TorCounterStatus) and the timing value | -| (pul_TorCounterValue) after a conting cycle stop | -| from selected tor counter module (b_ModulNbr). | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Selected module number (0 to 3) | -| unsigned char_ b_TorCounter : Tor counter selection (0 or 1). - b_ModulNbr = CR_AREF(insn->chanspec); - b_ReadType = (unsigned char) data[0]; - b_TorCounter = (unsigned char) data[1]; - ui_TimeOut = (unsigned int) data[2]; | -+----------------------------------------------------------------------------+ -| Output Parameters : unsigned char *_ pb_TorCounterStatus : Return the tor counter | -| status. | -| 0 : Conting cycle not started| -| Software gate not set. | -| 1 : Conting cycle started. | -| Software gate set. | -| 2 : Conting cycle stopped. | -| The conting cycle is | -| terminate. | -| 3 : A overflow occur. You | -| must change the base | -| timing witch the | -| function | -| "i_APCI1710_InitTorCounter"| -| 4 : Timeeout occur | -| unsigned int * pul_TorCounterValue : Tor counter value. - pb_TorCounterStatus=(unsigned char *) &data[0]; - pul_TorCounterValue=(unsigned int *) &data[1]; | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: Module selection wrong | -| -3: The module is not a tor counter module | -| -4: Tor counter selection is wrong | -| -5: Tor counter not initialised see function | -| "i_APCI1710_InitTorCounter" | -| -6: Tor counter not enabled see function | -| "i_APCI1710_EnableTorCounter" | -| -7: Timeout parameter is wrong (0 to 65535) | -+----------------------------------------------------------------------------+ -*/ - -static int i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned int dw_Status; - unsigned int dw_TimeOut = 0; - unsigned char b_ModulNbr; - unsigned char b_TorCounter; - unsigned char b_ReadType; - unsigned int ui_TimeOut; - unsigned char *pb_TorCounterStatus; - unsigned int *pul_TorCounterValue; - - i_ReturnValue = insn->n; - b_ModulNbr = CR_AREF(insn->chanspec); - b_ReadType = (unsigned char) data[0]; - b_TorCounter = (unsigned char) data[1]; - ui_TimeOut = (unsigned int) data[2]; - pb_TorCounterStatus = (unsigned char *) &data[0]; - pul_TorCounterValue = (unsigned int *) &data[1]; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ReadType == APCI1710_TOR_READINTERRUPT) { - - data[0] = devpriv->s_InterruptParameters. - s_FIFOInterruptParameters[devpriv-> - s_InterruptParameters.ui_Read].b_OldModuleMask; - data[1] = devpriv->s_InterruptParameters. - s_FIFOInterruptParameters[devpriv-> - s_InterruptParameters.ui_Read].ul_OldInterruptMask; - data[2] = devpriv->s_InterruptParameters. - s_FIFOInterruptParameters[devpriv-> - s_InterruptParameters.ui_Read].ul_OldCounterLatchValue; - - /**************************/ - /* Increment the read FIFO */ - /***************************/ - - devpriv-> - s_InterruptParameters. - ui_Read = (devpriv-> - s_InterruptParameters. - ui_Read + 1) % APCI1710_SAVE_INTERRUPT; - - return insn->n; - } - - if (b_ModulNbr < 4) { - /***********************/ - /* Test if tor counter */ - /***********************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModulNbr] & - 0xFFFF0000UL) == APCI1710_TOR_COUNTER) { - /**********************************/ - /* Test the tor counter selection */ - /**********************************/ - - if (b_TorCounter <= 1) { - /***********************************/ - /* Test if tor counter initialised */ - /***********************************/ - - dw_Status = inl(devpriv->s_BoardInfos. - ui_Address + 8 + (16 * b_TorCounter) + - (64 * b_ModulNbr)); - - /*******************************/ - /* Test if counter initialised */ - /*******************************/ - - if (dw_Status & 0x10) { - /***************************/ - /* Test if counter enabled */ - /***************************/ - - if (dw_Status & 0x1) { - - switch (b_ReadType) { - - case APCI1710_TOR_GETPROGRESSSTATUS: - /*******************/ - /* Read the status */ - /*******************/ - - dw_Status = - inl(devpriv-> - s_BoardInfos. - ui_Address + 4 + - (16 * b_TorCounter) + (64 * b_ModulNbr)); - - dw_Status = - dw_Status & 0xF; - - /*****************/ - /* Test if start */ - /*****************/ - - if (dw_Status & 1) { - if (dw_Status & - 2) { - if (dw_Status & 4) { - /************************/ - /* Tor counter overflow */ - /************************/ - - *pb_TorCounterStatus - = - 3; - } else { - /***********************/ - /* Tor counter started */ - /***********************/ - - *pb_TorCounterStatus - = - 2; - } - } else { - /***********************/ - /* Tor counter started */ - /***********************/ - - *pb_TorCounterStatus - = - 1; - } - } else { - /***************************/ - /* Tor counter not started */ - /***************************/ - - *pb_TorCounterStatus - = 0; - } - break; - - case APCI1710_TOR_GETCOUNTERVALUE: - - /*****************************/ - /* Test the timout parameter */ - /*****************************/ - - if ((ui_TimeOut >= 0) - && (ui_TimeOut - <= - 65535UL)) - { - for (;;) { - /*******************/ - /* Read the status */ - /*******************/ - - dw_Status - = - inl - (devpriv-> - s_BoardInfos. - ui_Address - + - 4 - + - (16 * b_TorCounter) + (64 * b_ModulNbr)); - /********************/ - /* Test if overflow */ - /********************/ - - if ((dw_Status & 4) == 4) { - /******************/ - /* Overflow occur */ - /******************/ - - *pb_TorCounterStatus - = - 3; - - /******************/ - /* Read the value */ - /******************/ - - *pul_TorCounterValue - = - inl - (devpriv-> - s_BoardInfos. - ui_Address - + - 0 - + - (16 * b_TorCounter) + (64 * b_ModulNbr)); - break; - } /* if ((dw_Status & 4) == 4) */ - else { - /*******************************/ - /* Test if measurement stopped */ - /*******************************/ - - if ((dw_Status & 2) == 2) { - /***********************/ - /* A stop signal occur */ - /***********************/ - - *pb_TorCounterStatus - = - 2; - - /******************/ - /* Read the value */ - /******************/ - - *pul_TorCounterValue - = - inl - (devpriv-> - s_BoardInfos. - ui_Address - + - 0 - + - (16 * b_TorCounter) + (64 * b_ModulNbr)); - - break; - } /* if ((dw_Status & 2) == 2) */ - else { - /*******************************/ - /* Test if measurement started */ - /*******************************/ - - if ((dw_Status & 1) == 1) { - /************************/ - /* A start signal occur */ - /************************/ - - *pb_TorCounterStatus - = - 1; - } /* if ((dw_Status & 1) == 1) */ - else { - /***************************/ - /* Measurement not started */ - /***************************/ - - *pb_TorCounterStatus - = - 0; - } /* if ((dw_Status & 1) == 1) */ - } /* if ((dw_Status & 2) == 2) */ - } /* if ((dw_Status & 8) == 8) */ - - if (dw_TimeOut == ui_TimeOut) { - /*****************/ - /* Timeout occur */ - /*****************/ - - break; - } else { - /*************************/ - /* Increment the timeout */ - /*************************/ - - dw_TimeOut - = - dw_TimeOut - + - 1; - - mdelay(1000); - } - } /* for (;;) */ - - /*************************/ - /* Test if timeout occur */ - /*************************/ - - if ((*pb_TorCounterStatus != 3) && (dw_TimeOut == ui_TimeOut) && (ui_TimeOut != 0)) { - /*****************/ - /* Timeout occur */ - /*****************/ - - *pb_TorCounterStatus - = - 4; - } - } else { - /******************************/ - /* Timeout parameter is wrong */ - /******************************/ - - DPRINTK("Timeout parameter is wrong\n"); - i_ReturnValue = - -7; - } - break; - - default: - printk("Inputs wrong\n"); - } /* switch end */ - } /* if (dw_Status & 0x1) */ - else { - /***************************/ - /* Tor counter not enabled */ - /***************************/ - - DPRINTK("Tor counter not enabled\n"); - i_ReturnValue = -6; - } /* if (dw_Status & 0x1) */ - } else { - /*******************************/ - /* Tor counter not initialised */ - /*******************************/ - - DPRINTK("Tor counter not initialised\n"); - i_ReturnValue = -5; - } - } /* if (b_TorCounter <= 1) */ - else { - /**********************************/ - /* Tor counter selection is wrong */ - /**********************************/ - - DPRINTK("Tor counter selection is wrong\n"); - i_ReturnValue = -4; - } /* if (b_TorCounter <= 1) */ - } else { - /******************************************/ - /* The module is not a tor counter module */ - /******************************************/ - - DPRINTK("The module is not a tor counter module\n"); - i_ReturnValue = -3; - } - } else { - /***********************/ - /* Module number error */ - /***********************/ - - DPRINTK("Module number error\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c deleted file mode 100644 index c01497a8a457..000000000000 --- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c +++ /dev/null @@ -1,1044 +0,0 @@ -/** -@verbatim - -Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. - - ADDI-DATA GmbH - Dieselstrasse 3 - D-77833 Ottersweier - Tel: +19(0)7223/9493-0 - Fax: +49(0)7223/9493-92 - http://www.addi-data.com - info@addi-data.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. - -@endverbatim -*/ -/* - - +-----------------------------------------------------------------------+ - | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier | - +-----------------------------------------------------------------------+ - | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | - | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | - +-----------------------------------------------------------------------+ - | Project : API APCI1710 | Compiler : gcc | - | Module name : TTL.C | Version : 2.96 | - +-------------------------------+---------------------------------------+ - | Project manager: Eric Stolz | Date : 02/12/2002 | - +-----------------------------------------------------------------------+ - | Description : APCI-1710 TTL I/O module | - | | - | | - +-----------------------------------------------------------------------+ - | UPDATES | - +-----------------------------------------------------------------------+ - | Date | Author | Description of updates | - +----------+-----------+------------------------------------------------+ - | 13/05/98 | S. Weber | TTL digital input / output implementation | - |----------|-----------|------------------------------------------------| - | 08/05/00 | Guinot C | - 0400/0228 All Function in RING 0 | - | | | available | - +-----------------------------------------------------------------------+ - | | | | - | | | | - +-----------------------------------------------------------------------+ -*/ - -#define APCI1710_TTL_INIT 0 -#define APCI1710_TTL_INITDIRECTION 1 - -#define APCI1710_TTL_READCHANNEL 0 -#define APCI1710_TTL_READPORT 1 - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_InitTTLIODirection | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_PortAMode, | -| unsigned char_ b_PortBMode, | -| unsigned char_ b_PortCMode, | -| unsigned char_ b_PortDMode) | -+----------------------------------------------------------------------------+ -| Task APCI1710_TTL_INIT (using defaults) : Configure the TTL I/O operating mode from selected | -| module (b_ModulNbr). You must calling this function be| -| for you call any other function witch access of TTL. | - APCI1710_TTL_INITDIRECTION(user inputs for direction) - -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710| -| unsigned char_ b_ModulNbr : Module number to | -| configure (0 to 3) - b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec); - b_InitType = (unsigned char) data[0]; - b_PortAMode = (unsigned char) data[1]; - b_PortBMode = (unsigned char) data[2]; - b_PortCMode = (unsigned char) data[3]; - b_PortDMode = (unsigned char) data[4];| -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: The module parameter is wrong | -| -3: The module is not a TTL module | -| -4: Function not available for this version | -| -5: Port A mode selection is wrong | -| -6: Port B mode selection is wrong | -| -7: Port C mode selection is wrong | -| -8: Port D mode selection is wrong | -+----------------------------------------------------------------------------+ -*/ - -static int i_APCI1710_InsnConfigInitTTLIO(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned char b_ModulNbr; - unsigned char b_InitType; - unsigned char b_PortAMode; - unsigned char b_PortBMode; - unsigned char b_PortCMode; - unsigned char b_PortDMode; - - b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec); - b_InitType = (unsigned char) data[0]; - i_ReturnValue = insn->n; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /**************************/ - /* Test if TTL I/O module */ - /**************************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModulNbr] & - 0xFFFF0000UL) == APCI1710_TTL_IO) { - switch (b_InitType) { - case APCI1710_TTL_INIT: - - devpriv->s_ModuleInfo[b_ModulNbr]. - s_TTLIOInfo.b_TTLInit = 1; - - /***************************/ - /* Set TTL port A to input */ - /***************************/ - - devpriv->s_ModuleInfo[b_ModulNbr]. - s_TTLIOInfo.b_PortConfiguration[0] = 0; - - /***************************/ - /* Set TTL port B to input */ - /***************************/ - - devpriv->s_ModuleInfo[b_ModulNbr]. - s_TTLIOInfo.b_PortConfiguration[1] = 0; - - /***************************/ - /* Set TTL port C to input */ - /***************************/ - - devpriv->s_ModuleInfo[b_ModulNbr]. - s_TTLIOInfo.b_PortConfiguration[2] = 0; - - /****************************/ - /* Set TTL port D to output */ - /****************************/ - - devpriv->s_ModuleInfo[b_ModulNbr]. - s_TTLIOInfo.b_PortConfiguration[3] = 1; - - /*************************/ - /* Set the configuration */ - /*************************/ - - outl(0x8, - devpriv->s_BoardInfos.ui_Address + 20 + - (64 * b_ModulNbr)); - break; - - case APCI1710_TTL_INITDIRECTION: - - b_PortAMode = (unsigned char) data[1]; - b_PortBMode = (unsigned char) data[2]; - b_PortCMode = (unsigned char) data[3]; - b_PortDMode = (unsigned char) data[4]; - - /********************/ - /* Test the version */ - /********************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration - [b_ModulNbr] & 0xFFFF) >= - 0x3230) { - /************************/ - /* Test the port A mode */ - /************************/ - - if ((b_PortAMode == 0) - || (b_PortAMode == 1)) { - /************************/ - /* Test the port B mode */ - /************************/ - - if ((b_PortBMode == 0) - || (b_PortBMode == 1)) { - /************************/ - /* Test the port C mode */ - /************************/ - - if ((b_PortCMode == 0) - || (b_PortCMode - == 1)) { - /************************/ - /* Test the port D mode */ - /************************/ - - if ((b_PortDMode == 0) || (b_PortDMode == 1)) { - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_TTLIOInfo. - b_TTLInit - = - 1; - - /***********************/ - /* Set TTL port A mode */ - /***********************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_TTLIOInfo. - b_PortConfiguration - [0] - = - b_PortAMode; - - /***********************/ - /* Set TTL port B mode */ - /***********************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_TTLIOInfo. - b_PortConfiguration - [1] - = - b_PortBMode; - - /***********************/ - /* Set TTL port C mode */ - /***********************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_TTLIOInfo. - b_PortConfiguration - [2] - = - b_PortCMode; - - /***********************/ - /* Set TTL port D mode */ - /***********************/ - - devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_TTLIOInfo. - b_PortConfiguration - [3] - = - b_PortDMode; - - /*************************/ - /* Set the configuration */ - /*************************/ - - outl((b_PortAMode << 0) | (b_PortBMode << 1) | (b_PortCMode << 2) | (b_PortDMode << 3), devpriv->s_BoardInfos.ui_Address + 20 + (64 * b_ModulNbr)); - } else { - /**********************************/ - /* Port D mode selection is wrong */ - /**********************************/ - - DPRINTK("Port D mode selection is wrong\n"); - i_ReturnValue - = - -8; - } - } else { - /**********************************/ - /* Port C mode selection is wrong */ - /**********************************/ - - DPRINTK("Port C mode selection is wrong\n"); - i_ReturnValue = - -7; - } - } else { - /**********************************/ - /* Port B mode selection is wrong */ - /**********************************/ - - DPRINTK("Port B mode selection is wrong\n"); - i_ReturnValue = -6; - } - } else { - /**********************************/ - /* Port A mode selection is wrong */ - /**********************************/ - - DPRINTK("Port A mode selection is wrong\n"); - i_ReturnValue = -5; - } - } else { - /*******************************************/ - /* Function not available for this version */ - /*******************************************/ - - DPRINTK("Function not available for this version\n"); - i_ReturnValue = -4; - } - break; - - DPRINTK("\n"); - default: - printk("Bad Config Type\n"); - } /* switch end */ - } else { - /**********************************/ - /* The module is not a TTL module */ - /**********************************/ - - DPRINTK("The module is not a TTL module\n"); - i_ReturnValue = -3; - } - } else { - /***********************/ - /* Module number error */ - /***********************/ - - DPRINTK("Module number error\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| INPUT FUNCTIONS | -+----------------------------------------------------------------------------+ -*/ - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_ReadTTLIOChannelValue | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_SelectedPort, | -| unsigned char_ b_InputChannel, | -| unsigned char *_ pb_ChannelStatus) | -+----------------------------------------------------------------------------+ -| Task : Read the status from selected TTL digital input | -| (b_InputChannel) -+----------------------------------------------------------------------------+ -| Task : Read the status from digital input port | -| (b_SelectedPort) from selected TTL module (b_ModulNbr) | -+----------------------------------------------------------------------------+ - -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710| -| unsigned char_ b_ModulNbr : Module number to | -| configure (0 to 7) | -| unsigned char_ b_SelectedPort, : Selection from TTL I/O | -| port (0 to 2) | -| 0 : Port A selection | -| 1 : Port B selection | -| 2 : Port C selection | -| 3 : Port D selection | -| unsigned char_ b_InputChannel : Selection from digital | -| input ( 0 to 2) -APCI1710_TTL_READCHANNEL - b_ModulNbr = CR_AREF(insn->chanspec); - b_SelectedPort= CR_RANGE(insn->chanspec); - b_InputChannel= CR_CHAN(insn->chanspec); - b_ReadType = (unsigned char) data[0]; - - APCI1710_TTL_READPORT| - b_ModulNbr = CR_AREF(insn->chanspec); - b_SelectedPort= CR_RANGE(insn->chanspec); - b_ReadType = (unsigned char) data[0]; - -+----------------------------------------------------------------------------+ -| Output Parameters : data[0] - - unsigned char *_ pb_ChannelStatus : Digital input channel | -| status | -| 0 : Channle is not active| -| 1 : Channle is active | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: The module parameter is wrong | -| -3: The module is not a TTL module | -| -4: The selected TTL input port is wrong | -| -5: The selected TTL digital input is wrong | -| -6: TTL I/O not initialised | -+----------------------------------------------------------------------------+ -*/ - -static int i_APCI1710_InsnBitsReadTTLIO(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned int dw_StatusReg; - unsigned char b_ModulNbr; - unsigned char b_SelectedPort; - unsigned char b_InputChannel; - unsigned char b_ReadType; - unsigned char *pb_ChannelStatus; - unsigned char *pb_PortValue; - - i_ReturnValue = insn->n; - b_ReadType = (unsigned char) data[0]; - b_ModulNbr = CR_AREF(insn->chanspec); - b_SelectedPort = CR_RANGE(insn->chanspec); - b_InputChannel = CR_CHAN(insn->chanspec); - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /**************************/ - /* Test if TTL I/O module */ - /**************************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModulNbr] & - 0xFFFF0000UL) == APCI1710_TTL_IO) { - switch (b_ReadType) { - - case APCI1710_TTL_READCHANNEL: - pb_ChannelStatus = (unsigned char *) &data[0]; - /********************************/ - /* Test the TTL I/O port number */ - /********************************/ - - if (((b_SelectedPort <= 2) - && ((devpriv->s_BoardInfos. - dw_MolduleConfiguration - [b_ModulNbr] & - 0xFFFF) == - 0x3130)) - || ((b_SelectedPort <= 3) - && ((devpriv->s_BoardInfos. - dw_MolduleConfiguration - [b_ModulNbr] & - 0xFFFF) >= - 0x3230))) { - /******************************************/ - /* Test the digital imnput channel number */ - /******************************************/ - - if (((b_InputChannel <= 7) - && (b_SelectedPort < 3)) - || ((b_InputChannel <= 1) - && (b_SelectedPort == - 3))) { - /******************************************/ - /* Test if the TTL I/O module initialised */ - /******************************************/ - - if (devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_TTLIOInfo.b_TTLInit == - 1) { - /***********************************/ - /* Test if TTL port used for input */ - /***********************************/ - - if (((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) == 0x3130) || (((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) >= 0x3230) && (devpriv->s_ModuleInfo[b_ModulNbr].s_TTLIOInfo.b_PortConfiguration[b_SelectedPort] == 0))) { - /**************************/ - /* Read all digital input */ - /**************************/ - - dw_StatusReg = - inl - (devpriv-> - s_BoardInfos. - ui_Address - + - (64 * b_ModulNbr)); - - *pb_ChannelStatus - = - (unsigned char) ( - (dw_StatusReg - >> - (8 * b_SelectedPort)) >> b_InputChannel) & 1; - } else { - /*******************************/ - /* Selected TTL I/O port error */ - /*******************************/ - - DPRINTK("Selected TTL I/O port error\n"); - i_ReturnValue = - -4; - } - } else { - /***************************/ - /* TTL I/O not initialised */ - /***************************/ - - DPRINTK("TTL I/O not initialised\n"); - i_ReturnValue = -6; - } - } else { - /********************************/ - /* Selected digital input error */ - /********************************/ - - DPRINTK("Selected digital input error\n"); - i_ReturnValue = -5; - } - } else { - /*******************************/ - /* Selected TTL I/O port error */ - /*******************************/ - - DPRINTK("Selected TTL I/O port error\n"); - i_ReturnValue = -4; - } - break; - - case APCI1710_TTL_READPORT: - pb_PortValue = (unsigned char *) &data[0]; - /********************************/ - /* Test the TTL I/O port number */ - /********************************/ - - if (((b_SelectedPort <= 2) - && ((devpriv->s_BoardInfos. - dw_MolduleConfiguration - [b_ModulNbr] & - 0xFFFF) == - 0x3130)) - || ((b_SelectedPort <= 3) - && ((devpriv->s_BoardInfos. - dw_MolduleConfiguration - [b_ModulNbr] & - 0xFFFF) >= - 0x3230))) { - /******************************************/ - /* Test if the TTL I/O module initialised */ - /******************************************/ - - if (devpriv->s_ModuleInfo[b_ModulNbr]. - s_TTLIOInfo.b_TTLInit == 1) { - /***********************************/ - /* Test if TTL port used for input */ - /***********************************/ - - if (((devpriv->s_BoardInfos. - dw_MolduleConfiguration - [b_ModulNbr] - & - 0xFFFF) - == 0x3130) - || (((devpriv->s_BoardInfos.dw_MolduleConfiguration[b_ModulNbr] & 0xFFFF) >= 0x3230) && (devpriv->s_ModuleInfo[b_ModulNbr].s_TTLIOInfo.b_PortConfiguration[b_SelectedPort] == 0))) { - /**************************/ - /* Read all digital input */ - /**************************/ - - dw_StatusReg = - inl(devpriv-> - s_BoardInfos. - ui_Address + - (64 * b_ModulNbr)); - - *pb_PortValue = - (unsigned char) ( - (dw_StatusReg >> - (8 * b_SelectedPort)) & 0xFF); - } else { - /*******************************/ - /* Selected TTL I/O port error */ - /*******************************/ - - DPRINTK("Selected TTL I/O port error\n"); - i_ReturnValue = -4; - } - } else { - /***************************/ - /* TTL I/O not initialised */ - /***************************/ - - DPRINTK("TTL I/O not initialised\n"); - i_ReturnValue = -5; - } - } else { - /*******************************/ - /* Selected TTL I/O port error */ - /*******************************/ - - DPRINTK("Selected TTL I/O port error\n"); - i_ReturnValue = -4; - } - break; - - default: - printk("Bad ReadType\n"); - - } /* End Switch */ - } else { - /**********************************/ - /* The module is not a TTL module */ - /**********************************/ - - DPRINTK("The module is not a TTL module\n"); - i_ReturnValue = -3; - } - } else { - /***********************/ - /* Module number error */ - /***********************/ - - DPRINTK("Module number error\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : int i_APCI1710_InsnReadTTLIOAllPortValue(comedi_device -*dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) | -+----------------------------------------------------------------------------+ -| Task : Read the status from all digital input ports | -| (port A, port B and port C) from selected TTL | -| module (b_ModulNbr) | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710| -| unsigned char_ b_ModulNbr : Module number to | -| configure (0 to 3) | -+----------------------------------------------------------------------------+ -| Output Parameters : PULONG_ pul_PortValue : Digital TTL inputs port | -| status | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: The module parameter is wrong | -| -3: The module is not a TTL module | -| -4: TTL I/O not initialised | -+----------------------------------------------------------------------------+ -*/ - -static int i_APCI1710_InsnReadTTLIOAllPortValue(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned int dw_StatusReg; - unsigned char b_ModulNbr; - unsigned int *pul_PortValue; - - b_ModulNbr = (unsigned char) CR_AREF(insn->chanspec); - i_ReturnValue = insn->n; - pul_PortValue = (unsigned int *) &data[0]; - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /**************************/ - /* Test if TTL I/O module */ - /**************************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModulNbr] & - 0xFFFF0000UL) == APCI1710_TTL_IO) { - /******************************************/ - /* Test if the TTL I/O module initialised */ - /******************************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_TTLIOInfo.b_TTLInit == 1) { - /**************************/ - /* Read all digital input */ - /**************************/ - - dw_StatusReg = inl(devpriv->s_BoardInfos. - ui_Address + (64 * b_ModulNbr)); - - /**********************/ - /* Test if TTL Rev1.0 */ - /**********************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration - [b_ModulNbr] & 0xFFFF) == - 0x3130) { - *pul_PortValue = - dw_StatusReg & 0xFFFFFFUL; - } else { - /**************************************/ - /* Test if port A not used for output */ - /**************************************/ - - if (devpriv->s_ModuleInfo[b_ModulNbr]. - s_TTLIOInfo. - b_PortConfiguration[0] == 1) { - *pul_PortValue = - dw_StatusReg & - 0x3FFFF00UL; - } - - /**************************************/ - /* Test if port B not used for output */ - /**************************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_TTLIOInfo. - b_PortConfiguration[1] == 1) { - *pul_PortValue = - dw_StatusReg & - 0x3FF00FFUL; - } - - /**************************************/ - /* Test if port C not used for output */ - /**************************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_TTLIOInfo. - b_PortConfiguration[2] == 1) { - *pul_PortValue = - dw_StatusReg & - 0x300FFFFUL; - } - - /**************************************/ - /* Test if port D not used for output */ - /**************************************/ - - if (devpriv-> - s_ModuleInfo[b_ModulNbr]. - s_TTLIOInfo. - b_PortConfiguration[3] == 1) { - *pul_PortValue = - dw_StatusReg & - 0xFFFFFFUL; - } - } - } else { - /***************************/ - /* TTL I/O not initialised */ - /***************************/ - DPRINTK("TTL I/O not initialised\n"); - i_ReturnValue = -5; - } - } else { - /**********************************/ - /* The module is not a TTL module */ - /**********************************/ - DPRINTK("The module is not a TTL module\n"); - i_ReturnValue = -3; - } - } else { - /***********************/ - /* Module number error */ - /***********************/ - DPRINTK("Module number error\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} - -/* -+----------------------------------------------------------------------------+ -| OUTPUT FUNCTIONS | -+----------------------------------------------------------------------------+ -*/ - -/* -+----------------------------------------------------------------------------+ -| Function Name : _INT_ i_APCI1710_SetTTLIOChlOn | -| (unsigned char_ b_BoardHandle, | -| unsigned char_ b_ModulNbr, | -| unsigned char_ b_OutputChannel) -int i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device *dev,struct comedi_subdevice *s, - struct comedi_insn *insn,unsigned int *data) | -+----------------------------------------------------------------------------+ -| Task : Sets or resets the output witch has been passed with the | -| parameter b_Channel. Setting an output means setting | -| an ouput high. | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char_ b_BoardHandle : Handle of board APCI-1710 | -| unsigned char_ b_ModulNbr : Selected module number (0 to 3)| -| unsigned char_ b_OutputChannel : Selection from digital output | -| channel (0 or 1) | -| 0 : PD0 | -| 1 : PD1 | -| 2 to 9 : PA | -| 10 to 17: PB | -| 18 to 25: PC | - - b_ModulNbr = CR_AREF(insn->chanspec); - b_OutputChannel= CR_CHAN(insn->chanspec); - ui_State = data[0]; ON or OFF -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0: No error | -| -1: The handle parameter of the board is wrong | -| -2: The module parameter is wrong | -| -3: The module is not a TTL I/O module | -| -4: The selected digital output is wrong | -| -5: TTL I/O not initialised see function | -| " i_APCI1710_InitTTLIO" -+----------------------------------------------------------------------------+ -*/ - -static int i_APCI1710_InsnWriteSetTTLIOChlOnOff(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct addi_private *devpriv = dev->private; - int i_ReturnValue = 0; - unsigned int dw_StatusReg = 0; - unsigned char b_ModulNbr; - unsigned char b_OutputChannel; - unsigned int ui_State; - - i_ReturnValue = insn->n; - b_ModulNbr = CR_AREF(insn->chanspec); - b_OutputChannel = CR_CHAN(insn->chanspec); - ui_State = data[0]; /* ON or OFF */ - - /**************************/ - /* Test the module number */ - /**************************/ - - if (b_ModulNbr < 4) { - /**************************/ - /* Test if TTL I/O module */ - /**************************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModulNbr] & - 0xFFFF0000UL) == APCI1710_TTL_IO) { - /******************************************/ - /* Test if the TTL I/O module initialised */ - /******************************************/ - - if (devpriv->s_ModuleInfo[b_ModulNbr]. - s_TTLIOInfo.b_TTLInit == 1) { - /***********************************/ - /* Test the TTL I/O channel number */ - /***********************************/ - - if (((b_OutputChannel <= 1) - && ((devpriv->s_BoardInfos. - dw_MolduleConfiguration - [b_ModulNbr] & - 0xFFFF) == - 0x3130)) - || ((b_OutputChannel <= 25) - && ((devpriv->s_BoardInfos. - dw_MolduleConfiguration - [b_ModulNbr] & - 0xFFFF) >= - 0x3230))) { - /****************************************************/ - /* Test if the selected channel is a output channel */ - /****************************************************/ - - if (((b_OutputChannel <= 1) - && (devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_TTLIOInfo. - b_PortConfiguration - [3] == 1)) - || ((b_OutputChannel >= 2) - && (b_OutputChannel <= - 9) - && (devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_TTLIOInfo. - b_PortConfiguration - [0] == 1)) - || ((b_OutputChannel >= 10) - && (b_OutputChannel <= - 17) - && (devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_TTLIOInfo. - b_PortConfiguration - [1] == 1)) - || ((b_OutputChannel >= 18) - && (b_OutputChannel <= - 25) - && (devpriv-> - s_ModuleInfo - [b_ModulNbr]. - s_TTLIOInfo. - b_PortConfiguration - [2] == 1))) { - /************************/ - /* Test if PD0 selected */ - /************************/ - - if (b_OutputChannel == 0) { - - outl(ui_State, - devpriv-> - s_BoardInfos. - ui_Address + - (64 * b_ModulNbr)); - } else { - /************************/ - /* Test if PD1 selected */ - /************************/ - - if (b_OutputChannel == - 1) { - - outl(ui_State, - devpriv-> - s_BoardInfos. - ui_Address - + 4 + - (64 * b_ModulNbr)); - } else { - b_OutputChannel - = - b_OutputChannel - - 2; - - /********************/ - /* Read all channel */ - /********************/ - - dw_StatusReg = - inl - (devpriv-> - s_BoardInfos. - ui_Address - + - (64 * b_ModulNbr)); - if (ui_State) /* ON */ - { - dw_StatusReg - = - (dw_StatusReg - >> - ((b_OutputChannel / 8) * 8)) & 0xFF; - dw_StatusReg - = - dw_StatusReg - | - (1 - << - (b_OutputChannel - % - 8)); - } else /* Off */ - { - dw_StatusReg - = - (dw_StatusReg - >> - ((b_OutputChannel / 8) * 8)) & 0xFF; - dw_StatusReg - = - dw_StatusReg - & - (0xFF - - - (1 << (b_OutputChannel % 8))); - - } - - /****************************/ - /* Set the new output value */ - /****************************/ - - outl(dw_StatusReg, devpriv->s_BoardInfos.ui_Address + 8 + ((b_OutputChannel / 8) * 4) + (64 * b_ModulNbr)); - } - } - } else { - /************************************/ - /* The selected TTL output is wrong */ - /************************************/ - - DPRINTK(" The selected TTL output is wrong\n"); - i_ReturnValue = -4; - } - } else { - /************************************/ - /* The selected TTL output is wrong */ - /************************************/ - - DPRINTK("The selected TTL output is wrong\n"); - i_ReturnValue = -4; - } - } else { - /***************************/ - /* TTL I/O not initialised */ - /***************************/ - - DPRINTK("TTL I/O not initialised\n"); - i_ReturnValue = -5; - } - } else { - /**************************************/ - /* The module is not a TTL I/O module */ - /**************************************/ - - DPRINTK("The module is not a TTL I/O module\n"); - i_ReturnValue = -3; - } - } else { - /***********************/ - /* Module number error */ - /***********************/ - - DPRINTK("Module number error\n"); - i_ReturnValue = -2; - } - - return i_ReturnValue; -} diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c deleted file mode 100644 index b1a7ec1035e1..000000000000 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c +++ /dev/null @@ -1,1314 +0,0 @@ -/** -@verbatim - -Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. - - ADDI-DATA GmbH - Dieselstrasse 3 - D-77833 Ottersweier - Tel: +19(0)7223/9493-0 - Fax: +49(0)7223/9493-92 - http://www.addi-data.com - info@addi-data.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. - -@endverbatim -*/ -/* - +-----------------------------------------------------------------------+ - | (C) ADDI-DATA GmbH Dieselstraße 3 D-77833 Ottersweier | - +-----------------------------------------------------------------------+ - | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | - | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | - +-------------------------------+---------------------------------------+ - | Project : APCI-1710 | Compiler : GCC | - | Module name : hwdrv_apci1710.c| Version : 2.96 | - +-------------------------------+---------------------------------------+ - | Project manager: Eric Stolz | Date : 02/12/2002 | - +-------------------------------+---------------------------------------+ - | Description : Hardware Layer Access For APCI-1710 | - +-----------------------------------------------------------------------+ - | UPDATES | - +----------+-----------+------------------------------------------------+ - | Date | Author | Description of updates | - +----------+-----------+------------------------------------------------+ - | | | | - | | | | - | | | | - +----------+-----------+------------------------------------------------+ -*/ - -#define COMEDI_SUBD_TTLIO 11 /* Digital Input Output But TTL */ -#define COMEDI_SUBD_PWM 12 /* Pulse width Measurement */ -#define COMEDI_SUBD_SSI 13 /* Synchronous serial interface */ -#define COMEDI_SUBD_TOR 14 /* Tor counter */ -#define COMEDI_SUBD_CHRONO 15 /* Chrono meter */ -#define COMEDI_SUBD_PULSEENCODER 16 /* Pulse Encoder INP CPT */ -#define COMEDI_SUBD_INCREMENTALCOUNTER 17 /* Incremental Counter */ - -#define APCI1710_BOARD_NAME "apci1710" -#define APCI1710_BOARD_DEVICE_ID 0x818F -#define APCI1710_ADDRESS_RANGE 256 -#define APCI1710_CONFIG_ADDRESS_RANGE 8 -#define APCI1710_INCREMENTAL_COUNTER 0x53430000UL -#define APCI1710_SSI_COUNTER 0x53490000UL -#define APCI1710_TTL_IO 0x544C0000UL -#define APCI1710_DIGITAL_IO 0x44490000UL -#define APCI1710_82X54_TIMER 0x49430000UL -#define APCI1710_CHRONOMETER 0x43480000UL -#define APCI1710_PULSE_ENCODER 0x495A0000UL -#define APCI1710_TOR_COUNTER 0x544F0000UL -#define APCI1710_PWM 0x50570000UL -#define APCI1710_ETM 0x45540000UL -#define APCI1710_CDA 0x43440000UL -#define APCI1710_DISABLE 0 -#define APCI1710_ENABLE 1 -#define APCI1710_SYNCHRONOUS_MODE 1 -#define APCI1710_ASYNCHRONOUS_MODE 0 - -#include "APCI1710_Inp_cpt.c" - -#include "APCI1710_Ssi.c" -#include "APCI1710_Tor.c" -#include "APCI1710_Ttl.c" -#include "APCI1710_Dig_io.c" -#include "APCI1710_82x54.c" -#include "APCI1710_Chrono.c" -#include "APCI1710_Pwm.c" -#include "APCI1710_INCCPT.c" - -static const struct comedi_lrange range_apci1710_ttl = { - 4, { - BIP_RANGE(10), - BIP_RANGE(5), - BIP_RANGE(2), - BIP_RANGE(1) - } -}; - -static const struct comedi_lrange range_apci1710_ssi = { - 4, { - BIP_RANGE(10), - BIP_RANGE(5), - BIP_RANGE(2), - BIP_RANGE(1) - } -}; - -static const struct comedi_lrange range_apci1710_inccpt = { - 4, { - BIP_RANGE(10), - BIP_RANGE(5), - BIP_RANGE(2), - BIP_RANGE(1) - } -}; - -static void i_ADDI_AttachPCI1710(struct comedi_device *dev) -{ - struct comedi_subdevice *s; - int ret = 0; - int n_subdevices = 9; - - ret = comedi_alloc_subdevices(dev, n_subdevices); - if (ret) - return; - - /* Allocate and Initialise Timer Subdevice Structures */ - s = &dev->subdevices[0]; - - s->type = COMEDI_SUBD_TIMER; - s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON; - s->n_chan = 3; - s->maxdata = 0; - s->len_chanlist = 3; - s->range_table = &range_digital; - s->insn_write = i_APCI1710_InsnWriteEnableDisableTimer; - s->insn_read = i_APCI1710_InsnReadAllTimerValue; - s->insn_config = i_APCI1710_InsnConfigInitTimer; - s->insn_bits = i_APCI1710_InsnBitsTimer; - - /* Allocate and Initialise DIO Subdevice Structures */ - s = &dev->subdevices[1]; - - s->type = COMEDI_SUBD_DIO; - s->subdev_flags = - SDF_WRITEABLE | SDF_READABLE | SDF_GROUND | SDF_COMMON; - s->n_chan = 7; - s->maxdata = 1; - s->len_chanlist = 7; - s->range_table = &range_digital; - s->insn_config = i_APCI1710_InsnConfigDigitalIO; - s->insn_read = i_APCI1710_InsnReadDigitalIOChlValue; - s->insn_bits = i_APCI1710_InsnBitsDigitalIOPortOnOff; - s->insn_write = i_APCI1710_InsnWriteDigitalIOChlOnOff; - - /* Allocate and Initialise Chrono Subdevice Structures */ - s = &dev->subdevices[2]; - - s->type = COMEDI_SUBD_CHRONO; - s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON; - s->n_chan = 4; - s->maxdata = 0; - s->len_chanlist = 4; - s->range_table = &range_digital; - s->insn_write = i_APCI1710_InsnWriteEnableDisableChrono; - s->insn_read = i_APCI1710_InsnReadChrono; - s->insn_config = i_APCI1710_InsnConfigInitChrono; - s->insn_bits = i_APCI1710_InsnBitsChronoDigitalIO; - - /* Allocate and Initialise PWM Subdevice Structures */ - s = &dev->subdevices[3]; - s->type = COMEDI_SUBD_PWM; - s->subdev_flags = - SDF_WRITEABLE | SDF_READABLE | SDF_GROUND | SDF_COMMON; - s->n_chan = 3; - s->maxdata = 1; - s->len_chanlist = 3; - s->range_table = &range_digital; - s->io_bits = 0; /* all bits input */ - s->insn_config = i_APCI1710_InsnConfigPWM; - s->insn_read = i_APCI1710_InsnReadGetPWMStatus; - s->insn_write = i_APCI1710_InsnWritePWM; - s->insn_bits = i_APCI1710_InsnBitsReadPWMInterrupt; - - /* Allocate and Initialise TTLIO Subdevice Structures */ - s = &dev->subdevices[4]; - s->type = COMEDI_SUBD_TTLIO; - s->subdev_flags = - SDF_WRITEABLE | SDF_READABLE | SDF_GROUND | SDF_COMMON; - s->n_chan = 8; - s->maxdata = 1; - s->len_chanlist = 8; - s->range_table = &range_apci1710_ttl; /* to pass arguments in range */ - s->insn_config = i_APCI1710_InsnConfigInitTTLIO; - s->insn_bits = i_APCI1710_InsnBitsReadTTLIO; - s->insn_write = i_APCI1710_InsnWriteSetTTLIOChlOnOff; - s->insn_read = i_APCI1710_InsnReadTTLIOAllPortValue; - - /* Allocate and Initialise TOR Subdevice Structures */ - s = &dev->subdevices[5]; - s->type = COMEDI_SUBD_TOR; - s->subdev_flags = - SDF_WRITEABLE | SDF_READABLE | SDF_GROUND | SDF_COMMON; - s->n_chan = 8; - s->maxdata = 1; - s->len_chanlist = 8; - s->range_table = &range_digital; - s->io_bits = 0; /* all bits input */ - s->insn_config = i_APCI1710_InsnConfigInitTorCounter; - s->insn_read = i_APCI1710_InsnReadGetTorCounterInitialisation; - s->insn_write = i_APCI1710_InsnWriteEnableDisableTorCounter; - s->insn_bits = i_APCI1710_InsnBitsGetTorCounterProgressStatusAndValue; - - /* Allocate and Initialise SSI Subdevice Structures */ - s = &dev->subdevices[6]; - s->type = COMEDI_SUBD_SSI; - s->subdev_flags = - SDF_WRITEABLE | SDF_READABLE | SDF_GROUND | SDF_COMMON; - s->n_chan = 4; - s->maxdata = 1; - s->len_chanlist = 4; - s->range_table = &range_apci1710_ssi; - s->insn_config = i_APCI1710_InsnConfigInitSSI; - s->insn_read = i_APCI1710_InsnReadSSIValue; - s->insn_bits = i_APCI1710_InsnBitsSSIDigitalIO; - - /* Allocate and Initialise PULSEENCODER Subdevice Structures */ - s = &dev->subdevices[7]; - s->type = COMEDI_SUBD_PULSEENCODER; - s->subdev_flags = - SDF_WRITEABLE | SDF_READABLE | SDF_GROUND | SDF_COMMON; - s->n_chan = 4; - s->maxdata = 1; - s->len_chanlist = 4; - s->range_table = &range_digital; - s->insn_config = i_APCI1710_InsnConfigInitPulseEncoder; - s->insn_write = i_APCI1710_InsnWriteEnableDisablePulseEncoder; - s->insn_bits = i_APCI1710_InsnBitsReadWritePulseEncoder; - s->insn_read = i_APCI1710_InsnReadInterruptPulseEncoder; - - /* Allocate and Initialise INCREMENTALCOUNTER Subdevice Structures */ - s = &dev->subdevices[8]; - s->type = COMEDI_SUBD_INCREMENTALCOUNTER; - s->subdev_flags = - SDF_WRITEABLE | SDF_READABLE | SDF_GROUND | SDF_COMMON; - s->n_chan = 500; - s->maxdata = 1; - s->len_chanlist = 500; - s->range_table = &range_apci1710_inccpt; - s->insn_config = i_APCI1710_InsnConfigINCCPT; - s->insn_write = i_APCI1710_InsnWriteINCCPT; - s->insn_read = i_APCI1710_InsnReadINCCPT; - s->insn_bits = i_APCI1710_InsnBitsINCCPT; -} - -static int i_APCI1710_Reset(struct comedi_device *dev) -{ - struct addi_private *devpriv = dev->private; - int ret; - unsigned int dw_Dummy; - - /*********************************/ - /* Read all module configuration */ - /*********************************/ - ret = inl(devpriv->s_BoardInfos.ui_Address + 60); - devpriv->s_BoardInfos.dw_MolduleConfiguration[0] = ret; - - ret = inl(devpriv->s_BoardInfos.ui_Address + 124); - devpriv->s_BoardInfos.dw_MolduleConfiguration[1] = ret; - - ret = inl(devpriv->s_BoardInfos.ui_Address + 188); - devpriv->s_BoardInfos.dw_MolduleConfiguration[2] = ret; - - ret = inl(devpriv->s_BoardInfos.ui_Address + 252); - devpriv->s_BoardInfos.dw_MolduleConfiguration[3] = ret; - - /* outl(0x80808082,devpriv->s_BoardInfos.ui_Address+0x60); */ - outl(0x83838383, devpriv->s_BoardInfos.ui_Address + 0x60); - - devpriv->s_BoardInfos.b_BoardVersion = 1; - - /* Enable the interrupt for the controller */ - dw_Dummy = inl(devpriv->s_BoardInfos.ui_Address + 0x38); - outl(dw_Dummy | 0x2000, devpriv->s_BoardInfos.ui_Address + 0x38); - - return 0; -} - -/* -+----------------------------------------------------------------------------+ -| Function's Name : __void__ v_APCI1710_InterruptFunction | -| (unsigned char b_Interrupt, __CPPARGS) | -+----------------------------------------------------------------------------+ -| Task : APCI-1710 interrupt function | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned char b_Interrupt : Interrupt number | -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0 : OK | -| -1 : Error | -+----------------------------------------------------------------------------+ -*/ - -static void v_APCI1710_Interrupt(int irq, void *d) -{ - struct comedi_device *dev = d; - struct addi_private *devpriv = dev->private; - unsigned char b_ModuleCpt = 0; - unsigned char b_InterruptFlag = 0; - unsigned char b_PWMCpt = 0; - unsigned char b_TorCounterCpt = 0; - unsigned char b_PulseIncoderCpt = 0; - unsigned int ui_16BitValue; - unsigned int ul_InterruptLatchReg = 0; - unsigned int ul_LatchRegisterValue = 0; - unsigned int ul_82X54InterruptStatus; - unsigned int ul_StatusRegister; - - union str_ModuleInfo *ps_ModuleInfo; - - printk("APCI1710 Interrupt\n"); - for (b_ModuleCpt = 0; b_ModuleCpt < 4; b_ModuleCpt++, ps_ModuleInfo++) { - - /**************************/ - /* 1199/0225 to 0100/0226 */ - /**************************/ - ps_ModuleInfo = &devpriv->s_ModuleInfo[b_ModuleCpt]; - - /***********************/ - /* Test if 82X54 timer */ - /***********************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModuleCpt] & - 0xFFFF0000UL) == APCI1710_82X54_TIMER) { - - /* printk("TIMER Interrupt Occurred\n"); */ - ul_82X54InterruptStatus = inl(devpriv->s_BoardInfos. - ui_Address + 12 + (64 * b_ModuleCpt)); - - /***************************/ - /* Test if interrupt occur */ - /***************************/ - - if ((ul_82X54InterruptStatus & ps_ModuleInfo-> - s_82X54ModuleInfo. - b_InterruptMask) != 0) { - devpriv-> - s_InterruptParameters. - s_FIFOInterruptParameters[devpriv-> - s_InterruptParameters. - ui_Write]. - ul_OldInterruptMask = - (ul_82X54InterruptStatus & - ps_ModuleInfo->s_82X54ModuleInfo. - b_InterruptMask) << 4; - - devpriv-> - s_InterruptParameters. - s_FIFOInterruptParameters[devpriv-> - s_InterruptParameters. - ui_Write]. - b_OldModuleMask = 1 << b_ModuleCpt; - - devpriv-> - s_InterruptParameters. - s_FIFOInterruptParameters[devpriv-> - s_InterruptParameters. - ui_Write].ul_OldCounterLatchValue = 0; - - devpriv-> - s_InterruptParameters. - ul_InterruptOccur++; - - /****************************/ - /* Increment the write FIFO */ - /****************************/ - - devpriv-> - s_InterruptParameters. - ui_Write = (devpriv-> - s_InterruptParameters. - ui_Write + 1) % APCI1710_SAVE_INTERRUPT; - - b_InterruptFlag = 1; - - /**********************/ - /* Call user function */ - /**********************/ - /* Send a signal to from kernel to user space */ - send_sig(SIGIO, devpriv->tsk_Current, 0); - - } /* if ((ul_82X54InterruptStatus & 0x7) != 0) */ - } /* 82X54 timer */ - - /***************************/ - /* Test if increm. counter */ - /***************************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModuleCpt] & - 0xFFFF0000UL) == APCI1710_INCREMENTAL_COUNTER) { - - ul_InterruptLatchReg = inl(devpriv->s_BoardInfos. - ui_Address + (64 * b_ModuleCpt)); - - /*********************/ - /* Test if interrupt */ - /*********************/ - - if ((ul_InterruptLatchReg & 0x22) && (ps_ModuleInfo-> - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister2 & 0x80)) { - /************************************/ - /* Test if strobe latch I interrupt */ - /************************************/ - - if (ul_InterruptLatchReg & 2) { - ul_LatchRegisterValue = - inl(devpriv->s_BoardInfos. - ui_Address + 4 + - (64 * b_ModuleCpt)); - - devpriv-> - s_InterruptParameters. - s_FIFOInterruptParameters - [devpriv->s_InterruptParameters. - ui_Write].ul_OldInterruptMask = - 1UL; - - devpriv-> - s_InterruptParameters. - s_FIFOInterruptParameters - [devpriv->s_InterruptParameters. - ui_Write].b_OldModuleMask = - 1 << b_ModuleCpt; - - devpriv-> - s_InterruptParameters. - s_FIFOInterruptParameters - [devpriv->s_InterruptParameters. - ui_Write]. - ul_OldCounterLatchValue = - ul_LatchRegisterValue; - - devpriv-> - s_InterruptParameters. - ul_InterruptOccur++; - - /****************************/ - /* 0899/0224 to 1199/0225 */ - /****************************/ - /* Increment the write FIFO */ - /****************************/ - - devpriv-> - s_InterruptParameters. - ui_Write = (devpriv-> - s_InterruptParameters. - ui_Write + - 1) % APCI1710_SAVE_INTERRUPT; - - b_InterruptFlag = 1; - - /**********************/ - /* Call user function */ - /**********************/ - /* Send a signal to from kernel to user space */ - send_sig(SIGIO, devpriv->tsk_Current, - 0); - - } - - /*************************************/ - /* Test if strobe latch II interrupt */ - /*************************************/ - - if (ul_InterruptLatchReg & 0x20) { - - ul_LatchRegisterValue = - inl(devpriv->s_BoardInfos. - ui_Address + 8 + - (64 * b_ModuleCpt)); - - devpriv-> - s_InterruptParameters. - s_FIFOInterruptParameters - [devpriv->s_InterruptParameters. - ui_Write].ul_OldInterruptMask = - 2UL; - - devpriv-> - s_InterruptParameters. - s_FIFOInterruptParameters - [devpriv->s_InterruptParameters. - ui_Write].b_OldModuleMask = - 1 << b_ModuleCpt; - - devpriv-> - s_InterruptParameters. - s_FIFOInterruptParameters - [devpriv->s_InterruptParameters. - ui_Write]. - ul_OldCounterLatchValue = - ul_LatchRegisterValue; - - devpriv-> - s_InterruptParameters. - ul_InterruptOccur++; - - /****************************/ - /* 0899/0224 to 1199/0225 */ - /****************************/ - /* Increment the write FIFO */ - /****************************/ - - devpriv-> - s_InterruptParameters. - ui_Write = (devpriv-> - s_InterruptParameters. - ui_Write + - 1) % APCI1710_SAVE_INTERRUPT; - - b_InterruptFlag = 1; - - /**********************/ - /* Call user function */ - /**********************/ - /* Send a signal to from kernel to user space */ - send_sig(SIGIO, devpriv->tsk_Current, - 0); - - } - } - - ul_InterruptLatchReg = inl(devpriv->s_BoardInfos. - ui_Address + 24 + (64 * b_ModuleCpt)); - - /***************************/ - /* Test if index interrupt */ - /***************************/ - - if (ul_InterruptLatchReg & 0x8) { - ps_ModuleInfo-> - s_SiemensCounterInfo. - s_InitFlag.b_IndexInterruptOccur = 1; - - if (ps_ModuleInfo-> - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister2 & - APCI1710_INDEX_AUTO_MODE) { - - outl(ps_ModuleInfo-> - s_SiemensCounterInfo. - s_ModeRegister. - dw_ModeRegister1_2_3_4, - devpriv->s_BoardInfos. - ui_Address + 20 + - (64 * b_ModuleCpt)); - } - - /*****************************/ - /* Test if interrupt enabled */ - /*****************************/ - - if ((ps_ModuleInfo-> - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister3 & - APCI1710_ENABLE_INDEX_INT) == - APCI1710_ENABLE_INDEX_INT) { - devpriv->s_InterruptParameters. - s_FIFOInterruptParameters - [devpriv->s_InterruptParameters. - ui_Write].ul_OldInterruptMask = - 4UL; - - devpriv-> - s_InterruptParameters. - s_FIFOInterruptParameters - [devpriv->s_InterruptParameters. - ui_Write].b_OldModuleMask = - 1 << b_ModuleCpt; - - devpriv-> - s_InterruptParameters. - s_FIFOInterruptParameters - [devpriv->s_InterruptParameters. - ui_Write]. - ul_OldCounterLatchValue = - ul_LatchRegisterValue; - - devpriv-> - s_InterruptParameters. - ul_InterruptOccur++; - - /****************************/ - /* 0899/0224 to 1199/0225 */ - /****************************/ - /* Increment the write FIFO */ - /****************************/ - - devpriv-> - s_InterruptParameters. - ui_Write = (devpriv-> - s_InterruptParameters. - ui_Write + - 1) % APCI1710_SAVE_INTERRUPT; - - b_InterruptFlag = 1; - - /**********************/ - /* Call user function */ - /**********************/ - /* Send a signal to from kernel to user space */ - send_sig(SIGIO, devpriv->tsk_Current, - 0); - - } - } - - /*****************************/ - /* Test if compare interrupt */ - /*****************************/ - - if (ul_InterruptLatchReg & 0x10) { - /*****************************/ - /* Test if interrupt enabled */ - /*****************************/ - - if ((ps_ModuleInfo-> - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister3 & - APCI1710_ENABLE_COMPARE_INT) == - APCI1710_ENABLE_COMPARE_INT) { - devpriv->s_InterruptParameters. - s_FIFOInterruptParameters - [devpriv->s_InterruptParameters. - ui_Write].ul_OldInterruptMask = - 8UL; - - devpriv-> - s_InterruptParameters. - s_FIFOInterruptParameters - [devpriv->s_InterruptParameters. - ui_Write].b_OldModuleMask = - 1 << b_ModuleCpt; - - devpriv-> - s_InterruptParameters. - s_FIFOInterruptParameters - [devpriv->s_InterruptParameters. - ui_Write]. - ul_OldCounterLatchValue = - ul_LatchRegisterValue; - - devpriv-> - s_InterruptParameters. - ul_InterruptOccur++; - - /****************************/ - /* 0899/0224 to 1199/0225 */ - /****************************/ - /* Increment the write FIFO */ - /****************************/ - - devpriv-> - s_InterruptParameters. - ui_Write = (devpriv-> - s_InterruptParameters. - ui_Write + - 1) % APCI1710_SAVE_INTERRUPT; - - b_InterruptFlag = 1; - - /**********************/ - /* Call user function */ - /**********************/ - /* Send a signal to from kernel to user space */ - send_sig(SIGIO, devpriv->tsk_Current, - 0); - - } - } - - /*******************************************/ - /* Test if frequency measurement interrupt */ - /*******************************************/ - - if (ul_InterruptLatchReg & 0x20) { - /*******************/ - /* Read the status */ - /*******************/ - - ul_StatusRegister = inl(devpriv->s_BoardInfos. - ui_Address + 32 + (64 * b_ModuleCpt)); - - /******************/ - /* Read the value */ - /******************/ - - ul_LatchRegisterValue = - inl(devpriv->s_BoardInfos.ui_Address + - 28 + (64 * b_ModuleCpt)); - - switch ((ul_StatusRegister >> 1) & 3) { - case 0: - /*************************/ - /* Test the counter mode */ - /*************************/ - - if ((devpriv->s_ModuleInfo[b_ModuleCpt]. - s_SiemensCounterInfo. - s_ModeRegister. - s_ByteModeRegister. - b_ModeRegister1 & - APCI1710_16BIT_COUNTER) - == APCI1710_16BIT_COUNTER) { - /****************************************/ - /* Test if 16-bit counter 1 pulse occur */ - /****************************************/ - - if ((ul_LatchRegisterValue & - 0xFFFFU) != 0) { - ui_16BitValue = - (unsigned int) - ul_LatchRegisterValue - & 0xFFFFU; - ul_LatchRegisterValue = - (ul_LatchRegisterValue - & 0xFFFF0000UL) - | (0xFFFFU - - ui_16BitValue); - } - - /****************************************/ - /* Test if 16-bit counter 2 pulse occur */ - /****************************************/ - - if ((ul_LatchRegisterValue & - 0xFFFF0000UL) != - 0) { - ui_16BitValue = - (unsigned int) ( - (ul_LatchRegisterValue - >> 16) & - 0xFFFFU); - ul_LatchRegisterValue = - (ul_LatchRegisterValue - & 0xFFFFUL) | - ((0xFFFFU - - ui_16BitValue) - << 16); - } - } else { - if (ul_LatchRegisterValue != 0) { - ul_LatchRegisterValue = - 0xFFFFFFFFUL - - ul_LatchRegisterValue; - } - } - break; - - case 1: - /****************************************/ - /* Test if 16-bit counter 2 pulse occur */ - /****************************************/ - - if ((ul_LatchRegisterValue & - 0xFFFF0000UL) != 0) { - ui_16BitValue = - (unsigned int) ( - (ul_LatchRegisterValue - >> 16) & - 0xFFFFU); - ul_LatchRegisterValue = - (ul_LatchRegisterValue & - 0xFFFFUL) | ((0xFFFFU - - ui_16BitValue) - << 16); - } - break; - - case 2: - /****************************************/ - /* Test if 16-bit counter 1 pulse occur */ - /****************************************/ - - if ((ul_LatchRegisterValue & 0xFFFFU) != - 0) { - ui_16BitValue = - (unsigned int) - ul_LatchRegisterValue & - 0xFFFFU; - ul_LatchRegisterValue = - (ul_LatchRegisterValue & - 0xFFFF0000UL) | (0xFFFFU - - ui_16BitValue); - } - break; - } - - devpriv-> - s_InterruptParameters. - s_FIFOInterruptParameters[devpriv-> - s_InterruptParameters. - ui_Write]. - ul_OldInterruptMask = 0x10000UL; - - devpriv-> - s_InterruptParameters. - s_FIFOInterruptParameters[devpriv-> - s_InterruptParameters. - ui_Write]. - b_OldModuleMask = 1 << b_ModuleCpt; - - devpriv-> - s_InterruptParameters. - s_FIFOInterruptParameters[devpriv-> - s_InterruptParameters. - ui_Write]. - ul_OldCounterLatchValue = - ul_LatchRegisterValue; - - devpriv-> - s_InterruptParameters. - ul_InterruptOccur++; - - /****************************/ - /* 0899/0224 to 1199/0225 */ - /****************************/ - /* Increment the write FIFO */ - /****************************/ - - devpriv-> - s_InterruptParameters. - ui_Write = (devpriv-> - s_InterruptParameters. - ui_Write + 1) % APCI1710_SAVE_INTERRUPT; - - b_InterruptFlag = 1; - - /**********************/ - /* Call user function */ - /**********************/ - /* Send a signal to from kernel to user space */ - send_sig(SIGIO, devpriv->tsk_Current, 0); - - } - } /* Incremental counter */ - - /***************/ - /* Test if CDA */ - /***************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModuleCpt] & - 0xFFFF0000UL) == APCI1710_CDA) { - /******************************************/ - /* Test if CDA enable and functionality 0 */ - /******************************************/ - - if ((devpriv->s_ModuleInfo[b_ModuleCpt]. - s_CDAModuleInfo. - b_CDAEnable == APCI1710_ENABLE) - && (devpriv->s_ModuleInfo[b_ModuleCpt]. - s_CDAModuleInfo.b_FctSelection == 0)) { - /****************************/ - /* Get the interrupt status */ - /****************************/ - - ul_StatusRegister = inl(devpriv->s_BoardInfos. - ui_Address + 16 + (64 * b_ModuleCpt)); - /***************************/ - /* Test if interrupt occur */ - /***************************/ - - if (ul_StatusRegister & 1) { - devpriv-> - s_InterruptParameters. - s_FIFOInterruptParameters - [devpriv->s_InterruptParameters. - ui_Write].ul_OldInterruptMask = - 0x80000UL; - - devpriv-> - s_InterruptParameters. - s_FIFOInterruptParameters - [devpriv->s_InterruptParameters. - ui_Write].b_OldModuleMask = - 1 << b_ModuleCpt; - - devpriv-> - s_InterruptParameters. - s_FIFOInterruptParameters - [devpriv->s_InterruptParameters. - ui_Write]. - ul_OldCounterLatchValue = 0; - - devpriv-> - s_InterruptParameters. - ul_InterruptOccur++; - - /****************************/ - /* Increment the write FIFO */ - /****************************/ - - devpriv-> - s_InterruptParameters. - ui_Write = (devpriv-> - s_InterruptParameters. - ui_Write + - 1) % APCI1710_SAVE_INTERRUPT; - - b_InterruptFlag = 1; - - /**********************/ - /* Call user function */ - /**********************/ - - /* Send a signal to from kernel to user space */ - send_sig(SIGIO, devpriv->tsk_Current, - 0); - - } /* if (ul_StatusRegister & 1) */ - - } - } /* CDA */ - - /***********************/ - /* Test if PWM counter */ - /***********************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModuleCpt] & - 0xFFFF0000UL) == APCI1710_PWM) { - for (b_PWMCpt = 0; b_PWMCpt < 2; b_PWMCpt++) { - /*************************************/ - /* Test if PWM interrupt initialised */ - /*************************************/ - - if (devpriv-> - s_ModuleInfo[b_ModuleCpt]. - s_PWMModuleInfo. - s_PWMInfo[b_PWMCpt]. - b_InterruptEnable == APCI1710_ENABLE) { - /*****************************/ - /* Read the interrupt status */ - /*****************************/ - - ul_StatusRegister = - inl(devpriv->s_BoardInfos. - ui_Address + 16 + - (20 * b_PWMCpt) + - (64 * b_ModuleCpt)); - - /***************************/ - /* Test if interrupt occur */ - /***************************/ - - if (ul_StatusRegister & 0x1) { - devpriv-> - s_InterruptParameters. - s_FIFOInterruptParameters - [devpriv-> - s_InterruptParameters. - ui_Write]. - ul_OldInterruptMask = - 0x4000UL << b_PWMCpt; - - devpriv-> - s_InterruptParameters. - s_FIFOInterruptParameters - [devpriv-> - s_InterruptParameters. - ui_Write]. - b_OldModuleMask = - 1 << b_ModuleCpt; - - devpriv-> - s_InterruptParameters. - ul_InterruptOccur++; - - /****************************/ - /* Increment the write FIFO */ - /****************************/ - - devpriv-> - s_InterruptParameters. - ui_Write = (devpriv-> - s_InterruptParameters. - ui_Write + - 1) % - APCI1710_SAVE_INTERRUPT; - - b_InterruptFlag = 1; - - /**********************/ - /* Call user function */ - /**********************/ - /* Send a signal to from kernel to user space */ - send_sig(SIGIO, - devpriv->tsk_Current, - 0); - - } /* if (ul_StatusRegister & 0x1) */ - } /* if (APCI1710_ENABLE) */ - } /* for (b_PWMCpt == 0; b_PWMCpt < 0; b_PWMCpt ++) */ - } /* PWM counter */ - - /***********************/ - /* Test if tor counter */ - /***********************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModuleCpt] & - 0xFFFF0000UL) == APCI1710_TOR_COUNTER) { - for (b_TorCounterCpt = 0; b_TorCounterCpt < 2; - b_TorCounterCpt++) { - /*************************************/ - /* Test if tor interrupt initialised */ - /*************************************/ - - if (devpriv-> - s_ModuleInfo[b_ModuleCpt]. - s_TorCounterModuleInfo. - s_TorCounterInfo[b_TorCounterCpt]. - b_InterruptEnable == APCI1710_ENABLE) { - /*****************************/ - /* Read the interrupt status */ - /*****************************/ - - ul_StatusRegister = - inl(devpriv->s_BoardInfos. - ui_Address + 12 + - (16 * b_TorCounterCpt) + - (64 * b_ModuleCpt)); - - /***************************/ - /* Test if interrupt occur */ - /***************************/ - - if (ul_StatusRegister & 0x1) { - /******************************/ - /* Read the tor counter value */ - /******************************/ - - ul_LatchRegisterValue = - inl(devpriv-> - s_BoardInfos. - ui_Address + 0 + - (16 * b_TorCounterCpt) + - (64 * b_ModuleCpt)); - - devpriv-> - s_InterruptParameters. - s_FIFOInterruptParameters - [devpriv-> - s_InterruptParameters. - ui_Write]. - ul_OldInterruptMask = - 0x1000UL << - b_TorCounterCpt; - - devpriv-> - s_InterruptParameters. - s_FIFOInterruptParameters - [devpriv-> - s_InterruptParameters. - ui_Write]. - b_OldModuleMask = - 1 << b_ModuleCpt; - - devpriv-> - s_InterruptParameters. - s_FIFOInterruptParameters - [devpriv-> - s_InterruptParameters. - ui_Write]. - ul_OldCounterLatchValue - = ul_LatchRegisterValue; - - devpriv-> - s_InterruptParameters. - ul_InterruptOccur++; - - /****************************/ - /* Increment the write FIFO */ - /****************************/ - - devpriv-> - s_InterruptParameters. - ui_Write = (devpriv-> - s_InterruptParameters. - ui_Write + - 1) % - APCI1710_SAVE_INTERRUPT; - - b_InterruptFlag = 1; - - /**********************/ - /* Call user function */ - /**********************/ - - /* Send a signal to from kernel to user space */ - send_sig(SIGIO, - devpriv->tsk_Current, - 0); - } /* if (ul_StatusRegister & 0x1) */ - } /* if (APCI1710_ENABLE) */ - } /* for (b_TorCounterCpt == 0; b_TorCounterCpt < 0; b_TorCounterCpt ++) */ - } /* Tor counter */ - - /***********************/ - /* Test if chronometer */ - /***********************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModuleCpt] & - 0xFFFF0000UL) == APCI1710_CHRONOMETER) { - - /* printk("APCI1710 Chrono Interrupt\n"); */ - /*****************************/ - /* Read the interrupt status */ - /*****************************/ - - ul_InterruptLatchReg = inl(devpriv->s_BoardInfos. - ui_Address + 12 + (64 * b_ModuleCpt)); - - /***************************/ - /* Test if interrupt occur */ - /***************************/ - - if ((ul_InterruptLatchReg & 0x8) == 0x8) { - /****************************/ - /* Clear the interrupt flag */ - /****************************/ - - outl(0, devpriv->s_BoardInfos. - ui_Address + 32 + (64 * b_ModuleCpt)); - - /***************************/ - /* Test if continuous mode */ - /***************************/ - - if (ps_ModuleInfo-> - s_ChronoModuleInfo. - b_CycleMode == APCI1710_ENABLE) { - /********************/ - /* Clear the status */ - /********************/ - - outl(0, devpriv->s_BoardInfos. - ui_Address + 36 + - (64 * b_ModuleCpt)); - } - - /*************************/ - /* Read the timing value */ - /*************************/ - - ul_LatchRegisterValue = - inl(devpriv->s_BoardInfos.ui_Address + - 4 + (64 * b_ModuleCpt)); - - /*****************************/ - /* Test if interrupt enabled */ - /*****************************/ - - if (ps_ModuleInfo-> - s_ChronoModuleInfo.b_InterruptMask) { - devpriv-> - s_InterruptParameters. - s_FIFOInterruptParameters - [devpriv->s_InterruptParameters. - ui_Write].ul_OldInterruptMask = - 0x80; - - devpriv-> - s_InterruptParameters. - s_FIFOInterruptParameters - [devpriv->s_InterruptParameters. - ui_Write].b_OldModuleMask = - 1 << b_ModuleCpt; - - devpriv-> - s_InterruptParameters. - s_FIFOInterruptParameters - [devpriv->s_InterruptParameters. - ui_Write]. - ul_OldCounterLatchValue = - ul_LatchRegisterValue; - - devpriv-> - s_InterruptParameters. - ul_InterruptOccur++; - - /****************************/ - /* Increment the write FIFO */ - /****************************/ - - devpriv-> - s_InterruptParameters. - ui_Write = (devpriv-> - s_InterruptParameters. - ui_Write + - 1) % APCI1710_SAVE_INTERRUPT; - - b_InterruptFlag = 1; - - /**********************/ - /* Call user function */ - /**********************/ - /* Send a signal to from kernel to user space */ - send_sig(SIGIO, devpriv->tsk_Current, - 0); - - } - } - } /* Chronometer */ - - /*************************/ - /* Test if pulse encoder */ - /*************************/ - - if ((devpriv->s_BoardInfos. - dw_MolduleConfiguration[b_ModuleCpt] & - 0xFFFF0000UL) == APCI1710_PULSE_ENCODER) { - /****************************/ - /* Read the status register */ - /****************************/ - - ul_StatusRegister = inl(devpriv->s_BoardInfos. - ui_Address + 20 + (64 * b_ModuleCpt)); - - if (ul_StatusRegister & 0xF) { - for (b_PulseIncoderCpt = 0; - b_PulseIncoderCpt < 4; - b_PulseIncoderCpt++) { - /*************************************/ - /* Test if pulse encoder initialised */ - /*************************************/ - - if ((ps_ModuleInfo-> - s_PulseEncoderModuleInfo. - s_PulseEncoderInfo - [b_PulseIncoderCpt]. - b_PulseEncoderInit == 1) - && (((ps_ModuleInfo->s_PulseEncoderModuleInfo.dw_SetRegister >> b_PulseIncoderCpt) & 1) == 1) && (((ul_StatusRegister >> (b_PulseIncoderCpt)) & 1) == 1)) { - devpriv->s_InterruptParameters. - s_FIFOInterruptParameters - [devpriv-> - s_InterruptParameters. - ui_Write]. - ul_OldInterruptMask = - 0x100UL << - b_PulseIncoderCpt; - - devpriv-> - s_InterruptParameters. - s_FIFOInterruptParameters - [devpriv-> - s_InterruptParameters. - ui_Write]. - b_OldModuleMask = - 1 << b_ModuleCpt; - - devpriv-> - s_InterruptParameters. - s_FIFOInterruptParameters - [devpriv-> - s_InterruptParameters. - ui_Write]. - ul_OldCounterLatchValue - = ul_LatchRegisterValue; - - devpriv-> - s_InterruptParameters. - ul_InterruptOccur++; - - /****************************/ - /* 0899/0224 to 1199/0225 */ - /****************************/ - /* Increment the write FIFO */ - /****************************/ - - devpriv-> - s_InterruptParameters. - ui_Write = (devpriv-> - s_InterruptParameters. - ui_Write + - 1) % - APCI1710_SAVE_INTERRUPT; - - b_InterruptFlag = 1; - - /**********************/ - /* Call user function */ - /**********************/ - /* Send a signal to from kernel to user space */ - send_sig(SIGIO, - devpriv->tsk_Current, - 0); - - } - } - } - } /* pulse encoder */ - - } - return; - -} diff --git a/drivers/staging/comedi/drivers/addi_apci_1710.c b/drivers/staging/comedi/drivers/addi_apci_1710.c deleted file mode 100644 index 9157ac50815e..000000000000 --- a/drivers/staging/comedi/drivers/addi_apci_1710.c +++ /dev/null @@ -1,237 +0,0 @@ -#include -#include -#include - -#include - -#include "../comedidev.h" -#include "comedi_fc.h" -#include "amcc_s5933.h" - -#define APCI1710_SAVE_INTERRUPT 1 - -union str_ModuleInfo { - /* Incremental counter infos */ - struct { - union { - struct { - unsigned char b_ModeRegister1; - unsigned char b_ModeRegister2; - unsigned char b_ModeRegister3; - unsigned char b_ModeRegister4; - } s_ByteModeRegister; - unsigned int dw_ModeRegister1_2_3_4; - } s_ModeRegister; - - struct { - unsigned int b_IndexInit:1; - unsigned int b_CounterInit:1; - unsigned int b_ReferenceInit:1; - unsigned int b_IndexInterruptOccur:1; - unsigned int b_CompareLogicInit:1; - unsigned int b_FrequencyMeasurementInit:1; - unsigned int b_FrequencyMeasurementEnable:1; - } s_InitFlag; - - } s_SiemensCounterInfo; - - /* SSI infos */ - struct { - unsigned char b_SSIProfile; - unsigned char b_PositionTurnLength; - unsigned char b_TurnCptLength; - unsigned char b_SSIInit; - } s_SSICounterInfo; - - /* TTL I/O infos */ - struct { - unsigned char b_TTLInit; - unsigned char b_PortConfiguration[4]; - } s_TTLIOInfo; - - /* Digital I/O infos */ - struct { - unsigned char b_DigitalInit; - unsigned char b_ChannelAMode; - unsigned char b_ChannelBMode; - unsigned char b_OutputMemoryEnabled; - unsigned int dw_OutputMemory; - } s_DigitalIOInfo; - - /* 82X54 timer infos */ - struct { - struct { - unsigned char b_82X54Init; - unsigned char b_InputClockSelection; - unsigned char b_InputClockLevel; - unsigned char b_OutputLevel; - unsigned char b_HardwareGateLevel; - unsigned int dw_ConfigurationWord; - } s_82X54TimerInfo[3]; - unsigned char b_InterruptMask; - } s_82X54ModuleInfo; - - /* Chronometer infos */ - struct { - unsigned char b_ChronoInit; - unsigned char b_InterruptMask; - unsigned char b_PCIInputClock; - unsigned char b_TimingUnit; - unsigned char b_CycleMode; - double d_TimingInterval; - unsigned int dw_ConfigReg; - } s_ChronoModuleInfo; - - /* Pulse encoder infos */ - struct { - struct { - unsigned char b_PulseEncoderInit; - } s_PulseEncoderInfo[4]; - unsigned int dw_SetRegister; - unsigned int dw_ControlRegister; - unsigned int dw_StatusRegister; - } s_PulseEncoderModuleInfo; - - /* Tor conter infos */ - struct { - struct { - unsigned char b_TorCounterInit; - unsigned char b_TimingUnit; - unsigned char b_InterruptEnable; - double d_TimingInterval; - unsigned int ul_RealTimingInterval; - } s_TorCounterInfo[2]; - unsigned char b_PCIInputClock; - } s_TorCounterModuleInfo; - - /* PWM infos */ - struct { - struct { - unsigned char b_PWMInit; - unsigned char b_TimingUnit; - unsigned char b_InterruptEnable; - double d_LowTiming; - double d_HighTiming; - unsigned int ul_RealLowTiming; - unsigned int ul_RealHighTiming; - } s_PWMInfo[2]; - unsigned char b_ClockSelection; - } s_PWMModuleInfo; - - /* CDA infos */ - struct { - unsigned char b_CDAEnable; - unsigned char b_FctSelection; - } s_CDAModuleInfo; -}; - -struct addi_private { - /* Pointer to the current process */ - struct task_struct *tsk_Current; - - struct { - unsigned int ui_Address; - unsigned char b_BoardVersion; - unsigned int dw_MolduleConfiguration[4]; - } s_BoardInfos; - - struct { - unsigned int ul_InterruptOccur; - unsigned int ui_Read; - unsigned int ui_Write; - struct { - unsigned char b_OldModuleMask; - unsigned int ul_OldInterruptMask; - unsigned int ul_OldCounterLatchValue; - } s_FIFOInterruptParameters[APCI1710_SAVE_INTERRUPT]; - } s_InterruptParameters; - - union str_ModuleInfo s_ModuleInfo[4]; -}; - -static void fpu_begin(void) -{ - kernel_fpu_begin(); -} - -static void fpu_end(void) -{ - kernel_fpu_end(); -} - -#include "addi-data/hwdrv_APCI1710.c" - -static irqreturn_t v_ADDI_Interrupt(int irq, void *d) -{ - v_APCI1710_Interrupt(irq, d); - return IRQ_RETVAL(1); -} - -static int apci1710_auto_attach(struct comedi_device *dev, - unsigned long context_unused) -{ - struct pci_dev *pcidev = comedi_to_pci_dev(dev); - struct addi_private *devpriv; - int ret; - - devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); - if (!devpriv) - return -ENOMEM; - - ret = comedi_pci_enable(dev); - if (ret) - return ret; - devpriv->s_BoardInfos.ui_Address = pci_resource_start(pcidev, 2); - - if (pcidev->irq > 0) { - ret = request_irq(pcidev->irq, v_ADDI_Interrupt, IRQF_SHARED, - dev->board_name, dev); - if (ret == 0) - dev->irq = pcidev->irq; - } - - i_ADDI_AttachPCI1710(dev); - - i_APCI1710_Reset(dev); - return 0; -} - -static void apci1710_detach(struct comedi_device *dev) -{ - if (dev->iobase) - i_APCI1710_Reset(dev); - if (dev->irq) - free_irq(dev->irq, dev); - comedi_pci_disable(dev); -} - -static struct comedi_driver apci1710_driver = { - .driver_name = "addi_apci_1710", - .module = THIS_MODULE, - .auto_attach = apci1710_auto_attach, - .detach = apci1710_detach, -}; - -static int apci1710_pci_probe(struct pci_dev *dev, - const struct pci_device_id *id) -{ - return comedi_pci_auto_config(dev, &apci1710_driver, id->driver_data); -} - -static DEFINE_PCI_DEVICE_TABLE(apci1710_pci_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_AMCC, APCI1710_BOARD_DEVICE_ID) }, - { 0 } -}; -MODULE_DEVICE_TABLE(pci, apci1710_pci_table); - -static struct pci_driver apci1710_pci_driver = { - .name = "addi_apci_1710", - .id_table = apci1710_pci_table, - .probe = apci1710_pci_probe, - .remove = comedi_pci_auto_unconfig, -}; -module_comedi_pci_driver(apci1710_driver, apci1710_pci_driver); - -MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); -MODULE_LICENSE("GPL"); From 4f2cfd6778969c02dbeb6f6856ff2065d305baf7 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 11:14:43 -0700 Subject: [PATCH 0741/3400] staging: comedi: addi_common.h: cleanup after removal of addi_apci_1710 Now that the addi_apci_1710 driver has been removed, get rid of all the unnecessary stuff in addi_common.h. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- .../comedi/drivers/addi-data/addi_common.h | 169 ------------------ 1 file changed, 169 deletions(-) diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h index f1be5ade9962..dfd1e666cc18 100644 --- a/drivers/staging/comedi/drivers/addi-data/addi_common.h +++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h @@ -113,150 +113,6 @@ struct addi_board { struct comedi_insn *, unsigned int *); }; -/* MODULE INFO STRUCTURE */ - -union str_ModuleInfo { - /* Incremental counter infos */ - struct { - union { - struct { - unsigned char b_ModeRegister1; - unsigned char b_ModeRegister2; - unsigned char b_ModeRegister3; - unsigned char b_ModeRegister4; - } s_ByteModeRegister; - unsigned int dw_ModeRegister1_2_3_4; - } s_ModeRegister; - - struct { - unsigned int b_IndexInit:1; - unsigned int b_CounterInit:1; - unsigned int b_ReferenceInit:1; - unsigned int b_IndexInterruptOccur:1; - unsigned int b_CompareLogicInit:1; - unsigned int b_FrequencyMeasurementInit:1; - unsigned int b_FrequencyMeasurementEnable:1; - } s_InitFlag; - - } s_SiemensCounterInfo; - - /* SSI infos */ - struct { - unsigned char b_SSIProfile; - unsigned char b_PositionTurnLength; - unsigned char b_TurnCptLength; - unsigned char b_SSIInit; - } s_SSICounterInfo; - - /* TTL I/O infos */ - struct { - unsigned char b_TTLInit; - unsigned char b_PortConfiguration[4]; - } s_TTLIOInfo; - - /* Digital I/O infos */ - struct { - unsigned char b_DigitalInit; - unsigned char b_ChannelAMode; - unsigned char b_ChannelBMode; - unsigned char b_OutputMemoryEnabled; - unsigned int dw_OutputMemory; - } s_DigitalIOInfo; - - /*********************/ - /* 82X54 timer infos */ - /*********************/ - - struct { - struct { - unsigned char b_82X54Init; - unsigned char b_InputClockSelection; - unsigned char b_InputClockLevel; - unsigned char b_OutputLevel; - unsigned char b_HardwareGateLevel; - unsigned int dw_ConfigurationWord; - } s_82X54TimerInfo[3]; - unsigned char b_InterruptMask; - } s_82X54ModuleInfo; - - /*********************/ - /* Chronometer infos */ - /*********************/ - - struct { - unsigned char b_ChronoInit; - unsigned char b_InterruptMask; - unsigned char b_PCIInputClock; - unsigned char b_TimingUnit; - unsigned char b_CycleMode; - double d_TimingInterval; - unsigned int dw_ConfigReg; - } s_ChronoModuleInfo; - - /***********************/ - /* Pulse encoder infos */ - /***********************/ - - struct { - struct { - unsigned char b_PulseEncoderInit; - } s_PulseEncoderInfo[4]; - unsigned int dw_SetRegister; - unsigned int dw_ControlRegister; - unsigned int dw_StatusRegister; - } s_PulseEncoderModuleInfo; - - /* Tor conter infos */ - struct { - struct { - unsigned char b_TorCounterInit; - unsigned char b_TimingUnit; - unsigned char b_InterruptEnable; - double d_TimingInterval; - unsigned int ul_RealTimingInterval; - } s_TorCounterInfo[2]; - unsigned char b_PCIInputClock; - } s_TorCounterModuleInfo; - - /* PWM infos */ - struct { - struct { - unsigned char b_PWMInit; - unsigned char b_TimingUnit; - unsigned char b_InterruptEnable; - double d_LowTiming; - double d_HighTiming; - unsigned int ul_RealLowTiming; - unsigned int ul_RealHighTiming; - } s_PWMInfo[2]; - unsigned char b_ClockSelection; - } s_PWMModuleInfo; - - /* ETM infos */ - struct { - struct { - unsigned char b_ETMEnable; - unsigned char b_ETMInterrupt; - } s_ETMInfo[2]; - unsigned char b_ETMInit; - unsigned char b_TimingUnit; - unsigned char b_ClockSelection; - double d_TimingInterval; - unsigned int ul_Timing; - } s_ETMModuleInfo; - - /* CDA infos */ - struct { - unsigned char b_CDAEnable; - unsigned char b_CDAInterrupt; - unsigned char b_CDAInit; - unsigned char b_FctSelection; - unsigned char b_CDAReadFIFOOverflow; - } s_CDAModuleInfo; - -}; - -/* Private structure for the addi_apci3120 driver */ struct addi_private { int iobase; int i_IobaseAmcc; /* base+size for AMCC chip */ @@ -299,31 +155,6 @@ struct addi_private { /* Pointer to the current process */ struct task_struct *tsk_Current; - /* Hardware board infos for 1710 */ - struct { - unsigned int ui_Address; /* Board address */ - unsigned int ui_FlashAddress; - unsigned char b_InterruptNbr; /* Board interrupt number */ - unsigned char b_SlotNumber; /* PCI slot number */ - unsigned char b_BoardVersion; - unsigned int dw_MolduleConfiguration[4]; /* Module config */ - } s_BoardInfos; - - /* Interrupt infos */ - struct { - unsigned int ul_InterruptOccur; /* 0 : No interrupt occur */ - /* > 0 : Interrupt occur */ - unsigned int ui_Read; /* Read FIFO */ - unsigned int ui_Write; /* Write FIFO */ - struct { - unsigned char b_OldModuleMask; - unsigned int ul_OldInterruptMask; /* Interrupt mask */ - unsigned int ul_OldCounterLatchValue; /* Interrupt counter value */ - } s_FIFOInterruptParameters[APCI1710_SAVE_INTERRUPT]; - } s_InterruptParameters; - - union str_ModuleInfo s_ModuleInfo[4]; - /* Parameters read from EEPROM overriding static board info */ struct { int i_NbrAiChannel; /* num of A/D chans */ From 2b00f54b248144acc393740e4c4679b6aa531193 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 12:08:58 -0700 Subject: [PATCH 0742/3400] staging: comedi: ii_pci20kc: use comedi_alloc_spriv() For aesthetic reasons, use the helper function to allocate the subdevice private data instead of hanging it on the device private data. The core will free the memory during the detach. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ii_pci20kc.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c index 9c199a194d2b..45d76ed66498 100644 --- a/drivers/staging/comedi/drivers/ii_pci20kc.c +++ b/drivers/staging/comedi/drivers/ii_pci20kc.c @@ -149,9 +149,7 @@ union pci20xxx_subdev_private { }; struct pci20xxx_private { - void __iomem *ioaddr; - union pci20xxx_subdev_private subdev_private[PCI20000_MODULES]; }; #define CHAN (CR_CHAN(it->chanlist[0])) @@ -222,9 +220,10 @@ static int pci20xxx_attach(struct comedi_device *dev, for (i = 0; i < PCI20000_MODULES; i++) { s = &dev->subdevices[i]; + sdp = comedi_alloc_spriv(s, sizeof(*sdp)); + if (!sdp) + return -ENOMEM; id = readb(devpriv->ioaddr + (i + 1) * PCI20000_OFFSET); - s->private = devpriv->subdev_private + i; - sdp = s->private; switch (id) { case PCI20006_ID: sdp->pci20006.iobase = From 0f8409dc057935900a53d4781bcbb77149348267 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 12:09:25 -0700 Subject: [PATCH 0743/3400] staging: comedi: ii_pci20kc: remove forward declarations 1 Move the pci20xxx_attach() and pci20xxx_detach() functions to remove the need for some of the forward declarations. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ii_pci20kc.c | 184 ++++++++------------ 1 file changed, 75 insertions(+), 109 deletions(-) diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c index 45d76ed66498..bc95cd66dc5f 100644 --- a/drivers/staging/comedi/drivers/ii_pci20kc.c +++ b/drivers/staging/comedi/drivers/ii_pci20kc.c @@ -154,115 +154,6 @@ struct pci20xxx_private { #define CHAN (CR_CHAN(it->chanlist[0])) -static int pci20006_init(struct comedi_device *dev, struct comedi_subdevice *s, - int opt0, int opt1); -static int pci20341_init(struct comedi_device *dev, struct comedi_subdevice *s, - int opt0, int opt1); -static int pci20xxx_dio_init(struct comedi_device *dev, - struct comedi_subdevice *s); - -/* - options[0] Board base address - options[1] IRQ - options[2] first option for module 1 - options[3] second option for module 1 - options[4] first option for module 2 - options[5] second option for module 2 - options[6] first option for module 3 - options[7] second option for module 3 - - options for PCI-20341M: - first Analog input gain configuration - 0 == 1 - 1 == 10 - 2 == 100 - 3 == 200 - - options for PCI-20006M: - first Analog output channel 0 range configuration - 0 == bipolar 10 (-10V -- +10V) - 1 == unipolar 10V (0V -- +10V) - 2 == bipolar 5V (-5V -- +5V) - second Analog output channel 1 range configuration - 0 == bipolar 10 (-10V -- +10V) - 1 == unipolar 10V (0V -- +10V) - 2 == bipolar 5V (-5V -- +5V) -*/ -static int pci20xxx_attach(struct comedi_device *dev, - struct comedi_devconfig *it) -{ - struct pci20xxx_private *devpriv; - unsigned char i; - int ret; - int id; - struct comedi_subdevice *s; - union pci20xxx_subdev_private *sdp; - - ret = comedi_alloc_subdevices(dev, 1 + PCI20000_MODULES); - if (ret) - return ret; - - devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); - if (!devpriv) - return -ENOMEM; - - devpriv->ioaddr = (void __iomem *)(unsigned long)it->options[0]; - - /* Check PCI-20001 C-2A Carrier Board ID */ - if ((readb(devpriv->ioaddr) & PCI20000_ID) != PCI20000_ID) { - dev_warn(dev->class_dev, - "PCI-20001 C-2A Carrier Board at base=0x%p not found !\n", - devpriv->ioaddr); - return -EINVAL; - } - dev_info(dev->class_dev, "PCI-20001 C-2A at base=0x%p\n", - devpriv->ioaddr); - - for (i = 0; i < PCI20000_MODULES; i++) { - s = &dev->subdevices[i]; - sdp = comedi_alloc_spriv(s, sizeof(*sdp)); - if (!sdp) - return -ENOMEM; - id = readb(devpriv->ioaddr + (i + 1) * PCI20000_OFFSET); - switch (id) { - case PCI20006_ID: - sdp->pci20006.iobase = - devpriv->ioaddr + (i + 1) * PCI20000_OFFSET; - pci20006_init(dev, s, it->options[2 * i + 2], - it->options[2 * i + 3]); - dev_info(dev->class_dev, - "PCI-20006 module in slot %d\n", i + 1); - break; - case PCI20341_ID: - sdp->pci20341.iobase = - devpriv->ioaddr + (i + 1) * PCI20000_OFFSET; - pci20341_init(dev, s, it->options[2 * i + 2], - it->options[2 * i + 3]); - dev_info(dev->class_dev, - "PCI-20341 module in slot %d\n", i + 1); - break; - default: - dev_warn(dev->class_dev, - "unknown module code 0x%02x in slot %d: module disabled\n", - id, i); /* XXX this looks like a bug! i + 1 ?? */ - /* fall through */ - case PCI20xxx_EMPTY_ID: - s->type = COMEDI_SUBD_UNUSED; - break; - } - } - - /* initialize struct pci20xxx_private */ - pci20xxx_dio_init(dev, &dev->subdevices[PCI20000_MODULES]); - - return 1; -} - -static void pci20xxx_detach(struct comedi_device *dev) -{ - /* Nothing to cleanup */ -} - /* pci20006m */ static int pci20006_insn_read(struct comedi_device *dev, @@ -649,6 +540,81 @@ static unsigned int pci20xxx_di(struct comedi_device *dev, } #endif +static int pci20xxx_attach(struct comedi_device *dev, + struct comedi_devconfig *it) +{ + struct pci20xxx_private *devpriv; + unsigned char i; + int ret; + int id; + struct comedi_subdevice *s; + union pci20xxx_subdev_private *sdp; + + ret = comedi_alloc_subdevices(dev, 1 + PCI20000_MODULES); + if (ret) + return ret; + + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); + if (!devpriv) + return -ENOMEM; + + devpriv->ioaddr = (void __iomem *)(unsigned long)it->options[0]; + + /* Check PCI-20001 C-2A Carrier Board ID */ + if ((readb(devpriv->ioaddr) & PCI20000_ID) != PCI20000_ID) { + dev_warn(dev->class_dev, + "PCI-20001 C-2A Carrier Board at base=0x%p not found !\n", + devpriv->ioaddr); + return -EINVAL; + } + dev_info(dev->class_dev, "PCI-20001 C-2A at base=0x%p\n", + devpriv->ioaddr); + + for (i = 0; i < PCI20000_MODULES; i++) { + s = &dev->subdevices[i]; + sdp = comedi_alloc_spriv(s, sizeof(*sdp)); + if (!sdp) + return -ENOMEM; + id = readb(devpriv->ioaddr + (i + 1) * PCI20000_OFFSET); + switch (id) { + case PCI20006_ID: + sdp->pci20006.iobase = + devpriv->ioaddr + (i + 1) * PCI20000_OFFSET; + pci20006_init(dev, s, it->options[2 * i + 2], + it->options[2 * i + 3]); + dev_info(dev->class_dev, + "PCI-20006 module in slot %d\n", i + 1); + break; + case PCI20341_ID: + sdp->pci20341.iobase = + devpriv->ioaddr + (i + 1) * PCI20000_OFFSET; + pci20341_init(dev, s, it->options[2 * i + 2], + it->options[2 * i + 3]); + dev_info(dev->class_dev, + "PCI-20341 module in slot %d\n", i + 1); + break; + default: + dev_warn(dev->class_dev, + "unknown module code 0x%02x in slot %d: module disabled\n", + id, i); /* XXX this looks like a bug! i + 1 ?? */ + /* fall through */ + case PCI20xxx_EMPTY_ID: + s->type = COMEDI_SUBD_UNUSED; + break; + } + } + + /* initialize struct pci20xxx_private */ + pci20xxx_dio_init(dev, &dev->subdevices[PCI20000_MODULES]); + + return 1; +} + +static void pci20xxx_detach(struct comedi_device *dev) +{ + /* Nothing to cleanup */ +} + static struct comedi_driver pci20xxx_driver = { .driver_name = "ii_pci20kc", .module = THIS_MODULE, From 63d6e8ff0d25256d57453959c4d192b950a417ce Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 12:09:53 -0700 Subject: [PATCH 0744/3400] staging: comedi: ii_pci20kc: remove forward declarations 2 Move the pci20xxx_dio_*() functions to remove the need for some of the forward declarations. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ii_pci20kc.c | 206 +++++++++----------- 1 file changed, 96 insertions(+), 110 deletions(-) diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c index bc95cd66dc5f..eab48e31fb82 100644 --- a/drivers/staging/comedi/drivers/ii_pci20kc.c +++ b/drivers/staging/comedi/drivers/ii_pci20kc.c @@ -361,37 +361,93 @@ static int pci20341_insn_read(struct comedi_device *dev, return i; } -/* native DIO */ +#if 0 +static void pci20xxx_do(struct comedi_device *dev, struct comedi_subdevice *s) +{ + struct pci20xxx_private *devpriv = dev->private; + + /* XXX if the channel is configured for input, does this + do bad things? */ + /* XXX it would be a good idea to only update the registers + that _need_ to be updated. This requires changes to + comedi, however. */ + writeb((s->state >> 0) & 0xff, devpriv->ioaddr + PCI20000_DIO_0); + writeb((s->state >> 8) & 0xff, devpriv->ioaddr + PCI20000_DIO_1); + writeb((s->state >> 16) & 0xff, devpriv->ioaddr + PCI20000_DIO_2); + writeb((s->state >> 24) & 0xff, devpriv->ioaddr + PCI20000_DIO_3); +} + +static unsigned int pci20xxx_di(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + struct pci20xxx_private *devpriv = dev->private; + unsigned int bits; + + /* XXX same note as above */ + bits = readb(devpriv->ioaddr + PCI20000_DIO_0); + bits |= readb(devpriv->ioaddr + PCI20000_DIO_1) << 8; + bits |= readb(devpriv->ioaddr + PCI20000_DIO_2) << 16; + bits |= readb(devpriv->ioaddr + PCI20000_DIO_3) << 24; + + return bits; +} +#endif static void pci20xxx_dio_config(struct comedi_device *dev, - struct comedi_subdevice *s); -static int pci20xxx_dio_insn_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int pci20xxx_dio_insn_config(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data); - -/* initialize struct pci20xxx_private */ -static int pci20xxx_dio_init(struct comedi_device *dev, - struct comedi_subdevice *s) + struct comedi_subdevice *s) { + struct pci20xxx_private *devpriv = dev->private; + unsigned char control_01; + unsigned char control_23; + unsigned char buffer; - s->type = COMEDI_SUBD_DIO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = 32; - s->insn_bits = pci20xxx_dio_insn_bits; - s->insn_config = pci20xxx_dio_insn_config; - s->maxdata = 1; - s->len_chanlist = 32; - s->range_table = &range_digital; - s->io_bits = 0; + control_01 = readb(devpriv->ioaddr + PCI20000_DIO_CONTROL_01); + control_23 = readb(devpriv->ioaddr + PCI20000_DIO_CONTROL_23); + buffer = readb(devpriv->ioaddr + PCI20000_DIO_BUFFER); - /* digital I/O lines default to input on board reset. */ - pci20xxx_dio_config(dev, s); - - return 0; + if (s->io_bits & 0x000000ff) { + /* output port 0 */ + control_01 &= PCI20000_DIO_EOC; + buffer = (buffer & (~(DIO_BE << DIO_PS_0))) | (DIO_BO << + DIO_PS_0); + } else { + /* input port 0 */ + control_01 = (control_01 & DIO_CAND) | PCI20000_DIO_EIC; + buffer = (buffer & (~(DIO_BI << DIO_PS_0))); + } + if (s->io_bits & 0x0000ff00) { + /* output port 1 */ + control_01 &= PCI20000_DIO_OOC; + buffer = (buffer & (~(DIO_BE << DIO_PS_1))) | (DIO_BO << + DIO_PS_1); + } else { + /* input port 1 */ + control_01 = (control_01 & DIO_CAND) | PCI20000_DIO_OIC; + buffer = (buffer & (~(DIO_BI << DIO_PS_1))); + } + if (s->io_bits & 0x00ff0000) { + /* output port 2 */ + control_23 &= PCI20000_DIO_EOC; + buffer = (buffer & (~(DIO_BE << DIO_PS_2))) | (DIO_BO << + DIO_PS_2); + } else { + /* input port 2 */ + control_23 = (control_23 & DIO_CAND) | PCI20000_DIO_EIC; + buffer = (buffer & (~(DIO_BI << DIO_PS_2))); + } + if (s->io_bits & 0xff000000) { + /* output port 3 */ + control_23 &= PCI20000_DIO_OOC; + buffer = (buffer & (~(DIO_BE << DIO_PS_3))) | (DIO_BO << + DIO_PS_3); + } else { + /* input port 3 */ + control_23 = (control_23 & DIO_CAND) | PCI20000_DIO_OIC; + buffer = (buffer & (~(DIO_BI << DIO_PS_3))); + } + writeb(control_01, devpriv->ioaddr + PCI20000_DIO_CONTROL_01); + writeb(control_23, devpriv->ioaddr + PCI20000_DIO_CONTROL_23); + writeb(buffer, devpriv->ioaddr + PCI20000_DIO_BUFFER); } static int pci20xxx_dio_insn_config(struct comedi_device *dev, @@ -451,95 +507,25 @@ static int pci20xxx_dio_insn_bits(struct comedi_device *dev, return insn->n; } -static void pci20xxx_dio_config(struct comedi_device *dev, - struct comedi_subdevice *s) +static int pci20xxx_dio_init(struct comedi_device *dev, + struct comedi_subdevice *s) { - struct pci20xxx_private *devpriv = dev->private; - unsigned char control_01; - unsigned char control_23; - unsigned char buffer; + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 32; + s->insn_bits = pci20xxx_dio_insn_bits; + s->insn_config = pci20xxx_dio_insn_config; + s->maxdata = 1; + s->len_chanlist = 32; + s->range_table = &range_digital; + s->io_bits = 0; - control_01 = readb(devpriv->ioaddr + PCI20000_DIO_CONTROL_01); - control_23 = readb(devpriv->ioaddr + PCI20000_DIO_CONTROL_23); - buffer = readb(devpriv->ioaddr + PCI20000_DIO_BUFFER); + /* digital I/O lines default to input on board reset. */ + pci20xxx_dio_config(dev, s); - if (s->io_bits & 0x000000ff) { - /* output port 0 */ - control_01 &= PCI20000_DIO_EOC; - buffer = (buffer & (~(DIO_BE << DIO_PS_0))) | (DIO_BO << - DIO_PS_0); - } else { - /* input port 0 */ - control_01 = (control_01 & DIO_CAND) | PCI20000_DIO_EIC; - buffer = (buffer & (~(DIO_BI << DIO_PS_0))); - } - if (s->io_bits & 0x0000ff00) { - /* output port 1 */ - control_01 &= PCI20000_DIO_OOC; - buffer = (buffer & (~(DIO_BE << DIO_PS_1))) | (DIO_BO << - DIO_PS_1); - } else { - /* input port 1 */ - control_01 = (control_01 & DIO_CAND) | PCI20000_DIO_OIC; - buffer = (buffer & (~(DIO_BI << DIO_PS_1))); - } - if (s->io_bits & 0x00ff0000) { - /* output port 2 */ - control_23 &= PCI20000_DIO_EOC; - buffer = (buffer & (~(DIO_BE << DIO_PS_2))) | (DIO_BO << - DIO_PS_2); - } else { - /* input port 2 */ - control_23 = (control_23 & DIO_CAND) | PCI20000_DIO_EIC; - buffer = (buffer & (~(DIO_BI << DIO_PS_2))); - } - if (s->io_bits & 0xff000000) { - /* output port 3 */ - control_23 &= PCI20000_DIO_OOC; - buffer = (buffer & (~(DIO_BE << DIO_PS_3))) | (DIO_BO << - DIO_PS_3); - } else { - /* input port 3 */ - control_23 = (control_23 & DIO_CAND) | PCI20000_DIO_OIC; - buffer = (buffer & (~(DIO_BI << DIO_PS_3))); - } - writeb(control_01, devpriv->ioaddr + PCI20000_DIO_CONTROL_01); - writeb(control_23, devpriv->ioaddr + PCI20000_DIO_CONTROL_23); - writeb(buffer, devpriv->ioaddr + PCI20000_DIO_BUFFER); + return 0; } -#if 0 -static void pci20xxx_do(struct comedi_device *dev, struct comedi_subdevice *s) -{ - struct pci20xxx_private *devpriv = dev->private; - - /* XXX if the channel is configured for input, does this - do bad things? */ - /* XXX it would be a good idea to only update the registers - that _need_ to be updated. This requires changes to - comedi, however. */ - writeb((s->state >> 0) & 0xff, devpriv->ioaddr + PCI20000_DIO_0); - writeb((s->state >> 8) & 0xff, devpriv->ioaddr + PCI20000_DIO_1); - writeb((s->state >> 16) & 0xff, devpriv->ioaddr + PCI20000_DIO_2); - writeb((s->state >> 24) & 0xff, devpriv->ioaddr + PCI20000_DIO_3); -} - -static unsigned int pci20xxx_di(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - struct pci20xxx_private *devpriv = dev->private; - unsigned int bits; - - /* XXX same note as above */ - bits = readb(devpriv->ioaddr + PCI20000_DIO_0); - bits |= readb(devpriv->ioaddr + PCI20000_DIO_1) << 8; - bits |= readb(devpriv->ioaddr + PCI20000_DIO_2) << 16; - bits |= readb(devpriv->ioaddr + PCI20000_DIO_3) << 24; - - return bits; -} -#endif - static int pci20xxx_attach(struct comedi_device *dev, struct comedi_devconfig *it) { From 842525c6c1efa0bfefb7fb96838ef6ec588ce95e Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 12:10:18 -0700 Subject: [PATCH 0745/3400] staging: comedi: ii_pci20kc: remove forward declarations 3 Move a couple functions to remove the need for the last forward declarations. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ii_pci20kc.c | 135 +++++++++----------- 1 file changed, 62 insertions(+), 73 deletions(-) diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c index eab48e31fb82..ad4dc5741b27 100644 --- a/drivers/staging/comedi/drivers/ii_pci20kc.c +++ b/drivers/staging/comedi/drivers/ii_pci20kc.c @@ -156,44 +156,12 @@ struct pci20xxx_private { /* pci20006m */ -static int pci20006_insn_read(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); -static int pci20006_insn_write(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); - static const struct comedi_lrange *pci20006_range_list[] = { &range_bipolar10, &range_unipolar10, &range_bipolar5, }; -static int pci20006_init(struct comedi_device *dev, struct comedi_subdevice *s, - int opt0, int opt1) -{ - union pci20xxx_subdev_private *sdp = s->private; - - if (opt0 < 0 || opt0 > 2) - opt0 = 0; - if (opt1 < 0 || opt1 > 2) - opt1 = 0; - - sdp->pci20006.ao_range_list[0] = pci20006_range_list[opt0]; - sdp->pci20006.ao_range_list[1] = pci20006_range_list[opt1]; - - /* ao subdevice */ - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = 2; - s->len_chanlist = 2; - s->insn_read = pci20006_insn_read; - s->insn_write = pci20006_insn_write; - s->maxdata = 0xffff; - s->range_table_list = sdp->pci20006.ao_range_list; - return 0; -} - static int pci20006_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -238,11 +206,32 @@ static int pci20006_insn_write(struct comedi_device *dev, return 1; } -/* PCI20341M */ +static int pci20006_init(struct comedi_device *dev, struct comedi_subdevice *s, + int opt0, int opt1) +{ + union pci20xxx_subdev_private *sdp = s->private; -static int pci20341_insn_read(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data); + if (opt0 < 0 || opt0 > 2) + opt0 = 0; + if (opt1 < 0 || opt1 > 2) + opt1 = 0; + + sdp->pci20006.ao_range_list[0] = pci20006_range_list[opt0]; + sdp->pci20006.ao_range_list[1] = pci20006_range_list[opt1]; + + /* ao subdevice */ + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 2; + s->len_chanlist = 2; + s->insn_read = pci20006_insn_read; + s->insn_write = pci20006_insn_write; + s->maxdata = 0xffff; + s->range_table_list = sdp->pci20006.ao_range_list; + return 0; +} + +/* PCI20341M */ static const int pci20341_timebase[] = { 0x00, 0x00, 0x00, 0x04 }; static const int pci20341_settling_time[] = { 0x58, 0x58, 0x93, 0x99 }; @@ -269,43 +258,6 @@ static const struct comedi_lrange *const pci20341_ranges[] = { &range_bipolar0_025, }; -static int pci20341_init(struct comedi_device *dev, struct comedi_subdevice *s, - int opt0, int opt1) -{ - union pci20xxx_subdev_private *sdp = s->private; - int option; - - /* options handling */ - if (opt0 < 0 || opt0 > 3) - opt0 = 0; - sdp->pci20341.timebase = pci20341_timebase[opt0]; - sdp->pci20341.settling_time = pci20341_settling_time[opt0]; - - /* ai subdevice */ - s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE; - s->n_chan = PCI20341_CHAN_NR; - s->len_chanlist = PCI20341_SCANLIST; - s->insn_read = pci20341_insn_read; - s->maxdata = 0xffff; - s->range_table = pci20341_ranges[opt0]; - - /* depends on gain, trigger, repetition mode */ - option = sdp->pci20341.timebase | PCI20341_REPMODE; - - /* initialize Module */ - writeb(PCI20341_INIT, sdp->iobase + PCI20341_CONFIG_REG); - /* set Pacer */ - writeb(PCI20341_PACER, sdp->iobase + PCI20341_MOD_STATUS); - /* option register */ - writeb(option, sdp->iobase + PCI20341_OPT_REG); - /* settling time counter */ - writeb(sdp->pci20341.settling_time, - sdp->iobase + PCI20341_SET_TIME_REG); - /* trigger not implemented */ - return 0; -} - static int pci20341_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -361,6 +313,43 @@ static int pci20341_insn_read(struct comedi_device *dev, return i; } +static int pci20341_init(struct comedi_device *dev, struct comedi_subdevice *s, + int opt0, int opt1) +{ + union pci20xxx_subdev_private *sdp = s->private; + int option; + + /* options handling */ + if (opt0 < 0 || opt0 > 3) + opt0 = 0; + sdp->pci20341.timebase = pci20341_timebase[opt0]; + sdp->pci20341.settling_time = pci20341_settling_time[opt0]; + + /* ai subdevice */ + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE; + s->n_chan = PCI20341_CHAN_NR; + s->len_chanlist = PCI20341_SCANLIST; + s->insn_read = pci20341_insn_read; + s->maxdata = 0xffff; + s->range_table = pci20341_ranges[opt0]; + + /* depends on gain, trigger, repetition mode */ + option = sdp->pci20341.timebase | PCI20341_REPMODE; + + /* initialize Module */ + writeb(PCI20341_INIT, sdp->iobase + PCI20341_CONFIG_REG); + /* set Pacer */ + writeb(PCI20341_PACER, sdp->iobase + PCI20341_MOD_STATUS); + /* option register */ + writeb(option, sdp->iobase + PCI20341_OPT_REG); + /* settling time counter */ + writeb(sdp->pci20341.settling_time, + sdp->iobase + PCI20341_SET_TIME_REG); + /* trigger not implemented */ + return 0; +} + #if 0 static void pci20xxx_do(struct comedi_device *dev, struct comedi_subdevice *s) { From 3366244718f5c95b25cc96318cf448dafa1dcd00 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 12:10:41 -0700 Subject: [PATCH 0746/3400] staging: comedi: ii_pci20kc: move comedi_lrange tables For aesthetic reasons, move the static const data to the head of the file. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ii_pci20kc.c | 65 +++++++++++---------- 1 file changed, 34 insertions(+), 31 deletions(-) diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c index ad4dc5741b27..273034a71464 100644 --- a/drivers/staging/comedi/drivers/ii_pci20kc.c +++ b/drivers/staging/comedi/drivers/ii_pci20kc.c @@ -132,6 +132,40 @@ options for PCI-20341M: #define PCI20341_MUX 0x04 /* Enable on-board MUX */ #define PCI20341_SCANLIST 0x80 /* Channel/Gain Scan List */ +static const struct comedi_lrange range_bipolar0_5 = { + 1, { + BIP_RANGE(0.5) + } +}; + +static const struct comedi_lrange range_bipolar0_05 = { + 1, { + BIP_RANGE(0.05) + } +}; + +static const struct comedi_lrange range_bipolar0_025 = { + 1, { + BIP_RANGE(0.025) + } +}; + +static const struct comedi_lrange *pci20006_range_list[] = { + &range_bipolar10, + &range_unipolar10, + &range_bipolar5, +}; + +static const struct comedi_lrange *const pci20341_ranges[] = { + &range_bipolar5, + &range_bipolar0_5, + &range_bipolar0_05, + &range_bipolar0_025, +}; + +static const int pci20341_timebase[] = { 0x00, 0x00, 0x00, 0x04 }; +static const int pci20341_settling_time[] = { 0x58, 0x58, 0x93, 0x99 }; + union pci20xxx_subdev_private { void __iomem *iobase; struct { @@ -156,12 +190,6 @@ struct pci20xxx_private { /* pci20006m */ -static const struct comedi_lrange *pci20006_range_list[] = { - &range_bipolar10, - &range_unipolar10, - &range_bipolar5, -}; - static int pci20006_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -233,31 +261,6 @@ static int pci20006_init(struct comedi_device *dev, struct comedi_subdevice *s, /* PCI20341M */ -static const int pci20341_timebase[] = { 0x00, 0x00, 0x00, 0x04 }; -static const int pci20341_settling_time[] = { 0x58, 0x58, 0x93, 0x99 }; - -static const struct comedi_lrange range_bipolar0_5 = { - 1, - {BIP_RANGE(0.5)} -}; - -static const struct comedi_lrange range_bipolar0_05 = { - 1, - {BIP_RANGE(0.05)} -}; - -static const struct comedi_lrange range_bipolar0_025 = { - 1, - {BIP_RANGE(0.025)} -}; - -static const struct comedi_lrange *const pci20341_ranges[] = { - &range_bipolar5, - &range_bipolar0_5, - &range_bipolar0_05, - &range_bipolar0_025, -}; - static int pci20341_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) From 6d305f89529f1c4400e3d04fedfb8411041f1387 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 12:11:00 -0700 Subject: [PATCH 0747/3400] staging: comedi: ii_pci20kc: remove CHAN macro This macro is not used, and it looks to much like the comedi CR_CHAN macro. Just remove it. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ii_pci20kc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c index 273034a71464..056afdf1165a 100644 --- a/drivers/staging/comedi/drivers/ii_pci20kc.c +++ b/drivers/staging/comedi/drivers/ii_pci20kc.c @@ -186,8 +186,6 @@ struct pci20xxx_private { void __iomem *ioaddr; }; -#define CHAN (CR_CHAN(it->chanlist[0])) - /* pci20006m */ static int pci20006_insn_read(struct comedi_device *dev, From 9abeb196a740bd52401a24108df27e20576da036 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 12:11:25 -0700 Subject: [PATCH 0748/3400] staging: comedi: ii_pci20kc.c: cleanup the dio subdevice For asethetics, redefine the register map for the carrier board. The 'PCI*' names lead one to think this is a PCI board not a legacy ISA board. Remove the #if 0'd out pci20xxx_{do,di}() functions. They are not needed. Rename, and fix, the pci20xxx_dio_config() function. The control and direction registers are not readable. Use the new register map defines instead of the crazy bit shifts. Rename, and fix, the pci20xxx_dio_insn_config() function. This function should treat data[0] as the 'instruction' to handle not just use it to determine if the port is an input or output. Rename, and tix, the pci20xxx_dio_insn_bits() function. The 'state' only needs to be updated if the 'mask' indicates. For aesthetics, abosrb the pci20xxx_dio_init() into the (*attach) function. Fix the carrier board id detect in the (*attach). There are two carrier board types, one with 32 dio channels and one without. Use this info when setting up the dio subdevice. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ii_pci20kc.c | 359 ++++++++++---------- 1 file changed, 180 insertions(+), 179 deletions(-) diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c index 056afdf1165a..60a3bb2c3657 100644 --- a/drivers/staging/comedi/drivers/ii_pci20kc.c +++ b/drivers/staging/comedi/drivers/ii_pci20kc.c @@ -80,33 +80,47 @@ options for PCI-20341M: #include #include "../comedidev.h" -#define PCI20000_ID 0x1d +/* + * Register I/O map + */ +#define II20K_ID_REG 0x00 +#define II20K_ID_MOD1_EMPTY (1 << 7) +#define II20K_ID_MOD2_EMPTY (1 << 6) +#define II20K_ID_MOD3_EMPTY (1 << 5) +#define II20K_ID_MASK 0x1f +#define II20K_ID_PCI20001C_1A 0x1b /* no on-board DIO */ +#define II20K_ID_PCI20001C_2A 0x1d /* on-board DIO */ +#define II20K_MOD_STATUS_REG 0x40 +#define II20K_MOD_STATUS_IRQ_MOD1 (1 << 7) +#define II20K_MOD_STATUS_IRQ_MOD2 (1 << 6) +#define II20K_MOD_STATUS_IRQ_MOD3 (1 << 5) +#define II20K_DIO0_REG 0x80 +#define II20K_DIO1_REG 0x81 +#define II20K_DIR_ENA_REG 0x82 +#define II20K_DIR_DIO3_OUT (1 << 7) +#define II20K_DIR_DIO2_OUT (1 << 6) +#define II20K_BUF_DISAB_DIO3 (1 << 5) +#define II20K_BUF_DISAB_DIO2 (1 << 4) +#define II20K_DIR_DIO1_OUT (1 << 3) +#define II20K_DIR_DIO0_OUT (1 << 2) +#define II20K_BUF_DISAB_DIO1 (1 << 1) +#define II20K_BUF_DISAB_DIO0 (1 << 0) +#define II20K_CTRL01_REG 0x83 +#define II20K_CTRL01_SET (1 << 7) +#define II20K_CTRL01_DIO0_IN (1 << 4) +#define II20K_CTRL01_DIO1_IN (1 << 1) +#define II20K_DIO2_REG 0xc0 +#define II20K_DIO3_REG 0xc1 +#define II20K_CTRL23_REG 0xc3 +#define II20K_CTRL23_SET (1 << 7) +#define II20K_CTRL23_DIO2_IN (1 << 4) +#define II20K_CTRL23_DIO3_IN (1 << 1) + #define PCI20341_ID 0x77 #define PCI20006_ID 0xe3 #define PCI20xxx_EMPTY_ID 0xff #define PCI20000_OFFSET 0x100 -#define PCI20000_MODULES 3 - -#define PCI20000_DIO_0 0x80 -#define PCI20000_DIO_1 0x81 -#define PCI20000_DIO_2 0xc0 -#define PCI20000_DIO_3 0xc1 -#define PCI20000_DIO_CONTROL_01 0x83 /* port 0, 1 control */ -#define PCI20000_DIO_CONTROL_23 0xc3 /* port 2, 3 control */ -#define PCI20000_DIO_BUFFER 0x82 /* buffer direction & enable */ -#define PCI20000_DIO_EOC 0xef /* even port, control output */ -#define PCI20000_DIO_OOC 0xfd /* odd port, control output */ -#define PCI20000_DIO_EIC 0x90 /* even port, control input */ -#define PCI20000_DIO_OIC 0x82 /* odd port, control input */ -#define DIO_CAND 0x12 /* and bit 1 & 4 of control */ -#define DIO_BE 0x01 /* buffer: port enable */ -#define DIO_BO 0x04 /* buffer: output */ -#define DIO_BI 0x05 /* buffer: input */ -#define DIO_PS_0 0x00 /* buffer: port shift 0 */ -#define DIO_PS_1 0x01 /* buffer: port shift 1 */ -#define DIO_PS_2 0x04 /* buffer: port shift 2 */ -#define DIO_PS_3 0x05 /* buffer: port shift 3 */ #define PCI20006_LCHAN0 0x0d #define PCI20006_STROBE0 0x0b @@ -351,103 +365,79 @@ static int pci20341_init(struct comedi_device *dev, struct comedi_subdevice *s, return 0; } -#if 0 -static void pci20xxx_do(struct comedi_device *dev, struct comedi_subdevice *s) +static void ii20k_dio_config(struct comedi_device *dev, + struct comedi_subdevice *s) { struct pci20xxx_private *devpriv = dev->private; + unsigned char ctrl01 = 0; + unsigned char ctrl23 = 0; + unsigned char dir_ena = 0; - /* XXX if the channel is configured for input, does this - do bad things? */ - /* XXX it would be a good idea to only update the registers - that _need_ to be updated. This requires changes to - comedi, however. */ - writeb((s->state >> 0) & 0xff, devpriv->ioaddr + PCI20000_DIO_0); - writeb((s->state >> 8) & 0xff, devpriv->ioaddr + PCI20000_DIO_1); - writeb((s->state >> 16) & 0xff, devpriv->ioaddr + PCI20000_DIO_2); - writeb((s->state >> 24) & 0xff, devpriv->ioaddr + PCI20000_DIO_3); + /* port 0 - channels 0-7 */ + if (s->io_bits & 0x000000ff) { + /* output port */ + ctrl01 &= ~II20K_CTRL01_DIO0_IN; + dir_ena &= ~II20K_BUF_DISAB_DIO0; + dir_ena |= II20K_DIR_DIO0_OUT; + } else { + /* input port */ + ctrl01 |= II20K_CTRL01_DIO0_IN; + dir_ena &= ~II20K_DIR_DIO0_OUT; + } + + /* port 1 - channels 8-15 */ + if (s->io_bits & 0x0000ff00) { + /* output port */ + ctrl01 &= ~II20K_CTRL01_DIO1_IN; + dir_ena &= ~II20K_BUF_DISAB_DIO1; + dir_ena |= II20K_DIR_DIO1_OUT; + } else { + /* input port */ + ctrl01 |= II20K_CTRL01_DIO1_IN; + dir_ena &= ~II20K_DIR_DIO1_OUT; + } + + /* port 2 - channels 16-23 */ + if (s->io_bits & 0x00ff0000) { + /* output port */ + ctrl23 &= ~II20K_CTRL23_DIO2_IN; + dir_ena &= ~II20K_BUF_DISAB_DIO2; + dir_ena |= II20K_DIR_DIO2_OUT; + } else { + /* input port */ + ctrl23 |= II20K_CTRL23_DIO2_IN; + dir_ena &= ~II20K_DIR_DIO2_OUT; + } + + /* port 3 - channels 24-31 */ + if (s->io_bits & 0xff000000) { + /* output port */ + ctrl23 &= ~II20K_CTRL23_DIO3_IN; + dir_ena &= ~II20K_BUF_DISAB_DIO3; + dir_ena |= II20K_DIR_DIO3_OUT; + } else { + /* input port */ + ctrl23 |= II20K_CTRL23_DIO3_IN; + dir_ena &= ~II20K_DIR_DIO3_OUT; + } + + ctrl23 |= II20K_CTRL01_SET; + ctrl23 |= II20K_CTRL23_SET; + + /* order is important */ + writeb(ctrl01, devpriv->ioaddr + II20K_CTRL01_REG); + writeb(ctrl23, devpriv->ioaddr + II20K_CTRL23_REG); + writeb(dir_ena, devpriv->ioaddr + II20K_DIR_ENA_REG); } -static unsigned int pci20xxx_di(struct comedi_device *dev, - struct comedi_subdevice *s) +static int ii20k_dio_insn_config(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { - struct pci20xxx_private *devpriv = dev->private; + unsigned int mask = 1 << CR_CHAN(insn->chanspec); unsigned int bits; - /* XXX same note as above */ - bits = readb(devpriv->ioaddr + PCI20000_DIO_0); - bits |= readb(devpriv->ioaddr + PCI20000_DIO_1) << 8; - bits |= readb(devpriv->ioaddr + PCI20000_DIO_2) << 16; - bits |= readb(devpriv->ioaddr + PCI20000_DIO_3) << 24; - - return bits; -} -#endif - -static void pci20xxx_dio_config(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - struct pci20xxx_private *devpriv = dev->private; - unsigned char control_01; - unsigned char control_23; - unsigned char buffer; - - control_01 = readb(devpriv->ioaddr + PCI20000_DIO_CONTROL_01); - control_23 = readb(devpriv->ioaddr + PCI20000_DIO_CONTROL_23); - buffer = readb(devpriv->ioaddr + PCI20000_DIO_BUFFER); - - if (s->io_bits & 0x000000ff) { - /* output port 0 */ - control_01 &= PCI20000_DIO_EOC; - buffer = (buffer & (~(DIO_BE << DIO_PS_0))) | (DIO_BO << - DIO_PS_0); - } else { - /* input port 0 */ - control_01 = (control_01 & DIO_CAND) | PCI20000_DIO_EIC; - buffer = (buffer & (~(DIO_BI << DIO_PS_0))); - } - if (s->io_bits & 0x0000ff00) { - /* output port 1 */ - control_01 &= PCI20000_DIO_OOC; - buffer = (buffer & (~(DIO_BE << DIO_PS_1))) | (DIO_BO << - DIO_PS_1); - } else { - /* input port 1 */ - control_01 = (control_01 & DIO_CAND) | PCI20000_DIO_OIC; - buffer = (buffer & (~(DIO_BI << DIO_PS_1))); - } - if (s->io_bits & 0x00ff0000) { - /* output port 2 */ - control_23 &= PCI20000_DIO_EOC; - buffer = (buffer & (~(DIO_BE << DIO_PS_2))) | (DIO_BO << - DIO_PS_2); - } else { - /* input port 2 */ - control_23 = (control_23 & DIO_CAND) | PCI20000_DIO_EIC; - buffer = (buffer & (~(DIO_BI << DIO_PS_2))); - } - if (s->io_bits & 0xff000000) { - /* output port 3 */ - control_23 &= PCI20000_DIO_OOC; - buffer = (buffer & (~(DIO_BE << DIO_PS_3))) | (DIO_BO << - DIO_PS_3); - } else { - /* input port 3 */ - control_23 = (control_23 & DIO_CAND) | PCI20000_DIO_OIC; - buffer = (buffer & (~(DIO_BI << DIO_PS_3))); - } - writeb(control_01, devpriv->ioaddr + PCI20000_DIO_CONTROL_01); - writeb(control_23, devpriv->ioaddr + PCI20000_DIO_CONTROL_23); - writeb(buffer, devpriv->ioaddr + PCI20000_DIO_BUFFER); -} - -static int pci20xxx_dio_insn_config(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - int mask, bits; - - mask = 1 << CR_CHAN(insn->chanspec); if (mask & 0x000000ff) bits = 0x000000ff; else if (mask & 0x0000ff00) @@ -456,79 +446,71 @@ static int pci20xxx_dio_insn_config(struct comedi_device *dev, bits = 0x00ff0000; else bits = 0xff000000; - if (data[0]) - s->io_bits |= bits; - else + + switch (data[0]) { + case INSN_CONFIG_DIO_INPUT: s->io_bits &= ~bits; - pci20xxx_dio_config(dev, s); + break; + case INSN_CONFIG_DIO_OUTPUT: + s->io_bits |= bits; + break; + case INSN_CONFIG_DIO_QUERY: + data[1] = (s->io_bits & bits) ? COMEDI_OUTPUT : COMEDI_INPUT; + return insn->n; + default: + return -EINVAL; + } - return 1; -} - -static int pci20xxx_dio_insn_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - struct pci20xxx_private *devpriv = dev->private; - unsigned int mask = data[0]; - - s->state &= ~mask; - s->state |= (mask & data[1]); - - mask &= s->io_bits; - if (mask & 0x000000ff) - writeb((s->state >> 0) & 0xff, - devpriv->ioaddr + PCI20000_DIO_0); - if (mask & 0x0000ff00) - writeb((s->state >> 8) & 0xff, - devpriv->ioaddr + PCI20000_DIO_1); - if (mask & 0x00ff0000) - writeb((s->state >> 16) & 0xff, - devpriv->ioaddr + PCI20000_DIO_2); - if (mask & 0xff000000) - writeb((s->state >> 24) & 0xff, - devpriv->ioaddr + PCI20000_DIO_3); - - data[1] = readb(devpriv->ioaddr + PCI20000_DIO_0); - data[1] |= readb(devpriv->ioaddr + PCI20000_DIO_1) << 8; - data[1] |= readb(devpriv->ioaddr + PCI20000_DIO_2) << 16; - data[1] |= readb(devpriv->ioaddr + PCI20000_DIO_3) << 24; + ii20k_dio_config(dev, s); return insn->n; } -static int pci20xxx_dio_init(struct comedi_device *dev, - struct comedi_subdevice *s) +static int ii20k_dio_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { - s->type = COMEDI_SUBD_DIO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = 32; - s->insn_bits = pci20xxx_dio_insn_bits; - s->insn_config = pci20xxx_dio_insn_config; - s->maxdata = 1; - s->len_chanlist = 32; - s->range_table = &range_digital; - s->io_bits = 0; + struct pci20xxx_private *devpriv = dev->private; + unsigned int mask = data[0] & s->io_bits; /* outputs only */ + unsigned int bits = data[1]; - /* digital I/O lines default to input on board reset. */ - pci20xxx_dio_config(dev, s); + if (mask) { + s->state &= ~mask; + s->state |= (bits & mask); - return 0; + if (mask & 0x000000ff) + writeb((s->state >> 0) & 0xff, + devpriv->ioaddr + II20K_DIO0_REG); + if (mask & 0x0000ff00) + writeb((s->state >> 8) & 0xff, + devpriv->ioaddr + II20K_DIO1_REG); + if (mask & 0x00ff0000) + writeb((s->state >> 16) & 0xff, + devpriv->ioaddr + II20K_DIO2_REG); + if (mask & 0xff000000) + writeb((s->state >> 24) & 0xff, + devpriv->ioaddr + II20K_DIO3_REG); + } + + data[1] = readb(devpriv->ioaddr + II20K_DIO0_REG); + data[1] |= readb(devpriv->ioaddr + II20K_DIO1_REG) << 8; + data[1] |= readb(devpriv->ioaddr + II20K_DIO2_REG) << 16; + data[1] |= readb(devpriv->ioaddr + II20K_DIO3_REG) << 24; + + return insn->n; } static int pci20xxx_attach(struct comedi_device *dev, struct comedi_devconfig *it) { struct pci20xxx_private *devpriv; - unsigned char i; - int ret; - int id; - struct comedi_subdevice *s; union pci20xxx_subdev_private *sdp; - - ret = comedi_alloc_subdevices(dev, 1 + PCI20000_MODULES); - if (ret) - return ret; + struct comedi_subdevice *s; + unsigned char id; + bool has_dio; + int ret; + int i; devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) @@ -536,17 +518,22 @@ static int pci20xxx_attach(struct comedi_device *dev, devpriv->ioaddr = (void __iomem *)(unsigned long)it->options[0]; - /* Check PCI-20001 C-2A Carrier Board ID */ - if ((readb(devpriv->ioaddr) & PCI20000_ID) != PCI20000_ID) { - dev_warn(dev->class_dev, - "PCI-20001 C-2A Carrier Board at base=0x%p not found !\n", - devpriv->ioaddr); - return -EINVAL; + id = readb(devpriv->ioaddr + II20K_ID_REG); + switch (id & II20K_ID_MASK) { + case II20K_ID_PCI20001C_1A: + break; + case II20K_ID_PCI20001C_2A: + has_dio = true; + break; + default: + return -ENODEV; } - dev_info(dev->class_dev, "PCI-20001 C-2A at base=0x%p\n", - devpriv->ioaddr); - for (i = 0; i < PCI20000_MODULES; i++) { + ret = comedi_alloc_subdevices(dev, 4); + if (ret) + return ret; + + for (i = 0; i < 3; i++) { s = &dev->subdevices[i]; sdp = comedi_alloc_spriv(s, sizeof(*sdp)); if (!sdp) @@ -580,8 +567,22 @@ static int pci20xxx_attach(struct comedi_device *dev, } } - /* initialize struct pci20xxx_private */ - pci20xxx_dio_init(dev, &dev->subdevices[PCI20000_MODULES]); + /* Digital I/O subdevice */ + s = &dev->subdevices[3]; + if (has_dio) { + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 32; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = ii20k_dio_insn_bits; + s->insn_config = ii20k_dio_insn_config; + + /* default all channels to input */ + ii20k_dio_config(dev, s); + } else { + s->type = COMEDI_SUBD_UNUSED; + } return 1; } From f0e32df3d21f048ee35c07e523e918015845d95f Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 12:11:47 -0700 Subject: [PATCH 0749/3400] staging: comedi: ii_pci20kc.c: tidy up the subdevice module init Use the carrier board id to determine if a module is installed for a given subdevice. Consolidate the module init code into ii20k_init_module(). For aesthetic reasons, rename the subdevice functions to remove 'pci' from them. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ii_pci20kc.c | 197 +++++++++++--------- 1 file changed, 104 insertions(+), 93 deletions(-) diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c index 60a3bb2c3657..14721b2832ac 100644 --- a/drivers/staging/comedi/drivers/ii_pci20kc.c +++ b/drivers/staging/comedi/drivers/ii_pci20kc.c @@ -83,6 +83,7 @@ options for PCI-20341M: /* * Register I/O map */ +#define II20K_MOD_OFFSET 0x100 #define II20K_ID_REG 0x00 #define II20K_ID_MOD1_EMPTY (1 << 7) #define II20K_ID_MOD2_EMPTY (1 << 6) @@ -120,8 +121,6 @@ options for PCI-20341M: #define PCI20006_ID 0xe3 #define PCI20xxx_EMPTY_ID 0xff -#define PCI20000_OFFSET 0x100 - #define PCI20006_LCHAN0 0x0d #define PCI20006_STROBE0 0x0b #define PCI20006_LCHAN1 0x15 @@ -130,7 +129,6 @@ options for PCI-20341M: #define PCI20341_INIT 0x04 #define PCI20341_REPMODE 0x00 /* single shot mode */ #define PCI20341_PACER 0x00 /* Hardware Pacer disabled */ -#define PCI20341_CHAN_NR 0x04 /* number of input channels */ #define PCI20341_CONFIG_REG 0x10 #define PCI20341_MOD_STATUS 0x01 #define PCI20341_OPT_REG 0x11 @@ -164,13 +162,13 @@ static const struct comedi_lrange range_bipolar0_025 = { } }; -static const struct comedi_lrange *pci20006_range_list[] = { +static const struct comedi_lrange *ii20k_ao_ranges[] = { &range_bipolar10, &range_unipolar10, &range_bipolar5, }; -static const struct comedi_lrange *const pci20341_ranges[] = { +static const struct comedi_lrange *const ii20k_ai_ranges[] = { &range_bipolar5, &range_bipolar0_5, &range_bipolar0_05, @@ -200,11 +198,10 @@ struct pci20xxx_private { void __iomem *ioaddr; }; -/* pci20006m */ - -static int pci20006_insn_read(struct comedi_device *dev, +static int ii20k_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { union pci20xxx_subdev_private *sdp = s->private; @@ -213,9 +210,10 @@ static int pci20006_insn_read(struct comedi_device *dev, return 1; } -static int pci20006_insn_write(struct comedi_device *dev, +static int ii20k_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { union pci20xxx_subdev_private *sdp = s->private; int hi, lo; @@ -246,36 +244,10 @@ static int pci20006_insn_write(struct comedi_device *dev, return 1; } -static int pci20006_init(struct comedi_device *dev, struct comedi_subdevice *s, - int opt0, int opt1) -{ - union pci20xxx_subdev_private *sdp = s->private; - - if (opt0 < 0 || opt0 > 2) - opt0 = 0; - if (opt1 < 0 || opt1 > 2) - opt1 = 0; - - sdp->pci20006.ao_range_list[0] = pci20006_range_list[opt0]; - sdp->pci20006.ao_range_list[1] = pci20006_range_list[opt1]; - - /* ao subdevice */ - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = 2; - s->len_chanlist = 2; - s->insn_read = pci20006_insn_read; - s->insn_write = pci20006_insn_write; - s->maxdata = 0xffff; - s->range_table_list = sdp->pci20006.ao_range_list; - return 0; -} - -/* PCI20341M */ - -static int pci20341_insn_read(struct comedi_device *dev, +static int ii20k_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { union pci20xxx_subdev_private *sdp = s->private; unsigned int i = 0, j = 0; @@ -328,26 +300,11 @@ static int pci20341_insn_read(struct comedi_device *dev, return i; } -static int pci20341_init(struct comedi_device *dev, struct comedi_subdevice *s, - int opt0, int opt1) +static void ii20k_ai_init(struct comedi_device *dev, + struct comedi_subdevice *s) { union pci20xxx_subdev_private *sdp = s->private; - int option; - - /* options handling */ - if (opt0 < 0 || opt0 > 3) - opt0 = 0; - sdp->pci20341.timebase = pci20341_timebase[opt0]; - sdp->pci20341.settling_time = pci20341_settling_time[opt0]; - - /* ai subdevice */ - s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE; - s->n_chan = PCI20341_CHAN_NR; - s->len_chanlist = PCI20341_SCANLIST; - s->insn_read = pci20341_insn_read; - s->maxdata = 0xffff; - s->range_table = pci20341_ranges[opt0]; + unsigned char option; /* depends on gain, trigger, repetition mode */ option = sdp->pci20341.timebase | PCI20341_REPMODE; @@ -362,7 +319,6 @@ static int pci20341_init(struct comedi_device *dev, struct comedi_subdevice *s, writeb(sdp->pci20341.settling_time, sdp->iobase + PCI20341_SET_TIME_REG); /* trigger not implemented */ - return 0; } static void ii20k_dio_config(struct comedi_device *dev, @@ -501,16 +457,78 @@ static int ii20k_dio_insn_bits(struct comedi_device *dev, return insn->n; } +static int ii20k_init_module(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_devconfig *it) +{ + struct pci20xxx_private *devpriv = dev->private; + union pci20xxx_subdev_private *sdp; + unsigned int opt0 = it->options[(2 * s->index) + 2]; + unsigned int opt1 = it->options[(2 * s->index) + 3]; + void __iomem *iobase; + unsigned char id; + + sdp = comedi_alloc_spriv(s, sizeof(*sdp)); + if (!sdp) + return -ENOMEM; + + iobase = devpriv->ioaddr + (s->index + 1) * II20K_MOD_OFFSET; + id = readb(iobase + II20K_ID_REG); + switch (id) { + case PCI20006_ID: + if (opt0 < 0 || opt0 > 2) + opt0 = 0; + if (opt1 < 0 || opt1 > 2) + opt1 = 0; + + sdp->pci20006.iobase = iobase; + sdp->pci20006.ao_range_list[0] = ii20k_ao_ranges[opt0]; + sdp->pci20006.ao_range_list[1] = ii20k_ao_ranges[opt1]; + + /* Analog Output subdevice */ + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 2; + s->maxdata = 0xffff; + s->range_table_list = sdp->pci20006.ao_range_list; + s->insn_read = ii20k_ao_insn_read; + s->insn_write = ii20k_ao_insn_write; + break; + case PCI20341_ID: + if (opt0 < 0 || opt0 > 3) + opt0 = 0; + + sdp->pci20341.iobase = iobase; + sdp->pci20341.timebase = pci20341_timebase[opt0]; + sdp->pci20341.settling_time = pci20341_settling_time[opt0]; + + /* Analog Input subdevice */ + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 4; + s->maxdata = 0xffff; + s->range_table = ii20k_ai_ranges[opt0]; + s->insn_read = ii20k_ai_insn_read; + + ii20k_ai_init(dev, s); + break; + case PCI20xxx_EMPTY_ID: + default: + s->type = COMEDI_SUBD_UNUSED; + break; + } + + return 0; +} + static int pci20xxx_attach(struct comedi_device *dev, struct comedi_devconfig *it) { struct pci20xxx_private *devpriv; - union pci20xxx_subdev_private *sdp; struct comedi_subdevice *s; unsigned char id; bool has_dio; int ret; - int i; devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) @@ -533,38 +551,31 @@ static int pci20xxx_attach(struct comedi_device *dev, if (ret) return ret; - for (i = 0; i < 3; i++) { - s = &dev->subdevices[i]; - sdp = comedi_alloc_spriv(s, sizeof(*sdp)); - if (!sdp) - return -ENOMEM; - id = readb(devpriv->ioaddr + (i + 1) * PCI20000_OFFSET); - switch (id) { - case PCI20006_ID: - sdp->pci20006.iobase = - devpriv->ioaddr + (i + 1) * PCI20000_OFFSET; - pci20006_init(dev, s, it->options[2 * i + 2], - it->options[2 * i + 3]); - dev_info(dev->class_dev, - "PCI-20006 module in slot %d\n", i + 1); - break; - case PCI20341_ID: - sdp->pci20341.iobase = - devpriv->ioaddr + (i + 1) * PCI20000_OFFSET; - pci20341_init(dev, s, it->options[2 * i + 2], - it->options[2 * i + 3]); - dev_info(dev->class_dev, - "PCI-20341 module in slot %d\n", i + 1); - break; - default: - dev_warn(dev->class_dev, - "unknown module code 0x%02x in slot %d: module disabled\n", - id, i); /* XXX this looks like a bug! i + 1 ?? */ - /* fall through */ - case PCI20xxx_EMPTY_ID: - s->type = COMEDI_SUBD_UNUSED; - break; - } + s = &dev->subdevices[0]; + if (id & II20K_ID_MOD1_EMPTY) { + s->type = COMEDI_SUBD_UNUSED; + } else { + ret = ii20k_init_module(dev, s, it); + if (ret) + return ret; + } + + s = &dev->subdevices[1]; + if (id & II20K_ID_MOD2_EMPTY) { + s->type = COMEDI_SUBD_UNUSED; + } else { + ret = ii20k_init_module(dev, s, it); + if (ret) + return ret; + } + + s = &dev->subdevices[2]; + if (id & II20K_ID_MOD3_EMPTY) { + s->type = COMEDI_SUBD_UNUSED; + } else { + ret = ii20k_init_module(dev, s, it); + if (ret) + return ret; } /* Digital I/O subdevice */ From 57b2161f021c26f56574edfaaaa9503f877fc1a2 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 12:12:09 -0700 Subject: [PATCH 0750/3400] staging: comedi: ii_pci20kc.c: remove 'iobase' from the subdevice private data The 'iobase' can be calculated when needed. Remove it from the subdevice private data. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ii_pci20kc.c | 58 +++++++++++---------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c index 14721b2832ac..888c6c32257a 100644 --- a/drivers/staging/comedi/drivers/ii_pci20kc.c +++ b/drivers/staging/comedi/drivers/ii_pci20kc.c @@ -179,15 +179,12 @@ static const int pci20341_timebase[] = { 0x00, 0x00, 0x00, 0x04 }; static const int pci20341_settling_time[] = { 0x58, 0x58, 0x93, 0x99 }; union pci20xxx_subdev_private { - void __iomem *iobase; struct { - void __iomem *iobase; const struct comedi_lrange *ao_range_list[2]; /* range of channels of ao module */ unsigned int last_data[2]; } pci20006; struct { - void __iomem *iobase; int timebase; int settling_time; int ai_gain; @@ -198,6 +195,14 @@ struct pci20xxx_private { void __iomem *ioaddr; }; +static void __iomem *ii20k_module_iobase(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + struct pci20xxx_private *devpriv = dev->private; + + return devpriv->ioaddr + (s->index + 1) * II20K_MOD_OFFSET; +} + static int ii20k_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, @@ -216,6 +221,7 @@ static int ii20k_ao_insn_write(struct comedi_device *dev, unsigned int *data) { union pci20xxx_subdev_private *sdp = s->private; + void __iomem *iobase = ii20k_module_iobase(dev, s); int hi, lo; unsigned int boarddata; @@ -227,14 +233,14 @@ static int ii20k_ao_insn_write(struct comedi_device *dev, switch (CR_CHAN(insn->chanspec)) { case 0: - writeb(lo, sdp->iobase + PCI20006_LCHAN0); - writeb(hi, sdp->iobase + PCI20006_LCHAN0 + 1); - writeb(0x00, sdp->iobase + PCI20006_STROBE0); + writeb(lo, iobase + PCI20006_LCHAN0); + writeb(hi, iobase + PCI20006_LCHAN0 + 1); + writeb(0x00, iobase + PCI20006_STROBE0); break; case 1: - writeb(lo, sdp->iobase + PCI20006_LCHAN1); - writeb(hi, sdp->iobase + PCI20006_LCHAN1 + 1); - writeb(0x00, sdp->iobase + PCI20006_STROBE1); + writeb(lo, iobase + PCI20006_LCHAN1); + writeb(hi, iobase + PCI20006_LCHAN1 + 1); + writeb(0x00, iobase + PCI20006_STROBE1); break; default: dev_warn(dev->class_dev, "ao channel Error!\n"); @@ -250,6 +256,7 @@ static int ii20k_ai_insn_read(struct comedi_device *dev, unsigned int *data) { union pci20xxx_subdev_private *sdp = s->private; + void __iomem *iobase = ii20k_module_iobase(dev, s); unsigned int i = 0, j = 0; int lo, hi; unsigned char eoc; /* end of conversion */ @@ -257,15 +264,15 @@ static int ii20k_ai_insn_read(struct comedi_device *dev, unsigned int boarddata; /* write number of input channels */ - writeb(1, sdp->iobase + PCI20341_LCHAN_ADDR_REG); + writeb(1, iobase + PCI20341_LCHAN_ADDR_REG); clb = PCI20341_DAISY_CHAIN | PCI20341_MUX | (sdp->pci20341.ai_gain << 3) | CR_CHAN(insn->chanspec); - writeb(clb, sdp->iobase + PCI20341_CHAN_LIST); + writeb(clb, iobase + PCI20341_CHAN_LIST); /* reset settling time counter and trigger delay counter */ - writeb(0x00, sdp->iobase + PCI20341_CC_RESET); + writeb(0x00, iobase + PCI20341_CC_RESET); - writeb(0x00, sdp->iobase + PCI20341_CHAN_RESET); + writeb(0x00, iobase + PCI20341_CHAN_RESET); /* generate Pacer */ @@ -276,21 +283,21 @@ static int ii20k_ai_insn_read(struct comedi_device *dev, */ j = 0; /* generate Pacer */ - readb(sdp->iobase + PCI20341_SOFT_PACER); + readb(iobase + PCI20341_SOFT_PACER); - eoc = readb(sdp->iobase + PCI20341_STATUS_REG); + eoc = readb(iobase + PCI20341_STATUS_REG); /* poll Interrupt Flag */ while ((eoc < 0x80) && j < 100) { j++; - eoc = readb(sdp->iobase + PCI20341_STATUS_REG); + eoc = readb(iobase + PCI20341_STATUS_REG); } if (j >= 100) { dev_warn(dev->class_dev, "AI interrupt channel %i polling exit !\n", i); return -EINVAL; } - lo = readb(sdp->iobase + PCI20341_LDATA); - hi = readb(sdp->iobase + PCI20341_LDATA + 1); + lo = readb(iobase + PCI20341_LDATA); + hi = readb(iobase + PCI20341_LDATA + 1); boarddata = lo + 0x100 * hi; /* board-data -> comedi-data */ @@ -304,20 +311,21 @@ static void ii20k_ai_init(struct comedi_device *dev, struct comedi_subdevice *s) { union pci20xxx_subdev_private *sdp = s->private; + void __iomem *iobase = ii20k_module_iobase(dev, s); unsigned char option; /* depends on gain, trigger, repetition mode */ option = sdp->pci20341.timebase | PCI20341_REPMODE; /* initialize Module */ - writeb(PCI20341_INIT, sdp->iobase + PCI20341_CONFIG_REG); + writeb(PCI20341_INIT, iobase + PCI20341_CONFIG_REG); /* set Pacer */ - writeb(PCI20341_PACER, sdp->iobase + PCI20341_MOD_STATUS); + writeb(PCI20341_PACER, iobase + PCI20341_MOD_STATUS); /* option register */ - writeb(option, sdp->iobase + PCI20341_OPT_REG); + writeb(option, iobase + PCI20341_OPT_REG); /* settling time counter */ writeb(sdp->pci20341.settling_time, - sdp->iobase + PCI20341_SET_TIME_REG); + iobase + PCI20341_SET_TIME_REG); /* trigger not implemented */ } @@ -461,18 +469,16 @@ static int ii20k_init_module(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_devconfig *it) { - struct pci20xxx_private *devpriv = dev->private; union pci20xxx_subdev_private *sdp; + void __iomem *iobase = ii20k_module_iobase(dev, s); unsigned int opt0 = it->options[(2 * s->index) + 2]; unsigned int opt1 = it->options[(2 * s->index) + 3]; - void __iomem *iobase; unsigned char id; sdp = comedi_alloc_spriv(s, sizeof(*sdp)); if (!sdp) return -ENOMEM; - iobase = devpriv->ioaddr + (s->index + 1) * II20K_MOD_OFFSET; id = readb(iobase + II20K_ID_REG); switch (id) { case PCI20006_ID: @@ -481,7 +487,6 @@ static int ii20k_init_module(struct comedi_device *dev, if (opt1 < 0 || opt1 > 2) opt1 = 0; - sdp->pci20006.iobase = iobase; sdp->pci20006.ao_range_list[0] = ii20k_ao_ranges[opt0]; sdp->pci20006.ao_range_list[1] = ii20k_ao_ranges[opt1]; @@ -498,7 +503,6 @@ static int ii20k_init_module(struct comedi_device *dev, if (opt0 < 0 || opt0 > 3) opt0 = 0; - sdp->pci20341.iobase = iobase; sdp->pci20341.timebase = pci20341_timebase[opt0]; sdp->pci20341.settling_time = pci20341_settling_time[opt0]; From 04815a4b5e2d1b3a741326f75c500382a55f7968 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 12:12:30 -0700 Subject: [PATCH 0751/3400] staging: comedi: ii_pci20kc.c: break up the subdevice private data union The union used for the subdevice private data just adds confusion. Split the union into two separate private data structs. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ii_pci20kc.c | 64 +++++++++++---------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c index 888c6c32257a..e86a2b5399ce 100644 --- a/drivers/staging/comedi/drivers/ii_pci20kc.c +++ b/drivers/staging/comedi/drivers/ii_pci20kc.c @@ -178,17 +178,15 @@ static const struct comedi_lrange *const ii20k_ai_ranges[] = { static const int pci20341_timebase[] = { 0x00, 0x00, 0x00, 0x04 }; static const int pci20341_settling_time[] = { 0x58, 0x58, 0x93, 0x99 }; -union pci20xxx_subdev_private { - struct { - const struct comedi_lrange *ao_range_list[2]; - /* range of channels of ao module */ - unsigned int last_data[2]; - } pci20006; - struct { - int timebase; - int settling_time; - int ai_gain; - } pci20341; +struct ii20k_ao_private { + const struct comedi_lrange *ao_range_list[2]; + unsigned int last_data[2]; +}; + +struct ii20k_ai_private { + int timebase; + int settling_time; + int ai_gain; }; struct pci20xxx_private { @@ -208,9 +206,9 @@ static int ii20k_ao_insn_read(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - union pci20xxx_subdev_private *sdp = s->private; + struct ii20k_ao_private *ao_spriv = s->private; - data[0] = sdp->pci20006.last_data[CR_CHAN(insn->chanspec)]; + data[0] = ao_spriv->last_data[CR_CHAN(insn->chanspec)]; return 1; } @@ -220,12 +218,12 @@ static int ii20k_ao_insn_write(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - union pci20xxx_subdev_private *sdp = s->private; + struct ii20k_ao_private *ao_spriv = s->private; void __iomem *iobase = ii20k_module_iobase(dev, s); int hi, lo; unsigned int boarddata; - sdp->pci20006.last_data[CR_CHAN(insn->chanspec)] = data[0]; + ao_spriv->last_data[CR_CHAN(insn->chanspec)] = data[0]; boarddata = (((unsigned int)data[0] + 0x8000) & 0xffff); /* comedi-data -> board-data */ lo = (boarddata & 0xff); @@ -255,7 +253,7 @@ static int ii20k_ai_insn_read(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - union pci20xxx_subdev_private *sdp = s->private; + struct ii20k_ai_private *ai_spriv = s->private; void __iomem *iobase = ii20k_module_iobase(dev, s); unsigned int i = 0, j = 0; int lo, hi; @@ -265,7 +263,7 @@ static int ii20k_ai_insn_read(struct comedi_device *dev, /* write number of input channels */ writeb(1, iobase + PCI20341_LCHAN_ADDR_REG); - clb = PCI20341_DAISY_CHAIN | PCI20341_MUX | (sdp->pci20341.ai_gain << 3) + clb = PCI20341_DAISY_CHAIN | PCI20341_MUX | (ai_spriv->ai_gain << 3) | CR_CHAN(insn->chanspec); writeb(clb, iobase + PCI20341_CHAN_LIST); @@ -310,12 +308,12 @@ static int ii20k_ai_insn_read(struct comedi_device *dev, static void ii20k_ai_init(struct comedi_device *dev, struct comedi_subdevice *s) { - union pci20xxx_subdev_private *sdp = s->private; + struct ii20k_ai_private *ai_spriv = s->private; void __iomem *iobase = ii20k_module_iobase(dev, s); unsigned char option; /* depends on gain, trigger, repetition mode */ - option = sdp->pci20341.timebase | PCI20341_REPMODE; + option = ai_spriv->timebase | PCI20341_REPMODE; /* initialize Module */ writeb(PCI20341_INIT, iobase + PCI20341_CONFIG_REG); @@ -324,8 +322,7 @@ static void ii20k_ai_init(struct comedi_device *dev, /* option register */ writeb(option, iobase + PCI20341_OPT_REG); /* settling time counter */ - writeb(sdp->pci20341.settling_time, - iobase + PCI20341_SET_TIME_REG); + writeb(ai_spriv->settling_time, iobase + PCI20341_SET_TIME_REG); /* trigger not implemented */ } @@ -469,16 +466,13 @@ static int ii20k_init_module(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_devconfig *it) { - union pci20xxx_subdev_private *sdp; + struct ii20k_ao_private *ao_spriv; + struct ii20k_ai_private *ai_spriv; void __iomem *iobase = ii20k_module_iobase(dev, s); unsigned int opt0 = it->options[(2 * s->index) + 2]; unsigned int opt1 = it->options[(2 * s->index) + 3]; unsigned char id; - sdp = comedi_alloc_spriv(s, sizeof(*sdp)); - if (!sdp) - return -ENOMEM; - id = readb(iobase + II20K_ID_REG); switch (id) { case PCI20006_ID: @@ -487,15 +481,19 @@ static int ii20k_init_module(struct comedi_device *dev, if (opt1 < 0 || opt1 > 2) opt1 = 0; - sdp->pci20006.ao_range_list[0] = ii20k_ao_ranges[opt0]; - sdp->pci20006.ao_range_list[1] = ii20k_ao_ranges[opt1]; + ao_spriv = comedi_alloc_spriv(s, sizeof(*ao_spriv)); + if (!ao_spriv) + return -ENOMEM; + + ao_spriv->ao_range_list[0] = ii20k_ao_ranges[opt0]; + ao_spriv->ao_range_list[1] = ii20k_ao_ranges[opt1]; /* Analog Output subdevice */ s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; s->n_chan = 2; s->maxdata = 0xffff; - s->range_table_list = sdp->pci20006.ao_range_list; + s->range_table_list = ao_spriv->ao_range_list; s->insn_read = ii20k_ao_insn_read; s->insn_write = ii20k_ao_insn_write; break; @@ -503,8 +501,12 @@ static int ii20k_init_module(struct comedi_device *dev, if (opt0 < 0 || opt0 > 3) opt0 = 0; - sdp->pci20341.timebase = pci20341_timebase[opt0]; - sdp->pci20341.settling_time = pci20341_settling_time[opt0]; + ai_spriv = comedi_alloc_spriv(s, sizeof(*ai_spriv)); + if (!ai_spriv) + return -ENOMEM; + + ai_spriv->timebase = pci20341_timebase[opt0]; + ai_spriv->settling_time = pci20341_settling_time[opt0]; /* Analog Input subdevice */ s->type = COMEDI_SUBD_AI; From 87a61614e3cd841cb6d73878b46d8e858418e536 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 12:13:04 -0700 Subject: [PATCH 0752/3400] staging: comedi: ii_pci20kc: cleanup the ao subdevice The PCI-20006M-1 and PCI-20006M-2 modules can both provide an analog output subdevice in this driver. Fix the module init code to detect both of them. The analog output can support +/-5, 0-10, or +/-10 volt ranges depending on jumpers on the board. Report all the ranges to the user instead of relying on the configuration options to set the range. The user can then select the appropriate range depending on how they have configured the hardware. Tidy up the (*insn_{read,write})() functions to work like the comedi core expects. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ii_pci20kc.c | 95 +++++++++------------ 1 file changed, 40 insertions(+), 55 deletions(-) diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c index e86a2b5399ce..1119a1a33135 100644 --- a/drivers/staging/comedi/drivers/ii_pci20kc.c +++ b/drivers/staging/comedi/drivers/ii_pci20kc.c @@ -63,11 +63,6 @@ Options: 7 second option for module 3 options for PCI-20006M: - first: Analog output channel 0 range configuration - 0 bipolar 10 (-10V -- +10V) - 1 unipolar 10 (0V -- +10V) - 2 bipolar 5 (-5V -- 5V) - second: Analog output channel 1 range configuration options for PCI-20341M: first: Analog input gain configuration @@ -117,14 +112,15 @@ options for PCI-20341M: #define II20K_CTRL23_DIO2_IN (1 << 4) #define II20K_CTRL23_DIO3_IN (1 << 1) -#define PCI20341_ID 0x77 -#define PCI20006_ID 0xe3 -#define PCI20xxx_EMPTY_ID 0xff +#define II20K_ID_PCI20006M_1 0xe2 /* 1 AO channels */ +#define II20K_ID_PCI20006M_2 0xe3 /* 2 AO channels */ +#define II20K_AO_STRB_REG(x) (0x0b + ((x) * 0x08)) +#define II20K_AO_LSB_REG(x) (0x0d + ((x) * 0x08)) +#define II20K_AO_MSB_REG(x) (0x0e + ((x) * 0x08)) +#define II20K_AO_STRB_BOTH_REG 0x1b -#define PCI20006_LCHAN0 0x0d -#define PCI20006_STROBE0 0x0b -#define PCI20006_LCHAN1 0x15 -#define PCI20006_STROBE1 0x13 +#define PCI20341_ID 0x77 +#define PCI20xxx_EMPTY_ID 0xff #define PCI20341_INIT 0x04 #define PCI20341_REPMODE 0x00 /* single shot mode */ @@ -144,6 +140,14 @@ options for PCI-20341M: #define PCI20341_MUX 0x04 /* Enable on-board MUX */ #define PCI20341_SCANLIST 0x80 /* Channel/Gain Scan List */ +/* the AO range is set by jumpers on the 20006M module */ +static const struct comedi_lrange ii20k_ao_ranges = { + 3, { + BIP_RANGE(5), /* Chan 0 - W1/W3 in Chan 1 - W2/W4 in */ + UNI_RANGE(10), /* Chan 0 - W1/W3 out Chan 1 - W2/W4 in */ + BIP_RANGE(10) /* Chan 0 - W1/W3 in Chan 1 - W2/W4 out */ + } +}; static const struct comedi_lrange range_bipolar0_5 = { 1, { BIP_RANGE(0.5) @@ -162,12 +166,6 @@ static const struct comedi_lrange range_bipolar0_025 = { } }; -static const struct comedi_lrange *ii20k_ao_ranges[] = { - &range_bipolar10, - &range_unipolar10, - &range_bipolar5, -}; - static const struct comedi_lrange *const ii20k_ai_ranges[] = { &range_bipolar5, &range_bipolar0_5, @@ -179,7 +177,6 @@ static const int pci20341_timebase[] = { 0x00, 0x00, 0x00, 0x04 }; static const int pci20341_settling_time[] = { 0x58, 0x58, 0x93, 0x99 }; struct ii20k_ao_private { - const struct comedi_lrange *ao_range_list[2]; unsigned int last_data[2]; }; @@ -207,10 +204,13 @@ static int ii20k_ao_insn_read(struct comedi_device *dev, unsigned int *data) { struct ii20k_ao_private *ao_spriv = s->private; + unsigned int chan = CR_CHAN(insn->chanspec); + int i; - data[0] = ao_spriv->last_data[CR_CHAN(insn->chanspec)]; + for (i = 0; i < insn->n; i++) + data[i] = ao_spriv->last_data[chan]; - return 1; + return insn->n; } static int ii20k_ao_insn_write(struct comedi_device *dev, @@ -220,32 +220,25 @@ static int ii20k_ao_insn_write(struct comedi_device *dev, { struct ii20k_ao_private *ao_spriv = s->private; void __iomem *iobase = ii20k_module_iobase(dev, s); - int hi, lo; - unsigned int boarddata; + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int val = ao_spriv->last_data[chan]; + int i; - ao_spriv->last_data[CR_CHAN(insn->chanspec)] = data[0]; - boarddata = (((unsigned int)data[0] + 0x8000) & 0xffff); - /* comedi-data -> board-data */ - lo = (boarddata & 0xff); - hi = ((boarddata >> 8) & 0xff); + for (i = 0; i < insn->n; i++) { + val = data[i]; - switch (CR_CHAN(insn->chanspec)) { - case 0: - writeb(lo, iobase + PCI20006_LCHAN0); - writeb(hi, iobase + PCI20006_LCHAN0 + 1); - writeb(0x00, iobase + PCI20006_STROBE0); - break; - case 1: - writeb(lo, iobase + PCI20006_LCHAN1); - writeb(hi, iobase + PCI20006_LCHAN1 + 1); - writeb(0x00, iobase + PCI20006_STROBE1); - break; - default: - dev_warn(dev->class_dev, "ao channel Error!\n"); - return -EINVAL; + /* munge data */ + val += ((s->maxdata + 1) >> 1); + val &= s->maxdata; + + writeb(val & 0xff, iobase + II20K_AO_LSB_REG(chan)); + writeb((val >> 8) & 0xff, iobase + II20K_AO_MSB_REG(chan)); + writeb(0x00, iobase + II20K_AO_STRB_REG(chan)); } - return 1; + ao_spriv->last_data[chan] = val; + + return insn->n; } static int ii20k_ai_insn_read(struct comedi_device *dev, @@ -470,30 +463,22 @@ static int ii20k_init_module(struct comedi_device *dev, struct ii20k_ai_private *ai_spriv; void __iomem *iobase = ii20k_module_iobase(dev, s); unsigned int opt0 = it->options[(2 * s->index) + 2]; - unsigned int opt1 = it->options[(2 * s->index) + 3]; unsigned char id; id = readb(iobase + II20K_ID_REG); switch (id) { - case PCI20006_ID: - if (opt0 < 0 || opt0 > 2) - opt0 = 0; - if (opt1 < 0 || opt1 > 2) - opt1 = 0; - + case II20K_ID_PCI20006M_1: + case II20K_ID_PCI20006M_2: ao_spriv = comedi_alloc_spriv(s, sizeof(*ao_spriv)); if (!ao_spriv) return -ENOMEM; - ao_spriv->ao_range_list[0] = ii20k_ao_ranges[opt0]; - ao_spriv->ao_range_list[1] = ii20k_ao_ranges[opt1]; - /* Analog Output subdevice */ s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; - s->n_chan = 2; + s->n_chan = (id == II20K_ID_PCI20006M_2) ? 2 : 1; s->maxdata = 0xffff; - s->range_table_list = ao_spriv->ao_range_list; + s->range_table = &ii20k_ao_ranges; s->insn_read = ii20k_ao_insn_read; s->insn_write = ii20k_ao_insn_write; break; From 3aa5e81177bd8bf235d2b506659a3ecd05d67634 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 12:13:51 -0700 Subject: [PATCH 0753/3400] staging: comedi: ii_pci20kc: cleanup the ai subdevice The PCI-200341M-1 module can both provide an analog input subdevice in this driver. The module provides four differential input channels with four programmable gains. Currently the gain is configured as an option passed when the board is attached. Rewrite the ai subdevice support functions to properly handle the programmable gain. For aesthetics, redefine the memory map for the module. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ii_pci20kc.c | 279 +++++++++----------- 1 file changed, 127 insertions(+), 152 deletions(-) diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c index 1119a1a33135..069cd959ba4b 100644 --- a/drivers/staging/comedi/drivers/ii_pci20kc.c +++ b/drivers/staging/comedi/drivers/ii_pci20kc.c @@ -55,21 +55,6 @@ are: Options: 0 Board base address 1 IRQ - 2 first option for module 1 - 3 second option for module 1 - 4 first option for module 2 - 5 second option for module 2 - 6 first option for module 3 - 7 second option for module 3 - -options for PCI-20006M: - -options for PCI-20341M: - first: Analog input gain configuration - 0 1 - 1 10 - 2 100 - 3 200 */ #include @@ -119,26 +104,44 @@ options for PCI-20341M: #define II20K_AO_MSB_REG(x) (0x0e + ((x) * 0x08)) #define II20K_AO_STRB_BOTH_REG 0x1b -#define PCI20341_ID 0x77 -#define PCI20xxx_EMPTY_ID 0xff - -#define PCI20341_INIT 0x04 -#define PCI20341_REPMODE 0x00 /* single shot mode */ -#define PCI20341_PACER 0x00 /* Hardware Pacer disabled */ -#define PCI20341_CONFIG_REG 0x10 -#define PCI20341_MOD_STATUS 0x01 -#define PCI20341_OPT_REG 0x11 -#define PCI20341_SET_TIME_REG 0x15 -#define PCI20341_LCHAN_ADDR_REG 0x13 -#define PCI20341_CHAN_LIST 0x80 -#define PCI20341_CC_RESET 0x1b -#define PCI20341_CHAN_RESET 0x19 -#define PCI20341_SOFT_PACER 0x04 -#define PCI20341_STATUS_REG 0x12 -#define PCI20341_LDATA 0x02 -#define PCI20341_DAISY_CHAIN 0x20 /* On-board inputs only */ -#define PCI20341_MUX 0x04 /* Enable on-board MUX */ -#define PCI20341_SCANLIST 0x80 /* Channel/Gain Scan List */ +#define II20K_ID_PCI200341M_1 0x77 /* 4 AI channels */ +#define II20K_AI_STATUS_CMD_REG 0x01 +#define II20K_AI_STATUS_CMD_BUSY (1 << 7) +#define II20K_AI_STATUS_CMD_HW_ENA (1 << 1) +#define II20K_AI_STATUS_CMD_EXT_START (1 << 0) +#define II20K_AI_LSB_REG 0x02 +#define II20K_AI_MSB_REG 0x03 +#define II20K_AI_PACER_RESET_REG 0x04 +#define II20K_AI_16BIT_DATA_REG 0x06 +#define II20K_AI_CONF_REG 0x10 +#define II20K_AI_CONF_ENA (1 << 2) +#define II20K_AI_OPT_REG 0x11 +#define II20K_AI_OPT_TRIG_ENA (1 << 5) +#define II20K_AI_OPT_TRIG_INV (1 << 4) +#define II20K_AI_OPT_TIMEBASE(x) (((x) & 0x3) << 1) +#define II20K_AI_OPT_BURST_MODE (1 << 0) +#define II20K_AI_STATUS_REG 0x12 +#define II20K_AI_STATUS_INT (1 << 7) +#define II20K_AI_STATUS_TRIG (1 << 6) +#define II20K_AI_STATUS_TRIG_ENA (1 << 5) +#define II20K_AI_STATUS_PACER_ERR (1 << 2) +#define II20K_AI_STATUS_DATA_ERR (1 << 1) +#define II20K_AI_STATUS_SET_TIME_ERR (1 << 0) +#define II20K_AI_LAST_CHAN_ADDR_REG 0x13 +#define II20K_AI_CUR_ADDR_REG 0x14 +#define II20K_AI_SET_TIME_REG 0x15 +#define II20K_AI_DELAY_LSB_REG 0x16 +#define II20K_AI_DELAY_MSB_REG 0x17 +#define II20K_AI_CHAN_ADV_REG 0x18 +#define II20K_AI_CHAN_RESET_REG 0x19 +#define II20K_AI_START_TRIG_REG 0x1a +#define II20K_AI_COUNT_RESET_REG 0x1b +#define II20K_AI_CHANLIST_REG 0x80 +#define II20K_AI_CHANLIST_ONBOARD_ONLY (1 << 5) +#define II20K_AI_CHANLIST_GAIN(x) (((x) & 0x3) << 3) +#define II20K_AI_CHANLIST_MUX_ENA (1 << 2) +#define II20K_AI_CHANLIST_CHAN(x) (((x) & 0x3) << 0) +#define II20K_AI_CHANLIST_LEN 0x80 /* the AO range is set by jumpers on the 20006M module */ static const struct comedi_lrange ii20k_ao_ranges = { @@ -148,44 +151,20 @@ static const struct comedi_lrange ii20k_ao_ranges = { BIP_RANGE(10) /* Chan 0 - W1/W3 in Chan 1 - W2/W4 out */ } }; -static const struct comedi_lrange range_bipolar0_5 = { - 1, { - BIP_RANGE(0.5) - } -}; -static const struct comedi_lrange range_bipolar0_05 = { - 1, { - BIP_RANGE(0.05) - } +static const struct comedi_lrange ii20k_ai_ranges = { + 4, { + BIP_RANGE(5), /* gain 1 */ + BIP_RANGE(0.5), /* gain 10 */ + BIP_RANGE(0.05), /* gain 100 */ + BIP_RANGE(0.025) /* gain 200 */ + }, }; -static const struct comedi_lrange range_bipolar0_025 = { - 1, { - BIP_RANGE(0.025) - } -}; - -static const struct comedi_lrange *const ii20k_ai_ranges[] = { - &range_bipolar5, - &range_bipolar0_5, - &range_bipolar0_05, - &range_bipolar0_025, -}; - -static const int pci20341_timebase[] = { 0x00, 0x00, 0x00, 0x04 }; -static const int pci20341_settling_time[] = { 0x58, 0x58, 0x93, 0x99 }; - struct ii20k_ao_private { unsigned int last_data[2]; }; -struct ii20k_ai_private { - int timebase; - int settling_time; - int ai_gain; -}; - struct pci20xxx_private { void __iomem *ioaddr; }; @@ -241,82 +220,94 @@ static int ii20k_ao_insn_write(struct comedi_device *dev, return insn->n; } +static int ii20k_ai_wait_eoc(struct comedi_device *dev, + struct comedi_subdevice *s, + int timeout) +{ + void __iomem *iobase = ii20k_module_iobase(dev, s); + unsigned char status; + + do { + status = readb(iobase + II20K_AI_STATUS_REG); + if ((status & II20K_AI_STATUS_INT) == 0) + return 0; + } while (timeout--); + + return -ETIME; +} + +static void ii20k_ai_setup(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int chanspec) +{ + void __iomem *iobase = ii20k_module_iobase(dev, s); + unsigned int chan = CR_CHAN(chanspec); + unsigned int range = CR_RANGE(chanspec); + unsigned char val; + + /* initialize module */ + writeb(II20K_AI_CONF_ENA, iobase + II20K_AI_CONF_REG); + + /* software conversion */ + writeb(0, iobase + II20K_AI_STATUS_CMD_REG); + + /* set the time base for the settling time counter based on the gain */ + val = (range < 3) ? II20K_AI_OPT_TIMEBASE(0) : II20K_AI_OPT_TIMEBASE(2); + writeb(val, iobase + II20K_AI_OPT_REG); + + /* set the settling time counter based on the gain */ + val = (range < 2) ? 0x58 : (range < 3) ? 0x93 : 0x99; + writeb(val, iobase + II20K_AI_SET_TIME_REG); + + /* set number of input channels */ + writeb(1, iobase + II20K_AI_LAST_CHAN_ADDR_REG); + + /* set the channel list byte */ + val = II20K_AI_CHANLIST_ONBOARD_ONLY | + II20K_AI_CHANLIST_MUX_ENA | + II20K_AI_CHANLIST_GAIN(range) | + II20K_AI_CHANLIST_CHAN(chan); + writeb(val, iobase + II20K_AI_CHANLIST_REG); + + /* reset settling time counter and trigger delay counter */ + writeb(0, iobase + II20K_AI_COUNT_RESET_REG); + + /* reset channel scanner */ + writeb(0, iobase + II20K_AI_CHAN_RESET_REG); +} + static int ii20k_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct ii20k_ai_private *ai_spriv = s->private; void __iomem *iobase = ii20k_module_iobase(dev, s); - unsigned int i = 0, j = 0; - int lo, hi; - unsigned char eoc; /* end of conversion */ - unsigned int clb; /* channel list byte */ - unsigned int boarddata; + int ret; + int i; - /* write number of input channels */ - writeb(1, iobase + PCI20341_LCHAN_ADDR_REG); - clb = PCI20341_DAISY_CHAIN | PCI20341_MUX | (ai_spriv->ai_gain << 3) - | CR_CHAN(insn->chanspec); - writeb(clb, iobase + PCI20341_CHAN_LIST); - - /* reset settling time counter and trigger delay counter */ - writeb(0x00, iobase + PCI20341_CC_RESET); - - writeb(0x00, iobase + PCI20341_CHAN_RESET); - - /* generate Pacer */ + ii20k_ai_setup(dev, s, insn->chanspec); for (i = 0; i < insn->n; i++) { - /* data polling isn't the niciest way to get the data, I know, - * but there are only 6 cycles (mean) and it is easier than - * the whole interrupt stuff - */ - j = 0; - /* generate Pacer */ - readb(iobase + PCI20341_SOFT_PACER); + unsigned int val; - eoc = readb(iobase + PCI20341_STATUS_REG); - /* poll Interrupt Flag */ - while ((eoc < 0x80) && j < 100) { - j++; - eoc = readb(iobase + PCI20341_STATUS_REG); - } - if (j >= 100) { - dev_warn(dev->class_dev, - "AI interrupt channel %i polling exit !\n", i); - return -EINVAL; - } - lo = readb(iobase + PCI20341_LDATA); - hi = readb(iobase + PCI20341_LDATA + 1); - boarddata = lo + 0x100 * hi; + /* generate a software start convert signal */ + readb(iobase + II20K_AI_PACER_RESET_REG); - /* board-data -> comedi-data */ - data[i] = (short)((boarddata + 0x8000) & 0xffff); + ret = ii20k_ai_wait_eoc(dev, s, 100); + if (ret) + return ret; + + val = readb(iobase + II20K_AI_LSB_REG); + val |= (readb(iobase + II20K_AI_MSB_REG) << 8); + + /* munge two's complement data */ + val += ((s->maxdata + 1) >> 1); + val &= s->maxdata; + + data[i] = val; } - return i; -} - -static void ii20k_ai_init(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - struct ii20k_ai_private *ai_spriv = s->private; - void __iomem *iobase = ii20k_module_iobase(dev, s); - unsigned char option; - - /* depends on gain, trigger, repetition mode */ - option = ai_spriv->timebase | PCI20341_REPMODE; - - /* initialize Module */ - writeb(PCI20341_INIT, iobase + PCI20341_CONFIG_REG); - /* set Pacer */ - writeb(PCI20341_PACER, iobase + PCI20341_MOD_STATUS); - /* option register */ - writeb(option, iobase + PCI20341_OPT_REG); - /* settling time counter */ - writeb(ai_spriv->settling_time, iobase + PCI20341_SET_TIME_REG); - /* trigger not implemented */ + return insn->n; } static void ii20k_dio_config(struct comedi_device *dev, @@ -456,13 +447,10 @@ static int ii20k_dio_insn_bits(struct comedi_device *dev, } static int ii20k_init_module(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_devconfig *it) + struct comedi_subdevice *s) { struct ii20k_ao_private *ao_spriv; - struct ii20k_ai_private *ai_spriv; void __iomem *iobase = ii20k_module_iobase(dev, s); - unsigned int opt0 = it->options[(2 * s->index) + 2]; unsigned char id; id = readb(iobase + II20K_ID_REG); @@ -482,28 +470,15 @@ static int ii20k_init_module(struct comedi_device *dev, s->insn_read = ii20k_ao_insn_read; s->insn_write = ii20k_ao_insn_write; break; - case PCI20341_ID: - if (opt0 < 0 || opt0 > 3) - opt0 = 0; - - ai_spriv = comedi_alloc_spriv(s, sizeof(*ai_spriv)); - if (!ai_spriv) - return -ENOMEM; - - ai_spriv->timebase = pci20341_timebase[opt0]; - ai_spriv->settling_time = pci20341_settling_time[opt0]; - + case II20K_ID_PCI200341M_1: /* Analog Input subdevice */ s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE; + s->subdev_flags = SDF_READABLE | SDF_DIFF; s->n_chan = 4; s->maxdata = 0xffff; - s->range_table = ii20k_ai_ranges[opt0]; + s->range_table = &ii20k_ai_ranges; s->insn_read = ii20k_ai_insn_read; - - ii20k_ai_init(dev, s); break; - case PCI20xxx_EMPTY_ID: default: s->type = COMEDI_SUBD_UNUSED; break; @@ -546,7 +521,7 @@ static int pci20xxx_attach(struct comedi_device *dev, if (id & II20K_ID_MOD1_EMPTY) { s->type = COMEDI_SUBD_UNUSED; } else { - ret = ii20k_init_module(dev, s, it); + ret = ii20k_init_module(dev, s); if (ret) return ret; } @@ -555,7 +530,7 @@ static int pci20xxx_attach(struct comedi_device *dev, if (id & II20K_ID_MOD2_EMPTY) { s->type = COMEDI_SUBD_UNUSED; } else { - ret = ii20k_init_module(dev, s, it); + ret = ii20k_init_module(dev, s); if (ret) return ret; } @@ -564,7 +539,7 @@ static int pci20xxx_attach(struct comedi_device *dev, if (id & II20K_ID_MOD3_EMPTY) { s->type = COMEDI_SUBD_UNUSED; } else { - ret = ii20k_init_module(dev, s, it); + ret = ii20k_init_module(dev, s); if (ret) return ret; } From c325f9a9edf24dfc13145b5fce792aec577fe381 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 24 Jul 2013 12:14:11 -0700 Subject: [PATCH 0754/3400] staging: comedi: ii_pci20kc: cleanup final pieces Tidy up the multi-line comments at the beginning of the file and remove any irrelevant information. Fix the II20K_ID_PCI200341M_1 define, there are one to many 0's. Rename all the remaining pci20xxx_* to ii20k_*. The "pci" just adds confusion, this is not a PCI board. Remove the private (*detach) function. It's safe to call the comedi core provided comedi_legacy_detach() even if there is nothing to cleanup. Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ii_pci20kc.c | 111 +++++++------------- 1 file changed, 38 insertions(+), 73 deletions(-) diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c index 069cd959ba4b..954c5397f33c 100644 --- a/drivers/staging/comedi/drivers/ii_pci20kc.c +++ b/drivers/staging/comedi/drivers/ii_pci20kc.c @@ -1,61 +1,31 @@ /* - * comedi/drivers/ii_pci20kc.c - * Driver for Intelligent Instruments PCI-20001C carrier board - * and modules. - * - * Copyright (C) 2000 Markus Kempf - * with suggestions from David Schleef - * 16.06.2000 - * - * Linux device driver for COMEDI - * Intelligent Instrumentation - * PCI-20001 C-2A Carrier Board - * PCI-20341 M-1A 16-Bit analog input module - * - differential - * - range (-5V - +5V) - * - 16 bit - * PCI-20006 M-2 16-Bit analog output module - * - ranges (-10V - +10V) (0V - +10V) (-5V - +5V) - * - 16 bit - * - * only ONE PCI-20341 module possible - * only ONE PCI-20006 module possible - * no extern trigger implemented - * - * NOT WORKING (but soon) only 4 on-board differential channels supported - * NOT WORKING (but soon) only ONE di-port and ONE do-port supported - * instead of 4 digital ports - * di-port == Port 0 - * do-port == Port 1 - * - * The state of this driver is only a starting point for a complete - * COMEDI-driver. The final driver should support all features of the - * carrier board and modules. - * - * The test configuration: - * - * kernel 2.2.14 with RTAI v1.2 and patch-2.2.14rthal2 - * COMEDI 0.7.45 - * COMEDILIB 0.7.9 + * ii_pci20kc.c + * Driver for Intelligent Instruments PCI-20001C carrier board and modules. * + * Copyright (C) 2000 Markus Kempf + * with suggestions from David Schleef 16.06.2000 */ + /* -Driver: ii_pci20kc -Description: Intelligent Instruments PCI-20001C carrier board -Author: Markus Kempf -Devices: [Intelligent Instrumentation] PCI-20001C (ii_pci20kc) -Status: works - -Supports the PCI-20001 C-2a Carrier board, and could probably support -the other carrier boards with small modifications. Modules supported -are: - PCI-20006 M-2 16-bit analog output module - PCI-20341 M-1A 16-bit analog input module - -Options: - 0 Board base address - 1 IRQ -*/ + * Driver: ii_pci20kc + * Description: Intelligent Instruments PCI-20001C carrier board + * Devices: (Intelligent Instrumentation) PCI-20001C [ii_pci20kc] + * Author: Markus Kempf + * Status: works + * + * Supports the PCI-20001C-1a and PCI-20001C-2a carrier boards. The + * -2a version has 32 on-board DIO channels. Three add-on modules + * can be added to the carrier board for additional functionality. + * + * Supported add-on modules: + * PCI-20006M-1 1 channel, 16-bit analog output module + * PCI-20006M-2 2 channel, 16-bit analog output module + * PCI-20341M-1A 4 channel, 16-bit analog input module + * + * Options: + * 0 Board base address + * 1 IRQ (not-used) + */ #include #include "../comedidev.h" @@ -104,7 +74,7 @@ Options: #define II20K_AO_MSB_REG(x) (0x0e + ((x) * 0x08)) #define II20K_AO_STRB_BOTH_REG 0x1b -#define II20K_ID_PCI200341M_1 0x77 /* 4 AI channels */ +#define II20K_ID_PCI20341M_1 0x77 /* 4 AI channels */ #define II20K_AI_STATUS_CMD_REG 0x01 #define II20K_AI_STATUS_CMD_BUSY (1 << 7) #define II20K_AI_STATUS_CMD_HW_ENA (1 << 1) @@ -165,14 +135,14 @@ struct ii20k_ao_private { unsigned int last_data[2]; }; -struct pci20xxx_private { +struct ii20k_private { void __iomem *ioaddr; }; static void __iomem *ii20k_module_iobase(struct comedi_device *dev, struct comedi_subdevice *s) { - struct pci20xxx_private *devpriv = dev->private; + struct ii20k_private *devpriv = dev->private; return devpriv->ioaddr + (s->index + 1) * II20K_MOD_OFFSET; } @@ -313,7 +283,7 @@ static int ii20k_ai_insn_read(struct comedi_device *dev, static void ii20k_dio_config(struct comedi_device *dev, struct comedi_subdevice *s) { - struct pci20xxx_private *devpriv = dev->private; + struct ii20k_private *devpriv = dev->private; unsigned char ctrl01 = 0; unsigned char ctrl23 = 0; unsigned char dir_ena = 0; @@ -416,7 +386,7 @@ static int ii20k_dio_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - struct pci20xxx_private *devpriv = dev->private; + struct ii20k_private *devpriv = dev->private; unsigned int mask = data[0] & s->io_bits; /* outputs only */ unsigned int bits = data[1]; @@ -470,7 +440,7 @@ static int ii20k_init_module(struct comedi_device *dev, s->insn_read = ii20k_ao_insn_read; s->insn_write = ii20k_ao_insn_write; break; - case II20K_ID_PCI200341M_1: + case II20K_ID_PCI20341M_1: /* Analog Input subdevice */ s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_DIFF; @@ -487,10 +457,10 @@ static int ii20k_init_module(struct comedi_device *dev, return 0; } -static int pci20xxx_attach(struct comedi_device *dev, - struct comedi_devconfig *it) +static int ii20k_attach(struct comedi_device *dev, + struct comedi_devconfig *it) { - struct pci20xxx_private *devpriv; + struct ii20k_private *devpriv; struct comedi_subdevice *s; unsigned char id; bool has_dio; @@ -561,21 +531,16 @@ static int pci20xxx_attach(struct comedi_device *dev, s->type = COMEDI_SUBD_UNUSED; } - return 1; + return 0; } -static void pci20xxx_detach(struct comedi_device *dev) -{ - /* Nothing to cleanup */ -} - -static struct comedi_driver pci20xxx_driver = { +static struct comedi_driver ii20k_driver = { .driver_name = "ii_pci20kc", .module = THIS_MODULE, - .attach = pci20xxx_attach, - .detach = pci20xxx_detach, + .attach = ii20k_attach, + .detach = comedi_legacy_detach, }; -module_comedi_driver(pci20xxx_driver); +module_comedi_driver(ii20k_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); From bcc27c82bac2622e352c732a0bda49651e1799b3 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 25 Jul 2013 22:02:48 +0200 Subject: [PATCH 0755/3400] staging: comedi: Add missing #include sparc64 allmodconfig: drivers/staging/comedi/drivers/addi_apci_2032.c: In function 'apci2032_auto_attach': drivers/staging/comedi/drivers/addi_apci_2032.c:328:3: error: implicit declaration of function 'kzalloc' [-Werror=implicit-function-declaration] drivers/staging/comedi/drivers/addi_apci_2032.c:328:11: warning: assignment makes pointer from integer without a cast [enabled by default] drivers/staging/comedi/drivers/addi_apci_2032.c: In function 'apci2032_detach': drivers/staging/comedi/drivers/addi_apci_2032.c:350:3: error: implicit declaration of function 'kfree' [-Werror=implicit-function-declaration] drivers/staging/comedi/drivers/amplc_pci224.c: In function 'pci224_attach_common': drivers/staging/comedi/drivers/amplc_pci224.c:1289:2: error: implicit declaration of function 'kmalloc' [-Werror=implicit-function-declaration] drivers/staging/comedi/drivers/amplc_pci224.c:1289:23: warning: assignment makes pointer from integer without a cast [enabled by default] drivers/staging/comedi/drivers/amplc_pci224.c:1296:24: warning: assignment makes pointer from integer without a cast [enabled by default] drivers/staging/comedi/drivers/amplc_pci224.c:1303:25: warning: assignment makes pointer from integer without a cast [enabled by default] drivers/staging/comedi/drivers/amplc_pci224.c:1348:42: warning: assignment makes pointer from integer without a cast [enabled by default] drivers/staging/comedi/drivers/amplc_pci224.c: In function 'pci224_detach': drivers/staging/comedi/drivers/amplc_pci224.c:1474:3: error: implicit declaration of function 'kfree' [-Werror=implicit-function-declaration] Introduced by commit 0bdab509bf9c6d838dc0a3b1d68bbf841fc20b5a ("staging: comedi: use comedi_alloc_devpriv()"), which removed some inclusions of . Signed-off-by: Geert Uytterhoeven Cc: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/addi_apci_2032.c | 1 + drivers/staging/comedi/drivers/amplc_pci224.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/staging/comedi/drivers/addi_apci_2032.c b/drivers/staging/comedi/drivers/addi_apci_2032.c index cb5d26a567d3..6b0ea16ff546 100644 --- a/drivers/staging/comedi/drivers/addi_apci_2032.c +++ b/drivers/staging/comedi/drivers/addi_apci_2032.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "../comedidev.h" #include "addi_watchdog.h" diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c index 2fc56c40f5b1..179de53a86f0 100644 --- a/drivers/staging/comedi/drivers/amplc_pci224.c +++ b/drivers/staging/comedi/drivers/amplc_pci224.c @@ -101,6 +101,7 @@ Caveats: #include #include #include +#include #include "../comedidev.h" From ea8d15832016b0d07a8121159904e6b1d21b5b8b Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 28 Jun 2013 13:55:27 -0300 Subject: [PATCH 0756/3400] imx-drm: imx-drm-core: Export imx_drm_encoder_get_mux_id When building imx_v6_v7_defconfig with imx-drm drivers selected as modules, we get the following build error: ERROR: "imx_drm_encoder_get_mux_id" [drivers/staging/imx-drm/imx-ldb.ko] undefined! Export the required function to avoid this problem. Signed-off-by: Fabio Estevam Acked-by: Sascha Hauer Acked-by: Philipp Zabel Signed-off-by: Greg Kroah-Hartman --- drivers/staging/imx-drm/imx-drm-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c index 9854a1daf606..6bc205baa4a5 100644 --- a/drivers/staging/imx-drm/imx-drm-core.c +++ b/drivers/staging/imx-drm/imx-drm-core.c @@ -678,6 +678,7 @@ found: return i; } +EXPORT_SYMBOL_GPL(imx_drm_encoder_get_mux_id); /* * imx_drm_remove_encoder - remove an encoder From 55b31cf40654b32a75e7c010f9345f361ccae927 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 28 Jun 2013 13:55:28 -0300 Subject: [PATCH 0757/3400] imx-drm: ipu-dp: Check the return value of devm_kzalloc() devm_kzalloc() may fail, so let's check its return value. Signed-off-by: Fabio Estevam Acked-by: Sascha Hauer Acked-by: Philipp Zabel Signed-off-by: Greg Kroah-Hartman --- drivers/staging/imx-drm/ipu-v3/ipu-dp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-dp.c b/drivers/staging/imx-drm/ipu-v3/ipu-dp.c index 113b046c0225..04495158398e 100644 --- a/drivers/staging/imx-drm/ipu-v3/ipu-dp.c +++ b/drivers/staging/imx-drm/ipu-v3/ipu-dp.c @@ -309,6 +309,8 @@ int ipu_dp_init(struct ipu_soc *ipu, struct device *dev, unsigned long base) int i; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; priv->dev = dev; priv->ipu = ipu; From ded15b5af1f05a57badd7ea5a1428d2fec83a215 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 28 Jun 2013 13:55:29 -0300 Subject: [PATCH 0758/3400] imx-drm: ipu-dp: Remove unneeded braces No need to have braces for a single line 'if' block Signed-off-by: Fabio Estevam Acked-by: Sascha Hauer Acked-by: Philipp Zabel Signed-off-by: Greg Kroah-Hartman --- drivers/staging/imx-drm/ipu-v3/ipu-dp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-dp.c b/drivers/staging/imx-drm/ipu-v3/ipu-dp.c index 04495158398e..6e0e9f1c6517 100644 --- a/drivers/staging/imx-drm/ipu-v3/ipu-dp.c +++ b/drivers/staging/imx-drm/ipu-v3/ipu-dp.c @@ -317,9 +317,8 @@ int ipu_dp_init(struct ipu_soc *ipu, struct device *dev, unsigned long base) ipu->dp_priv = priv; priv->base = devm_ioremap(dev, base, PAGE_SIZE); - if (!priv->base) { + if (!priv->base) return -ENOMEM; - } mutex_init(&priv->mutex); From 6fe9a899edc8c145e6ba6d8217f95cf23932f999 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 28 Jun 2013 13:55:30 -0300 Subject: [PATCH 0759/3400] imx-drm: ipu-dp: Introduce IPUV3_NUM_FLOWS IPUv3 has a total of 3 flows (one synchronous flow and 2 asynchronous flows). Let's add a definition for such number in order to let the code easier to understand. Signed-off-by: Fabio Estevam Acked-by: Sascha Hauer Acked-by: Philipp Zabel Signed-off-by: Greg Kroah-Hartman --- drivers/staging/imx-drm/ipu-v3/ipu-dp.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-dp.c b/drivers/staging/imx-drm/ipu-v3/ipu-dp.c index 6e0e9f1c6517..231afd6c60f8 100644 --- a/drivers/staging/imx-drm/ipu-v3/ipu-dp.c +++ b/drivers/staging/imx-drm/ipu-v3/ipu-dp.c @@ -46,6 +46,8 @@ #define DP_COM_CONF_CSC_DEF_BG (2 << 8) #define DP_COM_CONF_CSC_DEF_BOTH (1 << 8) +#define IPUV3_NUM_FLOWS 3 + struct ipu_dp_priv; struct ipu_dp { @@ -67,7 +69,7 @@ struct ipu_dp_priv { struct ipu_soc *ipu; struct device *dev; void __iomem *base; - struct ipu_flow flow[3]; + struct ipu_flow flow[IPUV3_NUM_FLOWS]; struct mutex mutex; int use_count; }; @@ -280,7 +282,7 @@ struct ipu_dp *ipu_dp_get(struct ipu_soc *ipu, unsigned int flow) struct ipu_dp_priv *priv = ipu->dp_priv; struct ipu_dp *dp; - if (flow > 5) + if ((flow >> 1) >= IPUV3_NUM_FLOWS) return ERR_PTR(-EINVAL); if (flow & 1) @@ -322,7 +324,7 @@ int ipu_dp_init(struct ipu_soc *ipu, struct device *dev, unsigned long base) mutex_init(&priv->mutex); - for (i = 0; i < 3; i++) { + for (i = 0; i < IPUV3_NUM_FLOWS; i++) { priv->flow[i].foreground.foreground = 1; priv->flow[i].base = priv->base + ipu_dp_flow_base[i]; priv->flow[i].priv = priv; From 5d78bf80f63cc85548b0643d147b76b1949c64de Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 16 Jul 2013 02:16:14 -0300 Subject: [PATCH 0760/3400] imx-drm: imx-tve: Provide __acquires/__releases annotation Fix the following sparse warnings: drivers/staging/imx-drm/imx-tve.c:133:13: warning: context imbalance in 'tve_lock' - wrong count at exit drivers/staging/imx-drm/imx-tve.c:139:13: warning: context imbalance in 'tve_unlock' - unexpected unlock Signed-off-by: Fabio Estevam Signed-off-by: Greg Kroah-Hartman --- drivers/staging/imx-drm/imx-tve.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/imx-drm/imx-tve.c b/drivers/staging/imx-drm/imx-tve.c index a56797d88edc..0a1c6ab76344 100644 --- a/drivers/staging/imx-drm/imx-tve.c +++ b/drivers/staging/imx-drm/imx-tve.c @@ -131,12 +131,14 @@ struct imx_tve { }; static void tve_lock(void *__tve) +__acquires(&tve->lock) { struct imx_tve *tve = __tve; spin_lock(&tve->lock); } static void tve_unlock(void *__tve) +__releases(&tve->lock) { struct imx_tve *tve = __tve; spin_unlock(&tve->lock); From 1c0541873c281d39e167a47634d5402adb4e3ae4 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 23 Jul 2013 14:15:32 -0300 Subject: [PATCH 0761/3400] imx-drm: TODO: Remove LVDS support from missing features list. LVDS Display Bridge is currently supported, so remove it from the missing features list. Signed-off-by: Fabio Estevam Acked-by: Sascha Hauer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/imx-drm/TODO | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/imx-drm/TODO b/drivers/staging/imx-drm/TODO index f80641528f75..9cfa2a7efdc0 100644 --- a/drivers/staging/imx-drm/TODO +++ b/drivers/staging/imx-drm/TODO @@ -10,7 +10,6 @@ TODO: Missing features (not necessarily for moving out of staging): - Add KMS plane support for CRTC driver -- Add LDB (LVDS Display Bridge) support - Add i.MX6 HDMI support - Add support for IC (Image converter) - Add support for CSI (CMOS Sensor interface) From 7c3836a48e318ef8676f43af6632db3f89bf8cc1 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sun, 21 Jul 2013 22:19:42 -0300 Subject: [PATCH 0762/3400] imx-drm: imx-tve: Remove unneeded check for platform_get_resource() As devm_ioremap_resource() is used on probe, there is no need to explicitly check the return value from platform_get_resource(), as this is something that devm_ioremap_resource() takes care by itself. Signed-off-by: Fabio Estevam Acked-by: Philipp Zabel Signed-off-by: Greg Kroah-Hartman --- drivers/staging/imx-drm/imx-tve.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/staging/imx-drm/imx-tve.c b/drivers/staging/imx-drm/imx-tve.c index 0a1c6ab76344..12a3940de695 100644 --- a/drivers/staging/imx-drm/imx-tve.c +++ b/drivers/staging/imx-drm/imx-tve.c @@ -625,11 +625,6 @@ static int imx_tve_probe(struct platform_device *pdev) } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "failed to get memory region\n"); - return -ENOENT; - } - base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(base)) return PTR_ERR(base); From be798b2b13bca5a1b25b56acec60ec42bcc57c50 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sat, 20 Jul 2013 18:22:09 -0300 Subject: [PATCH 0763/3400] imx-drm: ipu-common: Simplify the error path Instead of jumping to goto labels, just return the error code directly. Signed-off-by: Fabio Estevam Acked-by: Sascha Hauer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/imx-drm/ipu-v3/ipu-common.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-common.c b/drivers/staging/imx-drm/ipu-v3/ipu-common.c index e35d0bf03c7b..d06b0c81f397 100644 --- a/drivers/staging/imx-drm/ipu-v3/ipu-common.c +++ b/drivers/staging/imx-drm/ipu-v3/ipu-common.c @@ -1075,16 +1075,14 @@ static int ipu_probe(struct platform_device *pdev) ipu->cpmem_base = devm_ioremap(&pdev->dev, ipu_base + devtype->cpmem_ofs, PAGE_SIZE); - if (!ipu->cm_reg || !ipu->idmac_reg || !ipu->cpmem_base) { - ret = -ENOMEM; - goto failed_ioremap; - } + if (!ipu->cm_reg || !ipu->idmac_reg || !ipu->cpmem_base) + return -ENOMEM; ipu->clk = devm_clk_get(&pdev->dev, "bus"); if (IS_ERR(ipu->clk)) { ret = PTR_ERR(ipu->clk); dev_err(&pdev->dev, "clk_get failed with %d", ret); - goto failed_clk_get; + return ret; } platform_set_drvdata(pdev, ipu); @@ -1134,8 +1132,6 @@ out_failed_reset: ipu_irq_exit(ipu); out_failed_irq: clk_disable_unprepare(ipu->clk); -failed_clk_get: -failed_ioremap: return ret; } From 62645a27ba9b93cf13d505d9ced64171010fb57d Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sat, 20 Jul 2013 18:22:10 -0300 Subject: [PATCH 0764/3400] imx-drm: ipu-common: Check the return value from clk_prepare_enable() clk_prepare_enable() may fail, so let's check its return value and propagate it in the case of error. Signed-off-by: Fabio Estevam Acked-by: Sascha Hauer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/imx-drm/ipu-v3/ipu-common.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-common.c b/drivers/staging/imx-drm/ipu-v3/ipu-common.c index d06b0c81f397..f1299da5ec20 100644 --- a/drivers/staging/imx-drm/ipu-v3/ipu-common.c +++ b/drivers/staging/imx-drm/ipu-v3/ipu-common.c @@ -1087,7 +1087,11 @@ static int ipu_probe(struct platform_device *pdev) platform_set_drvdata(pdev, ipu); - clk_prepare_enable(ipu->clk); + ret = clk_prepare_enable(ipu->clk); + if (ret) { + dev_err(&pdev->dev, "clk_prepare_enable failed: %d\n", ret); + return ret; + } ipu->dev = &pdev->dev; ipu->irq_sync = irq_sync; From 10f2268df80d127d0777dbf5986b58e3956ddb0f Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sat, 20 Jul 2013 18:22:11 -0300 Subject: [PATCH 0765/3400] imx-drm: ipu-common: Add MODULE_ALIAS Add MODULE_ALIAS, so that auto module loading can work. Signed-off-by: Fabio Estevam Acked-by: Sascha Hauer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/imx-drm/ipu-v3/ipu-common.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-common.c b/drivers/staging/imx-drm/ipu-v3/ipu-common.c index f1299da5ec20..ba464e5d9f12 100644 --- a/drivers/staging/imx-drm/ipu-v3/ipu-common.c +++ b/drivers/staging/imx-drm/ipu-v3/ipu-common.c @@ -1163,6 +1163,7 @@ static struct platform_driver imx_ipu_driver = { module_platform_driver(imx_ipu_driver); +MODULE_ALIAS("platform:imx-ipuv3"); MODULE_DESCRIPTION("i.MX IPU v3 driver"); MODULE_AUTHOR("Sascha Hauer "); MODULE_LICENSE("GPL"); From aaba4b58820aebebdee3e3191ef71c11b569c629 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 10 Jul 2013 14:11:45 +0200 Subject: [PATCH 0766/3400] drm/imx: kill firstopen callback This thing seems to do some kind of delayed setup. Really, real kms drivers shouldn't do that at all. Either stuff needs to be dynamically hotplugged or the driver setup sequence needs to be fixed. This patch here just moves the setup at the very end of the driver load callback, with the locking adjusted accordingly. v2: Also move the corresponding put from ->lastclose to ->unload. Cc: Sascha Hauer Signed-off-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/imx-drm/imx-drm-core.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c index 6bc205baa4a5..878f16882107 100644 --- a/drivers/staging/imx-drm/imx-drm-core.c +++ b/drivers/staging/imx-drm/imx-drm-core.c @@ -69,28 +69,20 @@ struct imx_drm_connector { struct module *owner; }; -static int imx_drm_driver_firstopen(struct drm_device *drm) -{ - if (!imx_drm_device_get()) - return -EINVAL; - - return 0; -} - static void imx_drm_driver_lastclose(struct drm_device *drm) { struct imx_drm_device *imxdrm = drm->dev_private; if (imxdrm->fbhelper) drm_fbdev_cma_restore_mode(imxdrm->fbhelper); - - imx_drm_device_put(); } static int imx_drm_driver_unload(struct drm_device *drm) { struct imx_drm_device *imxdrm = drm->dev_private; + imx_drm_device_put(); + drm_mode_config_cleanup(imxdrm->drm); drm_kms_helper_poll_fini(imxdrm->drm); @@ -226,8 +218,6 @@ struct drm_device *imx_drm_device_get(void) struct imx_drm_connector *con; struct imx_drm_crtc *crtc; - mutex_lock(&imxdrm->mutex); - list_for_each_entry(enc, &imxdrm->encoder_list, list) { if (!try_module_get(enc->owner)) { dev_err(imxdrm->dev, "could not get module %s\n", @@ -254,8 +244,6 @@ struct drm_device *imx_drm_device_get(void) imxdrm->references++; - mutex_unlock(&imxdrm->mutex); - return imxdrm->drm; unwind_crtc: @@ -447,6 +435,9 @@ static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags) */ imxdrm->drm->vblank_disable_allowed = 1; + if (!imx_drm_device_get()) + ret = -EINVAL; + ret = 0; err_init: @@ -792,7 +783,6 @@ static struct drm_driver imx_drm_driver = { .driver_features = DRIVER_MODESET | DRIVER_GEM, .load = imx_drm_driver_load, .unload = imx_drm_driver_unload, - .firstopen = imx_drm_driver_firstopen, .lastclose = imx_drm_driver_lastclose, .gem_free_object = drm_gem_cma_free_object, .gem_vm_ops = &drm_gem_cma_vm_ops, From f4616af01813cbf6a2c2aabcedb11c721d5e7680 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Wed, 24 Jul 2013 13:29:22 +0200 Subject: [PATCH 0767/3400] staging: dwc2: Don't touch the dma_mask when dma is disabled There was some code that cleared the dma_mask when dma was disabled in the driver. Given that clearing the mask doesn't actually tell the usb core we're not using dma, and a previous commit explicitely sets the hcd->self.uses_dma value, it seems these values are unneeded and can only potentially cause problems (when reloading a module, for example). Signed-off-by: Matthijs Kooijman Acked-by: Paul Zimmerman Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dwc2/hcd.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/staging/dwc2/hcd.c b/drivers/staging/dwc2/hcd.c index fbacf6a9f72e..32b52ad5f74f 100644 --- a/drivers/staging/dwc2/hcd.c +++ b/drivers/staging/dwc2/hcd.c @@ -2845,9 +2845,6 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq, dev_warn(hsotg->dev, "can't set DMA mask\n"); if (dma_set_coherent_mask(hsotg->dev, DMA_BIT_MASK(32)) < 0) dev_warn(hsotg->dev, "can't set coherent DMA mask\n"); - } else { - dma_set_mask(hsotg->dev, 0); - dma_set_coherent_mask(hsotg->dev, 0); } hcd = usb_create_hcd(&dwc2_hc_driver, hsotg->dev, dev_name(hsotg->dev)); From 5607ce90d727d2aaad93bd72551b97067141d68a Mon Sep 17 00:00:00 2001 From: Jens Frederich Date: Thu, 25 Jul 2013 22:06:32 +0200 Subject: [PATCH 0768/3400] Staging: olpc_dcon: change to msleep to usleep_range The resolution of msleep is related to HZ, so with HZ set to 100 any msleep of less then 10ms will become ~10ms. This is not what we want. Use usleep_range to get more control of what is happening here. Signed-off-by: Jens Frederich Signed-off-by: Greg Kroah-Hartman --- drivers/staging/olpc_dcon/olpc_dcon.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/olpc_dcon/olpc_dcon.c b/drivers/staging/olpc_dcon/olpc_dcon.c index 193e1c68bb45..7c460f2c0d23 100644 --- a/drivers/staging/olpc_dcon/olpc_dcon.c +++ b/drivers/staging/olpc_dcon/olpc_dcon.c @@ -131,13 +131,13 @@ power_up: pr_warn("unable to force dcon to power up: %d!\n", x); return x; } - msleep(10); /* we'll be conservative */ + usleep_range(10000, 11000); /* we'll be conservative */ } pdata->bus_stabilize_wiggle(); for (x = -1, timeout = 50; timeout && x < 0; timeout--) { - msleep(1); + usleep_range(1000, 1100); x = dcon_read(dcon, DCON_REG_ID); } if (x < 0) { From c70bda992c12e593e411c02a52e4bd6985407539 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Fri, 12 Jul 2013 14:20:52 -0400 Subject: [PATCH 0769/3400] staging: zram: Add auto loading of module if user opens /dev/zram. Greg spotted that said driver is not subscribing to the automagic mechanism of auto-loading if a user tries to open /dev/zram. This fixes it. CC: Minchan Kim Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Greg Kroah-Hartman --- drivers/staging/zram/zram_drv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c index 82c7202fd5cc..1b30a5e87c78 100644 --- a/drivers/staging/zram/zram_drv.c +++ b/drivers/staging/zram/zram_drv.c @@ -919,3 +919,4 @@ MODULE_PARM_DESC(num_devices, "Number of zram devices"); MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Nitin Gupta "); MODULE_DESCRIPTION("Compressed RAM Block Device"); +MODULE_ALIAS("devname:zram"); From 8dbc6aa0e84455afcd5f90290e438b36569b4eec Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Tue, 23 Jul 2013 23:07:02 +0100 Subject: [PATCH 0770/3400] staging: vt6656: Remove dead code macro ASSERT ASSERT is always defined as empty macro because VIAWET_DEBUG is never defined. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/baseband.c | 1 - drivers/staging/vt6656/device_cfg.h | 8 -------- drivers/staging/vt6656/dpc.c | 6 ------ drivers/staging/vt6656/main_usb.c | 1 - drivers/staging/vt6656/rxtx.c | 3 --- drivers/staging/vt6656/usbpipe.c | 1 - 6 files changed, 20 deletions(-) diff --git a/drivers/staging/vt6656/baseband.c b/drivers/staging/vt6656/baseband.c index 33fa76759bf1..a14a6a0c1cd2 100644 --- a/drivers/staging/vt6656/baseband.c +++ b/drivers/staging/vt6656/baseband.c @@ -680,7 +680,6 @@ BBuGetFrameTime( unsigned int uRate = 0; if (uRateIdx > RATE_54M) { - ASSERT(0); return 0; } diff --git a/drivers/staging/vt6656/device_cfg.h b/drivers/staging/vt6656/device_cfg.h index ea66b975fa5b..ad1fbf6fab3d 100644 --- a/drivers/staging/vt6656/device_cfg.h +++ b/drivers/staging/vt6656/device_cfg.h @@ -83,16 +83,8 @@ typedef enum _chip_type { } CHIP_TYPE, *PCHIP_TYPE; #ifdef VIAWET_DEBUG -#define ASSERT(x) { \ - if (!(x)) { \ - printk(KERN_ERR "assertion %s failed: file %s line %d\n", #x, \ - __FUNCTION__, __LINE__);\ - *(int *) 0 = 0; \ - } \ -} #define DBG_PORT80(value) outb(value, 0x80) #else -#define ASSERT(x) #define DBG_PORT80(value) #endif diff --git a/drivers/staging/vt6656/dpc.c b/drivers/staging/vt6656/dpc.c index 7ec166a2ac81..4bc362f530a7 100644 --- a/drivers/staging/vt6656/dpc.c +++ b/drivers/staging/vt6656/dpc.c @@ -314,7 +314,6 @@ int RXbBulkInProcessData(struct vnt_private *pDevice, PRCB pRCB, (BytesToIndicate < (*pwPLCP_Length)) ) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Wrong PLCP Length %x\n", (int) *pwPLCP_Length); - ASSERT(0); return false; } for ( ii=RATE_1M;iiNumRecvFreeList != 0) ) { pRCB = pDevice->FirstRecvFreeList; pDevice->NumRecvFreeList--; - ASSERT(pRCB);// cannot be NULL DequeueRCB(pDevice->FirstRecvFreeList, pDevice->LastRecvFreeList); ntStatus = PIPEnsBulkInUsbRead(pDevice, pRCB); } @@ -1362,9 +1360,6 @@ void RXvFreeRCB(PRCB pRCB, int bReAllocSkb) DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->RXvFreeRCB\n"); - ASSERT(!pRCB->Ref); // should be 0 - ASSERT(pRCB->pDevice); // shouldn't be NULL - if (bReAllocSkb == false) { kfree_skb(pRCB->skb); bReAllocSkb = true; @@ -1411,7 +1406,6 @@ void RXvMngWorkItem(struct vnt_private *pDevice) if(!pRCB){ break; } - ASSERT(pRCB);// cannot be NULL pRxPacket = &(pRCB->sMngPacket); vMgrRxManagePacket(pDevice, &pDevice->vnt_mgmt, pRxPacket); pRCB->Ref--; diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index 3a3fdc58b6da..0c9e60fd57f7 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -925,7 +925,6 @@ int device_alloc_frag_buf(struct vnt_private *pDevice, pDeF->skb = dev_alloc_skb((int)pDevice->rx_buf_sz); if (pDeF->skb == NULL) return false; - ASSERT(pDeF->skb); pDeF->skb->dev = pDevice->dev; return true; diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index 9bf2f8d562c3..00e0c7118776 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -538,7 +538,6 @@ static u32 s_uGetDataDuration(struct vnt_private *pDevice, u8 byDurType, break; } - ASSERT(false); return 0; } @@ -1475,8 +1474,6 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType, memcpy((pbyPayloadHead + cb802_1_H_len), ((u8 *)psEthHeader) + ETH_HLEN, uSkbPacketLen - ETH_HLEN); } - ASSERT(uLength == cbNdisBodySize); - if ((bNeedEncryption == true) && (pTransmitKey != NULL) && (pTransmitKey->byCipherSuite == KEY_CTL_TKIP)) { /////////////////////////////////////////////////////////////////// diff --git a/drivers/staging/vt6656/usbpipe.c b/drivers/staging/vt6656/usbpipe.c index 098be609107c..9b9122dc68cd 100644 --- a/drivers/staging/vt6656/usbpipe.c +++ b/drivers/staging/vt6656/usbpipe.c @@ -635,7 +635,6 @@ static void s_nsBulkOutIoCompleteWrite(struct urb *urb) // The context given to IoSetCompletionRoutine is an USB_CONTEXT struct // pContext = (PUSB_SEND_CONTEXT) urb->context; - ASSERT( NULL != pContext ); pDevice = pContext->pDevice; ContextType = pContext->Type; From f830a01339afe35b46c270faef22c86ad5622912 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Tue, 23 Jul 2013 23:10:59 +0100 Subject: [PATCH 0771/3400] staging: vt6656: remove dead code DBG_PORT80/VIAWET_DEBUG DBG_PORT80 is always defined as empty macro because VIAWET_DEBUG is never defined. Remove it and VIAWET_DEBUG. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/device_cfg.h | 6 ------ drivers/staging/vt6656/wmgr.c | 2 -- 2 files changed, 8 deletions(-) diff --git a/drivers/staging/vt6656/device_cfg.h b/drivers/staging/vt6656/device_cfg.h index ad1fbf6fab3d..a97f7bb13db8 100644 --- a/drivers/staging/vt6656/device_cfg.h +++ b/drivers/staging/vt6656/device_cfg.h @@ -82,10 +82,4 @@ typedef enum _chip_type { VT3184 = 1 } CHIP_TYPE, *PCHIP_TYPE; -#ifdef VIAWET_DEBUG -#define DBG_PORT80(value) outb(value, 0x80) -#else -#define DBG_PORT80(value) -#endif - #endif diff --git a/drivers/staging/vt6656/wmgr.c b/drivers/staging/vt6656/wmgr.c index 6d1ff5eeafa9..b6cbd138a2b4 100644 --- a/drivers/staging/vt6656/wmgr.c +++ b/drivers/staging/vt6656/wmgr.c @@ -751,7 +751,6 @@ static void s_vMgrRxAssocResponse(struct vnt_private *pDevice, || (sFrame.pwStatus == NULL) || (sFrame.pwAid == NULL) || (sFrame.pSuppRates == NULL)) { - DBG_PORT80(0xCC); return; } @@ -3750,7 +3749,6 @@ static void s_vMgrRxProbeResponse(struct vnt_private *pDevice, DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Probe resp:Fail addr:[%p]\n", pRxPacket->p80211Header); - DBG_PORT80(0xCC); return; } From 8079154a1d7c724569d5e3cd2af147a8eb3867c3 Mon Sep 17 00:00:00 2001 From: Rupesh Gujare Date: Wed, 24 Jul 2013 15:06:46 +0100 Subject: [PATCH 0772/3400] staging: ozwpan: Fix coding style. This patch fixes coding style issues reported by Dan here:- http://driverdev.linuxdriverproject.org/pipermail/driverdev-devel/2012-June/027767.html Reported-by: Dan Carpenter Signed-off-by: Rupesh Gujare Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ozwpan/ozcdev.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/staging/ozwpan/ozcdev.c b/drivers/staging/ozwpan/ozcdev.c index 3e29760ba77e..73b582cdf424 100644 --- a/drivers/staging/ozwpan/ozcdev.c +++ b/drivers/staging/ozwpan/ozcdev.c @@ -333,10 +333,11 @@ int oz_cdev_register(void) { int err; struct device *dev; + memset(&g_cdev, 0, sizeof(g_cdev)); err = alloc_chrdev_region(&g_cdev.devnum, 0, 1, "ozwpan"); if (err < 0) - goto out3; + return err; oz_dbg(ON, "Alloc dev number %d:%d\n", MAJOR(g_cdev.devnum), MINOR(g_cdev.devnum)); cdev_init(&g_cdev.cdev, &oz_fops); @@ -347,26 +348,26 @@ int oz_cdev_register(void) err = cdev_add(&g_cdev.cdev, g_cdev.devnum, 1); if (err < 0) { oz_dbg(ON, "Failed to add cdev\n"); - goto out2; + goto unregister; } g_oz_class = class_create(THIS_MODULE, "ozmo_wpan"); if (IS_ERR(g_oz_class)) { oz_dbg(ON, "Failed to register ozmo_wpan class\n"); err = PTR_ERR(g_oz_class); - goto out1; + goto delete; } dev = device_create(g_oz_class, NULL, g_cdev.devnum, NULL, "ozwpan"); if (IS_ERR(dev)) { oz_dbg(ON, "Failed to create sysfs entry for cdev\n"); err = PTR_ERR(dev); - goto out1; + goto delete; } return 0; -out1: + +delete: cdev_del(&g_cdev.cdev); -out2: +unregister: unregister_chrdev_region(g_cdev.devnum, 1); -out3: return err; } /*------------------------------------------------------------------------------ From 48bae0507410a7b8bbedec6d790c9b85c5a6391f Mon Sep 17 00:00:00 2001 From: Eli Billauer Date: Mon, 24 Jun 2013 18:55:47 +0300 Subject: [PATCH 0773/3400] staging: New driver: Xillybus generic interface for FPGA This is the driver for Xillybus, which is a general-purpose interface for data communication with FPGAs (programmable logic). Please refer to the README included in this patch for a detailed explanation. It was previously submitted for misc-devices, but it appears like noone's willing to review the code (which I can understand, given its magnitude). Hence submitted as a staging driver. Signed-off-by: Eli Billauer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/Kconfig | 2 + drivers/staging/Makefile | 1 + drivers/staging/xillybus/Kconfig | 35 + drivers/staging/xillybus/Makefile | 7 + drivers/staging/xillybus/README | 403 ++++ drivers/staging/xillybus/TODO | 5 + drivers/staging/xillybus/xillybus.h | 185 ++ drivers/staging/xillybus/xillybus_core.c | 2345 ++++++++++++++++++++++ drivers/staging/xillybus/xillybus_of.c | 210 ++ drivers/staging/xillybus/xillybus_pcie.c | 260 +++ 10 files changed, 3453 insertions(+) create mode 100644 drivers/staging/xillybus/Kconfig create mode 100644 drivers/staging/xillybus/Makefile create mode 100644 drivers/staging/xillybus/README create mode 100644 drivers/staging/xillybus/TODO create mode 100644 drivers/staging/xillybus/xillybus.h create mode 100644 drivers/staging/xillybus/xillybus_core.c create mode 100644 drivers/staging/xillybus/xillybus_of.c create mode 100644 drivers/staging/xillybus/xillybus_pcie.c diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index d55bc344c5ea..d036cd29bcd6 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -144,4 +144,6 @@ source "drivers/staging/lustre/Kconfig" source "drivers/staging/btmtk_usb/Kconfig" +source "drivers/staging/xillybus/Kconfig" + endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index c23cf3b60c34..7fe578ea1708 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -64,3 +64,4 @@ obj-$(CONFIG_GOLDFISH) += goldfish/ obj-$(CONFIG_USB_DWC2) += dwc2/ obj-$(CONFIG_LUSTRE_FS) += lustre/ obj-$(CONFIG_USB_BTMTK) += btmtk_usb/ +obj-$(CONFIG_XILLYBUS) += xillybus/ diff --git a/drivers/staging/xillybus/Kconfig b/drivers/staging/xillybus/Kconfig new file mode 100644 index 000000000000..58fd5488fefb --- /dev/null +++ b/drivers/staging/xillybus/Kconfig @@ -0,0 +1,35 @@ +# +# Xillybus devices +# + +config XILLYBUS + tristate "Xillybus generic FPGA interface" + depends on PCI || (OF_ADDRESS && OF_DEVICE && OF_IRQ) + default n + help + Xillybus is a generic interface for peripherals designed on + programmable logic (FPGA). The driver probes the hardware for + its capabilities, and creates device files accordingly. + + If unsure, say N. + +if XILLYBUS + +config XILLYBUS_PCIE + tristate "Xillybus over PCIe" + depends on XILLYBUS && PCI + default n + help + Set to M if you want Xillybus to use PCI Express for communicating + with the FPGA. + +config XILLYBUS_OF + tristate "Xillybus over Device Tree" + depends on XILLYBUS && OF_ADDRESS && OF_DEVICE && OF_IRQ + default n + help + Set to M if you want Xillybus to find its resources from the + Open Firmware Flattened Device Tree. If the target is an embedded + system, say M. + +endif # if XILLYBUS diff --git a/drivers/staging/xillybus/Makefile b/drivers/staging/xillybus/Makefile new file mode 100644 index 000000000000..b68b7ebfd381 --- /dev/null +++ b/drivers/staging/xillybus/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for Xillybus driver +# + +obj-$(CONFIG_XILLYBUS) += xillybus_core.o +obj-$(CONFIG_XILLYBUS_PCIE) += xillybus_pcie.o +obj-$(CONFIG_XILLYBUS_OF) += xillybus_of.o diff --git a/drivers/staging/xillybus/README b/drivers/staging/xillybus/README new file mode 100644 index 000000000000..d2d848ae3169 --- /dev/null +++ b/drivers/staging/xillybus/README @@ -0,0 +1,403 @@ + + ========================================== + Xillybus driver for generic FPGA interface + ========================================== + +Author: Eli Billauer, Xillybus Ltd. (http://xillybus.com) +Email: eli.billauer@gmail.com or as advertised on Xillybus' site. + +Contents: + + - Introduction + -- Background + -- Xillybus Overview + + - Usage + -- User interface + -- Synchronization + -- Seekable pipes + +- Internals + -- Source code organization + -- Pipe attributes + -- Host never reads from the FPGA + -- Channels, pipes, and the message channel + -- Data streaming + -- Data granularity + -- Probing + -- Buffer allocation + -- Memory management + -- The "nonempty" message (supporting poll) + + +INTRODUCTION +============ + +Background +---------- + +An FPGA (Field Programmable Gate Array) is a piece of logic hardware, which +can be programmed to become virtually anything that is usually found as a +dedicated chipset: For instance, a display adapter, network interface card, +or even a processor with its peripherals. FPGAs are the LEGO of hardware: +Based upon certain building blocks, you make your own toys the way you like +them. It's usually pointless to reimplement something that is already +available on the market as a chipset, so FPGAs are mostly used when some +special functionality is needed, and the production volume is relatively low +(hence not justifying the development of an ASIC). + +The challenge with FPGAs is that everything is implemented at a very low +level, even lower than assembly language. In order to allow FPGA designers to +focus on their specific project, and not reinvent the wheel over and over +again, pre-designed building blocks, IP cores, are often used. These are the +FPGA parallels of library functions. IP cores may implement certain +mathematical functions, a functional unit (e.g. a USB interface), an entire +processor (e.g. ARM) or anything that might come handy. Think of them as a +building block, with electrical wires dangling on the sides for connection to +other blocks. + +One of the daunting tasks in FPGA design is communicating with a fullblown +operating system (actually, with the processor running it): Implementing the +low-level bus protocol and the somewhat higher-level interface with the host +(registers, interrupts, DMA etc.) is a project in itself. When the FPGA's +function is a well-known one (e.g. a video adapter card, or a NIC), it can +make sense to design the FPGA's interface logic specifically for the project. +A special driver is then written to present the FPGA as a well-known interface +to the kernel and/or user space. In that case, there is no reason to treat the +FPGA differently than any device on the bus. + +It's however common that the desired data communication doesn't fit any well- +known peripheral function. Also, the effort of designing an elegant +abstraction for the data exchange is often considered too big. In those cases, +a quicker and possibly less elegant solution is sought: The driver is +effectively written as a user space program, leaving the kernel space part +with just elementary data transport. This still requires designing some +interface logic for the FPGA, and write a simple ad-hoc driver for the kernel. + +Xillybus Overview +----------------- + +Xillybus is an IP core and a Linux driver. Together, they form a kit for +elementary data transport between an FPGA and the host, providing pipe-like +data streams with a straightforward user interface. It's intended as a low- +effort solution for mixed FPGA-host projects, for which it makes sense to +have the project-specific part of the driver running in a user-space program. + +Since the communication requirements may vary significantly from one FPGA +project to another (the number of data pipes needed in each direction and +their attributes), there isn't one specific chunk of logic being the Xillybus +IP core. Rather, the IP core is configured and built based upon a +specification given by its end user. + +Xillybus presents independent data streams, which resemble pipes or TCP/IP +communication to the user. At the host side, a character device file is used +just like any pipe file. On the FPGA side, hardware FIFOs are used to stream +the data. This is contrary to a common method of communicating through fixed- +sized buffers (even though such buffers are used by Xillybus under the hood). +There may be more than a hundred of these streams on a single IP core, but +also no more than one, depending on the configuration. + +In order to ease the deployment of the Xillybus IP core, it contains a simple +data structure which completely defines the core's configuration. The Linux +driver fetches this data structure during its initialization process, and sets +up the DMA buffers and character devices accordingly. As a result, a single +driver is used to work out of the box with any Xillybus IP core. + +The data structure just mentioned should not be confused with PCI's +configuration space or the Flattened Device Tree. + +USAGE +===== + +User interface +-------------- + +On the host, all interface with Xillybus is done through /dev/xillybus_* +device files, which are generated automatically as the drivers loads. The +names of these files depend on the IP core that is loaded in the FPGA (see +Probing below). To communicate with the FPGA, open the device file that +corresponds to the hardware FIFO you want to send data or receive data from, +and use plain write() or read() calls, just like with a regular pipe. In +particular, it makes perfect sense to go: + +$ cat mydata > /dev/xillybus_thisfifo + +$ cat /dev/xillybus_thatfifo > hisdata + +possibly pressing CTRL-C as some stage, even though the xillybus_* pipes have +the capability to send an EOF (but may not use it). + +The driver and hardware are designed to behave sensibly as pipes, including: + +* Supporting non-blocking I/O (by setting O_NONBLOCK on open() ). + +* Supporting poll() and select(). + +* Being bandwidth efficient under load (using DMA) but also handle small + pieces of data sent across (like TCP/IP) by autoflushing. + +A device file can be read only, write only or bidirectional. Bidirectional +device files are treated like two independent pipes (except for sharing a +"channel" structure in the implementation code). + +Synchronization +--------------- + +Xillybus pipes are configured (on the IP core) to be either synchronous or +asynchronous. For a synchronous pipe, write() returns successfully only after +some data has been submitted and acknowledged by the FPGA. This slows down +bulk data transfers, and is nearly impossible for use with streams that +require data at a constant rate: There is no data transmitted to the FPGA +between write() calls, in particular when the process loses the CPU. + +When a pipe is configured asynchronous, write() returns if there was enough +room in the buffers to store any of the data in the buffers. + +For FPGA to host pipes, asynchronous pipes allow data transfer from the FPGA +as soon as the respective device file is opened, regardless of if the data +has been requested by a read() call. On synchronous pipes, only the amount +of data requested by a read() call is transmitted. + +In summary, for synchronous pipes, data between the host and FPGA is +transmitted only to satisfy the read() or write() call currently handled +by the driver, and those calls wait for the transmission to complete before +returning. + +Note that the synchronization attribute has nothing to do with the possibility +that read() or write() completes less bytes than requested. There is a +separate configuration flag ("allowpartial") that determines whether such a +partial completion is allowed. + +Seekable pipes +-------------- + +A synchronous pipe can be configured to have the stream's position exposed +to the user logic at the FPGA. Such a pipe is also seekable on the host API. +With this feature, a memory or register interface can be attached on the +FPGA side to the seekable stream. Reading or writing to a certain address in +the attached memory is done by seeking to the desired address, and calling +read() or write() as required. + + +INTERNALS +========= + +Source code organization +------------------------ + +The Xillybus driver consists of a core module, xillybus_core.c, and modules +that depend on the specific bus interface (xillybus_of.c and xillybus_pcie.c). + +The bus specific modules are those probed when a suitable device is found by +the kernel. Since the DMA mapping and synchronization functions, which are bus +dependent by their nature, are used by the core module, a +xilly_endpoint_hardware structure is passed to the core module on +initialization. This structure is populated with pointers to wrapper functions +which execute the DMA-related operations on the bus. + +Pipe attributes +--------------- + +Each pipe has a number of attributes which are set when the FPGA component +(IP core) is built. They are fetched from the IDT (the data structure which +defines the core's configuration, see Probing below) by xilly_setupchannels() +in xillybus_core.c as follows: + +* is_writebuf: The pipe's direction. A non-zero value means it's an FPGA to + host pipe (the FPGA "writes"). + +* channelnum: The pipe's identification number in communication between the + host and FPGA. + +* format: The underlying data width. See Data Granularity below. + +* allowpartial: A non-zero value means that a read() or write() (whichever + applies) may return with less than the requested number of bytes. The common + choice is a non-zero value, to match standard UNIX behavior. + +* synchronous: A non-zero value means that the pipe is synchronous. See + Syncronization above. + +* bufsize: Each DMA buffer's size. Always a power of two. + +* bufnum: The number of buffers allocated for this pipe. Always a power of two. + +* exclusive_open: A non-zero value forces exclusive opening of the associated + device file. If the device file is bidirectional, and already opened only in + one direction, the opposite direction may be opened once. + +* seekable: A non-zero value indicates that the pipe is seekable. See + Seekable pipes above. + +* supports_nonempty: A non-zero value (which is typical) indicates that the + hardware will send the messages that are necessary to support select() and + poll() for this pipe. + +Host never reads from the FPGA +------------------------------ + +Even though PCI Express is hotpluggable in general, a typical motherboard +doesn't expect a card to go away all of the sudden. But since the PCIe card +is based upon reprogrammable logic, a sudden disappearance from the bus is +quite likely as a result of an accidental reprogramming of the FPGA while the +host is up. In practice, nothing happens immediately in such a situation. But +if the host attempts to read from an address that is mapped to the PCI Express +device, that leads to an immediate freeze of the system on some motherboards, +even though the PCIe standard requires a graceful recovery. + +In order to avoid these freezes, the Xillybus driver refrains completely from +reading from the device's register space. All communication from the FPGA to +the host is done through DMA. In particular, the Interrupt Service Routine +doesn't follow the common practice of checking a status register when it's +invoked. Rather, the FPGA prepares a small buffer which contains short +messages, which inform the host what the interrupt was about. + +This mechanism is used on non-PCIe buses as well for the sake of uniformity. + + +Channels, pipes, and the message channel +---------------------------------------- + +Each of the (possibly bidirectional) pipes presented to the user is allocated +a data channel between the FPGA and the host. The distinction between channels +and pipes is necessary only because of channel 0, which is used for interrupt- +related messages from the FPGA, and has no pipe attached to it. + +Data streaming +-------------- + +Even though a non-segmented data stream is presented to the user at both +sides, the implementation relies on a set of DMA buffers which is allocated +for each channel. For the sake of illustration, let's take the FPGA to host +direction: As data streams into the respective channel's interface in the +FPGA, the Xillybus IP core writes it to one of the DMA buffers. When the +buffer is full, the FPGA informs the host about that (appending a +XILLYMSG_OPCODE_RELEASEBUF message channel 0 and sending an interrupt if +necessary). The host responds by making the data available for reading through +the character device. When all data has been read, the host writes on the +the FPGA's buffer control register, allowing the buffer's overwriting. Flow +control mechanisms exist on both sides to prevent underflows and overflows. + +This is not good enough for creating a TCP/IP-like stream: If the data flow +stops momentarily before a DMA buffer is filled, the intuitive expectation is +that the partial data in buffer will arrive anyhow, despite the buffer not +being completed. This is implemented by adding a field in the +XILLYMSG_OPCODE_RELEASEBUF message, through which the FPGA informs not just +which buffer is submitted, but how much data it contains. + +But the FPGA will submit a partially filled buffer only if directed to do so +by the host. This situation occurs when the read() method has been blocking +for XILLY_RX_TIMEOUT jiffies (currently 10 ms), after which the host commands +the FPGA to submit a DMA buffer as soon as it can. This timeout mechanism +balances between bus bandwidth efficiency (preventing a lot of partially +filled buffers being sent) and a latency held fairly low for tails of data. + +A similar setting is used in the host to FPGA direction. The handling of +partial DMA buffers is somewhat different, though. The user can tell the +driver to submit all data it has in the buffers to the FPGA, by issuing a +write() with the byte count set to zero. This is similar to a flush request, +but it doesn't block. There is also an autoflushing mechanism, which triggers +an equivalent flush roughly XILLY_RX_TIMEOUT jiffies after the last write(). +This allows the user to be oblivious about the underlying buffering mechanism +and yet enjoy a stream-like interface. + +Note that the issue of partial buffer flushing is irrelevant for pipes having +the "synchronous" attribute nonzero, since synchronous pipes don't allow data +to lay around in the DMA buffers between read() and write() anyhow. + +Data granularity +---------------- + +The data arrives or is sent at the FPGA as 8, 16 or 32 bit wide words, as +configured by the "format" attribute. Whenever possible, the driver attempts +to hide this when the pipe is accessed differently from its natural alignment. +For example, reading single bytes from a pipe with 32 bit granularity works +with no issues. Writing single bytes to pipes with 16 or 32 bit granularity +will also work, but the driver can't send partially completed words to the +FPGA, so the transmission of up to one word may be held until it's fully +occupied with user data. + +This somewhat complicates the handling of host to FPGA streams, because +when a buffer is flushed, it may contain up to 3 bytes don't form a word in +the FPGA, and hence can't be sent. To prevent loss of data, these leftover +bytes need to be moved to the next buffer. The parts in xillybus_core.c +that mention "leftovers" in some way are related to this complication. + +Probing +------- + +As mentioned earlier, the number of pipes that are created when the driver +loads and their attributes depend on the Xillybus IP core in the FPGA. During +the driver's initialization, a blob containing configuration info, the +Interface Description Table (IDT), is sent from the FPGA to the host. The +bootstrap process is done in three phases: + +1. Acquire the length of the IDT, so a buffer can be allocated for it. This + is done by sending a quiesce command to the device, since the acknowledge + for this command contains the IDT's buffer length. + +2. Acquire the IDT itself. + +3. Create the interfaces according to the IDT. + +Buffer allocation +----------------- + +In order to simplify the logic that prevents illegal boundary crossings of +PCIe packets, the following rule applies: If a buffer is smaller than 4kB, +it must not cross a 4kB boundary. Otherwise, it must be 4kB aligned. The +xilly_setupchannels() functions allocates these buffers by requesting whole +pages from the kernel, and diving them into DMA buffers as necessary. Since +all buffers' sizes are powers of two, it's possible to pack any set of such +buffers, with a maximal waste of one page of memory. + +All buffers are allocated when the driver is loaded. This is necessary, +since large continuous physical memory segments are sometimes requested, +which are more likely to be available when the system is freshly booted. + +The allocation of buffer memory takes place in the same order they appear in +the IDT. The driver relies on a rule that the pipes are sorted with decreasing +buffer size in the IDT. If a requested buffer is larger or equal to a page, +the necessary number of pages is requested from the kernel, and these are +used for this buffer. If the requested buffer is smaller than a page, one +single page is requested from the kernel, and that page is partially used. +Or, if there already is a partially used page at hand, the buffer is packed +into that page. It can be shown that all pages requested from the kernel +(except possibly for the last) are 100% utilized this way. + +Memory management +----------------- + +The tricky part about the buffer allocation procedure described above is +freeing and unmapping the buffers, in particular if something goes wrong in +the middle, and the allocations need to be rolled back. The three-stage +probing procedure makes this even more crucial, since temporary buffers are +set up and mapped in the first of its two stages. + +To keep the code clean from complicated and bug-prone memory release routines, +there are special routines for allocating memory. For example, instead of +calling kzalloc, there's + +void *xilly_malloc(struct xilly_cleanup *mem, size_t size) + +which effectively allocates a zeroed buffer of size "size". Its first +argument, "mem", is where this allocation is enlisted, so that it's released +when xillybus_do_cleanup() is called with the same "mem" structure. + +Two other functions enlist allocations in this structure: xilly_pagealloc() +for page allocations and xilly_map_single_*() for DMA mapping. + +The "nonempty" message (supporting poll) +--------------------------------------- + +In order to support the "poll" method (and hence select() ), there is a small +catch regarding the FPGA to host direction: The FPGA may have filled a DMA +buffer with some data, but not submitted that buffer. If the host waited for +the buffer's submission by the FPGA, there would be a possibility that the +FPGA side has sent data, but a select() call would still block, because the +host has not received any notification about this. This is solved with +XILLYMSG_OPCODE_NONEMPTY messages sent by the FPGA when a channel goes from +completely empty to containing some data. + +These messages are used only to support poll() and select(). The IP core can +be configured not to send them for a slight reduction of bandwidth. diff --git a/drivers/staging/xillybus/TODO b/drivers/staging/xillybus/TODO new file mode 100644 index 000000000000..95cfe2f62fcd --- /dev/null +++ b/drivers/staging/xillybus/TODO @@ -0,0 +1,5 @@ +TODO: +- have the driver reviewed + +Please send any patches and/or comments to Eli Billauer, +. diff --git a/drivers/staging/xillybus/xillybus.h b/drivers/staging/xillybus/xillybus.h new file mode 100644 index 000000000000..c260ebcc6c4d --- /dev/null +++ b/drivers/staging/xillybus/xillybus.h @@ -0,0 +1,185 @@ +/* + * linux/drivers/misc/xillybus.h + * + * Copyright 2011 Xillybus Ltd, http://xillybus.com + * + * Header file for the Xillybus FPGA/host framework. + * + * This program is free software; you can redistribute it and/or modify + * it under the smems of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + */ + +#ifndef __XILLYBUS_H +#define __XILLYBUS_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +char xillyname[] = "xillybus"; + +struct xilly_endpoint_hardware; + +struct xilly_page { + struct list_head node; + unsigned long addr; + unsigned int order; +}; + +struct xilly_dma { + struct list_head node; + struct pci_dev *pdev; + struct device *dev; + dma_addr_t dma_addr; + size_t size; + int direction; +}; + +struct xilly_buffer { + void *addr; + dma_addr_t dma_addr; + int end_offset; /* Counting elements, not bytes */ +}; + +struct xilly_cleanup { + struct list_head to_kfree; + struct list_head to_pagefree; + struct list_head to_unmap; +}; + +struct xilly_idt_handle { + unsigned char *chandesc; + unsigned char *idt; + int entries; +}; + +/* + * Read-write confusion: wr_* and rd_* notation sticks to FPGA view, so + * wr_* buffers are those consumed by read(), since the FPGA writes to them + * and vice versa. + */ + +struct xilly_channel { + struct xilly_endpoint *endpoint; + int chan_num; + int log2_element_size; + int seekable; + + struct xilly_buffer **wr_buffers; /* FPGA writes, driver reads! */ + int num_wr_buffers; + unsigned int wr_buf_size; /* In bytes */ + int wr_fpga_buf_idx; + int wr_host_buf_idx; + int wr_host_buf_pos; + int wr_empty; + int wr_ready; /* Significant only when wr_empty == 1 */ + int wr_sleepy; + int wr_eof; + int wr_hangup; + spinlock_t wr_spinlock; + struct mutex wr_mutex; + wait_queue_head_t wr_wait; + wait_queue_head_t wr_ready_wait; + int wr_ref_count; + int wr_synchronous; + int wr_allow_partial; + int wr_exclusive_open; + int wr_supports_nonempty; + + struct xilly_buffer **rd_buffers; /* FPGA reads, driver writes! */ + int num_rd_buffers; + unsigned int rd_buf_size; /* In bytes */ + int rd_fpga_buf_idx; + int rd_host_buf_pos; + int rd_host_buf_idx; + int rd_full; + spinlock_t rd_spinlock; + struct mutex rd_mutex; + wait_queue_head_t rd_wait; + int rd_ref_count; + int rd_allow_partial; + int rd_synchronous; + int rd_exclusive_open; + struct delayed_work rd_workitem; + unsigned char rd_leftovers[4]; +}; + +struct xilly_endpoint { + /* + * One of pdev and dev is always NULL, and the other is a valid + * pointer, depending on the type of device + */ + struct pci_dev *pdev; + struct device *dev; + struct resource res; /* OF devices only */ + struct xilly_endpoint_hardware *ephw; + + struct list_head ep_list; + int dma_using_dac; /* =1 if 64-bit DMA is used, =0 otherwise. */ + u32 *registers; + int fatal_error; + + struct mutex register_mutex; + wait_queue_head_t ep_wait; + + /* List of memory allocations, to make release easy */ + struct xilly_cleanup cleanup; + + /* Channels and message handling */ + struct cdev cdev; + + int major; + int lowest_minor; /* Highest minor = lowest_minor + num_channels - 1 */ + + int num_channels; /* EXCLUDING message buffer */ + struct xilly_channel **channels; + int msg_counter; + int failed_messages; + int idtlen; + + u32 *msgbuf_addr; + dma_addr_t msgbuf_dma_addr; + unsigned int msg_buf_size; +}; + +struct xilly_endpoint_hardware { + struct module *owner; + void (*sync_single_for_cpu)(struct xilly_endpoint *, + dma_addr_t, + size_t, + int); + void (*sync_single_for_device)(struct xilly_endpoint *, + dma_addr_t, + size_t, + int); + dma_addr_t (*map_single)(struct xilly_cleanup *, + struct xilly_endpoint *, + void *, + size_t, + int); + void (*unmap_single)(struct xilly_dma *entry); +}; + +irqreturn_t xillybus_isr(int irq, void *data); + +void xillybus_do_cleanup(struct xilly_cleanup *mem, + struct xilly_endpoint *endpoint); + +struct xilly_endpoint *xillybus_init_endpoint(struct pci_dev *pdev, + struct device *dev, + struct xilly_endpoint_hardware + *ephw); + +int xillybus_endpoint_discovery(struct xilly_endpoint *endpoint); + +void xillybus_endpoint_remove(struct xilly_endpoint *endpoint); + +#endif /* __XILLYBUS_H */ diff --git a/drivers/staging/xillybus/xillybus_core.c b/drivers/staging/xillybus/xillybus_core.c new file mode 100644 index 000000000000..dd0a71c6b518 --- /dev/null +++ b/drivers/staging/xillybus/xillybus_core.c @@ -0,0 +1,2345 @@ +/* + * linux/drivers/misc/xillybus_core.c + * + * Copyright 2011 Xillybus Ltd, http://xillybus.com + * + * Driver for the Xillybus FPGA/host framework. + * + * This driver interfaces with a special IP core in an FPGA, setting up + * a pipe between a hardware FIFO in the programmable logic and a device + * file in the host. The number of such pipes and their attributes are + * set up on the logic. This driver detects these automatically and + * creates the device files accordingly. + * + * This program is free software; you can redistribute it and/or modify + * it under the smems of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "xillybus.h" + +MODULE_DESCRIPTION("Xillybus core functions"); +MODULE_AUTHOR("Eli Billauer, Xillybus Ltd."); +MODULE_VERSION("1.07"); +MODULE_ALIAS("xillybus_core"); +MODULE_LICENSE("GPL v2"); + +/* General timeout is 100 ms, rx timeout is 10 ms */ +#define XILLY_RX_TIMEOUT (10*HZ/1000) +#define XILLY_TIMEOUT (100*HZ/1000) + +#define fpga_msg_ctrl_reg 0x0002 +#define fpga_dma_control_reg 0x0008 +#define fpga_dma_bufno_reg 0x0009 +#define fpga_dma_bufaddr_lowaddr_reg 0x000a +#define fpga_dma_bufaddr_highaddr_reg 0x000b +#define fpga_buf_ctrl_reg 0x000c +#define fpga_buf_offset_reg 0x000d +#define fpga_endian_reg 0x0010 + +#define XILLYMSG_OPCODE_RELEASEBUF 1 +#define XILLYMSG_OPCODE_QUIESCEACK 2 +#define XILLYMSG_OPCODE_FIFOEOF 3 +#define XILLYMSG_OPCODE_FATAL_ERROR 4 +#define XILLYMSG_OPCODE_NONEMPTY 5 + +static struct class *xillybus_class; + +/* + * ep_list_lock is the last lock to be taken; No other lock requests are + * allowed while holding it. It merely protects list_of_endpoints, and not + * the endpoints listed in it. + */ + +static LIST_HEAD(list_of_endpoints); +static struct mutex ep_list_lock; +struct workqueue_struct *xillybus_wq; + +/* + * Locking scheme: Mutexes protect invocations of character device methods. + * If both locks are taken, wr_mutex is taken first, rd_mutex second. + * + * wr_spinlock protects wr_*_buf_idx, wr_empty, wr_sleepy, wr_ready and the + * buffers' end_offset fields against changes made by IRQ handler (and in + * theory, other file request handlers, but the mutex handles that). Nothing + * else. + * They are held for short direct memory manipulations. Needless to say, + * no mutex locking is allowed when a spinlock is held. + * + * rd_spinlock does the same with rd_*_buf_idx, rd_empty and end_offset. + * + * register_mutex is endpoint-specific, and is held when non-atomic + * register operations are performed. wr_mutex and rd_mutex may be + * held when register_mutex is taken, but none of the spinlocks. Note that + * register_mutex doesn't protect against sporadic buf_ctrl_reg writes + * which are unrelated to buf_offset_reg, since they are harmless. + * + * Blocking on the wait queues is allowed with mutexes held, but not with + * spinlocks. + * + * Only interruptible blocking is allowed on mutexes and wait queues. + * + * All in all, the locking order goes (with skips allowed, of course): + * wr_mutex -> rd_mutex -> register_mutex -> wr_spinlock -> rd_spinlock + */ + +static void malformed_message(u32 *buf) +{ + int opcode; + int msg_channel, msg_bufno, msg_data, msg_dir; + + opcode = (buf[0] >> 24) & 0xff; + msg_dir = buf[0] & 1; + msg_channel = (buf[0] >> 1) & 0x7ff; + msg_bufno = (buf[0] >> 12) & 0x3ff; + msg_data = buf[1] & 0xfffffff; + + pr_warn("xillybus: Malformed message (skipping): " + "opcode=%d, channel=%03x, dir=%d, bufno=%03x, data=%07x\n", + opcode, msg_channel, msg_dir, msg_bufno, msg_data); +} + +/* + * xillybus_isr assumes the interrupt is allocated exclusively to it, + * which is the natural case MSI and several other hardware-oriented + * interrupts. Sharing is not allowed. + */ + +irqreturn_t xillybus_isr(int irq, void *data) +{ + struct xilly_endpoint *ep = data; + u32 *buf; + unsigned int buf_size; + int i; + int opcode; + unsigned int msg_channel, msg_bufno, msg_data, msg_dir; + struct xilly_channel *channel; + + /* + * The endpoint structure is altered during periods when it's + * guaranteed no interrupt will occur, but in theory, the cache + * lines may not be updated. So a memory barrier is issued. + */ + + smp_rmb(); + + buf = ep->msgbuf_addr; + buf_size = ep->msg_buf_size/sizeof(u32); + + + ep->ephw->sync_single_for_cpu(ep, + ep->msgbuf_dma_addr, + ep->msg_buf_size, + DMA_FROM_DEVICE); + + for (i = 0; i < buf_size; i += 2) + if (((buf[i+1] >> 28) & 0xf) != ep->msg_counter) { + malformed_message(&buf[i]); + pr_warn("xillybus: Sending a NACK on " + "counter %x (instead of %x) on entry %d\n", + ((buf[i+1] >> 28) & 0xf), + ep->msg_counter, + i/2); + + if (++ep->failed_messages > 10) + pr_err("xillybus: Lost sync with " + "interrupt messages. Stopping.\n"); + else { + ep->ephw->sync_single_for_device( + ep, + ep->msgbuf_dma_addr, + ep->msg_buf_size, + DMA_FROM_DEVICE); + + iowrite32(0x01, /* Message NACK */ + &ep->registers[fpga_msg_ctrl_reg]); + } + return IRQ_HANDLED; + } else if (buf[i] & (1 << 22)) /* Last message */ + break; + + if (i >= buf_size) { + pr_err("xillybus: Bad interrupt message. Stopping.\n"); + return IRQ_HANDLED; + } + + buf_size = i; + + for (i = 0; i <= buf_size; i += 2) { /* Scan through messages */ + opcode = (buf[i] >> 24) & 0xff; + + msg_dir = buf[i] & 1; + msg_channel = (buf[i] >> 1) & 0x7ff; + msg_bufno = (buf[i] >> 12) & 0x3ff; + msg_data = buf[i+1] & 0xfffffff; + + switch (opcode) { + case XILLYMSG_OPCODE_RELEASEBUF: + + if ((msg_channel > ep->num_channels) || + (msg_channel == 0)) { + malformed_message(&buf[i]); + break; + } + + channel = ep->channels[msg_channel]; + + if (msg_dir) { /* Write channel */ + if (msg_bufno >= channel->num_wr_buffers) { + malformed_message(&buf[i]); + break; + } + spin_lock(&channel->wr_spinlock); + channel->wr_buffers[msg_bufno]->end_offset = + msg_data; + channel->wr_fpga_buf_idx = msg_bufno; + channel->wr_empty = 0; + channel->wr_sleepy = 0; + spin_unlock(&channel->wr_spinlock); + + wake_up_interruptible(&channel->wr_wait); + + } else { + /* Read channel */ + + if (msg_bufno >= channel->num_rd_buffers) { + malformed_message(&buf[i]); + break; + } + + spin_lock(&channel->rd_spinlock); + channel->rd_fpga_buf_idx = msg_bufno; + channel->rd_full = 0; + spin_unlock(&channel->rd_spinlock); + + wake_up_interruptible(&channel->rd_wait); + if (!channel->rd_synchronous) + queue_delayed_work( + xillybus_wq, + &channel->rd_workitem, + XILLY_RX_TIMEOUT); + } + + break; + case XILLYMSG_OPCODE_NONEMPTY: + if ((msg_channel > ep->num_channels) || + (msg_channel == 0) || (!msg_dir) || + !ep->channels[msg_channel]->wr_supports_nonempty) { + malformed_message(&buf[i]); + break; + } + + channel = ep->channels[msg_channel]; + + if (msg_bufno >= channel->num_wr_buffers) { + malformed_message(&buf[i]); + break; + } + spin_lock(&channel->wr_spinlock); + if (msg_bufno == channel->wr_host_buf_idx) + channel->wr_ready = 1; + spin_unlock(&channel->wr_spinlock); + + wake_up_interruptible(&channel->wr_ready_wait); + + break; + case XILLYMSG_OPCODE_QUIESCEACK: + ep->idtlen = msg_data; + wake_up_interruptible(&ep->ep_wait); + + break; + case XILLYMSG_OPCODE_FIFOEOF: + channel = ep->channels[msg_channel]; + spin_lock(&channel->wr_spinlock); + channel->wr_eof = msg_bufno; + channel->wr_sleepy = 0; + + channel->wr_hangup = channel->wr_empty && + (channel->wr_host_buf_idx == msg_bufno); + + spin_unlock(&channel->wr_spinlock); + + wake_up_interruptible(&channel->wr_wait); + + break; + case XILLYMSG_OPCODE_FATAL_ERROR: + ep->fatal_error = 1; + wake_up_interruptible(&ep->ep_wait); /* For select() */ + pr_err("xillybus: FPGA reported a fatal " + "error. This means that the low-level " + "communication with the device has failed. " + "This hardware problem is most likely " + "unrelated to xillybus (neither kernel " + "module nor FPGA core), but reports are " + "still welcome. All I/O is aborted.\n"); + break; + default: + malformed_message(&buf[i]); + break; + } + } + + ep->ephw->sync_single_for_device(ep, + ep->msgbuf_dma_addr, + ep->msg_buf_size, + DMA_FROM_DEVICE); + + ep->msg_counter = (ep->msg_counter + 1) & 0xf; + ep->failed_messages = 0; + iowrite32(0x03, &ep->registers[fpga_msg_ctrl_reg]); /* Message ACK */ + + return IRQ_HANDLED; +} +EXPORT_SYMBOL(xillybus_isr); + +/* + * A few trivial memory management functions. + * NOTE: These functions are used only on probe and remove, and therefore + * no locks are applied! + */ + +void xillybus_do_cleanup(struct xilly_cleanup *mem, + struct xilly_endpoint *endpoint) +{ + struct list_head *this, *next; + + list_for_each_safe(this, next, &mem->to_unmap) { + struct xilly_dma *entry = + list_entry(this, struct xilly_dma, node); + + endpoint->ephw->unmap_single(entry); + kfree(entry); + } + + INIT_LIST_HEAD(&mem->to_unmap); + + list_for_each_safe(this, next, &mem->to_kfree) + kfree(this); + + INIT_LIST_HEAD(&mem->to_kfree); + + list_for_each_safe(this, next, &mem->to_pagefree) { + struct xilly_page *entry = + list_entry(this, struct xilly_page, node); + + free_pages(entry->addr, entry->order); + kfree(entry); + } + INIT_LIST_HEAD(&mem->to_pagefree); +} +EXPORT_SYMBOL(xillybus_do_cleanup); + +static void *xilly_malloc(struct xilly_cleanup *mem, size_t size) +{ + void *ptr; + + ptr = kzalloc(sizeof(struct list_head) + size, GFP_KERNEL); + + if (!ptr) + return ptr; + + list_add_tail((struct list_head *) ptr, &mem->to_kfree); + + return ptr + sizeof(struct list_head); +} + +static unsigned long xilly_pagealloc(struct xilly_cleanup *mem, + unsigned long order) +{ + unsigned long addr; + struct xilly_page *this; + + this = kmalloc(sizeof(struct xilly_page), GFP_KERNEL); + if (!this) + return 0; + + addr = __get_free_pages(GFP_KERNEL | __GFP_DMA32 | __GFP_ZERO, order); + + if (!addr) { + kfree(this); + return 0; + } + + this->addr = addr; + this->order = order; + + list_add_tail(&this->node, &mem->to_pagefree); + + return addr; +} + + +static void xillybus_autoflush(struct work_struct *work); + +static int xilly_setupchannels(struct xilly_endpoint *ep, + struct xilly_cleanup *mem, + unsigned char *chandesc, + int entries + ) +{ + int i, entry, wr_nbuffer, rd_nbuffer; + struct xilly_channel *channel; + int channelnum, bufnum, bufsize, format, is_writebuf; + int bytebufsize; + int synchronous, allowpartial, exclusive_open, seekable; + int supports_nonempty; + void *wr_salami = NULL; + void *rd_salami = NULL; + int left_of_wr_salami = 0; + int left_of_rd_salami = 0; + dma_addr_t dma_addr; + int msg_buf_done = 0; + + struct xilly_buffer *this_buffer = NULL; /* Init to silence warning */ + + channel = xilly_malloc(mem, ep->num_channels * + sizeof(struct xilly_channel)); + + if (!channel) + goto memfail; + + ep->channels = xilly_malloc(mem, (ep->num_channels + 1) * + sizeof(struct xilly_channel *)); + + if (!ep->channels) + goto memfail; + + ep->channels[0] = NULL; /* Channel 0 is message buf. */ + + /* Initialize all channels with defaults */ + + for (i = 1; i <= ep->num_channels; i++) { + channel->wr_buffers = NULL; + channel->rd_buffers = NULL; + channel->num_wr_buffers = 0; + channel->num_rd_buffers = 0; + channel->wr_fpga_buf_idx = -1; + channel->wr_host_buf_idx = 0; + channel->wr_host_buf_pos = 0; + channel->wr_empty = 1; + channel->wr_ready = 0; + channel->wr_sleepy = 1; + channel->rd_fpga_buf_idx = 0; + channel->rd_host_buf_idx = 0; + channel->rd_host_buf_pos = 0; + channel->rd_full = 0; + channel->wr_ref_count = 0; + channel->rd_ref_count = 0; + + spin_lock_init(&channel->wr_spinlock); + spin_lock_init(&channel->rd_spinlock); + mutex_init(&channel->wr_mutex); + mutex_init(&channel->rd_mutex); + init_waitqueue_head(&channel->rd_wait); + init_waitqueue_head(&channel->wr_wait); + init_waitqueue_head(&channel->wr_ready_wait); + + INIT_DELAYED_WORK(&channel->rd_workitem, xillybus_autoflush); + + channel->endpoint = ep; + channel->chan_num = i; + + channel->log2_element_size = 0; + + ep->channels[i] = channel++; + } + + /* + * The DMA buffer address update is atomic on the FPGA, so even if + * it was in the middle of sending messages to some buffer, changing + * the address is safe, since the data will go to either of the + * buffers. Not that this situation should occur at all anyhow. + */ + + wr_nbuffer = 1; + rd_nbuffer = 1; /* Buffer zero isn't used at all */ + + for (entry = 0; entry < entries; entry++, chandesc += 4) { + is_writebuf = chandesc[0] & 0x01; + channelnum = (chandesc[0] >> 1) | ((chandesc[1] & 0x0f) << 7); + format = (chandesc[1] >> 4) & 0x03; + allowpartial = (chandesc[1] >> 6) & 0x01; + synchronous = (chandesc[1] >> 7) & 0x01; + bufsize = 1 << (chandesc[2] & 0x1f); + bufnum = 1 << (chandesc[3] & 0x0f); + exclusive_open = (chandesc[2] >> 7) & 0x01; + seekable = (chandesc[2] >> 6) & 0x01; + supports_nonempty = (chandesc[2] >> 5) & 0x01; + + if ((channelnum > ep->num_channels) || + ((channelnum == 0) && !is_writebuf)) { + pr_err("xillybus: IDT requests channel out " + "of range. Aborting.\n"); + return -ENODEV; + } + + channel = ep->channels[channelnum]; /* NULL for msg channel */ + + bytebufsize = bufsize << 2; /* Overwritten just below */ + + if (!is_writebuf) { + channel->num_rd_buffers = bufnum; + channel->log2_element_size = ((format > 2) ? + 2 : format); + bytebufsize = channel->rd_buf_size = bufsize * + (1 << channel->log2_element_size); + channel->rd_allow_partial = allowpartial; + channel->rd_synchronous = synchronous; + channel->rd_exclusive_open = exclusive_open; + channel->seekable = seekable; + + channel->rd_buffers = xilly_malloc( + mem, + bufnum * sizeof(struct xilly_buffer *)); + + if (!channel->rd_buffers) + goto memfail; + + this_buffer = xilly_malloc( + mem, + bufnum * sizeof(struct xilly_buffer)); + + if (!this_buffer) + goto memfail; + } + + else if (channelnum > 0) { + channel->num_wr_buffers = bufnum; + channel->log2_element_size = ((format > 2) ? + 2 : format); + bytebufsize = channel->wr_buf_size = bufsize * + (1 << channel->log2_element_size); + + channel->seekable = seekable; + channel->wr_supports_nonempty = supports_nonempty; + + channel->wr_allow_partial = allowpartial; + channel->wr_synchronous = synchronous; + channel->wr_exclusive_open = exclusive_open; + + channel->wr_buffers = xilly_malloc( + mem, + bufnum * sizeof(struct xilly_buffer *)); + + if (!channel->wr_buffers) + goto memfail; + + this_buffer = xilly_malloc( + mem, + bufnum * sizeof(struct xilly_buffer)); + + if (!this_buffer) + goto memfail; + } + + /* + * Although daunting, we cut the chunks for read buffers + * from a different salami than the write buffers', + * possibly improving performance. + */ + + if (is_writebuf) + for (i = 0; i < bufnum; i++) { + /* + * Buffers are expected in descending + * byte-size order, so there is either + * enough for this buffer or none at all. + */ + if ((left_of_wr_salami < bytebufsize) && + (left_of_wr_salami > 0)) { + pr_err("xillybus: " + "Corrupt buffer allocation " + "in IDT. Aborting.\n"); + return -ENODEV; + } + + if (left_of_wr_salami == 0) { + int allocorder, allocsize; + + allocsize = PAGE_SIZE; + allocorder = 0; + while (bytebufsize > allocsize) { + allocsize *= 2; + allocorder++; + } + + wr_salami = (void *) + xilly_pagealloc(mem, + allocorder); + if (!wr_salami) + goto memfail; + left_of_wr_salami = allocsize; + } + + dma_addr = ep->ephw->map_single( + mem, + ep, + wr_salami, + bytebufsize, + DMA_FROM_DEVICE); + + if (!dma_addr) + goto dmafail; + + iowrite32( + (u32) (dma_addr & 0xffffffff), + &ep->registers[ + fpga_dma_bufaddr_lowaddr_reg] + ); + iowrite32( + ((u32) ((((u64) dma_addr) >> 32) + & 0xffffffff)), + &ep->registers[ + fpga_dma_bufaddr_highaddr_reg] + ); + mmiowb(); + + if (channelnum > 0) { + this_buffer->addr = wr_salami; + this_buffer->dma_addr = dma_addr; + channel->wr_buffers[i] = this_buffer++; + + iowrite32( + 0x80000000 | wr_nbuffer++, + &ep->registers[ + fpga_dma_bufno_reg]); + } else { + ep->msgbuf_addr = wr_salami; + ep->msgbuf_dma_addr = dma_addr; + ep->msg_buf_size = bytebufsize; + msg_buf_done++; + + iowrite32( + 0x80000000, &ep->registers[ + fpga_dma_bufno_reg]); + } + + left_of_wr_salami -= bytebufsize; + wr_salami += bytebufsize; + } + else /* Read buffers */ + for (i = 0; i < bufnum; i++) { + /* + * Buffers are expected in descending + * byte-size order, so there is either + * enough for this buffer or none at all. + */ + if ((left_of_rd_salami < bytebufsize) && + (left_of_rd_salami > 0)) { + pr_err("xillybus: " + "Corrupt buffer allocation " + "in IDT. Aborting.\n"); + return -ENODEV; + } + + if (left_of_rd_salami == 0) { + int allocorder, allocsize; + + allocsize = PAGE_SIZE; + allocorder = 0; + while (bytebufsize > allocsize) { + allocsize *= 2; + allocorder++; + } + + rd_salami = (void *) + xilly_pagealloc( + mem, + allocorder); + + if (!rd_salami) + goto memfail; + left_of_rd_salami = allocsize; + } + + dma_addr = ep->ephw->map_single( + mem, + ep, + rd_salami, + bytebufsize, + DMA_TO_DEVICE); + + if (!dma_addr) + goto dmafail; + + iowrite32( + (u32) (dma_addr & 0xffffffff), + &ep->registers[ + fpga_dma_bufaddr_lowaddr_reg] + ); + iowrite32( + ((u32) ((((u64) dma_addr) >> 32) + & 0xffffffff)), + &ep->registers[ + fpga_dma_bufaddr_highaddr_reg] + ); + mmiowb(); + + this_buffer->addr = rd_salami; + this_buffer->dma_addr = dma_addr; + channel->rd_buffers[i] = this_buffer++; + + iowrite32(rd_nbuffer++, + &ep->registers[fpga_dma_bufno_reg]); + + left_of_rd_salami -= bytebufsize; + rd_salami += bytebufsize; + } + } + + if (!msg_buf_done) { + pr_err("xillybus: Corrupt IDT: No message buffer. " + "Aborting.\n"); + return -ENODEV; + } + + return 0; + +memfail: + pr_err("xillybus: Failed to allocate write buffer memory. " + "Aborting.\n"); + return -ENOMEM; +dmafail: + pr_err("xillybus: Failed to map DMA memory!. Aborting.\n"); + return -ENOMEM; +} + +static void xilly_scan_idt(struct xilly_endpoint *endpoint, + struct xilly_idt_handle *idt_handle) +{ + int count = 0; + unsigned char *idt = endpoint->channels[1]->wr_buffers[0]->addr; + unsigned char *end_of_idt = idt + endpoint->idtlen - 4; + unsigned char *scan; + int len; + + scan = idt; + idt_handle->idt = idt; + + scan++; /* Skip version number */ + + while ((scan <= end_of_idt) && *scan) { + while ((scan <= end_of_idt) && *scan++) + /* Do nothing, just scan thru string */; + count++; + } + + scan++; + + if (scan > end_of_idt) { + pr_err("xillybus: IDT device name list overflow. " + "Aborting.\n"); + idt_handle->chandesc = NULL; + return; + } else + idt_handle->chandesc = scan; + + len = endpoint->idtlen - (3 + ((int) (scan - idt))); + + if (len & 0x03) { + idt_handle->chandesc = NULL; + + pr_err("xillybus: Corrupt IDT device name list. " + "Aborting.\n"); + } + + idt_handle->entries = len >> 2; + + endpoint->num_channels = count; +} + +static int xilly_obtain_idt(struct xilly_endpoint *endpoint) +{ + int rc = 0; + struct xilly_channel *channel; + unsigned char *version; + + channel = endpoint->channels[1]; /* This should be generated ad-hoc */ + + channel->wr_sleepy = 1; + wmb(); /* Setting wr_sleepy must come before the command */ + + iowrite32(1 | + (3 << 24), /* Opcode 3 for channel 0 = Send IDT */ + &endpoint->registers[fpga_buf_ctrl_reg]); + mmiowb(); /* Just to appear safe */ + + wait_event_interruptible_timeout(channel->wr_wait, + (!channel->wr_sleepy), + XILLY_TIMEOUT); + + if (channel->wr_sleepy) { + pr_err("xillybus: Failed to obtain IDT. Aborting.\n"); + + if (endpoint->fatal_error) + return -EIO; + + rc = -ENODEV; + return rc; + } + + endpoint->ephw->sync_single_for_cpu( + channel->endpoint, + channel->wr_buffers[0]->dma_addr, + channel->wr_buf_size, + DMA_FROM_DEVICE); + + if (channel->wr_buffers[0]->end_offset != endpoint->idtlen) { + pr_err("xillybus: IDT length mismatch (%d != %d). " + "Aborting.\n", + channel->wr_buffers[0]->end_offset, endpoint->idtlen); + rc = -ENODEV; + return rc; + } + + if (crc32_le(~0, channel->wr_buffers[0]->addr, + endpoint->idtlen+1) != 0) { + pr_err("xillybus: IDT failed CRC check. Aborting.\n"); + rc = -ENODEV; + return rc; + } + + version = channel->wr_buffers[0]->addr; + + /* Check version number. Accept anything below 0x82 for now. */ + if (*version > 0x82) { + pr_err("xillybus: No support for IDT version 0x%02x. " + "Maybe the xillybus driver needs an upgarde. " + "Aborting.\n", + (int) *version); + rc = -ENODEV; + return rc; + } + + return 0; /* Success */ +} + +static ssize_t xillybus_read(struct file *filp, char *userbuf, size_t count, + loff_t *f_pos) +{ + ssize_t rc; + unsigned long flags; + int bytes_done = 0; + int no_time_left = 0; + long deadline, left_to_sleep; + struct xilly_channel *channel = filp->private_data; + + int empty, reached_eof, exhausted, ready; + /* Initializations are there only to silence warnings */ + + int howmany = 0, bufpos = 0, bufidx = 0, bufferdone = 0; + int waiting_bufidx; + + if (channel->endpoint->fatal_error) + return -EIO; + + deadline = jiffies + 1 + XILLY_RX_TIMEOUT; + + rc = mutex_lock_interruptible(&channel->wr_mutex); + + if (rc) + return rc; + + rc = 0; /* Just to be clear about it. Compiler optimizes this out */ + + while (1) { /* Note that we may drop mutex within this loop */ + int bytes_to_do = count - bytes_done; + spin_lock_irqsave(&channel->wr_spinlock, flags); + + empty = channel->wr_empty; + ready = !empty || channel->wr_ready; + + if (!empty) { + bufidx = channel->wr_host_buf_idx; + bufpos = channel->wr_host_buf_pos; + howmany = ((channel->wr_buffers[bufidx]->end_offset + + 1) << channel->log2_element_size) + - bufpos; + + /* Update wr_host_* to its post-operation state */ + if (howmany > bytes_to_do) { + bufferdone = 0; + + howmany = bytes_to_do; + channel->wr_host_buf_pos += howmany; + } else { + bufferdone = 1; + + channel->wr_host_buf_pos = 0; + + if (bufidx == channel->wr_fpga_buf_idx) { + channel->wr_empty = 1; + channel->wr_sleepy = 1; + channel->wr_ready = 0; + } + + if (bufidx >= (channel->num_wr_buffers - 1)) + channel->wr_host_buf_idx = 0; + else + channel->wr_host_buf_idx++; + } + } + + /* + * Marking our situation after the possible changes above, + * for use after releasing the spinlock. + * + * empty = empty before change + * exhasted = empty after possible change + */ + + reached_eof = channel->wr_empty && + (channel->wr_host_buf_idx == channel->wr_eof); + channel->wr_hangup = reached_eof; + exhausted = channel->wr_empty; + waiting_bufidx = channel->wr_host_buf_idx; + + spin_unlock_irqrestore(&channel->wr_spinlock, flags); + + if (!empty) { /* Go on, now without the spinlock */ + + if (bufpos == 0) /* Position zero means it's virgin */ + channel->endpoint->ephw->sync_single_for_cpu( + channel->endpoint, + channel->wr_buffers[bufidx]->dma_addr, + channel->wr_buf_size, + DMA_FROM_DEVICE); + + if (copy_to_user( + userbuf, + channel->wr_buffers[bufidx]->addr + + bufpos, howmany)) + rc = -EFAULT; + + userbuf += howmany; + bytes_done += howmany; + + if (bufferdone) { + channel->endpoint->ephw-> + sync_single_for_device + ( + channel->endpoint, + channel->wr_buffers[bufidx]-> + dma_addr, + channel->wr_buf_size, + DMA_FROM_DEVICE); + + /* + * Tell FPGA the buffer is done with. It's an + * atomic operation to the FPGA, so what + * happens with other channels doesn't matter, + * and the certain channel is protected with + * the channel-specific mutex. + */ + + iowrite32(1 | (channel->chan_num << 1) + | (bufidx << 12), + &channel->endpoint->registers[ + fpga_buf_ctrl_reg]); + mmiowb(); /* Just to appear safe */ + } + + if (rc) { + mutex_unlock(&channel->wr_mutex); + return rc; + } + } + + /* This includes a zero-count return = EOF */ + if ((bytes_done >= count) || reached_eof) + break; + + if (!exhausted) + continue; /* More in RAM buffer(s)? Just go on. */ + + if ((bytes_done > 0) && + (no_time_left || + (channel->wr_synchronous && channel->wr_allow_partial))) + break; + + /* + * Nonblocking read: The "ready" flag tells us that the FPGA + * has data to send. In non-blocking mode, if it isn't on, + * just return. But if there is, we jump directly to the point + * where we ask for the FPGA to send all it has, and wait + * until that data arrives. So in a sense, we *do* block in + * nonblocking mode, but only for a very short time. + */ + + if (!no_time_left && (filp->f_flags & O_NONBLOCK)) { + if (bytes_done > 0) + break; + + if (ready) + goto desperate; + + bytes_done = -EAGAIN; + break; + } + + if (!no_time_left || (bytes_done > 0)) { + /* + * Note that in case of an element-misaligned read + * request, offsetlimit will include the last element, + * which will be partially read from. + */ + int offsetlimit = ((count - bytes_done) - 1) >> + channel->log2_element_size; + int buf_elements = channel->wr_buf_size >> + channel->log2_element_size; + + /* + * In synchronous mode, always send an offset limit. + * Just don't send a value too big. + */ + + if (channel->wr_synchronous) { + /* Don't request more than one buffer */ + if (channel->wr_allow_partial && + (offsetlimit >= buf_elements)) + offsetlimit = buf_elements - 1; + + /* Don't request more than all buffers */ + if (!channel->wr_allow_partial && + (offsetlimit >= + (buf_elements * channel->num_wr_buffers))) + offsetlimit = buf_elements * + channel->num_wr_buffers - 1; + } + + /* + * In asynchronous mode, force early flush of a buffer + * only if that will allow returning a full count. The + * "offsetlimit < ( ... )" rather than "<=" excludes + * requesting a full buffer, which would obviously + * cause a buffer transmission anyhow + */ + + if (channel->wr_synchronous || + (offsetlimit < (buf_elements - 1))) { + + mutex_lock(&channel->endpoint->register_mutex); + + iowrite32(offsetlimit, + &channel->endpoint->registers[ + fpga_buf_offset_reg]); + mmiowb(); + + iowrite32(1 | (channel->chan_num << 1) | + (2 << 24) | /* 2 = offset limit */ + (waiting_bufidx << 12), + &channel->endpoint->registers[ + fpga_buf_ctrl_reg]); + + mmiowb(); /* Just to appear safe */ + + mutex_unlock(&channel->endpoint-> + register_mutex); + } + + } + + /* + * If partial completion is disallowed, there is no point in + * timeout sleeping. Neither if no_time_left is set and + * there's no data. + */ + + if (!channel->wr_allow_partial || + (no_time_left && (bytes_done == 0))) { + + /* + * This do-loop will run more than once if another + * thread reasserted wr_sleepy before we got the mutex + * back, so we try again. + */ + + do { + mutex_unlock(&channel->wr_mutex); + + if (wait_event_interruptible( + channel->wr_wait, + (!channel->wr_sleepy))) + goto interrupted; + + if (mutex_lock_interruptible( + &channel->wr_mutex)) + goto interrupted; + } while (channel->wr_sleepy); + + continue; + +interrupted: /* Mutex is not held if got here */ + if (channel->endpoint->fatal_error) + return -EIO; + if (bytes_done) + return bytes_done; + if (filp->f_flags & O_NONBLOCK) + return -EAGAIN; /* Don't admit snoozing */ + return -EINTR; + } + + left_to_sleep = deadline - ((long) jiffies); + + /* + * If our time is out, skip the waiting. We may miss wr_sleepy + * being deasserted but hey, almost missing the train is like + * missing it. + */ + + if (left_to_sleep > 0) { + left_to_sleep = + wait_event_interruptible_timeout( + channel->wr_wait, + (!channel->wr_sleepy), + left_to_sleep); + + if (!channel->wr_sleepy) + continue; + + if (left_to_sleep < 0) { /* Interrupt */ + mutex_unlock(&channel->wr_mutex); + if (channel->endpoint->fatal_error) + return -EIO; + if (bytes_done) + return bytes_done; + return -EINTR; + } + } + +desperate: + no_time_left = 1; /* We're out of sleeping time. Desperate! */ + + if (bytes_done == 0) { + /* + * Reaching here means that we allow partial return, + * that we've run out of time, and that we have + * nothing to return. + * So tell the FPGA to send anything it has or gets. + */ + + iowrite32(1 | (channel->chan_num << 1) | + (3 << 24) | /* Opcode 3, flush it all! */ + (waiting_bufidx << 12), + &channel->endpoint->registers[ + fpga_buf_ctrl_reg]); + mmiowb(); /* Just to appear safe */ + } + + /* + * Formally speaking, we should block for data at this point. + * But to keep the code cleaner, we'll just finish the loop, + * make the unlikely check for data, and then block at the + * usual place. + */ + } + + mutex_unlock(&channel->wr_mutex); + + if (channel->endpoint->fatal_error) + return -EIO; + + return bytes_done; +} + +/* + * The timeout argument takes values as follows: + * >0 : Flush with timeout + * ==0 : Flush, and wait idefinitely for the flush to complete + * <0 : Autoflush: Flush only if there's a single buffer occupied + */ + +static int xillybus_myflush(struct xilly_channel *channel, long timeout) +{ + int rc = 0; + unsigned long flags; + + int end_offset_plus1; + int bufidx, bufidx_minus1; + int i; + int empty; + int new_rd_host_buf_pos; + + if (channel->endpoint->fatal_error) + return -EIO; + rc = mutex_lock_interruptible(&channel->rd_mutex); + + if (rc) + return rc; + + /* + * Don't flush a closed channel. This can happen when the work queued + * autoflush thread fires off after the file has closed. This is not + * an error, just something to dismiss. + */ + + if (!channel->rd_ref_count) + goto done; + + bufidx = channel->rd_host_buf_idx; + + bufidx_minus1 = (bufidx == 0) ? channel->num_rd_buffers - 1 : bufidx-1; + + end_offset_plus1 = channel->rd_host_buf_pos >> + channel->log2_element_size; + + new_rd_host_buf_pos = channel->rd_host_buf_pos - + (end_offset_plus1 << channel->log2_element_size); + + /* Submit the current buffer if it's nonempty */ + if (end_offset_plus1) { + unsigned char *tail = channel->rd_buffers[bufidx]->addr + + (end_offset_plus1 << channel->log2_element_size); + + /* Copy unflushed data, so we can put it in next buffer */ + for (i = 0; i < new_rd_host_buf_pos; i++) + channel->rd_leftovers[i] = *tail++; + + spin_lock_irqsave(&channel->rd_spinlock, flags); + + /* Autoflush only if a single buffer is occupied */ + + if ((timeout < 0) && + (channel->rd_full || + (bufidx_minus1 != channel->rd_fpga_buf_idx))) { + spin_unlock_irqrestore(&channel->rd_spinlock, flags); + /* + * A new work item may be queued by the ISR exactly + * now, since the execution of a work item allows the + * queuing of a new one while it's running. + */ + goto done; + } + + /* The 4th element is never needed for data, so it's a flag */ + channel->rd_leftovers[3] = (new_rd_host_buf_pos != 0); + + /* Set up rd_full to reflect a certain moment's state */ + + if (bufidx == channel->rd_fpga_buf_idx) + channel->rd_full = 1; + spin_unlock_irqrestore(&channel->rd_spinlock, flags); + + if (bufidx >= (channel->num_rd_buffers - 1)) + channel->rd_host_buf_idx = 0; + else + channel->rd_host_buf_idx++; + + channel->endpoint->ephw->sync_single_for_device( + channel->endpoint, + channel->rd_buffers[bufidx]->dma_addr, + channel->rd_buf_size, + DMA_TO_DEVICE); + + mutex_lock(&channel->endpoint->register_mutex); + + iowrite32(end_offset_plus1 - 1, + &channel->endpoint->registers[fpga_buf_offset_reg]); + mmiowb(); + + iowrite32((channel->chan_num << 1) | /* Channel ID */ + (2 << 24) | /* Opcode 2, submit buffer */ + (bufidx << 12), + &channel->endpoint->registers[fpga_buf_ctrl_reg]); + mmiowb(); /* Just to appear safe */ + + mutex_unlock(&channel->endpoint->register_mutex); + } else if (bufidx == 0) + bufidx = channel->num_rd_buffers - 1; + else + bufidx--; + + channel->rd_host_buf_pos = new_rd_host_buf_pos; + + if (timeout < 0) + goto done; /* Autoflush */ + + + /* + * bufidx is now the last buffer written to (or equal to + * rd_fpga_buf_idx if buffer was never written to), and + * channel->rd_host_buf_idx the one after it. + * + * If bufidx == channel->rd_fpga_buf_idx we're either empty or full. + */ + + rc = 0; + + while (1) { /* Loop waiting for draining of buffers */ + spin_lock_irqsave(&channel->rd_spinlock, flags); + + if (bufidx != channel->rd_fpga_buf_idx) + channel->rd_full = 1; /* + * Not really full, + * but needs waiting. + */ + + empty = !channel->rd_full; + + spin_unlock_irqrestore(&channel->rd_spinlock, flags); + + if (empty) + break; + + /* + * Indefinite sleep with mutex taken. With data waiting for + * flushing user should not be surprised if open() for write + * sleeps. + */ + if (timeout == 0) + wait_event_interruptible(channel->rd_wait, + (!channel->rd_full)); + + else if (wait_event_interruptible_timeout( + channel->rd_wait, + (!channel->rd_full), + timeout) == 0) { + pr_warn("xillybus: " + "Timed out while flushing. " + "Output data may be lost.\n"); + + rc = -ETIMEDOUT; + break; + } + + if (channel->rd_full) { + rc = -EINTR; + break; + } + } + +done: + mutex_unlock(&channel->rd_mutex); + + if (channel->endpoint->fatal_error) + return -EIO; + + return rc; +} + +static int xillybus_flush(struct file *filp, fl_owner_t id) +{ + if (!(filp->f_mode & FMODE_WRITE)) + return 0; + + return xillybus_myflush(filp->private_data, HZ); /* 1 second timeout */ +} + +static void xillybus_autoflush(struct work_struct *work) +{ + struct delayed_work *workitem = container_of( + work, struct delayed_work, work); + struct xilly_channel *channel = container_of( + workitem, struct xilly_channel, rd_workitem); + int rc; + + rc = xillybus_myflush(channel, -1); + + if (rc == -EINTR) + pr_warn("xillybus: Autoflush failed because " + "work queue thread got a signal.\n"); + else if (rc) + pr_err("xillybus: Autoflush failed under " + "weird circumstances.\n"); + +} + +static ssize_t xillybus_write(struct file *filp, const char *userbuf, + size_t count, loff_t *f_pos) +{ + ssize_t rc; + unsigned long flags; + int bytes_done = 0; + struct xilly_channel *channel = filp->private_data; + + int full, exhausted; + /* Initializations are there only to silence warnings */ + + int howmany = 0, bufpos = 0, bufidx = 0, bufferdone = 0; + int end_offset_plus1 = 0; + + if (channel->endpoint->fatal_error) + return -EIO; + + rc = mutex_lock_interruptible(&channel->rd_mutex); + + if (rc) + return rc; + + rc = 0; /* Just to be clear about it. Compiler optimizes this out */ + + while (1) { + int bytes_to_do = count - bytes_done; + + spin_lock_irqsave(&channel->rd_spinlock, flags); + + full = channel->rd_full; + + if (!full) { + bufidx = channel->rd_host_buf_idx; + bufpos = channel->rd_host_buf_pos; + howmany = channel->rd_buf_size - bufpos; + + /* + * Update rd_host_* to its state after this operation. + * count=0 means committing the buffer immediately, + * which is like flushing, but not necessarily block. + */ + + if ((howmany > bytes_to_do) && + (count || + ((bufpos >> channel->log2_element_size) == 0))) { + bufferdone = 0; + + howmany = bytes_to_do; + channel->rd_host_buf_pos += howmany; + } else { + bufferdone = 1; + + if (count) { + end_offset_plus1 = + channel->rd_buf_size >> + channel->log2_element_size; + channel->rd_host_buf_pos = 0; + } else { + unsigned char *tail; + int i; + + end_offset_plus1 = bufpos >> + channel->log2_element_size; + + channel->rd_host_buf_pos -= + end_offset_plus1 << + channel->log2_element_size; + + tail = channel-> + rd_buffers[bufidx]->addr + + (end_offset_plus1 << + channel->log2_element_size); + + for (i = 0; + i < channel->rd_host_buf_pos; + i++) + channel->rd_leftovers[i] = + *tail++; + } + + if (bufidx == channel->rd_fpga_buf_idx) + channel->rd_full = 1; + + if (bufidx >= (channel->num_rd_buffers - 1)) + channel->rd_host_buf_idx = 0; + else + channel->rd_host_buf_idx++; + } + } + + /* + * Marking our situation after the possible changes above, + * for use after releasing the spinlock. + * + * full = full before change + * exhasted = full after possible change + */ + + exhausted = channel->rd_full; + + spin_unlock_irqrestore(&channel->rd_spinlock, flags); + + if (!full) { /* Go on, now without the spinlock */ + unsigned char *head = + channel->rd_buffers[bufidx]->addr; + int i; + + if ((bufpos == 0) || /* Zero means it's virgin */ + (channel->rd_leftovers[3] != 0)) { + channel->endpoint->ephw->sync_single_for_cpu( + channel->endpoint, + channel->rd_buffers[bufidx]->dma_addr, + channel->rd_buf_size, + DMA_TO_DEVICE); + + /* Virgin, but leftovers are due */ + for (i = 0; i < bufpos; i++) + *head++ = channel->rd_leftovers[i]; + + channel->rd_leftovers[3] = 0; /* Clear flag */ + } + + if (copy_from_user( + channel->rd_buffers[bufidx]->addr + bufpos, + userbuf, howmany)) + rc = -EFAULT; + + userbuf += howmany; + bytes_done += howmany; + + if (bufferdone) { + channel->endpoint->ephw-> + sync_single_for_device( + channel->endpoint, + channel->rd_buffers[bufidx]-> + dma_addr, + channel->rd_buf_size, + DMA_TO_DEVICE); + + mutex_lock(&channel->endpoint->register_mutex); + + iowrite32(end_offset_plus1 - 1, + &channel->endpoint->registers[ + fpga_buf_offset_reg]); + mmiowb(); + iowrite32((channel->chan_num << 1) | + (2 << 24) | /* 2 = submit buffer */ + (bufidx << 12), + &channel->endpoint->registers[ + fpga_buf_ctrl_reg]); + mmiowb(); /* Just to appear safe */ + + mutex_unlock(&channel->endpoint-> + register_mutex); + + channel->rd_leftovers[3] = + (channel->rd_host_buf_pos != 0); + } + + if (rc) { + mutex_unlock(&channel->rd_mutex); + + if (channel->endpoint->fatal_error) + return -EIO; + + if (!channel->rd_synchronous) + queue_delayed_work( + xillybus_wq, + &channel->rd_workitem, + XILLY_RX_TIMEOUT); + + return rc; + } + } + + if (bytes_done >= count) + break; + + if (!exhausted) + continue; /* If there's more space, just go on */ + + if ((bytes_done > 0) && channel->rd_allow_partial) + break; + + /* + * Indefinite sleep with mutex taken. With data waiting for + * flushing, user should not be surprised if open() for write + * sleeps. + */ + + if (filp->f_flags & O_NONBLOCK) { + bytes_done = -EAGAIN; + break; + } + + wait_event_interruptible(channel->rd_wait, + (!channel->rd_full)); + + if (channel->rd_full) { + mutex_unlock(&channel->rd_mutex); + + if (channel->endpoint->fatal_error) + return -EIO; + + if (bytes_done) + return bytes_done; + return -EINTR; + } + } + + mutex_unlock(&channel->rd_mutex); + + if (!channel->rd_synchronous) + queue_delayed_work(xillybus_wq, + &channel->rd_workitem, + XILLY_RX_TIMEOUT); + + if ((channel->rd_synchronous) && (bytes_done > 0)) { + rc = xillybus_myflush(filp->private_data, 0); /* No timeout */ + + if (rc && (rc != -EINTR)) + return rc; + } + + if (channel->endpoint->fatal_error) + return -EIO; + + return bytes_done; +} + +static int xillybus_open(struct inode *inode, struct file *filp) +{ + int rc = 0; + unsigned long flags; + int minor = iminor(inode); + int major = imajor(inode); + struct xilly_endpoint *ep_iter, *endpoint = NULL; + struct xilly_channel *channel; + + mutex_lock(&ep_list_lock); + + list_for_each_entry(ep_iter, &list_of_endpoints, ep_list) { + if ((ep_iter->major == major) && + (minor >= ep_iter->lowest_minor) && + (minor < (ep_iter->lowest_minor + + ep_iter->num_channels))) { + endpoint = ep_iter; + break; + } + } + mutex_unlock(&ep_list_lock); + + if (!endpoint) { + pr_err("xillybus: open() failed to find a device " + "for major=%d and minor=%d\n", major, minor); + return -ENODEV; + } + + if (endpoint->fatal_error) + return -EIO; + + channel = endpoint->channels[1 + minor - endpoint->lowest_minor]; + filp->private_data = channel; + + + /* + * It gets complicated because: + * 1. We don't want to take a mutex we don't have to + * 2. We don't want to open one direction if the other will fail. + */ + + if ((filp->f_mode & FMODE_READ) && (!channel->num_wr_buffers)) + return -ENODEV; + + if ((filp->f_mode & FMODE_WRITE) && (!channel->num_rd_buffers)) + return -ENODEV; + + if ((filp->f_mode & FMODE_READ) && (filp->f_flags & O_NONBLOCK) && + (channel->wr_synchronous || !channel->wr_allow_partial || + !channel->wr_supports_nonempty)) { + pr_err("xillybus: open() failed: " + "O_NONBLOCK not allowed for read on this device\n"); + return -ENODEV; + } + + if ((filp->f_mode & FMODE_WRITE) && (filp->f_flags & O_NONBLOCK) && + (channel->rd_synchronous || !channel->rd_allow_partial)) { + pr_err("xillybus: open() failed: " + "O_NONBLOCK not allowed for write on this device\n"); + return -ENODEV; + } + + /* + * Note: open() may block on getting mutexes despite O_NONBLOCK. + * This shouldn't occur normally, since multiple open of the same + * file descriptor is almost always prohibited anyhow + * (*_exclusive_open is normally set in real-life systems). + */ + + if (filp->f_mode & FMODE_READ) { + rc = mutex_lock_interruptible(&channel->wr_mutex); + if (rc) + return rc; + } + + if (filp->f_mode & FMODE_WRITE) { + rc = mutex_lock_interruptible(&channel->rd_mutex); + if (rc) + goto unlock_wr; + } + + if ((filp->f_mode & FMODE_READ) && + (channel->wr_ref_count != 0) && + (channel->wr_exclusive_open)) { + rc = -EBUSY; + goto unlock; + } + + if ((filp->f_mode & FMODE_WRITE) && + (channel->rd_ref_count != 0) && + (channel->rd_exclusive_open)) { + rc = -EBUSY; + goto unlock; + } + + + if (filp->f_mode & FMODE_READ) { + if (channel->wr_ref_count == 0) { /* First open of file */ + /* Move the host to first buffer */ + spin_lock_irqsave(&channel->wr_spinlock, flags); + channel->wr_host_buf_idx = 0; + channel->wr_host_buf_pos = 0; + channel->wr_fpga_buf_idx = -1; + channel->wr_empty = 1; + channel->wr_ready = 0; + channel->wr_sleepy = 1; + channel->wr_eof = -1; + channel->wr_hangup = 0; + + spin_unlock_irqrestore(&channel->wr_spinlock, flags); + + iowrite32(1 | (channel->chan_num << 1) | + (4 << 24) | /* Opcode 4, open channel */ + ((channel->wr_synchronous & 1) << 23), + &channel->endpoint->registers[ + fpga_buf_ctrl_reg]); + mmiowb(); /* Just to appear safe */ + } + + channel->wr_ref_count++; + } + + if (filp->f_mode & FMODE_WRITE) { + if (channel->rd_ref_count == 0) { /* First open of file */ + /* Move the host to first buffer */ + spin_lock_irqsave(&channel->rd_spinlock, flags); + channel->rd_host_buf_idx = 0; + channel->rd_host_buf_pos = 0; + channel->rd_leftovers[3] = 0; /* No leftovers. */ + channel->rd_fpga_buf_idx = channel->num_rd_buffers - 1; + channel->rd_full = 0; + + spin_unlock_irqrestore(&channel->rd_spinlock, flags); + + iowrite32((channel->chan_num << 1) | + (4 << 24), /* Opcode 4, open channel */ + &channel->endpoint->registers[ + fpga_buf_ctrl_reg]); + mmiowb(); /* Just to appear safe */ + } + + channel->rd_ref_count++; + } + +unlock: + if (filp->f_mode & FMODE_WRITE) + mutex_unlock(&channel->rd_mutex); +unlock_wr: + if (filp->f_mode & FMODE_READ) + mutex_unlock(&channel->wr_mutex); + + if (!rc && (!channel->seekable)) + return nonseekable_open(inode, filp); + + return rc; +} + +static int xillybus_release(struct inode *inode, struct file *filp) +{ + int rc; + unsigned long flags; + struct xilly_channel *channel = filp->private_data; + + int buf_idx; + int eof; + + if (channel->endpoint->fatal_error) + return -EIO; + + if (filp->f_mode & FMODE_WRITE) { + rc = mutex_lock_interruptible(&channel->rd_mutex); + + if (rc) { + pr_warn("xillybus: Failed to close file. " + "Hardware left in messy state.\n"); + return rc; + } + + channel->rd_ref_count--; + + if (channel->rd_ref_count == 0) { + + /* + * We rely on the kernel calling flush() + * before we get here. + */ + + iowrite32((channel->chan_num << 1) | /* Channel ID */ + (5 << 24), /* Opcode 5, close channel */ + &channel->endpoint->registers[ + fpga_buf_ctrl_reg]); + mmiowb(); /* Just to appear safe */ + } + mutex_unlock(&channel->rd_mutex); + } + + if (filp->f_mode & FMODE_READ) { + rc = mutex_lock_interruptible(&channel->wr_mutex); + if (rc) { + pr_warn("xillybus: Failed to close file. " + "Hardware left in messy state.\n"); + return rc; + } + + channel->wr_ref_count--; + + if (channel->wr_ref_count == 0) { + + iowrite32(1 | (channel->chan_num << 1) | + (5 << 24), /* Opcode 5, close channel */ + &channel->endpoint->registers[ + fpga_buf_ctrl_reg]); + mmiowb(); /* Just to appear safe */ + + /* + * This is crazily cautious: We make sure that not + * only that we got an EOF (be it because we closed + * the channel or because of a user's EOF), but verify + * that it's one beyond the last buffer arrived, so + * we have no leftover buffers pending before wrapping + * up (which can only happen in asynchronous channels, + * BTW) + */ + + while (1) { + spin_lock_irqsave(&channel->wr_spinlock, + flags); + buf_idx = channel->wr_fpga_buf_idx; + eof = channel->wr_eof; + channel->wr_sleepy = 1; + spin_unlock_irqrestore(&channel->wr_spinlock, + flags); + + /* + * Check if eof points at the buffer after + * the last one the FPGA submitted. Note that + * no EOF is marked by negative eof. + */ + + buf_idx++; + if (buf_idx == channel->num_wr_buffers) + buf_idx = 0; + + if (buf_idx == eof) + break; + + /* + * Steal extra 100 ms if awaken by interrupt. + * This is a simple workaround for an + * interrupt pending when entering, which would + * otherwise result in declaring the hardware + * non-responsive. + */ + + if (wait_event_interruptible( + channel->wr_wait, + (!channel->wr_sleepy))) + msleep(100); + + if (channel->wr_sleepy) { + mutex_unlock(&channel->wr_mutex); + pr_warn("xillybus: Hardware failed to " + "respond to close command, " + "therefore left in " + "messy state.\n"); + return -EINTR; + } + } + } + + mutex_unlock(&channel->wr_mutex); + } + + return 0; +} +loff_t xillybus_llseek(struct file *filp, loff_t offset, int whence) +{ + struct xilly_channel *channel = filp->private_data; + loff_t pos = filp->f_pos; + int rc = 0; + + /* + * Take both mutexes not allowing interrupts, since it seems like + * common applications don't expect an -EINTR here. Besides, multiple + * access to a single file desriptor on seekable devices is a mess + * anyhow. + */ + + if (channel->endpoint->fatal_error) + return -EIO; + + mutex_lock(&channel->wr_mutex); + mutex_lock(&channel->rd_mutex); + + switch (whence) { + case 0: + pos = offset; + break; + case 1: + pos += offset; + break; + case 2: + pos = offset; /* Going to the end => to the beginning */ + break; + default: + rc = -EINVAL; + goto end; + } + + /* In any case, we must finish on an element boundary */ + if (pos & ((1 << channel->log2_element_size) - 1)) { + rc = -EINVAL; + goto end; + } + + mutex_lock(&channel->endpoint->register_mutex); + + iowrite32(pos >> channel->log2_element_size, + &channel->endpoint->registers[fpga_buf_offset_reg]); + mmiowb(); + iowrite32((channel->chan_num << 1) | + (6 << 24), /* Opcode 6, set address */ + &channel->endpoint->registers[fpga_buf_ctrl_reg]); + mmiowb(); /* Just to appear safe */ + + mutex_unlock(&channel->endpoint->register_mutex); + +end: + mutex_unlock(&channel->rd_mutex); + mutex_unlock(&channel->wr_mutex); + + if (rc) /* Return error after releasing mutexes */ + return rc; + + filp->f_pos = pos; + + /* + * Since seekable devices are allowed only when the channel is + * synchronous, we assume that there is no data pending in either + * direction (which holds true as long as no concurrent access on the + * file descriptor takes place). + * The only thing we may need to throw away is leftovers from partial + * write() flush. + */ + + channel->rd_leftovers[3] = 0; + + return pos; +} + +static unsigned int xillybus_poll(struct file *filp, poll_table *wait) +{ + struct xilly_channel *channel = filp->private_data; + unsigned int mask = 0; + unsigned long flags; + + poll_wait(filp, &channel->endpoint->ep_wait, wait); + + /* + * poll() won't play ball regarding read() channels which + * aren't asynchronous and support the nonempty message. Allowing + * that will create situations where data has been delivered at + * the FPGA, and users expecting select() to wake up, which it may + * not. + */ + + if (!channel->wr_synchronous && channel->wr_supports_nonempty) { + poll_wait(filp, &channel->wr_wait, wait); + poll_wait(filp, &channel->wr_ready_wait, wait); + + spin_lock_irqsave(&channel->wr_spinlock, flags); + if (!channel->wr_empty || channel->wr_ready) + mask |= POLLIN | POLLRDNORM; + + if (channel->wr_hangup) + /* + * Not POLLHUP, because its behavior is in the + * mist, and POLLIN does what we want: Wake up + * the read file descriptor so it sees EOF. + */ + mask |= POLLIN | POLLRDNORM; + spin_unlock_irqrestore(&channel->wr_spinlock, flags); + } + + /* + * If partial data write is disallowed on a write() channel, + * it's pointless to ever signal OK to write, because is could + * block despite some space being available. + */ + + if (channel->rd_allow_partial) { + poll_wait(filp, &channel->rd_wait, wait); + + spin_lock_irqsave(&channel->rd_spinlock, flags); + if (!channel->rd_full) + mask |= POLLOUT | POLLWRNORM; + spin_unlock_irqrestore(&channel->rd_spinlock, flags); + } + + if (channel->endpoint->fatal_error) + mask |= POLLERR; + + return mask; +} + +static const struct file_operations xillybus_fops = { + .owner = THIS_MODULE, + .read = xillybus_read, + .write = xillybus_write, + .open = xillybus_open, + .flush = xillybus_flush, + .release = xillybus_release, + .llseek = xillybus_llseek, + .poll = xillybus_poll, +}; + +static int xillybus_init_chrdev(struct xilly_endpoint *endpoint, + const unsigned char *idt) +{ + int rc; + dev_t dev; + int devnum, i, minor, major; + char devname[48]; + struct device *device; + + rc = alloc_chrdev_region(&dev, 0, /* minor start */ + endpoint->num_channels, + xillyname); + + if (rc) { + pr_warn("xillybus: Failed to obtain major/minors"); + goto error1; + } + + endpoint->major = major = MAJOR(dev); + endpoint->lowest_minor = minor = MINOR(dev); + + cdev_init(&endpoint->cdev, &xillybus_fops); + endpoint->cdev.owner = endpoint->ephw->owner; + rc = cdev_add(&endpoint->cdev, MKDEV(major, minor), + endpoint->num_channels); + if (rc) { + pr_warn("xillybus: Failed to add cdev. Aborting.\n"); + goto error2; + } + + idt++; + + for (i = minor, devnum = 0; + devnum < endpoint->num_channels; + devnum++, i++) { + snprintf(devname, sizeof(devname)-1, "xillybus_%s", idt); + + devname[sizeof(devname)-1] = 0; /* Should never matter */ + + while (*idt++) + /* Skip to next */; + + device = device_create(xillybus_class, + NULL, + MKDEV(major, i), + NULL, + devname); + + if (IS_ERR(device)) { + pr_warn("xillybus: Failed to create %s " + "device. Aborting.\n", devname); + goto error3; + } + } + + pr_info("xillybus: Created %d device files.\n", + endpoint->num_channels); + return 0; /* succeed */ + +error3: + devnum--; i--; + for (; devnum >= 0; devnum--, i--) + device_destroy(xillybus_class, MKDEV(major, i)); + + cdev_del(&endpoint->cdev); +error2: + unregister_chrdev_region(MKDEV(major, minor), endpoint->num_channels); +error1: + + return rc; +} + +static void xillybus_cleanup_chrdev(struct xilly_endpoint *endpoint) +{ + int minor; + + for (minor = endpoint->lowest_minor; + minor < (endpoint->lowest_minor + endpoint->num_channels); + minor++) + device_destroy(xillybus_class, MKDEV(endpoint->major, minor)); + cdev_del(&endpoint->cdev); + unregister_chrdev_region(MKDEV(endpoint->major, + endpoint->lowest_minor), + endpoint->num_channels); + + pr_info("xillybus: Removed %d device files.\n", + endpoint->num_channels); +} + + +struct xilly_endpoint *xillybus_init_endpoint(struct pci_dev *pdev, + struct device *dev, + struct xilly_endpoint_hardware + *ephw) +{ + struct xilly_endpoint *endpoint; + + endpoint = kzalloc(sizeof(*endpoint), GFP_KERNEL); + if (!endpoint) { + pr_err("xillybus: Failed to allocate memory. Aborting.\n"); + return NULL; + } + + endpoint->pdev = pdev; + endpoint->dev = dev; + endpoint->ephw = ephw; + INIT_LIST_HEAD(&endpoint->cleanup.to_kfree); + INIT_LIST_HEAD(&endpoint->cleanup.to_pagefree); + INIT_LIST_HEAD(&endpoint->cleanup.to_unmap); + endpoint->msg_counter = 0x0b; + endpoint->failed_messages = 0; + endpoint->fatal_error = 0; + + init_waitqueue_head(&endpoint->ep_wait); + mutex_init(&endpoint->register_mutex); + + return endpoint; +} +EXPORT_SYMBOL(xillybus_init_endpoint); + +static int xilly_quiesce(struct xilly_endpoint *endpoint) +{ + endpoint->idtlen = -1; + wmb(); /* Make sure idtlen is set before sending command */ + iowrite32((u32) (endpoint->dma_using_dac & 0x0001), + &endpoint->registers[fpga_dma_control_reg]); + mmiowb(); + + wait_event_interruptible_timeout(endpoint->ep_wait, + (endpoint->idtlen >= 0), + XILLY_TIMEOUT); + + if (endpoint->idtlen < 0) { + pr_err("xillybus: Failed to quiesce the device on " + "exit. Quitting while leaving a mess.\n"); + return -ENODEV; + } + return 0; /* Success */ +} + +int xillybus_endpoint_discovery(struct xilly_endpoint *endpoint) +{ + int rc = 0; + + struct xilly_cleanup tmpmem; + int idtbuffersize = (1 << PAGE_SHIFT); + + /* + * The bogus IDT is used during bootstrap for allocating the initial + * message buffer, and then the message buffer and space for the IDT + * itself. The initial message buffer is of a single page's size, but + * it's soon replaced with a more modest one (and memory is freed). + */ + + unsigned char bogus_idt[8] = { 1, 224, (PAGE_SHIFT)-2, 0, + 3, 192, PAGE_SHIFT, 0 }; + struct xilly_idt_handle idt_handle; + + INIT_LIST_HEAD(&tmpmem.to_kfree); + INIT_LIST_HEAD(&tmpmem.to_pagefree); + INIT_LIST_HEAD(&tmpmem.to_unmap); + + /* + * Writing the value 0x00000001 to Endianess register signals which + * endianess this processor is using, so the FPGA can swap words as + * necessary. + */ + + iowrite32(1, &endpoint->registers[fpga_endian_reg]); + mmiowb(); /* Writes below are affected by the one above. */ + + /* Bootstrap phase I: Allocate temporary message buffer */ + + endpoint->num_channels = 0; + + rc = xilly_setupchannels(endpoint, &tmpmem, bogus_idt, 1); + + if (rc) + goto failed_buffers; + + /* Clear the message subsystem (and counter in particular) */ + iowrite32(0x04, &endpoint->registers[fpga_msg_ctrl_reg]); + mmiowb(); + + endpoint->idtlen = -1; + + smp_wmb(); + + /* + * Set DMA 32/64 bit mode, quiesce the device (?!) and get IDT + * buffer size. + */ + iowrite32((u32) (endpoint->dma_using_dac & 0x0001), + &endpoint->registers[fpga_dma_control_reg]); + mmiowb(); + + wait_event_interruptible_timeout(endpoint->ep_wait, + (endpoint->idtlen >= 0), + XILLY_TIMEOUT); + + if (endpoint->idtlen < 0) { + pr_err("xillybus: No response from FPGA. Aborting.\n"); + rc = -ENODEV; + goto failed_quiesce; + } + + /* Enable DMA */ + iowrite32((u32) (0x0002 | (endpoint->dma_using_dac & 0x0001)), + &endpoint->registers[fpga_dma_control_reg]); + mmiowb(); + + /* Bootstrap phase II: Allocate buffer for IDT and obtain it */ + while (endpoint->idtlen >= idtbuffersize) { + idtbuffersize *= 2; + bogus_idt[6]++; + } + + endpoint->num_channels = 1; + + rc = xilly_setupchannels(endpoint, &tmpmem, bogus_idt, 2); + + if (rc) + goto failed_idt; + + smp_wmb(); + + rc = xilly_obtain_idt(endpoint); + + if (rc) + goto failed_idt; + + xilly_scan_idt(endpoint, &idt_handle); + + if (!idt_handle.chandesc) { + rc = -ENODEV; + goto failed_idt; + } + /* Bootstrap phase III: Allocate buffers according to IDT */ + + rc = xilly_setupchannels(endpoint, + &endpoint->cleanup, + idt_handle.chandesc, + idt_handle.entries); + + if (rc) + goto failed_idt; + + smp_wmb(); /* mutex_lock below should suffice, but won't hurt.*/ + + /* + * endpoint is now completely configured. We put it on the list + * available to open() before registering the char device(s) + */ + + mutex_lock(&ep_list_lock); + list_add_tail(&endpoint->ep_list, &list_of_endpoints); + mutex_unlock(&ep_list_lock); + + rc = xillybus_init_chrdev(endpoint, idt_handle.idt); + + if (rc) + goto failed_chrdevs; + + xillybus_do_cleanup(&tmpmem, endpoint); + + return 0; + +failed_chrdevs: + mutex_lock(&ep_list_lock); + list_del(&endpoint->ep_list); + mutex_unlock(&ep_list_lock); + +failed_idt: + /* Quiesce the device. Now it's serious to do it */ + rc = xilly_quiesce(endpoint); + + if (rc) + return rc; /* FPGA may still DMA, so no release */ + + flush_workqueue(xillybus_wq); +failed_quiesce: +failed_buffers: + xillybus_do_cleanup(&tmpmem, endpoint); + + return rc; +} +EXPORT_SYMBOL(xillybus_endpoint_discovery); + +void xillybus_endpoint_remove(struct xilly_endpoint *endpoint) +{ + xillybus_cleanup_chrdev(endpoint); + + mutex_lock(&ep_list_lock); + list_del(&endpoint->ep_list); + mutex_unlock(&ep_list_lock); + + xilly_quiesce(endpoint); + + /* + * Flushing is done upon endpoint release to prevent access to memory + * just about to be released. This makes the quiesce complete. + */ + flush_workqueue(xillybus_wq); +} +EXPORT_SYMBOL(xillybus_endpoint_remove); + +static int __init xillybus_init(void) +{ + int rc = 0; + + mutex_init(&ep_list_lock); + + xillybus_class = class_create(THIS_MODULE, xillyname); + if (IS_ERR(xillybus_class)) { + rc = PTR_ERR(xillybus_class); + pr_warn("xillybus: Failed to register class xillybus\n"); + + return rc; + } + + xillybus_wq = alloc_workqueue(xillyname, 0, 0); + + return 0; /* Success */ +} + +static void __exit xillybus_exit(void) +{ + /* flush_workqueue() was called for each endpoint released */ + destroy_workqueue(xillybus_wq); + + class_destroy(xillybus_class); +} + +module_init(xillybus_init); +module_exit(xillybus_exit); diff --git a/drivers/staging/xillybus/xillybus_of.c b/drivers/staging/xillybus/xillybus_of.c new file mode 100644 index 000000000000..b875376766a2 --- /dev/null +++ b/drivers/staging/xillybus/xillybus_of.c @@ -0,0 +1,210 @@ +/* + * linux/drivers/misc/xillybus_of.c + * + * Copyright 2011 Xillybus Ltd, http://xillybus.com + * + * Driver for the Xillybus FPGA/host framework using Open Firmware. + * + * This program is free software; you can redistribute it and/or modify + * it under the smems of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "xillybus.h" + +MODULE_DESCRIPTION("Xillybus driver for Open Firmware"); +MODULE_AUTHOR("Eli Billauer, Xillybus Ltd."); +MODULE_VERSION("1.06"); +MODULE_ALIAS("xillybus_of"); +MODULE_LICENSE("GPL v2"); + +/* Match table for of_platform binding */ +static struct of_device_id xillybus_of_match[] = { + { .compatible = "xlnx,xillybus-1.00.a", }, + {} +}; + +MODULE_DEVICE_TABLE(of, xillybus_of_match); + +static void xilly_dma_sync_single_for_cpu_of(struct xilly_endpoint *ep, + dma_addr_t dma_handle, + size_t size, + int direction) +{ + dma_sync_single_for_cpu(ep->dev, dma_handle, size, direction); +} + +static void xilly_dma_sync_single_for_device_of(struct xilly_endpoint *ep, + dma_addr_t dma_handle, + size_t size, + int direction) +{ + dma_sync_single_for_device(ep->dev, dma_handle, size, direction); +} + +static dma_addr_t xilly_map_single_of(struct xilly_cleanup *mem, + struct xilly_endpoint *ep, + void *ptr, + size_t size, + int direction + ) +{ + + dma_addr_t addr = 0; + struct xilly_dma *this; + + this = kmalloc(sizeof(struct xilly_dma), GFP_KERNEL); + if (!this) + return 0; + + addr = dma_map_single(ep->dev, ptr, size, direction); + this->direction = direction; + + if (dma_mapping_error(ep->dev, addr)) { + kfree(this); + return 0; + } + + this->dma_addr = addr; + this->dev = ep->dev; + this->size = size; + + list_add_tail(&this->node, &mem->to_unmap); + + return addr; +} + +void xilly_unmap_single_of(struct xilly_dma *entry) +{ + dma_unmap_single(entry->dev, + entry->dma_addr, + entry->size, + entry->direction); +} + +static struct xilly_endpoint_hardware of_hw = { + .owner = THIS_MODULE, + .sync_single_for_cpu = xilly_dma_sync_single_for_cpu_of, + .sync_single_for_device = xilly_dma_sync_single_for_device_of, + .map_single = xilly_map_single_of, + .unmap_single = xilly_unmap_single_of +}; + +static int xilly_drv_probe(struct platform_device *op) +{ + struct device *dev = &op->dev; + struct xilly_endpoint *endpoint; + int rc = 0; + int irq; + + endpoint = xillybus_init_endpoint(NULL, dev, &of_hw); + + if (!endpoint) + return -ENOMEM; + + dev_set_drvdata(dev, endpoint); + + rc = of_address_to_resource(dev->of_node, 0, &endpoint->res); + if (rc) { + pr_warn("xillybus: Failed to obtain device tree " + "resource\n"); + goto failed_request_regions; + } + + if (!request_mem_region(endpoint->res.start, + resource_size(&endpoint->res), xillyname)) { + pr_err("xillybus: request_mem_region failed. Aborting.\n"); + rc = -EBUSY; + goto failed_request_regions; + } + + endpoint->registers = of_iomap(dev->of_node, 0); + + if (!endpoint->registers) { + pr_err("xillybus: Failed to map I/O memory. Aborting.\n"); + goto failed_iomap0; + } + + irq = irq_of_parse_and_map(dev->of_node, 0); + + rc = request_irq(irq, xillybus_isr, 0, xillyname, endpoint); + + if (rc) { + pr_err("xillybus: Failed to register IRQ handler. " + "Aborting.\n"); + rc = -ENODEV; + goto failed_register_irq; + } + + rc = xillybus_endpoint_discovery(endpoint); + + if (!rc) + return 0; + + free_irq(irq, endpoint); + +failed_register_irq: + iounmap(endpoint->registers); +failed_iomap0: + release_mem_region(endpoint->res.start, + resource_size(&endpoint->res)); + +failed_request_regions: + xillybus_do_cleanup(&endpoint->cleanup, endpoint); + + kfree(endpoint); + return rc; +} + +static int xilly_drv_remove(struct platform_device *op) +{ + struct device *dev = &op->dev; + struct xilly_endpoint *endpoint = dev_get_drvdata(dev); + int irq = irq_of_parse_and_map(dev->of_node, 0); + + xillybus_endpoint_remove(endpoint); + + free_irq(irq, endpoint); + + iounmap(endpoint->registers); + release_mem_region(endpoint->res.start, + resource_size(&endpoint->res)); + + xillybus_do_cleanup(&endpoint->cleanup, endpoint); + + kfree(endpoint); + + return 0; +} + +static struct platform_driver xillybus_platform_driver = { + .probe = xilly_drv_probe, + .remove = xilly_drv_remove, + .driver = { + .name = xillyname, + .owner = THIS_MODULE, + .of_match_table = xillybus_of_match, + }, +}; + +static int __init xillybus_of_init(void) +{ + return platform_driver_register(&xillybus_platform_driver); +} + +static void __exit xillybus_of_exit(void) +{ + platform_driver_unregister(&xillybus_platform_driver); +} + +module_init(xillybus_of_init); +module_exit(xillybus_of_exit); diff --git a/drivers/staging/xillybus/xillybus_pcie.c b/drivers/staging/xillybus/xillybus_pcie.c new file mode 100644 index 000000000000..592f8f7a0b2c --- /dev/null +++ b/drivers/staging/xillybus/xillybus_pcie.c @@ -0,0 +1,260 @@ +/* + * linux/drivers/misc/xillybus_pcie.c + * + * Copyright 2011 Xillybus Ltd, http://xillybus.com + * + * Driver for the Xillybus FPGA/host framework using PCI Express. + * + * This program is free software; you can redistribute it and/or modify + * it under the smems of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + */ + +#include +#include +#include +#include +#include "xillybus.h" + +MODULE_DESCRIPTION("Xillybus driver for PCIe"); +MODULE_AUTHOR("Eli Billauer, Xillybus Ltd."); +MODULE_VERSION("1.06"); +MODULE_ALIAS("xillybus_pcie"); +MODULE_LICENSE("GPL v2"); + +#define PCI_DEVICE_ID_XILLYBUS 0xebeb + +#define PCI_VENDOR_ID_ALTERA 0x1172 +#define PCI_VENDOR_ID_ACTEL 0x11aa +#define PCI_VENDOR_ID_LATTICE 0x1204 + +static DEFINE_PCI_DEVICE_TABLE(xillyids) = { + {PCI_DEVICE(PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_XILLYBUS)}, + {PCI_DEVICE(PCI_VENDOR_ID_ALTERA, PCI_DEVICE_ID_XILLYBUS)}, + {PCI_DEVICE(PCI_VENDOR_ID_ACTEL, PCI_DEVICE_ID_XILLYBUS)}, + {PCI_DEVICE(PCI_VENDOR_ID_LATTICE, PCI_DEVICE_ID_XILLYBUS)}, + { /* End: all zeroes */ } +}; + +static int xilly_pci_direction(int direction) +{ + switch (direction) { + case DMA_TO_DEVICE: + return PCI_DMA_TODEVICE; + case DMA_FROM_DEVICE: + return PCI_DMA_FROMDEVICE; + default: + return PCI_DMA_BIDIRECTIONAL; + } +} + +static void xilly_dma_sync_single_for_cpu_pci(struct xilly_endpoint *ep, + dma_addr_t dma_handle, + size_t size, + int direction) +{ + pci_dma_sync_single_for_cpu(ep->pdev, + dma_handle, + size, + xilly_pci_direction(direction)); +} + +static void xilly_dma_sync_single_for_device_pci(struct xilly_endpoint *ep, + dma_addr_t dma_handle, + size_t size, + int direction) +{ + pci_dma_sync_single_for_device(ep->pdev, + dma_handle, + size, + xilly_pci_direction(direction)); +} + +/* + * Map either through the PCI DMA mapper or the non_PCI one. Behind the + * scenes exactly the same functions are called with the same parameters, + * but that can change. + */ + +static dma_addr_t xilly_map_single_pci(struct xilly_cleanup *mem, + struct xilly_endpoint *ep, + void *ptr, + size_t size, + int direction + ) +{ + + dma_addr_t addr = 0; + struct xilly_dma *this; + int pci_direction; + + this = kmalloc(sizeof(struct xilly_dma), GFP_KERNEL); + if (!this) + return 0; + + pci_direction = xilly_pci_direction(direction); + addr = pci_map_single(ep->pdev, ptr, size, pci_direction); + this->direction = pci_direction; + + if (pci_dma_mapping_error(ep->pdev, addr)) { + kfree(this); + return 0; + } + + this->dma_addr = addr; + this->pdev = ep->pdev; + this->size = size; + + list_add_tail(&this->node, &mem->to_unmap); + + return addr; +} + +void xilly_unmap_single_pci(struct xilly_dma *entry) +{ + pci_unmap_single(entry->pdev, + entry->dma_addr, + entry->size, + entry->direction); +} + +static struct xilly_endpoint_hardware pci_hw = { + .owner = THIS_MODULE, + .sync_single_for_cpu = xilly_dma_sync_single_for_cpu_pci, + .sync_single_for_device = xilly_dma_sync_single_for_device_pci, + .map_single = xilly_map_single_pci, + .unmap_single = xilly_unmap_single_pci +}; + +static int xilly_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct xilly_endpoint *endpoint; + int rc = 0; + + endpoint = xillybus_init_endpoint(pdev, NULL, &pci_hw); + + if (!endpoint) + return -ENOMEM; + + pci_set_drvdata(pdev, endpoint); + + rc = pci_enable_device(pdev); + + /* L0s has caused packet drops. No power saving, thank you. */ + + pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S); + + if (rc) { + pr_err("xillybus: pci_enable_device() failed. " + "Aborting.\n"); + goto no_enable; + } + + if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { + pr_err("xillybus: Incorrect BAR configuration. " + "Aborting.\n"); + rc = -ENODEV; + goto bad_bar; + } + + rc = pci_request_regions(pdev, xillyname); + if (rc) { + pr_err("xillybus: pci_request_regions() failed. " + "Aborting.\n"); + goto failed_request_regions; + } + + endpoint->registers = pci_iomap(pdev, 0, 128); + + if (!endpoint->registers) { + pr_err("xillybus: Failed to map BAR 0. Aborting.\n"); + goto failed_iomap0; + } + + pci_set_master(pdev); + + /* Set up a single MSI interrupt */ + if (pci_enable_msi(pdev)) { + pr_err("xillybus: Failed to enable MSI interrupts. " + "Aborting.\n"); + rc = -ENODEV; + goto failed_enable_msi; + } + rc = request_irq(pdev->irq, xillybus_isr, 0, xillyname, endpoint); + + if (rc) { + pr_err("xillybus: Failed to register MSI handler. " + "Aborting.\n"); + rc = -ENODEV; + goto failed_register_msi; + } + + /* + * In theory, an attempt to set the DMA mask to 64 and dma_using_dac=1 + * is the right thing. But some unclever PCIe drivers report it's OK + * when the hardware drops those 64-bit PCIe packets. So trust + * nobody and use 32 bits DMA addressing in any case. + */ + + if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) + endpoint->dma_using_dac = 0; + else { + pr_err("xillybus: Failed to set DMA mask. " + "Aborting.\n"); + rc = -ENODEV; + goto failed_dmamask; + } + + rc = xillybus_endpoint_discovery(endpoint); + + if (!rc) + return 0; + +failed_dmamask: + free_irq(pdev->irq, endpoint); +failed_register_msi: + pci_disable_msi(pdev); +failed_enable_msi: + /* pci_clear_master(pdev); Nobody else seems to do this */ + pci_iounmap(pdev, endpoint->registers); +failed_iomap0: + pci_release_regions(pdev); +failed_request_regions: +bad_bar: + pci_disable_device(pdev); +no_enable: + xillybus_do_cleanup(&endpoint->cleanup, endpoint); + + kfree(endpoint); + return rc; +} + +static void xilly_remove(struct pci_dev *pdev) +{ + struct xilly_endpoint *endpoint = pci_get_drvdata(pdev); + + xillybus_endpoint_remove(endpoint); + + free_irq(pdev->irq, endpoint); + + pci_disable_msi(pdev); + pci_iounmap(pdev, endpoint->registers); + pci_release_regions(pdev); + pci_disable_device(pdev); + + xillybus_do_cleanup(&endpoint->cleanup, endpoint); + + kfree(endpoint); +} + +MODULE_DEVICE_TABLE(pci, xillyids); + +static struct pci_driver xillybus_driver = { + .name = xillyname, + .id_table = xillyids, + .probe = xilly_probe, + .remove = xilly_remove, +}; + +module_pci_driver(xillybus_driver); From 7c42721fe0c58a848849b43ff558cf2fb86aa35a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 25 Jul 2013 13:50:30 -0700 Subject: [PATCH 0774/3400] char: tile-srom: fix build error This fixes the build error: drivers/char/tile-srom.c:307:2: warning: missing braces around initializer [-Wmissing-braces] and the resulting fallout for the missing '*' character, sorry, my fault... Reported-by: kbuild test robot Signed-off-by: Greg Kroah-Hartman --- drivers/char/tile-srom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/tile-srom.c b/drivers/char/tile-srom.c index 344e97b91014..ae82933883bd 100644 --- a/drivers/char/tile-srom.c +++ b/drivers/char/tile-srom.c @@ -303,7 +303,7 @@ static ssize_t page_size_show(struct device *dev, } static DEVICE_ATTR_RO(page_size); -static struct attribute srom_dev_attrs[] = { +static struct attribute *srom_dev_attrs[] = { &dev_attr_total_size.attr, &dev_attr_sector_size.attr, &dev_attr_page_size.attr, From 2b4883972271f8d61de67aa365ade89dfff69db1 Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Wed, 24 Jul 2013 11:25:17 -0700 Subject: [PATCH 0775/3400] mutex: Avoid label warning when !CONFIG_MUTEX_SPIN_ON_OWNER Fengguang reported the following warning when optimistic spinning is disabled (ie: make allnoconfig): kernel/mutex.c:599:1: warning: label 'done' defined but not used Remove the 'done' label altogether. Reported-by: Fengguang Wu Signed-off-by: Davidlohr Bueso Signed-off-by: Ingo Molnar --- kernel/mutex.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/mutex.c b/kernel/mutex.c index 386ad5da47a5..98164a55a4dc 100644 --- a/kernel/mutex.c +++ b/kernel/mutex.c @@ -489,7 +489,8 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass, mutex_set_owner(lock); mspin_unlock(MLOCK(lock), &node); - goto done; + preempt_enable(); + return 0; } mspin_unlock(MLOCK(lock), &node); @@ -596,7 +597,6 @@ skip_wait: } spin_unlock_mutex(&lock->wait_lock, flags); -done: preempt_enable(); return 0; From 0177f29fea534ef5e6af2d76e9a9be0fdd325c4d Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 17 Jul 2013 08:33:25 +0800 Subject: [PATCH 0776/3400] ACPI / dock: fix error return code in dock_add() Fix to return -ENODEV in the acpi notify handler install error handling case instead of 0, as done elsewhere in this function. Signed-off-by: Wei Yongjun Signed-off-by: Rafael J. Wysocki --- drivers/acpi/dock.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index f601658a4ad2..b527c1bd8bb2 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -881,8 +881,10 @@ static int __init dock_add(acpi_handle handle) status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, dock_notify_handler, dock_station); - if (ACPI_FAILURE(status)) + if (ACPI_FAILURE(status)) { + ret = -ENODEV; goto err_rmgroup; + } dock_station_count++; list_add(&dock_station->sibling, &dock_stations); From 1129c92faa069581bf3acf34cae92477bd6161d8 Mon Sep 17 00:00:00 2001 From: Lv Zheng Date: Tue, 23 Jul 2013 16:11:55 +0800 Subject: [PATCH 0777/3400] ACPI: Cleanup sparse warning on acpi_os_initialize1() This patch cleans up the following sparse warning: # make C=2 drivers/acpi/osl.o ... drivers/acpi/osl.c:1775:20: warning: symbol 'acpi_os_initialize1' was not declared. Should it be static? ... CC drivers/acpi/osl.o Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/bus.c | 1 - drivers/acpi/internal.h | 1 + drivers/acpi/osl.c | 1 + 3 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index b6e9a3786e2d..25b289ff4290 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -617,7 +617,6 @@ static int __init acpi_bus_init(void) { int result; acpi_status status; - extern acpi_status acpi_os_initialize1(void); acpi_os_initialize1(); diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 3a50a34fe176..b636b7481f31 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -23,6 +23,7 @@ #define PREFIX "ACPI: " +acpi_status acpi_os_initialize1(void); int init_acpi_device_notify(void); int acpi_scan_init(void); #ifdef CONFIG_ACPI_PCI_SLOT diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 6ab2c3505520..605718f66642 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -52,6 +52,7 @@ #include #include #include +#include "internal.h" #define _COMPONENT ACPI_OS_SERVICES ACPI_MODULE_NAME("osl"); From c817a67ecba7c3c2aaa104796d78f160af60920d Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 27 Jun 2013 15:06:14 +0100 Subject: [PATCH 0778/3400] kobject: delayed kobject release: help find buggy drivers Implement debugging for kobject release functions. kobjects are reference counted, so the drop of the last reference to them is not predictable. However, the common case is for the last reference to be the kobject's removal from a subsystem, which results in the release function being immediately called. This can hide subtle bugs, which can occur when another thread holds a reference to the kobject at the same time that a kobject is removed. This results in the release method being delayed. In order to make these kinds of problems more visible, the following patch implements a delayed release; this has the effect that the release function will be out of order with respect to the removal of the kobject in the same manner that it would be if a reference was being held. This provides us with an easy way to allow driver writers to debug their drivers and fix otherwise hidden problems. Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- include/linux/kobject.h | 4 ++++ lib/Kconfig.debug | 19 +++++++++++++++++++ lib/kobject.c | 22 +++++++++++++++++++--- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/include/linux/kobject.h b/include/linux/kobject.h index 939b11268c86..de6dcbcc6ef7 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -26,6 +26,7 @@ #include #include #include +#include #define UEVENT_HELPER_PATH_LEN 256 #define UEVENT_NUM_ENVP 32 /* number of env pointers */ @@ -65,6 +66,9 @@ struct kobject { struct kobj_type *ktype; struct sysfs_dirent *sd; struct kref kref; +#ifdef CONFIG_DEBUG_KOBJECT_RELEASE + struct delayed_work release; +#endif unsigned int state_initialized:1; unsigned int state_in_sysfs:1; unsigned int state_add_uevent_sent:1; diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 1501aa553221..444e1c12fea9 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -981,6 +981,25 @@ config DEBUG_KOBJECT If you say Y here, some extra kobject debugging messages will be sent to the syslog. +config DEBUG_KOBJECT_RELEASE + bool "kobject release debugging" + depends on DEBUG_KERNEL + help + kobjects are reference counted objects. This means that their + last reference count put is not predictable, and the kobject can + live on past the point at which a driver decides to drop it's + initial reference to the kobject gained on allocation. An + example of this would be a struct device which has just been + unregistered. + + However, some buggy drivers assume that after such an operation, + the memory backing the kobject can be immediately freed. This + goes completely against the principles of a refcounted object. + + If you say Y here, the kernel will delay the release of kobjects + on the last reference count to improve the visibility of this + kind of kobject release bug. + config HAVE_DEBUG_BUGVERBOSE bool diff --git a/lib/kobject.c b/lib/kobject.c index 4a1f33d43548..1d46c151a4ae 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -545,8 +545,8 @@ static void kobject_cleanup(struct kobject *kobj) struct kobj_type *t = get_ktype(kobj); const char *name = kobj->name; - pr_debug("kobject: '%s' (%p): %s\n", - kobject_name(kobj), kobj, __func__); + pr_debug("kobject: '%s' (%p): %s, parent %p\n", + kobject_name(kobj), kobj, __func__, kobj->parent); if (t && !t->release) pr_debug("kobject: '%s' (%p): does not have a release() " @@ -580,9 +580,25 @@ static void kobject_cleanup(struct kobject *kobj) } } +#ifdef CONFIG_DEBUG_KOBJECT_RELEASE +static void kobject_delayed_cleanup(struct work_struct *work) +{ + kobject_cleanup(container_of(to_delayed_work(work), + struct kobject, release)); +} +#endif + static void kobject_release(struct kref *kref) { - kobject_cleanup(container_of(kref, struct kobject, kref)); + struct kobject *kobj = container_of(kref, struct kobject, kref); +#ifdef CONFIG_DEBUG_KOBJECT_RELEASE + pr_debug("kobject: '%s' (%p): %s, parent %p (delayed)\n", + kobject_name(kobj), kobj, __func__, kobj->parent); + INIT_DELAYED_WORK(&kobj->release, kobject_delayed_cleanup); + schedule_delayed_work(&kobj->release, HZ); +#else + kobject_cleanup(kobj); +#endif } /** From 3831261eb08557a1390b29c1038a0217232d8fdb Mon Sep 17 00:00:00 2001 From: "Brandt, Todd E" Date: Thu, 11 Jul 2013 07:44:35 +0000 Subject: [PATCH 0779/3400] PM / Sleep: increase ftrace coverage in suspend/resume Change where ftrace is disabled and re-enabled during system suspend/resume to allow tracing of device driver pm callbacks. Ftrace will now be turned off when suspend reaches disable_nonboot_cpus() instead of at the very beginning of system suspend. Ftrace was disabled during suspend/resume back in 2008 by Steven Rostedt as he discovered there was a conflict in the enable_nonboot_cpus() call (see commit f42ac38 "ftrace: disable tracing for suspend to ram"). This change preserves his fix by disabling ftrace, but only at the function where it is known to cause problems. The new change allows tracing of the device level code for better debug. [rjw: Changelog] Signed-off-by: Todd Brandt Signed-off-by: Rafael J. Wysocki --- kernel/power/suspend.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index ece04223bb1e..62ee437b5c7e 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c @@ -210,6 +210,7 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) goto Platform_wake; } + ftrace_stop(); error = disable_nonboot_cpus(); if (error || suspend_test(TEST_CPUS)) goto Enable_cpus; @@ -232,6 +233,7 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) Enable_cpus: enable_nonboot_cpus(); + ftrace_start(); Platform_wake: if (need_suspend_ops(state) && suspend_ops->wake) @@ -265,7 +267,6 @@ int suspend_devices_and_enter(suspend_state_t state) goto Close; } suspend_console(); - ftrace_stop(); suspend_test_start(); error = dpm_suspend_start(PMSG_SUSPEND); if (error) { @@ -285,7 +286,6 @@ int suspend_devices_and_enter(suspend_state_t state) suspend_test_start(); dpm_resume_end(PMSG_RESUME); suspend_test_finish("resume devices"); - ftrace_start(); resume_console(); Close: if (need_suspend_ops(state) && suspend_ops->end) From dfa5bb622555d9da0df21b50f46ebdeef390041b Mon Sep 17 00:00:00 2001 From: Stratos Karafotis Date: Wed, 5 Jun 2013 19:01:25 +0300 Subject: [PATCH 0780/3400] cpufreq: ondemand: Change the calculation of target frequency The ondemand governor calculates load in terms of frequency and increases it only if load_freq is greater than up_threshold multiplied by the current or average frequency. This appears to produce oscillations of frequency between min and max because, for example, a relatively small load can easily saturate minimum frequency and lead the CPU to the max. Then, it will decrease back to the min due to small load_freq. Change the calculation method of load and target frequency on the basis of the following two observations: - Load computation should not depend on the current or average measured frequency. For example, absolute load of 80% at 100MHz is not necessarily equivalent to 8% at 1000MHz in the next sampling interval. - It should be possible to increase the target frequency to any value present in the frequency table proportional to the absolute load, rather than to the max only, so that: Target frequency = C * load where we take C = policy->cpuinfo.max_freq / 100. Tested on Intel i7-3770 CPU @ 3.40GHz and on Quad core 1500MHz Krait. Phoronix benchmark of Linux Kernel Compilation 3.1 test shows an increase ~1.5% in performance. cpufreq_stats (time_in_state) shows that middle frequencies are used more, with this patch. Highest and lowest frequencies were used less by ~9%. [rjw: We have run multiple other tests on kernels with this change applied and in the vast majority of cases it turns out that the resulting performance improvement also leads to reduced consumption of energy. The change is additionally justified by the overall simplification of the code in question.] Signed-off-by: Stratos Karafotis Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq_governor.c | 10 +------- drivers/cpufreq/cpufreq_governor.h | 1 - drivers/cpufreq/cpufreq_ondemand.c | 39 ++++++------------------------ 3 files changed, 8 insertions(+), 42 deletions(-) diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c index 7b839a8db2a7..7409dbd1d897 100644 --- a/drivers/cpufreq/cpufreq_governor.c +++ b/drivers/cpufreq/cpufreq_governor.c @@ -53,7 +53,7 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu) policy = cdbs->cur_policy; - /* Get Absolute Load (in terms of freq for ondemand gov) */ + /* Get Absolute Load */ for_each_cpu(j, policy->cpus) { struct cpu_dbs_common_info *j_cdbs; u64 cur_wall_time, cur_idle_time; @@ -104,14 +104,6 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu) load = 100 * (wall_time - idle_time) / wall_time; - if (dbs_data->cdata->governor == GOV_ONDEMAND) { - int freq_avg = __cpufreq_driver_getavg(policy, j); - if (freq_avg <= 0) - freq_avg = policy->cur; - - load *= freq_avg; - } - if (load > max_load) max_load = load; } diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h index 6663ec3b3056..0e0dd4c82020 100644 --- a/drivers/cpufreq/cpufreq_governor.h +++ b/drivers/cpufreq/cpufreq_governor.h @@ -169,7 +169,6 @@ struct od_dbs_tuners { unsigned int sampling_rate; unsigned int sampling_down_factor; unsigned int up_threshold; - unsigned int adj_up_threshold; unsigned int powersave_bias; unsigned int io_is_busy; }; diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 93eb5cbcc1f6..a3c5574f9b3a 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -29,11 +29,9 @@ #include "cpufreq_governor.h" /* On-demand governor macros */ -#define DEF_FREQUENCY_DOWN_DIFFERENTIAL (10) #define DEF_FREQUENCY_UP_THRESHOLD (80) #define DEF_SAMPLING_DOWN_FACTOR (1) #define MAX_SAMPLING_DOWN_FACTOR (100000) -#define MICRO_FREQUENCY_DOWN_DIFFERENTIAL (3) #define MICRO_FREQUENCY_UP_THRESHOLD (95) #define MICRO_FREQUENCY_MIN_SAMPLE_RATE (10000) #define MIN_FREQUENCY_UP_THRESHOLD (11) @@ -161,14 +159,10 @@ static void dbs_freq_increase(struct cpufreq_policy *p, unsigned int freq) /* * Every sampling_rate, we check, if current idle time is less than 20% - * (default), then we try to increase frequency. Every sampling_rate, we look - * for the lowest frequency which can sustain the load while keeping idle time - * over 30%. If such a frequency exist, we try to decrease to this frequency. - * - * Any frequency increase takes it to the maximum frequency. Frequency reduction - * happens at minimum steps of 5% (default) of current frequency + * (default), then we try to increase frequency. Else, we adjust the frequency + * proportional to load. */ -static void od_check_cpu(int cpu, unsigned int load_freq) +static void od_check_cpu(int cpu, unsigned int load) { struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, cpu); struct cpufreq_policy *policy = dbs_info->cdbs.cur_policy; @@ -178,29 +172,17 @@ static void od_check_cpu(int cpu, unsigned int load_freq) dbs_info->freq_lo = 0; /* Check for frequency increase */ - if (load_freq > od_tuners->up_threshold * policy->cur) { + if (load > od_tuners->up_threshold) { /* If switching to max speed, apply sampling_down_factor */ if (policy->cur < policy->max) dbs_info->rate_mult = od_tuners->sampling_down_factor; dbs_freq_increase(policy, policy->max); return; - } - - /* Check for frequency decrease */ - /* if we cannot reduce the frequency anymore, break out early */ - if (policy->cur == policy->min) - return; - - /* - * The optimal frequency is the frequency that is the lowest that can - * support the current CPU usage without triggering the up policy. To be - * safe, we focus 10 points under the threshold. - */ - if (load_freq < od_tuners->adj_up_threshold - * policy->cur) { + } else { + /* Calculate the next frequency proportional to load */ unsigned int freq_next; - freq_next = load_freq / od_tuners->adj_up_threshold; + freq_next = load * policy->cpuinfo.max_freq / 100; /* No longer fully busy, reset rate_mult */ dbs_info->rate_mult = 1; @@ -374,9 +356,6 @@ static ssize_t store_up_threshold(struct dbs_data *dbs_data, const char *buf, input < MIN_FREQUENCY_UP_THRESHOLD) { return -EINVAL; } - /* Calculate the new adj_up_threshold */ - od_tuners->adj_up_threshold += input; - od_tuners->adj_up_threshold -= od_tuners->up_threshold; od_tuners->up_threshold = input; return count; @@ -525,8 +504,6 @@ static int od_init(struct dbs_data *dbs_data) if (idle_time != -1ULL) { /* Idle micro accounting is supported. Use finer thresholds */ tuners->up_threshold = MICRO_FREQUENCY_UP_THRESHOLD; - tuners->adj_up_threshold = MICRO_FREQUENCY_UP_THRESHOLD - - MICRO_FREQUENCY_DOWN_DIFFERENTIAL; /* * In nohz/micro accounting case we set the minimum frequency * not depending on HZ, but fixed (very low). The deferred @@ -535,8 +512,6 @@ static int od_init(struct dbs_data *dbs_data) dbs_data->min_sampling_rate = MICRO_FREQUENCY_MIN_SAMPLE_RATE; } else { tuners->up_threshold = DEF_FREQUENCY_UP_THRESHOLD; - tuners->adj_up_threshold = DEF_FREQUENCY_UP_THRESHOLD - - DEF_FREQUENCY_DOWN_DIFFERENTIAL; /* For correct statistics, we need 10 ticks for each measure */ dbs_data->min_sampling_rate = MIN_SAMPLING_RATE_RATIO * From 61c63e5ed3b9c472899d7152e961f2ffaafcf5a0 Mon Sep 17 00:00:00 2001 From: Stratos Karafotis Date: Wed, 5 Jun 2013 19:01:42 +0300 Subject: [PATCH 0781/3400] cpufreq: Remove unused APERF/MPERF support The target frequency calculation method in the ondemand governor has changed and it is now independent of the measured average frequency. Consequently, the APERF/MPERF support in cpufreq is not used any more, so drop it. [rjw: Changelog] Signed-off-by: Stratos Karafotis Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- arch/x86/include/asm/processor.h | 29 ------------------ drivers/cpufreq/Makefile | 2 +- drivers/cpufreq/acpi-cpufreq.c | 5 ---- drivers/cpufreq/mperf.c | 51 -------------------------------- drivers/cpufreq/mperf.h | 9 ------ 5 files changed, 1 insertion(+), 95 deletions(-) delete mode 100644 drivers/cpufreq/mperf.c delete mode 100644 drivers/cpufreq/mperf.h diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 24cf5aefb704..4f4a3d98c170 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -942,35 +942,6 @@ extern int set_tsc_mode(unsigned int val); extern u16 amd_get_nb_id(int cpu); -struct aperfmperf { - u64 aperf, mperf; -}; - -static inline void get_aperfmperf(struct aperfmperf *am) -{ - WARN_ON_ONCE(!boot_cpu_has(X86_FEATURE_APERFMPERF)); - - rdmsrl(MSR_IA32_APERF, am->aperf); - rdmsrl(MSR_IA32_MPERF, am->mperf); -} - -#define APERFMPERF_SHIFT 10 - -static inline -unsigned long calc_aperfmperf_ratio(struct aperfmperf *old, - struct aperfmperf *new) -{ - u64 aperf = new->aperf - old->aperf; - u64 mperf = new->mperf - old->mperf; - unsigned long ratio = aperf; - - mperf >>= APERFMPERF_SHIFT; - if (mperf) - ratio = div64_u64(aperf, mperf); - - return ratio; -} - extern unsigned long arch_align_stack(unsigned long sp); extern void free_init_pages(char *what, unsigned long begin, unsigned long end); diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index d345b5a7aa71..ad5866c2ada0 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -23,7 +23,7 @@ obj-$(CONFIG_GENERIC_CPUFREQ_CPU0) += cpufreq-cpu0.o # powernow-k8 can load then. ACPI is preferred to all other hardware-specific drivers. # speedstep-* is preferred over p4-clockmod. -obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi-cpufreq.o mperf.o +obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi-cpufreq.o obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o obj-$(CONFIG_X86_PCC_CPUFREQ) += pcc-cpufreq.o obj-$(CONFIG_X86_POWERNOW_K6) += powernow-k6.o diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index 39264020b88a..e673670d2321 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c @@ -45,7 +45,6 @@ #include #include #include -#include "mperf.h" MODULE_AUTHOR("Paul Diefenbaugh, Dominik Brodowski"); MODULE_DESCRIPTION("ACPI Processor P-States Driver"); @@ -861,10 +860,6 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) /* notify BIOS that we exist */ acpi_processor_notify_smm(THIS_MODULE); - /* Check for APERF/MPERF support in hardware */ - if (boot_cpu_has(X86_FEATURE_APERFMPERF)) - acpi_cpufreq_driver.getavg = cpufreq_get_measured_perf; - pr_debug("CPU%u - ACPI performance management activated.\n", cpu); for (i = 0; i < perf->state_count; i++) pr_debug(" %cP%d: %d MHz, %d mW, %d uS\n", diff --git a/drivers/cpufreq/mperf.c b/drivers/cpufreq/mperf.c deleted file mode 100644 index 911e193018ae..000000000000 --- a/drivers/cpufreq/mperf.c +++ /dev/null @@ -1,51 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include "mperf.h" - -static DEFINE_PER_CPU(struct aperfmperf, acfreq_old_perf); - -/* Called via smp_call_function_single(), on the target CPU */ -static void read_measured_perf_ctrs(void *_cur) -{ - struct aperfmperf *am = _cur; - - get_aperfmperf(am); -} - -/* - * Return the measured active (C0) frequency on this CPU since last call - * to this function. - * Input: cpu number - * Return: Average CPU frequency in terms of max frequency (zero on error) - * - * We use IA32_MPERF and IA32_APERF MSRs to get the measured performance - * over a period of time, while CPU is in C0 state. - * IA32_MPERF counts at the rate of max advertised frequency - * IA32_APERF counts at the rate of actual CPU frequency - * Only IA32_APERF/IA32_MPERF ratio is architecturally defined and - * no meaning should be associated with absolute values of these MSRs. - */ -unsigned int cpufreq_get_measured_perf(struct cpufreq_policy *policy, - unsigned int cpu) -{ - struct aperfmperf perf; - unsigned long ratio; - unsigned int retval; - - if (smp_call_function_single(cpu, read_measured_perf_ctrs, &perf, 1)) - return 0; - - ratio = calc_aperfmperf_ratio(&per_cpu(acfreq_old_perf, cpu), &perf); - per_cpu(acfreq_old_perf, cpu) = perf; - - retval = (policy->cpuinfo.max_freq * ratio) >> APERFMPERF_SHIFT; - - return retval; -} -EXPORT_SYMBOL_GPL(cpufreq_get_measured_perf); -MODULE_LICENSE("GPL"); diff --git a/drivers/cpufreq/mperf.h b/drivers/cpufreq/mperf.h deleted file mode 100644 index 5dbf2950dc22..000000000000 --- a/drivers/cpufreq/mperf.h +++ /dev/null @@ -1,9 +0,0 @@ -/* - * (c) 2010 Advanced Micro Devices, Inc. - * Your use of this code is subject to the terms and conditions of the - * GNU general public license version 2. See "COPYING" or - * http://www.gnu.org/licenses/gpl.html - */ - -unsigned int cpufreq_get_measured_perf(struct cpufreq_policy *policy, - unsigned int cpu); From cffe4e0e7413eb29fb8bd035c8b12b33a4b8522a Mon Sep 17 00:00:00 2001 From: Stratos Karafotis Date: Wed, 5 Jun 2013 19:01:50 +0300 Subject: [PATCH 0782/3400] cpufreq: Remove unused function __cpufreq_driver_getavg() The target frequency calculation method in the ondemand governor has changed and it is now independent of the measured average frequency. Consequently, the __cpufreq_driver_getavg() function and getavg member of struct cpufreq_driver are not used any more, so drop them. [rjw: Changelog] Signed-off-by: Stratos Karafotis Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq.c | 12 ------------ include/linux/cpufreq.h | 6 ------ 2 files changed, 18 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index a4ad7339588d..9a9d8ee9faec 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1593,18 +1593,6 @@ fail: } EXPORT_SYMBOL_GPL(cpufreq_driver_target); -int __cpufreq_driver_getavg(struct cpufreq_policy *policy, unsigned int cpu) -{ - if (cpufreq_disabled()) - return 0; - - if (!cpufreq_driver->getavg) - return 0; - - return cpufreq_driver->getavg(policy, cpu); -} -EXPORT_SYMBOL_GPL(__cpufreq_driver_getavg); - /* * when "event" is CPUFREQ_GOV_LIMITS */ diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 90d5a15120d5..e1fd215e16c9 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -216,10 +216,6 @@ extern int cpufreq_driver_target(struct cpufreq_policy *policy, extern int __cpufreq_driver_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation); - -extern int __cpufreq_driver_getavg(struct cpufreq_policy *policy, - unsigned int cpu); - int cpufreq_register_governor(struct cpufreq_governor *governor); void cpufreq_unregister_governor(struct cpufreq_governor *governor); @@ -258,8 +254,6 @@ struct cpufreq_driver { unsigned int (*get) (unsigned int cpu); /* optional */ - unsigned int (*getavg) (struct cpufreq_policy *policy, - unsigned int cpu); int (*bios_limit) (int cpu, unsigned int *limit); int (*exit) (struct cpufreq_policy *policy); From 58b267d3e3f3ce87c3e559e4c330c8c03e905f5e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Jul 2013 15:05:08 -0700 Subject: [PATCH 0783/3400] dma: convert dma_devclass to use dev_groups The dev_attrs field of struct class is going away soon, dev_groups should be used instead. This converts the dma dma_devclass code to use the correct field. Cc: Dan Williams Acked-by: Vinod Koul Signed-off-by: Greg Kroah-Hartman --- drivers/dma/dmaengine.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index 9e56745f87bf..99af4db5948b 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -87,7 +87,8 @@ static struct dma_chan *dev_to_dma_chan(struct device *dev) return chan_dev->chan; } -static ssize_t show_memcpy_count(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t memcpy_count_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct dma_chan *chan; unsigned long count = 0; @@ -106,9 +107,10 @@ static ssize_t show_memcpy_count(struct device *dev, struct device_attribute *at return err; } +static DEVICE_ATTR_RO(memcpy_count); -static ssize_t show_bytes_transferred(struct device *dev, struct device_attribute *attr, - char *buf) +static ssize_t bytes_transferred_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct dma_chan *chan; unsigned long count = 0; @@ -127,8 +129,10 @@ static ssize_t show_bytes_transferred(struct device *dev, struct device_attribut return err; } +static DEVICE_ATTR_RO(bytes_transferred); -static ssize_t show_in_use(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t in_use_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct dma_chan *chan; int err; @@ -143,13 +147,15 @@ static ssize_t show_in_use(struct device *dev, struct device_attribute *attr, ch return err; } +static DEVICE_ATTR_RO(in_use); -static struct device_attribute dma_attrs[] = { - __ATTR(memcpy_count, S_IRUGO, show_memcpy_count, NULL), - __ATTR(bytes_transferred, S_IRUGO, show_bytes_transferred, NULL), - __ATTR(in_use, S_IRUGO, show_in_use, NULL), - __ATTR_NULL +static struct attribute *dma_dev_attrs[] = { + &dev_attr_memcpy_count.attr, + &dev_attr_bytes_transferred.attr, + &dev_attr_in_use.attr, + NULL, }; +ATTRIBUTE_GROUPS(dma_dev); static void chan_dev_release(struct device *dev) { @@ -167,7 +173,7 @@ static void chan_dev_release(struct device *dev) static struct class dma_devclass = { .name = "dma", - .dev_attrs = dma_attrs, + .dev_groups = dma_dev_groups, .dev_release = chan_dev_release, }; From af01da0e02def46c7f32f86811d6befb6ca16170 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Jul 2013 15:05:10 -0700 Subject: [PATCH 0784/3400] extcon: convert extcon_class to use dev_groups The dev_attrs field of struct class is going away soon, dev_groups should be used instead. This converts the extcon_class code to use the correct field. Cc: MyungJoo Ham Acked-by: Chanwoo Choi Signed-off-by: Greg Kroah-Hartman --- drivers/extcon/extcon-class.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c index 18ccadef43fd..022ca369834a 100644 --- a/drivers/extcon/extcon-class.c +++ b/drivers/extcon/extcon-class.c @@ -148,6 +148,7 @@ static ssize_t state_store(struct device *dev, struct device_attribute *attr, return count; } +static DEVICE_ATTR_RW(state); static ssize_t name_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -163,6 +164,7 @@ static ssize_t name_show(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%s\n", dev_name(edev->dev)); } +static DEVICE_ATTR_RO(name); static ssize_t cable_name_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -527,11 +529,12 @@ int extcon_unregister_notifier(struct extcon_dev *edev, } EXPORT_SYMBOL_GPL(extcon_unregister_notifier); -static struct device_attribute extcon_attrs[] = { - __ATTR(state, S_IRUGO | S_IWUSR, state_show, state_store), - __ATTR_RO(name), - __ATTR_NULL, +static struct attribute *extcon_attrs[] = { + &dev_attr_state.attr, + &dev_attr_name.attr, + NULL, }; +ATTRIBUTE_GROUPS(extcon); static int create_extcon_class(void) { @@ -539,7 +542,7 @@ static int create_extcon_class(void) extcon_class = class_create(THIS_MODULE, "extcon"); if (IS_ERR(extcon_class)) return PTR_ERR(extcon_class); - extcon_class->dev_attrs = extcon_attrs; + extcon_class->dev_groups = extcon_groups; #if defined(CONFIG_ANDROID) switch_class = class_compat_register("switch"); From 92a3e661bf55457091817c5c346c4313be2508af Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Jul 2013 15:05:27 -0700 Subject: [PATCH 0785/3400] SCSI: OSD: convert class code to use dev_groups The dev_attrs field of struct class is going away soon, dev_groups should be used instead. This converts the scsi osd class code to use the correct field. Acked-by: Boaz Harrosh Cc: Benny Halevy Cc: James E.J. Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/osd/osd_uld.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c index 9d86947d67fe..e1d9a4c4c4b3 100644 --- a/drivers/scsi/osd/osd_uld.c +++ b/drivers/scsi/osd/osd_uld.c @@ -107,6 +107,7 @@ static ssize_t osdname_show(struct device *dev, struct device_attribute *attr, class_dev); return sprintf(buf, "%s\n", ould->odi.osdname); } +static DEVICE_ATTR_RO(osdname); static ssize_t systemid_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -117,17 +118,19 @@ static ssize_t systemid_show(struct device *dev, struct device_attribute *attr, memcpy(buf, ould->odi.systemid, ould->odi.systemid_len); return ould->odi.systemid_len; } +static DEVICE_ATTR_RO(systemid); -static struct device_attribute osd_uld_attrs[] = { - __ATTR(osdname, S_IRUGO, osdname_show, NULL), - __ATTR(systemid, S_IRUGO, systemid_show, NULL), - __ATTR_NULL, +static struct attribute *osd_uld_attrs[] = { + &dev_attr_osdname.attr, + &dev_attr_systemid.attr, + NULL, }; +ATTRIBUTE_GROUPS(osd_uld); static struct class osd_uld_class = { .owner = THIS_MODULE, .name = "scsi_osd", - .dev_attrs = osd_uld_attrs, + .dev_groups = osd_uld_groups, }; /* From ea1bb7064fd6972ef00a93ba882a2f38450b273e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Jul 2013 15:05:30 -0700 Subject: [PATCH 0786/3400] video: backlight: convert class code to use dev_groups The dev_attrs field of struct class is going away soon, dev_groups should be used instead. This converts the video backlight class code to use the correct field. Cc: Richard Purdie Acked-by: Jingoo Han Signed-off-by: Greg Kroah-Hartman --- drivers/video/backlight/backlight.c | 44 ++++++++++++++++------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index 3fccb6d3c8c3..94a403a9717a 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c @@ -103,16 +103,16 @@ static void backlight_generate_event(struct backlight_device *bd, sysfs_notify(&bd->dev.kobj, NULL, "actual_brightness"); } -static ssize_t backlight_show_power(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t bl_power_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct backlight_device *bd = to_backlight_device(dev); return sprintf(buf, "%d\n", bd->props.power); } -static ssize_t backlight_store_power(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) +static ssize_t bl_power_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { int rc; struct backlight_device *bd = to_backlight_device(dev); @@ -136,8 +136,9 @@ static ssize_t backlight_store_power(struct device *dev, return rc; } +static DEVICE_ATTR_RW(bl_power); -static ssize_t backlight_show_brightness(struct device *dev, +static ssize_t brightness_show(struct device *dev, struct device_attribute *attr, char *buf) { struct backlight_device *bd = to_backlight_device(dev); @@ -145,7 +146,7 @@ static ssize_t backlight_show_brightness(struct device *dev, return sprintf(buf, "%d\n", bd->props.brightness); } -static ssize_t backlight_store_brightness(struct device *dev, +static ssize_t brightness_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int rc; @@ -175,24 +176,27 @@ static ssize_t backlight_store_brightness(struct device *dev, return rc; } +static DEVICE_ATTR_RW(brightness); -static ssize_t backlight_show_type(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t type_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct backlight_device *bd = to_backlight_device(dev); return sprintf(buf, "%s\n", backlight_types[bd->props.type]); } +static DEVICE_ATTR_RO(type); -static ssize_t backlight_show_max_brightness(struct device *dev, +static ssize_t max_brightness_show(struct device *dev, struct device_attribute *attr, char *buf) { struct backlight_device *bd = to_backlight_device(dev); return sprintf(buf, "%d\n", bd->props.max_brightness); } +static DEVICE_ATTR_RO(max_brightness); -static ssize_t backlight_show_actual_brightness(struct device *dev, +static ssize_t actual_brightness_show(struct device *dev, struct device_attribute *attr, char *buf) { int rc = -ENXIO; @@ -205,6 +209,7 @@ static ssize_t backlight_show_actual_brightness(struct device *dev, return rc; } +static DEVICE_ATTR_RO(actual_brightness); static struct class *backlight_class; @@ -247,16 +252,15 @@ static void bl_device_release(struct device *dev) kfree(bd); } -static struct device_attribute bl_device_attributes[] = { - __ATTR(bl_power, 0644, backlight_show_power, backlight_store_power), - __ATTR(brightness, 0644, backlight_show_brightness, - backlight_store_brightness), - __ATTR(actual_brightness, 0444, backlight_show_actual_brightness, - NULL), - __ATTR(max_brightness, 0444, backlight_show_max_brightness, NULL), - __ATTR(type, 0444, backlight_show_type, NULL), - __ATTR_NULL, +static struct attribute *bl_device_attrs[] = { + &dev_attr_bl_power.attr, + &dev_attr_brightness.attr, + &dev_attr_actual_brightness.attr, + &dev_attr_max_brightness.attr, + &dev_attr_type.attr, + NULL, }; +ATTRIBUTE_GROUPS(bl_device); /** * backlight_force_update - tell the backlight subsystem that hardware state @@ -493,7 +497,7 @@ static int __init backlight_class_init(void) return PTR_ERR(backlight_class); } - backlight_class->dev_attrs = bl_device_attributes; + backlight_class->dev_groups = bl_device_groups; backlight_class->pm = &backlight_class_dev_pm_ops; return 0; } From d79fd03fd651bd91a081fc97f5f0d221557f8cbb Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Jul 2013 15:05:31 -0700 Subject: [PATCH 0787/3400] video: backlight: lcd: convert class code to use dev_groups The dev_attrs field of struct class is going away soon, dev_groups should be used instead. This converts the video backlight lcd class code to use the correct field. Cc: Richard Purdie Acked-by: Jingoo Han Signed-off-by: Greg Kroah-Hartman --- drivers/video/backlight/lcd.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c index 41964a71a036..93cf15efc717 100644 --- a/drivers/video/backlight/lcd.c +++ b/drivers/video/backlight/lcd.c @@ -89,7 +89,7 @@ static inline void lcd_unregister_fb(struct lcd_device *ld) } #endif /* CONFIG_FB */ -static ssize_t lcd_show_power(struct device *dev, struct device_attribute *attr, +static ssize_t lcd_power_show(struct device *dev, struct device_attribute *attr, char *buf) { int rc; @@ -105,7 +105,7 @@ static ssize_t lcd_show_power(struct device *dev, struct device_attribute *attr, return rc; } -static ssize_t lcd_store_power(struct device *dev, +static ssize_t lcd_power_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int rc; @@ -128,8 +128,9 @@ static ssize_t lcd_store_power(struct device *dev, return rc; } +static DEVICE_ATTR_RW(lcd_power); -static ssize_t lcd_show_contrast(struct device *dev, +static ssize_t contrast_show(struct device *dev, struct device_attribute *attr, char *buf) { int rc = -ENXIO; @@ -143,7 +144,7 @@ static ssize_t lcd_show_contrast(struct device *dev, return rc; } -static ssize_t lcd_store_contrast(struct device *dev, +static ssize_t contrast_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int rc; @@ -166,14 +167,16 @@ static ssize_t lcd_store_contrast(struct device *dev, return rc; } +static DEVICE_ATTR_RW(contrast); -static ssize_t lcd_show_max_contrast(struct device *dev, +static ssize_t max_contrast_show(struct device *dev, struct device_attribute *attr, char *buf) { struct lcd_device *ld = to_lcd_device(dev); return sprintf(buf, "%d\n", ld->props.max_contrast); } +static DEVICE_ATTR_RO(max_contrast); static struct class *lcd_class; @@ -183,12 +186,13 @@ static void lcd_device_release(struct device *dev) kfree(ld); } -static struct device_attribute lcd_device_attributes[] = { - __ATTR(lcd_power, 0644, lcd_show_power, lcd_store_power), - __ATTR(contrast, 0644, lcd_show_contrast, lcd_store_contrast), - __ATTR(max_contrast, 0444, lcd_show_max_contrast, NULL), - __ATTR_NULL, +static struct attribute *lcd_device_attrs[] = { + &dev_attr_lcd_power.attr, + &dev_attr_contrast.attr, + &dev_attr_max_contrast.attr, + NULL, }; +ATTRIBUTE_GROUPS(lcd_device); /** * lcd_device_register - register a new object of lcd_device class. @@ -344,7 +348,7 @@ static int __init lcd_class_init(void) return PTR_ERR(lcd_class); } - lcd_class->dev_attrs = lcd_device_attributes; + lcd_class->dev_groups = lcd_device_groups; return 0; } From f0bc99c84349ce87af5b35839d19bfb17bb9b27f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Jul 2013 15:05:35 -0700 Subject: [PATCH 0788/3400] net: wireless: convert class code to use dev_groups The dev_attrs field of struct class is going away soon, dev_groups should be used instead. This converts the networking wireless class code to use the correct field. Reviewed-by: Johannes Berg Cc: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/wireless/sysfs.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c index a23253e06358..9ee6bc1a7610 100644 --- a/net/wireless/sysfs.c +++ b/net/wireless/sysfs.c @@ -30,7 +30,8 @@ static ssize_t name ## _show(struct device *dev, \ char *buf) \ { \ return sprintf(buf, fmt "\n", dev_to_rdev(dev)->member); \ -} +} \ +static DEVICE_ATTR_RO(name) SHOW_FMT(index, "%d", wiphy_idx); SHOW_FMT(macaddress, "%pM", wiphy.perm_addr); @@ -42,7 +43,7 @@ static ssize_t name_show(struct device *dev, struct wiphy *wiphy = &dev_to_rdev(dev)->wiphy; return sprintf(buf, "%s\n", dev_name(&wiphy->dev)); } - +static DEVICE_ATTR_RO(name); static ssize_t addresses_show(struct device *dev, struct device_attribute *attr, @@ -60,15 +61,17 @@ static ssize_t addresses_show(struct device *dev, return buf - start; } +static DEVICE_ATTR_RO(addresses); -static struct device_attribute ieee80211_dev_attrs[] = { - __ATTR_RO(index), - __ATTR_RO(macaddress), - __ATTR_RO(address_mask), - __ATTR_RO(addresses), - __ATTR_RO(name), - {} +static struct attribute *ieee80211_attrs[] = { + &dev_attr_index.attr, + &dev_attr_macaddress.attr, + &dev_attr_address_mask.attr, + &dev_attr_addresses.attr, + &dev_attr_name.attr, + NULL, }; +ATTRIBUTE_GROUPS(ieee80211); static void wiphy_dev_release(struct device *dev) { @@ -146,7 +149,7 @@ struct class ieee80211_class = { .name = "ieee80211", .owner = THIS_MODULE, .dev_release = wiphy_dev_release, - .dev_attrs = ieee80211_dev_attrs, + .dev_groups = ieee80211_groups, .dev_uevent = wiphy_uevent, #ifdef CONFIG_PM .suspend = wiphy_suspend, From e49df67df1296b804f49b17a4f095a627fe059f4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Jul 2013 15:05:36 -0700 Subject: [PATCH 0789/3400] net: rfkill: convert class code to use dev_groups The dev_attrs field of struct class is going away soon, dev_groups should be used instead. This converts the rfkill class code to use the correct field. Cc: John W. Linville Reviewed-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/rfkill/core.c | 88 +++++++++++++++++++++-------------------------- 1 file changed, 40 insertions(+), 48 deletions(-) diff --git a/net/rfkill/core.c b/net/rfkill/core.c index 1cec5e4f3a5e..1bacc1079942 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c @@ -576,14 +576,14 @@ void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw) } EXPORT_SYMBOL(rfkill_set_states); -static ssize_t rfkill_name_show(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t name_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct rfkill *rfkill = to_rfkill(dev); return sprintf(buf, "%s\n", rfkill->name); } +static DEVICE_ATTR_RO(name); static const char *rfkill_get_type_str(enum rfkill_type type) { @@ -611,54 +611,52 @@ static const char *rfkill_get_type_str(enum rfkill_type type) } } -static ssize_t rfkill_type_show(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t type_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct rfkill *rfkill = to_rfkill(dev); return sprintf(buf, "%s\n", rfkill_get_type_str(rfkill->type)); } +static DEVICE_ATTR_RO(type); -static ssize_t rfkill_idx_show(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t index_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct rfkill *rfkill = to_rfkill(dev); return sprintf(buf, "%d\n", rfkill->idx); } +static DEVICE_ATTR_RO(index); -static ssize_t rfkill_persistent_show(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t persistent_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct rfkill *rfkill = to_rfkill(dev); return sprintf(buf, "%d\n", rfkill->persistent); } +static DEVICE_ATTR_RO(persistent); -static ssize_t rfkill_hard_show(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t hard_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct rfkill *rfkill = to_rfkill(dev); return sprintf(buf, "%d\n", (rfkill->state & RFKILL_BLOCK_HW) ? 1 : 0 ); } +static DEVICE_ATTR_RO(hard); -static ssize_t rfkill_soft_show(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t soft_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct rfkill *rfkill = to_rfkill(dev); return sprintf(buf, "%d\n", (rfkill->state & RFKILL_BLOCK_SW) ? 1 : 0 ); } -static ssize_t rfkill_soft_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t soft_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct rfkill *rfkill = to_rfkill(dev); unsigned long state; @@ -680,6 +678,7 @@ static ssize_t rfkill_soft_store(struct device *dev, return count; } +static DEVICE_ATTR_RW(soft); static u8 user_state_from_blocked(unsigned long state) { @@ -691,18 +690,16 @@ static u8 user_state_from_blocked(unsigned long state) return RFKILL_USER_STATE_UNBLOCKED; } -static ssize_t rfkill_state_show(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t state_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct rfkill *rfkill = to_rfkill(dev); return sprintf(buf, "%d\n", user_state_from_blocked(rfkill->state)); } -static ssize_t rfkill_state_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t state_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct rfkill *rfkill = to_rfkill(dev); unsigned long state; @@ -725,32 +722,27 @@ static ssize_t rfkill_state_store(struct device *dev, return count; } +static DEVICE_ATTR_RW(state); -static ssize_t rfkill_claim_show(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t claim_show(struct device *dev, struct device_attribute *attr, + char *buf) { return sprintf(buf, "%d\n", 0); } +static DEVICE_ATTR_RO(claim); -static ssize_t rfkill_claim_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - return -EOPNOTSUPP; -} - -static struct device_attribute rfkill_dev_attrs[] = { - __ATTR(name, S_IRUGO, rfkill_name_show, NULL), - __ATTR(type, S_IRUGO, rfkill_type_show, NULL), - __ATTR(index, S_IRUGO, rfkill_idx_show, NULL), - __ATTR(persistent, S_IRUGO, rfkill_persistent_show, NULL), - __ATTR(state, S_IRUGO|S_IWUSR, rfkill_state_show, rfkill_state_store), - __ATTR(claim, S_IRUGO|S_IWUSR, rfkill_claim_show, rfkill_claim_store), - __ATTR(soft, S_IRUGO|S_IWUSR, rfkill_soft_show, rfkill_soft_store), - __ATTR(hard, S_IRUGO, rfkill_hard_show, NULL), - __ATTR_NULL +static struct attribute *rfkill_dev_attrs[] = { + &dev_attr_name.attr, + &dev_attr_type.attr, + &dev_attr_index.attr, + &dev_attr_persistent.attr, + &dev_attr_state.attr, + &dev_attr_claim.attr, + &dev_attr_soft.attr, + &dev_attr_hard.attr, + NULL, }; +ATTRIBUTE_GROUPS(rfkill_dev); static void rfkill_release(struct device *dev) { @@ -830,7 +822,7 @@ static int rfkill_resume(struct device *dev) static struct class rfkill_class = { .name = "rfkill", .dev_release = rfkill_release, - .dev_attrs = rfkill_dev_attrs, + .dev_groups = rfkill_dev_groups, .dev_uevent = rfkill_dev_uevent, .suspend = rfkill_suspend, .resume = rfkill_resume, From b2634562ad90be16441cff1127136457ea619466 Mon Sep 17 00:00:00 2001 From: John Sheu Date: Thu, 30 May 2013 16:42:08 -0300 Subject: [PATCH 0790/3400] [media] s5p-mfc: Fix input/output format reporting The video encode/decode paths have duplicated logic between VIDIOC_TRY_FMT and VIDIOC_S_FMT that should be de-duped. Also, video decode reports V4L2_PIX_FMT_NV12MT_16X16 output format, regardless of what the actual output has been set at. Fix this. Signed-off-by: John Sheu Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/s5p-mfc/s5p_mfc_dec.c | 83 ++++++++------------ drivers/media/platform/s5p-mfc/s5p_mfc_enc.c | 46 ++++------- 2 files changed, 50 insertions(+), 79 deletions(-) diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c index 00b07032f4f0..06091c01176a 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c @@ -344,7 +344,7 @@ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) pix_mp->num_planes = 2; /* Set pixelformat to the format in which MFC outputs the decoded frame */ - pix_mp->pixelformat = V4L2_PIX_FMT_NV12MT; + pix_mp->pixelformat = ctx->dst_fmt->fourcc; pix_mp->plane_fmt[0].bytesperline = ctx->buf_width; pix_mp->plane_fmt[0].sizeimage = ctx->luma_size; pix_mp->plane_fmt[1].bytesperline = ctx->buf_width; @@ -382,10 +382,16 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) mfc_err("Unsupported format for source.\n"); return -EINVAL; } - if (!IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_VP8)) { - mfc_err("Not supported format.\n"); + if (fmt->codec_mode == S5P_FIMV_CODEC_NONE) { + mfc_err("Unknown codec\n"); return -EINVAL; } + if (!IS_MFCV6(dev)) { + if (fmt->fourcc == V4L2_PIX_FMT_VP8) { + mfc_err("Not supported format.\n"); + return -EINVAL; + } + } } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { fmt = find_format(f, MFC_FMT_RAW); if (!fmt) { @@ -411,7 +417,6 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) struct s5p_mfc_dev *dev = video_drvdata(file); struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); int ret = 0; - struct s5p_mfc_fmt *fmt; struct v4l2_pix_format_mplane *pix_mp; mfc_debug_enter(); @@ -425,54 +430,32 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) goto out; } if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { - fmt = find_format(f, MFC_FMT_RAW); - if (!fmt) { - mfc_err("Unsupported format for source.\n"); - return -EINVAL; - } - if (!IS_MFCV6(dev) && (fmt->fourcc != V4L2_PIX_FMT_NV12MT)) { - mfc_err("Not supported format.\n"); - return -EINVAL; - } else if (IS_MFCV6(dev) && - (fmt->fourcc == V4L2_PIX_FMT_NV12MT)) { - mfc_err("Not supported format.\n"); - return -EINVAL; - } - ctx->dst_fmt = fmt; - mfc_debug_leave(); - return ret; - } else if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { - mfc_err("Wrong type error for S_FMT : %d", f->type); - return -EINVAL; - } - fmt = find_format(f, MFC_FMT_DEC); - if (!fmt || fmt->codec_mode == S5P_MFC_CODEC_NONE) { - mfc_err("Unknown codec\n"); - ret = -EINVAL; + /* dst_fmt is validated by call to vidioc_try_fmt */ + ctx->dst_fmt = find_format(f, MFC_FMT_RAW); + ret = 0; goto out; - } - if (fmt->type != MFC_FMT_DEC) { - mfc_err("Wrong format selected, you should choose " - "format for decoding\n"); - ret = -EINVAL; - goto out; - } - if (!IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_VP8)) { - mfc_err("Not supported format.\n"); - return -EINVAL; - } - ctx->src_fmt = fmt; - ctx->codec_mode = fmt->codec_mode; - mfc_debug(2, "The codec number is: %d\n", ctx->codec_mode); - pix_mp->height = 0; - pix_mp->width = 0; - if (pix_mp->plane_fmt[0].sizeimage) - ctx->dec_src_buf_size = pix_mp->plane_fmt[0].sizeimage; - else - pix_mp->plane_fmt[0].sizeimage = ctx->dec_src_buf_size = + } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { + /* src_fmt is validated by call to vidioc_try_fmt */ + ctx->src_fmt = find_format(f, MFC_FMT_DEC); + ctx->codec_mode = ctx->src_fmt->codec_mode; + mfc_debug(2, "The codec number is: %d\n", ctx->codec_mode); + pix_mp->height = 0; + pix_mp->width = 0; + if (pix_mp->plane_fmt[0].sizeimage) + ctx->dec_src_buf_size = pix_mp->plane_fmt[0].sizeimage; + else + pix_mp->plane_fmt[0].sizeimage = ctx->dec_src_buf_size = DEF_CPB_SIZE; - pix_mp->plane_fmt[0].bytesperline = 0; - ctx->state = MFCINST_INIT; + pix_mp->plane_fmt[0].bytesperline = 0; + ctx->state = MFCINST_INIT; + ret = 0; + goto out; + } else { + mfc_err("Wrong type error for S_FMT : %d", f->type); + ret = -EINVAL; + goto out; + } + out: mfc_debug_leave(); return ret; diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c index 2549967b2f85..59e56f4c8ce3 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c @@ -906,6 +906,7 @@ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) { + struct s5p_mfc_dev *dev = video_drvdata(file); struct s5p_mfc_fmt *fmt; struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp; @@ -930,6 +931,18 @@ static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f) return -EINVAL; } + if (!IS_MFCV6(dev)) { + if (fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16) { + mfc_err("Not supported format.\n"); + return -EINVAL; + } + } else if (IS_MFCV6(dev)) { + if (fmt->fourcc == V4L2_PIX_FMT_NV12MT) { + mfc_err("Not supported format.\n"); + return -EINVAL; + } + } + if (fmt->num_planes != pix_fmt_mp->num_planes) { mfc_err("failed to try output format\n"); return -EINVAL; @@ -947,7 +960,6 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) { struct s5p_mfc_dev *dev = video_drvdata(file); struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); - struct s5p_mfc_fmt *fmt; struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp; int ret = 0; @@ -960,13 +972,9 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) goto out; } if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { - fmt = find_format(f, MFC_FMT_ENC); - if (!fmt) { - mfc_err("failed to set capture format\n"); - return -EINVAL; - } + /* dst_fmt is validated by call to vidioc_try_fmt */ + ctx->dst_fmt = find_format(f, MFC_FMT_ENC); ctx->state = MFCINST_INIT; - ctx->dst_fmt = fmt; ctx->codec_mode = ctx->dst_fmt->codec_mode; ctx->enc_dst_buf_size = pix_fmt_mp->plane_fmt[0].sizeimage; pix_fmt_mp->plane_fmt[0].bytesperline = 0; @@ -987,28 +995,8 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f) } mfc_debug(2, "Got instance number: %d\n", ctx->inst_no); } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { - fmt = find_format(f, MFC_FMT_RAW); - if (!fmt) { - mfc_err("failed to set output format\n"); - return -EINVAL; - } - - if (!IS_MFCV6(dev) && - (fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16)) { - mfc_err("Not supported format.\n"); - return -EINVAL; - } else if (IS_MFCV6(dev) && - (fmt->fourcc == V4L2_PIX_FMT_NV12MT)) { - mfc_err("Not supported format.\n"); - return -EINVAL; - } - - if (fmt->num_planes != pix_fmt_mp->num_planes) { - mfc_err("failed to set output format\n"); - ret = -EINVAL; - goto out; - } - ctx->src_fmt = fmt; + /* src_fmt is validated by call to vidioc_try_fmt */ + ctx->src_fmt = find_format(f, MFC_FMT_RAW); ctx->img_width = pix_fmt_mp->width; ctx->img_height = pix_fmt_mp->height; mfc_debug(2, "codec number: %d\n", ctx->src_fmt->codec_mode); From 66da64f06755134aee54d127bca54159fbbdcfb8 Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Sat, 15 Jun 2013 08:09:57 -0300 Subject: [PATCH 0791/3400] [media] media: coda: Fix DT driver data pointer for i.MX27 The data pointer should point to DT data, and not to the ID array. Signed-off-by: Alexander Shiyan Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index df4ada880e42..bd9405df1bd6 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c @@ -1987,7 +1987,7 @@ MODULE_DEVICE_TABLE(platform, coda_platform_ids); #ifdef CONFIG_OF static const struct of_device_id coda_dt_ids[] = { - { .compatible = "fsl,imx27-vpu", .data = &coda_platform_ids[CODA_IMX27] }, + { .compatible = "fsl,imx27-vpu", .data = &coda_devdata[CODA_IMX27] }, { .compatible = "fsl,imx53-vpu", .data = &coda_devdata[CODA_IMX53] }, { /* sentinel */ } }; From 8b64f75588ad87c9d6daa385817a4d43af6877be Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 15 Jul 2013 02:36:23 -0300 Subject: [PATCH 0792/3400] [media] s5p-g2d: Fix registration failure Commit 1c1d86a1ea ("[media] v4l2: always require v4l2_dev, rename parent to dev_parent") expects v4l2_dev to be always set. It converted most of the drivers using the parent field of video_device to v4l2_dev field. G2D driver did not set the parent field. Hence it got left out. Without this patch we get the following boot warning and G2D driver fails to register the video device. WARNING: CPU: 0 PID: 1 at drivers/media/v4l2-core/v4l2-dev.c:775 __video_register_device+0xfc0/0x1028() Modules linked in: CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.11.0-rc1-00001-g1c3e372-dirty #9 [] (unwind_backtrace+0x0/0xf4) from [] (show_stack+0x10/0x14) [] (show_stack+0x10/0x14) from [] (dump_stack+0x7c/0xb0) [] (dump_stack+0x7c/0xb0) from [] (warn_slowpath_common+0x6c/0x88) [] (warn_slowpath_common+0x6c/0x88) from [] (warn_slowpath_null+0x1c/0x24) [] (warn_slowpath_null+0x1c/0x24) from [] (__video_register_device+0xfc0/0x1028) [] (__video_register_device+0xfc0/0x1028) from [] (g2d_probe+0x1f8/0x398) [] (g2d_probe+0x1f8/0x398) from [] (platform_drv_probe+0x14/0x18) [] (platform_drv_probe+0x14/0x18) from [] (driver_probe_device+0x108/0x220) [] (driver_probe_device+0x108/0x220) from [] (__driver_attach+0x8c/0x90) [] (__driver_attach+0x8c/0x90) from [] (bus_for_each_dev+0x60/0x94) [] (bus_for_each_dev+0x60/0x94) from [] (bus_add_driver+0x1c0/0x24c) [] (bus_add_driver+0x1c0/0x24c) from [] (driver_register+0x78/0x140) [] (driver_register+0x78/0x140) from [] (do_one_initcall+0xf8/0x144) [] (do_one_initcall+0xf8/0x144) from [] (kernel_init_freeable+0x13c/0x1d8) [] (kernel_init_freeable+0x13c/0x1d8) from [] (kernel_init+0xc/0x160) [] (kernel_init+0xc/0x160) from [] (ret_from_fork+0x14/0x3c) ---[ end trace 4e0ec028b0028e02 ]--- s5p-g2d 12800000.g2d: Failed to register video device s5p-g2d: probe of 12800000.g2d failed with error -22 Signed-off-by: Sachin Kamat Cc: Hans Verkuil Signed-off-by: Kamil Debski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/s5p-g2d/g2d.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/platform/s5p-g2d/g2d.c b/drivers/media/platform/s5p-g2d/g2d.c index 553d87e5ceab..fd6289d60cde 100644 --- a/drivers/media/platform/s5p-g2d/g2d.c +++ b/drivers/media/platform/s5p-g2d/g2d.c @@ -784,6 +784,7 @@ static int g2d_probe(struct platform_device *pdev) } *vfd = g2d_videodev; vfd->lock = &dev->mutex; + vfd->v4l2_dev = &dev->v4l2_dev; ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); if (ret) { v4l2_err(&dev->v4l2_dev, "Failed to register video device\n"); From 8e2872ce7b9a06b951680d196e893f5c0d6a3229 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 18 Jul 2013 15:18:24 +0200 Subject: [PATCH 0793/3400] s390: add support for LZ4-compressed kernel Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/Kconfig | 1 + arch/s390/boot/compressed/Makefile | 9 ++++++--- arch/s390/boot/compressed/misc.c | 4 ++++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 22f75b504f7f..5a4c668676b5 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -118,6 +118,7 @@ config S390 select HAVE_FUNCTION_TRACE_MCOUNT_TEST select HAVE_KERNEL_BZIP2 select HAVE_KERNEL_GZIP + select HAVE_KERNEL_LZ4 select HAVE_KERNEL_LZMA select HAVE_KERNEL_LZO select HAVE_KERNEL_XZ diff --git a/arch/s390/boot/compressed/Makefile b/arch/s390/boot/compressed/Makefile index 3ad8f61c9985..866ecbe670e4 100644 --- a/arch/s390/boot/compressed/Makefile +++ b/arch/s390/boot/compressed/Makefile @@ -6,9 +6,9 @@ BITS := $(if $(CONFIG_64BIT),64,31) -targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 \ - vmlinux.bin.xz vmlinux.bin.lzma vmlinux.bin.lzo misc.o piggy.o \ - sizes.h head$(BITS).o +targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 +targets += vmlinux.bin.xz vmlinux.bin.lzma vmlinux.bin.lzo vmlinux.bin.lz4 +targets += misc.o piggy.o sizes.h head$(BITS).o KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2 KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING @@ -48,6 +48,7 @@ vmlinux.bin.all-y := $(obj)/vmlinux.bin suffix-$(CONFIG_KERNEL_GZIP) := gz suffix-$(CONFIG_KERNEL_BZIP2) := bz2 +suffix-$(CONFIG_KERNEL_LZ4) := lz4 suffix-$(CONFIG_KERNEL_LZMA) := lzma suffix-$(CONFIG_KERNEL_LZO) := lzo suffix-$(CONFIG_KERNEL_XZ) := xz @@ -56,6 +57,8 @@ $(obj)/vmlinux.bin.gz: $(vmlinux.bin.all-y) $(call if_changed,gzip) $(obj)/vmlinux.bin.bz2: $(vmlinux.bin.all-y) $(call if_changed,bzip2) +$(obj)/vmlinux.bin.lz4: $(vmlinux.bin.all-y) + $(call if_changed,lz4) $(obj)/vmlinux.bin.lzma: $(vmlinux.bin.all-y) $(call if_changed,lzma) $(obj)/vmlinux.bin.lzo: $(vmlinux.bin.all-y) diff --git a/arch/s390/boot/compressed/misc.c b/arch/s390/boot/compressed/misc.c index c4c6a1cf221b..57cbaff1f397 100644 --- a/arch/s390/boot/compressed/misc.c +++ b/arch/s390/boot/compressed/misc.c @@ -47,6 +47,10 @@ static unsigned long free_mem_end_ptr; #include "../../../../lib/decompress_bunzip2.c" #endif +#ifdef CONFIG_KERNEL_LZ4 +#include "../../../../lib/decompress_unlz4.c" +#endif + #ifdef CONFIG_KERNEL_LZMA #include "../../../../lib/decompress_unlzma.c" #endif From 79b6f7fbd1c18154a93313712ab91e413778afa6 Mon Sep 17 00:00:00 2001 From: Chen Gang Date: Tue, 23 Jul 2013 16:26:08 +0800 Subject: [PATCH 0794/3400] s390/Kconfig: select 'TTY' when 'S390_GUEST' is enabled 'VIRTIO_CONSOLE' depends on 'TTY', so need to select 'TTY' explicitly before selecting 'VIRTIO_CONSOLE'. Otherwise randconfig can generate a config file which enables 'VIRTIO_CONSOLE' but has 'TTY' disabled. Signed-off-by: Chen Gang Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 5a4c668676b5..a281bd6e94db 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -710,6 +710,7 @@ config S390_GUEST def_bool y prompt "s390 support for virtio devices" depends on 64BIT + select TTY select VIRTUALIZATION select VIRTIO select VIRTIO_CONSOLE From 594712276e737961d30e11eae80d403b2b3815df Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 24 Jul 2013 10:35:33 +0200 Subject: [PATCH 0795/3400] s390: add support for IBM zBC12 machine Just add the new model number where appropiate. Cc: stable@vger.kernel.org # v3.10 Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/Kconfig | 7 ++++--- arch/s390/kernel/setup.c | 1 + arch/s390/mm/init.c | 1 + arch/s390/oprofile/init.c | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index a281bd6e94db..8a4cae78f03c 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -228,11 +228,12 @@ config MARCH_Z196 not work on older machines. config MARCH_ZEC12 - bool "IBM zEC12" + bool "IBM zBC12 and zEC12" select HAVE_MARCH_ZEC12_FEATURES if 64BIT help - Select this to enable optimizations for IBM zEC12 (2827 series). The - kernel will be slightly faster but will not work on older machines. + Select this to enable optimizations for IBM zBC12 and zEC12 (2828 and + 2827 series). The kernel will be slightly faster but will not work on + older machines. endchoice diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 497451ec5e26..aeed8a61fa0d 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -994,6 +994,7 @@ static void __init setup_hwcaps(void) strcpy(elf_platform, "z196"); break; case 0x2827: + case 0x2828: strcpy(elf_platform, "zEC12"); break; } diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c index ce36ea80e4f9..ad446b0c55b6 100644 --- a/arch/s390/mm/init.c +++ b/arch/s390/mm/init.c @@ -69,6 +69,7 @@ static void __init setup_zero_pages(void) order = 2; break; case 0x2827: /* zEC12 */ + case 0x2828: /* zEC12 */ default: order = 5; break; diff --git a/arch/s390/oprofile/init.c b/arch/s390/oprofile/init.c index ffeb17ce7f31..930783d2c99b 100644 --- a/arch/s390/oprofile/init.c +++ b/arch/s390/oprofile/init.c @@ -440,7 +440,7 @@ static int oprofile_hwsampler_init(struct oprofile_operations *ops) switch (id.machine) { case 0x2097: case 0x2098: ops->cpu_type = "s390/z10"; break; case 0x2817: case 0x2818: ops->cpu_type = "s390/z196"; break; - case 0x2827: ops->cpu_type = "s390/zEC12"; break; + case 0x2827: case 0x2828: ops->cpu_type = "s390/zEC12"; break; default: return -ENODEV; } } From 3b0040a47ad63f7147e9e7d2febb61a3b564bb90 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Thu, 25 Jul 2013 10:18:17 +0200 Subject: [PATCH 0796/3400] s390/bitops: fix find_next_bit_left The find_next_bit_left function is broken if used with an offset which is not a multiple of 64. The shift to mask the bits of a 64-bit word not to search is in the wrong direction, the result can be either a bit found smaller than the offset or failure to find a set bit. Cc: # v3.8+ Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/bitops.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/s390/include/asm/bitops.h b/arch/s390/include/asm/bitops.h index 4d8604e311f3..7d4676758733 100644 --- a/arch/s390/include/asm/bitops.h +++ b/arch/s390/include/asm/bitops.h @@ -693,7 +693,7 @@ static inline int find_next_bit_left(const unsigned long *addr, size -= offset; p = addr + offset / BITS_PER_LONG; if (bit) { - set = __flo_word(0, *p & (~0UL << bit)); + set = __flo_word(0, *p & (~0UL >> bit)); if (set >= size) return size + offset; if (set < BITS_PER_LONG) From 198b1bf8c3a06de42a88ad7f9d664f18d740a418 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 25 Jul 2013 11:16:48 +0200 Subject: [PATCH 0797/3400] s390/perf: fix compile error (undefined reference sie_exit) The perf_event code references sie_exit even if KVM is not available. So add proper ifdefs to fix this one: arch/s390/built-in.o: In function `sys_call_table_emu': (.rodata+0x2b98): undefined reference to `sie_exit' arch/s390/built-in.o: In function `sys_call_table_emu': (.rodata+0x2ba0): undefined reference to `sie_exit' make: *** [vmlinux] Error 1 Reported-by: Zhouping Liu Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/perf_event.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/s390/kernel/perf_event.c b/arch/s390/kernel/perf_event.c index a6fc037671b1..500aa1029bcb 100644 --- a/arch/s390/kernel/perf_event.c +++ b/arch/s390/kernel/perf_event.c @@ -52,12 +52,13 @@ static struct kvm_s390_sie_block *sie_block(struct pt_regs *regs) static bool is_in_guest(struct pt_regs *regs) { - unsigned long ip = instruction_pointer(regs); - if (user_mode(regs)) return false; - - return ip == (unsigned long) &sie_exit; +#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) + return instruction_pointer(regs) == (unsigned long) &sie_exit; +#else + return false; +#endif } static unsigned long guest_is_user_mode(struct pt_regs *regs) From 3f1a94ba9fce90dbe0d26806a027964bea7adc14 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 30 Jun 2013 04:40:32 -0300 Subject: [PATCH 0798/3400] [media] ml86v7667: fix compile warning: 'ret' set but not used media_build/v4l/ml86v7667.c: In function 'ml86v7667_s_ctrl': media_build/v4l/ml86v7667.c:120:6: warning: variable 'ret' set but not used [-Wunused-but-set-variable] int ret; ^ And indeed, ret is set but not used. Let's actually return the error code. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ml86v7667.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/ml86v7667.c b/drivers/media/i2c/ml86v7667.c index efdc873e58d1..a9857022f71d 100644 --- a/drivers/media/i2c/ml86v7667.c +++ b/drivers/media/i2c/ml86v7667.c @@ -117,7 +117,7 @@ static int ml86v7667_s_ctrl(struct v4l2_ctrl *ctrl) { struct v4l2_subdev *sd = to_sd(ctrl); struct i2c_client *client = v4l2_get_subdevdata(sd); - int ret; + int ret = -EINVAL; switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: @@ -157,7 +157,7 @@ static int ml86v7667_s_ctrl(struct v4l2_ctrl *ctrl) break; } - return 0; + return ret; } static int ml86v7667_querystd(struct v4l2_subdev *sd, v4l2_std_id *std) From 41337042c92835e7460c5bb718fb27c50c096fa9 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Fri, 28 Jun 2013 05:34:20 -0300 Subject: [PATCH 0799/3400] [media] DocBook: upgrade media_api DocBook version to 4.2 Fixes the last three errors of media_api DocBook validatation: (...) media_api.xml:414: element imagedata: validity error : Value "SVG" for attribute format of imagedata is not among the enumerated set media_api.xml:432: element imagedata: validity error : Value "SVG" for attribute format of imagedata is not among the enumerated set media_api.xml:452: element imagedata: validity error : Value "SVG" for attribute format of imagedata is not among the enumerated set (...) Signed-off-by: Andrzej Hajda Signed-off-by: Kyungmin Park Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media_api.tmpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/DocBook/media_api.tmpl b/Documentation/DocBook/media_api.tmpl index 6a8b7158697f..9c92bb879b6d 100644 --- a/Documentation/DocBook/media_api.tmpl +++ b/Documentation/DocBook/media_api.tmpl @@ -1,6 +1,6 @@ - %media-entities; From 81913283c80be8c0b7e038c26e2a611ab38394f1 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Fri, 28 Jun 2013 05:44:22 -0300 Subject: [PATCH 0800/3400] [media] v4l2: added missing mutex.h include to v4l2-ctrls.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes following error: include/media/v4l2-ctrls.h:193:15: error: field ‘_lock’ has incomplete type include/media/v4l2-ctrls.h: In function ‘v4l2_ctrl_lock’: include/media/v4l2-ctrls.h:570:2: error: implicit declaration of function ‘mutex_lock’ [-Werror=implicit-function-declaration] include/media/v4l2-ctrls.h: In function ‘v4l2_ctrl_unlock’: include/media/v4l2-ctrls.h:579:2: error: implicit declaration of function ‘mutex_unlock’ [-Werror=implicit-function-declaration] Signed-off-by: Andrzej Hajda Signed-off-by: Kyungmin Park Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-ctrls.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h index 7343a27fe819..47ada23345a1 100644 --- a/include/media/v4l2-ctrls.h +++ b/include/media/v4l2-ctrls.h @@ -22,6 +22,7 @@ #define _V4L2_CTRLS_H #include +#include #include /* forward references */ From a34cacab1565fdee77544b12407274ffb4d9daa0 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Tue, 2 Jul 2013 07:56:38 -0300 Subject: [PATCH 0801/3400] [media] usbtv: Fix deinterlacing The image data is laid out a bit more weirdly and thus needs more work to properly interlace. What we get from hardware is V4L2_FIELD_ALTERNATE, but since userspace support for it is practically nonexistent, thus we make V4L2_FIELD_INTERLACED from it so that it's more easily interpreted. Signed-off-by: Lubomir Rintel Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/usbtv/usbtv.c | 36 +++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/drivers/media/usb/usbtv/usbtv.c b/drivers/media/usb/usbtv/usbtv.c index bf43f874685e..9dcc677f3015 100644 --- a/drivers/media/usb/usbtv/usbtv.c +++ b/drivers/media/usb/usbtv/usbtv.c @@ -57,7 +57,7 @@ #define USBTV_CHUNK_SIZE 256 #define USBTV_CHUNK 240 #define USBTV_CHUNKS (USBTV_WIDTH * USBTV_HEIGHT \ - / 2 / USBTV_CHUNK) + / 4 / USBTV_CHUNK) /* Chunk header. */ #define USBTV_MAGIC_OK(chunk) ((be32_to_cpu(chunk[0]) & 0xff000000) \ @@ -202,6 +202,26 @@ static int usbtv_setup_capture(struct usbtv *usbtv) return 0; } +/* Copy data from chunk into a frame buffer, deinterlacing the data + * into every second line. Unfortunately, they don't align nicely into + * 720 pixel lines, as the chunk is 240 words long, which is 480 pixels. + * Therefore, we break down the chunk into two halves before copyting, + * so that we can interleave a line if needed. */ +static void usbtv_chunk_to_vbuf(u32 *frame, u32 *src, int chunk_no, int odd) +{ + int half; + + for (half = 0; half < 2; half++) { + int part_no = chunk_no * 2 + half; + int line = part_no / 3; + int part_index = (line * 2 + !odd) * 3 + (part_no % 3); + + u32 *dst = &frame[part_index * USBTV_CHUNK/2]; + memcpy(dst, src, USBTV_CHUNK/2 * sizeof(*src)); + src += USBTV_CHUNK/2; + } +} + /* Called for each 256-byte image chunk. * First word identifies the chunk, followed by 240 words of image * data and padding. */ @@ -218,11 +238,6 @@ static void usbtv_image_chunk(struct usbtv *usbtv, u32 *chunk) frame_id = USBTV_FRAME_ID(chunk); odd = USBTV_ODD(chunk); chunk_no = USBTV_CHUNK_NO(chunk); - - /* Deinterlace. TODO: Use interlaced frame format. */ - chunk_no = (chunk_no - chunk_no % 3) * 2 + chunk_no % 3; - chunk_no += !odd * 3; - if (chunk_no >= USBTV_CHUNKS) return; @@ -241,12 +256,11 @@ static void usbtv_image_chunk(struct usbtv *usbtv, u32 *chunk) buf = list_first_entry(&usbtv->bufs, struct usbtv_buf, list); frame = vb2_plane_vaddr(&buf->vb, 0); - /* Copy the chunk. */ - memcpy(&frame[chunk_no * USBTV_CHUNK], &chunk[1], - USBTV_CHUNK * sizeof(chunk[1])); + /* Copy the chunk data. */ + usbtv_chunk_to_vbuf(frame, &chunk[1], chunk_no, odd); /* Last chunk in a frame, signalling an end */ - if (usbtv->frame_id && chunk_no == USBTV_CHUNKS-1) { + if (odd && chunk_no == USBTV_CHUNKS-1) { int size = vb2_plane_size(&buf->vb, 0); buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED; @@ -518,7 +532,7 @@ static int usbtv_queue_setup(struct vb2_queue *vq, if (*nbuffers < 2) *nbuffers = 2; *nplanes = 1; - sizes[0] = USBTV_CHUNK * USBTV_CHUNKS * sizeof(u32); + sizes[0] = USBTV_WIDTH * USBTV_HEIGHT / 2 * sizeof(u32); return 0; } From f52dc448a344ddb90c8516c06656d62710baa869 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Tue, 2 Jul 2013 07:56:39 -0300 Subject: [PATCH 0802/3400] [media] usbtv: Throw corrupted frames away Ignore out of order data and mark incomplete buffers as errored. This gets rid of annoying flicker due to occassional garbage from hardware. Signed-off-by: Lubomir Rintel Cc: Hans Verkuil Cc: Mauro Carvalho Chehab Cc: linux-kernel@vger.kernel.org Cc: linux-media@vger.kernel.org Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/usbtv/usbtv.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/media/usb/usbtv/usbtv.c b/drivers/media/usb/usbtv/usbtv.c index 9dcc677f3015..91650173941a 100644 --- a/drivers/media/usb/usbtv/usbtv.c +++ b/drivers/media/usb/usbtv/usbtv.c @@ -89,6 +89,7 @@ struct usbtv { /* Number of currently processed frame, useful find * out when a new one begins. */ u32 frame_id; + int chunks_done; int iso_size; unsigned int sequence; @@ -242,8 +243,13 @@ static void usbtv_image_chunk(struct usbtv *usbtv, u32 *chunk) return; /* Beginning of a frame. */ - if (chunk_no == 0) + if (chunk_no == 0) { usbtv->frame_id = frame_id; + usbtv->chunks_done = 0; + } + + if (usbtv->frame_id != frame_id) + return; spin_lock_irqsave(&usbtv->buflock, flags); if (list_empty(&usbtv->bufs)) { @@ -258,16 +264,21 @@ static void usbtv_image_chunk(struct usbtv *usbtv, u32 *chunk) /* Copy the chunk data. */ usbtv_chunk_to_vbuf(frame, &chunk[1], chunk_no, odd); + usbtv->chunks_done++; /* Last chunk in a frame, signalling an end */ if (odd && chunk_no == USBTV_CHUNKS-1) { int size = vb2_plane_size(&buf->vb, 0); + enum vb2_buffer_state state = usbtv->chunks_done == + USBTV_CHUNKS ? + VB2_BUF_STATE_DONE : + VB2_BUF_STATE_ERROR; buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED; buf->vb.v4l2_buf.sequence = usbtv->sequence++; v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp); vb2_set_plane_payload(&buf->vb, 0, size); - vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE); + vb2_buffer_done(&buf->vb, state); list_del(&buf->list); } From 4f24abb51ffe24d1a1442fdd3648a2e521487c1b Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 28 Jun 2013 04:24:15 -0300 Subject: [PATCH 0803/3400] [media] usbtv: fix dependency This fixes a dependency problem as found by Randy Dunlap: https://lkml.org/lkml/2013/6/27/501 Reported-by: Randy Dunlap Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/usbtv/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/usb/usbtv/Kconfig b/drivers/media/usb/usbtv/Kconfig index 8864436464bf..7c5b86006ee6 100644 --- a/drivers/media/usb/usbtv/Kconfig +++ b/drivers/media/usb/usbtv/Kconfig @@ -1,6 +1,6 @@ config VIDEO_USBTV tristate "USBTV007 video capture support" - depends on VIDEO_DEV + depends on VIDEO_V4L2 select VIDEOBUF2_VMALLOC ---help--- From e2f11c58ae49d57b0e634685dd944c1771ba38c0 Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Wed, 3 Jul 2013 16:17:34 -0300 Subject: [PATCH 0804/3400] [media] hdpvr: fix iteration over uninitialized lists in hdpvr_probe() free_buff_list and rec_buff_list are initialized in the middle of hdpvr_probe(), but if something bad happens before that, error handling code calls hdpvr_delete(), which contains iteration over the lists (via hdpvr_free_buffers()). The patch moves the lists initialization to the beginning and by the way fixes goto label in error handling of registering videodev. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/hdpvr/hdpvr-core.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/media/usb/hdpvr/hdpvr-core.c b/drivers/media/usb/hdpvr/hdpvr-core.c index cb694055ba7d..6e5070774dc2 100644 --- a/drivers/media/usb/hdpvr/hdpvr-core.c +++ b/drivers/media/usb/hdpvr/hdpvr-core.c @@ -303,6 +303,11 @@ static int hdpvr_probe(struct usb_interface *interface, dev->workqueue = 0; + /* init video transfer queues first of all */ + /* to prevent oops in hdpvr_delete() on error paths */ + INIT_LIST_HEAD(&dev->free_buff_list); + INIT_LIST_HEAD(&dev->rec_buff_list); + /* register v4l2_device early so it can be used for printks */ if (v4l2_device_register(&interface->dev, &dev->v4l2_dev)) { dev_err(&interface->dev, "v4l2_device_register failed\n"); @@ -325,10 +330,6 @@ static int hdpvr_probe(struct usb_interface *interface, if (!dev->workqueue) goto error; - /* init video transfer queues */ - INIT_LIST_HEAD(&dev->free_buff_list); - INIT_LIST_HEAD(&dev->rec_buff_list); - dev->options = hdpvr_default_options; if (default_video_input < HDPVR_VIDEO_INPUTS) @@ -405,7 +406,7 @@ static int hdpvr_probe(struct usb_interface *interface, video_nr[atomic_inc_return(&dev_nr)]); if (retval < 0) { v4l2_err(&dev->v4l2_dev, "registering videodev failed\n"); - goto error; + goto reg_fail; } /* let the user know what node this device is now attached to */ From df981edcb9bce00b9c5e4f3cc33f3f98bc9a2394 Mon Sep 17 00:00:00 2001 From: Roy Franz Date: Wed, 24 Jul 2013 17:48:44 -0700 Subject: [PATCH 0805/3400] x86, efi: correct call to free_pages Specify memory size in pages, not bytes. Signed-off-by: Roy Franz Signed-off-by: Matt Fleming --- arch/x86/boot/compressed/eboot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index d606463aa6d6..b7388a425f09 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c @@ -225,7 +225,7 @@ static void low_free(unsigned long size, unsigned long addr) unsigned long nr_pages; nr_pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE; - efi_call_phys2(sys_table->boottime->free_pages, addr, size); + efi_call_phys2(sys_table->boottime->free_pages, addr, nr_pages); } static void find_bits(unsigned long mask, u8 *pos, u8 *size) From f813b5775b471b656382ae8f087bb34dc894261f Mon Sep 17 00:00:00 2001 From: Alban Browaeys Date: Tue, 16 Jul 2013 18:57:53 -0300 Subject: [PATCH 0806/3400] [media] em28xx: fix assignment of the eeprom data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Set the config structure pointer to the eeprom data pointer (data, here eedata dereferenced) not the pointer to the pointer to the eeprom data (eedata itself). Signed-off-by: Alban Browaeys Signed-off-by: Frank Schäfer Cc: stable@vger.kernel.org # for v3.10 Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/usb/em28xx/em28xx-i2c.c b/drivers/media/usb/em28xx/em28xx-i2c.c index 4851cc2e4a4d..c4ff9739a7ae 100644 --- a/drivers/media/usb/em28xx/em28xx-i2c.c +++ b/drivers/media/usb/em28xx/em28xx-i2c.c @@ -726,7 +726,7 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned bus, *eedata = data; *eedata_len = len; - dev_config = (void *)eedata; + dev_config = (void *)*eedata; switch (le16_to_cpu(dev_config->chip_conf) >> 4 & 0x3) { case 0: From eaa5a990191d204ba0f9d35dbe5505ec2cdd1460 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Fri, 26 Jul 2013 09:11:56 -0700 Subject: [PATCH 0807/3400] x86, fpu: correct the asm constraints for fxsave, unbreak mxcsr.daz MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GCC will optimize mxcsr_feature_mask_init in arch/x86/kernel/i387.c: memset(&fx_scratch, 0, sizeof(struct i387_fxsave_struct)); asm volatile("fxsave %0" : : "m" (fx_scratch)); mask = fx_scratch.mxcsr_mask; if (mask == 0) mask = 0x0000ffbf; to memset(&fx_scratch, 0, sizeof(struct i387_fxsave_struct)); asm volatile("fxsave %0" : : "m" (fx_scratch)); mask = 0x0000ffbf; since asm statement doesn’t say it will update fx_scratch. As the result, the DAZ bit will be cleared. This patch fixes it. This bug dates back to at least kernel 2.6.12. Signed-off-by: H. Peter Anvin Cc: --- arch/x86/kernel/i387.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index 202d24f0f7e7..5d576ab34403 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c @@ -116,7 +116,7 @@ static void mxcsr_feature_mask_init(void) if (cpu_has_fxsr) { memset(&fx_scratch, 0, sizeof(struct i387_fxsave_struct)); - asm volatile("fxsave %0" : : "m" (fx_scratch)); + asm volatile("fxsave %0" : "+m" (fx_scratch)); mask = fx_scratch.mxcsr_mask; if (mask == 0) mask = 0x0000ffbf; From 07f9b61c3915e8eb156cb4461b3946736356ad02 Mon Sep 17 00:00:00 2001 From: "ethan.zhao" Date: Fri, 26 Jul 2013 11:21:24 -0600 Subject: [PATCH 0808/3400] x86/PCI: MMCONFIG: Check earlier for MMCONFIG region at address zero We can check for addr being zero earlier and thus avoid the mutex_unlock() cleanup path. [bhelgaas: drop warning printk] Signed-off-by: ethan.zhao Signed-off-by: Bjorn Helgaas Acked-by: Yinghai Lu --- arch/x86/pci/mmconfig-shared.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c index 082e88129712..5596c7bdd327 100644 --- a/arch/x86/pci/mmconfig-shared.c +++ b/arch/x86/pci/mmconfig-shared.c @@ -700,7 +700,7 @@ int pci_mmconfig_insert(struct device *dev, u16 seg, u8 start, u8 end, if (!(pci_probe & PCI_PROBE_MMCONF) || pci_mmcfg_arch_init_failed) return -ENODEV; - if (start > end) + if (start > end || !addr) return -EINVAL; mutex_lock(&pci_mmcfg_lock); @@ -716,11 +716,6 @@ int pci_mmconfig_insert(struct device *dev, u16 seg, u8 start, u8 end, return -EEXIST; } - if (!addr) { - mutex_unlock(&pci_mmcfg_lock); - return -EINVAL; - } - rc = -EBUSY; cfg = pci_mmconfig_alloc(seg, start, end, addr); if (cfg == NULL) { From 102c9323c35a83789ad5ebd3c45fa8fb389add88 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Fri, 12 Jul 2013 17:07:27 -0400 Subject: [PATCH 0809/3400] tracing: Add __tracepoint_string() to export string pointers There are several tracepoints (mostly in RCU), that reference a string pointer and uses the print format of "%s" to display the string that exists in the kernel, instead of copying the actual string to the ring buffer (saves time and ring buffer space). But this has an issue with userspace tools that read the binary buffers that has the address of the string but has no access to what the string itself is. The end result is just output that looks like: rcu_dyntick: ffffffff818adeaa 1 0 rcu_dyntick: ffffffff818adeb5 0 140000000000000 rcu_dyntick: ffffffff818adeb5 0 140000000000000 rcu_utilization: ffffffff8184333b rcu_utilization: ffffffff8184333b The above is pretty useless when read by the userspace tools. Ideally we would want something that looks like this: rcu_dyntick: Start 1 0 rcu_dyntick: End 0 140000000000000 rcu_dyntick: Start 140000000000000 0 rcu_callback: rcu_preempt rhp=0xffff880037aff710 func=put_cred_rcu 0/4 rcu_callback: rcu_preempt rhp=0xffff880078961980 func=file_free_rcu 0/5 rcu_dyntick: End 0 1 The trace_printk() which also only stores the address of the string format instead of recording the string into the buffer itself, exports the mapping of kernel addresses to format strings via the printk_format file in the debugfs tracing directory. The tracepoint strings can use this same method and output the format to the same file and the userspace tools will be able to decipher the address without any modification. The tracepoint strings need its own section to save the strings because the trace_printk section will cause the trace_printk() buffers to be allocated if anything exists within the section. trace_printk() is only used for debugging and should never exist in the kernel, we can not use the trace_printk sections. Add a new tracepoint_str section that will also be examined by the output of the printk_format file. Cc: Paul E. McKenney Signed-off-by: Steven Rostedt --- include/asm-generic/vmlinux.lds.h | 7 ++++++- include/linux/ftrace_event.h | 34 +++++++++++++++++++++++++++++++ kernel/trace/trace.h | 3 +++ kernel/trace/trace_printk.c | 19 +++++++++++++++++ 4 files changed, 62 insertions(+), 1 deletion(-) diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 69732d279e8b..83e2c31e8b00 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -122,8 +122,12 @@ #define TRACE_PRINTKS() VMLINUX_SYMBOL(__start___trace_bprintk_fmt) = .; \ *(__trace_printk_fmt) /* Trace_printk fmt' pointer */ \ VMLINUX_SYMBOL(__stop___trace_bprintk_fmt) = .; +#define TRACEPOINT_STR() VMLINUX_SYMBOL(__start___tracepoint_str) = .; \ + *(__tracepoint_str) /* Trace_printk fmt' pointer */ \ + VMLINUX_SYMBOL(__stop___tracepoint_str) = .; #else #define TRACE_PRINTKS() +#define TRACEPOINT_STR() #endif #ifdef CONFIG_FTRACE_SYSCALLS @@ -190,7 +194,8 @@ VMLINUX_SYMBOL(__stop___verbose) = .; \ LIKELY_PROFILE() \ BRANCH_PROFILE() \ - TRACE_PRINTKS() + TRACE_PRINTKS() \ + TRACEPOINT_STR() /* * Data section helpers diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h index 4372658c73ae..81af18a75f4d 100644 --- a/include/linux/ftrace_event.h +++ b/include/linux/ftrace_event.h @@ -357,6 +357,40 @@ do { \ __trace_printk(ip, fmt, ##args); \ } while (0) +/** + * tracepoint_string - register constant persistent string to trace system + * @str - a constant persistent string that will be referenced in tracepoints + * + * If constant strings are being used in tracepoints, it is faster and + * more efficient to just save the pointer to the string and reference + * that with a printf "%s" instead of saving the string in the ring buffer + * and wasting space and time. + * + * The problem with the above approach is that userspace tools that read + * the binary output of the trace buffers do not have access to the string. + * Instead they just show the address of the string which is not very + * useful to users. + * + * With tracepoint_string(), the string will be registered to the tracing + * system and exported to userspace via the debugfs/tracing/printk_formats + * file that maps the string address to the string text. This way userspace + * tools that read the binary buffers have a way to map the pointers to + * the ASCII strings they represent. + * + * The @str used must be a constant string and persistent as it would not + * make sense to show a string that no longer exists. But it is still fine + * to be used with modules, because when modules are unloaded, if they + * had tracepoints, the ring buffers are cleared too. As long as the string + * does not change during the life of the module, it is fine to use + * tracepoint_string() within a module. + */ +#define tracepoint_string(str) \ + ({ \ + static const char *___tp_str __tracepoint_string = str; \ + ___tp_str; \ + }) +#define __tracepoint_string __attribute__((section("__tracepoint_str"))) + #ifdef CONFIG_PERF_EVENTS struct perf_event; diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 4a4f6e1828b6..ba321f12df8c 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -1022,6 +1022,9 @@ extern struct list_head ftrace_events; extern const char *__start___trace_bprintk_fmt[]; extern const char *__stop___trace_bprintk_fmt[]; +extern const char *__start___tracepoint_str[]; +extern const char *__stop___tracepoint_str[]; + void trace_printk_init_buffers(void); void trace_printk_start_comm(void); int trace_keep_overwrite(struct tracer *tracer, u32 mask, int set); diff --git a/kernel/trace/trace_printk.c b/kernel/trace/trace_printk.c index a9077c1b4ad3..2900817ba65c 100644 --- a/kernel/trace/trace_printk.c +++ b/kernel/trace/trace_printk.c @@ -244,12 +244,31 @@ static const char **find_next(void *v, loff_t *pos) { const char **fmt = v; int start_index; + int last_index; start_index = __stop___trace_bprintk_fmt - __start___trace_bprintk_fmt; if (*pos < start_index) return __start___trace_bprintk_fmt + *pos; + /* + * The __tracepoint_str section is treated the same as the + * __trace_printk_fmt section. The difference is that the + * __trace_printk_fmt section should only be used by trace_printk() + * in a debugging environment, as if anything exists in that section + * the trace_prink() helper buffers are allocated, which would just + * waste space in a production environment. + * + * The __tracepoint_str sections on the other hand are used by + * tracepoints which need to map pointers to their strings to + * the ASCII text for userspace. + */ + last_index = start_index; + start_index = __stop___tracepoint_str - __start___tracepoint_str; + + if (*pos < last_index + start_index) + return __start___tracepoint_str + (*pos - last_index); + return find_next_mod_format(start_index, v, fmt, pos); } From 205c97bcb8773f31184aedd86e229c95fffb179a Mon Sep 17 00:00:00 2001 From: Robin Gong Date: Fri, 26 Jul 2013 10:27:18 +0800 Subject: [PATCH 0810/3400] regulator:pfuze100: fix build warning and correct the binding doc fix building warning and correct the binding doc Signed-off-by: Robin Gong Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/regulator/pfuze100.txt | 2 ++ drivers/regulator/pfuze100-regulator.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/regulator/pfuze100.txt b/Documentation/devicetree/bindings/regulator/pfuze100.txt index 22e1a48f7e83..fc989b2e8057 100644 --- a/Documentation/devicetree/bindings/regulator/pfuze100.txt +++ b/Documentation/devicetree/bindings/regulator/pfuze100.txt @@ -3,6 +3,8 @@ PFUZE100 family of regulators Required properties: - compatible: "fsl,pfuze100" - reg: I2C slave address + +Required child node: - regulators: This is the list of child nodes that specify the regulator initialization data for defined regulators. Please refer to below doc Documentation/devicetree/bindings/regulator/regulator.txt. diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c index fcc7cd0d25cc..e2f9dcf3eb21 100644 --- a/drivers/regulator/pfuze100-regulator.c +++ b/drivers/regulator/pfuze100-regulator.c @@ -295,7 +295,7 @@ static inline struct device_node *match_of_node(int index) #else static int pfuze_parse_regulators_dt(struct pfuze_chip *chip) { - return NULL; + return 0; } static inline struct regulator_init_data *match_init_data(int index) From a34eb503742fd25155fd6cff6163daacead9fbc3 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Fri, 26 Jul 2013 15:15:46 -0400 Subject: [PATCH 0811/3400] ext4: make sure group number is bumped after a inode allocation race When we try to allocate an inode, and there is a race between two CPU's trying to grab the same inode, _and_ this inode is the last free inode in the block group, make sure the group number is bumped before we continue searching the rest of the block groups. Otherwise, we end up searching the current block group twice, and we end up skipping searching the last block group. So in the unlikely situation where almost all of the inodes are allocated, it's possible that we will return ENOSPC even though there might be free inodes in that last block group. Signed-off-by: "Theodore Ts'o" Cc: stable@vger.kernel.org --- fs/ext4/ialloc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index f03598c6ffd3..8bf5999875ee 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -734,11 +734,8 @@ repeat_in_this_group: ino = ext4_find_next_zero_bit((unsigned long *) inode_bitmap_bh->b_data, EXT4_INODES_PER_GROUP(sb), ino); - if (ino >= EXT4_INODES_PER_GROUP(sb)) { - if (++group == ngroups) - group = 0; - continue; - } + if (ino >= EXT4_INODES_PER_GROUP(sb)) + goto next_group; if (group == 0 && (ino+1) < EXT4_FIRST_INO(sb)) { ext4_error(sb, "reserved inode found cleared - " "inode=%lu", ino + 1); @@ -769,6 +766,9 @@ repeat_in_this_group: goto got; /* we grabbed the inode! */ if (ino < EXT4_INODES_PER_GROUP(sb)) goto repeat_in_this_group; +next_group: + if (++group == ngroups) + group = 0; } err = -ENOSPC; goto out; From dd12ed144e9797094c04736f97aa27d5fe401476 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Fri, 26 Jul 2013 15:21:11 -0400 Subject: [PATCH 0812/3400] ext4: destroy ext4_es_cachep on module unload Without this, module can't be reloaded. [ 500.521980] kmem_cache_sanity_check (ext4_extent_status): Cache name already exists. Signed-off-by: Eric Sandeen Signed-off-by: "Theodore Ts'o" Cc: stable@vger.kernel.org # v3.8+ --- fs/ext4/super.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index bca26f34edf4..36b141e420b7 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -5481,6 +5481,7 @@ static void __exit ext4_exit_fs(void) kset_unregister(ext4_kset); ext4_exit_system_zone(); ext4_exit_pageio(); + ext4_exit_es(); } MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others"); From 8bd3902d8be2b4ba484d5dbbe0f30b73b2f8c017 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 1 Jul 2013 15:52:42 -0700 Subject: [PATCH 0813/3400] usb: ohci-ep93xx: use devm_ioremap_resource() Use devm_ioremap_resource() to make the code a bit cleaner and simpler. Signed-off-by: H Hartley Sweeten Acked-by: Alan Stern Cc: Lennert Buytenhek Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-ep93xx.c | 35 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c index 8704e9fa5a80..4e12f67a32dd 100644 --- a/drivers/usb/host/ohci-ep93xx.c +++ b/drivers/usb/host/ohci-ep93xx.c @@ -43,38 +43,37 @@ static void ep93xx_stop_hc(struct device *dev) static int usb_hcd_ep93xx_probe(const struct hc_driver *driver, struct platform_device *pdev) { - int retval; struct usb_hcd *hcd; + struct resource *res; + int retval; if (pdev->resource[1].flags != IORESOURCE_IRQ) { dev_dbg(&pdev->dev, "resource[1] is not IORESOURCE_IRQ\n"); return -ENOMEM; } + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENXIO; + hcd = usb_create_hcd(driver, &pdev->dev, "ep93xx"); if (hcd == NULL) return -ENOMEM; - hcd->rsrc_start = pdev->resource[0].start; - hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1; - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { - usb_put_hcd(hcd); - retval = -EBUSY; - goto err1; - } + hcd->rsrc_start = res->start; + hcd->rsrc_len = resource_size(res); - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); - if (hcd->regs == NULL) { - dev_dbg(&pdev->dev, "ioremap failed\n"); - retval = -ENOMEM; - goto err2; + hcd->regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(hcd->regs)) { + retval = PTR_ERR(hcd->regs); + goto err_put_hcd; } usb_host_clock = clk_get(&pdev->dev, NULL); if (IS_ERR(usb_host_clock)) { dev_dbg(&pdev->dev, "clk_get failed\n"); retval = PTR_ERR(usb_host_clock); - goto err3; + goto err_put_hcd; } ep93xx_start_hc(&pdev->dev); @@ -86,11 +85,7 @@ static int usb_hcd_ep93xx_probe(const struct hc_driver *driver, return retval; ep93xx_stop_hc(&pdev->dev); -err3: - iounmap(hcd->regs); -err2: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -err1: +err_put_hcd: usb_put_hcd(hcd); return retval; @@ -102,8 +97,6 @@ static void usb_hcd_ep93xx_remove(struct usb_hcd *hcd, usb_remove_hcd(hcd); ep93xx_stop_hc(&pdev->dev); clk_put(usb_host_clock); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); } From 8fb35f2d3189f27fe51fb485e9b9751b202d585b Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 1 Jul 2013 15:52:51 -0700 Subject: [PATCH 0814/3400] usb: ohci-ep93xx: use platform_get_irq() Use platform_get_irq() instead of accessing the platform_device resources directly. Signed-off-by: H Hartley Sweeten Acked-by: Alan Stern Cc: Lennert Buytenhek Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-ep93xx.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c index 4e12f67a32dd..b4f5e6403991 100644 --- a/drivers/usb/host/ohci-ep93xx.c +++ b/drivers/usb/host/ohci-ep93xx.c @@ -45,12 +45,12 @@ static int usb_hcd_ep93xx_probe(const struct hc_driver *driver, { struct usb_hcd *hcd; struct resource *res; + int irq; int retval; - if (pdev->resource[1].flags != IORESOURCE_IRQ) { - dev_dbg(&pdev->dev, "resource[1] is not IORESOURCE_IRQ\n"); - return -ENOMEM; - } + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) @@ -80,7 +80,7 @@ static int usb_hcd_ep93xx_probe(const struct hc_driver *driver, ohci_hcd_init(hcd_to_ohci(hcd)); - retval = usb_add_hcd(hcd, pdev->resource[1].start, 0); + retval = usb_add_hcd(hcd, irq, 0); if (retval == 0) return retval; From 09ae8e7ead08e403413ceb4ba0f47eb324d03995 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 1 Jul 2013 15:52:59 -0700 Subject: [PATCH 0815/3400] usb: ohci-ep93xx: use devm_clk_get() Use devm_clk_get() to make the code a bit cleaner and simpler. This also fixes a bug where a clk_put() is not done if usb_add_hcd() fails. Signed-off-by: H Hartley Sweeten Acked-by: Alan Stern Cc: Lennert Buytenhek Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-ep93xx.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c index b4f5e6403991..28fa6b8b5acd 100644 --- a/drivers/usb/host/ohci-ep93xx.c +++ b/drivers/usb/host/ohci-ep93xx.c @@ -69,9 +69,8 @@ static int usb_hcd_ep93xx_probe(const struct hc_driver *driver, goto err_put_hcd; } - usb_host_clock = clk_get(&pdev->dev, NULL); + usb_host_clock = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(usb_host_clock)) { - dev_dbg(&pdev->dev, "clk_get failed\n"); retval = PTR_ERR(usb_host_clock); goto err_put_hcd; } @@ -96,7 +95,6 @@ static void usb_hcd_ep93xx_remove(struct usb_hcd *hcd, { usb_remove_hcd(hcd); ep93xx_stop_hc(&pdev->dev); - clk_put(usb_host_clock); usb_put_hcd(hcd); } From af3f233fd27b6a59cd6ea46a7dc048fff3ef2740 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 1 Jul 2013 15:53:02 -0700 Subject: [PATCH 0816/3400] usb: ohci-ep93xx: tidy up driver (*probe) and (*remove) Merge the usb_hcd_ep93xx_probe() into ohci_hcd_ep93xx_drv_probe() and the usb_hcd_ep93xx_remove() into ohci_hcd_ep93xx_drv_remove(). As Alan Stern pointed out, there is no reason for them to be separate. Also, as Alan Stern suggested, eliminate the ep93xx_start_hc() and ep93xx_stop_hc() routines and simply call clk_enable() and clk_disable() directly. The extra level of redirection does not add any clarity. Signed-off-by: H Hartley Sweeten Acked-by: Alan Stern Cc: Lennert Buytenhek Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-ep93xx.c | 128 ++++++++++++++------------------- 1 file changed, 52 insertions(+), 76 deletions(-) diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c index 28fa6b8b5acd..84a20d5223b9 100644 --- a/drivers/usb/host/ohci-ep93xx.c +++ b/drivers/usb/host/ohci-ep93xx.c @@ -30,74 +30,6 @@ static struct clk *usb_host_clock; -static void ep93xx_start_hc(struct device *dev) -{ - clk_enable(usb_host_clock); -} - -static void ep93xx_stop_hc(struct device *dev) -{ - clk_disable(usb_host_clock); -} - -static int usb_hcd_ep93xx_probe(const struct hc_driver *driver, - struct platform_device *pdev) -{ - struct usb_hcd *hcd; - struct resource *res; - int irq; - int retval; - - irq = platform_get_irq(pdev, 0); - if (irq < 0) - return irq; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENXIO; - - hcd = usb_create_hcd(driver, &pdev->dev, "ep93xx"); - if (hcd == NULL) - return -ENOMEM; - - hcd->rsrc_start = res->start; - hcd->rsrc_len = resource_size(res); - - hcd->regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(hcd->regs)) { - retval = PTR_ERR(hcd->regs); - goto err_put_hcd; - } - - usb_host_clock = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(usb_host_clock)) { - retval = PTR_ERR(usb_host_clock); - goto err_put_hcd; - } - - ep93xx_start_hc(&pdev->dev); - - ohci_hcd_init(hcd_to_ohci(hcd)); - - retval = usb_add_hcd(hcd, irq, 0); - if (retval == 0) - return retval; - - ep93xx_stop_hc(&pdev->dev); -err_put_hcd: - usb_put_hcd(hcd); - - return retval; -} - -static void usb_hcd_ep93xx_remove(struct usb_hcd *hcd, - struct platform_device *pdev) -{ - usb_remove_hcd(hcd); - ep93xx_stop_hc(&pdev->dev); - usb_put_hcd(hcd); -} - static int ohci_ep93xx_start(struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci(hcd); @@ -138,15 +70,57 @@ static struct hc_driver ohci_ep93xx_hc_driver = { .start_port_reset = ohci_start_port_reset, }; -extern int usb_disabled(void); - static int ohci_hcd_ep93xx_drv_probe(struct platform_device *pdev) { + struct usb_hcd *hcd; + struct resource *res; + int irq; int ret; - ret = -ENODEV; - if (!usb_disabled()) - ret = usb_hcd_ep93xx_probe(&ohci_ep93xx_hc_driver, pdev); + if (usb_disabled()) + return -ENODEV; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENXIO; + + hcd = usb_create_hcd(&ohci_ep93xx_hc_driver, &pdev->dev, "ep93xx"); + if (!hcd) + return -ENOMEM; + + hcd->rsrc_start = res->start; + hcd->rsrc_len = resource_size(res); + + hcd->regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(hcd->regs)) { + ret = PTR_ERR(hcd->regs); + goto err_put_hcd; + } + + usb_host_clock = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(usb_host_clock)) { + ret = PTR_ERR(usb_host_clock); + goto err_put_hcd; + } + + clk_enable(usb_host_clock); + + ohci_hcd_init(hcd_to_ohci(hcd)); + + ret = usb_add_hcd(hcd, irq, 0); + if (ret) + goto err_clk_disable; + + return 0; + +err_clk_disable: + clk_disable(usb_host_clock); +err_put_hcd: + usb_put_hcd(hcd); return ret; } @@ -155,7 +129,9 @@ static int ohci_hcd_ep93xx_drv_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); - usb_hcd_ep93xx_remove(hcd, pdev); + usb_remove_hcd(hcd); + clk_disable(usb_host_clock); + usb_put_hcd(hcd); return 0; } @@ -170,7 +146,7 @@ static int ohci_hcd_ep93xx_drv_suspend(struct platform_device *pdev, pm_message_ msleep(5); ohci->next_statechange = jiffies; - ep93xx_stop_hc(&pdev->dev); + clk_disable(usb_host_clock); return 0; } @@ -183,7 +159,7 @@ static int ohci_hcd_ep93xx_drv_resume(struct platform_device *pdev) msleep(5); ohci->next_statechange = jiffies; - ep93xx_start_hc(&pdev->dev); + clk_enable(usb_host_clock); ohci_resume(hcd, false); return 0; From 4e682bbd32708f3eab55b66960933b36bc00e31a Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Thu, 4 Jul 2013 01:39:10 -0400 Subject: [PATCH 0817/3400] usb: limit OMAP related USB options to OMAP2PLUS platforms commit 57f6ce072e35770a63be0c5d5e82f90d8da7d665 ("usb: phy: add a new driver for usb3 phy") added the new Kconfig option OMAP_USB3, but it had no dependencies whatsoever, and hence became available across all arch/platforms. Which presumably caused this to show up in x86 randconfig: warning: (USB_MUSB_HDRC && OMAP_USB3) selects \ OMAP_CONTROL_USB which has unmet direct \ dependencies (USB_SUPPORT && ARCH_OMAP2PLUS) Then commit 6992819feb39cb9adac72170555d957d07f869f2 ("usb: phy: fix Kconfig warning") was added. However, this just deleted the ARCH_OMAP2PLUS dependency from OMAP_CONTROL_USB, further compounding the problem by opening up OMAP_CONTROL_USB to all arch/platforms as well. Earlier it was suggested[1] that we revert the change of 6992819feb to restore the dependency, and add a same ARCH_OMAP2PLUS dependency to the new OMAP_USB3 entry. However that was discouraged on the grounds of people wanting the extra sanity compile testing on x86, even though the driver could probably never be used there. Now we have CONFIG_COMPILE_TEST, so developers who value the ability to compile drivers on an architecture that it never can be used for can have that, and people who want dependencies to shield them from seeing options that aren't relevant to their platform get what they want too. Here we restore the dependency but couple it with COMPILE_TEST, in order to achieve both of the above goals. [1] https://patchwork.kernel.org/patch/2194511/ Acked-by: Felipe Balbi Cc: Kishon Vijay Abraham I Cc: Moiz Sonasath Cc: Jiri Slaby Signed-off-by: Paul Gortmaker Signed-off-by: Greg Kroah-Hartman --- drivers/usb/phy/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index 3622fff8b798..b57514ba486a 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -65,6 +65,7 @@ config NOP_USB_XCEIV config OMAP_CONTROL_USB tristate "OMAP CONTROL USB Driver" + depends on ARCH_OMAP2PLUS || COMPILE_TEST help Enable this to add support for the USB part present in the control module. This driver has API to power on the USB2 PHY and to write to @@ -84,6 +85,7 @@ config OMAP_USB2 config OMAP_USB3 tristate "OMAP USB3 PHY Driver" + depends on ARCH_OMAP2PLUS || COMPILE_TEST select OMAP_CONTROL_USB help Enable this to support the USB3 PHY that is part of SOC. This From 435932f2c75efcdd07273a437b9be32647d56d73 Mon Sep 17 00:00:00 2001 From: caizhiyong Date: Fri, 26 Jul 2013 07:12:14 +0000 Subject: [PATCH 0818/3400] USB: ohci_usb warn "irq nobody cared" on shutdown When ohci-hcd is shutting down, call ohci_usb_reset reset ohci-hcd, the root hub generate an interrupt, but ohci->rh_state is OHCI_RH_HALTED, and ohci_irq ignore the interrupt, the kernel trigger warning "irq nobody cared". ehci-hcd is first disable interrupts, then reset ehci. This patch disable ohci interrupt before reset ohci. The patch is tested at the arm cortex-a9 demo board. Signed-off-by: caizhiyong Reviewed-by: Alan Stern 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 a9d3437da220..8f6b695af6a4 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -938,8 +938,8 @@ static void ohci_stop (struct usb_hcd *hcd) if (quirk_nec(ohci)) flush_work(&ohci->nec_work); - ohci_usb_reset (ohci); ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); + ohci_usb_reset(ohci); free_irq(hcd->irq, hcd); hcd->irq = 0; From f6a6621e543b049323b5a384532da5d1b37b8508 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 26 Jul 2013 14:20:39 -0700 Subject: [PATCH 0819/3400] staging: xillybus: force to be a module As reported, this driver causes problems when built into the kernel, so force it to be a module until those issues are fixed. Also delete the "default n" lines in the Kconfig, as they are not needed. Reported-by: Stephen Rothwell Cc: Eli Billauer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xillybus/Kconfig | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/staging/xillybus/Kconfig b/drivers/staging/xillybus/Kconfig index 58fd5488fefb..459d050065f7 100644 --- a/drivers/staging/xillybus/Kconfig +++ b/drivers/staging/xillybus/Kconfig @@ -4,8 +4,7 @@ config XILLYBUS tristate "Xillybus generic FPGA interface" - depends on PCI || (OF_ADDRESS && OF_DEVICE && OF_IRQ) - default n + depends on PCI || (OF_ADDRESS && OF_DEVICE && OF_IRQ) && m help Xillybus is a generic interface for peripherals designed on programmable logic (FPGA). The driver probes the hardware for @@ -18,7 +17,6 @@ if XILLYBUS config XILLYBUS_PCIE tristate "Xillybus over PCIe" depends on XILLYBUS && PCI - default n help Set to M if you want Xillybus to use PCI Express for communicating with the FPGA. @@ -26,7 +24,6 @@ config XILLYBUS_PCIE config XILLYBUS_OF tristate "Xillybus over Device Tree" depends on XILLYBUS && OF_ADDRESS && OF_DEVICE && OF_IRQ - default n help Set to M if you want Xillybus to find its resources from the Open Firmware Flattened Device Tree. If the target is an embedded From 8fd62389a778c902c7e8532594ea924bbaf465e8 Mon Sep 17 00:00:00 2001 From: Rohit Vaswani Date: Tue, 18 Jun 2013 18:53:33 -0700 Subject: [PATCH 0820/3400] ARM: msm: Consolidate gpiomux for older architectures Msm gpiomux can be used only for 7x30 and 8x50. Prevent compilation and fix build issues on 7X00, 8X60 and 8960. Signed-off-by: Rohit Vaswani Signed-off-by: David Brown --- arch/arm/mach-msm/Kconfig | 3 +-- arch/arm/mach-msm/gpiomux-v1.c | 33 --------------------------------- arch/arm/mach-msm/gpiomux.h | 10 ---------- 3 files changed, 1 insertion(+), 45 deletions(-) delete mode 100644 arch/arm/mach-msm/gpiomux-v1.c diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig index 614e41e7881b..905efc8cac79 100644 --- a/arch/arm/mach-msm/Kconfig +++ b/arch/arm/mach-msm/Kconfig @@ -121,8 +121,7 @@ config MSM_SMD bool config MSM_GPIOMUX - depends on !(ARCH_MSM8X60 || ARCH_MSM8960) - bool "MSM V1 TLMM GPIOMUX architecture" + bool help Support for MSM V1 TLMM GPIOMUX architecture. diff --git a/arch/arm/mach-msm/gpiomux-v1.c b/arch/arm/mach-msm/gpiomux-v1.c deleted file mode 100644 index 27de2abd7144..000000000000 --- a/arch/arm/mach-msm/gpiomux-v1.c +++ /dev/null @@ -1,33 +0,0 @@ -/* Copyright (c) 2010, Code Aurora Forum. 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 and - * only 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 Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ -#include -#include "gpiomux.h" -#include "proc_comm.h" - -void __msm_gpiomux_write(unsigned gpio, gpiomux_config_t val) -{ - unsigned tlmm_config = (val & ~GPIOMUX_CTL_MASK) | - ((gpio & 0x3ff) << 4); - unsigned tlmm_disable = 0; - int rc; - - rc = msm_proc_comm(PCOM_RPC_GPIO_TLMM_CONFIG_EX, - &tlmm_config, &tlmm_disable); - if (rc) - pr_err("%s: unexpected proc_comm failure %d: %08x %08x\n", - __func__, rc, tlmm_config, tlmm_disable); -} diff --git a/arch/arm/mach-msm/gpiomux.h b/arch/arm/mach-msm/gpiomux.h index 8e82f41a8923..4410d7766f93 100644 --- a/arch/arm/mach-msm/gpiomux.h +++ b/arch/arm/mach-msm/gpiomux.h @@ -73,16 +73,6 @@ extern struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS]; int msm_gpiomux_write(unsigned gpio, gpiomux_config_t active, gpiomux_config_t suspended); - -/* Architecture-internal function for use by the framework only. - * This function can assume the following: - * - the gpio value has passed a bounds-check - * - the gpiomux spinlock has been obtained - * - * This function is not for public consumption. External users - * should use msm_gpiomux_write. - */ -void __msm_gpiomux_write(unsigned gpio, gpiomux_config_t val); #else static inline int msm_gpiomux_write(unsigned gpio, gpiomux_config_t active, From e71042f24129fbe8f1d126721eceaf5ad690c97a Mon Sep 17 00:00:00 2001 From: Eli Billauer Date: Sat, 27 Jul 2013 00:24:00 +0300 Subject: [PATCH 0821/3400] staging: xillybus: Multiple definition of xillyname resolved (bug fix) Reported-by: Stephen Rothwell Signed-off-by: Eli Billauer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xillybus/xillybus.h | 2 -- drivers/staging/xillybus/xillybus_core.c | 2 ++ drivers/staging/xillybus/xillybus_of.c | 2 ++ drivers/staging/xillybus/xillybus_pcie.c | 2 ++ 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/staging/xillybus/xillybus.h b/drivers/staging/xillybus/xillybus.h index c260ebcc6c4d..b62faeb31c53 100644 --- a/drivers/staging/xillybus/xillybus.h +++ b/drivers/staging/xillybus/xillybus.h @@ -24,8 +24,6 @@ #include #include -char xillyname[] = "xillybus"; - struct xilly_endpoint_hardware; struct xilly_page { diff --git a/drivers/staging/xillybus/xillybus_core.c b/drivers/staging/xillybus/xillybus_core.c index dd0a71c6b518..7991e572ef04 100644 --- a/drivers/staging/xillybus/xillybus_core.c +++ b/drivers/staging/xillybus/xillybus_core.c @@ -61,6 +61,8 @@ MODULE_LICENSE("GPL v2"); #define XILLYMSG_OPCODE_FATAL_ERROR 4 #define XILLYMSG_OPCODE_NONEMPTY 5 +static const char xillyname[] = "xillybus"; + static struct class *xillybus_class; /* diff --git a/drivers/staging/xillybus/xillybus_of.c b/drivers/staging/xillybus/xillybus_of.c index b875376766a2..122d9ba1b28b 100644 --- a/drivers/staging/xillybus/xillybus_of.c +++ b/drivers/staging/xillybus/xillybus_of.c @@ -27,6 +27,8 @@ MODULE_VERSION("1.06"); MODULE_ALIAS("xillybus_of"); MODULE_LICENSE("GPL v2"); +static const char xillyname[] = "xillybus_of"; + /* Match table for of_platform binding */ static struct of_device_id xillybus_of_match[] = { { .compatible = "xlnx,xillybus-1.00.a", }, diff --git a/drivers/staging/xillybus/xillybus_pcie.c b/drivers/staging/xillybus/xillybus_pcie.c index 592f8f7a0b2c..ad45bdb2a715 100644 --- a/drivers/staging/xillybus/xillybus_pcie.c +++ b/drivers/staging/xillybus/xillybus_pcie.c @@ -28,6 +28,8 @@ MODULE_LICENSE("GPL v2"); #define PCI_VENDOR_ID_ACTEL 0x11aa #define PCI_VENDOR_ID_LATTICE 0x1204 +static const char xillyname[] = "xillybus_pcie"; + static DEFINE_PCI_DEVICE_TABLE(xillyids) = { {PCI_DEVICE(PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_XILLYBUS)}, {PCI_DEVICE(PCI_VENDOR_ID_ALTERA, PCI_DEVICE_ID_XILLYBUS)}, From e4ea910a487af187950f88d345e6dc9744c8d257 Mon Sep 17 00:00:00 2001 From: Shaun Laing Date: Fri, 26 Jul 2013 08:25:34 -0600 Subject: [PATCH 0822/3400] staging: comedi: dt9812: Resolves sparse endian warnings. Resolves warnings from the "sparse" checker of the form "warning: cast to restricted __le??". Signed-off-by: Shaun Laing Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt9812.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c index ffb7572b10f5..bd14017b798c 100644 --- a/drivers/staging/comedi/drivers/dt9812.c +++ b/drivers/staging/comedi/drivers/dt9812.c @@ -707,8 +707,9 @@ static int dt9812_reset_device(struct comedi_device *dev) u32 serial; u16 vendor; u16 product; - u16 tmp16; u8 tmp8; + __le16 tmp16; + __le32 tmp32; int ret; int i; @@ -731,19 +732,19 @@ static int dt9812_reset_device(struct comedi_device *dev) } } - ret = dt9812_read_info(dev, 1, &vendor, sizeof(vendor)); + ret = dt9812_read_info(dev, 1, &tmp16, sizeof(tmp16)); if (ret) { dev_err(dev->class_dev, "failed to read vendor id\n"); return ret; } - vendor = le16_to_cpu(vendor); + vendor = le16_to_cpu(tmp16); - ret = dt9812_read_info(dev, 3, &product, sizeof(product)); + ret = dt9812_read_info(dev, 3, &tmp16, sizeof(tmp16)); if (ret) { dev_err(dev->class_dev, "failed to read product id\n"); return ret; } - product = le16_to_cpu(product); + product = le16_to_cpu(tmp16); ret = dt9812_read_info(dev, 5, &tmp16, sizeof(tmp16)); if (ret) { @@ -752,12 +753,12 @@ static int dt9812_reset_device(struct comedi_device *dev) } devpriv->device = le16_to_cpu(tmp16); - ret = dt9812_read_info(dev, 7, &serial, sizeof(serial)); + ret = dt9812_read_info(dev, 7, &tmp32, sizeof(tmp32)); if (ret) { dev_err(dev->class_dev, "failed to read serial number\n"); return ret; } - serial = le32_to_cpu(serial); + serial = le32_to_cpu(tmp32); /* let the user know what node this device is now attached to */ dev_info(dev->class_dev, "USB DT9812 (%4.4x.%4.4x.%4.4x) #0x%8.8x\n", From 91f44915115f8c9f79457d24a57472cac78dc2ee Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 26 Jul 2013 12:03:19 +0100 Subject: [PATCH 0823/3400] staging: comedi: Kconfig: COMEDI_NI_ATMIO16D should not depend on ISAPNP The COMEDI_NI_ATMIO16D configuration option causes the "ni_atmio16d" module to be built, which handles the National Instruments AT-MIO-16 and AT-MIO-16D cards. The configuration option currently depends on ISAPNP, but the module doesn't use any ISAPNP functions and the cards are legacy ISA cards with base I/O port, IRQ and DMA channel configured by jumpers. (The driver doesn't use DMA though.) Remove the ISADNP dependancy from COMEDI_NI_ATMIO16D and fix up the help text - the card names are missing a dash and they're not ISA-PNP. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/Kconfig | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index 01782fccbf2a..8c6527f7b93e 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -480,11 +480,10 @@ config COMEDI_NI_ATMIO called ni_atmio. config COMEDI_NI_ATMIO16D - tristate "NI AT-MIO16/AT-MIO16D series ISA-PNP card support" - depends on ISAPNP + tristate "NI AT-MIO-16/AT-MIO-16D series ISA card support" select COMEDI_8255 ---help--- - Enable support for National Instruments AT-MIO16/AT-MIO16D cards. + Enable support for National Instruments AT-MIO-16/AT-MIO-16D cards. To compile this driver as a module, choose M here: the module will be called ni_atmio16d. From 4bed4f03883af9af08f3d0ae276ace2b5898d846 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 26 Jul 2013 12:03:20 +0100 Subject: [PATCH 0824/3400] staging: comedi: Kconfig: COMEDI_NI_ATMIO doesn't need to depend on ISAPNP The COMEDI_NI_ATMIO configuration option causes the "ni_atmio" module to be built, which handles various National Instruments ISA-PNP data acquisition cards. The configuration option currently depends on ISAPNP. The "ni_atmio" module is a "legacy" comedi driver with no auto-configuration support and it doesn't register as a PNP card driver. The only difference in initialization from the other comedi ISA card drivers is that it will use the ISA-PNP functions to find, attach and activate the card if no I/O base address has been specified by the user in the COMEDI_DEVCONFIG ioctl. The module compiles fine without the ISAPNP configuration option as the and headers provide dummy inline functions if the ISAPNP and PNP options, respectively, are not enabled. Remove the dependancy on the ISAPNP option since the module builds without it and can be used without it. (There is a very slim chance that comedi will support proper ISA PNP drivers one day, in which case the ni_atmio driver could be converted to use this support and not support manual configuration. However, not all the PnP IDs of boards supported by this driver are currently known to us.) Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index 8c6527f7b93e..57362fee7593 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -467,7 +467,6 @@ config COMEDI_NI_AT_AO config COMEDI_NI_ATMIO tristate "NI AT-MIO E series ISA-PNP card support" - depends on ISAPNP select COMEDI_8255 select COMEDI_NI_TIO ---help--- From b07dee7c9aa78e9b55e0b4ecdba622db55a99ffe Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Fri, 26 Jul 2013 10:15:55 +0800 Subject: [PATCH 0825/3400] staging: gdm724x: use GFP_ATOMIC under spin lock A spin lock is taken here so we should use GFP_ATOMIC. Signed-off-by: Wei Yongjun Acked-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gdm724x/gdm_mux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/gdm724x/gdm_mux.c b/drivers/staging/gdm724x/gdm_mux.c index 2e619d2e7ba1..b630babb57af 100644 --- a/drivers/staging/gdm724x/gdm_mux.c +++ b/drivers/staging/gdm724x/gdm_mux.c @@ -409,7 +409,7 @@ static int gdm_mux_send(void *priv_dev, void *data, int len, int tty_index, gdm_mux_send_complete, t); - ret = usb_submit_urb(t->urb, GFP_KERNEL); + ret = usb_submit_urb(t->urb, GFP_ATOMIC); spin_unlock_irqrestore(&mux_dev->write_lock, flags); From 9c922a9076afd9e483bc17d768ed813d2f76f7cb Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 25 Jul 2013 16:21:13 -0700 Subject: [PATCH 0826/3400] staging: comedi: usbduxsigma: set *_cmd_running flags before submitting urbs As pointed out by Ian Abbott, the *_cmd_running flags should be set before submitting the urbs. There is a possible race condition where an urb could complete and the flag is checked in the completion routine before it's set. Reported-by: Ian Abbott Acked-by: Ian Abbott Reviewed-by: Ian Abbott Signed-off-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbduxsigma.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index 40eeb8c68306..1af235407eb4 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -686,13 +686,14 @@ static int usbduxsigma_ai_inttrig(struct comedi_device *dev, down(&devpriv->sem); if (!devpriv->ai_cmd_running) { + devpriv->ai_cmd_running = 1; ret = usbduxsigma_submit_urbs(dev, devpriv->ai_urbs, devpriv->n_ai_urbs, 1); if (ret < 0) { + devpriv->ai_cmd_running = 0; up(&devpriv->sem); return ret; } - devpriv->ai_cmd_running = 1; s->async->inttrig = NULL; } up(&devpriv->sem); @@ -740,14 +741,15 @@ static int usbduxsigma_ai_cmd(struct comedi_device *dev, if (cmd->start_src == TRIG_NOW) { /* enable this acquisition operation */ + devpriv->ai_cmd_running = 1; ret = usbduxsigma_submit_urbs(dev, devpriv->ai_urbs, devpriv->n_ai_urbs, 1); if (ret < 0) { + devpriv->ai_cmd_running = 0; up(&devpriv->sem); return ret; } s->async->inttrig = NULL; - devpriv->ai_cmd_running = 1; } else { /* TRIG_INT */ /* wait for an internal signal and submit the urbs later */ s->async->inttrig = usbduxsigma_ai_inttrig; @@ -876,13 +878,14 @@ static int usbduxsigma_ao_inttrig(struct comedi_device *dev, down(&devpriv->sem); if (!devpriv->ao_cmd_running) { + devpriv->ao_cmd_running = 1; ret = usbduxsigma_submit_urbs(dev, devpriv->ao_urbs, devpriv->n_ao_urbs, 0); if (ret < 0) { + devpriv->ao_cmd_running = 0; up(&devpriv->sem); return ret; } - devpriv->ao_cmd_running = 1; s->async->inttrig = NULL; } up(&devpriv->sem); @@ -1026,14 +1029,15 @@ static int usbduxsigma_ao_cmd(struct comedi_device *dev, if (cmd->start_src == TRIG_NOW) { /* enable this acquisition operation */ + devpriv->ao_cmd_running = 1; ret = usbduxsigma_submit_urbs(dev, devpriv->ao_urbs, devpriv->n_ao_urbs, 0); if (ret < 0) { + devpriv->ao_cmd_running = 0; up(&devpriv->sem); return ret; } s->async->inttrig = NULL; - devpriv->ao_cmd_running = 1; } else { /* TRIG_INT */ /* wait for an internal signal and submit the urbs later */ s->async->inttrig = usbduxsigma_ao_inttrig; @@ -1237,10 +1241,12 @@ static int usbduxsigma_pwm_start(struct comedi_device *dev, memset(devpriv->pwm_urb->transfer_buffer, 0, devpriv->pwm_buf_sz); - ret = usbduxsigma_submit_pwm_urb(dev); - if (ret < 0) - return ret; devpriv->pwm_cmd_running = 1; + ret = usbduxsigma_submit_pwm_urb(dev); + if (ret < 0) { + devpriv->pwm_cmd_running = 0; + return ret; + } return 0; } From e5cb2f9498e0a5b4c7f882a21dbba8f8ba351819 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 25 Jul 2013 16:03:15 -0700 Subject: [PATCH 0827/3400] staging: comedi: usbdux: tidy up usbdux_ai_inttrig() Rename the local variable used for the private data pointer to the comedi "norm". Remove the unnecessary sanity check of the private data pointer. This function can only be called is the private data was allocated during the attach. Tidy up the exit path using goto to ensure that the semaphore is released. Return -EBUSY if an ai command is already running. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 35 +++++++++++++------------ 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index d0d683bc83c2..95c11e820fd2 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -852,31 +852,32 @@ static int receive_dux_commands(struct comedi_device *dev, int command) } static int usbdux_ai_inttrig(struct comedi_device *dev, - struct comedi_subdevice *s, unsigned int trignum) + struct comedi_subdevice *s, + unsigned int trignum) { - int ret; - struct usbdux_private *this_usbduxsub = dev->private; - if (!this_usbduxsub) - return -EFAULT; + struct usbdux_private *devpriv = dev->private; + int ret = -EINVAL; - down(&this_usbduxsub->sem); + down(&devpriv->sem); - if (trignum != 0) { - up(&this_usbduxsub->sem); - return -EINVAL; - } - if (!(this_usbduxsub->ai_cmd_running)) { - this_usbduxsub->ai_cmd_running = 1; + if (trignum != 0) + goto ai_trig_exit; + + if (!devpriv->ai_cmd_running) { + devpriv->ai_cmd_running = 1; ret = usbduxsub_submit_inurbs(dev); if (ret < 0) { - this_usbduxsub->ai_cmd_running = 0; - up(&this_usbduxsub->sem); - return ret; + devpriv->ai_cmd_running = 0; + goto ai_trig_exit; } s->async->inttrig = NULL; + } else { + ret = -EBUSY; } - up(&this_usbduxsub->sem); - return 1; + +ai_trig_exit: + up(&devpriv->sem); + return ret; } static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) From 9a79dfce37416c5677512fe5cf7c5a59f8f9b73d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 25 Jul 2013 16:03:34 -0700 Subject: [PATCH 0828/3400] staging: comedi: usbdux: tidy up usbdux_ai_cmd() Rename the local variable used for the private data pointer to the comedi "norm". Remove the unnecessary sanity check of the private data pointer. This function can only be called is the private data was allocated during the attach. Tidy up the exit path using goto to ensure that the semaphore is released. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 93 ++++++++++++------------- 1 file changed, 45 insertions(+), 48 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 95c11e820fd2..aebc728c9be9 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -882,85 +882,79 @@ ai_trig_exit: static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { + struct usbdux_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; - unsigned int chan, range; - int i, ret; - struct usbdux_private *this_usbduxsub = dev->private; - int result; - - if (!this_usbduxsub) - return -EFAULT; + int len = cmd->chanlist_len; + int ret = -EBUSY; + int i; /* block other CPUs from starting an ai_cmd */ - down(&this_usbduxsub->sem); - if (this_usbduxsub->ai_cmd_running) { - up(&this_usbduxsub->sem); - return -EBUSY; - } + down(&devpriv->sem); + + if (devpriv->ai_cmd_running) + goto ai_cmd_exit; + /* set current channel of the running acquisition to zero */ s->async->cur_chan = 0; - this_usbduxsub->dux_commands[1] = cmd->chanlist_len; - for (i = 0; i < cmd->chanlist_len; ++i) { - chan = CR_CHAN(cmd->chanlist[i]); - range = CR_RANGE(cmd->chanlist[i]); + devpriv->dux_commands[1] = len; + for (i = 0; i < len; ++i) { + unsigned int chan = CR_CHAN(cmd->chanlist[i]); + unsigned int range = CR_RANGE(cmd->chanlist[i]); + if (i >= NUMCHANNELS) break; - this_usbduxsub->dux_commands[i + 2] = - create_adc_command(chan, range); + + devpriv->dux_commands[i + 2] = create_adc_command(chan, range); } - result = send_dux_commands(dev, SENDADCOMMANDS); - if (result < 0) { - up(&this_usbduxsub->sem); - return result; - } + ret = send_dux_commands(dev, SENDADCOMMANDS); + if (ret < 0) + goto ai_cmd_exit; - if (this_usbduxsub->high_speed) { + if (devpriv->high_speed) { /* * every channel gets a time window of 125us. Thus, if we * sample all 8 channels we need 1ms. If we sample only one * channel we need only 125us */ - this_usbduxsub->ai_interval = 1; + devpriv->ai_interval = 1; /* find a power of 2 for the interval */ - while ((this_usbduxsub->ai_interval) < (cmd->chanlist_len)) { - this_usbduxsub->ai_interval = - (this_usbduxsub->ai_interval) * 2; - } - this_usbduxsub->ai_timer = cmd->scan_begin_arg / (125000 * - (this_usbduxsub-> - ai_interval)); + while (devpriv->ai_interval < len) + devpriv->ai_interval *= 2; + + devpriv->ai_timer = cmd->scan_begin_arg / + (125000 * devpriv->ai_interval); } else { /* interval always 1ms */ - this_usbduxsub->ai_interval = 1; - this_usbduxsub->ai_timer = cmd->scan_begin_arg / 1000000; + devpriv->ai_interval = 1; + devpriv->ai_timer = cmd->scan_begin_arg / 1000000; } - if (this_usbduxsub->ai_timer < 1) { - up(&this_usbduxsub->sem); - return -EINVAL; + if (devpriv->ai_timer < 1) { + ret = -EINVAL; + goto ai_cmd_exit; } - this_usbduxsub->ai_counter = this_usbduxsub->ai_timer; + + devpriv->ai_counter = devpriv->ai_timer; if (cmd->stop_src == TRIG_COUNT) { /* data arrives as one packet */ - this_usbduxsub->ai_sample_count = cmd->stop_arg; - this_usbduxsub->ai_continous = 0; + devpriv->ai_sample_count = cmd->stop_arg; + devpriv->ai_continous = 0; } else { /* continous acquisition */ - this_usbduxsub->ai_continous = 1; - this_usbduxsub->ai_sample_count = 0; + devpriv->ai_continous = 1; + devpriv->ai_sample_count = 0; } if (cmd->start_src == TRIG_NOW) { /* enable this acquisition operation */ - this_usbduxsub->ai_cmd_running = 1; + devpriv->ai_cmd_running = 1; ret = usbduxsub_submit_inurbs(dev); if (ret < 0) { - this_usbduxsub->ai_cmd_running = 0; + devpriv->ai_cmd_running = 0; /* fixme: unlink here?? */ - up(&this_usbduxsub->sem); - return ret; + goto ai_cmd_exit; } s->async->inttrig = NULL; } else { @@ -969,8 +963,11 @@ static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* wait for an internal signal */ s->async->inttrig = usbdux_ai_inttrig; } - up(&this_usbduxsub->sem); - return 0; + +ai_cmd_exit: + up(&devpriv->sem); + + return ret; } /* Mode 0 is used to get a single conversion on demand */ From a79b4cdb52151dab5c5b2a86ab7619bc457470a8 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 25 Jul 2013 16:03:53 -0700 Subject: [PATCH 0829/3400] staging: comedi: usbdux: tidy up usbdux_ai_insn_read() Rename the local variable used for the private data pointer to the comedi "norm". Remove the unnecessary sanity check of the private data pointer. This function can only be called is the private data was allocated during the attach. Tidy up the exit path using goto to ensure that the semaphore is released. Return -EBUSY instead of 0 if the (*insn_read) cannot be done because a command is running. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 59 +++++++++++-------------- 1 file changed, 27 insertions(+), 32 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index aebc728c9be9..a536fa3b6858 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -973,50 +973,45 @@ ai_cmd_exit: /* Mode 0 is used to get a single conversion on demand */ static int usbdux_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { + struct usbdux_private *devpriv = dev->private; + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int range = CR_RANGE(insn->chanspec); + unsigned int val; + int ret = -EBUSY; int i; - unsigned int one = 0; - int chan, range; - int err; - struct usbdux_private *this_usbduxsub = dev->private; - if (!this_usbduxsub) - return 0; + down(&devpriv->sem); - down(&this_usbduxsub->sem); - if (this_usbduxsub->ai_cmd_running) { - up(&this_usbduxsub->sem); - return 0; - } + if (devpriv->ai_cmd_running) + goto ai_read_exit; - /* sample one channel */ - chan = CR_CHAN(insn->chanspec); - range = CR_RANGE(insn->chanspec); /* set command for the first channel */ - this_usbduxsub->dux_commands[1] = create_adc_command(chan, range); + devpriv->dux_commands[1] = create_adc_command(chan, range); /* adc commands */ - err = send_dux_commands(dev, SENDSINGLEAD); - if (err < 0) { - up(&this_usbduxsub->sem); - return err; - } + ret = send_dux_commands(dev, SENDSINGLEAD); + if (ret < 0) + goto ai_read_exit; for (i = 0; i < insn->n; i++) { - err = receive_dux_commands(dev, SENDSINGLEAD); - if (err < 0) { - up(&this_usbduxsub->sem); - return 0; - } - one = le16_to_cpu(this_usbduxsub->insn_buffer[1]); - if (CR_RANGE(insn->chanspec) <= 1) - one = one ^ 0x800; + ret = receive_dux_commands(dev, SENDSINGLEAD); + if (ret < 0) + goto ai_read_exit; - data[i] = one; + val = le16_to_cpu(devpriv->insn_buffer[1]); + if (range <= 1) + val ^= 0x800; + + data[i] = val; } - up(&this_usbduxsub->sem); - return i; + +ai_read_exit: + up(&devpriv->sem); + + return ret ? ret : insn->n; } /************************************/ From 91891f7cc6453bec358a3bc2a0cf9a0b2f8223d5 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 25 Jul 2013 16:04:17 -0700 Subject: [PATCH 0830/3400] staging: comedi: usbdux: clarify bipolar ai data Use the comedi_range_is_bipolar() helper instead of checking the 'range' index against a magic number. Also, use the s->maxdata to calculate the value needed to munge the value for bipolar data instead of the magic number. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index a536fa3b6858..a81b4b17b297 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -1002,8 +1002,10 @@ static int usbdux_ai_insn_read(struct comedi_device *dev, goto ai_read_exit; val = le16_to_cpu(devpriv->insn_buffer[1]); - if (range <= 1) - val ^= 0x800; + + /* bipolar data is two's-complement */ + if (comedi_range_is_bipolar(s, range)) + val ^= ((s->maxdata + 1) >> 1); data[i] = val; } From 818782c8a7744f5183e5e1a411622ce0ae25a558 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 25 Jul 2013 16:04:34 -0700 Subject: [PATCH 0831/3400] staging: comedi: usbdux: tidy up usbdux_ao_insn_read() Rename the local variable used for the private data pointer to the comedi "norm". Remove the unnecessary sanity check of the private data pointer. This function can only be called is the private data was allocated during the attach. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index a81b4b17b297..4159936a6312 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -1016,26 +1016,21 @@ ai_read_exit: return ret ? ret : insn->n; } -/************************************/ -/* analog out */ - static int usbdux_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { + struct usbdux_private *devpriv = dev->private; + unsigned int chan = CR_CHAN(insn->chanspec); int i; - int chan = CR_CHAN(insn->chanspec); - struct usbdux_private *this_usbduxsub = dev->private; - if (!this_usbduxsub) - return -EFAULT; - - down(&this_usbduxsub->sem); + down(&devpriv->sem); for (i = 0; i < insn->n; i++) - data[i] = this_usbduxsub->out_buffer[chan]; + data[i] = devpriv->out_buffer[chan]; + up(&devpriv->sem); - up(&this_usbduxsub->sem); - return i; + return insn->n; } static int usbdux_ao_insn_write(struct comedi_device *dev, From 37c1d1ec37144e9fe14bcc0c3ab0bba92c332312 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 25 Jul 2013 16:05:00 -0700 Subject: [PATCH 0832/3400] staging: comedi: usbdux: tidy up usbdux_ao_insn_write() Rename the local variable used for the private data pointer to the comedi "norm". Remove the unnecessary sanity check of the private data pointer. This function can only be called is the private data was allocated during the attach. Tidy up the exit path using goto to ensure that the semaphore is released. Return -EBUSY instead of 0 if the (*insn_write) cannot be done because a command is running. Tidy up the for() loop that writes the data. The dux_commands[1] and [4] can be set outside the loop since they are constant. Use a local pointer for dux_commands[2] to load the value to write. Only the last value needs to be cached in the private data for read back. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 57 +++++++++++++------------ 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 4159936a6312..1e6cb0a60a07 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -1035,39 +1035,42 @@ static int usbdux_ao_insn_read(struct comedi_device *dev, static int usbdux_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - int i, err; - int chan = CR_CHAN(insn->chanspec); - struct usbdux_private *this_usbduxsub = dev->private; + struct usbdux_private *devpriv = dev->private; + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int val = devpriv->out_buffer[chan]; + int16_t *p = (int16_t *)&devpriv->dux_commands[2]; + int ret = -EBUSY; + int i; - if (!this_usbduxsub) - return -EFAULT; + down(&devpriv->sem); - down(&this_usbduxsub->sem); - if (this_usbduxsub->ao_cmd_running) { - up(&this_usbduxsub->sem); - return 0; - } + if (devpriv->ao_cmd_running) + goto ao_write_exit; + + /* number of channels: 1 */ + devpriv->dux_commands[1] = 1; + /* channel number */ + devpriv->dux_commands[4] = chan << 6; for (i = 0; i < insn->n; i++) { - /* number of channels: 1 */ - this_usbduxsub->dux_commands[1] = 1; - /* one 16 bit value */ - *((int16_t *) (this_usbduxsub->dux_commands + 2)) = - cpu_to_le16(data[i]); - this_usbduxsub->out_buffer[chan] = data[i]; - /* channel number */ - this_usbduxsub->dux_commands[4] = (chan << 6); - err = send_dux_commands(dev, SENDDACOMMANDS); - if (err < 0) { - up(&this_usbduxsub->sem); - return err; - } - } - up(&this_usbduxsub->sem); + val = data[i]; - return i; + /* one 16 bit value */ + *p = cpu_to_le16(val); + + ret = send_dux_commands(dev, SENDDACOMMANDS); + if (ret < 0) + goto ao_write_exit; + } + devpriv->out_buffer[chan] = val; + +ao_write_exit: + up(&devpriv->sem); + + return ret ? ret : insn->n; } static int usbdux_ao_inttrig(struct comedi_device *dev, From f994282df674e31574291e2f8cbd986f234d9d91 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 25 Jul 2013 16:05:17 -0700 Subject: [PATCH 0833/3400] staging: comedi: usbdux: tidy up usbdux_ao_inttrig() Rename the local variable used for the private data pointer to the comedi "norm". Remove the unnecessary sanity check of the private data pointer. This function can only be called is the private data was allocated during the attach. Tidy up the exit path using goto to ensure that the semaphore is released. Return -EBUSY instead if an ao command is already running. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 35 +++++++++++++------------ 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 1e6cb0a60a07..9aa2e9ea53d1 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -1074,31 +1074,32 @@ ao_write_exit: } static int usbdux_ao_inttrig(struct comedi_device *dev, - struct comedi_subdevice *s, unsigned int trignum) + struct comedi_subdevice *s, + unsigned int trignum) { - int ret; - struct usbdux_private *this_usbduxsub = dev->private; + struct usbdux_private *devpriv = dev->private; + int ret = -EINVAL; - if (!this_usbduxsub) - return -EFAULT; + down(&devpriv->sem); - down(&this_usbduxsub->sem); - if (trignum != 0) { - up(&this_usbduxsub->sem); - return -EINVAL; - } - if (!(this_usbduxsub->ao_cmd_running)) { - this_usbduxsub->ao_cmd_running = 1; + if (trignum != 0) + goto ao_trig_exit; + + if (!devpriv->ao_cmd_running) { + devpriv->ao_cmd_running = 1; ret = usbduxsub_submit_outurbs(dev); if (ret < 0) { - this_usbduxsub->ao_cmd_running = 0; - up(&this_usbduxsub->sem); - return ret; + devpriv->ao_cmd_running = 0; + goto ao_trig_exit; } s->async->inttrig = NULL; + } else { + ret = -EBUSY; } - up(&this_usbduxsub->sem); - return 1; + +ao_trig_exit: + up(&devpriv->sem); + return ret; } static int usbdux_ao_cmdtest(struct comedi_device *dev, From 2a226948081f6285ddc7e8fd4c592d7378c7c55d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 25 Jul 2013 16:05:35 -0700 Subject: [PATCH 0834/3400] staging: comedi: usbdux: tidy up usbdux_ao_cmd() Rename the local variable used for the private data pointer to the comedi "norm". Remove the unnecessary sanity check of the private data pointer. This function can only be called is the private data was allocated during the attach. Make sure an ao command is not already running and return -EBUSY. Tidy up the exit path using goto to ensure that the semaphore is released. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 62 +++++++++++++------------ 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 9aa2e9ea53d1..40e1424ce5a0 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -1188,72 +1188,74 @@ static int usbdux_ao_cmdtest(struct comedi_device *dev, static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { + struct usbdux_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; - unsigned int chan, gain; - int i, ret; - struct usbdux_private *this_usbduxsub = dev->private; + int ret = -EBUSY; + int i; - if (!this_usbduxsub) - return -EFAULT; + down(&devpriv->sem); - down(&this_usbduxsub->sem); + if (devpriv->ao_cmd_running) + goto ao_cmd_exit; /* set current channel of the running acquisition to zero */ s->async->cur_chan = 0; + for (i = 0; i < cmd->chanlist_len; ++i) { - chan = CR_CHAN(cmd->chanlist[i]); - gain = CR_RANGE(cmd->chanlist[i]); + unsigned int chan = CR_CHAN(cmd->chanlist[i]); + if (i >= NUMOUTCHANNELS) break; - this_usbduxsub->dac_commands[i] = (chan << 6); + + devpriv->dac_commands[i] = chan << 6; } /* we count in steps of 1ms (125us) */ /* 125us mode not used yet */ - if (0) { /* (this_usbduxsub->high_speed) */ + if (0) { /* (devpriv->high_speed) */ /* 125us */ /* timing of the conversion itself: every 125 us */ - this_usbduxsub->ao_timer = cmd->convert_arg / 125000; + devpriv->ao_timer = cmd->convert_arg / 125000; } else { /* 1ms */ /* timing of the scan: we get all channels at once */ - this_usbduxsub->ao_timer = cmd->scan_begin_arg / 1000000; - if (this_usbduxsub->ao_timer < 1) { - up(&this_usbduxsub->sem); - return -EINVAL; + devpriv->ao_timer = cmd->scan_begin_arg / 1000000; + if (devpriv->ao_timer < 1) { + ret = -EINVAL; + goto ao_cmd_exit; } } - this_usbduxsub->ao_counter = this_usbduxsub->ao_timer; + + devpriv->ao_counter = devpriv->ao_timer; if (cmd->stop_src == TRIG_COUNT) { /* not continuous */ /* counter */ /* high speed also scans everything at once */ - if (0) { /* (this_usbduxsub->high_speed) */ - this_usbduxsub->ao_sample_count = - (cmd->stop_arg) * (cmd->scan_end_arg); + if (0) { /* (devpriv->high_speed) */ + devpriv->ao_sample_count = cmd->stop_arg * + cmd->scan_end_arg; } else { /* there's no scan as the scan has been */ /* perf inside the FX2 */ /* data arrives as one packet */ - this_usbduxsub->ao_sample_count = cmd->stop_arg; + devpriv->ao_sample_count = cmd->stop_arg; } - this_usbduxsub->ao_continous = 0; + devpriv->ao_continous = 0; } else { /* continous acquisition */ - this_usbduxsub->ao_continous = 1; - this_usbduxsub->ao_sample_count = 0; + devpriv->ao_continous = 1; + devpriv->ao_sample_count = 0; } if (cmd->start_src == TRIG_NOW) { /* enable this acquisition operation */ - this_usbduxsub->ao_cmd_running = 1; + devpriv->ao_cmd_running = 1; ret = usbduxsub_submit_outurbs(dev); if (ret < 0) { - this_usbduxsub->ao_cmd_running = 0; + devpriv->ao_cmd_running = 0; /* fixme: unlink here?? */ - up(&this_usbduxsub->sem); - return ret; + goto ao_cmd_exit; } s->async->inttrig = NULL; } else { @@ -1263,8 +1265,10 @@ static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) s->async->inttrig = usbdux_ao_inttrig; } - up(&this_usbduxsub->sem); - return 0; +ao_cmd_exit: + up(&devpriv->sem); + + return ret; } static int usbdux_dio_insn_config(struct comedi_device *dev, From fc110df61f0adf060d6b2011ecaba45332a479a6 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 25 Jul 2013 16:05:53 -0700 Subject: [PATCH 0835/3400] staging: comedi: usbdux: tidy up usbdux_dio_insn_config() Tidy up this function a bit. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 40e1424ce5a0..cdb02876a719 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -1273,32 +1273,30 @@ ao_cmd_exit: static int usbdux_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - int chan = CR_CHAN(insn->chanspec); - - /* The input or output configuration of each digital line is - * configured by a special insn_config instruction. chanspec - * contains the channel to be changed, and data[0] contains the - * value COMEDI_INPUT or COMEDI_OUTPUT. */ + unsigned int mask = 1 << CR_CHAN(insn->chanspec); switch (data[0]) { case INSN_CONFIG_DIO_OUTPUT: - s->io_bits |= 1 << chan; /* 1 means Out */ + s->io_bits |= mask; break; case INSN_CONFIG_DIO_INPUT: - s->io_bits &= ~(1 << chan); + s->io_bits &= ~mask; break; case INSN_CONFIG_DIO_QUERY: - data[1] = - (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT; + data[1] = (s->io_bits & mask) ? COMEDI_OUTPUT : COMEDI_INPUT; break; default: return -EINVAL; break; } - /* we don't tell the firmware here as it would take 8 frames */ - /* to submit the information. We do it in the insn_bits. */ + + /* + * We don't tell the firmware here as it would take 8 frames + * to submit the information. We do it in the insn_bits. + */ return insn->n; } From 81a9bdaac428174d04df8b361c9363a5e33f533f Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 25 Jul 2013 16:06:11 -0700 Subject: [PATCH 0836/3400] staging: comedi: usbdux: tidy up usbdux_dio_insn_bits() Rename the local variable used for the private data pointer to the comedi "norm". Remove the unnecessary sanity check of the private data pointer. This function can only be called is the private data was allocated during the attach. Tidy up the exit path using goto to ensure that the semaphore is released. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 54 ++++++++++++------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index cdb02876a719..a1e5cf1388f1 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -1302,40 +1302,40 @@ static int usbdux_dio_insn_config(struct comedi_device *dev, static int usbdux_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - struct usbdux_private *this_usbduxsub = dev->private; - int err; + struct usbdux_private *devpriv = dev->private; + unsigned int mask = data[0]; + unsigned int bits = data[1]; + int ret; - if (!this_usbduxsub) - return -EFAULT; + down(&devpriv->sem); - down(&this_usbduxsub->sem); + s->state &= ~mask; + s->state |= (bits & mask); - /* The insn data is a mask in data[0] and the new data - * in data[1], each channel cooresponding to a bit. */ - s->state &= ~data[0]; - s->state |= data[0] & data[1]; - this_usbduxsub->dux_commands[1] = s->io_bits; - this_usbduxsub->dux_commands[2] = s->state; + devpriv->dux_commands[1] = s->io_bits; + devpriv->dux_commands[2] = s->state; - /* This command also tells the firmware to return */ - /* the digital input lines */ - err = send_dux_commands(dev, SENDDIOBITSCOMMAND); - if (err < 0) { - up(&this_usbduxsub->sem); - return err; - } - err = receive_dux_commands(dev, SENDDIOBITSCOMMAND); - if (err < 0) { - up(&this_usbduxsub->sem); - return err; - } + /* + * This command also tells the firmware to return + * the digital input lines. + */ + ret = send_dux_commands(dev, SENDDIOBITSCOMMAND); + if (ret < 0) + goto dio_exit; + ret = receive_dux_commands(dev, SENDDIOBITSCOMMAND); + if (ret < 0) + goto dio_exit; - data[1] = le16_to_cpu(this_usbduxsub->insn_buffer[1]); - up(&this_usbduxsub->sem); - return insn->n; + data[1] = le16_to_cpu(devpriv->insn_buffer[1]); + +dio_exit: + up(&devpriv->sem); + + return ret ? ret : insn->n; } /* reads the 4 counters, only two are used just now */ From 48967d4f5d91acbe0e70fa821c5951059566ac84 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 25 Jul 2013 16:06:30 -0700 Subject: [PATCH 0837/3400] staging: comedi: usbdux: fix usbdux_counter_read() Comedi (*insn_read) operations are supposed to read and return insn->n values. Fix this function to work like the core expects. Rename the local variable used for the private data pointer to the comedi "norm". Remove the unnecessary sanity check of the private data pointer. This function can only be called is the private data was allocated during the attach. Tidy up the exit path using goto to ensure that the semaphore is released. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 39 ++++++++++++------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index a1e5cf1388f1..05bea98444db 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -1338,34 +1338,33 @@ dio_exit: return ret ? ret : insn->n; } -/* reads the 4 counters, only two are used just now */ static int usbdux_counter_read(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - struct usbdux_private *this_usbduxsub = dev->private; - int chan = insn->chanspec; - int err; + struct usbdux_private *devpriv = dev->private; + unsigned int chan = CR_CHAN(insn->chanspec); + int ret = 0; + int i; - if (!this_usbduxsub) - return -EFAULT; + down(&devpriv->sem); - down(&this_usbduxsub->sem); - err = send_dux_commands(dev, READCOUNTERCOMMAND); - if (err < 0) { - up(&this_usbduxsub->sem); - return err; + for (i = 0; i < insn->n; i++) { + ret = send_dux_commands(dev, READCOUNTERCOMMAND); + if (ret < 0) + goto counter_read_exit; + ret = receive_dux_commands(dev, READCOUNTERCOMMAND); + if (ret < 0) + goto counter_read_exit; + + data[i] = le16_to_cpu(devpriv->insn_buffer[chan + 1]); } - err = receive_dux_commands(dev, READCOUNTERCOMMAND); - if (err < 0) { - up(&this_usbduxsub->sem); - return err; - } +counter_read_exit: + up(&devpriv->sem); - data[0] = le16_to_cpu(this_usbduxsub->insn_buffer[chan + 1]); - up(&this_usbduxsub->sem); - return 1; + return ret ? ret : insn->n; } static int usbdux_counter_write(struct comedi_device *dev, From f2929618d376075e01136326148e7028350c7c38 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 25 Jul 2013 16:06:47 -0700 Subject: [PATCH 0838/3400] staging: comedi: usbdux: fix usbdux_counter_write() Comedi (*insn_write) operations are supposed to write insn->n values. Fix this function to work like the core expects. Rename the local variable used for the private data pointer to the comedi "norm". Remove the unnecessary sanity check of the private data pointer. This function can only be called is the private data was allocated during the attach. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 31 ++++++++++++++----------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 05bea98444db..82624a24eb3e 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -1369,27 +1369,30 @@ counter_read_exit: static int usbdux_counter_write(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - struct usbdux_private *this_usbduxsub = dev->private; - int err; + struct usbdux_private *devpriv = dev->private; + unsigned int chan = CR_CHAN(insn->chanspec); + int16_t *p = (int16_t *)&devpriv->dux_commands[2]; + int ret = 0; + int i; - if (!this_usbduxsub) - return -EFAULT; + down(&devpriv->sem); - down(&this_usbduxsub->sem); - this_usbduxsub->dux_commands[1] = insn->chanspec; - *((int16_t *) (this_usbduxsub->dux_commands + 2)) = cpu_to_le16(*data); + devpriv->dux_commands[1] = chan; - err = send_dux_commands(dev, WRITECOUNTERCOMMAND); - if (err < 0) { - up(&this_usbduxsub->sem); - return err; + for (i = 0; i < insn->n; i++) { + *p = cpu_to_le16(data[i]); + + ret = send_dux_commands(dev, WRITECOUNTERCOMMAND); + if (ret < 0) + break; } - up(&this_usbduxsub->sem); + up(&devpriv->sem); - return 1; + return ret ? ret : insn->n; } static int usbdux_counter_config(struct comedi_device *dev, From 38f0683502a5c57dd39e4c65ec86cbe8e3975d5b Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 25 Jul 2013 16:07:04 -0700 Subject: [PATCH 0839/3400] staging: comedi: usbdux: tidy up usbdux_pwm_stop() For aesthetic reasons, pass the comedi_device pointer to this function instead of the private data pointer. Rename the local variable used for the private data pointer to the comedi "norm". Remove the unnecessary sanity check of the private data pointer. This function can only be called is the private data was allocated during the attach. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 82624a24eb3e..61e9df90e403 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -1417,20 +1417,15 @@ static int usbduxsub_unlink_pwm_urbs(struct usbdux_private *usbduxsub_tmp) return err; } -/* This cancels a running acquisition operation - * in any context. - */ -static int usbdux_pwm_stop(struct usbdux_private *this_usbduxsub, int do_unlink) +static int usbdux_pwm_stop(struct comedi_device *dev, int do_unlink) { + struct usbdux_private *devpriv = dev->private; int ret = 0; - if (!this_usbduxsub) - return -EFAULT; - if (do_unlink) - ret = usbduxsub_unlink_pwm_urbs(this_usbduxsub); + ret = usbduxsub_unlink_pwm_urbs(devpriv); - this_usbduxsub->pwm_cmd_running = 0; + devpriv->pwm_cmd_running = 0; return ret; } @@ -1443,7 +1438,7 @@ static int usbdux_pwm_cancel(struct comedi_device *dev, int res = 0; /* unlink only if it is really running */ - res = usbdux_pwm_stop(this_usbduxsub, this_usbduxsub->pwm_cmd_running); + res = usbdux_pwm_stop(dev, this_usbduxsub->pwm_cmd_running); return send_dux_commands(dev, SENDPWMOFF); } @@ -1468,7 +1463,7 @@ static void usbduxsub_pwm_irq(struct urb *urb) * no unlink needed here. Already shutting down. */ if (devpriv->pwm_cmd_running) - usbdux_pwm_stop(devpriv, 0); + usbdux_pwm_stop(dev, 0); return; @@ -1478,7 +1473,7 @@ static void usbduxsub_pwm_irq(struct urb *urb) dev_err(dev->class_dev, "Non-zero urb status received in pwm intr context: %d\n", urb->status); - usbdux_pwm_stop(devpriv, 0); + usbdux_pwm_stop(dev, 0); } return; } @@ -1501,7 +1496,7 @@ static void usbduxsub_pwm_irq(struct urb *urb) "buggy USB host controller or bug in IRQ handling!\n"); /* don't do an unlink here */ - usbdux_pwm_stop(devpriv, 0); + usbdux_pwm_stop(dev, 0); } } } From 96ca37047e774c48cbf5ccf4e6d18e8cf5898dcd Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 25 Jul 2013 16:07:20 -0700 Subject: [PATCH 0840/3400] staging: comedi: usbdux: fix usbdux_pwm_cancel() Add the missing down/up of the semaphore to prevent other commands from being issued to the usb device while the pwn is being stopped. Rename the local variable used for the private data pointer to the comedi "norm". Make sure to check that usbdux_pwm_stop() was successful before sending command to the usb device to stop the pwm. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 61e9df90e403..14c26e559cb7 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -1430,17 +1430,25 @@ static int usbdux_pwm_stop(struct comedi_device *dev, int do_unlink) return ret; } -/* force unlink - is called by comedi */ static int usbdux_pwm_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { - struct usbdux_private *this_usbduxsub = dev->private; - int res = 0; + struct usbdux_private *devpriv = dev->private; + int ret; + + down(&devpriv->sem); /* unlink only if it is really running */ - res = usbdux_pwm_stop(dev, this_usbduxsub->pwm_cmd_running); + ret = usbdux_pwm_stop(dev, devpriv->pwm_cmd_running); + if (ret) + goto pwm_cancel_exit; - return send_dux_commands(dev, SENDPWMOFF); + ret = send_dux_commands(dev, SENDPWMOFF); + +pwm_cancel_exit: + up(&devpriv->sem); + + return ret; } static void usbduxsub_pwm_irq(struct urb *urb) From 81e8013484ae0790c7819aa9e08b265807eb6905 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 25 Jul 2013 16:07:39 -0700 Subject: [PATCH 0841/3400] staging: comedi: usbdux: fix usbdux_pwm_start() Add the missing down/up of the semaphore to prevent other commands from being issued to the usb device while the pwn is being stopped. Rename the local variable used for the private data pointer to the comedi "norm". Use memset() to initialize the urb transfer buffer. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 34 ++++++++++++------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 14c26e559cb7..0337da1f36fa 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -1544,34 +1544,34 @@ static int usbdux_pwm_period(struct comedi_device *dev, return 0; } -/* is called from insn so there's no need to do all the sanity checks */ static int usbdux_pwm_start(struct comedi_device *dev, struct comedi_subdevice *s) { - int ret, i; - struct usbdux_private *this_usbduxsub = dev->private; + struct usbdux_private *devpriv = dev->private; + int ret = 0; - if (this_usbduxsub->pwm_cmd_running) { - /* already running */ - return 0; - } + down(&devpriv->sem); - this_usbduxsub->dux_commands[1] = ((int8_t) this_usbduxsub->pwn_delay); + if (devpriv->pwm_cmd_running) + goto pwm_start_exit; + + devpriv->dux_commands[1] = devpriv->pwn_delay; ret = send_dux_commands(dev, SENDPWMON); if (ret < 0) - return ret; + goto pwm_start_exit; /* initialise the buffer */ - for (i = 0; i < this_usbduxsub->size_pwm_buf; i++) - ((char *)(this_usbduxsub->urb_pwm->transfer_buffer))[i] = 0; + memset(devpriv->urb_pwm->transfer_buffer, 0, devpriv->size_pwm_buf); - this_usbduxsub->pwm_cmd_running = 1; + devpriv->pwm_cmd_running = 1; ret = usbduxsub_submit_pwm_urbs(dev); - if (ret < 0) { - this_usbduxsub->pwm_cmd_running = 0; - return ret; - } - return 0; + if (ret < 0) + devpriv->pwm_cmd_running = 0; + +pwm_start_exit: + up(&devpriv->sem); + + return ret; } /* generates the bit pattern for PWM with the optional sign bit */ From 3c50bbb7cb0ba0d66aab4446b0554bd22e76f524 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 25 Jul 2013 16:07:57 -0700 Subject: [PATCH 0842/3400] staging: comedi: usbdux: tidy up unlink and stop helpers For aesthetic reasons, pass the comedi_device pointer to the unlink helpers instead of the private data pointer. All the unlink helpers simply call usb_kill_urb() to cancel any pending transfer requests. The usb passed to usb_kill_urb() can be NULL so the extra sanity check is not required. The unlink helpers will always return success so just make them void functions. Since the stop helpers will also always return success, make them void functions as well. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 123 +++++++++--------------- 1 file changed, 43 insertions(+), 80 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 0337da1f36fa..7077d268f883 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -249,53 +249,39 @@ struct usbdux_private { struct semaphore sem; }; -/* - * Stops the data acquision - * It should be safe to call this function from any context - */ -static int usbduxsub_unlink_inurbs(struct usbdux_private *usbduxsub_tmp) -{ - int i = 0; - int err = 0; - - if (usbduxsub_tmp && usbduxsub_tmp->urb_in) { - for (i = 0; i < usbduxsub_tmp->num_in_buffers; i++) { - if (usbduxsub_tmp->urb_in[i]) { - /* We wait here until all transfers have been - * cancelled. */ - usb_kill_urb(usbduxsub_tmp->urb_in[i]); - } - } - } - return err; -} - -static int usbdux_ai_stop(struct comedi_device *dev, int do_unlink) +static void usbduxsub_unlink_inurbs(struct comedi_device *dev) +{ + struct usbdux_private *devpriv = dev->private; + int i; + + if (devpriv->urb_in) { + for (i = 0; i < devpriv->num_in_buffers; i++) + usb_kill_urb(devpriv->urb_in[i]); + } +} + +static void usbdux_ai_stop(struct comedi_device *dev, int do_unlink) { struct usbdux_private *devpriv = dev->private; - int ret = 0; if (do_unlink) - ret = usbduxsub_unlink_inurbs(devpriv); + usbduxsub_unlink_inurbs(dev); devpriv->ai_cmd_running = 0; - - return ret; } static int usbdux_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { struct usbdux_private *devpriv = dev->private; - int ret = 0; /* prevent other CPUs from submitting new commands just now */ down(&devpriv->sem); /* unlink only if the urb really has been submitted */ - ret = usbdux_ai_stop(dev, devpriv->ai_cmd_running); + usbdux_ai_stop(dev, devpriv->ai_cmd_running); up(&devpriv->sem); - return ret; + return 0; } /* analogue IN - interrupt service routine */ @@ -422,46 +408,39 @@ static void usbduxsub_ai_isoc_irq(struct urb *urb) comedi_event(dev, s); } -static int usbduxsub_unlink_outurbs(struct usbdux_private *usbduxsub_tmp) -{ - int i = 0; - int err = 0; - - if (usbduxsub_tmp && usbduxsub_tmp->urb_out) { - for (i = 0; i < usbduxsub_tmp->num_out_buffers; i++) { - if (usbduxsub_tmp->urb_out[i]) - usb_kill_urb(usbduxsub_tmp->urb_out[i]); - } - } - return err; -} - -static int usbdux_ao_stop(struct comedi_device *dev, int do_unlink) +static void usbduxsub_unlink_outurbs(struct comedi_device *dev) +{ + struct usbdux_private *devpriv = dev->private; + int i; + + if (devpriv->urb_out) { + for (i = 0; i < devpriv->num_out_buffers; i++) + usb_kill_urb(devpriv->urb_out[i]); + } +} + +static void usbdux_ao_stop(struct comedi_device *dev, int do_unlink) { struct usbdux_private *devpriv = dev->private; - int ret = 0; if (do_unlink) - ret = usbduxsub_unlink_outurbs(devpriv); + usbduxsub_unlink_outurbs(dev); devpriv->ao_cmd_running = 0; - - return ret; } static int usbdux_ao_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { struct usbdux_private *devpriv = dev->private; - int ret = 0; /* prevent other CPUs from submitting a command just now */ down(&devpriv->sem); /* unlink only if it is really running */ - ret = usbdux_ao_stop(dev, devpriv->ao_cmd_running); + usbdux_ao_stop(dev, devpriv->ao_cmd_running); up(&devpriv->sem); - return ret; + return 0; } static void usbduxsub_ao_isoc_irq(struct urb *urb) @@ -1403,31 +1382,21 @@ static int usbdux_counter_config(struct comedi_device *dev, return 2; } -/***********************************/ -/* PWM */ - -static int usbduxsub_unlink_pwm_urbs(struct usbdux_private *usbduxsub_tmp) -{ - int err = 0; - - if (usbduxsub_tmp && usbduxsub_tmp->urb_pwm) { - if (usbduxsub_tmp->urb_pwm) - usb_kill_urb(usbduxsub_tmp->urb_pwm); - } - return err; -} - -static int usbdux_pwm_stop(struct comedi_device *dev, int do_unlink) +static void usbduxsub_unlink_pwm_urbs(struct comedi_device *dev) +{ + struct usbdux_private *devpriv = dev->private; + + usb_kill_urb(devpriv->urb_pwm); +} + +static void usbdux_pwm_stop(struct comedi_device *dev, int do_unlink) { struct usbdux_private *devpriv = dev->private; - int ret = 0; if (do_unlink) - ret = usbduxsub_unlink_pwm_urbs(devpriv); + usbduxsub_unlink_pwm_urbs(dev); devpriv->pwm_cmd_running = 0; - - return ret; } static int usbdux_pwm_cancel(struct comedi_device *dev, @@ -1437,15 +1406,9 @@ static int usbdux_pwm_cancel(struct comedi_device *dev, int ret; down(&devpriv->sem); - /* unlink only if it is really running */ - ret = usbdux_pwm_stop(dev, devpriv->pwm_cmd_running); - if (ret) - goto pwm_cancel_exit; - + usbdux_pwm_stop(dev, devpriv->pwm_cmd_running); ret = send_dux_commands(dev, SENDPWMOFF); - -pwm_cancel_exit: up(&devpriv->sem); return ret; @@ -1979,11 +1942,11 @@ static void usbdux_detach(struct comedi_device *dev) usb_set_intfdata(intf, NULL); if (devpriv->pwm_cmd_running) - usbduxsub_unlink_pwm_urbs(devpriv); + usbduxsub_unlink_pwm_urbs(dev); if (devpriv->ao_cmd_running) - usbduxsub_unlink_outurbs(devpriv); + usbduxsub_unlink_outurbs(dev); if (devpriv->ai_cmd_running) - usbduxsub_unlink_inurbs(devpriv); + usbduxsub_unlink_inurbs(dev); usbdux_free_usb_buffers(devpriv); From ecc2b22990bd59b2e8ea34afa0334598cbdfad71 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 25 Jul 2013 16:08:16 -0700 Subject: [PATCH 0843/3400] staging: comedi: usbdux: use the stop helpers in the detach Use the stop helpers instead of duplicating the code in the detach. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 7077d268f883..f60674344ea8 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -1941,12 +1941,10 @@ static void usbdux_detach(struct comedi_device *dev) usb_set_intfdata(intf, NULL); - if (devpriv->pwm_cmd_running) - usbduxsub_unlink_pwm_urbs(dev); - if (devpriv->ao_cmd_running) - usbduxsub_unlink_outurbs(dev); - if (devpriv->ai_cmd_running) - usbduxsub_unlink_inurbs(dev); + /* stop and unlink any submitted urbs */ + usbdux_pwm_stop(dev, devpriv->pwm_cmd_running); + usbdux_ao_stop(dev, devpriv->ao_cmd_running); + usbdux_ai_stop(dev, devpriv->ai_cmd_running); usbdux_free_usb_buffers(devpriv); From a3ef101f119b8510cb14a1f5a6bdb8639c8eb742 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 25 Jul 2013 16:08:35 -0700 Subject: [PATCH 0844/3400] staging: comedi: usbdux: remove the usb endpoint defines The endpoint defines are each only used in one place and don't help clarify the code. Remove the defines and just open code the values. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index f60674344ea8..644f6aba1941 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -113,21 +113,6 @@ sampling rate. If you sample two channels you get 4kHz and so on. /* max lenghth of the transfer-buffer for software upload */ #define TB_LEN 0x2000 -/* Input endpoint number: ISO/IRQ */ -#define ISOINEP 6 - -/* Output endpoint number: ISO/IRQ */ -#define ISOOUTEP 2 - -/* This EP sends DUX commands to USBDUX */ -#define COMMAND_OUT_EP 1 - -/* This EP receives the DUX commands from USBDUX */ -#define COMMAND_IN_EP 8 - -/* Output endpoint for PWM */ -#define PWM_EP 4 - /* 300Hz max frequ under PWM */ #define MIN_PWM_PERIOD ((long)(1E9/300)) @@ -804,7 +789,7 @@ static int send_dux_commands(struct comedi_device *dev, int cmd_type) devpriv->dux_commands[0] = cmd_type; - return usb_bulk_msg(usb, usb_sndbulkpipe(usb, COMMAND_OUT_EP), + return usb_bulk_msg(usb, usb_sndbulkpipe(usb, 1), devpriv->dux_commands, SIZEOFDUXBUFFER, &nsent, BULK_TIMEOUT); } @@ -818,7 +803,7 @@ static int receive_dux_commands(struct comedi_device *dev, int command) int i; for (i = 0; i < RETRIES; i++) { - ret = usb_bulk_msg(usb, usb_rcvbulkpipe(usb, COMMAND_IN_EP), + ret = usb_bulk_msg(usb, usb_rcvbulkpipe(usb, 8), devpriv->insn_buffer, SIZEINSNBUF, &nrec, BULK_TIMEOUT); if (ret < 0) @@ -1479,7 +1464,7 @@ static int usbduxsub_submit_pwm_urbs(struct comedi_device *dev) struct urb *urb = devpriv->urb_pwm; /* in case of a resubmission after an unlink... */ - usb_fill_bulk_urb(urb, usb, usb_sndbulkpipe(usb, PWM_EP), + usb_fill_bulk_urb(urb, usb, usb_sndbulkpipe(usb, 4), urb->transfer_buffer, devpriv->size_pwm_buf, usbduxsub_pwm_irq, @@ -1712,7 +1697,7 @@ static int usbdux_alloc_usb_buffers(struct comedi_device *dev) /* will be filled later with a pointer to the comedi-device */ /* and ONLY then the urb should be submitted */ urb->context = NULL; - urb->pipe = usb_rcvisocpipe(usb, ISOINEP); + urb->pipe = usb_rcvisocpipe(usb, 6); urb->transfer_flags = URB_ISO_ASAP; urb->transfer_buffer = kzalloc(SIZEINBUF, GFP_KERNEL); if (!urb->transfer_buffer) @@ -1742,7 +1727,7 @@ static int usbdux_alloc_usb_buffers(struct comedi_device *dev) /* will be filled later with a pointer to the comedi-device */ /* and ONLY then the urb should be submitted */ urb->context = NULL; - urb->pipe = usb_sndisocpipe(usb, ISOOUTEP); + urb->pipe = usb_sndisocpipe(usb, 2); urb->transfer_flags = URB_ISO_ASAP; urb->transfer_buffer = kzalloc(SIZEOUTBUF, GFP_KERNEL); if (!urb->transfer_buffer) From 887463bb7968455396a9c61cd3673160b3ebc58c Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 25 Jul 2013 16:08:52 -0700 Subject: [PATCH 0845/3400] staging: comedi: usbdux: remove some unused defines These defines are not used by the driver. Remove them. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 644f6aba1941..6991e85a6d80 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -103,16 +103,6 @@ sampling rate. If you sample two channels you get 4kHz and so on. /* internal addresses of the 8051 processor */ #define USBDUXSUB_CPUCS 0xE600 -/* - * the minor device number, major is 180 only for debugging purposes and to - * upload special firmware (programming the eeprom etc) which is not compatible - * with the comedi framwork - */ -#define USBDUXSUB_MINOR 32 - -/* max lenghth of the transfer-buffer for software upload */ -#define TB_LEN 0x2000 - /* 300Hz max frequ under PWM */ #define MIN_PWM_PERIOD ((long)(1E9/300)) From 1731a826cad3a71062b00c80abca4f887d57e501 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 25 Jul 2013 16:09:13 -0700 Subject: [PATCH 0846/3400] staging: comedi: usbdux: move usbdux_firmware_upload() For aesthetics, move this function closer to the (*auto_attach). Also, rename some of the defined constants that are used by the firmware upload. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 170 ++++++++++++------------ 1 file changed, 82 insertions(+), 88 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 6991e85a6d80..92d740a4c295 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -91,17 +91,16 @@ sampling rate. If you sample two channels you get 4kHz and so on. #include "comedi_fc.h" -/* timeout for the USB-transfer in ms*/ -#define BULK_TIMEOUT 1000 +/* constants for firmware upload and download */ +#define USBDUX_FIRMWARE "usbdux_firmware.bin" +#define USBDUX_FIRMWARE_MAX_LEN 0x2000 +#define USBDUX_FIRMWARE_CMD 0xa0 +#define VENDOR_DIR_IN 0xc0 +#define VENDOR_DIR_OUT 0x40 +#define USBDUX_CPU_CS 0xe600 -/* constants for "firmware" upload and download */ -#define FIRMWARE "usbdux_firmware.bin" -#define USBDUXSUB_FIRMWARE 0xA0 -#define VENDOR_DIR_IN 0xC0 -#define VENDOR_DIR_OUT 0x40 - -/* internal addresses of the 8051 processor */ -#define USBDUXSUB_CPUCS 0xE600 +/* timeout for the USB-transfer in ms */ +#define BULK_TIMEOUT 1000 /* 300Hz max frequ under PWM */ #define MIN_PWM_PERIOD ((long)(1E9/300)) @@ -539,80 +538,6 @@ static void usbduxsub_ao_isoc_irq(struct urb *urb) } } -#define FIRMWARE_MAX_LEN 0x2000 - -static int usbdux_firmware_upload(struct comedi_device *dev, - const u8 *data, size_t size, - unsigned long context) -{ - struct usb_device *usb = comedi_to_usb_dev(dev); - uint8_t *buf; - uint8_t *tmp; - int ret; - - if (!data) - return 0; - - if (size > FIRMWARE_MAX_LEN) { - dev_err(dev->class_dev, - "usbdux firmware binary it too large for FX2.\n"); - return -ENOMEM; - } - - /* we generate a local buffer for the firmware */ - buf = kmemdup(data, size, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - /* we need a malloc'ed buffer for usb_control_msg() */ - tmp = kmalloc(1, GFP_KERNEL); - if (!tmp) { - kfree(buf); - return -ENOMEM; - } - - /* stop the current firmware on the device */ - *tmp = 1; /* 7f92 to one */ - ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0), - USBDUXSUB_FIRMWARE, - VENDOR_DIR_OUT, - USBDUXSUB_CPUCS, 0x0000, - tmp, 1, - BULK_TIMEOUT); - if (ret < 0) { - dev_err(dev->class_dev, "can not stop firmware\n"); - goto done; - } - - /* upload the new firmware to the device */ - ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0), - USBDUXSUB_FIRMWARE, - VENDOR_DIR_OUT, - 0, 0x0000, - buf, size, - BULK_TIMEOUT); - if (ret < 0) { - dev_err(dev->class_dev, "firmware upload failed\n"); - goto done; - } - - /* start the new firmware on the device */ - *tmp = 0; /* 7f92 to zero */ - ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0), - USBDUXSUB_FIRMWARE, - VENDOR_DIR_OUT, - USBDUXSUB_CPUCS, 0x0000, - tmp, 1, - BULK_TIMEOUT); - if (ret < 0) - dev_err(dev->class_dev, "can not start firmware\n"); - -done: - kfree(tmp); - kfree(buf); - return ret; -} - static int usbduxsub_submit_inurbs(struct comedi_device *dev) { struct usb_device *usb = comedi_to_usb_dev(dev); @@ -1635,8 +1560,77 @@ static int usbdux_pwm_config(struct comedi_device *dev, return -EINVAL; } -/* end of PWM */ -/*****************************************************************/ +static int usbdux_firmware_upload(struct comedi_device *dev, + const u8 *data, size_t size, + unsigned long context) +{ + struct usb_device *usb = comedi_to_usb_dev(dev); + uint8_t *buf; + uint8_t *tmp; + int ret; + + if (!data) + return 0; + + if (size > USBDUX_FIRMWARE_MAX_LEN) { + dev_err(dev->class_dev, + "usbdux firmware binary it too large for FX2.\n"); + return -ENOMEM; + } + + /* we generate a local buffer for the firmware */ + buf = kmemdup(data, size, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + /* we need a malloc'ed buffer for usb_control_msg() */ + tmp = kmalloc(1, GFP_KERNEL); + if (!tmp) { + kfree(buf); + return -ENOMEM; + } + + /* stop the current firmware on the device */ + *tmp = 1; /* 7f92 to one */ + ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0), + USBDUX_FIRMWARE_CMD, + VENDOR_DIR_OUT, + USBDUX_CPU_CS, 0x0000, + tmp, 1, + BULK_TIMEOUT); + if (ret < 0) { + dev_err(dev->class_dev, "can not stop firmware\n"); + goto done; + } + + /* upload the new firmware to the device */ + ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0), + USBDUX_FIRMWARE_CMD, + VENDOR_DIR_OUT, + 0, 0x0000, + buf, size, + BULK_TIMEOUT); + if (ret < 0) { + dev_err(dev->class_dev, "firmware upload failed\n"); + goto done; + } + + /* start the new firmware on the device */ + *tmp = 0; /* 7f92 to zero */ + ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0), + USBDUX_FIRMWARE_CMD, + VENDOR_DIR_OUT, + USBDUX_CPU_CS, 0x0000, + tmp, 1, + BULK_TIMEOUT); + if (ret < 0) + dev_err(dev->class_dev, "can not start firmware\n"); + +done: + kfree(tmp); + kfree(buf); + return ret; +} static int usbdux_alloc_usb_buffers(struct comedi_device *dev) { @@ -1831,7 +1825,7 @@ static int usbdux_auto_attach(struct comedi_device *dev, return ret; } - ret = comedi_load_firmware(dev, &usb->dev, FIRMWARE, + ret = comedi_load_firmware(dev, &usb->dev, USBDUX_FIRMWARE, usbdux_firmware_upload, 0); if (ret < 0) return ret; @@ -1958,4 +1952,4 @@ module_comedi_usb_driver(usbdux_driver, usbdux_usb_driver); MODULE_AUTHOR("Bernd Porr, BerndPorr@f2s.com"); MODULE_DESCRIPTION("Stirling/ITL USB-DUX -- Bernd.Porr@f2s.com"); MODULE_LICENSE("GPL"); -MODULE_FIRMWARE(FIRMWARE); +MODULE_FIRMWARE(USBDUX_FIRMWARE); From 7acf26edbcba808cb6447af893f30c63751938f8 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 25 Jul 2013 16:09:30 -0700 Subject: [PATCH 0847/3400] staging: comedi: usbdux: clarify bipolar ai data in usbduxsub_ai_isoc_irq() Use the comedi_range_is_bipolar() helper instead of checking the 'range' index against a magic number. Also, use the s->maxdata to calculate the value needed to munge the value for bipolar data instead of the magic number. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 92d740a4c295..20b705e87d48 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -363,14 +363,15 @@ static void usbduxsub_ai_isoc_irq(struct urb *urb) /* get the data from the USB bus and hand it over to comedi */ n = s->async->cmd.chanlist_len; for (i = 0; i < n; i++) { + unsigned int range = CR_RANGE(s->async->cmd.chanlist[i]); + int16_t val = le16_to_cpu(devpriv->in_buffer[i]); + + /* bipolar data is two's-complement */ + if (comedi_range_is_bipolar(s, range)) + val ^= ((s->maxdata + 1) >> 1); + /* transfer data */ - if (CR_RANGE(s->async->cmd.chanlist[i]) <= 1) { - err = comedi_buf_put(s->async, - le16_to_cpu(devpriv->in_buffer[i]) ^ 0x800); - } else { - err = comedi_buf_put(s->async, - le16_to_cpu(devpriv->in_buffer[i])); - } + err = comedi_buf_put(s->async, val); if (unlikely(err == 0)) { /* buffer overflow */ usbdux_ai_stop(dev, 0); From c79bc875537d5d9ef396b3a4b7e2bf2b28bd9945 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 25 Jul 2013 16:09:48 -0700 Subject: [PATCH 0848/3400] staging: comedi: usbdux: rename private data variables The usbdux and usbduxsigma drivers are _very_ similar. For aesthetic reasons, rename the private data variables in this driver to match the names in the usbduxsigma driver so we can start sharing the common code. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 136 ++++++++++++------------ 1 file changed, 68 insertions(+), 68 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 20b705e87d48..bd46bec73d7b 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -177,24 +177,24 @@ static const struct comedi_lrange range_usbdux_ao_range = { struct usbdux_private { /* actual number of in-buffers */ - int num_in_buffers; + int n_ai_urbs; /* actual number of out-buffers */ - int num_out_buffers; + int n_ao_urbs; /* ISO-transfer handling: buffers */ - struct urb **urb_in; - struct urb **urb_out; + struct urb **ai_urbs; + struct urb **ao_urbs; /* pwm-transfer handling */ - struct urb *urb_pwm; + struct urb *pwm_urb; /* PWM period */ unsigned int pwm_period; /* PWM internal delay for the GPIF in the FX2 */ - int8_t pwn_delay; + int8_t pwm_delay; /* size of the PWM buffer which holds the bit pattern */ - int size_pwm_buf; + int pwm_buf_sz; /* input buffer for the ISO-transfer */ - int16_t *in_buffer; + int16_t *in_buf; /* input buffer for single insn */ - int16_t *insn_buffer; + int16_t *insn_buf; /* output buffer for single DA outputs */ int16_t *out_buffer; @@ -228,9 +228,9 @@ static void usbduxsub_unlink_inurbs(struct comedi_device *dev) struct usbdux_private *devpriv = dev->private; int i; - if (devpriv->urb_in) { - for (i = 0; i < devpriv->num_in_buffers; i++) - usb_kill_urb(devpriv->urb_in[i]); + if (devpriv->ai_urbs) { + for (i = 0; i < devpriv->n_ai_urbs; i++) + usb_kill_urb(devpriv->ai_urbs[i]); } } @@ -270,7 +270,7 @@ static void usbduxsub_ai_isoc_irq(struct urb *urb) switch (urb->status) { case 0: /* copy the result in the transfer buffer */ - memcpy(devpriv->in_buffer, urb->transfer_buffer, SIZEINBUF); + memcpy(devpriv->in_buf, urb->transfer_buffer, SIZEINBUF); break; case -EILSEQ: /* error in the ISOchronous data */ @@ -364,7 +364,7 @@ static void usbduxsub_ai_isoc_irq(struct urb *urb) n = s->async->cmd.chanlist_len; for (i = 0; i < n; i++) { unsigned int range = CR_RANGE(s->async->cmd.chanlist[i]); - int16_t val = le16_to_cpu(devpriv->in_buffer[i]); + int16_t val = le16_to_cpu(devpriv->in_buf[i]); /* bipolar data is two's-complement */ if (comedi_range_is_bipolar(s, range)) @@ -388,9 +388,9 @@ static void usbduxsub_unlink_outurbs(struct comedi_device *dev) struct usbdux_private *devpriv = dev->private; int i; - if (devpriv->urb_out) { - for (i = 0; i < devpriv->num_out_buffers; i++) - usb_kill_urb(devpriv->urb_out[i]); + if (devpriv->ao_urbs) { + for (i = 0; i < devpriv->n_ao_urbs; i++) + usb_kill_urb(devpriv->ao_urbs[i]); } } @@ -548,8 +548,8 @@ static int usbduxsub_submit_inurbs(struct comedi_device *dev) int i; /* Submit all URBs and start the transfer on the bus */ - for (i = 0; i < devpriv->num_in_buffers; i++) { - urb = devpriv->urb_in[i]; + for (i = 0; i < devpriv->n_ai_urbs; i++) { + urb = devpriv->ai_urbs[i]; /* in case of a resubmission after an unlink... */ urb->interval = devpriv->ai_interval; @@ -573,8 +573,8 @@ static int usbduxsub_submit_outurbs(struct comedi_device *dev) int ret; int i; - for (i = 0; i < devpriv->num_out_buffers; i++) { - urb = devpriv->urb_out[i]; + for (i = 0; i < devpriv->n_ao_urbs; i++) { + urb = devpriv->ao_urbs[i]; /* in case of a resubmission after an unlink... */ urb->context = dev; @@ -720,11 +720,11 @@ static int receive_dux_commands(struct comedi_device *dev, int command) for (i = 0; i < RETRIES; i++) { ret = usb_bulk_msg(usb, usb_rcvbulkpipe(usb, 8), - devpriv->insn_buffer, SIZEINSNBUF, + devpriv->insn_buf, SIZEINSNBUF, &nrec, BULK_TIMEOUT); if (ret < 0) return ret; - if (le16_to_cpu(devpriv->insn_buffer[0]) == command) + if (le16_to_cpu(devpriv->insn_buf[0]) == command) return ret; } /* command not received */ @@ -881,7 +881,7 @@ static int usbdux_ai_insn_read(struct comedi_device *dev, if (ret < 0) goto ai_read_exit; - val = le16_to_cpu(devpriv->insn_buffer[1]); + val = le16_to_cpu(devpriv->insn_buf[1]); /* bipolar data is two's-complement */ if (comedi_range_is_bipolar(s, range)) @@ -1210,7 +1210,7 @@ static int usbdux_dio_insn_bits(struct comedi_device *dev, if (ret < 0) goto dio_exit; - data[1] = le16_to_cpu(devpriv->insn_buffer[1]); + data[1] = le16_to_cpu(devpriv->insn_buf[1]); dio_exit: up(&devpriv->sem); @@ -1238,7 +1238,7 @@ static int usbdux_counter_read(struct comedi_device *dev, if (ret < 0) goto counter_read_exit; - data[i] = le16_to_cpu(devpriv->insn_buffer[chan + 1]); + data[i] = le16_to_cpu(devpriv->insn_buf[chan + 1]); } counter_read_exit: @@ -1287,7 +1287,7 @@ static void usbduxsub_unlink_pwm_urbs(struct comedi_device *dev) { struct usbdux_private *devpriv = dev->private; - usb_kill_urb(devpriv->urb_pwm); + usb_kill_urb(devpriv->pwm_urb); } static void usbdux_pwm_stop(struct comedi_device *dev, int do_unlink) @@ -1354,7 +1354,7 @@ static void usbduxsub_pwm_irq(struct urb *urb) if (!devpriv->pwm_cmd_running) return; - urb->transfer_buffer_length = devpriv->size_pwm_buf; + urb->transfer_buffer_length = devpriv->pwm_buf_sz; urb->dev = comedi_to_usb_dev(dev); urb->status = 0; if (devpriv->pwm_cmd_running) { @@ -1377,12 +1377,12 @@ static int usbduxsub_submit_pwm_urbs(struct comedi_device *dev) { struct usb_device *usb = comedi_to_usb_dev(dev); struct usbdux_private *devpriv = dev->private; - struct urb *urb = devpriv->urb_pwm; + struct urb *urb = devpriv->pwm_urb; /* in case of a resubmission after an unlink... */ usb_fill_bulk_urb(urb, usb, usb_sndbulkpipe(usb, 4), urb->transfer_buffer, - devpriv->size_pwm_buf, + devpriv->pwm_buf_sz, usbduxsub_pwm_irq, dev); @@ -1402,7 +1402,7 @@ static int usbdux_pwm_period(struct comedi_device *dev, if (fx2delay > 255) return -EAGAIN; } - this_usbduxsub->pwn_delay = fx2delay; + this_usbduxsub->pwm_delay = fx2delay; this_usbduxsub->pwm_period = period; return 0; @@ -1419,13 +1419,13 @@ static int usbdux_pwm_start(struct comedi_device *dev, if (devpriv->pwm_cmd_running) goto pwm_start_exit; - devpriv->dux_commands[1] = devpriv->pwn_delay; + devpriv->dux_commands[1] = devpriv->pwm_delay; ret = send_dux_commands(dev, SENDPWMON); if (ret < 0) goto pwm_start_exit; /* initialise the buffer */ - memset(devpriv->urb_pwm->transfer_buffer, 0, devpriv->size_pwm_buf); + memset(devpriv->pwm_urb->transfer_buffer, 0, devpriv->pwm_buf_sz); devpriv->pwm_cmd_running = 1; ret = usbduxsub_submit_pwm_urbs(dev); @@ -1459,8 +1459,8 @@ static int usbdux_pwm_pattern(struct comedi_device *dev, sgn_mask = (16 << channel); /* this is the buffer which will be filled with the with bit */ /* pattern for one period */ - szbuf = this_usbduxsub->size_pwm_buf; - p_buf = (char *)(this_usbduxsub->urb_pwm->transfer_buffer); + szbuf = this_usbduxsub->pwm_buf_sz; + p_buf = (char *)(this_usbduxsub->pwm_urb->transfer_buffer); for (i = 0; i < szbuf; i++) { c = *p_buf; /* reset bits */ @@ -1651,13 +1651,13 @@ static int usbdux_alloc_usb_buffers(struct comedi_device *dev) return -ENOMEM; /* create space for the in buffer and set it to zero */ - devpriv->in_buffer = kzalloc(SIZEINBUF, GFP_KERNEL); - if (!devpriv->in_buffer) + devpriv->in_buf = kzalloc(SIZEINBUF, GFP_KERNEL); + if (!devpriv->in_buf) return -ENOMEM; /* create space of the instruction buffer */ - devpriv->insn_buffer = kzalloc(SIZEINSNBUF, GFP_KERNEL); - if (!devpriv->insn_buffer) + devpriv->insn_buf = kzalloc(SIZEINSNBUF, GFP_KERNEL); + if (!devpriv->insn_buf) return -ENOMEM; /* create space for the outbuffer */ @@ -1666,17 +1666,17 @@ static int usbdux_alloc_usb_buffers(struct comedi_device *dev) return -ENOMEM; /* in urbs */ - devpriv->urb_in = kcalloc(devpriv->num_in_buffers, sizeof(*urb), - GFP_KERNEL); - if (!devpriv->urb_in) + devpriv->ai_urbs = kcalloc(devpriv->n_ai_urbs, sizeof(*urb), + GFP_KERNEL); + if (!devpriv->ai_urbs) return -ENOMEM; - for (i = 0; i < devpriv->num_in_buffers; i++) { + for (i = 0; i < devpriv->n_ai_urbs; i++) { /* one frame: 1ms */ urb = usb_alloc_urb(1, GFP_KERNEL); if (!urb) return -ENOMEM; - devpriv->urb_in[i] = urb; + devpriv->ai_urbs[i] = urb; urb->dev = usb; /* will be filled later with a pointer to the comedi-device */ @@ -1696,17 +1696,17 @@ static int usbdux_alloc_usb_buffers(struct comedi_device *dev) } /* out urbs */ - devpriv->urb_out = kcalloc(devpriv->num_out_buffers, sizeof(*urb), + devpriv->ao_urbs = kcalloc(devpriv->n_ao_urbs, sizeof(*urb), GFP_KERNEL); - if (!devpriv->urb_out) + if (!devpriv->ao_urbs) return -ENOMEM; - for (i = 0; i < devpriv->num_out_buffers; i++) { + for (i = 0; i < devpriv->n_ao_urbs; i++) { /* one frame: 1ms */ urb = usb_alloc_urb(1, GFP_KERNEL); if (!urb) return -ENOMEM; - devpriv->urb_out[i] = urb; + devpriv->ao_urbs[i] = urb; urb->dev = usb; /* will be filled later with a pointer to the comedi-device */ @@ -1730,14 +1730,14 @@ static int usbdux_alloc_usb_buffers(struct comedi_device *dev) } /* pwm */ - if (devpriv->size_pwm_buf) { + if (devpriv->pwm_buf_sz) { urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) return -ENOMEM; - devpriv->urb_pwm = urb; + devpriv->pwm_urb = urb; /* max bulk ep size in high speed */ - urb->transfer_buffer = kzalloc(devpriv->size_pwm_buf, + urb->transfer_buffer = kzalloc(devpriv->pwm_buf_sz, GFP_KERNEL); if (!urb->transfer_buffer) return -ENOMEM; @@ -1751,37 +1751,37 @@ static void usbdux_free_usb_buffers(struct usbdux_private *devpriv) struct urb *urb; int i; - urb = devpriv->urb_pwm; + urb = devpriv->pwm_urb; if (urb) { kfree(urb->transfer_buffer); usb_kill_urb(urb); usb_free_urb(urb); } - if (devpriv->urb_out) { - for (i = 0; i < devpriv->num_out_buffers; i++) { - urb = devpriv->urb_out[i]; + if (devpriv->ao_urbs) { + for (i = 0; i < devpriv->n_ao_urbs; i++) { + urb = devpriv->ao_urbs[i]; if (urb) { kfree(urb->transfer_buffer); usb_kill_urb(urb); usb_free_urb(urb); } } - kfree(devpriv->urb_out); + kfree(devpriv->ao_urbs); } - if (devpriv->urb_in) { - for (i = 0; i < devpriv->num_in_buffers; i++) { - urb = devpriv->urb_in[i]; + if (devpriv->ai_urbs) { + for (i = 0; i < devpriv->n_ai_urbs; i++) { + urb = devpriv->ai_urbs[i]; if (urb) { kfree(urb->transfer_buffer); usb_kill_urb(urb); usb_free_urb(urb); } } - kfree(devpriv->urb_in); + kfree(devpriv->ai_urbs); } kfree(devpriv->out_buffer); - kfree(devpriv->insn_buffer); - kfree(devpriv->in_buffer); + kfree(devpriv->insn_buf); + kfree(devpriv->in_buf); kfree(devpriv->dux_commands); kfree(devpriv->dac_commands); } @@ -1805,12 +1805,12 @@ static int usbdux_auto_attach(struct comedi_device *dev, devpriv->high_speed = (usb->speed == USB_SPEED_HIGH); if (devpriv->high_speed) { - devpriv->num_in_buffers = NUMOFINBUFFERSHIGH; - devpriv->num_out_buffers = NUMOFOUTBUFFERSHIGH; - devpriv->size_pwm_buf = 512; + devpriv->n_ai_urbs = NUMOFINBUFFERSHIGH; + devpriv->n_ao_urbs = NUMOFOUTBUFFERSHIGH; + devpriv->pwm_buf_sz = 512; } else { - devpriv->num_in_buffers = NUMOFINBUFFERSFULL; - devpriv->num_out_buffers = NUMOFOUTBUFFERSFULL; + devpriv->n_ai_urbs = NUMOFINBUFFERSFULL; + devpriv->n_ao_urbs = NUMOFOUTBUFFERSFULL; } ret = usbdux_alloc_usb_buffers(dev); @@ -1890,7 +1890,7 @@ static int usbdux_auto_attach(struct comedi_device *dev, s->type = COMEDI_SUBD_PWM; s->subdev_flags = SDF_WRITABLE | SDF_PWM_HBRIDGE; s->n_chan = 8; - s->maxdata = devpriv->size_pwm_buf; + s->maxdata = devpriv->pwm_buf_sz; s->insn_write = usbdux_pwm_write; s->insn_read = usbdux_pwm_read; s->insn_config = usbdux_pwm_config; From a998a3db530bff8094476e82e28c801b09f7aa9e Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 25 Jul 2013 16:10:07 -0700 Subject: [PATCH 0849/3400] staging: comedi: usbdux: cleanup the private data 'outBuffer' This buffer is used to cache the values that are written to the analog output channels. Currently it only caches the single writes to the channels using the (*insn_write) callback. The async command writes are not cached. The buffer is also being kzalloc'ed during the attach of the driver to a size much larger that required. Rename the CamelCase buffer and change it to an array in the private data of the correct size to cache the analog output channel values. Modify the analog output urb callback so it updates the cached values with those used for the asynchronous command to allow readback after the command completes. The sanity check of the index to dac_commands[] (i.e. the 'chan' being written) is not needed. The chanlist_len will always be less than the number of channels. Also, fix the dev_err() message so it uses the proper device pointer. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 49 +++++++++++-------------- 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index bd46bec73d7b..1399305d739f 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -99,6 +99,8 @@ sampling rate. If you sample two channels you get 4kHz and so on. #define VENDOR_DIR_OUT 0x40 #define USBDUX_CPU_CS 0xe600 +#define USBDUX_NUM_AO_CHAN 4 + /* timeout for the USB-transfer in ms */ #define BULK_TIMEOUT 1000 @@ -195,8 +197,8 @@ struct usbdux_private { int16_t *in_buf; /* input buffer for single insn */ int16_t *insn_buf; - /* output buffer for single DA outputs */ - int16_t *out_buffer; + + unsigned int ao_readback[USBDUX_NUM_AO_CHAN]; unsigned int high_speed:1; unsigned int ai_cmd_running:1; @@ -486,25 +488,24 @@ static void usbduxsub_ao_isoc_irq(struct urb *urb) ((uint8_t *) (urb->transfer_buffer))[0] = s->async->cmd.chanlist_len; for (i = 0; i < s->async->cmd.chanlist_len; i++) { - short temp; - if (i >= NUMOUTCHANNELS) - break; + unsigned int chan = devpriv->dac_commands[i]; + short val; + ret = comedi_buf_get(s->async, &val); + if (ret < 0) { + dev_err(dev->class_dev, "buffer underflow\n"); + s->async->events |= (COMEDI_CB_EOA | + COMEDI_CB_OVERFLOW); + } /* pointer to the DA */ datap = (&(((int8_t *) urb->transfer_buffer)[i * 3 + 1])); /* get the data from comedi */ - ret = comedi_buf_get(s->async, &temp); - datap[0] = temp; - datap[1] = temp >> 8; - datap[2] = devpriv->dac_commands[i]; - if (ret < 0) { - dev_err(&urb->dev->dev, - "comedi: buffer underflow\n"); - s->async->events |= COMEDI_CB_EOA; - s->async->events |= COMEDI_CB_OVERFLOW; - } - /* transmit data to comedi */ + datap[0] = val; + datap[1] = val >> 8; + datap[2] = chan; + devpriv->ao_readback[chan] = val; + s->async->events |= COMEDI_CB_BLOCK; comedi_event(dev, s); } @@ -907,7 +908,7 @@ static int usbdux_ao_insn_read(struct comedi_device *dev, down(&devpriv->sem); for (i = 0; i < insn->n; i++) - data[i] = devpriv->out_buffer[chan]; + data[i] = devpriv->ao_readback[chan]; up(&devpriv->sem); return insn->n; @@ -920,7 +921,7 @@ static int usbdux_ao_insn_write(struct comedi_device *dev, { struct usbdux_private *devpriv = dev->private; unsigned int chan = CR_CHAN(insn->chanspec); - unsigned int val = devpriv->out_buffer[chan]; + unsigned int val = devpriv->ao_readback[chan]; int16_t *p = (int16_t *)&devpriv->dux_commands[2]; int ret = -EBUSY; int i; @@ -945,7 +946,7 @@ static int usbdux_ao_insn_write(struct comedi_device *dev, if (ret < 0) goto ao_write_exit; } - devpriv->out_buffer[chan] = val; + devpriv->ao_readback[chan] = val; ao_write_exit: up(&devpriv->sem); @@ -1660,11 +1661,6 @@ static int usbdux_alloc_usb_buffers(struct comedi_device *dev) if (!devpriv->insn_buf) return -ENOMEM; - /* create space for the outbuffer */ - devpriv->out_buffer = kzalloc(SIZEOUTBUF, GFP_KERNEL); - if (!devpriv->out_buffer) - return -ENOMEM; - /* in urbs */ devpriv->ai_urbs = kcalloc(devpriv->n_ai_urbs, sizeof(*urb), GFP_KERNEL); @@ -1779,7 +1775,6 @@ static void usbdux_free_usb_buffers(struct usbdux_private *devpriv) } kfree(devpriv->ai_urbs); } - kfree(devpriv->out_buffer); kfree(devpriv->insn_buf); kfree(devpriv->in_buf); kfree(devpriv->dux_commands); @@ -1854,9 +1849,9 @@ static int usbdux_auto_attach(struct comedi_device *dev, dev->write_subdev = s; s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE; - s->n_chan = 4; + s->n_chan = USBDUX_NUM_AO_CHAN; s->maxdata = 0x0fff; - s->len_chanlist = 4; + s->len_chanlist = s->n_chan; s->range_table = &range_usbdux_ao_range; s->do_cmdtest = usbdux_ao_cmdtest; s->do_cmd = usbdux_ao_cmd; From c769f85e2740ebe7e4c726632fed52818640faba Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 25 Jul 2013 16:10:25 -0700 Subject: [PATCH 0850/3400] staging: comedi: usbdux: simplify initializing the ao urb transfer_buffer Remove the ugly casting of datap to the ao urb->transfer_buffer. The format of the data in the buffer is simply. [0] = # of channels to update (s->async->cmd.chanlist.len) [1] = lsb of value for 1st channel to update [2] = msb of value for 1st channel to update [3] = 1st channel to update (depvriv->dac_commands[0]) If more than 1 channel is to be updated they are simply added to the buffer: [4] = lsb of value for 2st channel to update [5] = msb of value for 2st channel to update [6] = 1st channel to update (depvriv->dac_commands[1]) etc. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 1399305d739f..cb94964cc9ba 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -425,8 +425,10 @@ static void usbduxsub_ao_isoc_irq(struct urb *urb) struct comedi_device *dev = urb->context; struct comedi_subdevice *s = dev->write_subdev; struct usbdux_private *devpriv = dev->private; - int i, ret; int8_t *datap; + int len; + int ret; + int i; switch (urb->status) { case 0: @@ -484,9 +486,11 @@ static void usbduxsub_ao_isoc_irq(struct urb *urb) return; } } + /* transmit data to the USB bus */ - ((uint8_t *) (urb->transfer_buffer))[0] = - s->async->cmd.chanlist_len; + datap = urb->transfer_buffer; + len = s->async->cmd.chanlist_len; + *datap++ = len; for (i = 0; i < s->async->cmd.chanlist_len; i++) { unsigned int chan = devpriv->dac_commands[i]; short val; @@ -498,12 +502,9 @@ static void usbduxsub_ao_isoc_irq(struct urb *urb) COMEDI_CB_OVERFLOW); } /* pointer to the DA */ - datap = - (&(((int8_t *) urb->transfer_buffer)[i * 3 + 1])); - /* get the data from comedi */ - datap[0] = val; - datap[1] = val >> 8; - datap[2] = chan; + *datap++ = val & 0xff; + *datap++ = (val >> 8) & 0xff; + *datap++ = chan; devpriv->ao_readback[chan] = val; s->async->events |= COMEDI_CB_BLOCK; From b979e485b4b9ed7aff8a987f3638b3be5983268c Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 25 Jul 2013 16:10:43 -0700 Subject: [PATCH 0851/3400] staging: comedi: usbdux: remove unnecessary check in usbdux_ai_cmd() This check is not necessary. The cmd->chanlist_len will always be less than or equal to the subdevice len_chanlist that was setup during the attach of the device. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index cb94964cc9ba..3fc61d134acb 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -110,9 +110,6 @@ sampling rate. If you sample two channels you get 4kHz and so on. /* Default PWM frequency */ #define PWM_DEFAULT_PERIOD ((long)(1E9/100)) -/* Number of channels */ -#define NUMCHANNELS 8 - /* Size of one A/D value */ #define SIZEADIN ((sizeof(int16_t))) @@ -784,9 +781,6 @@ static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) unsigned int chan = CR_CHAN(cmd->chanlist[i]); unsigned int range = CR_RANGE(cmd->chanlist[i]); - if (i >= NUMCHANNELS) - break; - devpriv->dux_commands[i + 2] = create_adc_command(chan, range); } From 66ce147c7d40b77704b44b6b2071d91f7c510b33 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 25 Jul 2013 16:11:10 -0700 Subject: [PATCH 0852/3400] staging: comedi: usbdux: remove unnecessary check in usbdux_ao_cmd() This check is not necessary. The cmd->chanlist_len will always be less than or equal to the subdevice len_chanlist that was setup during the attach of the device. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 3fc61d134acb..80cfa80ba650 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -1080,9 +1080,6 @@ static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) for (i = 0; i < cmd->chanlist_len; ++i) { unsigned int chan = CR_CHAN(cmd->chanlist[i]); - if (i >= NUMOUTCHANNELS) - break; - devpriv->dac_commands[i] = chan << 6; } From c5bbfe500be3c8f9f45d45b1ac644271761610a1 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 25 Jul 2013 16:11:28 -0700 Subject: [PATCH 0853/3400] staging: comedi: usbdux: 'dac_commands' does not need to be kzalloc()'d The 'dac_commands' buffer is used to pass the ao channel list from usbdux_ao_cmd() to the urb callback, usbduxsub_ao_isoc_irq(). This buffer does not need to be allocated. Change it into a simple array of the correct size. Rename the variable to 'ao_chanlist' to clarify what it actually is. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 80cfa80ba650..9529324fbace 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -195,6 +195,7 @@ struct usbdux_private { /* input buffer for single insn */ int16_t *insn_buf; + int8_t ao_chanlist[USBDUX_NUM_AO_CHAN]; unsigned int ao_readback[USBDUX_NUM_AO_CHAN]; unsigned int high_speed:1; @@ -215,8 +216,6 @@ struct usbdux_private { unsigned int ao_counter; /* interval in frames/uframes */ unsigned int ai_interval; - /* D/A commands */ - int8_t *dac_commands; /* commands */ int8_t *dux_commands; struct semaphore sem; @@ -489,7 +488,7 @@ static void usbduxsub_ao_isoc_irq(struct urb *urb) len = s->async->cmd.chanlist_len; *datap++ = len; for (i = 0; i < s->async->cmd.chanlist_len; i++) { - unsigned int chan = devpriv->dac_commands[i]; + unsigned int chan = devpriv->ao_chanlist[i]; short val; ret = comedi_buf_get(s->async, &val); @@ -1080,7 +1079,7 @@ static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) for (i = 0; i < cmd->chanlist_len; ++i) { unsigned int chan = CR_CHAN(cmd->chanlist[i]); - devpriv->dac_commands[i] = chan << 6; + devpriv->ao_chanlist[i] = chan << 6; } /* we count in steps of 1ms (125us) */ @@ -1633,11 +1632,6 @@ static int usbdux_alloc_usb_buffers(struct comedi_device *dev) struct urb *urb; int i; - /* create space for the commands of the DA converter */ - devpriv->dac_commands = kzalloc(NUMOUTCHANNELS, GFP_KERNEL); - if (!devpriv->dac_commands) - return -ENOMEM; - /* create space for the commands going to the usb device */ devpriv->dux_commands = kzalloc(SIZEOFDUXBUFFER, GFP_KERNEL); if (!devpriv->dux_commands) @@ -1770,7 +1764,6 @@ static void usbdux_free_usb_buffers(struct usbdux_private *devpriv) kfree(devpriv->insn_buf); kfree(devpriv->in_buf); kfree(devpriv->dux_commands); - kfree(devpriv->dac_commands); } static int usbdux_auto_attach(struct comedi_device *dev, From c2141c5b084781063d6f94680c46abcf2b5673c8 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 25 Jul 2013 16:11:46 -0700 Subject: [PATCH 0854/3400] staging: comedi: usbdux: remove unused define This define is not used, and it's actually incorrect. The usbdux device only has 4 analog output channels. Remove it. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 9529324fbace..0558613aa2c7 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -122,9 +122,6 @@ sampling rate. If you sample two channels you get 4kHz and so on. /* 16 bytes. */ #define SIZEINSNBUF 16 -/* Number of DA channels */ -#define NUMOUTCHANNELS 8 - /* size of one value for the D/A converter: channel and value */ #define SIZEDAOUT ((sizeof(int8_t)+sizeof(int16_t))) From 757fbc2a782276086088e4e6237fb66dac1f41a3 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 25 Jul 2013 16:12:05 -0700 Subject: [PATCH 0855/3400] staging: comedi: usbdux: move and rename the bulk transfer commands For aesthetic reasons, move the defines used for the bulk transfer commands out of the middle of the code and rename them so they are a bit more readable. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 45 ++++++++++++------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 0558613aa2c7..b94c655e374a 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -99,6 +99,17 @@ sampling rate. If you sample two channels you get 4kHz and so on. #define VENDOR_DIR_OUT 0x40 #define USBDUX_CPU_CS 0xe600 +/* usbdux bulk transfer commands */ +#define USBDUX_CMD_MULT_AI 0 +#define USBDUX_CMD_AO 1 +#define USBDUX_CMD_DIO_CFG 2 +#define USBDUX_CMD_DIO_BITS 3 +#define USBDUX_CMD_SINGLE_AI 4 +#define USBDUX_CMD_TIMER_RD 5 +#define USBDUX_CMD_TIMER_WR 6 +#define USBDUX_CMD_PWM_ON 7 +#define USBDUX_CMD_PWM_OFF 8 + #define USBDUX_NUM_AO_CHAN 4 /* timeout for the USB-transfer in ms */ @@ -680,18 +691,6 @@ static int8_t create_adc_command(unsigned int chan, int range) return (chan << 4) | ((p == 1) << 2) | ((r == 1) << 3); } -/* bulk transfers to usbdux */ - -#define SENDADCOMMANDS 0 -#define SENDDACOMMANDS 1 -#define SENDDIOCONFIGCOMMAND 2 -#define SENDDIOBITSCOMMAND 3 -#define SENDSINGLEAD 4 -#define READCOUNTERCOMMAND 5 -#define WRITECOUNTERCOMMAND 6 -#define SENDPWMON 7 -#define SENDPWMOFF 8 - static int send_dux_commands(struct comedi_device *dev, int cmd_type) { struct usb_device *usb = comedi_to_usb_dev(dev); @@ -780,7 +779,7 @@ static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->dux_commands[i + 2] = create_adc_command(chan, range); } - ret = send_dux_commands(dev, SENDADCOMMANDS); + ret = send_dux_commands(dev, USBDUX_CMD_MULT_AI); if (ret < 0) goto ai_cmd_exit; @@ -864,12 +863,12 @@ static int usbdux_ai_insn_read(struct comedi_device *dev, devpriv->dux_commands[1] = create_adc_command(chan, range); /* adc commands */ - ret = send_dux_commands(dev, SENDSINGLEAD); + ret = send_dux_commands(dev, USBDUX_CMD_SINGLE_AI); if (ret < 0) goto ai_read_exit; for (i = 0; i < insn->n; i++) { - ret = receive_dux_commands(dev, SENDSINGLEAD); + ret = receive_dux_commands(dev, USBDUX_CMD_SINGLE_AI); if (ret < 0) goto ai_read_exit; @@ -933,7 +932,7 @@ static int usbdux_ao_insn_write(struct comedi_device *dev, /* one 16 bit value */ *p = cpu_to_le16(val); - ret = send_dux_commands(dev, SENDDACOMMANDS); + ret = send_dux_commands(dev, USBDUX_CMD_AO); if (ret < 0) goto ao_write_exit; } @@ -1192,10 +1191,10 @@ static int usbdux_dio_insn_bits(struct comedi_device *dev, * This command also tells the firmware to return * the digital input lines. */ - ret = send_dux_commands(dev, SENDDIOBITSCOMMAND); + ret = send_dux_commands(dev, USBDUX_CMD_DIO_BITS); if (ret < 0) goto dio_exit; - ret = receive_dux_commands(dev, SENDDIOBITSCOMMAND); + ret = receive_dux_commands(dev, USBDUX_CMD_DIO_BITS); if (ret < 0) goto dio_exit; @@ -1220,10 +1219,10 @@ static int usbdux_counter_read(struct comedi_device *dev, down(&devpriv->sem); for (i = 0; i < insn->n; i++) { - ret = send_dux_commands(dev, READCOUNTERCOMMAND); + ret = send_dux_commands(dev, USBDUX_CMD_TIMER_RD); if (ret < 0) goto counter_read_exit; - ret = receive_dux_commands(dev, READCOUNTERCOMMAND); + ret = receive_dux_commands(dev, USBDUX_CMD_TIMER_RD); if (ret < 0) goto counter_read_exit; @@ -1254,7 +1253,7 @@ static int usbdux_counter_write(struct comedi_device *dev, for (i = 0; i < insn->n; i++) { *p = cpu_to_le16(data[i]); - ret = send_dux_commands(dev, WRITECOUNTERCOMMAND); + ret = send_dux_commands(dev, USBDUX_CMD_TIMER_WR); if (ret < 0) break; } @@ -1298,7 +1297,7 @@ static int usbdux_pwm_cancel(struct comedi_device *dev, down(&devpriv->sem); /* unlink only if it is really running */ usbdux_pwm_stop(dev, devpriv->pwm_cmd_running); - ret = send_dux_commands(dev, SENDPWMOFF); + ret = send_dux_commands(dev, USBDUX_CMD_PWM_OFF); up(&devpriv->sem); return ret; @@ -1409,7 +1408,7 @@ static int usbdux_pwm_start(struct comedi_device *dev, goto pwm_start_exit; devpriv->dux_commands[1] = devpriv->pwm_delay; - ret = send_dux_commands(dev, SENDPWMON); + ret = send_dux_commands(dev, USBDUX_CMD_PWM_ON); if (ret < 0) goto pwm_start_exit; From 0c4349c91625188930f12382b061399827bf4da6 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Thu, 25 Jul 2013 16:12:30 -0700 Subject: [PATCH 0856/3400] staging: comedi: usbdux: consolidate usbduxsub_unlink_{in, out}urbs() These functions are identical other than the which and how many urbs are unlinked. Consolidate the functions into one usbdux_unlink_urbs() function. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 28 +++++++------------------ 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index b94c655e374a..7ff731fd804a 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -229,23 +229,20 @@ struct usbdux_private { struct semaphore sem; }; -static void usbduxsub_unlink_inurbs(struct comedi_device *dev) +static void usbdux_unlink_urbs(struct urb **urbs, int num_urbs) { - struct usbdux_private *devpriv = dev->private; int i; - if (devpriv->ai_urbs) { - for (i = 0; i < devpriv->n_ai_urbs; i++) - usb_kill_urb(devpriv->ai_urbs[i]); - } + for (i = 0; i < num_urbs; i++) + usb_kill_urb(urbs[i]); } static void usbdux_ai_stop(struct comedi_device *dev, int do_unlink) { struct usbdux_private *devpriv = dev->private; - if (do_unlink) - usbduxsub_unlink_inurbs(dev); + if (do_unlink && devpriv->ai_urbs) + usbdux_unlink_urbs(devpriv->ai_urbs, devpriv->n_ai_urbs); devpriv->ai_cmd_running = 0; } @@ -389,23 +386,12 @@ static void usbduxsub_ai_isoc_irq(struct urb *urb) comedi_event(dev, s); } -static void usbduxsub_unlink_outurbs(struct comedi_device *dev) -{ - struct usbdux_private *devpriv = dev->private; - int i; - - if (devpriv->ao_urbs) { - for (i = 0; i < devpriv->n_ao_urbs; i++) - usb_kill_urb(devpriv->ao_urbs[i]); - } -} - static void usbdux_ao_stop(struct comedi_device *dev, int do_unlink) { struct usbdux_private *devpriv = dev->private; - if (do_unlink) - usbduxsub_unlink_outurbs(dev); + if (do_unlink && devpriv->ao_urbs) + usbdux_unlink_urbs(devpriv->ao_urbs, devpriv->n_ao_urbs); devpriv->ao_cmd_running = 0; } From ca01583539b62729609e0ec8c21c813b75617a21 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 26 Jul 2013 15:37:54 -0700 Subject: [PATCH 0857/3400] staging: asus_oled: delete driver No one has the hardware for it anymore, and there has not been any development on it in a long time. If someone shows up with the hardware, and wants to clean it up, this can be easily reverted. Reported-by: Lidza Louina Cc: Jakub Schmidtke Signed-off-by: Greg Kroah-Hartman --- drivers/staging/Kconfig | 2 - drivers/staging/Makefile | 1 - drivers/staging/asus_oled/Kconfig | 6 - drivers/staging/asus_oled/Makefile | 1 - drivers/staging/asus_oled/README | 156 ----- drivers/staging/asus_oled/TODO | 10 - drivers/staging/asus_oled/asus_oled.c | 847 ------------------------- drivers/staging/asus_oled/linux.txt | 33 - drivers/staging/asus_oled/linux_f.txt | 18 - drivers/staging/asus_oled/linux_fr.txt | 33 - drivers/staging/asus_oled/tux.txt | 33 - drivers/staging/asus_oled/tux_r.txt | 33 - drivers/staging/asus_oled/tux_r2.txt | 33 - drivers/staging/asus_oled/zig.txt | 33 - 14 files changed, 1239 deletions(-) delete mode 100644 drivers/staging/asus_oled/Kconfig delete mode 100644 drivers/staging/asus_oled/Makefile delete mode 100644 drivers/staging/asus_oled/README delete mode 100644 drivers/staging/asus_oled/TODO delete mode 100644 drivers/staging/asus_oled/asus_oled.c delete mode 100644 drivers/staging/asus_oled/linux.txt delete mode 100644 drivers/staging/asus_oled/linux_f.txt delete mode 100644 drivers/staging/asus_oled/linux_fr.txt delete mode 100644 drivers/staging/asus_oled/tux.txt delete mode 100644 drivers/staging/asus_oled/tux_r.txt delete mode 100644 drivers/staging/asus_oled/tux_r2.txt delete mode 100644 drivers/staging/asus_oled/zig.txt diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index d036cd29bcd6..869c488cfb72 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -40,8 +40,6 @@ source "drivers/staging/comedi/Kconfig" source "drivers/staging/olpc_dcon/Kconfig" -source "drivers/staging/asus_oled/Kconfig" - source "drivers/staging/panel/Kconfig" source "drivers/staging/rtl8187se/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 7fe578ea1708..ca14ab70b755 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -12,7 +12,6 @@ obj-$(CONFIG_PRISM2_USB) += wlan-ng/ obj-$(CONFIG_ECHO) += echo/ obj-$(CONFIG_COMEDI) += comedi/ obj-$(CONFIG_FB_OLPC_DCON) += olpc_dcon/ -obj-$(CONFIG_ASUS_OLED) += asus_oled/ obj-$(CONFIG_PANEL) += panel/ obj-$(CONFIG_R8187SE) += rtl8187se/ obj-$(CONFIG_RTL8192U) += rtl8192u/ diff --git a/drivers/staging/asus_oled/Kconfig b/drivers/staging/asus_oled/Kconfig deleted file mode 100644 index e56dbb25ac5d..000000000000 --- a/drivers/staging/asus_oled/Kconfig +++ /dev/null @@ -1,6 +0,0 @@ -config ASUS_OLED - tristate "Asus OLED driver" - depends on USB - default N - ---help--- - Enable support for the OLED display present in some Asus laptops. diff --git a/drivers/staging/asus_oled/Makefile b/drivers/staging/asus_oled/Makefile deleted file mode 100644 index e71f9aa9e037..000000000000 --- a/drivers/staging/asus_oled/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-$(CONFIG_ASUS_OLED) += asus_oled.o diff --git a/drivers/staging/asus_oled/README b/drivers/staging/asus_oled/README deleted file mode 100644 index 2d721232467a..000000000000 --- a/drivers/staging/asus_oled/README +++ /dev/null @@ -1,156 +0,0 @@ - - Driver for Asus OLED display present in some Asus laptops. - - The code of this driver is based on 'asusoled' program taken from - . I just wanted to have a simple - kernel driver for controlling this device, but I didn't know how - to do that. Now I know ;) Also, that program can not be used - with usbhid loaded, which means no USB mouse/keyboard while - controlling OLED display :( - - It has been tested on Asus G1 and didn't cause any problems, - but I don't guarantee that it won't do anything wrong :) - - It can (and probably does) have errors. It is usable - in my case, and I hope others will find it useful too! - -******* - -Building the module - - To build the module you need kernel 2.6 include files and some C compiler. - - Just run: - make - make install (as a root) - - It will build (hopefully) the module and install it in - /lib/modules/'uname -r'/extra/asus_oled.ko. - - To load it just use: - modprobe asus_oled - - You can check if it has detected your OLED display by looking into dmesg output. - There should be something like this: - asus-oled 2-7:1.0: Attached Asus OLED device - - If it doesn't find your display, you can try removing usbhid module. - If you add asus_oled into the list of modules loaded during system boot - before usbhid, it will work even when usbhid is present. - - If it still doesn't detect your hardware, check lsusb output. - There should be similar line: - Bus 002 Device 005: ID 0b05:1726 ASUSTek Computer, Inc. - - If you don't see any lines with '0b05:1726' it means that you have different - type of hardware that is not detected (it may or may not work, but the driver - knows only '0b05:1726' device). - -******* - -Configuration - - There is only one option: start_off. - You can use it by: 'modprobe asus_oled start_off=1', or by adding this - line to /etc/modprobe.d/asus_oled.conf: - options asus_oled start_off=1 - - With this option provided, asus_oled driver will switch off the display - when it is detected and attached. It is nice feature to just switch off the 'ASUS' - logo. If you don't use the display, it is probably the good idea to switch it off, - to protect OLEDs from "wearing off". - -******* - -Usage - - This module can be controlled with two special files: - /sys/class/asus_oled/oled_N/enabled - /sys/class/asus_oled/oled_N/picture - - (N is the device number, the first, and probably the only, has number 1, - so it is /sys/class/asus_oled/oled_1/enabled - and /sys/class/asus_oled/oled_1/picture) - - 'enabled' files is for reading and writing, 'picture' is writeable only. - - You can write 0 or 1 to 'enabled' file, which will switch - on and off the display. Reading from this file will tell you the last - status set, either 0 or 1. By default it is 1, so if the device was set to 'off', - and the computer was rebooted without power-off, this file will contain wrong - value - because the device is off, but hasn't been disabled this time and is - assumed to be on... - - To 'picture' file you write pictures to be displayed by the OLED device. - The format of the file: - - 00001110010111000 - 00010101010101010 - .... - - First line is a configuration parameter. Meaning of fields in : - M - picture mode. It can be either 's' for static pictures, - 'r' for rolling pictures, and 'f' for flashing pictures. - W - width of the picture. May be between 1 and 1792 - H - height of the picture. May be between 1 and 32 - - For example means static picture, 128 pixels long and 32 pixels high. - - The physical size of the display is 128x32 pixels. Static and flashing pictures - can't be larger than that (actually they can, but only part of them will be displayed ;) ) - - If the picture is smaller than 128x32 it will be centered. Rolling pictures wider than - 128 pixels will be centered too, unless their width = n*128. Vertically they will be - centered just like static pictures, if their height is smaller than 32. - - Flashing pictures will be centered horizontally if their width < 128, but they were - centered vertically in a different way. If their height < 16, they will be centered - in the upper half of the display (rows 0-15). This is because only the first half - of flashing pictures is used for flashing. When the picture with heigh = 32 is - displayed in flashing mode, its upper 16 rows will be flashing in the upper half - of the display, and the lower half will be empty. After few seconds upper part will - stop flashing (but that part of the picture will remain there), and the lower - half of the display will start displayin the lower half of the picture - in rolling mode, unless it is empty, or the picture was small enough to fit in - upper part. It is not mine idea, this is just the way Asus' display work ;) - So if you need just flashing, use at most 128x16 picture. If you need flashing and - rolling, use whole size of the display. - - Lines following the first, configuration, line are picture data. Each '1' means - that the pixel is lit, and '0' means that it is not. You can also use '#' as ON, - and ' ' (space) as OFF. Empty lines and all other characters are ignored. - - It is possible to write everything in one line 01010101010101010..., - and W*H characters will be used. If there is not enough characters, nothing will be - displayed. However, the 'line mode' is easier to read (and write), and it also - lets to omit parts of data. Whenever End-Of-Line character is found, but - the line is not W characters long, it is assumed that all missing characters - are equal to the last character in the line. - - Following line represents '0', '1' and a lots of '0's, dependng on the width of the picture - provided in configuration data: - 010 - - So if you need empty line, it is sufficient to write line with only one '0' in it. - The same works with '1' (or ' ' and '#'). - - If there are too many data in the file, they will be ignored. If you are not sure - how many characters you are missing, you can add few lines with one zero in each of them. - - There are some example pictures in .txt format, that can be used as follows: - cat foo.txt > /sys/class/asus_oled/oled_1/picture - - If the display is switched off you also need to run: - echo 1 > /sys/class/asus_oled/oled_1/enabled - To switch it off, just use: - echo 0 > /sys/class/asus_oled/oled_1/enabled - - -******* - - For any additional info please have a look at http://lapsus.berlios.de/asus_oled.html - - - - Jakub Schmidtke (sjakub@gmail.com) - diff --git a/drivers/staging/asus_oled/TODO b/drivers/staging/asus_oled/TODO deleted file mode 100644 index 2514131670a3..000000000000 --- a/drivers/staging/asus_oled/TODO +++ /dev/null @@ -1,10 +0,0 @@ -TODO: - - checkpatch.pl cleanups - - sparse fixes - - audit the userspace interface - - sysfs vs. char? - - Documentation/ABI/ needs to be added - - put the sample .txt files and README file somewhere. - -Please send patches to Greg Kroah-Hartman and -Cc: Jakub Schmidtke diff --git a/drivers/staging/asus_oled/asus_oled.c b/drivers/staging/asus_oled/asus_oled.c deleted file mode 100644 index 3654dc32a0c6..000000000000 --- a/drivers/staging/asus_oled/asus_oled.c +++ /dev/null @@ -1,847 +0,0 @@ -/* - * Asus OLED USB driver - * - * Copyright (C) 2007,2008 Jakub Schmidtke (sjakub@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. - * - * - * - * This module is based on usbled and asus-laptop modules. - * - * - * Asus OLED support is based on asusoled program taken from - * . - * - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define ASUS_OLED_VERSION "0.04-dev" -#define ASUS_OLED_NAME "asus-oled" -#define ASUS_OLED_UNDERSCORE_NAME "asus_oled" - -#define ASUS_OLED_STATIC 's' -#define ASUS_OLED_ROLL 'r' -#define ASUS_OLED_FLASH 'f' - -#define ASUS_OLED_MAX_WIDTH 1792 -#define ASUS_OLED_DISP_HEIGHT 32 -#define ASUS_OLED_PACKET_BUF_SIZE 256 - -#define USB_VENDOR_ID_ASUS 0x0b05 -#define USB_DEVICE_ID_ASUS_LCM 0x1726 -#define USB_DEVICE_ID_ASUS_LCM2 0x175b - -MODULE_AUTHOR("Jakub Schmidtke, sjakub@gmail.com"); -MODULE_DESCRIPTION("Asus OLED Driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(ASUS_OLED_VERSION); - -static struct class *oled_class; -static int oled_num; - -static uint start_off; - -module_param(start_off, uint, 0644); - -MODULE_PARM_DESC(start_off, - "Set to 1 to switch off OLED display after it is attached"); - -enum oled_pack_mode { - PACK_MODE_G1, - PACK_MODE_G50, - PACK_MODE_LAST -}; - -struct oled_dev_desc_str { - uint16_t idVendor; - uint16_t idProduct; - /* width of display */ - uint16_t devWidth; - /* formula to be used while packing the picture */ - enum oled_pack_mode packMode; - const char *devDesc; -}; - -/* table of devices that work with this driver */ -static const struct usb_device_id id_table[] = { - /* Asus G1/G2 (and variants)*/ - { USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM) }, - /* Asus G50V (and possibly others - G70? G71?)*/ - { USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM2) }, - { }, -}; - -/* parameters of specific devices */ -static struct oled_dev_desc_str oled_dev_desc_table[] = { - { USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM, 128, PACK_MODE_G1, - "G1/G2" }, - { USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM2, 256, PACK_MODE_G50, - "G50" }, - { }, -}; - -MODULE_DEVICE_TABLE(usb, id_table); - -struct asus_oled_header { - uint8_t magic1; - uint8_t magic2; - uint8_t flags; - uint8_t value3; - uint8_t buffer1; - uint8_t buffer2; - uint8_t value6; - uint8_t value7; - uint8_t value8; - uint8_t padding2[7]; -} __attribute((packed)); - -struct asus_oled_packet { - struct asus_oled_header header; - uint8_t bitmap[ASUS_OLED_PACKET_BUF_SIZE]; -} __attribute((packed)); - -struct asus_oled_dev { - struct usb_device *udev; - uint8_t pic_mode; - uint16_t dev_width; - enum oled_pack_mode pack_mode; - size_t height; - size_t width; - size_t x_shift; - size_t y_shift; - size_t buf_offs; - uint8_t last_val; - size_t buf_size; - char *buf; - uint8_t enabled; - uint8_t enabled_post_resume; - struct device *dev; -}; - -static void setup_packet_header(struct asus_oled_packet *packet, char flags, - char value3, char buffer1, char buffer2, char value6, - char value7, char value8) -{ - memset(packet, 0, sizeof(struct asus_oled_header)); - packet->header.magic1 = 0x55; - packet->header.magic2 = 0xaa; - packet->header.flags = flags; - packet->header.value3 = value3; - packet->header.buffer1 = buffer1; - packet->header.buffer2 = buffer2; - packet->header.value6 = value6; - packet->header.value7 = value7; - packet->header.value8 = value8; -} - -static void enable_oled(struct asus_oled_dev *odev, uint8_t enabl) -{ - int retval; - int act_len; - struct asus_oled_packet *packet; - - packet = kzalloc(sizeof(struct asus_oled_packet), GFP_KERNEL); - if (!packet) - return; - - setup_packet_header(packet, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00); - - if (enabl) - packet->bitmap[0] = 0xaf; - else - packet->bitmap[0] = 0xae; - - retval = usb_bulk_msg(odev->udev, - usb_sndbulkpipe(odev->udev, 2), - packet, - sizeof(struct asus_oled_header) + 1, - &act_len, - -1); - - if (retval) - dev_dbg(&odev->udev->dev, "retval = %d\n", retval); - - odev->enabled = enabl; - - kfree(packet); -} - -static ssize_t set_enabled(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct usb_interface *intf = to_usb_interface(dev); - struct asus_oled_dev *odev = usb_get_intfdata(intf); - unsigned long value; - if (kstrtoul(buf, 10, &value)) - return -EINVAL; - - enable_oled(odev, value); - - return count; -} - -static ssize_t class_set_enabled(struct device *device, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct asus_oled_dev *odev = - (struct asus_oled_dev *) dev_get_drvdata(device); - unsigned long value; - - if (kstrtoul(buf, 10, &value)) - return -EINVAL; - - enable_oled(odev, value); - - return count; -} - -static ssize_t get_enabled(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct usb_interface *intf = to_usb_interface(dev); - struct asus_oled_dev *odev = usb_get_intfdata(intf); - - return sprintf(buf, "%d\n", odev->enabled); -} - -static ssize_t class_get_enabled(struct device *device, - struct device_attribute *attr, char *buf) -{ - struct asus_oled_dev *odev = - (struct asus_oled_dev *) dev_get_drvdata(device); - - return sprintf(buf, "%d\n", odev->enabled); -} - -static void send_packets(struct usb_device *udev, - struct asus_oled_packet *packet, - char *buf, uint8_t p_type, size_t p_num) -{ - size_t i; - int act_len; - - for (i = 0; i < p_num; i++) { - int retval; - - switch (p_type) { - case ASUS_OLED_ROLL: - setup_packet_header(packet, 0x40, 0x80, p_num, - i + 1, 0x00, 0x01, 0xff); - break; - case ASUS_OLED_STATIC: - setup_packet_header(packet, 0x10 + i, 0x80, 0x01, - 0x01, 0x00, 0x01, 0x00); - break; - case ASUS_OLED_FLASH: - setup_packet_header(packet, 0x10 + i, 0x80, 0x01, - 0x01, 0x00, 0x00, 0xff); - break; - } - - memcpy(packet->bitmap, buf + (ASUS_OLED_PACKET_BUF_SIZE*i), - ASUS_OLED_PACKET_BUF_SIZE); - - retval = usb_bulk_msg(udev, usb_sndctrlpipe(udev, 2), - packet, sizeof(struct asus_oled_packet), - &act_len, -1); - - if (retval) - dev_dbg(&udev->dev, "retval = %d\n", retval); - } -} - -static void send_packet(struct usb_device *udev, - struct asus_oled_packet *packet, - size_t offset, size_t len, char *buf, uint8_t b1, - uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5, - uint8_t b6) { - int retval; - int act_len; - - setup_packet_header(packet, b1, b2, b3, b4, b5, b6, 0x00); - memcpy(packet->bitmap, buf + offset, len); - - retval = usb_bulk_msg(udev, - usb_sndctrlpipe(udev, 2), - packet, - sizeof(struct asus_oled_packet), - &act_len, - -1); - - if (retval) - dev_dbg(&udev->dev, "retval = %d\n", retval); -} - - -static void send_packets_g50(struct usb_device *udev, - struct asus_oled_packet *packet, char *buf) -{ - send_packet(udev, packet, 0, 0x100, buf, - 0x10, 0x00, 0x02, 0x01, 0x00, 0x01); - send_packet(udev, packet, 0x100, 0x080, buf, - 0x10, 0x00, 0x02, 0x02, 0x80, 0x00); - - send_packet(udev, packet, 0x180, 0x100, buf, - 0x11, 0x00, 0x03, 0x01, 0x00, 0x01); - send_packet(udev, packet, 0x280, 0x100, buf, - 0x11, 0x00, 0x03, 0x02, 0x00, 0x01); - send_packet(udev, packet, 0x380, 0x080, buf, - 0x11, 0x00, 0x03, 0x03, 0x80, 0x00); -} - - -static void send_data(struct asus_oled_dev *odev) -{ - size_t packet_num = odev->buf_size / ASUS_OLED_PACKET_BUF_SIZE; - struct asus_oled_packet *packet; - - packet = kzalloc(sizeof(struct asus_oled_packet), GFP_KERNEL); - if (!packet) - return; - - if (odev->pack_mode == PACK_MODE_G1) { - /* - * When sending roll-mode data the display updated only - * first packet. I have no idea why, but when static picture - * is sent just before rolling picture everything works fine. - */ - if (odev->pic_mode == ASUS_OLED_ROLL) - send_packets(odev->udev, packet, odev->buf, - ASUS_OLED_STATIC, 2); - - /* Only ROLL mode can use more than 2 packets.*/ - if (odev->pic_mode != ASUS_OLED_ROLL && packet_num > 2) - packet_num = 2; - - send_packets(odev->udev, packet, odev->buf, - odev->pic_mode, packet_num); - } else if (odev->pack_mode == PACK_MODE_G50) { - send_packets_g50(odev->udev, packet, odev->buf); - } - - kfree(packet); -} - -static int append_values(struct asus_oled_dev *odev, uint8_t val, size_t count) -{ - odev->last_val = val; - - if (val == 0) { - odev->buf_offs += count; - return 0; - } - - while (count-- > 0) { - size_t x = odev->buf_offs % odev->width; - size_t y = odev->buf_offs / odev->width; - size_t i; - - x += odev->x_shift; - y += odev->y_shift; - - switch (odev->pack_mode) { - case PACK_MODE_G1: - /* - * i = (x/128)*640 + 127 - x + (y/8)*128; - * This one for 128 is the same, but might be better - * for different widths? - */ - i = (x/odev->dev_width)*640 + - odev->dev_width - 1 - x + - (y/8)*odev->dev_width; - break; - - case PACK_MODE_G50: - i = (odev->dev_width - 1 - x)/8 + y*odev->dev_width/8; - break; - - default: - i = 0; - dev_err(odev->dev, "Unknown OLED Pack Mode: %d!\n", - odev->pack_mode); - break; - } - - if (i >= odev->buf_size) { - dev_err(odev->dev, "Buffer overflow! Report a bug: offs: %zu >= %zu i: %zu (x: %zu y: %zu)\n", - odev->buf_offs, odev->buf_size, i, x, y); - return -EIO; - } - - switch (odev->pack_mode) { - case PACK_MODE_G1: - odev->buf[i] &= ~(1<<(y%8)); - break; - - case PACK_MODE_G50: - odev->buf[i] &= ~(1<<(x%8)); - break; - - default: - /* cannot get here; stops gcc complaining*/ - break; - } - - odev->buf_offs++; - } - - return 0; -} - -static ssize_t odev_set_picture(struct asus_oled_dev *odev, - const char *buf, size_t count) -{ - size_t offs = 0, max_offs; - - if (count < 1) - return 0; - - if (tolower(buf[0]) == 'b') { - /* binary mode, set the entire memory*/ - - size_t i; - - odev->buf_size = (odev->dev_width * ASUS_OLED_DISP_HEIGHT) / 8; - - kfree(odev->buf); - odev->buf = kmalloc(odev->buf_size, GFP_KERNEL); - if (odev->buf == NULL) { - odev->buf_size = 0; - dev_err(odev->dev, "Out of memory!\n"); - return -ENOMEM; - } - - memset(odev->buf, 0xff, odev->buf_size); - - for (i = 1; i < count && i <= 32 * 32; i++) { - odev->buf[i-1] = buf[i]; - odev->buf_offs = i-1; - } - - odev->width = odev->dev_width / 8; - odev->height = ASUS_OLED_DISP_HEIGHT; - odev->x_shift = 0; - odev->y_shift = 0; - odev->last_val = 0; - - send_data(odev); - - return count; - } - - if (buf[0] == '<') { - size_t i; - size_t w = 0, h = 0; - size_t w_mem, h_mem; - - if (count < 10 || buf[2] != ':') - goto error_header; - - - switch (tolower(buf[1])) { - case ASUS_OLED_STATIC: - case ASUS_OLED_ROLL: - case ASUS_OLED_FLASH: - odev->pic_mode = buf[1]; - break; - default: - dev_err(odev->dev, "Wrong picture mode: '%c'.\n", - buf[1]); - return -EIO; - break; - } - - for (i = 3; i < count; ++i) { - if (buf[i] >= '0' && buf[i] <= '9') { - w = 10*w + (buf[i] - '0'); - - if (w > ASUS_OLED_MAX_WIDTH) - goto error_width; - } else if (tolower(buf[i]) == 'x') { - break; - } else { - goto error_width; - } - } - - for (++i; i < count; ++i) { - if (buf[i] >= '0' && buf[i] <= '9') { - h = 10*h + (buf[i] - '0'); - - if (h > ASUS_OLED_DISP_HEIGHT) - goto error_height; - } else if (tolower(buf[i]) == '>') { - break; - } else { - goto error_height; - } - } - - if (w < 1 || w > ASUS_OLED_MAX_WIDTH) - goto error_width; - - if (h < 1 || h > ASUS_OLED_DISP_HEIGHT) - goto error_height; - - if (i >= count || buf[i] != '>') - goto error_header; - - offs = i+1; - - if (w % (odev->dev_width) != 0) - w_mem = (w/(odev->dev_width) + 1)*(odev->dev_width); - else - w_mem = w; - - if (h < ASUS_OLED_DISP_HEIGHT) - h_mem = ASUS_OLED_DISP_HEIGHT; - else - h_mem = h; - - odev->buf_size = w_mem * h_mem / 8; - - kfree(odev->buf); - odev->buf = kmalloc(odev->buf_size, GFP_KERNEL); - - if (odev->buf == NULL) { - odev->buf_size = 0; - dev_err(odev->dev, "Out of memory!\n"); - return -ENOMEM; - } - - memset(odev->buf, 0xff, odev->buf_size); - - odev->buf_offs = 0; - odev->width = w; - odev->height = h; - odev->x_shift = 0; - odev->y_shift = 0; - odev->last_val = 0; - - if (odev->pic_mode == ASUS_OLED_FLASH) { - if (h < ASUS_OLED_DISP_HEIGHT/2) - odev->y_shift = (ASUS_OLED_DISP_HEIGHT/2 - h)/2; - } else { - if (h < ASUS_OLED_DISP_HEIGHT) - odev->y_shift = (ASUS_OLED_DISP_HEIGHT - h)/2; - } - - if (w < (odev->dev_width)) - odev->x_shift = ((odev->dev_width) - w)/2; - } - - max_offs = odev->width * odev->height; - - while (offs < count && odev->buf_offs < max_offs) { - int ret = 0; - - if (buf[offs] == '1' || buf[offs] == '#') { - ret = append_values(odev, 1, 1); - if (ret < 0) - return ret; - } else if (buf[offs] == '0' || buf[offs] == ' ') { - ret = append_values(odev, 0, 1); - if (ret < 0) - return ret; - } else if (buf[offs] == '\n') { - /* - * New line detected. Lets assume, that all characters - * till the end of the line were equal to the last - * character in this line. - */ - if (odev->buf_offs % odev->width != 0) - ret = append_values(odev, odev->last_val, - odev->width - - (odev->buf_offs % - odev->width)); - if (ret < 0) - return ret; - } - - offs++; - } - - if (odev->buf_offs >= max_offs) - send_data(odev); - - return count; - -error_width: - dev_err(odev->dev, "Wrong picture width specified.\n"); - return -EIO; - -error_height: - dev_err(odev->dev, "Wrong picture height specified.\n"); - return -EIO; - -error_header: - dev_err(odev->dev, "Wrong picture header.\n"); - return -EIO; -} - -static ssize_t set_picture(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct usb_interface *intf = to_usb_interface(dev); - - return odev_set_picture(usb_get_intfdata(intf), buf, count); -} - -static ssize_t class_set_picture(struct device *device, - struct device_attribute *attr, - const char *buf, size_t count) -{ - return odev_set_picture((struct asus_oled_dev *) - dev_get_drvdata(device), buf, count); -} - -#define ASUS_OLED_DEVICE_ATTR(_file) dev_attr_asus_oled_##_file - -static DEVICE_ATTR(asus_oled_enabled, S_IWUSR | S_IRUGO, - get_enabled, set_enabled); -static DEVICE_ATTR(asus_oled_picture, S_IWUSR , NULL, set_picture); - -static DEVICE_ATTR(enabled, S_IWUSR | S_IRUGO, - class_get_enabled, class_set_enabled); -static DEVICE_ATTR(picture, S_IWUSR, NULL, class_set_picture); - -static int asus_oled_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(interface); - struct asus_oled_dev *odev = NULL; - int retval = -ENOMEM; - uint16_t dev_width = 0; - enum oled_pack_mode pack_mode = PACK_MODE_LAST; - const struct oled_dev_desc_str *dev_desc = oled_dev_desc_table; - const char *desc = NULL; - - if (!id) { - /* Even possible? Just to make sure...*/ - dev_err(&interface->dev, "No usb_device_id provided!\n"); - return -ENODEV; - } - - for (; dev_desc->idVendor; dev_desc++) { - if (dev_desc->idVendor == id->idVendor - && dev_desc->idProduct == id->idProduct) { - dev_width = dev_desc->devWidth; - desc = dev_desc->devDesc; - pack_mode = dev_desc->packMode; - break; - } - } - - if (!desc || dev_width < 1 || pack_mode == PACK_MODE_LAST) { - dev_err(&interface->dev, - "Missing or incomplete device description!\n"); - return -ENODEV; - } - - odev = kzalloc(sizeof(struct asus_oled_dev), GFP_KERNEL); - if (odev == NULL) - return -ENOMEM; - - odev->udev = usb_get_dev(udev); - odev->pic_mode = ASUS_OLED_STATIC; - odev->dev_width = dev_width; - odev->pack_mode = pack_mode; - odev->height = 0; - odev->width = 0; - odev->x_shift = 0; - odev->y_shift = 0; - odev->buf_offs = 0; - odev->buf_size = 0; - odev->last_val = 0; - odev->buf = NULL; - odev->enabled = 1; - odev->dev = NULL; - - usb_set_intfdata(interface, odev); - - retval = device_create_file(&interface->dev, - &ASUS_OLED_DEVICE_ATTR(enabled)); - if (retval) - goto err_files; - - retval = device_create_file(&interface->dev, - &ASUS_OLED_DEVICE_ATTR(picture)); - if (retval) - goto err_files; - - odev->dev = device_create(oled_class, &interface->dev, MKDEV(0, 0), - NULL, "oled_%d", ++oled_num); - - if (IS_ERR(odev->dev)) { - retval = PTR_ERR(odev->dev); - goto err_files; - } - - dev_set_drvdata(odev->dev, odev); - - retval = device_create_file(odev->dev, &dev_attr_enabled); - if (retval) - goto err_class_enabled; - - retval = device_create_file(odev->dev, &dev_attr_picture); - if (retval) - goto err_class_picture; - - dev_info(&interface->dev, - "Attached Asus OLED device: %s [width %u, pack_mode %d]\n", - desc, odev->dev_width, odev->pack_mode); - - if (start_off) - enable_oled(odev, 0); - - return 0; - -err_class_picture: - device_remove_file(odev->dev, &dev_attr_picture); - -err_class_enabled: - device_remove_file(odev->dev, &dev_attr_enabled); - device_unregister(odev->dev); - -err_files: - device_remove_file(&interface->dev, &ASUS_OLED_DEVICE_ATTR(enabled)); - device_remove_file(&interface->dev, &ASUS_OLED_DEVICE_ATTR(picture)); - - usb_set_intfdata(interface, NULL); - usb_put_dev(odev->udev); - kfree(odev); - - return retval; -} - -static void asus_oled_disconnect(struct usb_interface *interface) -{ - struct asus_oled_dev *odev; - - odev = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); - - device_remove_file(odev->dev, &dev_attr_picture); - device_remove_file(odev->dev, &dev_attr_enabled); - device_unregister(odev->dev); - - device_remove_file(&interface->dev, &ASUS_OLED_DEVICE_ATTR(picture)); - device_remove_file(&interface->dev, &ASUS_OLED_DEVICE_ATTR(enabled)); - - usb_put_dev(odev->udev); - - kfree(odev->buf); - - kfree(odev); - - dev_info(&interface->dev, "Disconnected Asus OLED device\n"); -} - -#ifdef CONFIG_PM -static int asus_oled_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct asus_oled_dev *odev; - - odev = usb_get_intfdata(intf); - if (!odev) - return -ENODEV; - - odev->enabled_post_resume = odev->enabled; - enable_oled(odev, 0); - - return 0; -} - -static int asus_oled_resume(struct usb_interface *intf) -{ - struct asus_oled_dev *odev; - - odev = usb_get_intfdata(intf); - if (!odev) - return -ENODEV; - - enable_oled(odev, odev->enabled_post_resume); - - return 0; -} -#else -#define asus_oled_suspend NULL -#define asus_oled_resume NULL -#endif - -static struct usb_driver oled_driver = { - .name = ASUS_OLED_NAME, - .probe = asus_oled_probe, - .disconnect = asus_oled_disconnect, - .id_table = id_table, - .suspend = asus_oled_suspend, - .resume = asus_oled_resume, -}; - -static CLASS_ATTR_STRING(version, S_IRUGO, - ASUS_OLED_UNDERSCORE_NAME " " ASUS_OLED_VERSION); - -static int __init asus_oled_init(void) -{ - int retval = 0; - oled_class = class_create(THIS_MODULE, ASUS_OLED_UNDERSCORE_NAME); - - if (IS_ERR(oled_class)) { - pr_err("Error creating " ASUS_OLED_UNDERSCORE_NAME " class\n"); - return PTR_ERR(oled_class); - } - - retval = class_create_file(oled_class, &class_attr_version.attr); - if (retval) { - pr_err("Error creating class version file\n"); - goto error; - } - - retval = usb_register(&oled_driver); - - if (retval) { - pr_err("usb_register failed. Error number %d\n", retval); - goto error; - } - - return retval; - -error: - class_destroy(oled_class); - return retval; -} - -static void __exit asus_oled_exit(void) -{ - usb_deregister(&oled_driver); - class_remove_file(oled_class, &class_attr_version.attr); - class_destroy(oled_class); -} - -module_init(asus_oled_init); -module_exit(asus_oled_exit); - diff --git a/drivers/staging/asus_oled/linux.txt b/drivers/staging/asus_oled/linux.txt deleted file mode 100644 index dc758b0eb379..000000000000 --- a/drivers/staging/asus_oled/linux.txt +++ /dev/null @@ -1,33 +0,0 @@ - -0 -0 -00000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000000000000000000000000000000000000000000 -01111111111000000000000000000000000000000000000000000000000000000000000000 -00011111100000000000000111000000000000000000000000000000000000000000000000 -00001111000000000000000111000000000000000000000000000000000000000000000000 -00001111000000000000000111000000000000000000000000000000000000000000000000 -00001111000000000000000000000000000000000000000000000000000000000000000000 -00001111000000000000000000000000000000000000000000000000000000000000000000 -00001111000000000000011100001111111111100000111110011111100011111101111000 -00001111000000000000111110000011111000111000111110000111100001111000110000 -00001111000000000001101110000011111000111000001111000111100000111100100000 -00001111000000000001001110000011110000111100001111000111100000111101100000 -00001111000000000100001110000011110000111100001111000111100000011111000000 -00001111000000000100011110000011110000111100001111000111100000001111000000 -00001111000000000100011110000011110000111100001111000111100000001111000000 -00001111000000000100011100100011110000111100001111000111100000001111100000 -00001111000000001100111100100011110000111100001111000111100000001111110000 -00001111000000001100111101100011110000111100001111000111100000011011110000 -00001111000000011100111101000011110000111100001111000111100000010001111000 -00011111000001111100111011000011110000111100001111001111100000110000111100 -11111111111111111100011110001111111011111110000111110111111011111011111110 -00000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000000000000000000000000000000000000000000 -0 -0 -0 -0 diff --git a/drivers/staging/asus_oled/linux_f.txt b/drivers/staging/asus_oled/linux_f.txt deleted file mode 100644 index b4bb85cc6ebb..000000000000 --- a/drivers/staging/asus_oled/linux_f.txt +++ /dev/null @@ -1,18 +0,0 @@ - -00000000000000000000000000000000001111111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000011110000000000001110000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000011110000000000001110000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000011110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000011110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000011110000000000011000111111111100001111001111100111110111000000000000000000000000000000000000 -00000000000000000000000000000000000011110000000000111100001111000110001111000111100011100010000000000000000000000000000000000000 -00000000000000000000000000000000000011110000000001011100001111000111000111100111100001110110000000000000000000000000000000000000 -00000000000000000000000000000000000011110000000000011100001110000111000111100111100001111100000000000000000000000000000000000000 -00000000000000000000000000000000000011110000000100011100001110000111000111100111100000111100000000000000000000000000000000000000 -00000000000000000000000000000000000011110000000100011100001110000111000111100111100000111100000000000000000000000000000000000000 -00000000000000000000000000000000000011110000000100111001001110000111000111100111100000111110000000000000000000000000000000000000 -00000000000000000000000000000000000011110000001100111011001110000111000111100111100000111110000000000000000000000000000000000000 -00000000000000000000000000000000000011110000001100111010001110000111000111100111100000100111000000000000000000000000000000000000 -00000000000000000000000000000000000011110000111100110110001110000111000111100111100001000011100000000000000000000000000000000000 -00000000000000000000000000000000001111111111111100111100111111011111100011110111110111101111110000000000000000000000000000000000 - diff --git a/drivers/staging/asus_oled/linux_fr.txt b/drivers/staging/asus_oled/linux_fr.txt deleted file mode 100644 index f88e2b3bdd1b..000000000000 --- a/drivers/staging/asus_oled/linux_fr.txt +++ /dev/null @@ -1,33 +0,0 @@ - -00000000000000000000000000000000001111111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000011110000000000001110000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000011110000000000001110000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000011110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000011110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000011110000000000011000111111111100001111001111100111110111000000000000000000000000000000000000 -00000000000000000000000000000000000011110000000000111100001111000110001111000111100011100010000000000000000000000000000000000000 -00000000000000000000000000000000000011110000000001011100001111000111000111100111100001110110000000000000000000000000000000000000 -00000000000000000000000000000000000011110000000000011100001110000111000111100111100001111100000000000000000000000000000000000000 -00000000000000000000000000000000000011110000000100011100001110000111000111100111100000111100000000000000000000000000000000000000 -00000000000000000000000000000000000011110000000100011100001110000111000111100111100000111100000000000000000000000000000000000000 -00000000000000000000000000000000000011110000000100111001001110000111000111100111100000111110000000000000000000000000000000000000 -00000000000000000000000000000000000011110000001100111011001110000111000111100111100000111110000000000000000000000000000000000000 -00000000000000000000000000000000000011110000001100111010001110000111000111100111100000100111000000000000000000000000000000000000 -00000000000000000000000000000000000011110000111100110110001110000111000111100111100001000011100000000000000000000000000000000000 -00000000000000000000000000000000001111111111111100111100111111011111100011110111110111101111110000000000000000000000000000000000 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000 -00000000000000000000000000001111000000000000000000000000000000000000000000000000000000000000001111000000000000000000000000000000 -00000000000000000000000000011111100000000000000000000000000000000000000000000000000000000000011111100000000000000000000000000000 -00000000000000000000000000011111100000000000000000000000000000000000000000000000000000000000011111100000000000000000000000000000 -00000000000000000000000000001111000000000000000000000000000000000000000000000000000000000000001111000000000000000000000000000000 -00000000000000000000000000000110000000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 diff --git a/drivers/staging/asus_oled/tux.txt b/drivers/staging/asus_oled/tux.txt deleted file mode 100644 index 9d2052854b64..000000000000 --- a/drivers/staging/asus_oled/tux.txt +++ /dev/null @@ -1,33 +0,0 @@ - -00000000000001111111000000000000 -0000000000001 100000000000 -000000000001 10000000000 -000000000001 10000000000 -000000000001 10000000000 -000000000001 1 111 10000000000 -000000000001 1 1 1000000000 -000000000001 111 1000000000 -000000000001 111111 1000000000 -000000000001 111111 1000000000 -000000000001 1 1 100000000 -00000000001 11 100000000 -00000000001 11111111 10000000 -0000000001 11111111 1000000 -000000001 111111111 1000000 -000000001 1111111111 100000 -00000001 11111111111 100000 -00000001 111111111111 10000 -0000001 111111111111 10000 -0000001 111111111111 10000 -0000001 111111111111 10000 -0000001 111111111111 10000 -000000011 11111111111 10000 -000011 11 11111111111 100000 -0001 1111 111111111111111 1000 -001 1111111 11111111111111 1000 -001 1111111 1111111 111111 100 -001 11111111 111111 1111111 10 -001 11111111 11111 100 -001 1111111 111 11100 -000111 111 11111 11 100000 -000000111 111111111 1000000 diff --git a/drivers/staging/asus_oled/tux_r.txt b/drivers/staging/asus_oled/tux_r.txt deleted file mode 100644 index fd81a3e84949..000000000000 --- a/drivers/staging/asus_oled/tux_r.txt +++ /dev/null @@ -1,33 +0,0 @@ - -00000000000001111111000000000000 -0000000000001 100000000000 -000000000001 10000000000 -000000000001 10000000000 -000000000001 10000000000 -000000000001 1 111 10000000000 -000000000001 1 1 1000000000 -000000000001 111 1000000000 -000000000001 111111 1000000000 -000000000001 111111 1000000000 -000000000001 1 1 100000000 -00000000001 11 100000000 -00000000001 11111111 10000000 -0000000001 11111111 1000000 -000000001 111111111 1000000 -000000001 1111111111 100000 -00000001 11111111111 100000 -00000001 111111111111 10000 -0000001 111111111111 10000 -0000001 111111111111 10000 -0000001 111111111111 10000 -0000001 111111111111 10000 -000000011 11111111111 10000 -000011 11 11111111111 100000 -0001 1111 111111111111111 1000 -001 1111111 11111111111111 1000 -001 1111111 1111111 111111 100 -001 11111111 111111 1111111 10 -001 11111111 11111 100 -001 1111111 111 11100 -000111 111 11111 11 100000 -000000111 111111111 1000000 diff --git a/drivers/staging/asus_oled/tux_r2.txt b/drivers/staging/asus_oled/tux_r2.txt deleted file mode 100644 index e94d84eaab0b..000000000000 --- a/drivers/staging/asus_oled/tux_r2.txt +++ /dev/null @@ -1,33 +0,0 @@ - -000000000000000000000000000000000000000000000000000000000000011111110000000000000000000000000000000000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000000001 1000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000001 1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000001 1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000001 1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000001 1 111 1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000001 1 1 100000000000000000000000000000000000000000000000000000000000000000000000000000000000001111111111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000001 111 100000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111100000000000000111000000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000001 111111 100000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000000000000111000000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000001 111111 100000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000000000000111000000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000000001 1 1 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000000000000000000000000001 11 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -00000000000000000000000000000000000000000000000000000000001 11111111 1000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000000000011100001111111111100000111110011111100011111101111000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000000001 11111111 100000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000000000111110000011111000111000111110000111100001111000110000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000001 111111111 100000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000000001101110000011111000111000001111000111100000111100100000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000001 1111111111 10000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000000001001110000011110000111100001111000111100000111101100000000000000000000000000000000 -00000000000000000000000000000000000000000000000000000001 11111111111 10000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000000100001110000011110000111100001111000111100000011111000000000000000000000000000000000 -00000000000000000000000000000000000000000000000000000001 111111111111 10000000000000000000000000000000000000000000000000000000000000000000000000000000000011110000000001000111100000111100001111000011110001111000000011110000000 -0000000000000000000000000000000000000000000000000000001 111111111111 1000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000000100011110000011110000111100001111000111100000001111000000 -0000000000000000000000000000000000000000000000000000001 111111111111 1000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000000100011100100011110000111100001111000111100000001111100000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000001 111111111111 1000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000001100111100100011110000111100001111000111100000001111110000000000000000000000000000000 -0000000000000000000000000000000000000000000000000000001 111111111111 1000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000001100111101100011110000111100001111000111100000011011110000000000000000000000000000000 -000000000000000000000000000000000000000000000000000000011 11111111111 1000000000000000000000000000000000000000000000000000000000000000000000000000000000001111000000011100111101000011110000111100001111000111100000010001111000000000000000000000000000000 -000000000000000000000000000000000000000000000000000011 11 11111111111 10000000000000000000000000000000000000000000000000000000000000000000000000000000000011111000001111100111011000011110000111100001111001111100000110000111100000000000000000000000000000 -0000000000000000000000000000000000000000000000000001 1111 111111111111111 100000000000000000000000000000000000000000000000000000000000000000000000000000011111111111111111100011110001111111011111110000111110111111011111011111110000000000000000000000000000 -000000000000000000000000000000000000000000000000001 1111111 11111111111111 100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000001 1111111 1111111 111111 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000001 11111111 111111 1111111 1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000001 11111111 11111 1000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000001 1111111 111 111000000000000000000000000000000000000000000000000000 -000000000000000000000000000000000000000000000000000111 111 11111 11 10 -000000000000000000000000000000000000000000000000000000111 111111111 10 diff --git a/drivers/staging/asus_oled/zig.txt b/drivers/staging/asus_oled/zig.txt deleted file mode 100644 index 31573d8f799a..000000000000 --- a/drivers/staging/asus_oled/zig.txt +++ /dev/null @@ -1,33 +0,0 @@ - -10000000000000000000000000000000000000000000000000000000000000011000000000000000000000000000000000000000000000000000000000000001 -01000000000000000000000000000000000000000000000000000000000000100100000000000000000000000000000000000000000000000000000000000010 -00100000000000000000000000000000000000000000000000000000000001000010000000000000000000000000000000000000000000000000000000000100 -00010000000000000000000000000000000000000000000000000000000010000001000000000000000000000000000000000000000000000000000000001000 -00001000000000000000000000000000000000000000000000000000000100000000100000000000000000000000000000000000000000000000000000010000 -00000100000000000000000000000000000000000000000000000000001000000000010000000000000000000000000000000000000000000000000000100000 -00000010000000000000000000000000000000000000000000000000010000000000001000000000000000000000000000000000000000000000000001000000 -00000001000000000000000000000000000000000000000000000000100000000000000100000000000000000000000000000000000000000000000010000000 -00000000100000000000000000000000000000000000000000000001000000000000000010000000000000000000000000000000000000000000000100000000 -00000000010000000000000000000000000000000000000000000010000000000000000001000000000000000000000000000000000000000000001000000000 -00000000001000000000000000000000000000000000000000000100000000000000000000100000000000000000000000000000000000000000010000000000 -00000000000100000000000000000000000000000000000000001000000000000000000000010000000000000000000000000000000000000000100000000000 -00000000000010000000000000000000000000000000000000010000000000000000000000001000000000000000000000000000000000000001000000000000 -00000000000001000000000000000000000000000000000000100000000000000000000000000100000000000000000000000000000000000010000000000000 -00000000000000100000000000000000000000000000000001000000000000000000000000000010000000000000000000000000000000000100000000000000 -00000000000000010000000000000000000000000000000010000000000000000000000000000001000000000000000000000000000000001000000000000000 -00000000000000001000000000000000000000000000000100000000000000000000000000000000100000000000000000000000000000010000000000000000 -00000000000000000100000000000000000000000000001000000000000000000000000000000000010000000000000000000000000000100000000000000000 -00000000000000000010000000000000000000000000010000000000000000000000000000000000001000000000000000000000000001000000000000000000 -00000000000000000001000000000000000000000000100000000000000000000000000000000000000100000000000000000000000010000000000000000000 -00000000000000000000100000000000000000000001000000000000000000000000000000000000000010000000000000000000000100000000000000000000 -00000000000000000000010000000000000000000010000000000000000000000000000000000000000001000000000000000000001000000000000000000000 -00000000000000000000001000000000000000000100000000000000000000000000000000000000000000100000000000000000010000000000000000000000 -00000000000000000000000100000000000000001000000000000000000000000000000000000000000000010000000000000000100000000000000000000000 -00000000000000000000000010000000000000010000000000000000000000000000000000000000000000001000000000000001000000000000000000000000 -00000000000000000000000001000000000000100000000000000000000000000000000000000000000000000100000000000010000000000000000000000000 -00000000000000000000000000100000000001000000000000000000000000000000000000000000000000000010000000000100000000000000000000000000 -00000000000000000000000000010000000010000000000000000000000000000000000000000000000000000001000000001000000000000000000000000000 -00000000000000000000000000001000000100000000000000000000000000000000000000000000000000000000100000010000000000000000000000000000 -00000000000000000000000000000100001000000000000000000000000000000000000000000000000000000000010000100000000000000000000000000000 -00000000000000000000000000000010010000000000000000000000000000000000000000000000000000000000001001000000000000000000000000000000 -00000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000110000000000000000000000000000000 From 43b829b3c1aa8d4f748a8e68724df476d242365a Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 25 Jun 2013 10:08:49 +0900 Subject: [PATCH 0858/3400] serial: remove unnecessary platform_set_drvdata() The driver core clears the driver data to NULL after device_release or on probe failure, since commit 0998d0631001288a5974afc0b2a5f568bcdecb4d (device-core: Ensure drvdata = NULL when no driver is bound). Thus, it is not needed to manually clear the device driver data to NULL. Signed-off-by: Jingoo Han Acked-by: Barry Song Acked-by: Tony Prisk Acked-by: Shawn Guo Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/ar933x_uart.c | 1 - drivers/tty/serial/atmel_serial.c | 1 - drivers/tty/serial/bcm63xx_uart.c | 1 - drivers/tty/serial/clps711x.c | 11 ++--------- drivers/tty/serial/efm32-uart.c | 2 -- drivers/tty/serial/imx.c | 2 -- drivers/tty/serial/netx-serial.c | 2 -- drivers/tty/serial/pmac_zilog.c | 1 - drivers/tty/serial/pnx8xxx_uart.c | 2 -- drivers/tty/serial/pxa.c | 2 -- drivers/tty/serial/sa1100.c | 2 -- drivers/tty/serial/sccnxp.c | 3 --- drivers/tty/serial/sirfsoc_uart.c | 3 +-- drivers/tty/serial/vt8500_serial.c | 1 - 14 files changed, 3 insertions(+), 31 deletions(-) diff --git a/drivers/tty/serial/ar933x_uart.c b/drivers/tty/serial/ar933x_uart.c index 27f20c57abed..9824dfb1e4fe 100644 --- a/drivers/tty/serial/ar933x_uart.c +++ b/drivers/tty/serial/ar933x_uart.c @@ -703,7 +703,6 @@ static int ar933x_uart_remove(struct platform_device *pdev) struct ar933x_uart_port *up; up = platform_get_drvdata(pdev); - platform_set_drvdata(pdev, NULL); if (up) { uart_remove_one_port(&ar933x_uart_driver, &up->port); diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 0e39facfcb07..5c17f8dac91b 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -1860,7 +1860,6 @@ static int atmel_serial_remove(struct platform_device *pdev) int ret = 0; device_init_wakeup(&pdev->dev, 0); - platform_set_drvdata(pdev, NULL); ret = uart_remove_one_port(&atmel_uart, port); diff --git a/drivers/tty/serial/bcm63xx_uart.c b/drivers/tty/serial/bcm63xx_uart.c index 6fa2ae77fffd..d14ba5aa2ec7 100644 --- a/drivers/tty/serial/bcm63xx_uart.c +++ b/drivers/tty/serial/bcm63xx_uart.c @@ -852,7 +852,6 @@ static int bcm_uart_remove(struct platform_device *pdev) port = platform_get_drvdata(pdev); uart_remove_one_port(&bcm_uart_driver, port); - platform_set_drvdata(pdev, NULL); /* mark port as free */ ports[pdev->id].membase = 0; return 0; diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c index bfb17968c8db..7e4e4088471c 100644 --- a/drivers/tty/serial/clps711x.c +++ b/drivers/tty/serial/clps711x.c @@ -438,8 +438,7 @@ static int uart_clps711x_probe(struct platform_device *pdev) s->uart_clk = devm_clk_get(&pdev->dev, "uart"); if (IS_ERR(s->uart_clk)) { dev_err(&pdev->dev, "Can't get UART clocks\n"); - ret = PTR_ERR(s->uart_clk); - goto err_out; + return PTR_ERR(s->uart_clk); } s->uart.owner = THIS_MODULE; @@ -461,7 +460,7 @@ static int uart_clps711x_probe(struct platform_device *pdev) if (ret) { dev_err(&pdev->dev, "Registering UART driver failed\n"); devm_clk_put(&pdev->dev, s->uart_clk); - goto err_out; + return ret; } for (i = 0; i < UART_CLPS711X_NR; i++) { @@ -478,11 +477,6 @@ static int uart_clps711x_probe(struct platform_device *pdev) } return 0; - -err_out: - platform_set_drvdata(pdev, NULL); - - return ret; } static int uart_clps711x_remove(struct platform_device *pdev) @@ -495,7 +489,6 @@ static int uart_clps711x_remove(struct platform_device *pdev) devm_clk_put(&pdev->dev, s->uart_clk); uart_unregister_driver(&s->uart); - platform_set_drvdata(pdev, NULL); return 0; } diff --git a/drivers/tty/serial/efm32-uart.c b/drivers/tty/serial/efm32-uart.c index 7d199c8e1a75..e029907cf430 100644 --- a/drivers/tty/serial/efm32-uart.c +++ b/drivers/tty/serial/efm32-uart.c @@ -778,8 +778,6 @@ static int efm32_uart_remove(struct platform_device *pdev) { struct efm32_uart_port *efm_port = platform_get_drvdata(pdev); - platform_set_drvdata(pdev, NULL); - uart_remove_one_port(&efm32_uart_reg, &efm_port->port); if (pdev->id >= 0 && pdev->id < ARRAY_SIZE(efm32_uart_ports)) diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 2797e55d9753..40ca759d1f17 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -1596,8 +1596,6 @@ static int serial_imx_remove(struct platform_device *pdev) pdata = pdev->dev.platform_data; - platform_set_drvdata(pdev, NULL); - uart_remove_one_port(&imx_reg, &sport->port); if (pdata && pdata->exit) diff --git a/drivers/tty/serial/netx-serial.c b/drivers/tty/serial/netx-serial.c index b9a40ed70be2..ce04f3f8c547 100644 --- a/drivers/tty/serial/netx-serial.c +++ b/drivers/tty/serial/netx-serial.c @@ -693,8 +693,6 @@ static int serial_netx_remove(struct platform_device *pdev) { struct netx_port *sport = platform_get_drvdata(pdev); - platform_set_drvdata(pdev, NULL); - if (sport) uart_remove_one_port(&netx_reg, &sport->port); diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c index b1785f58b6e3..f87f1a0c8c6e 100644 --- a/drivers/tty/serial/pmac_zilog.c +++ b/drivers/tty/serial/pmac_zilog.c @@ -1798,7 +1798,6 @@ static int __exit pmz_detach(struct platform_device *pdev) uart_remove_one_port(&pmz_uart_reg, &uap->port); - platform_set_drvdata(pdev, NULL); uap->port.dev = NULL; return 0; diff --git a/drivers/tty/serial/pnx8xxx_uart.c b/drivers/tty/serial/pnx8xxx_uart.c index 7e277a5384a7..b6b7aca5707a 100644 --- a/drivers/tty/serial/pnx8xxx_uart.c +++ b/drivers/tty/serial/pnx8xxx_uart.c @@ -801,8 +801,6 @@ static int pnx8xxx_serial_remove(struct platform_device *pdev) { struct pnx8xxx_port *sport = platform_get_drvdata(pdev); - platform_set_drvdata(pdev, NULL); - if (sport) uart_remove_one_port(&pnx8xxx_reg, &sport->port); diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c index 05f504e0c271..ac8b2f5b2396 100644 --- a/drivers/tty/serial/pxa.c +++ b/drivers/tty/serial/pxa.c @@ -945,8 +945,6 @@ static int serial_pxa_remove(struct platform_device *dev) { struct uart_pxa_port *sport = platform_get_drvdata(dev); - platform_set_drvdata(dev, NULL); - uart_remove_one_port(&serial_pxa_reg, &sport->port); clk_unprepare(sport->clk); diff --git a/drivers/tty/serial/sa1100.c b/drivers/tty/serial/sa1100.c index af6b3e3ad24d..fc23ea19073a 100644 --- a/drivers/tty/serial/sa1100.c +++ b/drivers/tty/serial/sa1100.c @@ -864,8 +864,6 @@ static int sa1100_serial_remove(struct platform_device *pdev) { struct sa1100_port *sport = platform_get_drvdata(pdev); - platform_set_drvdata(pdev, NULL); - if (sport) uart_remove_one_port(&sa1100_reg, &sport->port); diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c index c77304155410..98555179fe10 100644 --- a/drivers/tty/serial/sccnxp.c +++ b/drivers/tty/serial/sccnxp.c @@ -997,8 +997,6 @@ static int sccnxp_probe(struct platform_device *pdev) } err_out: - platform_set_drvdata(pdev, NULL); - return ret; } @@ -1016,7 +1014,6 @@ static int sccnxp_remove(struct platform_device *pdev) uart_remove_one_port(&s->uart, &s->port[i]); uart_unregister_driver(&s->uart); - platform_set_drvdata(pdev, NULL); if (!IS_ERR(s->regulator)) return regulator_disable(s->regulator); diff --git a/drivers/tty/serial/sirfsoc_uart.c b/drivers/tty/serial/sirfsoc_uart.c index 1fd564b8194b..67a0d1b8341c 100644 --- a/drivers/tty/serial/sirfsoc_uart.c +++ b/drivers/tty/serial/sirfsoc_uart.c @@ -717,7 +717,6 @@ port_err: clk_disable_unprepare(sirfport->clk); clk_put(sirfport->clk); clk_err: - platform_set_drvdata(pdev, NULL); if (sirfport->hw_flow_ctrl) pinctrl_put(sirfport->p); err: @@ -728,7 +727,7 @@ static int sirfsoc_uart_remove(struct platform_device *pdev) { struct sirfsoc_uart_port *sirfport = platform_get_drvdata(pdev); struct uart_port *port = &sirfport->port; - platform_set_drvdata(pdev, NULL); + if (sirfport->hw_flow_ctrl) pinctrl_put(sirfport->p); clk_disable_unprepare(sirfport->clk); diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c index 48af43de3467..a90bf0440b4f 100644 --- a/drivers/tty/serial/vt8500_serial.c +++ b/drivers/tty/serial/vt8500_serial.c @@ -630,7 +630,6 @@ static int vt8500_serial_remove(struct platform_device *pdev) { struct vt8500_port *vt8500_port = platform_get_drvdata(pdev); - platform_set_drvdata(pdev, NULL); clk_disable_unprepare(vt8500_port->clk); uart_remove_one_port(&vt8500_uart_driver, &vt8500_port->uart); From 1cf93e0d5488e27270ece49e8c293d546140d144 Mon Sep 17 00:00:00 2001 From: Huang Shijie Date: Fri, 28 Jun 2013 13:39:42 +0800 Subject: [PATCH 0859/3400] serial: imx: remove the uart_console() check The uart_console() check makes the clocks(clk_per and clk_ipg) opened even when we close the console uart. This patch enable/disable the clocks in imx_console_write(), so we can keep the clocks closed when the console uart is closed. Also remove the clock enable/disable oprations in the probe, we do not need them any more. Signed-off-by: Huang Shijie Acked-by: Shawn Guo Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/imx.c | 69 +++++++++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 26 deletions(-) diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 40ca759d1f17..e43064b5c938 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -701,15 +701,13 @@ static int imx_startup(struct uart_port *port) int retval; unsigned long flags, temp; - if (!uart_console(port)) { - retval = clk_prepare_enable(sport->clk_per); - if (retval) - goto error_out1; - retval = clk_prepare_enable(sport->clk_ipg); - if (retval) { - clk_disable_unprepare(sport->clk_per); - goto error_out1; - } + retval = clk_prepare_enable(sport->clk_per); + if (retval) + goto error_out1; + retval = clk_prepare_enable(sport->clk_ipg); + if (retval) { + clk_disable_unprepare(sport->clk_per); + goto error_out1; } imx_setup_ufcr(sport, 0); @@ -900,10 +898,8 @@ static void imx_shutdown(struct uart_port *port) writel(temp, sport->port.membase + UCR1); spin_unlock_irqrestore(&sport->port.lock, flags); - if (!uart_console(&sport->port)) { - clk_disable_unprepare(sport->clk_per); - clk_disable_unprepare(sport->clk_ipg); - } + clk_disable_unprepare(sport->clk_per); + clk_disable_unprepare(sport->clk_ipg); } static void @@ -1250,6 +1246,16 @@ imx_console_write(struct console *co, const char *s, unsigned int count) unsigned int ucr1; unsigned long flags = 0; int locked = 1; + int retval; + + retval = clk_enable(sport->clk_per); + if (retval) + return; + retval = clk_enable(sport->clk_ipg); + if (retval) { + clk_disable(sport->clk_per); + return; + } if (sport->port.sysrq) locked = 0; @@ -1285,6 +1291,9 @@ imx_console_write(struct console *co, const char *s, unsigned int count) if (locked) spin_unlock_irqrestore(&sport->port.lock, flags); + + clk_disable(sport->clk_ipg); + clk_disable(sport->clk_per); } /* @@ -1358,6 +1367,7 @@ imx_console_setup(struct console *co, char *options) int bits = 8; int parity = 'n'; int flow = 'n'; + int retval; /* * Check whether an invalid uart number has been specified, and @@ -1370,6 +1380,11 @@ imx_console_setup(struct console *co, char *options) if (sport == NULL) return -ENODEV; + /* For setting the registers, we only need to enable the ipg clock. */ + retval = clk_prepare_enable(sport->clk_ipg); + if (retval) + goto error_console; + if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); else @@ -1377,7 +1392,20 @@ imx_console_setup(struct console *co, char *options) imx_setup_ufcr(sport, 0); - return uart_set_options(&sport->port, co, baud, parity, bits, flow); + retval = uart_set_options(&sport->port, co, baud, parity, bits, flow); + + clk_disable(sport->clk_ipg); + if (retval) { + clk_unprepare(sport->clk_ipg); + goto error_console; + } + + retval = clk_prepare(sport->clk_per); + if (retval) + clk_disable_unprepare(sport->clk_ipg); + +error_console: + return retval; } static struct uart_driver imx_reg; @@ -1555,9 +1583,6 @@ static int serial_imx_probe(struct platform_device *pdev) return ret; } - clk_prepare_enable(sport->clk_per); - clk_prepare_enable(sport->clk_ipg); - sport->port.uartclk = clk_get_rate(sport->clk_per); imx_ports[sport->port.line] = sport; @@ -1566,7 +1591,7 @@ static int serial_imx_probe(struct platform_device *pdev) if (pdata && pdata->init) { ret = pdata->init(pdev); if (ret) - goto clkput; + return ret; } ret = uart_add_one_port(&imx_reg, &sport->port); @@ -1574,18 +1599,10 @@ static int serial_imx_probe(struct platform_device *pdev) goto deinit; platform_set_drvdata(pdev, sport); - if (!uart_console(&sport->port)) { - clk_disable_unprepare(sport->clk_per); - clk_disable_unprepare(sport->clk_ipg); - } - return 0; deinit: if (pdata && pdata->exit) pdata->exit(pdev); -clkput: - clk_disable_unprepare(sport->clk_per); - clk_disable_unprepare(sport->clk_ipg); return ret; } From a496e6284c482555db8078190bb689594d129fa9 Mon Sep 17 00:00:00 2001 From: Huang Shijie Date: Mon, 8 Jul 2013 17:14:17 +0800 Subject: [PATCH 0860/3400] serial: imx: distinguish the imx6q uart from the others We will add the DMA support for the imx uart. For the firmware's limit, only the imx6 serial chips (including the imx6q, imx6dl, imx6sl) can support the DMA. This patch adds the necessary macro and helper to distinguish the imx6q uart from the other imx uart. Other chips can use the "fsl,imx6q-uart" to enable the DMA support. This patch also replaces the check "is_imx21_uart()" with "!is_imx1_uart()". Signed-off-by: Huang Shijie Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/imx.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index e43064b5c938..5bce53655c00 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -186,6 +186,7 @@ enum imx_uart_type { IMX1_UART, IMX21_UART, + IMX6Q_UART, }; /* device type dependent stuff */ @@ -231,6 +232,10 @@ static struct imx_uart_data imx_uart_devdata[] = { .uts_reg = IMX21_UTS, .devtype = IMX21_UART, }, + [IMX6Q_UART] = { + .uts_reg = IMX21_UTS, + .devtype = IMX6Q_UART, + }, }; static struct platform_device_id imx_uart_devtype[] = { @@ -240,6 +245,9 @@ static struct platform_device_id imx_uart_devtype[] = { }, { .name = "imx21-uart", .driver_data = (kernel_ulong_t) &imx_uart_devdata[IMX21_UART], + }, { + .name = "imx6q-uart", + .driver_data = (kernel_ulong_t) &imx_uart_devdata[IMX6Q_UART], }, { /* sentinel */ } @@ -247,6 +255,7 @@ static struct platform_device_id imx_uart_devtype[] = { MODULE_DEVICE_TABLE(platform, imx_uart_devtype); static struct of_device_id imx_uart_dt_ids[] = { + { .compatible = "fsl,imx6q-uart", .data = &imx_uart_devdata[IMX6Q_UART], }, { .compatible = "fsl,imx1-uart", .data = &imx_uart_devdata[IMX1_UART], }, { .compatible = "fsl,imx21-uart", .data = &imx_uart_devdata[IMX21_UART], }, { /* sentinel */ } @@ -268,6 +277,10 @@ static inline int is_imx21_uart(struct imx_port *sport) return sport->devdata->devtype == IMX21_UART; } +static inline int is_imx6q_uart(struct imx_port *sport) +{ + return sport->devdata->devtype == IMX6Q_UART; +} /* * Save and restore functions for UCR1, UCR2 and UCR3 registers */ @@ -800,7 +813,7 @@ static int imx_startup(struct uart_port *port) } } - if (is_imx21_uart(sport)) { + if (!is_imx1_uart(sport)) { temp = readl(sport->port.membase + UCR3); temp |= IMX21_UCR3_RXDMUXSEL; writel(temp, sport->port.membase + UCR3); @@ -1043,7 +1056,7 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios, writel(num, sport->port.membase + UBIR); writel(denom, sport->port.membase + UBMR); - if (is_imx21_uart(sport)) + if (!is_imx1_uart(sport)) writel(sport->port.uartclk / div / 1000, sport->port.membase + IMX21_ONEMS); From 09bd00f6e9a434727e4bfe93b0498c5d893c1906 Mon Sep 17 00:00:00 2001 From: Hubert Feurstein Date: Thu, 18 Jul 2013 18:52:49 +0200 Subject: [PATCH 0861/3400] serial/imx: fix custom-baudrate handling It was not possible to set custom-baudrates like 62500. Signed-off-by: Hubert Feurstein Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/imx.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 5bce53655c00..79d1943c2e79 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -1028,6 +1028,11 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios, */ div = 1; } else { + /* custom-baudrate handling */ + div = sport->port.uartclk / (baud * 16); + if (baud == 38400 && quot != div) + baud = sport->port.uartclk / (quot * 16); + div = sport->port.uartclk / (baud * 16); if (div > 7) div = 7; From b4cdc8f61beb2a55c8c3d22dfcaf5f34a919fe9b Mon Sep 17 00:00:00 2001 From: Huang Shijie Date: Mon, 8 Jul 2013 17:14:18 +0800 Subject: [PATCH 0862/3400] serial: imx: add DMA support for imx6q We only enable the DMA support when the following are meet: [1] The uart port supports the hardware flow control(CTS/RTS). (Some uart port does not support the CTS/RTS.) [2] The application enables the CTS/RTS. [3] The Soc is imx6q. For the sdma's firmware limit, we do not support the DMA except the imx6q platform. [4] The uart is not used as a console. Signed-off-by: Huang Shijie Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/imx.c | 405 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 400 insertions(+), 5 deletions(-) diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 79d1943c2e79..90655b875bab 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -48,9 +48,11 @@ #include #include #include +#include #include #include +#include /* Register definitions */ #define URXD0 0x0 /* Receiver Register */ @@ -82,6 +84,7 @@ #define UCR1_ADBR (1<<14) /* Auto detect baud rate */ #define UCR1_TRDYEN (1<<13) /* Transmitter ready interrupt enable */ #define UCR1_IDEN (1<<12) /* Idle condition interrupt */ +#define UCR1_ICD_REG(x) (((x) & 3) << 10) /* idle condition detect */ #define UCR1_RRDYEN (1<<9) /* Recv ready interrupt enable */ #define UCR1_RDMAEN (1<<8) /* Recv ready DMA enable */ #define UCR1_IREN (1<<7) /* Infrared interface enable */ @@ -90,6 +93,7 @@ #define UCR1_SNDBRK (1<<4) /* Send break */ #define UCR1_TDMAEN (1<<3) /* Transmitter ready DMA enable */ #define IMX1_UCR1_UARTCLKEN (1<<2) /* UART clock enabled, i.mx1 only */ +#define UCR1_ATDMAEN (1<<2) /* Aging DMA Timer Enable */ #define UCR1_DOZE (1<<1) /* Doze */ #define UCR1_UARTEN (1<<0) /* UART enabled */ #define UCR2_ESCI (1<<15) /* Escape seq interrupt enable */ @@ -125,6 +129,7 @@ #define UCR4_ENIRI (1<<8) /* Serial infrared interrupt enable */ #define UCR4_WKEN (1<<7) /* Wake interrupt enable */ #define UCR4_REF16 (1<<6) /* Ref freq 16 MHz */ +#define UCR4_IDDMAEN (1<<6) /* DMA IDLE Condition Detected */ #define UCR4_IRSC (1<<5) /* IR special case */ #define UCR4_TCEN (1<<3) /* Transmit complete interrupt enable */ #define UCR4_BKEN (1<<2) /* Break condition interrupt enable */ @@ -209,6 +214,19 @@ struct imx_port { struct clk *clk_ipg; struct clk *clk_per; const struct imx_uart_data *devdata; + + /* DMA fields */ + unsigned int dma_is_inited:1; + unsigned int dma_is_enabled:1; + unsigned int dma_is_rxing:1; + unsigned int dma_is_txing:1; + struct dma_chan *dma_chan_rx, *dma_chan_tx; + struct scatterlist rx_sgl, tx_sgl[2]; + void *rx_buf; + unsigned int rx_bytes, tx_bytes; + struct work_struct tsk_dma_rx, tsk_dma_tx; + unsigned int dma_tx_nents; + wait_queue_head_t dma_wait; }; struct imx_port_ucrs { @@ -399,6 +417,13 @@ static void imx_stop_tx(struct uart_port *port) return; } + /* + * We are maybe in the SMP context, so if the DMA TX thread is running + * on other cpu, we have to wait for it to finish. + */ + if (sport->dma_is_enabled && sport->dma_is_txing) + return; + temp = readl(sport->port.membase + UCR1); writel(temp & ~UCR1_TXMPTYEN, sport->port.membase + UCR1); } @@ -411,6 +436,13 @@ static void imx_stop_rx(struct uart_port *port) struct imx_port *sport = (struct imx_port *)port; unsigned long temp; + /* + * We are maybe in the SMP context, so if the DMA TX thread is running + * on other cpu, we have to wait for it to finish. + */ + if (sport->dma_is_enabled && sport->dma_is_rxing) + return; + temp = readl(sport->port.membase + UCR2); writel(temp & ~UCR2_RXEN, sport->port.membase + UCR2); } @@ -446,6 +478,95 @@ static inline void imx_transmit_buffer(struct imx_port *sport) imx_stop_tx(&sport->port); } +static void dma_tx_callback(void *data) +{ + struct imx_port *sport = data; + struct scatterlist *sgl = &sport->tx_sgl[0]; + struct circ_buf *xmit = &sport->port.state->xmit; + unsigned long flags; + + dma_unmap_sg(sport->port.dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE); + + sport->dma_is_txing = 0; + + /* update the stat */ + spin_lock_irqsave(&sport->port.lock, flags); + xmit->tail = (xmit->tail + sport->tx_bytes) & (UART_XMIT_SIZE - 1); + sport->port.icount.tx += sport->tx_bytes; + spin_unlock_irqrestore(&sport->port.lock, flags); + + dev_dbg(sport->port.dev, "we finish the TX DMA.\n"); + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(&sport->port); + + if (waitqueue_active(&sport->dma_wait)) { + wake_up(&sport->dma_wait); + dev_dbg(sport->port.dev, "exit in %s.\n", __func__); + return; + } + + schedule_work(&sport->tsk_dma_tx); +} + +static void dma_tx_work(struct work_struct *w) +{ + struct imx_port *sport = container_of(w, struct imx_port, tsk_dma_tx); + struct circ_buf *xmit = &sport->port.state->xmit; + struct scatterlist *sgl = sport->tx_sgl; + struct dma_async_tx_descriptor *desc; + struct dma_chan *chan = sport->dma_chan_tx; + struct device *dev = sport->port.dev; + enum dma_status status; + unsigned long flags; + int ret; + + status = chan->device->device_tx_status(chan, (dma_cookie_t)0, NULL); + if (DMA_IN_PROGRESS == status) + return; + + spin_lock_irqsave(&sport->port.lock, flags); + sport->tx_bytes = uart_circ_chars_pending(xmit); + if (sport->tx_bytes == 0) { + spin_unlock_irqrestore(&sport->port.lock, flags); + return; + } + + if (xmit->tail > xmit->head) { + sport->dma_tx_nents = 2; + sg_init_table(sgl, 2); + sg_set_buf(sgl, xmit->buf + xmit->tail, + UART_XMIT_SIZE - xmit->tail); + sg_set_buf(sgl + 1, xmit->buf, xmit->head); + } else { + sport->dma_tx_nents = 1; + sg_init_one(sgl, xmit->buf + xmit->tail, sport->tx_bytes); + } + spin_unlock_irqrestore(&sport->port.lock, flags); + + ret = dma_map_sg(dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE); + if (ret == 0) { + dev_err(dev, "DMA mapping error for TX.\n"); + return; + } + desc = dmaengine_prep_slave_sg(chan, sgl, sport->dma_tx_nents, + DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT); + if (!desc) { + dev_err(dev, "We cannot prepare for the TX slave dma!\n"); + return; + } + desc->callback = dma_tx_callback; + desc->callback_param = sport; + + dev_dbg(dev, "TX: prepare to send %lu bytes by DMA.\n", + uart_circ_chars_pending(xmit)); + /* fire it */ + sport->dma_is_txing = 1; + dmaengine_submit(desc); + dma_async_issue_pending(chan); + return; +} + /* * interrupts disabled on entry */ @@ -472,8 +593,10 @@ static void imx_start_tx(struct uart_port *port) temp |= UCR4_OREN; writel(temp, sport->port.membase + UCR4); - temp = readl(sport->port.membase + UCR1); - writel(temp | UCR1_TXMPTYEN, sport->port.membase + UCR1); + if (!sport->dma_is_enabled) { + temp = readl(sport->port.membase + UCR1); + writel(temp | UCR1_TXMPTYEN, sport->port.membase + UCR1); + } if (USE_IRDA(sport)) { temp = readl(sport->port.membase + UCR1); @@ -485,6 +608,15 @@ static void imx_start_tx(struct uart_port *port) writel(temp, sport->port.membase + UCR4); } + if (sport->dma_is_enabled) { + /* + * We may in the interrupt context, so arise a work_struct to + * do the real job. + */ + schedule_work(&sport->tsk_dma_tx); + return; + } + if (readl(sport->port.membase + uts_reg(sport)) & UTS_TXEMPTY) imx_transmit_buffer(sport); } @@ -600,6 +732,28 @@ out: return IRQ_HANDLED; } +/* + * If the RXFIFO is filled with some data, and then we + * arise a DMA operation to receive them. + */ +static void imx_dma_rxint(struct imx_port *sport) +{ + unsigned long temp; + + temp = readl(sport->port.membase + USR2); + if ((temp & USR2_RDR) && !sport->dma_is_rxing) { + sport->dma_is_rxing = 1; + + /* disable the `Recerver Ready Interrrupt` */ + temp = readl(sport->port.membase + UCR1); + temp &= ~(UCR1_RRDYEN); + writel(temp, sport->port.membase + UCR1); + + /* tell the DMA to receive the data. */ + schedule_work(&sport->tsk_dma_rx); + } +} + static irqreturn_t imx_int(int irq, void *dev_id) { struct imx_port *sport = dev_id; @@ -608,8 +762,12 @@ static irqreturn_t imx_int(int irq, void *dev_id) sts = readl(sport->port.membase + USR1); - if (sts & USR1_RRDY) - imx_rxint(irq, dev_id); + if (sts & USR1_RRDY) { + if (sport->dma_is_enabled) + imx_dma_rxint(sport); + else + imx_rxint(irq, dev_id); + } if (sts & USR1_TRDY && readl(sport->port.membase + UCR1) & UCR1_TXMPTYEN) @@ -666,7 +824,8 @@ static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl) temp = readl(sport->port.membase + UCR2) & ~UCR2_CTS; if (mctrl & TIOCM_RTS) - temp |= UCR2_CTS; + if (!sport->dma_is_enabled) + temp |= UCR2_CTS; writel(temp, sport->port.membase + UCR2); } @@ -705,6 +864,226 @@ static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode) return 0; } +#define RX_BUF_SIZE (PAGE_SIZE) +static int start_rx_dma(struct imx_port *sport); +static void dma_rx_work(struct work_struct *w) +{ + struct imx_port *sport = container_of(w, struct imx_port, tsk_dma_rx); + struct tty_port *port = &sport->port.state->port; + + if (sport->rx_bytes) { + tty_insert_flip_string(port, sport->rx_buf, sport->rx_bytes); + tty_flip_buffer_push(port); + sport->rx_bytes = 0; + } + + if (sport->dma_is_rxing) + start_rx_dma(sport); +} + +static void imx_rx_dma_done(struct imx_port *sport) +{ + unsigned long temp; + + /* Enable this interrupt when the RXFIFO is empty. */ + temp = readl(sport->port.membase + UCR1); + temp |= UCR1_RRDYEN; + writel(temp, sport->port.membase + UCR1); + + sport->dma_is_rxing = 0; + + /* Is the shutdown waiting for us? */ + if (waitqueue_active(&sport->dma_wait)) + wake_up(&sport->dma_wait); +} + +/* + * There are three kinds of RX DMA interrupts(such as in the MX6Q): + * [1] the RX DMA buffer is full. + * [2] the Aging timer expires(wait for 8 bytes long) + * [3] the Idle Condition Detect(enabled the UCR4_IDDMAEN). + * + * The [2] is trigger when a character was been sitting in the FIFO + * meanwhile [3] can wait for 32 bytes long when the RX line is + * on IDLE state and RxFIFO is empty. + */ +static void dma_rx_callback(void *data) +{ + struct imx_port *sport = data; + struct dma_chan *chan = sport->dma_chan_rx; + struct scatterlist *sgl = &sport->rx_sgl; + struct dma_tx_state state; + enum dma_status status; + unsigned int count; + + /* unmap it first */ + dma_unmap_sg(sport->port.dev, sgl, 1, DMA_FROM_DEVICE); + + status = chan->device->device_tx_status(chan, (dma_cookie_t)0, &state); + count = RX_BUF_SIZE - state.residue; + dev_dbg(sport->port.dev, "We get %d bytes.\n", count); + + if (count) { + sport->rx_bytes = count; + schedule_work(&sport->tsk_dma_rx); + } else + imx_rx_dma_done(sport); +} + +static int start_rx_dma(struct imx_port *sport) +{ + struct scatterlist *sgl = &sport->rx_sgl; + struct dma_chan *chan = sport->dma_chan_rx; + struct device *dev = sport->port.dev; + struct dma_async_tx_descriptor *desc; + int ret; + + sg_init_one(sgl, sport->rx_buf, RX_BUF_SIZE); + ret = dma_map_sg(dev, sgl, 1, DMA_FROM_DEVICE); + if (ret == 0) { + dev_err(dev, "DMA mapping error for RX.\n"); + return -EINVAL; + } + desc = dmaengine_prep_slave_sg(chan, sgl, 1, DMA_DEV_TO_MEM, + DMA_PREP_INTERRUPT); + if (!desc) { + dev_err(dev, "We cannot prepare for the RX slave dma!\n"); + return -EINVAL; + } + desc->callback = dma_rx_callback; + desc->callback_param = sport; + + dev_dbg(dev, "RX: prepare for the DMA.\n"); + dmaengine_submit(desc); + dma_async_issue_pending(chan); + return 0; +} + +static void imx_uart_dma_exit(struct imx_port *sport) +{ + if (sport->dma_chan_rx) { + dma_release_channel(sport->dma_chan_rx); + sport->dma_chan_rx = NULL; + + kfree(sport->rx_buf); + sport->rx_buf = NULL; + } + + if (sport->dma_chan_tx) { + dma_release_channel(sport->dma_chan_tx); + sport->dma_chan_tx = NULL; + } + + sport->dma_is_inited = 0; +} + +static int imx_uart_dma_init(struct imx_port *sport) +{ + struct dma_slave_config slave_config; + struct device *dev = sport->port.dev; + int ret; + + /* Prepare for RX : */ + sport->dma_chan_rx = dma_request_slave_channel(dev, "rx"); + if (!sport->dma_chan_rx) { + dev_dbg(dev, "cannot get the DMA channel.\n"); + ret = -EINVAL; + goto err; + } + + slave_config.direction = DMA_DEV_TO_MEM; + slave_config.src_addr = sport->port.mapbase + URXD0; + slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; + slave_config.src_maxburst = RXTL; + ret = dmaengine_slave_config(sport->dma_chan_rx, &slave_config); + if (ret) { + dev_err(dev, "error in RX dma configuration.\n"); + goto err; + } + + sport->rx_buf = kzalloc(PAGE_SIZE, GFP_KERNEL); + if (!sport->rx_buf) { + dev_err(dev, "cannot alloc DMA buffer.\n"); + ret = -ENOMEM; + goto err; + } + sport->rx_bytes = 0; + + /* Prepare for TX : */ + sport->dma_chan_tx = dma_request_slave_channel(dev, "tx"); + if (!sport->dma_chan_tx) { + dev_err(dev, "cannot get the TX DMA channel!\n"); + ret = -EINVAL; + goto err; + } + + slave_config.direction = DMA_MEM_TO_DEV; + slave_config.dst_addr = sport->port.mapbase + URTX0; + slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; + slave_config.dst_maxburst = TXTL; + ret = dmaengine_slave_config(sport->dma_chan_tx, &slave_config); + if (ret) { + dev_err(dev, "error in TX dma configuration."); + goto err; + } + + sport->dma_is_inited = 1; + + return 0; +err: + imx_uart_dma_exit(sport); + return ret; +} + +static void imx_enable_dma(struct imx_port *sport) +{ + unsigned long temp; + struct tty_port *port = &sport->port.state->port; + + port->low_latency = 1; + INIT_WORK(&sport->tsk_dma_tx, dma_tx_work); + INIT_WORK(&sport->tsk_dma_rx, dma_rx_work); + init_waitqueue_head(&sport->dma_wait); + + /* set UCR1 */ + temp = readl(sport->port.membase + UCR1); + temp |= UCR1_RDMAEN | UCR1_TDMAEN | UCR1_ATDMAEN | + /* wait for 32 idle frames for IDDMA interrupt */ + UCR1_ICD_REG(3); + writel(temp, sport->port.membase + UCR1); + + /* set UCR4 */ + temp = readl(sport->port.membase + UCR4); + temp |= UCR4_IDDMAEN; + writel(temp, sport->port.membase + UCR4); + + sport->dma_is_enabled = 1; +} + +static void imx_disable_dma(struct imx_port *sport) +{ + unsigned long temp; + struct tty_port *port = &sport->port.state->port; + + /* clear UCR1 */ + temp = readl(sport->port.membase + UCR1); + temp &= ~(UCR1_RDMAEN | UCR1_TDMAEN | UCR1_ATDMAEN); + writel(temp, sport->port.membase + UCR1); + + /* clear UCR2 */ + temp = readl(sport->port.membase + UCR2); + temp &= ~(UCR2_CTSC | UCR2_CTS); + writel(temp, sport->port.membase + UCR2); + + /* clear UCR4 */ + temp = readl(sport->port.membase + UCR4); + temp &= ~UCR4_IDDMAEN; + writel(temp, sport->port.membase + UCR4); + + sport->dma_is_enabled = 0; + port->low_latency = 0; +} + /* half the RX buffer size */ #define CTSTL 16 @@ -869,6 +1248,15 @@ static void imx_shutdown(struct uart_port *port) unsigned long temp; unsigned long flags; + if (sport->dma_is_enabled) { + /* We have to wait for the DMA to finish. */ + wait_event(sport->dma_wait, + !sport->dma_is_rxing && !sport->dma_is_txing); + imx_stop_rx(port); + imx_disable_dma(sport); + imx_uart_dma_exit(sport); + } + spin_lock_irqsave(&sport->port.lock, flags); temp = readl(sport->port.membase + UCR2); temp &= ~(UCR2_TXEN); @@ -955,6 +1343,11 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios, if (sport->have_rtscts) { ucr2 &= ~UCR2_IRTS; ucr2 |= UCR2_CTSC; + + /* Can we enable the DMA support? */ + if (is_imx6q_uart(sport) && !uart_console(port) + && !sport->dma_is_inited) + imx_uart_dma_init(sport); } else { termios->c_cflag &= ~CRTSCTS; } @@ -1073,6 +1466,8 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios, if (UART_ENABLE_MS(&sport->port, termios->c_cflag)) imx_enable_ms(&sport->port); + if (sport->dma_is_inited && !sport->dma_is_enabled) + imx_enable_dma(sport); spin_unlock_irqrestore(&sport->port.lock, flags); } From 10d8b34a421716d55a4ff7c2d427c35e88b8fd60 Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Sat, 29 Jun 2013 10:44:17 +0400 Subject: [PATCH 0863/3400] serial: max310x: Driver rework This patch rework max310x driver. Major changes have been made: - Prepare driver to support ICs with more than one UART. - Prepare driver to support work with I2C-bus. The patch changes almost every function and can not be divided into parts. Signed-off-by: Alexander Shiyan Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/Kconfig | 4 +- drivers/tty/serial/max310x.c | 920 +++++++++++++------------- include/linux/platform_data/max310x.h | 5 +- 3 files changed, 455 insertions(+), 474 deletions(-) diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 5e3d68917ffe..25772c15276d 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -291,9 +291,9 @@ config SERIAL_MAX3100 config SERIAL_MAX310X bool "MAX310X support" - depends on SPI + depends on SPI_MASTER select SERIAL_CORE - select REGMAP_SPI if SPI + select REGMAP_SPI if SPI_MASTER default n help This selects support for an advanced UART from Maxim (Dallas). diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index 8941e6418942..4620289e9e49 100644 --- a/drivers/tty/serial/max310x.c +++ b/drivers/tty/serial/max310x.c @@ -1,7 +1,7 @@ /* * Maxim (Dallas) MAX3107/8 serial driver * - * Copyright (C) 2012 Alexander Shiyan + * Copyright (C) 2012-2013 Alexander Shiyan * * Based on max3100.c, by Christian Pellegrin * Based on max3110.c, by Feng Tang @@ -17,7 +17,9 @@ /* TODO: MAX14830 support (Quad) */ #include +#include #include +#include #include #include #include @@ -25,8 +27,10 @@ #include #include #include + #include +#define MAX310X_NAME "max310x" #define MAX310X_MAJOR 204 #define MAX310X_MINOR 209 @@ -37,7 +41,8 @@ #define MAX310X_IRQSTS_REG (0x02) /* IRQ status */ #define MAX310X_LSR_IRQEN_REG (0x03) /* LSR IRQ enable */ #define MAX310X_LSR_IRQSTS_REG (0x04) /* LSR IRQ status */ -#define MAX310X_SPCHR_IRQEN_REG (0x05) /* Special char IRQ enable */ +#define MAX310X_REG_05 (0x05) +#define MAX310X_SPCHR_IRQEN_REG MAX310X_REG_05 /* Special char IRQ en */ #define MAX310X_SPCHR_IRQSTS_REG (0x06) /* Special char IRQ status */ #define MAX310X_STS_IRQEN_REG (0x07) /* Status IRQ enable */ #define MAX310X_STS_IRQSTS_REG (0x08) /* Status IRQ status */ @@ -63,8 +68,15 @@ #define MAX310X_BRGDIVLSB_REG (0x1c) /* Baud rate divisor LSB */ #define MAX310X_BRGDIVMSB_REG (0x1d) /* Baud rate divisor MSB */ #define MAX310X_CLKSRC_REG (0x1e) /* Clock source */ -/* Only present in MAX3107 */ -#define MAX3107_REVID_REG (0x1f) /* Revision identification */ +#define MAX310X_REG_1F (0x1f) + +#define MAX310X_REVID_REG MAX310X_REG_1F /* Revision ID */ + +#define MAX310X_GLOBALIRQ_REG MAX310X_REG_1F /* Global IRQ (RO) */ +#define MAX310X_GLOBALCMD_REG MAX310X_REG_1F /* Global Command (WO) */ + +/* Extended registers */ +#define MAX310X_REVID_EXTREG MAX310X_REG_05 /* Revision ID */ /* IRQ register bits */ #define MAX310X_IRQ_LSR_BIT (1 << 0) /* LSR interrupt */ @@ -246,58 +258,139 @@ #define MAX310X_CLKSRC_EXTCLK_BIT (1 << 4) /* External clock enable */ #define MAX310X_CLKSRC_CLK2RTS_BIT (1 << 7) /* Baud clk to RTS pin */ +/* Global commands */ +#define MAX310X_EXTREG_ENBL (0xce) +#define MAX310X_EXTREG_DSBL (0xcd) + /* Misc definitions */ #define MAX310X_FIFO_SIZE (128) +#define MAX310x_REV_MASK (0xfc) /* MAX3107 specific */ #define MAX3107_REV_ID (0xa0) -#define MAX3107_REV_MASK (0xfe) -/* IRQ status bits definitions */ -#define MAX310X_IRQ_TX (MAX310X_IRQ_TXFIFO_BIT | \ - MAX310X_IRQ_TXEMPTY_BIT) -#define MAX310X_IRQ_RX (MAX310X_IRQ_RXFIFO_BIT | \ - MAX310X_IRQ_RXEMPTY_BIT) +struct max310x_devtype { + char name[9]; + int nr; + int (*detect)(struct device *); + void (*power)(struct uart_port *, int); +}; -/* Supported chip types */ -enum { - MAX310X_TYPE_MAX3107 = 3107, - MAX310X_TYPE_MAX3108 = 3108, +struct max310x_one { + struct uart_port port; + struct work_struct tx_work; }; struct max310x_port { struct uart_driver uart; - struct uart_port port; - - const char *name; - int uartclk; - - unsigned int nr_gpio; + struct max310x_devtype *devtype; + struct regmap *regmap; + struct regmap_config regcfg; + struct mutex mutex; + struct max310x_pdata *pdata; + int gpio_used; #ifdef CONFIG_GPIOLIB struct gpio_chip gpio; #endif - - struct regmap *regmap; - struct regmap_config regcfg; - - struct workqueue_struct *wq; - struct work_struct tx_work; - - struct mutex max310x_mutex; - - struct max310x_pdata *pdata; + struct max310x_one p[0]; }; -static bool max3107_8_reg_writeable(struct device *dev, unsigned int reg) +static u8 max310x_port_read(struct uart_port *port, u8 reg) { - switch (reg) { + struct max310x_port *s = dev_get_drvdata(port->dev); + unsigned int val = 0; + + regmap_read(s->regmap, port->iobase + reg, &val); + + return val; +} + +static void max310x_port_write(struct uart_port *port, u8 reg, u8 val) +{ + struct max310x_port *s = dev_get_drvdata(port->dev); + + regmap_write(s->regmap, port->iobase + reg, val); +} + +static void max310x_port_update(struct uart_port *port, u8 reg, u8 mask, u8 val) +{ + struct max310x_port *s = dev_get_drvdata(port->dev); + + regmap_update_bits(s->regmap, port->iobase + reg, mask, val); +} + +static int max3107_detect(struct device *dev) +{ + struct max310x_port *s = dev_get_drvdata(dev); + unsigned int val = 0; + int ret; + + ret = regmap_read(s->regmap, MAX310X_REVID_REG, &val); + if (ret) + return ret; + + if (((val & MAX310x_REV_MASK) != MAX3107_REV_ID)) { + dev_err(dev, + "%s ID 0x%02x does not match\n", s->devtype->name, val); + return -ENODEV; + } + + return 0; +} + +static int max3108_detect(struct device *dev) +{ + struct max310x_port *s = dev_get_drvdata(dev); + unsigned int val = 0; + int ret; + + /* MAX3108 have not REV ID register, we just check default value + * from clocksource register to make sure everything works. + */ + ret = regmap_read(s->regmap, MAX310X_CLKSRC_REG, &val); + if (ret) + return ret; + + if (val != (MAX310X_CLKSRC_EXTCLK_BIT | MAX310X_CLKSRC_PLLBYP_BIT)) { + dev_err(dev, "%s not present\n", s->devtype->name); + return -ENODEV; + } + + return 0; +} + +static void max310x_power(struct uart_port *port, int on) +{ + max310x_port_update(port, MAX310X_MODE1_REG, + MAX310X_MODE1_FORCESLEEP_BIT, + on ? 0 : MAX310X_MODE1_FORCESLEEP_BIT); + if (on) + msleep(50); +} + +static const struct max310x_devtype max3107_devtype = { + .name = "MAX3107", + .nr = 1, + .detect = max3107_detect, + .power = max310x_power, +}; + +static const struct max310x_devtype max3108_devtype = { + .name = "MAX3108", + .nr = 1, + .detect = max3108_detect, + .power = max310x_power, +}; + +static bool max310x_reg_writeable(struct device *dev, unsigned int reg) +{ + switch (reg & 0x1f) { case MAX310X_IRQSTS_REG: case MAX310X_LSR_IRQSTS_REG: case MAX310X_SPCHR_IRQSTS_REG: case MAX310X_STS_IRQSTS_REG: case MAX310X_TXFIFOLVL_REG: case MAX310X_RXFIFOLVL_REG: - case MAX3107_REVID_REG: /* Only available on MAX3107 */ return false; default: break; @@ -308,7 +401,7 @@ static bool max3107_8_reg_writeable(struct device *dev, unsigned int reg) static bool max310x_reg_volatile(struct device *dev, unsigned int reg) { - switch (reg) { + switch (reg & 0x1f) { case MAX310X_RHR_REG: case MAX310X_IRQSTS_REG: case MAX310X_LSR_IRQSTS_REG: @@ -317,6 +410,9 @@ static bool max310x_reg_volatile(struct device *dev, unsigned int reg) case MAX310X_TXFIFOLVL_REG: case MAX310X_RXFIFOLVL_REG: case MAX310X_GPIODATA_REG: + case MAX310X_BRGDIVLSB_REG: + case MAX310X_REG_05: + case MAX310X_REG_1F: return true; default: break; @@ -327,7 +423,7 @@ static bool max310x_reg_volatile(struct device *dev, unsigned int reg) static bool max310x_reg_precious(struct device *dev, unsigned int reg) { - switch (reg) { + switch (reg & 0x1f) { case MAX310X_RHR_REG: case MAX310X_IRQSTS_REG: case MAX310X_SPCHR_IRQSTS_REG: @@ -340,42 +436,25 @@ static bool max310x_reg_precious(struct device *dev, unsigned int reg) return false; } -static void max310x_set_baud(struct max310x_port *s, int baud) +static void max310x_set_baud(struct uart_port *port, int baud) { - unsigned int mode = 0, div = s->uartclk / baud; + unsigned int mode = 0, div = port->uartclk / baud; if (!(div / 16)) { /* Mode x2 */ mode = MAX310X_BRGCFG_2XMODE_BIT; - div = (s->uartclk * 2) / baud; + div = (port->uartclk * 2) / baud; } if (!(div / 16)) { /* Mode x4 */ mode = MAX310X_BRGCFG_4XMODE_BIT; - div = (s->uartclk * 4) / baud; + div = (port->uartclk * 4) / baud; } - regmap_write(s->regmap, MAX310X_BRGDIVMSB_REG, - ((div / 16) >> 8) & 0xff); - regmap_write(s->regmap, MAX310X_BRGDIVLSB_REG, (div / 16) & 0xff); - regmap_write(s->regmap, MAX310X_BRGCFG_REG, (div % 16) | mode); -} - -static void max310x_wait_pll(struct max310x_port *s) -{ - int tryes = 1000; - - /* Wait for PLL only if crystal is used */ - if (!(s->pdata->driver_flags & MAX310X_EXT_CLK)) { - unsigned int sts = 0; - - while (tryes--) { - regmap_read(s->regmap, MAX310X_STS_IRQSTS_REG, &sts); - if (sts & MAX310X_STS_CLKREADY_BIT) - break; - } - } + max310x_port_write(port, MAX310X_BRGDIVMSB_REG, (div / 16) >> 8); + max310x_port_write(port, MAX310X_BRGDIVLSB_REG, div / 16); + max310x_port_write(port, MAX310X_BRGCFG_REG, (div % 16) | mode); } static int max310x_update_best_err(unsigned long f, long *besterr) @@ -449,49 +528,49 @@ static int max310x_set_ref_clk(struct max310x_port *s) regmap_write(s->regmap, MAX310X_CLKSRC_REG, clksrc); - if (pllcfg) - max310x_wait_pll(s); - - dev_dbg(s->port.dev, "Reference clock set to %lu Hz\n", bestfreq); + /* Wait for crystal */ + if (pllcfg && !(s->pdata->driver_flags & MAX310X_EXT_CLK)) + msleep(10); return (int)bestfreq; } -static void max310x_handle_rx(struct max310x_port *s, unsigned int rxlen) +static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen) { - unsigned int sts = 0, ch = 0, flag; + unsigned int sts, ch, flag; - if (unlikely(rxlen >= MAX310X_FIFO_SIZE)) { - dev_warn(s->port.dev, "Possible RX FIFO overrun %d\n", rxlen); + if (unlikely(rxlen >= port->fifosize)) { + dev_warn_ratelimited(port->dev, + "Port %i: Possible RX FIFO overrun\n", + port->line); + port->icount.buf_overrun++; /* Ensure sanity of RX level */ - rxlen = MAX310X_FIFO_SIZE; + rxlen = port->fifosize; } - dev_dbg(s->port.dev, "RX Len = %u\n", rxlen); - while (rxlen--) { - regmap_read(s->regmap, MAX310X_RHR_REG, &ch); - regmap_read(s->regmap, MAX310X_LSR_IRQSTS_REG, &sts); + ch = max310x_port_read(port, MAX310X_RHR_REG); + sts = max310x_port_read(port, MAX310X_LSR_IRQSTS_REG); sts &= MAX310X_LSR_RXPAR_BIT | MAX310X_LSR_FRERR_BIT | MAX310X_LSR_RXOVR_BIT | MAX310X_LSR_RXBRK_BIT; - s->port.icount.rx++; + port->icount.rx++; flag = TTY_NORMAL; if (unlikely(sts)) { if (sts & MAX310X_LSR_RXBRK_BIT) { - s->port.icount.brk++; - if (uart_handle_break(&s->port)) + port->icount.brk++; + if (uart_handle_break(port)) continue; } else if (sts & MAX310X_LSR_RXPAR_BIT) - s->port.icount.parity++; + port->icount.parity++; else if (sts & MAX310X_LSR_FRERR_BIT) - s->port.icount.frame++; + port->icount.frame++; else if (sts & MAX310X_LSR_RXOVR_BIT) - s->port.icount.overrun++; + port->icount.overrun++; - sts &= s->port.read_status_mask; + sts &= port->read_status_mask; if (sts & MAX310X_LSR_RXBRK_BIT) flag = TTY_BREAK; else if (sts & MAX310X_LSR_RXPAR_BIT) @@ -502,129 +581,129 @@ static void max310x_handle_rx(struct max310x_port *s, unsigned int rxlen) flag = TTY_OVERRUN; } - if (uart_handle_sysrq_char(s->port, ch)) + if (uart_handle_sysrq_char(port, ch)) continue; - if (sts & s->port.ignore_status_mask) + if (sts & port->ignore_status_mask) continue; - uart_insert_char(&s->port, sts, MAX310X_LSR_RXOVR_BIT, - ch, flag); + uart_insert_char(port, sts, MAX310X_LSR_RXOVR_BIT, ch, flag); } - tty_flip_buffer_push(&s->port.state->port); + tty_flip_buffer_push(&port->state->port); } -static void max310x_handle_tx(struct max310x_port *s) +static void max310x_handle_tx(struct uart_port *port) { - struct circ_buf *xmit = &s->port.state->xmit; - unsigned int txlen = 0, to_send; + struct circ_buf *xmit = &port->state->xmit; + unsigned int txlen, to_send; - if (unlikely(s->port.x_char)) { - regmap_write(s->regmap, MAX310X_THR_REG, s->port.x_char); - s->port.icount.tx++; - s->port.x_char = 0; + if (unlikely(port->x_char)) { + max310x_port_write(port, MAX310X_THR_REG, port->x_char); + port->icount.tx++; + port->x_char = 0; return; } - if (uart_circ_empty(xmit) || uart_tx_stopped(&s->port)) + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) return; /* Get length of data pending in circular buffer */ to_send = uart_circ_chars_pending(xmit); if (likely(to_send)) { /* Limit to size of TX FIFO */ - regmap_read(s->regmap, MAX310X_TXFIFOLVL_REG, &txlen); - txlen = MAX310X_FIFO_SIZE - txlen; + txlen = max310x_port_read(port, MAX310X_TXFIFOLVL_REG); + txlen = port->fifosize - txlen; to_send = (to_send > txlen) ? txlen : to_send; - dev_dbg(s->port.dev, "TX Len = %u\n", to_send); - /* Add data to send */ - s->port.icount.tx += to_send; + port->icount.tx += to_send; while (to_send--) { - regmap_write(s->regmap, MAX310X_THR_REG, - xmit->buf[xmit->tail]); + max310x_port_write(port, MAX310X_THR_REG, + xmit->buf[xmit->tail]); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); }; } if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) - uart_write_wakeup(&s->port); + uart_write_wakeup(port); +} + +static void max310x_port_irq(struct max310x_port *s, int portno) +{ + struct uart_port *port = &s->p[portno].port; + + do { + unsigned int ists, lsr, rxlen; + + /* Read IRQ status & RX FIFO level */ + ists = max310x_port_read(port, MAX310X_IRQSTS_REG); + rxlen = max310x_port_read(port, MAX310X_RXFIFOLVL_REG); + if (!ists && !rxlen) + break; + + if (ists & MAX310X_IRQ_CTS_BIT) { + lsr = max310x_port_read(port, MAX310X_LSR_IRQSTS_REG); + uart_handle_cts_change(port, + !!(lsr & MAX310X_LSR_CTS_BIT)); + } + if (rxlen) + max310x_handle_rx(port, rxlen); + if (ists & MAX310X_IRQ_TXEMPTY_BIT) { + mutex_lock(&s->mutex); + max310x_handle_tx(port); + mutex_unlock(&s->mutex); + } + } while (1); } static irqreturn_t max310x_ist(int irq, void *dev_id) { struct max310x_port *s = (struct max310x_port *)dev_id; - unsigned int ists = 0, lsr = 0, rxlen = 0; - mutex_lock(&s->max310x_mutex); + if (s->uart.nr > 1) { + do { + unsigned int val = ~0; - for (;;) { - /* Read IRQ status & RX FIFO level */ - regmap_read(s->regmap, MAX310X_IRQSTS_REG, &ists); - regmap_read(s->regmap, MAX310X_LSR_IRQSTS_REG, &lsr); - regmap_read(s->regmap, MAX310X_RXFIFOLVL_REG, &rxlen); - if (!ists && !(lsr & MAX310X_LSR_RXTO_BIT) && !rxlen) - break; - - dev_dbg(s->port.dev, "IRQ status: 0x%02x\n", ists); - - if (rxlen) - max310x_handle_rx(s, rxlen); - if (ists & MAX310X_IRQ_TX) - max310x_handle_tx(s); - if (ists & MAX310X_IRQ_CTS_BIT) - uart_handle_cts_change(&s->port, - !!(lsr & MAX310X_LSR_CTS_BIT)); - } - - mutex_unlock(&s->max310x_mutex); + WARN_ON_ONCE(regmap_read(s->regmap, + MAX310X_GLOBALIRQ_REG, &val)); + val = ((1 << s->uart.nr) - 1) & ~val; + if (!val) + break; + max310x_port_irq(s, fls(val) - 1); + } while (1); + } else + max310x_port_irq(s, 0); return IRQ_HANDLED; } static void max310x_wq_proc(struct work_struct *ws) { - struct max310x_port *s = container_of(ws, struct max310x_port, tx_work); + struct max310x_one *one = container_of(ws, struct max310x_one, tx_work); + struct max310x_port *s = dev_get_drvdata(one->port.dev); - mutex_lock(&s->max310x_mutex); - max310x_handle_tx(s); - mutex_unlock(&s->max310x_mutex); + mutex_lock(&s->mutex); + max310x_handle_tx(&one->port); + mutex_unlock(&s->mutex); } static void max310x_start_tx(struct uart_port *port) { - struct max310x_port *s = container_of(port, struct max310x_port, port); + struct max310x_one *one = container_of(port, struct max310x_one, port); - queue_work(s->wq, &s->tx_work); -} - -static void max310x_stop_tx(struct uart_port *port) -{ - /* Do nothing */ -} - -static void max310x_stop_rx(struct uart_port *port) -{ - /* Do nothing */ + if (!work_pending(&one->tx_work)) + schedule_work(&one->tx_work); } static unsigned int max310x_tx_empty(struct uart_port *port) { - unsigned int val = 0; - struct max310x_port *s = container_of(port, struct max310x_port, port); + unsigned int lvl, sts; - mutex_lock(&s->max310x_mutex); - regmap_read(s->regmap, MAX310X_TXFIFOLVL_REG, &val); - mutex_unlock(&s->max310x_mutex); + lvl = max310x_port_read(port, MAX310X_TXFIFOLVL_REG); + sts = max310x_port_read(port, MAX310X_IRQSTS_REG); - return val ? 0 : TIOCSER_TEMT; -} - -static void max310x_enable_ms(struct uart_port *port) -{ - /* Modem status not supported */ + return ((sts & MAX310X_IRQ_TXEMPTY_BIT) && !lvl) ? TIOCSER_TEMT : 0; } static unsigned int max310x_get_mctrl(struct uart_port *port) @@ -644,28 +723,20 @@ static void max310x_set_mctrl(struct uart_port *port, unsigned int mctrl) static void max310x_break_ctl(struct uart_port *port, int break_state) { - struct max310x_port *s = container_of(port, struct max310x_port, port); - - mutex_lock(&s->max310x_mutex); - regmap_update_bits(s->regmap, MAX310X_LCR_REG, - MAX310X_LCR_TXBREAK_BIT, - break_state ? MAX310X_LCR_TXBREAK_BIT : 0); - mutex_unlock(&s->max310x_mutex); + max310x_port_update(port, MAX310X_LCR_REG, + MAX310X_LCR_TXBREAK_BIT, + break_state ? MAX310X_LCR_TXBREAK_BIT : 0); } static void max310x_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { - struct max310x_port *s = container_of(port, struct max310x_port, port); unsigned int lcr, flow = 0; int baud; - mutex_lock(&s->max310x_mutex); - /* Mask termios capabilities we don't support */ termios->c_cflag &= ~CMSPAR; - termios->c_iflag &= ~IXANY; /* Word size */ switch (termios->c_cflag & CSIZE) { @@ -696,7 +767,7 @@ static void max310x_set_termios(struct uart_port *port, lcr |= MAX310X_LCR_STOPLEN_BIT; /* 2 stops */ /* Update LCR register */ - regmap_write(s->regmap, MAX310X_LCR_REG, lcr); + max310x_port_write(port, MAX310X_LCR_REG, lcr); /* Set read status mask */ port->read_status_mask = MAX310X_LSR_RXOVR_BIT; @@ -717,8 +788,8 @@ static void max310x_set_termios(struct uart_port *port, MAX310X_LSR_RXBRK_BIT; /* Configure flow control */ - regmap_write(s->regmap, MAX310X_XON1_REG, termios->c_cc[VSTART]); - regmap_write(s->regmap, MAX310X_XOFF1_REG, termios->c_cc[VSTOP]); + max310x_port_write(port, MAX310X_XON1_REG, termios->c_cc[VSTART]); + max310x_port_write(port, MAX310X_XOFF1_REG, termios->c_cc[VSTOP]); if (termios->c_cflag & CRTSCTS) flow |= MAX310X_FLOWCTRL_AUTOCTS_BIT | MAX310X_FLOWCTRL_AUTORTS_BIT; @@ -728,7 +799,7 @@ static void max310x_set_termios(struct uart_port *port, if (termios->c_iflag & IXOFF) flow |= MAX310X_FLOWCTRL_SWFLOW1_BIT | MAX310X_FLOWCTRL_SWFLOWEN_BIT; - regmap_write(s->regmap, MAX310X_FLOWCTRL_REG, flow); + max310x_port_write(port, MAX310X_FLOWCTRL_REG, flow); /* Get baud rate generator configuration */ baud = uart_get_baud_rate(port, termios, old, @@ -736,36 +807,30 @@ static void max310x_set_termios(struct uart_port *port, port->uartclk / 4); /* Setup baudrate generator */ - max310x_set_baud(s, baud); + max310x_set_baud(port, baud); /* Update timeout according to new baud rate */ uart_update_timeout(port, termios->c_cflag, baud); - - mutex_unlock(&s->max310x_mutex); } static int max310x_startup(struct uart_port *port) { unsigned int val, line = port->line; - struct max310x_port *s = container_of(port, struct max310x_port, port); + struct max310x_port *s = dev_get_drvdata(port->dev); - if (s->pdata->suspend) - s->pdata->suspend(0); - - mutex_lock(&s->max310x_mutex); + s->devtype->power(port, 1); /* Configure baud rate, 9600 as default */ - max310x_set_baud(s, 9600); + max310x_set_baud(port, 9600); /* Configure LCR register, 8N1 mode by default */ - val = MAX310X_LCR_WORD_LEN_8; - regmap_write(s->regmap, MAX310X_LCR_REG, val); + max310x_port_write(port, MAX310X_LCR_REG, MAX310X_LCR_WORD_LEN_8); /* Configure MODE1 register */ - regmap_update_bits(s->regmap, MAX310X_MODE1_REG, - MAX310X_MODE1_TRNSCVCTRL_BIT, - (s->pdata->uart_flags[line] & MAX310X_AUTO_DIR_CTRL) - ? MAX310X_MODE1_TRNSCVCTRL_BIT : 0); + max310x_port_update(port, MAX310X_MODE1_REG, + MAX310X_MODE1_TRNSCVCTRL_BIT, + (s->pdata->uart_flags[line] & MAX310X_AUTO_DIR_CTRL) + ? MAX310X_MODE1_TRNSCVCTRL_BIT : 0); /* Configure MODE2 register */ val = MAX310X_MODE2_RXEMPTINV_BIT; @@ -776,63 +841,40 @@ static int max310x_startup(struct uart_port *port) /* Reset FIFOs */ val |= MAX310X_MODE2_FIFORST_BIT; - regmap_write(s->regmap, MAX310X_MODE2_REG, val); - - /* Configure FIFO trigger level register */ - /* RX FIFO trigger for 16 words, TX FIFO trigger for 64 words */ - val = MAX310X_FIFOTRIGLVL_RX(16) | MAX310X_FIFOTRIGLVL_TX(64); - regmap_write(s->regmap, MAX310X_FIFOTRIGLVL_REG, val); + max310x_port_write(port, MAX310X_MODE2_REG, val); + max310x_port_update(port, MAX310X_MODE2_REG, + MAX310X_MODE2_FIFORST_BIT, 0); /* Configure flow control levels */ /* Flow control halt level 96, resume level 48 */ - val = MAX310X_FLOWLVL_RES(48) | MAX310X_FLOWLVL_HALT(96); - regmap_write(s->regmap, MAX310X_FLOWLVL_REG, val); + max310x_port_write(port, MAX310X_FLOWLVL_REG, + MAX310X_FLOWLVL_RES(48) | MAX310X_FLOWLVL_HALT(96)); - /* Clear timeout register */ - regmap_write(s->regmap, MAX310X_RXTO_REG, 0); + /* Clear IRQ status register */ + max310x_port_read(port, MAX310X_IRQSTS_REG); - /* Configure LSR interrupt enable register */ - /* Enable RX timeout interrupt */ - val = MAX310X_LSR_RXTO_BIT; - regmap_write(s->regmap, MAX310X_LSR_IRQEN_REG, val); - - /* Clear FIFO reset */ - regmap_update_bits(s->regmap, MAX310X_MODE2_REG, - MAX310X_MODE2_FIFORST_BIT, 0); - - /* Clear IRQ status register by reading it */ - regmap_read(s->regmap, MAX310X_IRQSTS_REG, &val); - - /* Configure interrupt enable register */ - /* Enable CTS change interrupt */ - val = MAX310X_IRQ_CTS_BIT; - /* Enable RX, TX interrupts */ - val |= MAX310X_IRQ_RX | MAX310X_IRQ_TX; - regmap_write(s->regmap, MAX310X_IRQEN_REG, val); - - mutex_unlock(&s->max310x_mutex); + /* Enable RX, TX, CTS change interrupts */ + val = MAX310X_IRQ_RXEMPTY_BIT | MAX310X_IRQ_TXEMPTY_BIT; + max310x_port_write(port, MAX310X_IRQEN_REG, val | MAX310X_IRQ_CTS_BIT); return 0; } static void max310x_shutdown(struct uart_port *port) { - struct max310x_port *s = container_of(port, struct max310x_port, port); + struct max310x_port *s = dev_get_drvdata(port->dev); /* Disable all interrupts */ - mutex_lock(&s->max310x_mutex); - regmap_write(s->regmap, MAX310X_IRQEN_REG, 0); - mutex_unlock(&s->max310x_mutex); + max310x_port_write(port, MAX310X_IRQEN_REG, 0); - if (s->pdata->suspend) - s->pdata->suspend(1); + s->devtype->power(port, 0); } static const char *max310x_type(struct uart_port *port) { - struct max310x_port *s = container_of(port, struct max310x_port, port); + struct max310x_port *s = dev_get_drvdata(port->dev); - return (port->type == PORT_MAX310X) ? s->name : NULL; + return (port->type == PORT_MAX310X) ? s->devtype->name : NULL; } static int max310x_request_port(struct uart_port *port) @@ -841,134 +883,100 @@ static int max310x_request_port(struct uart_port *port) return 0; } -static void max310x_release_port(struct uart_port *port) -{ - /* Do nothing */ -} - static void max310x_config_port(struct uart_port *port, int flags) { if (flags & UART_CONFIG_TYPE) port->type = PORT_MAX310X; } -static int max310x_verify_port(struct uart_port *port, struct serial_struct *ser) +static int max310x_verify_port(struct uart_port *port, struct serial_struct *s) { - if ((ser->type == PORT_UNKNOWN) || (ser->type == PORT_MAX310X)) - return 0; - if (ser->irq == port->irq) - return 0; + if ((s->type != PORT_UNKNOWN) && (s->type != PORT_MAX310X)) + return -EINVAL; + if (s->irq != port->irq) + return -EINVAL; - return -EINVAL; + return 0; } -static struct uart_ops max310x_ops = { +static void max310x_null_void(struct uart_port *port) +{ + /* Do nothing */ +} + +static const struct uart_ops max310x_ops = { .tx_empty = max310x_tx_empty, .set_mctrl = max310x_set_mctrl, .get_mctrl = max310x_get_mctrl, - .stop_tx = max310x_stop_tx, + .stop_tx = max310x_null_void, .start_tx = max310x_start_tx, - .stop_rx = max310x_stop_rx, - .enable_ms = max310x_enable_ms, + .stop_rx = max310x_null_void, + .enable_ms = max310x_null_void, .break_ctl = max310x_break_ctl, .startup = max310x_startup, .shutdown = max310x_shutdown, .set_termios = max310x_set_termios, .type = max310x_type, .request_port = max310x_request_port, - .release_port = max310x_release_port, + .release_port = max310x_null_void, .config_port = max310x_config_port, .verify_port = max310x_verify_port, }; -#ifdef CONFIG_PM_SLEEP - -static int max310x_suspend(struct device *dev) +static int __maybe_unused max310x_suspend(struct spi_device *spi, + pm_message_t state) { - int ret; - struct max310x_port *s = dev_get_drvdata(dev); + struct max310x_port *s = dev_get_drvdata(&spi->dev); + int i; - dev_dbg(dev, "Suspend\n"); + for (i = 0; i < s->uart.nr; i++) { + uart_suspend_port(&s->uart, &s->p[i].port); + s->devtype->power(&s->p[i].port, 0); + } - ret = uart_suspend_port(&s->uart, &s->port); - - mutex_lock(&s->max310x_mutex); - - /* Enable sleep mode */ - regmap_update_bits(s->regmap, MAX310X_MODE1_REG, - MAX310X_MODE1_FORCESLEEP_BIT, - MAX310X_MODE1_FORCESLEEP_BIT); - - mutex_unlock(&s->max310x_mutex); - - if (s->pdata->suspend) - s->pdata->suspend(1); - - return ret; + return 0; } -static int max310x_resume(struct device *dev) +static int __maybe_unused max310x_resume(struct spi_device *spi) { - struct max310x_port *s = dev_get_drvdata(dev); + struct max310x_port *s = dev_get_drvdata(&spi->dev); + int i; - dev_dbg(dev, "Resume\n"); + for (i = 0; i < s->uart.nr; i++) { + s->devtype->power(&s->p[i].port, 1); + uart_resume_port(&s->uart, &s->p[i].port); + } - if (s->pdata->suspend) - s->pdata->suspend(0); - - mutex_lock(&s->max310x_mutex); - - /* Disable sleep mode */ - regmap_update_bits(s->regmap, MAX310X_MODE1_REG, - MAX310X_MODE1_FORCESLEEP_BIT, - 0); - - max310x_wait_pll(s); - - mutex_unlock(&s->max310x_mutex); - - return uart_resume_port(&s->uart, &s->port); + return 0; } -static SIMPLE_DEV_PM_OPS(max310x_pm_ops, max310x_suspend, max310x_resume); -#define MAX310X_PM_OPS (&max310x_pm_ops) - -#else -#define MAX310X_PM_OPS NULL -#endif - #ifdef CONFIG_GPIOLIB static int max310x_gpio_get(struct gpio_chip *chip, unsigned offset) { - unsigned int val = 0; + unsigned int val; struct max310x_port *s = container_of(chip, struct max310x_port, gpio); + struct uart_port *port = &s->p[offset / 4].port; - mutex_lock(&s->max310x_mutex); - regmap_read(s->regmap, MAX310X_GPIODATA_REG, &val); - mutex_unlock(&s->max310x_mutex); + val = max310x_port_read(port, MAX310X_GPIODATA_REG); - return !!((val >> 4) & (1 << offset)); + return !!((val >> 4) & (1 << (offset % 4))); } static void max310x_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { struct max310x_port *s = container_of(chip, struct max310x_port, gpio); + struct uart_port *port = &s->p[offset / 4].port; - mutex_lock(&s->max310x_mutex); - regmap_update_bits(s->regmap, MAX310X_GPIODATA_REG, 1 << offset, value ? - 1 << offset : 0); - mutex_unlock(&s->max310x_mutex); + max310x_port_update(port, MAX310X_GPIODATA_REG, 1 << (offset % 4), + value ? 1 << (offset % 4) : 0); } static int max310x_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { struct max310x_port *s = container_of(chip, struct max310x_port, gpio); + struct uart_port *port = &s->p[offset / 4].port; - mutex_lock(&s->max310x_mutex); - - regmap_update_bits(s->regmap, MAX310X_GPIOCFG_REG, 1 << offset, 0); - - mutex_unlock(&s->max310x_mutex); + max310x_port_update(port, MAX310X_GPIOCFG_REG, 1 << (offset % 4), 0); return 0; } @@ -977,74 +985,42 @@ static int max310x_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value) { struct max310x_port *s = container_of(chip, struct max310x_port, gpio); + struct uart_port *port = &s->p[offset / 4].port; - mutex_lock(&s->max310x_mutex); - - regmap_update_bits(s->regmap, MAX310X_GPIOCFG_REG, 1 << offset, - 1 << offset); - regmap_update_bits(s->regmap, MAX310X_GPIODATA_REG, 1 << offset, value ? - 1 << offset : 0); - - mutex_unlock(&s->max310x_mutex); + max310x_port_update(port, MAX310X_GPIODATA_REG, 1 << (offset % 4), + value ? 1 << (offset % 4) : 0); + max310x_port_update(port, MAX310X_GPIOCFG_REG, 1 << (offset % 4), + 1 << (offset % 4)); return 0; } #endif -/* Generic platform data */ -static struct max310x_pdata generic_plat_data = { - .driver_flags = MAX310X_EXT_CLK, - .uart_flags[0] = MAX310X_ECHO_SUPRESS, - .frequency = 26000000, -}; - -static int max310x_probe(struct spi_device *spi) +static int max310x_probe(struct device *dev, int is_spi, + struct max310x_devtype *devtype, int irq) { struct max310x_port *s; - struct device *dev = &spi->dev; - int chiptype = spi_get_device_id(spi)->driver_data; - struct max310x_pdata *pdata = dev->platform_data; - unsigned int val = 0; - int ret; + struct max310x_pdata *pdata = dev_get_platdata(dev); + int i, ret, uartclk; /* Check for IRQ */ - if (spi->irq <= 0) { + if (irq <= 0) { dev_err(dev, "No IRQ specified\n"); return -ENOTSUPP; } + if (!pdata) { + dev_err(dev, "No platform data supplied\n"); + return -EINVAL; + } + /* Alloc port structure */ - s = devm_kzalloc(dev, sizeof(struct max310x_port), GFP_KERNEL); + s = devm_kzalloc(dev, sizeof(*s) + + sizeof(struct max310x_one) * devtype->nr, GFP_KERNEL); if (!s) { dev_err(dev, "Error allocating port structure\n"); return -ENOMEM; } - dev_set_drvdata(dev, s); - - if (!pdata) { - dev_warn(dev, "No platform data supplied, using defaults\n"); - pdata = &generic_plat_data; - } - s->pdata = pdata; - - /* Individual chip settings */ - switch (chiptype) { - case MAX310X_TYPE_MAX3107: - s->name = "MAX3107"; - s->nr_gpio = 4; - s->uart.nr = 1; - s->regcfg.max_register = 0x1f; - break; - case MAX310X_TYPE_MAX3108: - s->name = "MAX3108"; - s->nr_gpio = 4; - s->uart.nr = 1; - s->regcfg.max_register = 0x1e; - break; - default: - dev_err(dev, "Unsupported chip type %i\n", chiptype); - return -ENOTSUPP; - } /* Check input frequency */ if ((pdata->driver_flags & MAX310X_EXT_CLK) && @@ -1055,13 +1031,11 @@ static int max310x_probe(struct spi_device *spi) ((pdata->frequency < 1000000) || (pdata->frequency > 4000000))) goto err_freq; - mutex_init(&s->max310x_mutex); + s->pdata = pdata; + s->devtype = devtype; + dev_set_drvdata(dev, s); - /* Setup SPI bus */ - spi->mode = SPI_MODE_0; - spi->bits_per_word = 8; - spi->max_speed_hz = 26000000; - spi_setup(spi); + mutex_init(&s->mutex); /* Setup regmap */ s->regcfg.reg_bits = 8; @@ -1069,109 +1043,100 @@ static int max310x_probe(struct spi_device *spi) s->regcfg.read_flag_mask = 0x00; s->regcfg.write_flag_mask = 0x80; s->regcfg.cache_type = REGCACHE_RBTREE; - s->regcfg.writeable_reg = max3107_8_reg_writeable; + s->regcfg.writeable_reg = max310x_reg_writeable; s->regcfg.volatile_reg = max310x_reg_volatile; s->regcfg.precious_reg = max310x_reg_precious; - s->regmap = devm_regmap_init_spi(spi, &s->regcfg); + s->regcfg.max_register = devtype->nr * 0x20 - 1; + + if (IS_ENABLED(CONFIG_SPI_MASTER) && is_spi) { + struct spi_device *spi = to_spi_device(dev); + + s->regmap = devm_regmap_init_spi(spi, &s->regcfg); + } else + return -ENOTSUPP; + if (IS_ERR(s->regmap)) { - ret = PTR_ERR(s->regmap); dev_err(dev, "Failed to initialize register map\n"); - goto err_out; - } - - /* Reset chip & check SPI function */ - ret = regmap_write(s->regmap, MAX310X_MODE2_REG, MAX310X_MODE2_RST_BIT); - if (ret) { - dev_err(dev, "SPI transfer failed\n"); - goto err_out; - } - /* Clear chip reset */ - regmap_write(s->regmap, MAX310X_MODE2_REG, 0); - - switch (chiptype) { - case MAX310X_TYPE_MAX3107: - /* Check REV ID to ensure we are talking to what we expect */ - regmap_read(s->regmap, MAX3107_REVID_REG, &val); - if (((val & MAX3107_REV_MASK) != MAX3107_REV_ID)) { - dev_err(dev, "%s ID 0x%02x does not match\n", - s->name, val); - ret = -ENODEV; - goto err_out; - } - break; - case MAX310X_TYPE_MAX3108: - /* MAX3108 have not REV ID register, we just check default value - * from clocksource register to make sure everything works. - */ - regmap_read(s->regmap, MAX310X_CLKSRC_REG, &val); - if (val != (MAX310X_CLKSRC_EXTCLK_BIT | - MAX310X_CLKSRC_PLLBYP_BIT)) { - dev_err(dev, "%s not present\n", s->name); - ret = -ENODEV; - goto err_out; - } - break; + return PTR_ERR(s->regmap); } /* Board specific configure */ - if (pdata->init) - pdata->init(); - if (pdata->suspend) - pdata->suspend(0); + if (s->pdata->init) + s->pdata->init(); - /* Calculate referecne clock */ - s->uartclk = max310x_set_ref_clk(s); + /* Check device to ensure we are talking to what we expect */ + ret = devtype->detect(dev); + if (ret) + return ret; - /* Disable all interrupts */ - regmap_write(s->regmap, MAX310X_IRQEN_REG, 0); + for (i = 0; i < devtype->nr; i++) { + unsigned int offs = i << 5; - /* Setup MODE1 register */ - val = MAX310X_MODE1_IRQSEL_BIT; /* Enable IRQ pin */ - if (pdata->driver_flags & MAX310X_AUTOSLEEP) - val = MAX310X_MODE1_AUTOSLEEP_BIT; - regmap_write(s->regmap, MAX310X_MODE1_REG, val); + /* Reset port */ + regmap_write(s->regmap, MAX310X_MODE2_REG + offs, + MAX310X_MODE2_RST_BIT); + /* Clear port reset */ + regmap_write(s->regmap, MAX310X_MODE2_REG + offs, 0); - /* Setup interrupt */ - ret = devm_request_threaded_irq(dev, spi->irq, NULL, max310x_ist, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - dev_name(dev), s); - if (ret) { - dev_err(dev, "Unable to reguest IRQ %i\n", spi->irq); - goto err_out; + /* Wait for port startup */ + do { + regmap_read(s->regmap, + MAX310X_BRGDIVLSB_REG + offs, &ret); + } while (ret != 0x01); + + regmap_update_bits(s->regmap, MAX310X_MODE1_REG + offs, + MAX310X_MODE1_AUTOSLEEP_BIT, + MAX310X_MODE1_AUTOSLEEP_BIT); } + uartclk = max310x_set_ref_clk(s); + dev_dbg(dev, "Reference clock set to %i Hz\n", uartclk); + /* Register UART driver */ s->uart.owner = THIS_MODULE; - s->uart.driver_name = dev_name(dev); s->uart.dev_name = "ttyMAX"; s->uart.major = MAX310X_MAJOR; s->uart.minor = MAX310X_MINOR; + s->uart.nr = devtype->nr; ret = uart_register_driver(&s->uart); if (ret) { dev_err(dev, "Registering UART driver failed\n"); - goto err_out; + return ret; } - /* Initialize workqueue for start TX */ - s->wq = create_freezable_workqueue(dev_name(dev)); - INIT_WORK(&s->tx_work, max310x_wq_proc); - - /* Initialize UART port data */ - s->port.line = 0; - s->port.dev = dev; - s->port.irq = spi->irq; - s->port.type = PORT_MAX310X; - s->port.fifosize = MAX310X_FIFO_SIZE; - s->port.flags = UPF_SKIP_TEST | UPF_FIXED_TYPE; - s->port.iotype = UPIO_PORT; - s->port.membase = (void __iomem *)0xffffffff; /* Bogus value */ - s->port.uartclk = s->uartclk; - s->port.ops = &max310x_ops; - uart_add_one_port(&s->uart, &s->port); + for (i = 0; i < devtype->nr; i++) { + /* Initialize port data */ + s->p[i].port.line = i; + s->p[i].port.dev = dev; + s->p[i].port.irq = irq; + s->p[i].port.type = PORT_MAX310X; + s->p[i].port.fifosize = MAX310X_FIFO_SIZE; + s->p[i].port.flags = UPF_SKIP_TEST | UPF_FIXED_TYPE | + UPF_LOW_LATENCY; + s->p[i].port.iotype = UPIO_PORT; + s->p[i].port.iobase = i * 0x20; + s->p[i].port.membase = (void __iomem *)~0; + s->p[i].port.uartclk = uartclk; + s->p[i].port.ops = &max310x_ops; + /* Disable all interrupts */ + max310x_port_write(&s->p[i].port, MAX310X_IRQEN_REG, 0); + /* Clear IRQ status register */ + max310x_port_read(&s->p[i].port, MAX310X_IRQSTS_REG); + /* Enable IRQ pin */ + max310x_port_update(&s->p[i].port, MAX310X_MODE1_REG, + MAX310X_MODE1_IRQSEL_BIT, + MAX310X_MODE1_IRQSEL_BIT); + /* Initialize queue for start TX */ + INIT_WORK(&s->p[i].tx_work, max310x_wq_proc); + /* Register port */ + uart_add_one_port(&s->uart, &s->p[i].port); + /* Go to suspend mode */ + devtype->power(&s->p[i].port, 0); + } #ifdef CONFIG_GPIOLIB /* Setup GPIO cotroller */ - if (pdata->gpio_base) { + if (s->pdata->gpio_base) { s->gpio.owner = THIS_MODULE; s->gpio.dev = dev; s->gpio.label = dev_name(dev); @@ -1179,86 +1144,105 @@ static int max310x_probe(struct spi_device *spi) s->gpio.get = max310x_gpio_get; s->gpio.direction_output= max310x_gpio_direction_output; s->gpio.set = max310x_gpio_set; - s->gpio.base = pdata->gpio_base; - s->gpio.ngpio = s->nr_gpio; + s->gpio.base = s->pdata->gpio_base; + s->gpio.ngpio = devtype->nr * 4; s->gpio.can_sleep = 1; - if (gpiochip_add(&s->gpio)) { - /* Indicate that we should not call gpiochip_remove */ - s->gpio.base = 0; - } + if (!gpiochip_add(&s->gpio)) + s->gpio_used = 1; } else dev_info(dev, "GPIO support not enabled\n"); #endif - /* Go to suspend mode */ - if (pdata->suspend) - pdata->suspend(1); + /* Setup interrupt */ + ret = devm_request_threaded_irq(dev, irq, NULL, max310x_ist, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + dev_name(dev), s); + if (ret) { + dev_err(dev, "Unable to reguest IRQ %i\n", irq); +#ifdef CONFIG_GPIOLIB + if (s->gpio_used) + WARN_ON(gpiochip_remove(&s->gpio)); +#endif + } - return 0; + return ret; err_freq: dev_err(dev, "Frequency parameter incorrect\n"); - ret = -EINVAL; - -err_out: - dev_set_drvdata(dev, NULL); - - return ret; + return -EINVAL; } -static int max310x_remove(struct spi_device *spi) +static int max310x_remove(struct device *dev) { - struct device *dev = &spi->dev; struct max310x_port *s = dev_get_drvdata(dev); - int ret = 0; + int i, ret = 0; - dev_dbg(dev, "Removing port\n"); - - devm_free_irq(dev, s->port.irq, s); - - destroy_workqueue(s->wq); - - uart_remove_one_port(&s->uart, &s->port); + for (i = 0; i < s->uart.nr; i++) { + cancel_work_sync(&s->p[i].tx_work); + uart_remove_one_port(&s->uart, &s->p[i].port); + s->devtype->power(&s->p[i].port, 0); + } uart_unregister_driver(&s->uart); #ifdef CONFIG_GPIOLIB - if (s->pdata->gpio_base) { + if (s->gpio_used) ret = gpiochip_remove(&s->gpio); - if (ret) - dev_err(dev, "Failed to remove gpio chip: %d\n", ret); - } #endif - dev_set_drvdata(dev, NULL); - - if (s->pdata->suspend) - s->pdata->suspend(1); if (s->pdata->exit) s->pdata->exit(); return ret; } +#ifdef CONFIG_SPI_MASTER +static int max310x_spi_probe(struct spi_device *spi) +{ + struct max310x_devtype *devtype = + (struct max310x_devtype *)spi_get_device_id(spi)->driver_data; + int ret; + + /* Setup SPI bus */ + spi->bits_per_word = 8; + spi->mode = spi->mode ? : SPI_MODE_0; + spi->max_speed_hz = spi->max_speed_hz ? : 26000000; + ret = spi_setup(spi); + if (ret) { + dev_err(&spi->dev, "SPI setup failed\n"); + return ret; + } + + return max310x_probe(&spi->dev, 1, devtype, spi->irq); +} + +static int max310x_spi_remove(struct spi_device *spi) +{ + return max310x_remove(&spi->dev); +} + +static SIMPLE_DEV_PM_OPS(max310x_pm_ops, max310x_suspend, max310x_resume); + static const struct spi_device_id max310x_id_table[] = { - { "max3107", MAX310X_TYPE_MAX3107 }, - { "max3108", MAX310X_TYPE_MAX3108 }, + { "max3107", (kernel_ulong_t)&max3107_devtype, }, + { "max3108", (kernel_ulong_t)&max3108_devtype, }, { } }; MODULE_DEVICE_TABLE(spi, max310x_id_table); -static struct spi_driver max310x_driver = { +static struct spi_driver max310x_uart_driver = { .driver = { - .name = "max310x", + .name = MAX310X_NAME, .owner = THIS_MODULE, - .pm = MAX310X_PM_OPS, + .pm = &max310x_pm_ops, }, - .probe = max310x_probe, - .remove = max310x_remove, + .probe = max310x_spi_probe, + .remove = max310x_spi_remove, .id_table = max310x_id_table, }; -module_spi_driver(max310x_driver); +module_spi_driver(max310x_uart_driver); +#endif -MODULE_LICENSE("GPL v2"); +MODULE_LICENSE("GPL"); MODULE_AUTHOR("Alexander Shiyan "); MODULE_DESCRIPTION("MAX310X serial driver"); diff --git a/include/linux/platform_data/max310x.h b/include/linux/platform_data/max310x.h index 91648bf5fc5c..1aec0b620ac3 100644 --- a/include/linux/platform_data/max310x.h +++ b/include/linux/platform_data/max310x.h @@ -42,9 +42,8 @@ /* MAX310X platform data structure */ struct max310x_pdata { /* Flags global to driver */ - const u8 driver_flags:2; + const u8 driver_flags; #define MAX310X_EXT_CLK (0x00000001) /* External clock enable */ -#define MAX310X_AUTOSLEEP (0x00000002) /* Enable AutoSleep mode */ /* Flags global to UART port */ const u8 uart_flags[MAX310X_MAX_UARTS]; #define MAX310X_LOOPBACK (0x00000001) /* Loopback mode enable */ @@ -60,8 +59,6 @@ struct max310x_pdata { void (*init)(void); /* Called before finish */ void (*exit)(void); - /* Suspend callback */ - void (*suspend)(int do_suspend); }; #endif From 21fc509f1194c2fa06eff4c72238210089c29453 Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Sat, 29 Jun 2013 10:44:18 +0400 Subject: [PATCH 0864/3400] serial: max310x: Add MAX3109 support This patch adds support for MAX3109 (advanced dual universal asynchronous receiver-transmitter) into max310x driver. Signed-off-by: Alexander Shiyan Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/Kconfig | 2 +- drivers/tty/serial/max310x.c | 35 ++++++++++++++++++++++++--- include/linux/platform_data/max310x.h | 4 +-- 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 25772c15276d..8e1a9c53ad7f 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -297,7 +297,7 @@ config SERIAL_MAX310X default n help This selects support for an advanced UART from Maxim (Dallas). - Supported ICs are MAX3107, MAX3108. + Supported ICs are MAX3107, MAX3108, MAX3109. Each IC contains 128 words each of receive and transmit FIFO that can be controlled through I2C or high-speed SPI. diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index 4620289e9e49..a6c46427363b 100644 --- a/drivers/tty/serial/max310x.c +++ b/drivers/tty/serial/max310x.c @@ -1,5 +1,5 @@ /* - * Maxim (Dallas) MAX3107/8 serial driver + * Maxim (Dallas) MAX3107/8/9 serial driver * * Copyright (C) 2012-2013 Alexander Shiyan * @@ -13,9 +13,6 @@ * (at your option) any later version. */ -/* TODO: MAX3109 support (Dual) */ -/* TODO: MAX14830 support (Quad) */ - #include #include #include @@ -269,6 +266,9 @@ /* MAX3107 specific */ #define MAX3107_REV_ID (0xa0) +/* MAX3109 specific */ +#define MAX3109_REV_ID (0xc0) + struct max310x_devtype { char name[9]; int nr; @@ -359,6 +359,25 @@ static int max3108_detect(struct device *dev) return 0; } +static int max3109_detect(struct device *dev) +{ + struct max310x_port *s = dev_get_drvdata(dev); + unsigned int val = 0; + int ret; + + ret = regmap_read(s->regmap, MAX310X_REVID_REG, &val); + if (ret) + return ret; + + if (((val & MAX310x_REV_MASK) != MAX3109_REV_ID)) { + dev_err(dev, + "%s ID 0x%02x does not match\n", s->devtype->name, val); + return -ENODEV; + } + + return 0; +} + static void max310x_power(struct uart_port *port, int on) { max310x_port_update(port, MAX310X_MODE1_REG, @@ -382,6 +401,13 @@ static const struct max310x_devtype max3108_devtype = { .power = max310x_power, }; +static const struct max310x_devtype max3109_devtype = { + .name = "MAX3109", + .nr = 2, + .detect = max3109_detect, + .power = max310x_power, +}; + static bool max310x_reg_writeable(struct device *dev, unsigned int reg) { switch (reg & 0x1f) { @@ -1226,6 +1252,7 @@ static SIMPLE_DEV_PM_OPS(max310x_pm_ops, max310x_suspend, max310x_resume); static const struct spi_device_id max310x_id_table[] = { { "max3107", (kernel_ulong_t)&max3107_devtype, }, { "max3108", (kernel_ulong_t)&max3108_devtype, }, + { "max3109", (kernel_ulong_t)&max3109_devtype, }, { } }; MODULE_DEVICE_TABLE(spi, max310x_id_table); diff --git a/include/linux/platform_data/max310x.h b/include/linux/platform_data/max310x.h index 1aec0b620ac3..4c128eda26ba 100644 --- a/include/linux/platform_data/max310x.h +++ b/include/linux/platform_data/max310x.h @@ -1,5 +1,5 @@ /* - * Maxim (Dallas) MAX3107/8 serial driver + * Maxim (Dallas) MAX3107/8/9 serial driver * * Copyright (C) 2012 Alexander Shiyan * @@ -37,7 +37,7 @@ * }; */ -#define MAX310X_MAX_UARTS 1 +#define MAX310X_MAX_UARTS 2 /* MAX310X platform data structure */ struct max310x_pdata { From 003236d9ac4d02721867e47f7ad4371ab7f74689 Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Sat, 29 Jun 2013 10:44:19 +0400 Subject: [PATCH 0865/3400] serial: max310x: Add MAX14830 support This patch adds support for MAX14830 (advanced quad universal asynchronous receiver-transmitter) into max310x driver. Signed-off-by: Alexander Shiyan Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/Kconfig | 2 +- drivers/tty/serial/max310x.c | 45 ++++++++++++++++++++++++++- include/linux/platform_data/max310x.h | 4 +-- 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 8e1a9c53ad7f..bc486deeeae5 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -297,7 +297,7 @@ config SERIAL_MAX310X default n help This selects support for an advanced UART from Maxim (Dallas). - Supported ICs are MAX3107, MAX3108, MAX3109. + Supported ICs are MAX3107, MAX3108, MAX3109, MAX14830. Each IC contains 128 words each of receive and transmit FIFO that can be controlled through I2C or high-speed SPI. diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index a6c46427363b..4ab5b272a593 100644 --- a/drivers/tty/serial/max310x.c +++ b/drivers/tty/serial/max310x.c @@ -1,5 +1,5 @@ /* - * Maxim (Dallas) MAX3107/8/9 serial driver + * Maxim (Dallas) MAX3107/8/9, MAX14830 serial driver * * Copyright (C) 2012-2013 Alexander Shiyan * @@ -269,6 +269,10 @@ /* MAX3109 specific */ #define MAX3109_REV_ID (0xc0) +/* MAX14830 specific */ +#define MAX14830_BRGCFG_CLKDIS_BIT (1 << 6) /* Clock Disable */ +#define MAX14830_REV_ID (0xb0) + struct max310x_devtype { char name[9]; int nr; @@ -387,6 +391,37 @@ static void max310x_power(struct uart_port *port, int on) msleep(50); } +static int max14830_detect(struct device *dev) +{ + struct max310x_port *s = dev_get_drvdata(dev); + unsigned int val = 0; + int ret; + + ret = regmap_write(s->regmap, MAX310X_GLOBALCMD_REG, + MAX310X_EXTREG_ENBL); + if (ret) + return ret; + + regmap_read(s->regmap, MAX310X_REVID_EXTREG, &val); + regmap_write(s->regmap, MAX310X_GLOBALCMD_REG, MAX310X_EXTREG_DSBL); + if (((val & MAX310x_REV_MASK) != MAX14830_REV_ID)) { + dev_err(dev, + "%s ID 0x%02x does not match\n", s->devtype->name, val); + return -ENODEV; + } + + return 0; +} + +static void max14830_power(struct uart_port *port, int on) +{ + max310x_port_update(port, MAX310X_BRGCFG_REG, + MAX14830_BRGCFG_CLKDIS_BIT, + on ? 0 : MAX14830_BRGCFG_CLKDIS_BIT); + if (on) + msleep(50); +} + static const struct max310x_devtype max3107_devtype = { .name = "MAX3107", .nr = 1, @@ -408,6 +443,13 @@ static const struct max310x_devtype max3109_devtype = { .power = max310x_power, }; +static const struct max310x_devtype max14830_devtype = { + .name = "MAX14830", + .nr = 4, + .detect = max14830_detect, + .power = max14830_power, +}; + static bool max310x_reg_writeable(struct device *dev, unsigned int reg) { switch (reg & 0x1f) { @@ -1253,6 +1295,7 @@ static const struct spi_device_id max310x_id_table[] = { { "max3107", (kernel_ulong_t)&max3107_devtype, }, { "max3108", (kernel_ulong_t)&max3108_devtype, }, { "max3109", (kernel_ulong_t)&max3109_devtype, }, + { "max14830", (kernel_ulong_t)&max14830_devtype, }, { } }; MODULE_DEVICE_TABLE(spi, max310x_id_table); diff --git a/include/linux/platform_data/max310x.h b/include/linux/platform_data/max310x.h index 4c128eda26ba..dd11dcd1a184 100644 --- a/include/linux/platform_data/max310x.h +++ b/include/linux/platform_data/max310x.h @@ -1,5 +1,5 @@ /* - * Maxim (Dallas) MAX3107/8/9 serial driver + * Maxim (Dallas) MAX3107/8/9, MAX14830 serial driver * * Copyright (C) 2012 Alexander Shiyan * @@ -37,7 +37,7 @@ * }; */ -#define MAX310X_MAX_UARTS 2 +#define MAX310X_MAX_UARTS 4 /* MAX310X platform data structure */ struct max310x_pdata { From 972ce08578e0db8663740faea420699c01729f41 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Mon, 1 Jul 2013 09:14:21 +0200 Subject: [PATCH 0866/3400] 8250_pci: improve code comments and Kconfig help The recent regression about NetMos 9835 Multi-I/O boards indicates that comment pointing to the parport_serial driver could be helpful. Signed-off-by: Stefan Seyfried Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pci.c | 6 ++++++ drivers/tty/serial/8250/Kconfig | 2 ++ 2 files changed, 8 insertions(+) diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index c52948b368d8..c626c4fcf9b8 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -4797,6 +4797,12 @@ static struct pci_device_id serial_pci_tbl[] = { PCI_VENDOR_ID_IBM, 0x0299, 0, 0, pbn_b0_bt_2_115200 }, + /* + * other NetMos 9835 devices are most likely handled by the + * parport_serial driver, check drivers/parport/parport_serial.c + * before adding them here. + */ + { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9901, 0xA000, 0x1000, 0, 0, pbn_b0_1_115200 }, diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index a1ba94d64885..f3b306efaa59 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -116,6 +116,8 @@ config SERIAL_8250_PCI This builds standard PCI serial support. You may be able to disable this feature if you only need legacy serial support. Saves about 9K. + Note that serial ports on NetMos 9835 Multi-I/O cards are handled + by the parport_serial driver, enabled with CONFIG_PARPORT_SERIAL. config SERIAL_8250_HP300 tristate From f64ffda60e2c9b69ff2125e90cfca234b2eece2b Mon Sep 17 00:00:00 2001 From: "Govindraj.R" Date: Fri, 5 Jul 2013 18:25:59 +0300 Subject: [PATCH 0867/3400] OMAP2+: UART: enable tx wakeup bit for wer reg wer has TX wakeup bit available enable the same by populating the necessary tx wakeup flag for the applicable module ip blocks and use the same while configuaring wer reg. Also wer is not context restored, restore wer when context is lost. Cc: Paul Walmsley Cc: Felipe Balbi Cc: Kevin Hilman Acked-by: Greg Kroah-Hartman (for drivers/tty changes) Signed-off-by: Govindraj.R Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/omap-serial.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index eacb0def3d96..33c758e09d86 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -51,6 +51,11 @@ #define OMAP_UART_REV_52 0x0502 #define OMAP_UART_REV_63 0x0603 +#define OMAP_UART_TX_WAKEUP_EN BIT(7) + +/* Feature flags */ +#define OMAP_UART_WER_HAS_TX_WAKEUP BIT(0) + #define UART_ERRATA_i202_MDR1_ACCESS BIT(0) #define UART_ERRATA_i291_DMA_FORCEIDLE BIT(1) @@ -136,6 +141,7 @@ struct uart_omap_port { unsigned char dlh; unsigned char mdr1; unsigned char scr; + unsigned char wer; int use_dma; /* @@ -150,6 +156,7 @@ struct uart_omap_port { int context_loss_cnt; u32 errata; u8 wakeups_enabled; + u32 features; int DTR_gpio; int DTR_inverted; @@ -681,7 +688,11 @@ static int serial_omap_startup(struct uart_port *port) serial_out(up, UART_IER, up->ier); /* Enable module level wake up */ - serial_out(up, UART_OMAP_WER, OMAP_UART_WER_MOD_WKUP); + up->wer = OMAP_UART_WER_MOD_WKUP; + if (up->features & OMAP_UART_WER_HAS_TX_WAKEUP) + up->wer |= OMAP_UART_TX_WAKEUP_EN; + + serial_out(up, UART_OMAP_WER, up->wer); pm_runtime_mark_last_busy(up->dev); pm_runtime_put_autosuspend(up->dev); @@ -1371,9 +1382,11 @@ static void omap_serial_fill_features_erratas(struct uart_omap_port *up) case OMAP_UART_REV_52: up->errata |= (UART_ERRATA_i202_MDR1_ACCESS | UART_ERRATA_i291_DMA_FORCEIDLE); + up->features |= OMAP_UART_WER_HAS_TX_WAKEUP; break; case OMAP_UART_REV_63: up->errata |= UART_ERRATA_i202_MDR1_ACCESS; + up->features |= OMAP_UART_WER_HAS_TX_WAKEUP; break; default: break; @@ -1600,6 +1613,7 @@ static void serial_omap_restore_context(struct uart_omap_port *up) serial_omap_mdr1_errataset(up, up->mdr1); else serial_out(up, UART_OMAP_MDR1, up->mdr1); + serial_out(up, UART_OMAP_WER, up->wer); } static int serial_omap_runtime_suspend(struct device *dev) From c4415084218c68c5ee2fc583431e89a78d896b19 Mon Sep 17 00:00:00 2001 From: Dmitry Fink Date: Mon, 8 Jul 2013 13:04:44 +0300 Subject: [PATCH 0868/3400] OMAP: UART: Keep the TX fifo full when possible Current logic results in interrupt storm since the fifo is constantly below the threshold level. Change the logic to fill all the available spaces in the fifo as long as we have data to minimize the possibilty of underflow and elimiate excessive interrupts. Signed-off-by: Dmitry Fink Signed-off-by: Alexander Savchenko Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/omap-serial.c | 3 ++- include/uapi/linux/serial_reg.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 33c758e09d86..9271a1dceec3 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -315,7 +315,8 @@ static void transmit_chars(struct uart_omap_port *up, unsigned int lsr) serial_omap_stop_tx(&up->port); return; } - count = up->port.fifosize / 4; + count = up->port.fifosize - + (serial_in(up, UART_OMAP_TXFIFO_LVL) & 0xFF); do { serial_out(up, UART_TX, xmit->buf[xmit->tail]); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); diff --git a/include/uapi/linux/serial_reg.h b/include/uapi/linux/serial_reg.h index e6322605b138..97c26beae605 100644 --- a/include/uapi/linux/serial_reg.h +++ b/include/uapi/linux/serial_reg.h @@ -366,6 +366,7 @@ #define UART_OMAP_MDR1_FIR_MODE 0x05 /* FIR mode */ #define UART_OMAP_MDR1_CIR_MODE 0x06 /* CIR mode */ #define UART_OMAP_MDR1_DISABLE 0x07 /* Disable (default state) */ +#define UART_OMAP_TXFIFO_LVL 0x1A /* TX FIFO fullness */ /* * These are definitions for the Exar XR17V35X and XR17(C|D)15X From 76bac1987ca181d54f8c9456d20997cb1020af2d Mon Sep 17 00:00:00 2001 From: Ruchika Kharwar Date: Mon, 8 Jul 2013 10:28:57 +0300 Subject: [PATCH 0869/3400] OMAP: UART: Fix the revision register read. The revision register is a 32 bit register. The serial_in() function reads only the lower 16 bits of the register. This leads to an incorrect computation of the Module revision. Signed-off-by: Ruchika Kharwar [oleksandr.savchenko@ti.com: add some whitespaces] Signed-off-by: Alexander Savchenko Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/omap-serial.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 9271a1dceec3..9b6fc54967f2 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -1344,7 +1344,7 @@ static void omap_serial_fill_features_erratas(struct uart_omap_port *up) u32 mvr, scheme; u16 revision, major, minor; - mvr = serial_in(up, UART_OMAP_MVER); + mvr = readl(up->port.membase + (UART_OMAP_MVER << up->port.regshift)); /* Check revision register scheme */ scheme = mvr >> OMAP_UART_MVR_SCHEME_SHIFT; From a0a490f9df2bf7e077054c78221c6b5301681de6 Mon Sep 17 00:00:00 2001 From: Vikram Pandita Date: Mon, 8 Jul 2013 10:25:43 +0300 Subject: [PATCH 0870/3400] serial: omap: Initialize platform_data Otherwise serial driver would crash accessing platform_data that was not initialized in functions like: serial_omap_pm(...) ... if (!state && pdata->enable_wakeup) ^^^^^^^ ... Signed-off-by: Vikram Pandita Signed-off-by: Alexander Savchenko Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/omap-serial.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 9b6fc54967f2..72bb690829af 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -1414,8 +1414,10 @@ static int serial_omap_probe(struct platform_device *pdev) struct omap_uart_port_info *omap_up_info = pdev->dev.platform_data; int ret; - if (pdev->dev.of_node) + if (pdev->dev.of_node) { omap_up_info = of_get_uart_port_info(&pdev->dev); + pdev->dev.platform_data = omap_up_info; + } mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!mem) { From 908fd7e566b4c12e36e4487d2d5946de5e5ea30f Mon Sep 17 00:00:00 2001 From: Ruchika Kharwar Date: Wed, 17 Jul 2013 16:29:13 +0300 Subject: [PATCH 0871/3400] serial: omap: Fix IRQ handling return value Ensure the Interrupt handling routine return IRQ_HANDLED vs IRQ_NONE. Signed-off-by: Ruchika Kharwar Signed-off-by: Alexander Savchenko Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/omap-serial.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 72bb690829af..b0802149b3e7 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -485,7 +485,6 @@ static irqreturn_t serial_omap_irq(int irq, void *dev_id) struct uart_omap_port *up = dev_id; unsigned int iir, lsr; unsigned int type; - irqreturn_t ret = IRQ_NONE; int max_count = 256; spin_lock(&up->port.lock); @@ -496,7 +495,6 @@ static irqreturn_t serial_omap_irq(int irq, void *dev_id) if (iir & UART_IIR_NO_INT) break; - ret = IRQ_HANDLED; lsr = serial_in(up, UART_LSR); /* extract IRQ type from IIR register */ @@ -535,7 +533,7 @@ static irqreturn_t serial_omap_irq(int irq, void *dev_id) pm_runtime_put_autosuspend(up->dev); up->port_activity = jiffies; - return ret; + return IRQ_HANDLED; } static unsigned int serial_omap_tx_empty(struct uart_port *port) From bc764b8fdb4346cb21f624e08231267d0ea9578b Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Mon, 8 Jul 2013 15:53:38 +0800 Subject: [PATCH 0872/3400] serial: fsl_lpuart: restore UARTCR2 after watermark setup is done Function lpuart_setup_watermark() clears some bits in register UARTCR2 before writing FIFO configuration registers as required by hardware. But it should restore UARTCR2 after that. Otherwise, we end up changing UARTCR2 register when setting up watermark, and that is not really desirable. At least, when low-level debug and earlyprint is enabled, serial console is broken due to it. Fix the problem by restoring UARTCR2 register at the end of function lpuart_setup_watermark(). Signed-off-by: Shawn Guo Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/fsl_lpuart.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index 263cfaabe9e2..7bc17f21062a 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -342,8 +342,10 @@ static void lpuart_break_ctl(struct uart_port *port, int break_state) static void lpuart_setup_watermark(struct lpuart_port *sport) { unsigned char val, cr2; + unsigned char cr2_saved; cr2 = readb(sport->port.membase + UARTCR2); + cr2_saved = cr2; cr2 &= ~(UARTCR2_TIE | UARTCR2_TCIE | UARTCR2_TE | UARTCR2_RIE | UARTCR2_RE); writeb(cr2, sport->port.membase + UARTCR2); @@ -366,6 +368,9 @@ static void lpuart_setup_watermark(struct lpuart_port *sport) writeb(2, sport->port.membase + UARTTWFIFO); writeb(1, sport->port.membase + UARTRWFIFO); + + /* Restore cr2 */ + writeb(cr2_saved, sport->port.membase + UARTCR2); } static int lpuart_startup(struct uart_port *port) From 39c34b09f2fdb56c94891d5dd7ed4341d845cde5 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 22 Jul 2013 09:12:36 +0800 Subject: [PATCH 0873/3400] serial: fsl_lpuart: Return proper error on lpuart_serial_init error path Signed-off-by: Axel Lin Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/fsl_lpuart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index 7bc17f21062a..8978dc9a58b7 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -863,7 +863,7 @@ static int __init lpuart_serial_init(void) if (ret) uart_unregister_driver(&lpuart_reg); - return 0; + return ret; } static void __exit lpuart_serial_exit(void) From 3026d14a98d50c78e74d072cb05340a0f86b3938 Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Mon, 22 Jul 2013 15:31:15 +0530 Subject: [PATCH 0874/3400] serial: omap: enable PM runtime only when its fully configured If earlyprintk is enabled and current UART is console port the platform code can mark it as RPM_ACTIVE to sync real IP state with PM Runtime and avoid resuming of already active device, but now, driver initialization will be performed in the wrong way: pm_runtime_enable(&pdev->dev); <-- PM runtime alowed (device state RPM_ACTIVE) if (omap_up_info->autosuspend_timeout == 0) omap_up_info->autosuspend_timeout = -1; device_init_wakeup(up->dev, true); pm_runtime_use_autosuspend(&pdev->dev); <-- update_autosuspend() will be called and it will disable device (device state RPM_SUSPENDED) pm_runtime_set_autosuspend_delay(&pdev->dev, omap_up_info->autosuspend_timeout); <-- update_autosuspend() will be called which will re-enable device (device state RPM_ACTIVE), because autosuspend_timeout < 0 pm_runtime_irq_safe(&pdev->dev); pm_runtime_get_sync(&pdev->dev); <-- will do nothing Such behavior isn't expected by OMAP serial drivers and causes unpredictable calls of serial_omap_runtime_suspend() and serial_omap_runtime_resume(). Hence, fix it by allowing PM runtime only after all its parameters are configured. CC: Tony Lindgren CC: Rajendra Nayak CC: Felipe Balbi CC: Kevin Hilman Tested-by: Mark Jackson Signed-off-by: Grygorii Strashko Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/omap-serial.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index b0802149b3e7..c77bf0cf2684 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -1506,7 +1506,6 @@ static int serial_omap_probe(struct platform_device *pdev) INIT_WORK(&up->qos_work, serial_omap_uart_qos_work); platform_set_drvdata(pdev, up); - pm_runtime_enable(&pdev->dev); if (omap_up_info->autosuspend_timeout == 0) omap_up_info->autosuspend_timeout = -1; device_init_wakeup(up->dev, true); @@ -1515,6 +1514,8 @@ static int serial_omap_probe(struct platform_device *pdev) omap_up_info->autosuspend_timeout); pm_runtime_irq_safe(&pdev->dev); + pm_runtime_enable(&pdev->dev); + pm_runtime_get_sync(&pdev->dev); omap_serial_fill_features_erratas(up); From 7d12b9769f39bec1630c6a1947e8615ce26c9a52 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Fri, 12 Jul 2013 13:07:39 -0700 Subject: [PATCH 0875/3400] serial: report base_baud after initialization Some serial ports will not use the standard base baud rate. Report this after initialization so it might be discovered and used for early console configuration. Signed-off-by: Kees Cook Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 28cdd2829139..0f02351c9239 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -2095,12 +2095,12 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port) break; } - printk(KERN_INFO "%s%s%s%d at %s (irq = %d) is a %s\n", + printk(KERN_INFO "%s%s%s%d at %s (irq = %d, base_baud = %d) is a %s\n", port->dev ? dev_name(port->dev) : "", port->dev ? ": " : "", drv->dev_name, drv->tty_driver->name_base + port->line, - address, port->irq, uart_type(port)); + address, port->irq, port->uartclk / 16, uart_type(port)); } static void From 4e3234897fbc4c83286f3cd3105d38b26634812d Mon Sep 17 00:00:00 2001 From: Darren Hart Date: Fri, 12 Jul 2013 17:58:05 -0700 Subject: [PATCH 0876/3400] pch_uart: Use DMI interface for board detection Use the DMI interface rather than manually matching DMI strings. Signed-off-by: Darren Hart Cc: Michael Brunner Cc: Greg Kroah-Hartman Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/pch_uart.c | 71 ++++++++++++++++++++++++----------- 1 file changed, 49 insertions(+), 22 deletions(-) diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 572d48189de9..271cc733573c 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -373,35 +373,62 @@ static const struct file_operations port_regs_ops = { }; #endif /* CONFIG_DEBUG_FS */ +static struct dmi_system_id __initdata pch_uart_dmi_table[] = { + { + .ident = "CM-iTC", + { + DMI_MATCH(DMI_BOARD_NAME, "CM-iTC"), + }, + (void *)CMITC_UARTCLK, + }, + { + .ident = "FRI2", + { + DMI_MATCH(DMI_BIOS_VERSION, "FRI2"), + }, + (void *)FRI2_64_UARTCLK, + }, + { + .ident = "Fish River Island II", + { + DMI_MATCH(DMI_PRODUCT_NAME, "Fish River Island II"), + }, + (void *)FRI2_48_UARTCLK, + }, + { + .ident = "COMe-mTT", + { + DMI_MATCH(DMI_BOARD_NAME, "COMe-mTT"), + }, + (void *)NTC1_UARTCLK, + }, + { + .ident = "nanoETXexpress-TT", + { + DMI_MATCH(DMI_BOARD_NAME, "nanoETXexpress-TT"), + }, + (void *)NTC1_UARTCLK, + }, + { + .ident = "MinnowBoard", + { + DMI_MATCH(DMI_BOARD_NAME, "MinnowBoard"), + }, + (void *)MINNOW_UARTCLK, + }, +}; + /* Return UART clock, checking for board specific clocks. */ static int pch_uart_get_uartclk(void) { - const char *cmp; + const struct dmi_system_id *d; if (user_uartclk) return user_uartclk; - cmp = dmi_get_system_info(DMI_BOARD_NAME); - if (cmp && strstr(cmp, "CM-iTC")) - return CMITC_UARTCLK; - - cmp = dmi_get_system_info(DMI_BIOS_VERSION); - if (cmp && strnstr(cmp, "FRI2", 4)) - return FRI2_64_UARTCLK; - - cmp = dmi_get_system_info(DMI_PRODUCT_NAME); - if (cmp && strstr(cmp, "Fish River Island II")) - return FRI2_48_UARTCLK; - - /* Kontron COMe-mTT10 (nanoETXexpress-TT) */ - cmp = dmi_get_system_info(DMI_BOARD_NAME); - if (cmp && (strstr(cmp, "COMe-mTT") || - strstr(cmp, "nanoETXexpress-TT"))) - return NTC1_UARTCLK; - - cmp = dmi_get_system_info(DMI_BOARD_NAME); - if (cmp && strstr(cmp, "MinnowBoard")) - return MINNOW_UARTCLK; + d = dmi_first_match(pch_uart_dmi_table); + if (d) + return (int)d->driver_data; return DEFAULT_UARTCLK; } From 37e1ceb1796279d8a7b0dfaeff8a829d1dd1b2f3 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 15 Jul 2013 13:36:03 +0800 Subject: [PATCH 0877/3400] serial: bfin_uart: Remove redundant testing for ifdef CONFIG_SERIAL_BFIN_MODULE No idea why we have redundant testing for ifdef CONFIG_SERIAL_BFIN_MODULE, check it once is enough. Signed-off-by: Axel Lin Acked-by: Sonic Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/bfin_uart.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/tty/serial/bfin_uart.c b/drivers/tty/serial/bfin_uart.c index 26a3be7ced7d..72031d754dc0 100644 --- a/drivers/tty/serial/bfin_uart.c +++ b/drivers/tty/serial/bfin_uart.c @@ -41,10 +41,6 @@ # undef CONFIG_EARLY_PRINTK #endif -#ifdef CONFIG_SERIAL_BFIN_MODULE -# undef CONFIG_EARLY_PRINTK -#endif - /* UART name and device definitions */ #define BFIN_SERIAL_DEV_NAME "ttyBF" #define BFIN_SERIAL_MAJOR 204 From 195be84aaae50af84c833d91c81af015091ec86d Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 17 Jul 2013 13:34:09 +0800 Subject: [PATCH 0878/3400] msm_serial: add missing iounmap() on error in msm_request_port() Add the missing iounmap() before return from msm_request_port() in the error handling case. Signed-off-by: Wei Yongjun Reviewed-by: Ivan T. Ivanov Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/msm_serial.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c index 2c6cfb3cf032..0b38b288ed5b 100644 --- a/drivers/tty/serial/msm_serial.c +++ b/drivers/tty/serial/msm_serial.c @@ -637,7 +637,7 @@ static int msm_request_port(struct uart_port *port) if (!request_mem_region(gsbi_resource->start, size, "msm_serial")) { ret = -EBUSY; - goto fail_release_port; + goto fail_release_port_membase; } msm_port->gsbi_base = ioremap(gsbi_resource->start, size); @@ -651,6 +651,8 @@ static int msm_request_port(struct uart_port *port) fail_release_gsbi: release_mem_region(gsbi_resource->start, size); +fail_release_port_membase: + iounmap(port->membase); fail_release_port: release_mem_region(port->mapbase, size); return ret; From 2f2a0c70ce70572b517b7d2b5c68b7c9819fe3ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 17 Jul 2013 08:48:41 +0200 Subject: [PATCH 0879/3400] serial/efm32-uart: use COMPILE_TEST symbol to extend compile test coverage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver fails to build on x86 because writel_relaxed isn't available there. That function exists on arm, arm64, avr32, hexagon, mips and sh, but adding all these is overkill so stick to arm only. Signed-off-by: Uwe Kleine-König Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index bc486deeeae5..6e73781bea63 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -1424,8 +1424,8 @@ config SERIAL_AR933X_NR_UARTS to support. config SERIAL_EFM32_UART - tristate "EFM32 UART/USART port." - depends on ARCH_EFM32 + tristate "EFM32 UART/USART port" + depends on ARM && (ARCH_EFM32 || COMPILE_TEST) select SERIAL_CORE help This driver support the USART and UART ports on From 75e66aa65ed2224e3bb21b6c44555ff938c9046c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 18 Jul 2013 14:51:04 +0200 Subject: [PATCH 0880/3400] serial/efm32-uart: make of_device_id array const MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Uwe Kleine-König Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/efm32-uart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/efm32-uart.c b/drivers/tty/serial/efm32-uart.c index e029907cf430..868dbfb9f893 100644 --- a/drivers/tty/serial/efm32-uart.c +++ b/drivers/tty/serial/efm32-uart.c @@ -788,7 +788,7 @@ static int efm32_uart_remove(struct platform_device *pdev) return 0; } -static struct of_device_id efm32_uart_dt_ids[] = { +static const struct of_device_id efm32_uart_dt_ids[] = { { .compatible = "efm32,uart", }, { From c4b058560762ec7ffe159b668fc47a8b7e271949 Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Mon, 15 Jul 2013 12:39:23 +0100 Subject: [PATCH 0881/3400] serial:st-asc: Add ST ASC driver. This patch adds support to ASC (asynchronous serial controller) driver, which is basically a standard serial driver. This IP is common across all the ST parts for settop box platforms. ASC is embedded in ST COMMS IP block. It supports Rx & Tx functionality. It support all industry standard baud rates. Signed-off-by: Srinivas Kandagatla CC: Stephen Gallimore CC: Stuart Menefy CC: Arnd Bergmann CC: Greg Kroah-Hartman Signed-off-by: Greg Kroah-Hartman --- .../devicetree/bindings/tty/serial/st-asc.txt | 18 + drivers/tty/serial/Kconfig | 16 + drivers/tty/serial/Makefile | 1 + drivers/tty/serial/st-asc.c | 937 ++++++++++++++++++ include/uapi/linux/serial_core.h | 3 + 5 files changed, 975 insertions(+) create mode 100644 Documentation/devicetree/bindings/tty/serial/st-asc.txt create mode 100644 drivers/tty/serial/st-asc.c diff --git a/Documentation/devicetree/bindings/tty/serial/st-asc.txt b/Documentation/devicetree/bindings/tty/serial/st-asc.txt new file mode 100644 index 000000000000..75d877f5968f --- /dev/null +++ b/Documentation/devicetree/bindings/tty/serial/st-asc.txt @@ -0,0 +1,18 @@ +*st-asc(Serial Port) + +Required properties: +- compatible : Should be "st,asc". +- reg, reg-names, interrupts, interrupt-names : Standard way to define device + resources with names. look in + Documentation/devicetree/bindings/resource-names.txt + +Optional properties: +- st,hw-flow-ctrl bool flag to enable hardware flow control. +- st,force-m1 bool flat to force asc to be in Mode-1 recommeded + for high bit rates (above 19.2K) +Example: +serial@fe440000{ + compatible = "st,asc"; + reg = <0xfe440000 0x2c>; + interrupts = <0 209 0>; +}; diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 6e73781bea63..bdf5c0e44b68 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -1497,6 +1497,22 @@ config SERIAL_FSL_LPUART_CONSOLE If you have enabled the lpuart serial port on the Freescale SoCs, you can make it the console by answering Y to this option. +config SERIAL_ST_ASC + tristate "ST ASC serial port support" + select SERIAL_CORE + help + This driver is for the on-chip Asychronous Serial Controller on + STMicroelectronics STi SoCs. + ASC is embedded in ST COMMS IP block. It supports Rx & Tx functionality. + It support all industry standard baud rates. + + If unsure, say N. + +config SERIAL_ST_ASC_CONSOLE + bool "Support for console on ST ASC" + depends on SERIAL_ST_ASC=y + select SERIAL_CORE_CONSOLE + endmenu endif # TTY diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index cf650f0cd6e4..47b679c547e9 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile @@ -65,6 +65,7 @@ obj-$(CONFIG_SERIAL_KGDB_NMI) += kgdb_nmi.o obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o +obj-$(CONFIG_SERIAL_ST_ASC) += st-asc.o obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o obj-$(CONFIG_SERIAL_QE) += ucc_uart.o obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c new file mode 100644 index 000000000000..183879825695 --- /dev/null +++ b/drivers/tty/serial/st-asc.c @@ -0,0 +1,937 @@ +/* + * st-asc.c: ST Asynchronous serial controller (ASC) driver + * + * Copyright (C) 2003-2013 STMicroelectronics (R&D) Limited + * + * 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. + * + */ + +#if defined(CONFIG_SERIAL_ST_ASC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "st-asc" +#define ASC_SERIAL_NAME "ttyAS" +#define ASC_FIFO_SIZE 16 +#define ASC_MAX_PORTS 8 + +struct asc_port { + struct uart_port port; + struct clk *clk; + unsigned int hw_flow_control:1; + unsigned int force_m1:1; +}; + +static struct asc_port asc_ports[ASC_MAX_PORTS]; +static struct uart_driver asc_uart_driver; + +/*---- UART Register definitions ------------------------------*/ + +/* Register offsets */ + +#define ASC_BAUDRATE 0x00 +#define ASC_TXBUF 0x04 +#define ASC_RXBUF 0x08 +#define ASC_CTL 0x0C +#define ASC_INTEN 0x10 +#define ASC_STA 0x14 +#define ASC_GUARDTIME 0x18 +#define ASC_TIMEOUT 0x1C +#define ASC_TXRESET 0x20 +#define ASC_RXRESET 0x24 +#define ASC_RETRIES 0x28 + +/* ASC_RXBUF */ +#define ASC_RXBUF_PE 0x100 +#define ASC_RXBUF_FE 0x200 +/** + * Some of status comes from higher bits of the character and some come from + * the status register. Combining both of them in to single status using dummy + * bits. + */ +#define ASC_RXBUF_DUMMY_RX 0x10000 +#define ASC_RXBUF_DUMMY_BE 0x20000 +#define ASC_RXBUF_DUMMY_OE 0x40000 + +/* ASC_CTL */ + +#define ASC_CTL_MODE_MSK 0x0007 +#define ASC_CTL_MODE_8BIT 0x0001 +#define ASC_CTL_MODE_7BIT_PAR 0x0003 +#define ASC_CTL_MODE_9BIT 0x0004 +#define ASC_CTL_MODE_8BIT_WKUP 0x0005 +#define ASC_CTL_MODE_8BIT_PAR 0x0007 +#define ASC_CTL_STOP_MSK 0x0018 +#define ASC_CTL_STOP_HALFBIT 0x0000 +#define ASC_CTL_STOP_1BIT 0x0008 +#define ASC_CTL_STOP_1_HALFBIT 0x0010 +#define ASC_CTL_STOP_2BIT 0x0018 +#define ASC_CTL_PARITYODD 0x0020 +#define ASC_CTL_LOOPBACK 0x0040 +#define ASC_CTL_RUN 0x0080 +#define ASC_CTL_RXENABLE 0x0100 +#define ASC_CTL_SCENABLE 0x0200 +#define ASC_CTL_FIFOENABLE 0x0400 +#define ASC_CTL_CTSENABLE 0x0800 +#define ASC_CTL_BAUDMODE 0x1000 + +/* ASC_GUARDTIME */ + +#define ASC_GUARDTIME_MSK 0x00FF + +/* ASC_INTEN */ + +#define ASC_INTEN_RBE 0x0001 +#define ASC_INTEN_TE 0x0002 +#define ASC_INTEN_THE 0x0004 +#define ASC_INTEN_PE 0x0008 +#define ASC_INTEN_FE 0x0010 +#define ASC_INTEN_OE 0x0020 +#define ASC_INTEN_TNE 0x0040 +#define ASC_INTEN_TOI 0x0080 +#define ASC_INTEN_RHF 0x0100 + +/* ASC_RETRIES */ + +#define ASC_RETRIES_MSK 0x00FF + +/* ASC_RXBUF */ + +#define ASC_RXBUF_MSK 0x03FF + +/* ASC_STA */ + +#define ASC_STA_RBF 0x0001 +#define ASC_STA_TE 0x0002 +#define ASC_STA_THE 0x0004 +#define ASC_STA_PE 0x0008 +#define ASC_STA_FE 0x0010 +#define ASC_STA_OE 0x0020 +#define ASC_STA_TNE 0x0040 +#define ASC_STA_TOI 0x0080 +#define ASC_STA_RHF 0x0100 +#define ASC_STA_TF 0x0200 +#define ASC_STA_NKD 0x0400 + +/* ASC_TIMEOUT */ + +#define ASC_TIMEOUT_MSK 0x00FF + +/* ASC_TXBUF */ + +#define ASC_TXBUF_MSK 0x01FF + +/*---- Inline function definitions ---------------------------*/ + +static inline struct asc_port *to_asc_port(struct uart_port *port) +{ + return container_of(port, struct asc_port, port); +} + +static inline u32 asc_in(struct uart_port *port, u32 offset) +{ + return readl(port->membase + offset); +} + +static inline void asc_out(struct uart_port *port, u32 offset, u32 value) +{ + writel(value, port->membase + offset); +} + +/* + * Some simple utility functions to enable and disable interrupts. + * Note that these need to be called with interrupts disabled. + */ +static inline void asc_disable_tx_interrupts(struct uart_port *port) +{ + u32 intenable = asc_in(port, ASC_INTEN) & ~ASC_INTEN_THE; + asc_out(port, ASC_INTEN, intenable); + (void)asc_in(port, ASC_INTEN); /* Defeat bus write posting */ +} + +static inline void asc_enable_tx_interrupts(struct uart_port *port) +{ + u32 intenable = asc_in(port, ASC_INTEN) | ASC_INTEN_THE; + asc_out(port, ASC_INTEN, intenable); +} + +static inline void asc_disable_rx_interrupts(struct uart_port *port) +{ + u32 intenable = asc_in(port, ASC_INTEN) & ~ASC_INTEN_RBE; + asc_out(port, ASC_INTEN, intenable); + (void)asc_in(port, ASC_INTEN); /* Defeat bus write posting */ +} + +static inline void asc_enable_rx_interrupts(struct uart_port *port) +{ + u32 intenable = asc_in(port, ASC_INTEN) | ASC_INTEN_RBE; + asc_out(port, ASC_INTEN, intenable); +} + +static inline u32 asc_txfifo_is_empty(struct uart_port *port) +{ + return asc_in(port, ASC_STA) & ASC_STA_TE; +} + +static inline int asc_txfifo_is_full(struct uart_port *port) +{ + return asc_in(port, ASC_STA) & ASC_STA_TF; +} + +static inline const char *asc_port_name(struct uart_port *port) +{ + return to_platform_device(port->dev)->name; +} + +/*----------------------------------------------------------------------*/ + +/* + * This section contains code to support the use of the ASC as a + * generic serial port. + */ + +static inline unsigned asc_hw_txroom(struct uart_port *port) +{ + u32 status = asc_in(port, ASC_STA); + + if (status & ASC_STA_THE) + return port->fifosize / 2; + else if (!(status & ASC_STA_TF)) + return 1; + + return 0; +} + +/* + * Start transmitting chars. + * This is called from both interrupt and task level. + * Either way interrupts are disabled. + */ +static void asc_transmit_chars(struct uart_port *port) +{ + struct circ_buf *xmit = &port->state->xmit; + int txroom; + unsigned char c; + + txroom = asc_hw_txroom(port); + + if ((txroom != 0) && port->x_char) { + c = port->x_char; + port->x_char = 0; + asc_out(port, ASC_TXBUF, c); + port->icount.tx++; + txroom = asc_hw_txroom(port); + } + + if (uart_tx_stopped(port)) { + /* + * We should try and stop the hardware here, but I + * don't think the ASC has any way to do that. + */ + asc_disable_tx_interrupts(port); + return; + } + + if (uart_circ_empty(xmit)) { + asc_disable_tx_interrupts(port); + return; + } + + if (txroom == 0) + return; + + do { + c = xmit->buf[xmit->tail]; + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); + asc_out(port, ASC_TXBUF, c); + port->icount.tx++; + txroom--; + } while ((txroom > 0) && (!uart_circ_empty(xmit))); + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(port); + + if (uart_circ_empty(xmit)) + asc_disable_tx_interrupts(port); +} + +static void asc_receive_chars(struct uart_port *port) +{ + struct tty_port *tport = &port->state->port; + unsigned long status; + unsigned long c = 0; + char flag; + + if (port->irq_wake) + pm_wakeup_event(tport->tty->dev, 0); + + while ((status = asc_in(port, ASC_STA)) & ASC_STA_RBF) { + c = asc_in(port, ASC_RXBUF) | ASC_RXBUF_DUMMY_RX; + flag = TTY_NORMAL; + port->icount.rx++; + + if ((c & (ASC_RXBUF_FE | ASC_RXBUF_PE)) || + status & ASC_STA_OE) { + + if (c & ASC_RXBUF_FE) { + if (c == ASC_RXBUF_FE) { + port->icount.brk++; + if (uart_handle_break(port)) + continue; + c |= ASC_RXBUF_DUMMY_BE; + } else { + port->icount.frame++; + } + } else if (c & ASC_RXBUF_PE) { + port->icount.parity++; + } + /* + * Reading any data from the RX FIFO clears the + * overflow error condition. + */ + if (status & ASC_STA_OE) { + port->icount.overrun++; + c |= ASC_RXBUF_DUMMY_OE; + } + + c &= port->read_status_mask; + + if (c & ASC_RXBUF_DUMMY_BE) + flag = TTY_BREAK; + else if (c & ASC_RXBUF_PE) + flag = TTY_PARITY; + else if (c & ASC_RXBUF_FE) + flag = TTY_FRAME; + } + + if (uart_handle_sysrq_char(port, c)) + continue; + + uart_insert_char(port, c, ASC_RXBUF_DUMMY_OE, c & 0xff, flag); + } + + /* Tell the rest of the system the news. New characters! */ + tty_flip_buffer_push(tport); +} + +static irqreturn_t asc_interrupt(int irq, void *ptr) +{ + struct uart_port *port = ptr; + u32 status; + + spin_lock(&port->lock); + + status = asc_in(port, ASC_STA); + + if (status & ASC_STA_RBF) { + /* Receive FIFO not empty */ + asc_receive_chars(port); + } + + if ((status & ASC_STA_THE) && + (asc_in(port, ASC_INTEN) & ASC_INTEN_THE)) { + /* Transmitter FIFO at least half empty */ + asc_transmit_chars(port); + } + + spin_unlock(&port->lock); + + return IRQ_HANDLED; +} + +/*----------------------------------------------------------------------*/ + +/* + * UART Functions + */ + +static unsigned int asc_tx_empty(struct uart_port *port) +{ + return asc_txfifo_is_empty(port) ? TIOCSER_TEMT : 0; +} + +static void asc_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ + /* + * This routine is used for seting signals of: DTR, DCD, CTS/RTS + * We use ASC's hardware for CTS/RTS, so don't need any for that. + * Some boards have DTR and DCD implemented using PIO pins, + * code to do this should be hooked in here. + */ +} + +static unsigned int asc_get_mctrl(struct uart_port *port) +{ + /* + * This routine is used for geting signals of: DTR, DCD, DSR, RI, + * and CTS/RTS + */ + return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS; +} + +/* There are probably characters waiting to be transmitted. */ +static void asc_start_tx(struct uart_port *port) +{ + struct circ_buf *xmit = &port->state->xmit; + + if (!uart_circ_empty(xmit)) + asc_enable_tx_interrupts(port); +} + +/* Transmit stop */ +static void asc_stop_tx(struct uart_port *port) +{ + asc_disable_tx_interrupts(port); +} + +/* Receive stop */ +static void asc_stop_rx(struct uart_port *port) +{ + asc_disable_rx_interrupts(port); +} + +/* Force modem status interrupts on */ +static void asc_enable_ms(struct uart_port *port) +{ + /* Nothing here yet .. */ +} + +/* Handle breaks - ignored by us */ +static void asc_break_ctl(struct uart_port *port, int break_state) +{ + /* Nothing here yet .. */ +} + +/* + * Enable port for reception. + */ +static int asc_startup(struct uart_port *port) +{ + if (request_irq(port->irq, asc_interrupt, IRQF_NO_SUSPEND, + asc_port_name(port), port)) { + dev_err(port->dev, "cannot allocate irq.\n"); + return -ENODEV; + } + + asc_transmit_chars(port); + asc_enable_rx_interrupts(port); + + return 0; +} + +static void asc_shutdown(struct uart_port *port) +{ + asc_disable_tx_interrupts(port); + asc_disable_rx_interrupts(port); + free_irq(port->irq, port); +} + +static void asc_pm(struct uart_port *port, unsigned int state, + unsigned int oldstate) +{ + struct asc_port *ascport = to_asc_port(port); + unsigned long flags = 0; + u32 ctl; + + switch (state) { + case UART_PM_STATE_ON: + clk_prepare_enable(ascport->clk); + break; + case UART_PM_STATE_OFF: + /* + * Disable the ASC baud rate generator, which is as close as + * we can come to turning it off. Note this is not called with + * the port spinlock held. + */ + spin_lock_irqsave(&port->lock, flags); + ctl = asc_in(port, ASC_CTL) & ~ASC_CTL_RUN; + asc_out(port, ASC_CTL, ctl); + spin_unlock_irqrestore(&port->lock, flags); + clk_disable_unprepare(ascport->clk); + break; + } +} + +static void asc_set_termios(struct uart_port *port, struct ktermios *termios, + struct ktermios *old) +{ + struct asc_port *ascport = to_asc_port(port); + unsigned int baud; + u32 ctrl_val; + tcflag_t cflag; + unsigned long flags; + + /* Update termios to reflect hardware capabilities */ + termios->c_cflag &= ~(CMSPAR | + (ascport->hw_flow_control ? 0 : CRTSCTS)); + + port->uartclk = clk_get_rate(ascport->clk); + + baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); + cflag = termios->c_cflag; + + spin_lock_irqsave(&port->lock, flags); + + /* read control register */ + ctrl_val = asc_in(port, ASC_CTL); + + /* stop serial port and reset value */ + asc_out(port, ASC_CTL, (ctrl_val & ~ASC_CTL_RUN)); + ctrl_val = ASC_CTL_RXENABLE | ASC_CTL_FIFOENABLE; + + /* reset fifo rx & tx */ + asc_out(port, ASC_TXRESET, 1); + asc_out(port, ASC_RXRESET, 1); + + /* set character length */ + if ((cflag & CSIZE) == CS7) { + ctrl_val |= ASC_CTL_MODE_7BIT_PAR; + } else { + ctrl_val |= (cflag & PARENB) ? ASC_CTL_MODE_8BIT_PAR : + ASC_CTL_MODE_8BIT; + } + + /* set stop bit */ + ctrl_val |= (cflag & CSTOPB) ? ASC_CTL_STOP_2BIT : ASC_CTL_STOP_1BIT; + + /* odd parity */ + if (cflag & PARODD) + ctrl_val |= ASC_CTL_PARITYODD; + + /* hardware flow control */ + if ((cflag & CRTSCTS)) + ctrl_val |= ASC_CTL_CTSENABLE; + + if ((baud < 19200) && !ascport->force_m1) { + asc_out(port, ASC_BAUDRATE, (port->uartclk / (16 * baud))); + } else { + /* + * MODE 1: recommended for high bit rates (above 19.2K) + * + * baudrate * 16 * 2^16 + * ASCBaudRate = ------------------------ + * inputclock + * + * However to keep the maths inside 32bits we divide top and + * bottom by 64. The +1 is to avoid a divide by zero if the + * input clock rate is something unexpected. + */ + u32 counter = (baud * 16384) / ((port->uartclk / 64) + 1); + asc_out(port, ASC_BAUDRATE, counter); + ctrl_val |= ASC_CTL_BAUDMODE; + } + + uart_update_timeout(port, cflag, baud); + + ascport->port.read_status_mask = ASC_RXBUF_DUMMY_OE; + if (termios->c_iflag & INPCK) + ascport->port.read_status_mask |= ASC_RXBUF_FE | ASC_RXBUF_PE; + if (termios->c_iflag & (BRKINT | PARMRK)) + ascport->port.read_status_mask |= ASC_RXBUF_DUMMY_BE; + + /* + * Characters to ignore + */ + ascport->port.ignore_status_mask = 0; + if (termios->c_iflag & IGNPAR) + ascport->port.ignore_status_mask |= ASC_RXBUF_FE | ASC_RXBUF_PE; + if (termios->c_iflag & IGNBRK) { + ascport->port.ignore_status_mask |= ASC_RXBUF_DUMMY_BE; + /* + * If we're ignoring parity and break indicators, + * ignore overruns too (for real raw support). + */ + if (termios->c_iflag & IGNPAR) + ascport->port.ignore_status_mask |= ASC_RXBUF_DUMMY_OE; + } + + /* + * Ignore all characters if CREAD is not set. + */ + if (!(termios->c_cflag & CREAD)) + ascport->port.ignore_status_mask |= ASC_RXBUF_DUMMY_RX; + + /* Set the timeout */ + asc_out(port, ASC_TIMEOUT, 20); + + /* write final value and enable port */ + asc_out(port, ASC_CTL, (ctrl_val | ASC_CTL_RUN)); + + spin_unlock_irqrestore(&port->lock, flags); +} + +static const char *asc_type(struct uart_port *port) +{ + return (port->type == PORT_ASC) ? DRIVER_NAME : NULL; +} + +static void asc_release_port(struct uart_port *port) +{ +} + +static int asc_request_port(struct uart_port *port) +{ + return 0; +} + +/* + * Called when the port is opened, and UPF_BOOT_AUTOCONF flag is set + * Set type field if successful + */ +static void asc_config_port(struct uart_port *port, int flags) +{ + if ((flags & UART_CONFIG_TYPE)) + port->type = PORT_ASC; +} + +static int +asc_verify_port(struct uart_port *port, struct serial_struct *ser) +{ + /* No user changeable parameters */ + return -EINVAL; +} + +#ifdef CONFIG_CONSOLE_POLL +/* + * Console polling routines for writing and reading from the uart while + * in an interrupt or debug context (i.e. kgdb). + */ + +static int asc_get_poll_char(struct uart_port *port) +{ + if (!(asc_in(port, ASC_STA) & ASC_STA_RBF)) + return NO_POLL_CHAR; + + return asc_in(port, ASC_RXBUF); +} + +static void asc_put_poll_char(struct uart_port *port, unsigned char c) +{ + while (asc_txfifo_is_full(port)) + cpu_relax(); + asc_out(port, ASC_TXBUF, c); +} + +#endif /* CONFIG_CONSOLE_POLL */ + +/*---------------------------------------------------------------------*/ + +static struct uart_ops asc_uart_ops = { + .tx_empty = asc_tx_empty, + .set_mctrl = asc_set_mctrl, + .get_mctrl = asc_get_mctrl, + .start_tx = asc_start_tx, + .stop_tx = asc_stop_tx, + .stop_rx = asc_stop_rx, + .enable_ms = asc_enable_ms, + .break_ctl = asc_break_ctl, + .startup = asc_startup, + .shutdown = asc_shutdown, + .set_termios = asc_set_termios, + .type = asc_type, + .release_port = asc_release_port, + .request_port = asc_request_port, + .config_port = asc_config_port, + .verify_port = asc_verify_port, + .pm = asc_pm, +#ifdef CONFIG_CONSOLE_POLL + .poll_get_char = asc_get_poll_char, + .poll_put_char = asc_put_poll_char, +#endif /* CONFIG_CONSOLE_POLL */ +}; + +static int asc_init_port(struct asc_port *ascport, + struct platform_device *pdev) +{ + struct uart_port *port = &ascport->port; + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + if (!res) { + dev_err(&pdev->dev, "Unable to get io resource\n"); + return -ENODEV; + } + + port->iotype = UPIO_MEM; + port->flags = UPF_BOOT_AUTOCONF; + port->ops = &asc_uart_ops; + port->fifosize = ASC_FIFO_SIZE; + port->dev = &pdev->dev; + port->mapbase = res->start; + port->irq = platform_get_irq(pdev, 0); + + port->membase = devm_request_and_ioremap(&pdev->dev, res); + if (!port->membase) { + dev_err(&pdev->dev, "Unable to request io memory\n"); + return -ENODEV; + } + + spin_lock_init(&port->lock); + + ascport->clk = devm_clk_get(&pdev->dev, NULL); + + if (WARN_ON(IS_ERR(ascport->clk))) + return -EINVAL; + /* ensure that clk rate is correct by enabling the clk */ + clk_prepare_enable(ascport->clk); + ascport->port.uartclk = clk_get_rate(ascport->clk); + WARN_ON(ascport->port.uartclk == 0); + clk_disable_unprepare(ascport->clk); + + return 0; +} + +static struct asc_port *asc_of_get_asc_port(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + int id; + + if (!np) + return NULL; + + id = of_alias_get_id(np, ASC_SERIAL_NAME); + + if (id < 0) + id = 0; + + if (WARN_ON(id >= ASC_MAX_PORTS)) + return NULL; + + asc_ports[id].hw_flow_control = of_property_read_bool(np, + "st,hw-flow-control"); + asc_ports[id].force_m1 = of_property_read_bool(np, "st,force_m1"); + asc_ports[id].port.line = id; + return &asc_ports[id]; +} + +static struct of_device_id asc_match[] = { + { .compatible = "st,asc", }, + {}, +}; + +MODULE_DEVICE_TABLE(of, asc_match); + +static int asc_serial_probe(struct platform_device *pdev) +{ + int ret; + struct asc_port *ascport; + + ascport = asc_of_get_asc_port(pdev); + if (!ascport) + return -ENODEV; + + ret = asc_init_port(ascport, pdev); + if (ret) + return ret; + + ret = uart_add_one_port(&asc_uart_driver, &ascport->port); + if (ret) + return ret; + + platform_set_drvdata(pdev, &ascport->port); + + return 0; +} + +static int asc_serial_remove(struct platform_device *pdev) +{ + struct uart_port *port = platform_get_drvdata(pdev); + + platform_set_drvdata(pdev, NULL); + return uart_remove_one_port(&asc_uart_driver, port); +} + +#ifdef CONFIG_PM_SLEEP +static int asc_serial_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct uart_port *port = platform_get_drvdata(pdev); + + return uart_suspend_port(&asc_uart_driver, port); +} + +static int asc_serial_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct uart_port *port = platform_get_drvdata(pdev); + + return uart_resume_port(&asc_uart_driver, port); +} + +#endif /* CONFIG_PM_SLEEP */ + +/*----------------------------------------------------------------------*/ + +#ifdef CONFIG_SERIAL_ST_ASC_CONSOLE +static void asc_console_putchar(struct uart_port *port, int ch) +{ + unsigned int timeout = 1000000; + + /* Wait for upto 1 second in case flow control is stopping us. */ + while (--timeout && asc_txfifo_is_full(port)) + udelay(1); + + asc_out(port, ASC_TXBUF, ch); +} + +/* + * Print a string to the serial port trying not to disturb + * any possible real use of the port... + */ + +static void asc_console_write(struct console *co, const char *s, unsigned count) +{ + struct uart_port *port = &asc_ports[co->index].port; + unsigned long flags; + unsigned long timeout = 1000000; + int locked = 1; + u32 intenable; + + local_irq_save(flags); + if (port->sysrq) + locked = 0; /* asc_interrupt has already claimed the lock */ + else if (oops_in_progress) + locked = spin_trylock(&port->lock); + else + spin_lock(&port->lock); + + /* + * Disable interrupts so we don't get the IRQ line bouncing + * up and down while interrupts are disabled. + */ + intenable = asc_in(port, ASC_INTEN); + asc_out(port, ASC_INTEN, 0); + (void)asc_in(port, ASC_INTEN); /* Defeat bus write posting */ + + uart_console_write(port, s, count, asc_console_putchar); + + while (--timeout && !asc_txfifo_is_empty(port)) + udelay(1); + + asc_out(port, ASC_INTEN, intenable); + + if (locked) + spin_unlock(&port->lock); + local_irq_restore(flags); +} + +static int asc_console_setup(struct console *co, char *options) +{ + struct asc_port *ascport; + int baud = 9600; + int bits = 8; + int parity = 'n'; + int flow = 'n'; + + if (co->index >= ASC_MAX_PORTS) + return -ENODEV; + + ascport = &asc_ports[co->index]; + + /* + * This driver does not support early console initialization + * (use ARM early printk support instead), so we only expect + * this to be called during the uart port registration when the + * driver gets probed and the port should be mapped at that point. + */ + BUG_ON(ascport->port.mapbase == 0 || ascport->port.membase == NULL); + + if (options) + uart_parse_options(options, &baud, &parity, &bits, &flow); + + return uart_set_options(&ascport->port, co, baud, parity, bits, flow); +} + +static struct console asc_console = { + .name = ASC_SERIAL_NAME, + .device = uart_console_device, + .write = asc_console_write, + .setup = asc_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, + .data = &asc_uart_driver, +}; + +#define ASC_SERIAL_CONSOLE (&asc_console) + +#else +#define ASC_SERIAL_CONSOLE NULL +#endif /* CONFIG_SERIAL_ST_ASC_CONSOLE */ + +static struct uart_driver asc_uart_driver = { + .owner = THIS_MODULE, + .driver_name = DRIVER_NAME, + .dev_name = ASC_SERIAL_NAME, + .major = 0, + .minor = 0, + .nr = ASC_MAX_PORTS, + .cons = ASC_SERIAL_CONSOLE, +}; + +static const struct dev_pm_ops asc_serial_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(asc_serial_suspend, asc_serial_resume) +}; + +static struct platform_driver asc_serial_driver = { + .probe = asc_serial_probe, + .remove = asc_serial_remove, + .driver = { + .name = DRIVER_NAME, + .pm = &asc_serial_pm_ops, + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(asc_match), + }, +}; + +static int __init asc_init(void) +{ + int ret; + static char banner[] __initdata = + KERN_INFO "STMicroelectronics ASC driver initialized\n"; + + printk(banner); + + ret = uart_register_driver(&asc_uart_driver); + if (ret) + return ret; + + ret = platform_driver_register(&asc_serial_driver); + if (ret) + uart_unregister_driver(&asc_uart_driver); + + return ret; +} + +static void __exit asc_exit(void) +{ + platform_driver_unregister(&asc_serial_driver); + uart_unregister_driver(&asc_uart_driver); +} + +module_init(asc_init); +module_exit(asc_exit); + +MODULE_ALIAS("platform:" DRIVER_NAME); +MODULE_AUTHOR("STMicroelectronics (R&D) Limited"); +MODULE_DESCRIPTION("STMicroelectronics ASC serial port driver"); +MODULE_LICENSE("GPL"); diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h index 9119cc0977bf..e40ebe124ced 100644 --- a/include/uapi/linux/serial_core.h +++ b/include/uapi/linux/serial_core.h @@ -232,4 +232,7 @@ /* SH-SCI */ #define PORT_HSCIF 104 +/* ST ASC type numbers */ +#define PORT_ASC 105 + #endif /* _UAPILINUX_SERIAL_CORE_H */ From 12197de2cdb2ded83db7b5a3a06f4b275fb8e62c Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 16 Jul 2013 16:14:38 +0100 Subject: [PATCH 0882/3400] pci_ids.h: move PCI_VENDOR_ID_AMCC here PCI_VENDOR_ID_AMCC is defined locally in "drivers/staging/comedi/comedidev.h" for a few comedi hardware drivers, namely "adl_pci9118", "addi_apci_1500" and "addi_apci_3120" (also "addi_apci_1710" but that is not currently built and will probably be removed soon). Move the define into "include/linux/pci_ids.h" as it is shared by several drivers (albeit all comedi drivers currently). PCI_VENDOR_ID_AMCC happens to have the same value (0x10e8) as PCI_VENDOR_ID_ADDIDATA_OLD. The vendor ID is actually assigned to Applied Micro Circuits Corporation and Addi-Data were using device IDs assigned by AMCC on some of their earlier PCI boards. The PCI_VENDOR_ID_ADDIDATA_OLD define is still being used by the "8250_pci" PCI serial board driver. Signed-off-by: Ian Abbott Acked-by: Bjorn Helgaas Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedidev.h | 1 - include/linux/pci_ids.h | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index b75915f30f48..9f4f73fa652c 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -400,7 +400,6 @@ int comedi_driver_unregister(struct comedi_driver *); */ #define PCI_VENDOR_ID_KOLTER 0x1001 #define PCI_VENDOR_ID_ICP 0x104c -#define PCI_VENDOR_ID_AMCC 0x10e8 #define PCI_VENDOR_ID_DT 0x1116 #define PCI_VENDOR_ID_IOTECH 0x1616 #define PCI_VENDOR_ID_CONTEC 0x1221 diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 3bed2e89611b..9d9911926598 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1311,6 +1311,8 @@ #define PCI_DEVICE_ID_IMS_TT128 0x9128 #define PCI_DEVICE_ID_IMS_TT3D 0x9135 +#define PCI_VENDOR_ID_AMCC 0x10e8 + #define PCI_VENDOR_ID_INTERG 0x10ea #define PCI_DEVICE_ID_INTERG_1682 0x1682 #define PCI_DEVICE_ID_INTERG_2000 0x2000 @@ -2256,7 +2258,7 @@ /* * ADDI-DATA GmbH communication cards */ -#define PCI_VENDOR_ID_ADDIDATA_OLD 0x10E8 +#define PCI_VENDOR_ID_ADDIDATA_OLD 0x10E8 /* actually AMCC */ #define PCI_VENDOR_ID_ADDIDATA 0x15B8 #define PCI_DEVICE_ID_ADDIDATA_APCI7500 0x7000 #define PCI_DEVICE_ID_ADDIDATA_APCI7420 0x7001 From 086231f7f809f998e4afacbc94ea1fdca9c01e15 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 16 Jul 2013 16:14:39 +0100 Subject: [PATCH 0883/3400] serial: 8250_pci: replace PCI_VENDOR_ID_ADDIDATA_OLD PCI_VENDOR_ID_ADDIDATA_OLD has the same value (0x10e8) as PCI_VENDOR_ID_AMCC in . The vender ID is actually assigned to Applied Micro Circuits Corporation. The 8250_pci driver uses PCI_VENDOR_ID_ADDIDATA_OLD in the lists of quirks and PCI IDs for the ADDI-DATA APCI-7800 card. Change it to use the more accurate PCI_VENDOR_ID_AMCC. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index c626c4fcf9b8..fcfed9ff7561 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1587,7 +1587,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { * ADDI-DATA GmbH communication cards */ { - .vendor = PCI_VENDOR_ID_ADDIDATA_OLD, + .vendor = PCI_VENDOR_ID_AMCC, .device = PCI_DEVICE_ID_ADDIDATA_APCI7800, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, @@ -4697,7 +4697,7 @@ static struct pci_device_id serial_pci_tbl[] = { 0, pbn_b0_1_115200 }, - { PCI_VENDOR_ID_ADDIDATA_OLD, + { PCI_VENDOR_ID_AMCC, PCI_DEVICE_ID_ADDIDATA_APCI7800, PCI_ANY_ID, PCI_ANY_ID, From 57c1f0e93428f37c7220ab33fa47177576eb9d44 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 16 Jul 2013 16:14:40 +0100 Subject: [PATCH 0884/3400] serial: 8250_pci: use local device ID for ADDI-DATA APCI-7800 The quirks and PCI ID table entries for the original ADDI-DATA APCI-7800 (not the newer APCI-7800-3) use PCI_DEVICE_ID_ADDIDATA_APCI7800 from but the device ID was actually assigned to ADDI-DATA by Applied Micro Circuits Corporation (PCI_VENDOR_ID_AMCC). Replace it locally with #define PCI_DEVICE_ID_AMCC_ADDIDATA_APCI7800. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pci.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index fcfed9ff7561..c810da7c7a88 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1565,6 +1565,7 @@ pci_wch_ch353_setup(struct serial_private *priv, #define PCI_DEVICE_ID_COMMTECH_4228PCIE 0x0021 #define PCI_DEVICE_ID_COMMTECH_4222PCIE 0x0022 #define PCI_DEVICE_ID_BROADCOM_TRUMANAGE 0x160a +#define PCI_DEVICE_ID_AMCC_ADDIDATA_APCI7800 0x818e #define PCI_VENDOR_ID_SUNIX 0x1fd4 #define PCI_DEVICE_ID_SUNIX_1999 0x1999 @@ -1588,7 +1589,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { */ { .vendor = PCI_VENDOR_ID_AMCC, - .device = PCI_DEVICE_ID_ADDIDATA_APCI7800, + .device = PCI_DEVICE_ID_AMCC_ADDIDATA_APCI7800, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, .setup = addidata_apci7800_setup, @@ -4698,7 +4699,7 @@ static struct pci_device_id serial_pci_tbl[] = { pbn_b0_1_115200 }, { PCI_VENDOR_ID_AMCC, - PCI_DEVICE_ID_ADDIDATA_APCI7800, + PCI_DEVICE_ID_AMCC_ADDIDATA_APCI7800, PCI_ANY_ID, PCI_ANY_ID, 0, From fee8bf4b74e37bfeb8998a349cb788680eb3f634 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 16 Jul 2013 16:14:41 +0100 Subject: [PATCH 0885/3400] pci_ids.h: remove PCI_VENDOR_ID_ADDIDATA_OLD and PCI_DEVICE_ID_ADDIDATA_APCI7800 These two defines are no longer used. They were only used by the PCI serial driver "8250_pci" to support the original ADDI-DATA APCI-7800 card. In that driver, PCI_VENDOR_ID_ADDIDATA_OLD has been replaced with PCI_VENDOR_ID_AMCC which has the same value (0x10e8), and PCI_DEVICE_ID_ADDIDATA_APCI7800 has been replaced with a local #define PCI_DEVICE_ID_AMCC_ADDIDATA_APCI7800 with the same value (0x818e). Signed-off-by: Ian Abbott Acked-by: Bjorn Helgaas Signed-off-by: Greg Kroah-Hartman --- include/linux/pci_ids.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 9d9911926598..6dec3d6abe0b 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2258,12 +2258,10 @@ /* * ADDI-DATA GmbH communication cards */ -#define PCI_VENDOR_ID_ADDIDATA_OLD 0x10E8 /* actually AMCC */ #define PCI_VENDOR_ID_ADDIDATA 0x15B8 #define PCI_DEVICE_ID_ADDIDATA_APCI7500 0x7000 #define PCI_DEVICE_ID_ADDIDATA_APCI7420 0x7001 #define PCI_DEVICE_ID_ADDIDATA_APCI7300 0x7002 -#define PCI_DEVICE_ID_ADDIDATA_APCI7800 0x818E #define PCI_DEVICE_ID_ADDIDATA_APCI7500_2 0x7009 #define PCI_DEVICE_ID_ADDIDATA_APCI7420_2 0x700A #define PCI_DEVICE_ID_ADDIDATA_APCI7300_2 0x700B From 4a5662d6a6412dabe0b5518bec111e17babbba05 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 24 Jul 2013 11:37:28 -0700 Subject: [PATCH 0886/3400] msm_serial: Fix NUL byte output on UARTDM UARTDM serial devices require us to wait for the entire TX fifo to drain before we can change the contents of the NCF_TX register. Furthermore, if we write any characters to the TX fifo within the same clock cycle of changing the NCF_TX register the NCF_TX register won't latch properly. To fix these issues we should read back the NCF_TX register to delay any TX fifo accesses by a clock cycle and we should wait for the TX fifo to drain (instead of just waiting for the fifo to be ready to receive more characters). Failure to do so leads to random NUL bytes interspersed in the output. Signed-off-by: Stephen Boyd Acked-by: David Brown Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/msm_serial.c | 14 +++++++++----- drivers/tty/serial/msm_serial.h | 1 + 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c index 0b38b288ed5b..5a88d88b25da 100644 --- a/drivers/tty/serial/msm_serial.c +++ b/drivers/tty/serial/msm_serial.c @@ -50,11 +50,14 @@ struct msm_port { unsigned int old_snap_state; }; -static inline void wait_for_xmitr(struct uart_port *port, int bits) +static inline void wait_for_xmitr(struct uart_port *port) { - if (!(msm_read(port, UART_SR) & UART_SR_TX_EMPTY)) - while ((msm_read(port, UART_ISR) & bits) != bits) - cpu_relax(); + while (!(msm_read(port, UART_SR) & UART_SR_TX_EMPTY)) { + if (msm_read(port, UART_ISR) & UART_ISR_TX_READY) + break; + udelay(1); + } + msm_write(port, UART_CR_CMD_RESET_TX_READY, UART_CR); } static void msm_stop_tx(struct uart_port *port) @@ -194,8 +197,9 @@ static void handle_rx(struct uart_port *port) static void reset_dm_count(struct uart_port *port) { - wait_for_xmitr(port, UART_ISR_TX_READY); + wait_for_xmitr(port); msm_write(port, 1, UARTDM_NCF_TX); + msm_read(port, UARTDM_NCF_TX); } static void handle_tx(struct uart_port *port) diff --git a/drivers/tty/serial/msm_serial.h b/drivers/tty/serial/msm_serial.h index e4acef5de77e..15c186ecbd9e 100644 --- a/drivers/tty/serial/msm_serial.h +++ b/drivers/tty/serial/msm_serial.h @@ -71,6 +71,7 @@ #define UART_CR_CMD_RESET_RFR (14 << 4) #define UART_CR_CMD_PROTECTION_EN (16 << 4) #define UART_CR_CMD_STALE_EVENT_ENABLE (80 << 4) +#define UART_CR_CMD_RESET_TX_READY (3 << 8) #define UART_CR_TX_DISABLE (1 << 3) #define UART_CR_TX_ENABLE (1 << 2) #define UART_CR_RX_DISABLE (1 << 1) From f8fb952fd409a4c854a66473c11d35b4e5e9c2eb Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 24 Jul 2013 11:37:29 -0700 Subject: [PATCH 0887/3400] msm_serial: Fix sparse warnings drivers/tty/serial/msm_serial.c:302:6: warning: symbol 'msm_set_mctrl' was not declared. Should it be static? drivers/tty/serial/msm_serial.c:597:17: warning: incorrect type in argument 2 (different address spaces) drivers/tty/serial/msm_serial.c:597:17: expected void volatile [noderef] *addr drivers/tty/serial/msm_serial.c:597:17: got unsigned int * drivers/tty/serial/msm_serial.c:608:33: warning: incorrect type in argument 1 (different address spaces) drivers/tty/serial/msm_serial.c:608:33: expected void volatile [noderef] *addr drivers/tty/serial/msm_serial.c:608:33: got unsigned int *gsbi_base drivers/tty/serial/msm_serial.c:648:37: warning: incorrect type in assignment (different address spaces) drivers/tty/serial/msm_serial.c:648:37: expected unsigned int *gsbi_base drivers/tty/serial/msm_serial.c:648:37: got void [noderef] * Mark the ioremapped memory as __iomem and use writel instead of iowrite because we're not dealing with PCI devices. Also, mark msm_set_mctrl() static because it isn't used outside this file. Signed-off-by: Stephen Boyd Acked-by: David Brown Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/msm_serial.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c index 5a88d88b25da..4184c5164ab4 100644 --- a/drivers/tty/serial/msm_serial.c +++ b/drivers/tty/serial/msm_serial.c @@ -45,7 +45,7 @@ struct msm_port { struct clk *clk; struct clk *pclk; unsigned int imr; - unsigned int *gsbi_base; + void __iomem *gsbi_base; int is_uartdm; unsigned int old_snap_state; }; @@ -299,7 +299,7 @@ static void msm_reset(struct uart_port *port) msm_write(port, UART_CR_CMD_SET_RFR, UART_CR); } -void msm_set_mctrl(struct uart_port *port, unsigned int mctrl) +static void msm_set_mctrl(struct uart_port *port, unsigned int mctrl) { unsigned int mr; mr = msm_read(port, UART_MR1); @@ -593,12 +593,10 @@ static void msm_release_port(struct uart_port *port) port->membase = NULL; if (msm_port->gsbi_base) { - iowrite32(GSBI_PROTOCOL_IDLE, msm_port->gsbi_base + - GSBI_CONTROL); - - gsbi_resource = platform_get_resource(pdev, - IORESOURCE_MEM, 1); + writel_relaxed(GSBI_PROTOCOL_IDLE, + msm_port->gsbi_base + GSBI_CONTROL); + gsbi_resource = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (unlikely(!gsbi_resource)) return; @@ -672,10 +670,9 @@ static void msm_config_port(struct uart_port *port, int flags) if (ret) return; } - if (msm_port->is_uartdm) - iowrite32(GSBI_PROTOCOL_UART, msm_port->gsbi_base + - GSBI_CONTROL); + writel_relaxed(GSBI_PROTOCOL_UART, + msm_port->gsbi_base + GSBI_CONTROL); } static int msm_verify_port(struct uart_port *port, struct serial_struct *ser) From 6909dadd914259f459828b11c378ddea08d40ab6 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 24 Jul 2013 11:37:30 -0700 Subject: [PATCH 0888/3400] msm_serial: Make baud_code detection more dynamic Currently msm_set_baud_rate() assumes the uart clock rate is 1.8432 MHz. This is not always true, and limits our options to program the baud rate. Instead of assuming the rate and hard-coding the baud_code based on it, calculate the divider that we want and try to find the closest baud_code that matches. This allows us to support uarts with faster clock speeds. Signed-off-by: Stephen Boyd Acked-by: David Brown Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/msm_serial.c | 98 +++++++++++++++------------------ drivers/tty/serial/msm_serial.h | 18 ++---- 2 files changed, 48 insertions(+), 68 deletions(-) diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c index 4184c5164ab4..ca2ae6581149 100644 --- a/drivers/tty/serial/msm_serial.c +++ b/drivers/tty/serial/msm_serial.c @@ -322,70 +322,60 @@ static void msm_break_ctl(struct uart_port *port, int break_ctl) msm_write(port, UART_CR_CMD_STOP_BREAK, UART_CR); } +struct msm_baud_map { + u16 divisor; + u8 code; + u8 rxstale; +}; + +static const struct msm_baud_map * +msm_find_best_baud(struct uart_port *port, unsigned int baud) +{ + unsigned int i, divisor; + const struct msm_baud_map *entry; + static const struct msm_baud_map table[] = { + { 1536, 0x00, 1 }, + { 768, 0x11, 1 }, + { 384, 0x22, 1 }, + { 192, 0x33, 1 }, + { 96, 0x44, 1 }, + { 48, 0x55, 1 }, + { 32, 0x66, 1 }, + { 24, 0x77, 1 }, + { 16, 0x88, 1 }, + { 12, 0x99, 6 }, + { 8, 0xaa, 6 }, + { 6, 0xbb, 6 }, + { 4, 0xcc, 6 }, + { 3, 0xdd, 8 }, + { 2, 0xee, 16 }, + { 1, 0xff, 31 }, + }; + + divisor = uart_get_divisor(port, baud); + + for (i = 0, entry = table; i < ARRAY_SIZE(table); i++, entry++) + if (entry->divisor <= divisor) + break; + + return entry; /* Default to smallest divider */ +} + static int msm_set_baud_rate(struct uart_port *port, unsigned int baud) { - unsigned int baud_code, rxstale, watermark; + unsigned int rxstale, watermark; struct msm_port *msm_port = UART_TO_MSM(port); + const struct msm_baud_map *entry; - switch (baud) { - case 300: - baud_code = UART_CSR_300; - rxstale = 1; - break; - case 600: - baud_code = UART_CSR_600; - rxstale = 1; - break; - case 1200: - baud_code = UART_CSR_1200; - rxstale = 1; - break; - case 2400: - baud_code = UART_CSR_2400; - rxstale = 1; - break; - case 4800: - baud_code = UART_CSR_4800; - rxstale = 1; - break; - case 9600: - baud_code = UART_CSR_9600; - rxstale = 2; - break; - case 14400: - baud_code = UART_CSR_14400; - rxstale = 3; - break; - case 19200: - baud_code = UART_CSR_19200; - rxstale = 4; - break; - case 28800: - baud_code = UART_CSR_28800; - rxstale = 6; - break; - case 38400: - baud_code = UART_CSR_38400; - rxstale = 8; - break; - case 57600: - baud_code = UART_CSR_57600; - rxstale = 16; - break; - case 115200: - default: - baud_code = UART_CSR_115200; - baud = 115200; - rxstale = 31; - break; - } + entry = msm_find_best_baud(port, baud); if (msm_port->is_uartdm) msm_write(port, UART_CR_CMD_RESET_RX, UART_CR); - msm_write(port, baud_code, UART_CSR); + msm_write(port, entry->code, UART_CSR); /* RX stale watermark */ + rxstale = entry->rxstale; watermark = UART_IPR_STALE_LSB & rxstale; watermark |= UART_IPR_RXSTALE_LAST; watermark |= UART_IPR_STALE_TIMEOUT_MSB & (rxstale << 2); diff --git a/drivers/tty/serial/msm_serial.h b/drivers/tty/serial/msm_serial.h index 15c186ecbd9e..469fda50ac63 100644 --- a/drivers/tty/serial/msm_serial.h +++ b/drivers/tty/serial/msm_serial.h @@ -38,19 +38,7 @@ #define UART_MR2_PARITY_MODE_SPACE 0x3 #define UART_MR2_PARITY_MODE 0x3 -#define UART_CSR 0x0008 -#define UART_CSR_115200 0xFF -#define UART_CSR_57600 0xEE -#define UART_CSR_38400 0xDD -#define UART_CSR_28800 0xCC -#define UART_CSR_19200 0xBB -#define UART_CSR_14400 0xAA -#define UART_CSR_9600 0x99 -#define UART_CSR_4800 0x77 -#define UART_CSR_2400 0x55 -#define UART_CSR_1200 0x44 -#define UART_CSR_600 0x33 -#define UART_CSR_300 0x22 +#define UART_CSR 0x0008 #define UART_TF 0x000C #define UARTDM_TF 0x0070 @@ -152,6 +140,7 @@ static inline void msm_serial_set_mnd_regs_tcxo(struct uart_port *port) msm_write(port, 0xF1, UART_NREG); msm_write(port, 0x0F, UART_DREG); msm_write(port, 0x1A, UART_MNDREG); + port->uartclk = 1843200; } /* @@ -163,6 +152,7 @@ static inline void msm_serial_set_mnd_regs_tcxoby4(struct uart_port *port) msm_write(port, 0xF6, UART_NREG); msm_write(port, 0x0F, UART_DREG); msm_write(port, 0x0A, UART_MNDREG); + port->uartclk = 1843200; } static inline @@ -170,7 +160,7 @@ void msm_serial_set_mnd_regs_from_uartclk(struct uart_port *port) { if (port->uartclk == 19200000) msm_serial_set_mnd_regs_tcxo(port); - else + else if (port->uartclk == 4800000) msm_serial_set_mnd_regs_tcxoby4(port); } From 17fae28efe8f460918e13aedd7163690206c682d Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Wed, 24 Jul 2013 11:37:31 -0700 Subject: [PATCH 0889/3400] msm_serial: Send more than 1 character at a time on UARTDM UARTDM cores have a TX fifo that can accept more than one character per register write, but the msm_serial driver currently only supports 1 character mode. Add support for this mode of operation to speed up the transmit path on DM devices. Signed-off-by: Stephen Boyd Acked-by: David Brown Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/msm_serial.c | 51 +++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c index ca2ae6581149..252d514b47fb 100644 --- a/drivers/tty/serial/msm_serial.c +++ b/drivers/tty/serial/msm_serial.c @@ -195,10 +195,10 @@ static void handle_rx(struct uart_port *port) tty_flip_buffer_push(tport); } -static void reset_dm_count(struct uart_port *port) +static void reset_dm_count(struct uart_port *port, int count) { wait_for_xmitr(port); - msm_write(port, 1, UARTDM_NCF_TX); + msm_write(port, count, UARTDM_NCF_TX); msm_read(port, UARTDM_NCF_TX); } @@ -206,39 +206,52 @@ static void handle_tx(struct uart_port *port) { struct circ_buf *xmit = &port->state->xmit; struct msm_port *msm_port = UART_TO_MSM(port); - int sent_tx; + unsigned int tx_count, num_chars; + unsigned int tf_pointer = 0; + + tx_count = uart_circ_chars_pending(xmit); + tx_count = min3(tx_count, (unsigned int)UART_XMIT_SIZE - xmit->tail, + port->fifosize); if (port->x_char) { if (msm_port->is_uartdm) - reset_dm_count(port); + reset_dm_count(port, tx_count + 1); msm_write(port, port->x_char, msm_port->is_uartdm ? UARTDM_TF : UART_TF); port->icount.tx++; port->x_char = 0; + } else if (tx_count && msm_port->is_uartdm) { + reset_dm_count(port, tx_count); } - if (msm_port->is_uartdm) - reset_dm_count(port); + while (tf_pointer < tx_count) { + int i; + char buf[4] = { 0 }; + unsigned int *bf = (unsigned int *)&buf; - while (msm_read(port, UART_SR) & UART_SR_TX_READY) { - if (uart_circ_empty(xmit)) { - /* disable tx interrupts */ - msm_port->imr &= ~UART_IMR_TXLEV; - msm_write(port, msm_port->imr, UART_IMR); + if (!(msm_read(port, UART_SR) & UART_SR_TX_READY)) break; - } - msm_write(port, xmit->buf[xmit->tail], - msm_port->is_uartdm ? UARTDM_TF : UART_TF); if (msm_port->is_uartdm) - reset_dm_count(port); + num_chars = min(tx_count - tf_pointer, sizeof(buf)); + else + num_chars = 1; - xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); - port->icount.tx++; - sent_tx = 1; + for (i = 0; i < num_chars; i++) { + buf[i] = xmit->buf[xmit->tail + i]; + port->icount.tx++; + } + + msm_write(port, *bf, msm_port->is_uartdm ? UARTDM_TF : UART_TF); + xmit->tail = (xmit->tail + num_chars) & (UART_XMIT_SIZE - 1); + tf_pointer += num_chars; } + /* disable tx interrupts if nothing more to send */ + if (uart_circ_empty(xmit)) + msm_stop_tx(port); + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(port); } @@ -759,7 +772,7 @@ static void msm_console_putchar(struct uart_port *port, int c) struct msm_port *msm_port = UART_TO_MSM(port); if (msm_port->is_uartdm) - reset_dm_count(port); + reset_dm_count(port, 1); while (!(msm_read(port, UART_SR) & UART_SR_TX_READY)) ; From cf940ebe98e693aec2d10f9af2fb84eb55234e3c Mon Sep 17 00:00:00 2001 From: Andreas Platschek Date: Fri, 26 Jul 2013 06:46:37 +0200 Subject: [PATCH 0890/3400] tty: Remove dead code -> The ledptrs[] array is never initialized. -> There is no place where kbd->ledmode is set to LED_SHOW_MEM therefore the if statement does not make much sense. -> Since LED_SHOW_MEM is not used, it can be removed from the header file as well. Signed-off-by: Andreas Platschek Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/keyboard.c | 21 +-------------------- include/linux/kbd_kern.h | 3 +-- 2 files changed, 2 insertions(+), 22 deletions(-) diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c index a9af1b9ae160..d0e3a4497707 100644 --- a/drivers/tty/vt/keyboard.c +++ b/drivers/tty/vt/keyboard.c @@ -132,12 +132,6 @@ static int shift_state = 0; static unsigned char ledstate = 0xff; /* undefined */ static unsigned char ledioctl; -static struct ledptr { - unsigned int *addr; - unsigned int mask; - unsigned char valid:1; -} ledptrs[3]; - /* * Notifier list for console keyboard events */ @@ -994,24 +988,11 @@ void setledstate(struct kbd_struct *kbd, unsigned int led) static inline unsigned char getleds(void) { struct kbd_struct *kbd = kbd_table + fg_console; - unsigned char leds; - int i; if (kbd->ledmode == LED_SHOW_IOCTL) return ledioctl; - leds = kbd->ledflagstate; - - if (kbd->ledmode == LED_SHOW_MEM) { - for (i = 0; i < 3; i++) - if (ledptrs[i].valid) { - if (*ledptrs[i].addr & ledptrs[i].mask) - leds |= (1 << i); - else - leds &= ~(1 << i); - } - } - return leds; + return kbd->ledflagstate; } static int kbd_update_leds_helper(struct input_handle *handle, void *data) diff --git a/include/linux/kbd_kern.h b/include/linux/kbd_kern.h index b7c8cdc1d422..cbfb171bbcba 100644 --- a/include/linux/kbd_kern.h +++ b/include/linux/kbd_kern.h @@ -36,10 +36,9 @@ struct kbd_struct { #define VC_CTRLRLOCK KG_CTRLR /* ctrlr lock mode */ unsigned char slockstate; /* for `sticky' Shift, Ctrl, etc. */ - unsigned char ledmode:2; /* one 2-bit value */ + unsigned char ledmode:1; #define LED_SHOW_FLAGS 0 /* traditional state */ #define LED_SHOW_IOCTL 1 /* only change leds upon ioctl */ -#define LED_SHOW_MEM 2 /* `heartbeat': peek into memory */ unsigned char ledflagstate:4; /* flags, not lights */ unsigned char default_ledflagstate:4; From 299a62575a63b19add8206642b340f1b54ec4faf Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 26 Jul 2013 16:22:02 +0200 Subject: [PATCH 0891/3400] serial8250-em: Convert to devm_* managed helpers Replace kzalloc and clk_get by their managed counterparts to simplify error and cleanup paths. Signed-off-by: Laurent Pinchart Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_em.c | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/drivers/tty/serial/8250/8250_em.c b/drivers/tty/serial/8250/8250_em.c index 916cc19fbbda..5f3bba12c159 100644 --- a/drivers/tty/serial/8250/8250_em.c +++ b/drivers/tty/serial/8250/8250_em.c @@ -95,25 +95,23 @@ static int serial8250_em_probe(struct platform_device *pdev) struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); struct serial8250_em_priv *priv; struct uart_8250_port up; - int ret = -EINVAL; + int ret; if (!regs || !irq) { dev_err(&pdev->dev, "missing registers or irq\n"); - goto err0; + return -EINVAL; } - priv = kzalloc(sizeof(*priv), GFP_KERNEL); + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) { dev_err(&pdev->dev, "unable to allocate private data\n"); - ret = -ENOMEM; - goto err0; + return -ENOMEM; } - priv->sclk = clk_get(&pdev->dev, "sclk"); + priv->sclk = devm_clk_get(&pdev->dev, "sclk"); if (IS_ERR(priv->sclk)) { dev_err(&pdev->dev, "unable to get clock\n"); - ret = PTR_ERR(priv->sclk); - goto err1; + return PTR_ERR(priv->sclk); } memset(&up, 0, sizeof(up)); @@ -136,20 +134,13 @@ static int serial8250_em_probe(struct platform_device *pdev) ret = serial8250_register_8250_port(&up); if (ret < 0) { dev_err(&pdev->dev, "unable to register 8250 port\n"); - goto err2; + clk_disable(priv->sclk); + return ret; } priv->line = ret; platform_set_drvdata(pdev, priv); return 0; - - err2: - clk_disable(priv->sclk); - clk_put(priv->sclk); - err1: - kfree(priv); - err0: - return ret; } static int serial8250_em_remove(struct platform_device *pdev) @@ -158,8 +149,6 @@ static int serial8250_em_remove(struct platform_device *pdev) serial8250_unregister_port(priv->line); clk_disable(priv->sclk); - clk_put(priv->sclk); - kfree(priv); return 0; } From f40ac2ae1b506484dd9261a24bbf3e86b2206ff8 Mon Sep 17 00:00:00 2001 From: Sunghan Suh Date: Wed, 3 Jul 2013 20:10:05 +0900 Subject: [PATCH 0892/3400] zram: prevent data loss in error cases of function zram_bvec_write() In function zram_bvec_write(), previous data at the index is already freed by function zram_free_page(). When failed to compress or zs_malloc, there is no way to restore old data. Therefore, free previous data when it's about to update. Also, no need to check whether table is not empty outside of function zram_free_page(), because the function properly checks inside. Signed-off-by: Sunghan Suh Signed-off-by: Greg Kroah-Hartman --- drivers/staging/zram/zram_drv.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c index 1b30a5e87c78..5ef6508a587c 100644 --- a/drivers/staging/zram/zram_drv.c +++ b/drivers/staging/zram/zram_drv.c @@ -418,14 +418,6 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, goto out; } - /* - * System overwrites unused sectors. Free memory associated - * with this sector now. - */ - if (meta->table[index].handle || - zram_test_flag(meta, index, ZRAM_ZERO)) - zram_free_page(zram, index); - user_mem = kmap_atomic(page); if (is_partial_io(bvec)) { @@ -439,6 +431,9 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, if (page_zero_filled(uncmem)) { kunmap_atomic(user_mem); + /* Free memory associated with this sector now. */ + zram_free_page(zram, index); + zram->stats.pages_zero++; zram_set_flag(meta, index, ZRAM_ZERO); ret = 0; @@ -486,6 +481,12 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, zs_unmap_object(meta->mem_pool, handle); + /* + * Free memory associated with this sector + * before overwriting unused sectors. + */ + zram_free_page(zram, index); + meta->table[index].handle = handle; meta->table[index].size = clen; From 6496c045292b7afe74b5306c123186976f032125 Mon Sep 17 00:00:00 2001 From: Yijing Wang Date: Thu, 27 Jun 2013 20:57:23 +0800 Subject: [PATCH 0893/3400] vt6655/trivial: replace numeric with standard PM state macros Use standard PM state macros PCI_Dx instead of numeric 0/1/2.. Signed-off-by: Yijing Wang Cc: Forest Bond Cc: Jiri Kosina Cc: Devendra Naga Cc: Joe Perches Cc: Marcos Paulo de Souza Cc: Bill Pemberton Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/device_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index 08b250f01dae..7f36a7103c3e 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -3370,8 +3370,8 @@ viawget_resume(struct pci_dev *pcid) PSMgmtObject pMgmt = pDevice->pMgmt; int power_status; // to silence the compiler - power_status = pci_set_power_state(pcid, 0); - power_status = pci_enable_wake(pcid, 0, 0); + power_status = pci_set_power_state(pcid, PCI_D0); + power_status = pci_enable_wake(pcid, PCI_D0, 0); pci_restore_state(pcid); if (netif_running(pDevice->dev)) { spin_lock_irq(&pDevice->lock); From 5c2892698184bf82e1f7d5c557ad81c9570b569a Mon Sep 17 00:00:00 2001 From: Tomas Hozza Date: Thu, 27 Jun 2013 13:52:47 +0200 Subject: [PATCH 0894/3400] tools: hv: Improve error logging in VSS daemon. Use errno and strerror() when logging errors to provide more information. Signed-off-by: Tomas Hozza Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- tools/hv/hv_vss_daemon.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tools/hv/hv_vss_daemon.c b/tools/hv/hv_vss_daemon.c index fea03a3edaf4..64112e193552 100644 --- a/tools/hv/hv_vss_daemon.c +++ b/tools/hv/hv_vss_daemon.c @@ -156,7 +156,8 @@ int main(void) fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); if (fd < 0) { - syslog(LOG_ERR, "netlink socket creation failed; error:%d", fd); + syslog(LOG_ERR, "netlink socket creation failed; error:%d %s", + errno, strerror(errno)); exit(EXIT_FAILURE); } addr.nl_family = AF_NETLINK; @@ -167,7 +168,7 @@ int main(void) error = bind(fd, (struct sockaddr *)&addr, sizeof(addr)); if (error < 0) { - syslog(LOG_ERR, "bind failed; error:%d", error); + syslog(LOG_ERR, "bind failed; error:%d %s", errno, strerror(errno)); close(fd); exit(EXIT_FAILURE); } @@ -187,7 +188,7 @@ int main(void) len = netlink_send(fd, message); if (len < 0) { - syslog(LOG_ERR, "netlink_send failed; error:%d", len); + syslog(LOG_ERR, "netlink_send failed; error:%d %s", errno, strerror(errno)); close(fd); exit(EXIT_FAILURE); } @@ -241,7 +242,8 @@ int main(void) vss_msg->error = error; len = netlink_send(fd, incoming_cn_msg); if (len < 0) { - syslog(LOG_ERR, "net_link send failed; error:%d", len); + syslog(LOG_ERR, "net_link send failed; error:%d %s", + errno, strerror(errno)); exit(EXIT_FAILURE); } } From 9561d479314f16b41563f73511fb61d91de4642f Mon Sep 17 00:00:00 2001 From: Tomas Hozza Date: Thu, 27 Jun 2013 13:52:49 +0200 Subject: [PATCH 0895/3400] tools: hv: Check return value of poll call Check return value of poll call and if it fails print error to the system log. If errno is EINVAL then exit with non-zero value otherwise continue the while loop and call poll again. Signed-off-by: Tomas Hozza Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- tools/hv/hv_vss_daemon.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tools/hv/hv_vss_daemon.c b/tools/hv/hv_vss_daemon.c index 64112e193552..5febe3542f79 100644 --- a/tools/hv/hv_vss_daemon.c +++ b/tools/hv/hv_vss_daemon.c @@ -200,7 +200,16 @@ int main(void) socklen_t addr_l = sizeof(addr); pfd.events = POLLIN; pfd.revents = 0; - poll(&pfd, 1, -1); + + if (poll(&pfd, 1, -1) < 0) { + syslog(LOG_ERR, "poll failed; error:%d %s", errno, strerror(errno)); + if (errno == EINVAL) { + close(fd); + exit(EXIT_FAILURE); + } + else + continue; + } len = recvfrom(fd, vss_recv_buffer, sizeof(vss_recv_buffer), 0, addr_p, &addr_l); From d12e14692448e9f256028f53926a9bd3c3091e11 Mon Sep 17 00:00:00 2001 From: Tomas Hozza Date: Thu, 27 Jun 2013 13:52:48 +0200 Subject: [PATCH 0896/3400] tools: hv: Check return value of setsockopt call Check return value of setsockopt call and if it fails print error to the system log and exit with non-zero value. Signed-off-by: Tomas Hozza Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- tools/hv/hv_vss_daemon.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/hv/hv_vss_daemon.c b/tools/hv/hv_vss_daemon.c index 5febe3542f79..826d499dc354 100644 --- a/tools/hv/hv_vss_daemon.c +++ b/tools/hv/hv_vss_daemon.c @@ -173,7 +173,11 @@ int main(void) exit(EXIT_FAILURE); } nl_group = CN_VSS_IDX; - setsockopt(fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &nl_group, sizeof(nl_group)); + if (setsockopt(fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &nl_group, sizeof(nl_group)) < 0) { + syslog(LOG_ERR, "setsockopt failed; error:%d %s", errno, strerror(errno)); + close(fd); + exit(EXIT_FAILURE); + } /* * Register ourselves with the kernel. */ From 6741335bc7294548ac95cb1f4671991ff30da193 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Tue, 2 Jul 2013 10:31:30 -0700 Subject: [PATCH 0897/3400] Drivers: hv: util: Fix a bug in version negotiation code for util services The current code picked the highest version advertised by the host. WS2012 R2 has implemented a protocol version for KVP that is not compatible with prior protocol versions of KVP. Fix the bug in the current code by explicitly specifying the protocol version that the guest can support. Signed-off-by: K. Y. Srinivasan Reviewed-by: Haiyang Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/hv/channel_mgmt.c | 75 +++++++++++++++++++++++++++------------ drivers/hv/hv_kvp.c | 24 ++++++++++++- drivers/hv/hv_snapshot.c | 18 ++++------ drivers/hv/hv_util.c | 21 +++++++++-- include/linux/hyperv.h | 10 +++++- 5 files changed, 109 insertions(+), 39 deletions(-) diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index 0df75908200e..12ec8c801b25 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -48,30 +48,39 @@ struct vmbus_channel_message_table_entry { * @negop is of type &struct icmsg_negotiate. * Set up and fill in default negotiate response message. * - * The max_fw_version specifies the maximum framework version that - * we can support and max _srv_version specifies the maximum service - * version we can support. A special value MAX_SRV_VER can be - * specified to indicate that we can handle the maximum version - * exposed by the host. + * The fw_version specifies the framework version that + * we can support and srv_version specifies the service + * version we can support. * * Mainly used by Hyper-V drivers. */ -void vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, +bool vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, struct icmsg_negotiate *negop, u8 *buf, - int max_fw_version, int max_srv_version) + int fw_version, int srv_version) { - int icframe_vercnt; - int icmsg_vercnt; + int icframe_major, icframe_minor; + int icmsg_major, icmsg_minor; + int fw_major, fw_minor; + int srv_major, srv_minor; int i; + bool found_match = false; icmsghdrp->icmsgsize = 0x10; + fw_major = (fw_version >> 16); + fw_minor = (fw_version & 0xFFFF); + + srv_major = (srv_version >> 16); + srv_minor = (srv_version & 0xFFFF); negop = (struct icmsg_negotiate *)&buf[ sizeof(struct vmbuspipe_hdr) + sizeof(struct icmsg_hdr)]; - icframe_vercnt = negop->icframe_vercnt; - icmsg_vercnt = negop->icmsg_vercnt; + icframe_major = negop->icframe_vercnt; + icframe_minor = 0; + + icmsg_major = negop->icmsg_vercnt; + icmsg_minor = 0; /* * Select the framework version number we will @@ -79,26 +88,48 @@ void vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, */ for (i = 0; i < negop->icframe_vercnt; i++) { - if (negop->icversion_data[i].major <= max_fw_version) - icframe_vercnt = negop->icversion_data[i].major; + if ((negop->icversion_data[i].major == fw_major) && + (negop->icversion_data[i].minor == fw_minor)) { + icframe_major = negop->icversion_data[i].major; + icframe_minor = negop->icversion_data[i].minor; + found_match = true; + } } + if (!found_match) + goto fw_error; + + found_match = false; + for (i = negop->icframe_vercnt; (i < negop->icframe_vercnt + negop->icmsg_vercnt); i++) { - if (negop->icversion_data[i].major <= max_srv_version) - icmsg_vercnt = negop->icversion_data[i].major; + if ((negop->icversion_data[i].major == srv_major) && + (negop->icversion_data[i].minor == srv_minor)) { + icmsg_major = negop->icversion_data[i].major; + icmsg_minor = negop->icversion_data[i].minor; + found_match = true; + } } /* - * Respond with the maximum framework and service + * Respond with the framework and service * version numbers we can support. */ - negop->icframe_vercnt = 1; - negop->icmsg_vercnt = 1; - negop->icversion_data[0].major = icframe_vercnt; - negop->icversion_data[0].minor = 0; - negop->icversion_data[1].major = icmsg_vercnt; - negop->icversion_data[1].minor = 0; + +fw_error: + if (!found_match) { + negop->icframe_vercnt = 0; + negop->icmsg_vercnt = 0; + } else { + negop->icframe_vercnt = 1; + negop->icmsg_vercnt = 1; + } + + negop->icversion_data[0].major = icframe_major; + negop->icversion_data[0].minor = icframe_minor; + negop->icversion_data[1].major = icmsg_major; + negop->icversion_data[1].minor = icmsg_minor; + return found_match; } EXPORT_SYMBOL_GPL(vmbus_prep_negotiate_resp); diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c index ed50e9e83c61..53127209a404 100644 --- a/drivers/hv/hv_kvp.c +++ b/drivers/hv/hv_kvp.c @@ -29,6 +29,16 @@ #include +/* + * Pre win8 version numbers used in ws2008 and ws 2008 r2 (win7) + */ +#define WIN7_SRV_MAJOR 3 +#define WIN7_SRV_MINOR 0 +#define WIN7_SRV_MAJOR_MINOR (WIN7_SRV_MAJOR << 16 | WIN7_SRV_MINOR) + +#define WIN8_SRV_MAJOR 4 +#define WIN8_SRV_MINOR 0 +#define WIN8_SRV_MAJOR_MINOR (WIN8_SRV_MAJOR << 16 | WIN8_SRV_MINOR) /* * Global state maintained for transaction that is being processed. @@ -593,8 +603,19 @@ void hv_kvp_onchannelcallback(void *context) sizeof(struct vmbuspipe_hdr)]; if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { + /* + * We start with win8 version and if the host cannot + * support that we use the previous version. + */ + if (vmbus_prep_negotiate_resp(icmsghdrp, negop, + recv_buffer, UTIL_FW_MAJOR_MINOR, + WIN8_SRV_MAJOR_MINOR)) + goto done; + vmbus_prep_negotiate_resp(icmsghdrp, negop, - recv_buffer, MAX_SRV_VER, MAX_SRV_VER); + recv_buffer, UTIL_FW_MAJOR_MINOR, + WIN7_SRV_MAJOR_MINOR); + } else { kvp_msg = (struct hv_kvp_msg *)&recv_buffer[ sizeof(struct vmbuspipe_hdr) + @@ -626,6 +647,7 @@ void hv_kvp_onchannelcallback(void *context) return; } +done: icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE; diff --git a/drivers/hv/hv_snapshot.c b/drivers/hv/hv_snapshot.c index 8ad5653ce447..e4572f3f2834 100644 --- a/drivers/hv/hv_snapshot.c +++ b/drivers/hv/hv_snapshot.c @@ -24,6 +24,10 @@ #include #include +#define VSS_MAJOR 5 +#define VSS_MINOR 0 +#define VSS_MAJOR_MINOR (VSS_MAJOR << 16 | VSS_MINOR) + /* @@ -186,18 +190,8 @@ void hv_vss_onchannelcallback(void *context) if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { vmbus_prep_negotiate_resp(icmsghdrp, negop, - recv_buffer, MAX_SRV_VER, MAX_SRV_VER); - /* - * We currently negotiate the highest number the - * host has presented. If this version is not - * atleast 5.0, reject. - */ - negop = (struct icmsg_negotiate *)&recv_buffer[ - sizeof(struct vmbuspipe_hdr) + - sizeof(struct icmsg_hdr)]; - - if (negop->icversion_data[1].major < 5) - negop->icframe_vercnt = 0; + recv_buffer, UTIL_FW_MAJOR_MINOR, + VSS_MAJOR_MINOR); } else { vss_msg = (struct hv_vss_msg *)&recv_buffer[ sizeof(struct vmbuspipe_hdr) + diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c index 2f561c5dfe24..c16164d4a28b 100644 --- a/drivers/hv/hv_util.c +++ b/drivers/hv/hv_util.c @@ -28,6 +28,18 @@ #include #include +#define SHUTDOWN_MAJOR 3 +#define SHUTDOWN_MINOR 0 +#define SHUTDOWN_MAJOR_MINOR (SHUTDOWN_MAJOR << 16 | SHUTDOWN_MINOR) + +#define TIMESYNCH_MAJOR 3 +#define TIMESYNCH_MINOR 0 +#define TIMESYNCH_MAJOR_MINOR (TIMESYNCH_MAJOR << 16 | TIMESYNCH_MINOR) + +#define HEARTBEAT_MAJOR 3 +#define HEARTBEAT_MINOR 0 +#define HEARTBEAT_MAJOR_MINOR (HEARTBEAT_MAJOR << 16 | HEARTBEAT_MINOR) + static void shutdown_onchannelcallback(void *context); static struct hv_util_service util_shutdown = { .util_cb = shutdown_onchannelcallback, @@ -87,7 +99,8 @@ static void shutdown_onchannelcallback(void *context) if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { vmbus_prep_negotiate_resp(icmsghdrp, negop, - shut_txf_buf, MAX_SRV_VER, MAX_SRV_VER); + shut_txf_buf, UTIL_FW_MAJOR_MINOR, + SHUTDOWN_MAJOR_MINOR); } else { shutdown_msg = (struct shutdown_msg_data *)&shut_txf_buf[ @@ -213,7 +226,8 @@ static void timesync_onchannelcallback(void *context) if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { vmbus_prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf, - MAX_SRV_VER, MAX_SRV_VER); + UTIL_FW_MAJOR_MINOR, + TIMESYNCH_MAJOR_MINOR); } else { timedatap = (struct ictimesync_data *)&time_txf_buf[ sizeof(struct vmbuspipe_hdr) + @@ -253,7 +267,8 @@ static void heartbeat_onchannelcallback(void *context) if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { vmbus_prep_negotiate_resp(icmsghdrp, NULL, - hbeat_txf_buf, MAX_SRV_VER, MAX_SRV_VER); + hbeat_txf_buf, UTIL_FW_MAJOR_MINOR, + HEARTBEAT_MAJOR_MINOR); } else { heartbeat_msg = (struct heartbeat_msg_data *)&hbeat_txf_buf[ diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index fae8bac907ef..49949079cf47 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -27,6 +27,14 @@ #include +/* + * Framework version for util services. + */ + +#define UTIL_FW_MAJOR 3 +#define UTIL_FW_MINOR 0 +#define UTIL_FW_MAJOR_MINOR (UTIL_FW_MAJOR << 16 | UTIL_FW_MINOR) + /* * Implementation of host controlled snapshot of the guest. @@ -1494,7 +1502,7 @@ struct hyperv_service_callback { }; #define MAX_SRV_VER 0x7ffffff -extern void vmbus_prep_negotiate_resp(struct icmsg_hdr *, +extern bool vmbus_prep_negotiate_resp(struct icmsg_hdr *, struct icmsg_negotiate *, u8 *, int, int); From 20138d6cb838aa01bb1b382dcb5f3d3a119ff2cb Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Wed, 17 Jul 2013 17:27:27 -0700 Subject: [PATCH 0898/3400] Drivers: hv: balloon: Initialize the transaction ID just before sending the packet Each message sent from the guest carries with it a transaction ID. Assign the transaction ID just before putting the message on the VMBUS. This would help in debugging on the host side. Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- drivers/hv/hv_balloon.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c index 4c605c70ebf9..8dd08c029da2 100644 --- a/drivers/hv/hv_balloon.c +++ b/drivers/hv/hv_balloon.c @@ -828,7 +828,6 @@ static void hot_add_req(struct work_struct *dummy) memset(&resp, 0, sizeof(struct dm_hot_add_response)); resp.hdr.type = DM_MEM_HOT_ADD_RESPONSE; resp.hdr.size = sizeof(struct dm_hot_add_response); - resp.hdr.trans_id = atomic_inc_return(&trans_id); #ifdef CONFIG_MEMORY_HOTPLUG pg_start = dm->ha_wrk.ha_page_range.finfo.start_page; @@ -890,6 +889,7 @@ static void hot_add_req(struct work_struct *dummy) pr_info("Memory hot add failed\n"); dm->state = DM_INITIALIZED; + resp.hdr.trans_id = atomic_inc_return(&trans_id); vmbus_sendpacket(dm->dev->channel, &resp, sizeof(struct dm_hot_add_response), (unsigned long)NULL, @@ -1076,7 +1076,6 @@ static void balloon_up(struct work_struct *dummy) bl_resp = (struct dm_balloon_response *)send_buffer; memset(send_buffer, 0, PAGE_SIZE); bl_resp->hdr.type = DM_BALLOON_RESPONSE; - bl_resp->hdr.trans_id = atomic_inc_return(&trans_id); bl_resp->hdr.size = sizeof(struct dm_balloon_response); bl_resp->more_pages = 1; @@ -1104,6 +1103,7 @@ static void balloon_up(struct work_struct *dummy) */ do { + bl_resp->hdr.trans_id = atomic_inc_return(&trans_id); ret = vmbus_sendpacket(dm_device.dev->channel, bl_resp, bl_resp->hdr.size, From b950ac1dabfcbf97b99f26fa75f86087e1960aef Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 25 Jul 2013 20:15:53 +0300 Subject: [PATCH 0899/3400] mei: don't get stuck in select during reset Clear pending connection after hw reset but before hw start and wake up the waiting task in poll. Signal POLLERR in select when device went through reset. Add wrapper mei_cl_is_connected for checking if the device and client are connected. Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 14 +++++++++++--- drivers/misc/mei/client.c | 5 +---- drivers/misc/mei/client.h | 7 +++++++ drivers/misc/mei/init.c | 13 ++++++++----- drivers/misc/mei/main.c | 22 +++++++++++++++------- 5 files changed, 42 insertions(+), 19 deletions(-) diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index 749452f8e2f6..d0fdc134068a 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -418,15 +418,23 @@ unsigned int mei_amthif_poll(struct mei_device *dev, struct file *file, poll_table *wait) { unsigned int mask = 0; - mutex_unlock(&dev->device_lock); + poll_wait(file, &dev->iamthif_cl.wait, wait); + mutex_lock(&dev->device_lock); - if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE && - dev->iamthif_file_object == file) { + if (!mei_cl_is_connected(&dev->iamthif_cl)) { + + mask = POLLERR; + + } else if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE && + dev->iamthif_file_object == file) { + mask |= (POLLIN | POLLRDNORM); dev_dbg(&dev->pdev->dev, "run next amthif cb\n"); mei_amthif_run_next_cmd(dev); } + mutex_unlock(&dev->device_lock); + return mask; } diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index af1e60205140..e0684b4d9a08 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -635,10 +635,7 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length) dev = cl->dev; - if (cl->state != MEI_FILE_CONNECTED) - return -ENODEV; - - if (dev->dev_state != MEI_DEV_ENABLED) + if (!mei_cl_is_connected(cl)) return -ENODEV; if (cl->read_cb) { diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h index 9bae4c724603..9eb031e92070 100644 --- a/drivers/misc/mei/client.h +++ b/drivers/misc/mei/client.h @@ -84,6 +84,13 @@ int mei_cl_flow_ctrl_reduce(struct mei_cl *cl); /* * MEI input output function prototype */ +static inline bool mei_cl_is_connected(struct mei_cl *cl) +{ + return (cl->dev && + cl->dev->dev_state == MEI_DEV_ENABLED && + cl->state == MEI_FILE_CONNECTED); +} + bool mei_cl_is_other_connecting(struct mei_cl *cl); int mei_cl_disconnect(struct mei_cl *cl); int mei_cl_connect(struct mei_cl *cl, struct file *file); diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index 7929e14627ba..557eed2a1595 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c @@ -149,12 +149,20 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) dev->hbm_state = MEI_HBM_IDLE; if (dev->dev_state != MEI_DEV_INITIALIZING) { + if (dev->dev_state != MEI_DEV_DISABLED && dev->dev_state != MEI_DEV_POWER_DOWN) dev->dev_state = MEI_DEV_RESETTING; + + /* remove all waiting requests */ + mei_cl_all_write_clear(dev); + mei_cl_all_disconnect(dev); + /* wake up all readings so they can be interrupted */ + mei_cl_all_wakeup(dev); + /* remove entry if already in list */ dev_dbg(&dev->pdev->dev, "remove iamthif and wd from the file list.\n"); mei_cl_unlink(&dev->wd_cl); @@ -195,11 +203,6 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) mei_hbm_start_req(dev); - /* wake up all readings so they can be interrupted */ - mei_cl_all_wakeup(dev); - - /* remove all waiting requests */ - mei_cl_all_write_clear(dev); } EXPORT_SYMBOL_GPL(mei_reset); diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 5e11b5b9b65d..173ff095be0d 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -625,24 +625,32 @@ static unsigned int mei_poll(struct file *file, poll_table *wait) unsigned int mask = 0; if (WARN_ON(!cl || !cl->dev)) - return mask; + return POLLERR; dev = cl->dev; mutex_lock(&dev->device_lock); - if (dev->dev_state != MEI_DEV_ENABLED) - goto out; - - - if (cl == &dev->iamthif_cl) { - mask = mei_amthif_poll(dev, file, wait); + if (!mei_cl_is_connected(cl)) { + mask = POLLERR; goto out; } mutex_unlock(&dev->device_lock); + + + if (cl == &dev->iamthif_cl) + return mei_amthif_poll(dev, file, wait); + poll_wait(file, &cl->tx_wait, wait); + mutex_lock(&dev->device_lock); + + if (!mei_cl_is_connected(cl)) { + mask = POLLERR; + goto out; + } + if (MEI_WRITE_COMPLETE == cl->writing_state) mask |= (POLLIN | POLLRDNORM); From 26dac3c49d56642b06c07c80a2184abbf510920f Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Wed, 26 Jun 2013 11:52:12 +0200 Subject: [PATCH 0900/3400] uio: Remove uio_pdrv and use uio_pdrv_genirq instead The patch "UIO: fix uio_pdrv_genirq with device tree but no interrupt" (sha1: e3a3c3a205554e564751cd9c0276b2af813d7a92) add support to use this driver with no interrupts. uio_pdrv_genirq also supports device-tree binding which is not available in uio_pdrv. That's why this uio_pdrv driver can be just removed. Signed-off-by: Michal Simek Reviewed-by: Vitalii Demianets Reviewed-by: Pavel Machek Signed-off-by: Greg Kroah-Hartman --- drivers/uio/Kconfig | 7 --- drivers/uio/Makefile | 1 - drivers/uio/uio_pdrv.c | 113 ----------------------------------------- 3 files changed, 121 deletions(-) delete mode 100644 drivers/uio/uio_pdrv.c diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig index 5295be0342c1..a81d16389a58 100644 --- a/drivers/uio/Kconfig +++ b/drivers/uio/Kconfig @@ -23,13 +23,6 @@ config UIO_CIF To compile this driver as a module, choose M here: the module will be called uio_cif. -config UIO_PDRV - tristate "Userspace I/O platform driver" - help - Generic platform driver for Userspace I/O devices. - - If you don't know what to do here, say N. - config UIO_PDRV_GENIRQ tristate "Userspace I/O platform driver with generic IRQ handling" help diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile index b354c539507a..ea015a290127 100644 --- a/drivers/uio/Makefile +++ b/drivers/uio/Makefile @@ -1,6 +1,5 @@ obj-$(CONFIG_UIO) += uio.o 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_DMEM_GENIRQ) += uio_dmem_genirq.o obj-$(CONFIG_UIO_AEC) += uio_aec.o diff --git a/drivers/uio/uio_pdrv.c b/drivers/uio/uio_pdrv.c deleted file mode 100644 index 39be9e061700..000000000000 --- a/drivers/uio/uio_pdrv.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * drivers/uio/uio_pdrv.c - * - * Copyright (C) 2008 by Digi International 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. - */ -#include -#include -#include -#include -#include - -#define DRIVER_NAME "uio_pdrv" - -struct uio_platdata { - struct uio_info *uioinfo; -}; - -static int uio_pdrv_probe(struct platform_device *pdev) -{ - struct uio_info *uioinfo = pdev->dev.platform_data; - struct uio_platdata *pdata; - struct uio_mem *uiomem; - int ret = -ENODEV; - int i; - - if (!uioinfo || !uioinfo->name || !uioinfo->version) { - dev_dbg(&pdev->dev, "%s: err_uioinfo\n", __func__); - goto err_uioinfo; - } - - pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); - if (!pdata) { - ret = -ENOMEM; - dev_dbg(&pdev->dev, "%s: err_alloc_pdata\n", __func__); - goto err_alloc_pdata; - } - - pdata->uioinfo = uioinfo; - - uiomem = &uioinfo->mem[0]; - - for (i = 0; i < pdev->num_resources; ++i) { - struct resource *r = &pdev->resource[i]; - - if (r->flags != IORESOURCE_MEM) - continue; - - if (uiomem >= &uioinfo->mem[MAX_UIO_MAPS]) { - dev_warn(&pdev->dev, "device has more than " - __stringify(MAX_UIO_MAPS) - " I/O memory resources.\n"); - break; - } - - uiomem->memtype = UIO_MEM_PHYS; - uiomem->addr = r->start; - uiomem->size = resource_size(r); - uiomem->name = r->name; - ++uiomem; - } - - while (uiomem < &uioinfo->mem[MAX_UIO_MAPS]) { - uiomem->size = 0; - ++uiomem; - } - - pdata->uioinfo->priv = pdata; - - ret = uio_register_device(&pdev->dev, pdata->uioinfo); - - if (ret) { - kfree(pdata); -err_alloc_pdata: -err_uioinfo: - return ret; - } - - platform_set_drvdata(pdev, pdata); - - return 0; -} - -static int uio_pdrv_remove(struct platform_device *pdev) -{ - struct uio_platdata *pdata = platform_get_drvdata(pdev); - - uio_unregister_device(pdata->uioinfo); - - kfree(pdata); - - return 0; -} - -static struct platform_driver uio_pdrv = { - .probe = uio_pdrv_probe, - .remove = uio_pdrv_remove, - .driver = { - .name = DRIVER_NAME, - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(uio_pdrv); - -MODULE_AUTHOR("Uwe Kleine-Koenig"); -MODULE_DESCRIPTION("Userspace I/O platform driver"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:" DRIVER_NAME); From ecda040ff3724f021a96491ecee88d48e968c153 Mon Sep 17 00:00:00 2001 From: Alexandru Juncu Date: Fri, 19 Jul 2013 11:24:03 +0300 Subject: [PATCH 0901/3400] pcmcia: synclink_cs: replace sum of bitmasks with OR operation. Suggested by coccinelle and manually verified. Signed-off-by: Alexandru Juncu Signed-off-by: Greg Kroah-Hartman --- drivers/char/pcmcia/synclink_cs.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 5c5cc00ebb07..d39cca659a3f 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -1182,14 +1182,14 @@ static irqreturn_t mgslpc_isr(int dummy, void *dev_id) } count++; - if (gis & (BIT1 + BIT0)) { + if (gis & (BIT1 | BIT0)) { isr = read_reg16(info, CHB + ISR); if (isr & IRQ_DCD) dcd_change(info, tty); if (isr & IRQ_CTS) cts_change(info, tty); } - if (gis & (BIT3 + BIT2)) + if (gis & (BIT3 | BIT2)) { isr = read_reg16(info, CHA + ISR); if (isr & IRQ_TIMER) { @@ -1210,7 +1210,7 @@ static irqreturn_t mgslpc_isr(int dummy, void *dev_id) if (isr & IRQ_RXTIME) { issue_command(info, CHA, CMD_RXFIFO_READ); } - if (isr & (IRQ_RXEOM + IRQ_RXFIFO)) { + if (isr & (IRQ_RXEOM | IRQ_RXFIFO)) { if (info->params.mode == MGSL_MODE_HDLC) rx_ready_hdlc(info, isr & IRQ_RXEOM); else @@ -3031,11 +3031,11 @@ static void loopback_enable(MGSLPC_INFO *info) unsigned char val; /* CCR1:02..00 CM[2..0] Clock Mode = 111 (clock mode 7) */ - val = read_reg(info, CHA + CCR1) | (BIT2 + BIT1 + BIT0); + val = read_reg(info, CHA + CCR1) | (BIT2 | BIT1 | BIT0); write_reg(info, CHA + CCR1, val); /* CCR2:04 SSEL Clock source select, 1=submode b */ - val = read_reg(info, CHA + CCR2) | (BIT4 + BIT5); + val = read_reg(info, CHA + CCR2) | (BIT4 | BIT5); write_reg(info, CHA + CCR2, val); /* set LinkSpeed if available, otherwise default to 2Mbps */ @@ -3125,10 +3125,10 @@ static void hdlc_mode(MGSLPC_INFO *info) val |= BIT4; break; // FM0 case HDLC_ENCODING_BIPHASE_MARK: - val |= BIT4 + BIT2; + val |= BIT4 | BIT2; break; // FM1 case HDLC_ENCODING_BIPHASE_LEVEL: - val |= BIT4 + BIT3; + val |= BIT4 | BIT3; break; // Manchester } write_reg(info, CHA + CCR0, val); @@ -3185,7 +3185,7 @@ static void hdlc_mode(MGSLPC_INFO *info) */ val = 0x00; if (info->params.crc_type == HDLC_CRC_NONE) - val |= BIT2 + BIT1; + val |= BIT2 | BIT1; if (info->params.preamble != HDLC_PREAMBLE_PATTERN_NONE) val |= BIT5; switch (info->params.preamble_length) @@ -3197,7 +3197,7 @@ static void hdlc_mode(MGSLPC_INFO *info) val |= BIT6; break; case HDLC_PREAMBLE_LENGTH_64BITS: - val |= BIT7 + BIT6; + val |= BIT7 | BIT6; break; } write_reg(info, CHA + CCR3, val); @@ -3264,8 +3264,8 @@ static void hdlc_mode(MGSLPC_INFO *info) clear_reg_bits(info, CHA + PVR, BIT3); irq_enable(info, CHA, - IRQ_RXEOM + IRQ_RXFIFO + IRQ_ALLSENT + - IRQ_UNDERRUN + IRQ_TXFIFO); + IRQ_RXEOM | IRQ_RXFIFO | IRQ_ALLSENT | + IRQ_UNDERRUN | IRQ_TXFIFO); issue_command(info, CHA, CMD_TXRESET + CMD_RXRESET); wait_command_complete(info, CHA); read_reg16(info, CHA + ISR); /* clear pending IRQs */ @@ -3582,8 +3582,8 @@ static void async_mode(MGSLPC_INFO *info) } else clear_reg_bits(info, CHA + PVR, BIT3); irq_enable(info, CHA, - IRQ_RXEOM + IRQ_RXFIFO + IRQ_BREAK_ON + IRQ_RXTIME + - IRQ_ALLSENT + IRQ_TXFIFO); + IRQ_RXEOM | IRQ_RXFIFO | IRQ_BREAK_ON | IRQ_RXTIME | + IRQ_ALLSENT | IRQ_TXFIFO); issue_command(info, CHA, CMD_TXRESET + CMD_RXRESET); wait_command_complete(info, CHA); read_reg16(info, CHA + ISR); /* clear pending IRQs */ From 86df268705696ce2286410f1493e294e889bdce6 Mon Sep 17 00:00:00 2001 From: David Graham White Date: Sun, 21 Jul 2013 20:41:14 -0400 Subject: [PATCH 0902/3400] drivers:base:core: Moved sym export macros to respective functions Moved 11 calls to the EXPORT_SYMBOL_GPL beneath their respective functions per checkpatch.pl warnings. Signed-off-by: David Graham White Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index 8856d74545d9..4b9b0d7f6022 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -626,6 +626,7 @@ int device_create_file(struct device *dev, return error; } +EXPORT_SYMBOL_GPL(device_create_file); /** * device_remove_file - remove sysfs attribute file. @@ -638,6 +639,7 @@ void device_remove_file(struct device *dev, if (dev) sysfs_remove_file(&dev->kobj, &attr->attr); } +EXPORT_SYMBOL_GPL(device_remove_file); /** * device_create_bin_file - create sysfs binary attribute file for device. @@ -748,6 +750,7 @@ void device_initialize(struct device *dev) device_pm_init(dev); set_dev_node(dev, -1); } +EXPORT_SYMBOL_GPL(device_initialize); struct kobject *virtual_device_parent(struct device *dev) { @@ -1187,6 +1190,7 @@ name_error: dev->p = NULL; goto done; } +EXPORT_SYMBOL_GPL(device_add); /** * device_register - register a device with the system. @@ -1211,6 +1215,7 @@ int device_register(struct device *dev) device_initialize(dev); return device_add(dev); } +EXPORT_SYMBOL_GPL(device_register); /** * get_device - increment reference count for device. @@ -1224,6 +1229,7 @@ struct device *get_device(struct device *dev) { return dev ? kobj_to_dev(kobject_get(&dev->kobj)) : NULL; } +EXPORT_SYMBOL_GPL(get_device); /** * put_device - decrement reference count. @@ -1235,6 +1241,7 @@ void put_device(struct device *dev) if (dev) kobject_put(&dev->kobj); } +EXPORT_SYMBOL_GPL(put_device); /** * device_del - delete device from system. @@ -1297,6 +1304,7 @@ void device_del(struct device *dev) kobject_del(&dev->kobj); put_device(parent); } +EXPORT_SYMBOL_GPL(device_del); /** * device_unregister - unregister device from system. @@ -1315,6 +1323,7 @@ void device_unregister(struct device *dev) device_del(dev); put_device(dev); } +EXPORT_SYMBOL_GPL(device_unregister); static struct device *next_device(struct klist_iter *i) { @@ -1403,6 +1412,7 @@ int device_for_each_child(struct device *parent, void *data, klist_iter_exit(&i); return error; } +EXPORT_SYMBOL_GPL(device_for_each_child); /** * device_find_child - device iterator for locating a particular device. @@ -1437,6 +1447,7 @@ struct device *device_find_child(struct device *parent, void *data, klist_iter_exit(&i); return child; } +EXPORT_SYMBOL_GPL(device_find_child); int __init devices_init(void) { @@ -1464,21 +1475,6 @@ int __init devices_init(void) return -ENOMEM; } -EXPORT_SYMBOL_GPL(device_for_each_child); -EXPORT_SYMBOL_GPL(device_find_child); - -EXPORT_SYMBOL_GPL(device_initialize); -EXPORT_SYMBOL_GPL(device_add); -EXPORT_SYMBOL_GPL(device_register); - -EXPORT_SYMBOL_GPL(device_del); -EXPORT_SYMBOL_GPL(device_unregister); -EXPORT_SYMBOL_GPL(get_device); -EXPORT_SYMBOL_GPL(put_device); - -EXPORT_SYMBOL_GPL(device_create_file); -EXPORT_SYMBOL_GPL(device_remove_file); - static DEFINE_MUTEX(device_hotplug_lock); void lock_device_hotplug(void) From 34da5e6770ac06df770a0355b417155e6e84e263 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Fri, 26 Jul 2013 13:10:22 +0900 Subject: [PATCH 0903/3400] driver core: replace strict_strto*() with kstrto*() The usage of strict_strto*() is not preferred, because strict_strto*() is obsolete. Thus, kstrto*() should be used. Signed-off-by: Jingoo Han Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 2 +- drivers/base/memory.c | 4 ++-- drivers/base/power/sysfs.c | 2 +- drivers/base/regmap/regmap-debugfs.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index 4b9b0d7f6022..e51c78782933 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -38,7 +38,7 @@ long sysfs_deprecated = 0; #endif static __init int sysfs_deprecated_setup(char *arg) { - return strict_strtol(arg, 10, &sysfs_deprecated); + return kstrtol(arg, 10, &sysfs_deprecated); } early_param("sysfs.deprecated", sysfs_deprecated_setup); #endif diff --git a/drivers/base/memory.c b/drivers/base/memory.c index 2b7813ec6d02..ddd14ce6654c 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -469,7 +469,7 @@ store_soft_offline_page(struct device *dev, u64 pfn; if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (strict_strtoull(buf, 0, &pfn) < 0) + if (kstrtoull(buf, 0, &pfn) < 0) return -EINVAL; pfn >>= PAGE_SHIFT; if (!pfn_valid(pfn)) @@ -488,7 +488,7 @@ store_hard_offline_page(struct device *dev, u64 pfn; if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (strict_strtoull(buf, 0, &pfn) < 0) + if (kstrtoull(buf, 0, &pfn) < 0) return -EINVAL; pfn >>= PAGE_SHIFT; ret = memory_failure(pfn, 0, 0); diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c index a53ebd265701..03e089ade5ce 100644 --- a/drivers/base/power/sysfs.c +++ b/drivers/base/power/sysfs.c @@ -206,7 +206,7 @@ static ssize_t autosuspend_delay_ms_store(struct device *dev, if (!dev->power.use_autosuspend) return -EIO; - if (strict_strtol(buf, 10, &delay) != 0 || delay != (int) delay) + if (kstrtol(buf, 10, &delay) != 0 || delay != (int) delay) return -EINVAL; device_lock(dev); diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c index 53495753fbdb..634164da9c15 100644 --- a/drivers/base/regmap/regmap-debugfs.c +++ b/drivers/base/regmap/regmap-debugfs.c @@ -281,7 +281,7 @@ static ssize_t regmap_map_write_file(struct file *file, reg = simple_strtoul(start, &start, 16); while (*start == ' ') start++; - if (strict_strtoul(start, 16, &value)) + if (kstrtoul(start, 16, &value)) return -EINVAL; /* Userspace has been fiddling around behind the kernel's back */ From d98259cbf9f1c86e921caa1241aa8d229249e0b8 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Jul 2013 15:05:12 -0700 Subject: [PATCH 0904/3400] ISDN: convert class code to use dev_groups The dev_attrs field of struct class is going away soon, dev_groups should be used instead. This converts the mISDN class code to use the correct field. Acked-by: Karsten Keil Signed-off-by: Greg Kroah-Hartman --- drivers/isdn/mISDN/core.c | 62 ++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 27 deletions(-) diff --git a/drivers/isdn/mISDN/core.c b/drivers/isdn/mISDN/core.c index da30c5cb9609..faf505462a4f 100644 --- a/drivers/isdn/mISDN/core.c +++ b/drivers/isdn/mISDN/core.c @@ -37,8 +37,8 @@ static void mISDN_dev_release(struct device *dev) /* nothing to do: the device is part of its parent's data structure */ } -static ssize_t _show_id(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t id_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct mISDNdevice *mdev = dev_to_mISDN(dev); @@ -46,9 +46,10 @@ static ssize_t _show_id(struct device *dev, return -ENODEV; return sprintf(buf, "%d\n", mdev->id); } +static DEVICE_ATTR_RO(id); -static ssize_t _show_nrbchan(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t nrbchan_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct mISDNdevice *mdev = dev_to_mISDN(dev); @@ -56,9 +57,10 @@ static ssize_t _show_nrbchan(struct device *dev, return -ENODEV; return sprintf(buf, "%d\n", mdev->nrbchan); } +static DEVICE_ATTR_RO(nrbchan); -static ssize_t _show_d_protocols(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t d_protocols_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct mISDNdevice *mdev = dev_to_mISDN(dev); @@ -66,9 +68,10 @@ static ssize_t _show_d_protocols(struct device *dev, return -ENODEV; return sprintf(buf, "%d\n", mdev->Dprotocols); } +static DEVICE_ATTR_RO(d_protocols); -static ssize_t _show_b_protocols(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t b_protocols_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct mISDNdevice *mdev = dev_to_mISDN(dev); @@ -76,9 +79,10 @@ static ssize_t _show_b_protocols(struct device *dev, return -ENODEV; return sprintf(buf, "%d\n", mdev->Bprotocols | get_all_Bprotocols()); } +static DEVICE_ATTR_RO(b_protocols); -static ssize_t _show_protocol(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t protocol_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct mISDNdevice *mdev = dev_to_mISDN(dev); @@ -86,17 +90,19 @@ static ssize_t _show_protocol(struct device *dev, return -ENODEV; return sprintf(buf, "%d\n", mdev->D.protocol); } +static DEVICE_ATTR_RO(protocol); -static ssize_t _show_name(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t name_show(struct device *dev, + struct device_attribute *attr, char *buf) { strcpy(buf, dev_name(dev)); return strlen(buf); } +static DEVICE_ATTR_RO(name); #if 0 /* hangs */ -static ssize_t _set_name(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t name_set(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { int err = 0; char *out = kmalloc(count + 1, GFP_KERNEL); @@ -113,10 +119,11 @@ static ssize_t _set_name(struct device *dev, struct device_attribute *attr, return (err < 0) ? err : count; } +static DEVICE_ATTR_RW(name); #endif -static ssize_t _show_channelmap(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t channelmap_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct mISDNdevice *mdev = dev_to_mISDN(dev); char *bp = buf; @@ -127,18 +134,19 @@ static ssize_t _show_channelmap(struct device *dev, return bp - buf; } +static DEVICE_ATTR_RO(channelmap); -static struct device_attribute mISDN_dev_attrs[] = { - __ATTR(id, S_IRUGO, _show_id, NULL), - __ATTR(d_protocols, S_IRUGO, _show_d_protocols, NULL), - __ATTR(b_protocols, S_IRUGO, _show_b_protocols, NULL), - __ATTR(protocol, S_IRUGO, _show_protocol, NULL), - __ATTR(channelmap, S_IRUGO, _show_channelmap, NULL), - __ATTR(nrbchan, S_IRUGO, _show_nrbchan, NULL), - __ATTR(name, S_IRUGO, _show_name, NULL), -/* __ATTR(name, S_IRUGO | S_IWUSR, _show_name, _set_name), */ - {} +static struct attribute *mISDN_attrs[] = { + &dev_attr_id.attr, + &dev_attr_d_protocols.attr, + &dev_attr_b_protocols.attr, + &dev_attr_protocol.attr, + &dev_attr_channelmap.attr, + &dev_attr_nrbchan.attr, + &dev_attr_name.attr, + NULL, }; +ATTRIBUTE_GROUPS(mISDN); static int mISDN_uevent(struct device *dev, struct kobj_uevent_env *env) { @@ -162,7 +170,7 @@ static struct class mISDN_class = { .name = "mISDN", .owner = THIS_MODULE, .dev_uevent = mISDN_uevent, - .dev_attrs = mISDN_dev_attrs, + .dev_groups = mISDN_groups, .dev_release = mISDN_dev_release, .class_release = mISDN_class_release, }; From 5baa7503a7a0b8d65308ff3b2ab887bf343c65d3 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Jul 2013 15:05:13 -0700 Subject: [PATCH 0905/3400] leds: convert class code to use dev_groups The dev_attrs field of struct class is going away soon, dev_groups should be used instead. This converts the led class code to use the correct field. Acked-by: Bryan Wu Cc: Richard Purdie Signed-off-by: Greg Kroah-Hartman --- drivers/leds/led-class.c | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index 4336e37a97f4..f37d63cf726b 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -29,7 +29,7 @@ static void led_update_brightness(struct led_classdev *led_cdev) led_cdev->brightness = led_cdev->brightness_get(led_cdev); } -static ssize_t led_brightness_show(struct device *dev, +static ssize_t brightness_show(struct device *dev, struct device_attribute *attr, char *buf) { struct led_classdev *led_cdev = dev_get_drvdata(dev); @@ -40,7 +40,7 @@ static ssize_t led_brightness_show(struct device *dev, return sprintf(buf, "%u\n", led_cdev->brightness); } -static ssize_t led_brightness_store(struct device *dev, +static ssize_t brightness_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { struct led_classdev *led_cdev = dev_get_drvdata(dev); @@ -57,6 +57,7 @@ static ssize_t led_brightness_store(struct device *dev, return size; } +static DEVICE_ATTR_RW(brightness); static ssize_t led_max_brightness_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -65,14 +66,35 @@ static ssize_t led_max_brightness_show(struct device *dev, return sprintf(buf, "%u\n", led_cdev->max_brightness); } +static DEVICE_ATTR(max_brightness, 0444, led_max_brightness_show, NULL); -static struct device_attribute led_class_attrs[] = { - __ATTR(brightness, 0644, led_brightness_show, led_brightness_store), - __ATTR(max_brightness, 0444, led_max_brightness_show, NULL), #ifdef CONFIG_LEDS_TRIGGERS - __ATTR(trigger, 0644, led_trigger_show, led_trigger_store), +static DEVICE_ATTR(trigger, 0644, led_trigger_show, led_trigger_store); +static struct attribute *led_trigger_attrs[] = { + &dev_attr_trigger.attr, + NULL, +}; +static const struct attribute_group led_trigger_group = { + .attrs = led_trigger_attrs, +}; #endif - __ATTR_NULL, + +static struct attribute *led_class_attrs[] = { + &dev_attr_brightness.attr, + &dev_attr_max_brightness.attr, + NULL, +}; + +static const struct attribute_group led_group = { + .attrs = led_class_attrs, +}; + +static const struct attribute_group *led_groups[] = { + &led_group, +#ifdef CONFIG_LEDS_TRIGGERS + &led_trigger_group, +#endif + NULL, }; static void led_timer_function(unsigned long data) @@ -258,7 +280,7 @@ static int __init leds_init(void) if (IS_ERR(leds_class)) return PTR_ERR(leds_class); leds_class->pm = &leds_class_dev_pm_ops; - leds_class->dev_attrs = led_class_attrs; + leds_class->dev_groups = led_groups; return 0; } From 3499116b915e260b275c167a471e0e05bbe3f1d6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Jul 2013 15:05:20 -0700 Subject: [PATCH 0906/3400] PTP: convert class code to use dev_groups The dev_attrs field of struct class is going away soon, dev_groups should be used instead. This converts the ptp class code to use the correct field. Acked-by: Richard Cochran Signed-off-by: Greg Kroah-Hartman --- drivers/ptp/ptp_clock.c | 2 +- drivers/ptp/ptp_private.h | 2 +- drivers/ptp/ptp_sysfs.c | 51 ++++++++++++++++++++++----------------- 3 files changed, 31 insertions(+), 24 deletions(-) diff --git a/drivers/ptp/ptp_clock.c b/drivers/ptp/ptp_clock.c index 4a8c388364ca..a8319b266643 100644 --- a/drivers/ptp/ptp_clock.c +++ b/drivers/ptp/ptp_clock.c @@ -330,7 +330,7 @@ static int __init ptp_init(void) goto no_region; } - ptp_class->dev_attrs = ptp_dev_attrs; + ptp_class->dev_groups = ptp_groups; pr_info("PTP clock support registered\n"); return 0; diff --git a/drivers/ptp/ptp_private.h b/drivers/ptp/ptp_private.h index 69d32070cc65..df03f2e30ad9 100644 --- a/drivers/ptp/ptp_private.h +++ b/drivers/ptp/ptp_private.h @@ -84,7 +84,7 @@ uint ptp_poll(struct posix_clock *pc, * see ptp_sysfs.c */ -extern struct device_attribute ptp_dev_attrs[]; +extern const struct attribute_group *ptp_groups[]; int ptp_cleanup_sysfs(struct ptp_clock *ptp); diff --git a/drivers/ptp/ptp_sysfs.c b/drivers/ptp/ptp_sysfs.c index 2f93926ac976..13ec5311746a 100644 --- a/drivers/ptp/ptp_sysfs.c +++ b/drivers/ptp/ptp_sysfs.c @@ -27,36 +27,43 @@ static ssize_t clock_name_show(struct device *dev, struct ptp_clock *ptp = dev_get_drvdata(dev); return snprintf(page, PAGE_SIZE-1, "%s\n", ptp->info->name); } +static DEVICE_ATTR(clock_name, 0444, clock_name_show, NULL); -#define PTP_SHOW_INT(name) \ -static ssize_t name##_show(struct device *dev, \ +#define PTP_SHOW_INT(name, var) \ +static ssize_t var##_show(struct device *dev, \ struct device_attribute *attr, char *page) \ { \ struct ptp_clock *ptp = dev_get_drvdata(dev); \ - return snprintf(page, PAGE_SIZE-1, "%d\n", ptp->info->name); \ -} + return snprintf(page, PAGE_SIZE-1, "%d\n", ptp->info->var); \ +} \ +static DEVICE_ATTR(name, 0444, var##_show, NULL); -PTP_SHOW_INT(max_adj); -PTP_SHOW_INT(n_alarm); -PTP_SHOW_INT(n_ext_ts); -PTP_SHOW_INT(n_per_out); -PTP_SHOW_INT(pps); +PTP_SHOW_INT(max_adjustment, max_adj); +PTP_SHOW_INT(n_alarms, n_alarm); +PTP_SHOW_INT(n_external_timestamps, n_ext_ts); +PTP_SHOW_INT(n_periodic_outputs, n_per_out); +PTP_SHOW_INT(pps_available, pps); -#define PTP_RO_ATTR(_var, _name) { \ - .attr = { .name = __stringify(_name), .mode = 0444 }, \ - .show = _var##_show, \ -} - -struct device_attribute ptp_dev_attrs[] = { - PTP_RO_ATTR(clock_name, clock_name), - PTP_RO_ATTR(max_adj, max_adjustment), - PTP_RO_ATTR(n_alarm, n_alarms), - PTP_RO_ATTR(n_ext_ts, n_external_timestamps), - PTP_RO_ATTR(n_per_out, n_periodic_outputs), - PTP_RO_ATTR(pps, pps_available), - __ATTR_NULL, +static struct attribute *ptp_attrs[] = { + &dev_attr_clock_name.attr, + &dev_attr_max_adjustment.attr, + &dev_attr_n_alarms.attr, + &dev_attr_n_external_timestamps.attr, + &dev_attr_n_periodic_outputs.attr, + &dev_attr_pps_available.attr, + NULL, }; +static const struct attribute_group ptp_group = { + .attrs = ptp_attrs, +}; + +const struct attribute_group *ptp_groups[] = { + &ptp_group, + NULL, +}; + + static ssize_t extts_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) From 4183fb9503e117ef6d7564a4dbdf0582c5d638ad Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Jul 2013 15:05:24 -0700 Subject: [PATCH 0907/3400] cuse: convert class code to use dev_groups The dev_attrs field of struct class is going away soon, dev_groups should be used instead. This converts the cuse class code to use the correct field. Acked-by: Miklos Szeredi Signed-off-by: Greg Kroah-Hartman --- fs/fuse/cuse.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c index aef34b1e635e..adbfd66b380f 100644 --- a/fs/fuse/cuse.c +++ b/fs/fuse/cuse.c @@ -568,6 +568,7 @@ static ssize_t cuse_class_waiting_show(struct device *dev, return sprintf(buf, "%d\n", atomic_read(&cc->fc.num_waiting)); } +static DEVICE_ATTR(waiting, S_IFREG | 0400, cuse_class_waiting_show, NULL); static ssize_t cuse_class_abort_store(struct device *dev, struct device_attribute *attr, @@ -578,12 +579,14 @@ static ssize_t cuse_class_abort_store(struct device *dev, fuse_abort_conn(&cc->fc); return count; } +static DEVICE_ATTR(abort, S_IFREG | 0200, NULL, cuse_class_abort_store); -static struct device_attribute cuse_class_dev_attrs[] = { - __ATTR(waiting, S_IFREG | 0400, cuse_class_waiting_show, NULL), - __ATTR(abort, S_IFREG | 0200, NULL, cuse_class_abort_store), - { } +static struct attribute *cuse_class_dev_attrs[] = { + &dev_attr_waiting.attr, + &dev_attr_abort.attr, + NULL, }; +ATTRIBUTE_GROUPS(cuse_class_dev); static struct miscdevice cuse_miscdev = { .minor = MISC_DYNAMIC_MINOR, @@ -609,7 +612,7 @@ static int __init cuse_init(void) if (IS_ERR(cuse_class)) return PTR_ERR(cuse_class); - cuse_class->dev_attrs = cuse_class_dev_attrs; + cuse_class->dev_groups = cuse_class_dev_groups; rc = misc_register(&cuse_miscdev); if (rc) { From 6be8aeef348a7a4a18b7406aed5de951e6125c2d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Jul 2013 15:05:33 -0700 Subject: [PATCH 0908/3400] net: core: convert class code to use dev_groups The dev_attrs field of struct class is going away soon, dev_groups should be used instead. This converts the networking core class code to use the correct field. In order to do this in the "cleanest" way, some of the macros had to be changed to reflect the driver core format of naming show/store functions, which accounts for the majority of the churn in this file. Acked-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/core/net-sysfs.c | 134 ++++++++++++++++++++++++------------------- 1 file changed, 74 insertions(+), 60 deletions(-) diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 981fed397d1d..707c3134ddf2 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -60,12 +60,19 @@ static ssize_t format_##field(const struct net_device *net, char *buf) \ { \ return sprintf(buf, format_string, net->field); \ } \ -static ssize_t show_##field(struct device *dev, \ +static ssize_t field##_show(struct device *dev, \ struct device_attribute *attr, char *buf) \ { \ return netdev_show(dev, attr, buf, format_##field); \ -} +} \ +#define NETDEVICE_SHOW_RO(field, format_string) \ +NETDEVICE_SHOW(field, format_string); \ +static DEVICE_ATTR_RO(field) + +#define NETDEVICE_SHOW_RW(field, format_string) \ +NETDEVICE_SHOW(field, format_string); \ +static DEVICE_ATTR_RW(field) /* use same locking and permission rules as SIF* ioctl's */ static ssize_t netdev_store(struct device *dev, struct device_attribute *attr, @@ -96,16 +103,16 @@ static ssize_t netdev_store(struct device *dev, struct device_attribute *attr, return ret; } -NETDEVICE_SHOW(dev_id, fmt_hex); -NETDEVICE_SHOW(addr_assign_type, fmt_dec); -NETDEVICE_SHOW(addr_len, fmt_dec); -NETDEVICE_SHOW(iflink, fmt_dec); -NETDEVICE_SHOW(ifindex, fmt_dec); -NETDEVICE_SHOW(type, fmt_dec); -NETDEVICE_SHOW(link_mode, fmt_dec); +NETDEVICE_SHOW_RO(dev_id, fmt_hex); +NETDEVICE_SHOW_RO(addr_assign_type, fmt_dec); +NETDEVICE_SHOW_RO(addr_len, fmt_dec); +NETDEVICE_SHOW_RO(iflink, fmt_dec); +NETDEVICE_SHOW_RO(ifindex, fmt_dec); +NETDEVICE_SHOW_RO(type, fmt_dec); +NETDEVICE_SHOW_RO(link_mode, fmt_dec); /* use same locking rules as GIFHWADDR ioctl's */ -static ssize_t show_address(struct device *dev, struct device_attribute *attr, +static ssize_t address_show(struct device *dev, struct device_attribute *attr, char *buf) { struct net_device *net = to_net_dev(dev); @@ -117,15 +124,17 @@ static ssize_t show_address(struct device *dev, struct device_attribute *attr, read_unlock(&dev_base_lock); return ret; } +static DEVICE_ATTR_RO(address); -static ssize_t show_broadcast(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t broadcast_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct net_device *net = to_net_dev(dev); if (dev_isalive(net)) return sysfs_format_mac(buf, net->broadcast, net->addr_len); return -EINVAL; } +static DEVICE_ATTR_RO(broadcast); static int change_carrier(struct net_device *net, unsigned long new_carrier) { @@ -134,13 +143,13 @@ static int change_carrier(struct net_device *net, unsigned long new_carrier) return dev_change_carrier(net, (bool) new_carrier); } -static ssize_t store_carrier(struct device *dev, struct device_attribute *attr, - const char *buf, size_t len) +static ssize_t carrier_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len) { return netdev_store(dev, attr, buf, len, change_carrier); } -static ssize_t show_carrier(struct device *dev, +static ssize_t carrier_show(struct device *dev, struct device_attribute *attr, char *buf) { struct net_device *netdev = to_net_dev(dev); @@ -149,8 +158,9 @@ static ssize_t show_carrier(struct device *dev, } return -EINVAL; } +static DEVICE_ATTR_RW(carrier); -static ssize_t show_speed(struct device *dev, +static ssize_t speed_show(struct device *dev, struct device_attribute *attr, char *buf) { struct net_device *netdev = to_net_dev(dev); @@ -167,8 +177,9 @@ static ssize_t show_speed(struct device *dev, rtnl_unlock(); return ret; } +static DEVICE_ATTR_RO(speed); -static ssize_t show_duplex(struct device *dev, +static ssize_t duplex_show(struct device *dev, struct device_attribute *attr, char *buf) { struct net_device *netdev = to_net_dev(dev); @@ -198,8 +209,9 @@ static ssize_t show_duplex(struct device *dev, rtnl_unlock(); return ret; } +static DEVICE_ATTR_RO(duplex); -static ssize_t show_dormant(struct device *dev, +static ssize_t dormant_show(struct device *dev, struct device_attribute *attr, char *buf) { struct net_device *netdev = to_net_dev(dev); @@ -209,6 +221,7 @@ static ssize_t show_dormant(struct device *dev, return -EINVAL; } +static DEVICE_ATTR_RO(dormant); static const char *const operstates[] = { "unknown", @@ -220,7 +233,7 @@ static const char *const operstates[] = { "up" }; -static ssize_t show_operstate(struct device *dev, +static ssize_t operstate_show(struct device *dev, struct device_attribute *attr, char *buf) { const struct net_device *netdev = to_net_dev(dev); @@ -237,35 +250,33 @@ static ssize_t show_operstate(struct device *dev, return sprintf(buf, "%s\n", operstates[operstate]); } +static DEVICE_ATTR_RO(operstate); /* read-write attributes */ -NETDEVICE_SHOW(mtu, fmt_dec); static int change_mtu(struct net_device *net, unsigned long new_mtu) { return dev_set_mtu(net, (int) new_mtu); } -static ssize_t store_mtu(struct device *dev, struct device_attribute *attr, +static ssize_t mtu_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { return netdev_store(dev, attr, buf, len, change_mtu); } - -NETDEVICE_SHOW(flags, fmt_hex); +NETDEVICE_SHOW_RW(mtu, fmt_dec); static int change_flags(struct net_device *net, unsigned long new_flags) { return dev_change_flags(net, (unsigned int) new_flags); } -static ssize_t store_flags(struct device *dev, struct device_attribute *attr, +static ssize_t flags_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { return netdev_store(dev, attr, buf, len, change_flags); } - -NETDEVICE_SHOW(tx_queue_len, fmt_ulong); +NETDEVICE_SHOW_RW(flags, fmt_hex); static int change_tx_queue_len(struct net_device *net, unsigned long new_len) { @@ -273,7 +284,7 @@ static int change_tx_queue_len(struct net_device *net, unsigned long new_len) return 0; } -static ssize_t store_tx_queue_len(struct device *dev, +static ssize_t tx_queue_len_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { @@ -282,8 +293,9 @@ static ssize_t store_tx_queue_len(struct device *dev, return netdev_store(dev, attr, buf, len, change_tx_queue_len); } +NETDEVICE_SHOW_RW(tx_queue_len, fmt_ulong); -static ssize_t store_ifalias(struct device *dev, struct device_attribute *attr, +static ssize_t ifalias_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { struct net_device *netdev = to_net_dev(dev); @@ -306,7 +318,7 @@ static ssize_t store_ifalias(struct device *dev, struct device_attribute *attr, return ret < 0 ? ret : len; } -static ssize_t show_ifalias(struct device *dev, +static ssize_t ifalias_show(struct device *dev, struct device_attribute *attr, char *buf) { const struct net_device *netdev = to_net_dev(dev); @@ -319,8 +331,7 @@ static ssize_t show_ifalias(struct device *dev, rtnl_unlock(); return ret; } - -NETDEVICE_SHOW(group, fmt_dec); +static DEVICE_ATTR_RW(ifalias); static int change_group(struct net_device *net, unsigned long new_group) { @@ -328,35 +339,37 @@ static int change_group(struct net_device *net, unsigned long new_group) return 0; } -static ssize_t store_group(struct device *dev, struct device_attribute *attr, - const char *buf, size_t len) +static ssize_t group_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len) { return netdev_store(dev, attr, buf, len, change_group); } +NETDEVICE_SHOW(group, fmt_dec); +static DEVICE_ATTR(netdev_group, S_IRUGO | S_IWUSR, group_show, group_store); -static struct device_attribute net_class_attributes[] = { - __ATTR(addr_assign_type, S_IRUGO, show_addr_assign_type, NULL), - __ATTR(addr_len, S_IRUGO, show_addr_len, NULL), - __ATTR(dev_id, S_IRUGO, show_dev_id, NULL), - __ATTR(ifalias, S_IRUGO | S_IWUSR, show_ifalias, store_ifalias), - __ATTR(iflink, S_IRUGO, show_iflink, NULL), - __ATTR(ifindex, S_IRUGO, show_ifindex, NULL), - __ATTR(type, S_IRUGO, show_type, NULL), - __ATTR(link_mode, S_IRUGO, show_link_mode, NULL), - __ATTR(address, S_IRUGO, show_address, NULL), - __ATTR(broadcast, S_IRUGO, show_broadcast, NULL), - __ATTR(carrier, S_IRUGO | S_IWUSR, show_carrier, store_carrier), - __ATTR(speed, S_IRUGO, show_speed, NULL), - __ATTR(duplex, S_IRUGO, show_duplex, NULL), - __ATTR(dormant, S_IRUGO, show_dormant, NULL), - __ATTR(operstate, S_IRUGO, show_operstate, NULL), - __ATTR(mtu, S_IRUGO | S_IWUSR, show_mtu, store_mtu), - __ATTR(flags, S_IRUGO | S_IWUSR, show_flags, store_flags), - __ATTR(tx_queue_len, S_IRUGO | S_IWUSR, show_tx_queue_len, - store_tx_queue_len), - __ATTR(netdev_group, S_IRUGO | S_IWUSR, show_group, store_group), - {} +static struct attribute *net_class_attrs[] = { + &dev_attr_netdev_group.attr, + &dev_attr_type.attr, + &dev_attr_dev_id.attr, + &dev_attr_iflink.attr, + &dev_attr_ifindex.attr, + &dev_attr_addr_assign_type.attr, + &dev_attr_addr_len.attr, + &dev_attr_link_mode.attr, + &dev_attr_address.attr, + &dev_attr_broadcast.attr, + &dev_attr_speed.attr, + &dev_attr_duplex.attr, + &dev_attr_dormant.attr, + &dev_attr_operstate.attr, + &dev_attr_ifalias.attr, + &dev_attr_carrier.attr, + &dev_attr_mtu.attr, + &dev_attr_flags.attr, + &dev_attr_tx_queue_len.attr, + NULL, }; +ATTRIBUTE_GROUPS(net_class); /* Show a given an attribute in the statistics group */ static ssize_t netstat_show(const struct device *d, @@ -382,13 +395,13 @@ static ssize_t netstat_show(const struct device *d, /* generate a read-only statistics attribute */ #define NETSTAT_ENTRY(name) \ -static ssize_t show_##name(struct device *d, \ +static ssize_t name##_show(struct device *d, \ struct device_attribute *attr, char *buf) \ { \ return netstat_show(d, attr, buf, \ offsetof(struct rtnl_link_stats64, name)); \ } \ -static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL) +static DEVICE_ATTR_RO(name) NETSTAT_ENTRY(rx_packets); NETSTAT_ENTRY(tx_packets); @@ -457,6 +470,9 @@ static struct attribute_group wireless_group = { .attrs = wireless_attrs, }; #endif + +#else /* CONFIG_SYSFS */ +#define net_class_groups NULL #endif /* CONFIG_SYSFS */ #ifdef CONFIG_RPS @@ -1229,9 +1245,7 @@ static const void *net_namespace(struct device *d) static struct class net_class = { .name = "net", .dev_release = netdev_release, -#ifdef CONFIG_SYSFS - .dev_attrs = net_class_attributes, -#endif /* CONFIG_SYSFS */ + .dev_groups = net_class_groups, .dev_uevent = netdev_uevent, .ns_type = &net_ns_type_operations, .namespace = net_namespace, From 7f4708abf16ae48e58a9190898253bc7c94a30c1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Jul 2013 15:05:34 -0700 Subject: [PATCH 0909/3400] net: ieee802154: convert class code to use dev_groups The dev_attrs field of struct class is going away soon, dev_groups should be used instead. This converts the ieee802154 class code to use the correct field. Acked-by: David S. Miller Cc: Alexander Smirnov Cc: Dmitry Eremin-Solenikov Signed-off-by: Greg Kroah-Hartman --- net/ieee802154/wpan-class.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/net/ieee802154/wpan-class.c b/net/ieee802154/wpan-class.c index 13571eae6bae..ef56ab5b35fe 100644 --- a/net/ieee802154/wpan-class.c +++ b/net/ieee802154/wpan-class.c @@ -36,7 +36,8 @@ static ssize_t name ## _show(struct device *dev, \ ret = snprintf(buf, PAGE_SIZE, format_string "\n", args); \ mutex_unlock(&phy->pib_lock); \ return ret; \ -} +} \ +static DEVICE_ATTR_RO(name); #define MASTER_SHOW(field, format_string) \ MASTER_SHOW_COMPLEX(field, format_string, phy->field) @@ -66,15 +67,17 @@ static ssize_t channels_supported_show(struct device *dev, mutex_unlock(&phy->pib_lock); return len; } +static DEVICE_ATTR_RO(channels_supported); -static struct device_attribute pmib_attrs[] = { - __ATTR_RO(current_channel), - __ATTR_RO(current_page), - __ATTR_RO(channels_supported), - __ATTR_RO(transmit_power), - __ATTR_RO(cca_mode), - {}, +static struct attribute *pmib_attrs[] = { + &dev_attr_current_channel.attr, + &dev_attr_current_page.attr, + &dev_attr_channels_supported.attr, + &dev_attr_transmit_power.attr, + &dev_attr_cca_mode.attr, + NULL, }; +ATTRIBUTE_GROUPS(pmib); static void wpan_phy_release(struct device *d) { @@ -85,7 +88,7 @@ static void wpan_phy_release(struct device *d) static struct class wpan_phy_class = { .name = "ieee802154", .dev_release = wpan_phy_release, - .dev_attrs = pmib_attrs, + .dev_groups = pmib_groups, }; static DEFINE_MUTEX(wpan_phy_mutex); From 536446772f1181f3afdf332780b5325d1b6980c6 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Fri, 26 Jul 2013 13:30:20 -0600 Subject: [PATCH 0910/3400] PM / Sleep: new trace event to print device suspend and resume times A new trace event is added to PM events to print the time it takes to suspend and resume a device. It generates trace messages that include device, driver, parent information in addition to the type of PM ops invoked as well as the PM event and error status from the PM ops. Example trace below: bash-2239 [000] .... 290.883035: device_pm_report_time: backlight acpi_video0 parent=0000:00:02.0 state=freeze ops=class nsecs=332 err=0 bash-2239 [000] .... 290.883041: device_pm_report_time: rfkill rf kill3 parent=phy0 state=freeze ops=legacy class nsecs=216 err=0 bash-2239 [001] .... 290.973892: device_pm_report_time: ieee80211 phy0 parent=0000:01:00.0 state=freeze ops=legacy class nsecs=90846477 err=0 bash-2239 [001] .... 293.660129: device_pm_report_time: ieee80211 phy0 parent=0000:01:00.0 state=restore ops=legacy class nsecs=101295162 err=0 bash-2239 [001] .... 293.660147: device_pm_report_time: rfkill rfkill3 parent=phy0 state=restore ops=legacy class nsecs=1804 err=0 bash-2239 [001] .... 293.660157: device_pm_report_time: backlight acpi_video0 parent=0000:00:02.0 state=restore ops=class nsecs=757 err=0 Signed-off-by: Shuah Khan Signed-off-by: Rafael J. Wysocki --- drivers/base/power/main.c | 77 ++++++++++++++++++++---------------- include/trace/events/power.h | 37 +++++++++++++++++ 2 files changed, 80 insertions(+), 34 deletions(-) diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 5a9b6569dd74..9f098a82cf04 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include "../base.h" #include "power.h" @@ -56,6 +57,30 @@ static pm_message_t pm_transition; static int async_error; +static char *pm_verb(int event) +{ + switch (event) { + case PM_EVENT_SUSPEND: + return "suspend"; + case PM_EVENT_RESUME: + return "resume"; + case PM_EVENT_FREEZE: + return "freeze"; + case PM_EVENT_QUIESCE: + return "quiesce"; + case PM_EVENT_HIBERNATE: + return "hibernate"; + case PM_EVENT_THAW: + return "thaw"; + case PM_EVENT_RESTORE: + return "restore"; + case PM_EVENT_RECOVER: + return "recover"; + default: + return "(unknown PM event)"; + } +} + /** * device_pm_sleep_init - Initialize system suspend-related device fields. * @dev: Device object being initialized. @@ -172,16 +197,21 @@ static ktime_t initcall_debug_start(struct device *dev) } static void initcall_debug_report(struct device *dev, ktime_t calltime, - int error) + int error, pm_message_t state, char *info) { - ktime_t delta, rettime; + ktime_t rettime; + s64 nsecs; + + rettime = ktime_get(); + nsecs = (s64) ktime_to_ns(ktime_sub(rettime, calltime)); if (pm_print_times_enabled) { - rettime = ktime_get(); - delta = ktime_sub(rettime, calltime); pr_info("call %s+ returned %d after %Ld usecs\n", dev_name(dev), - error, (unsigned long long)ktime_to_ns(delta) >> 10); + error, (unsigned long long)nsecs >> 10); } + + trace_device_pm_report_time(dev, info, nsecs, pm_verb(state.event), + error); } /** @@ -309,30 +339,6 @@ static pm_callback_t pm_noirq_op(const struct dev_pm_ops *ops, pm_message_t stat return NULL; } -static char *pm_verb(int event) -{ - switch (event) { - case PM_EVENT_SUSPEND: - return "suspend"; - case PM_EVENT_RESUME: - return "resume"; - case PM_EVENT_FREEZE: - return "freeze"; - case PM_EVENT_QUIESCE: - return "quiesce"; - case PM_EVENT_HIBERNATE: - return "hibernate"; - case PM_EVENT_THAW: - return "thaw"; - case PM_EVENT_RESTORE: - return "restore"; - case PM_EVENT_RECOVER: - return "recover"; - default: - return "(unknown PM event)"; - } -} - static void pm_dev_dbg(struct device *dev, pm_message_t state, char *info) { dev_dbg(dev, "%s%s%s\n", info, pm_verb(state.event), @@ -379,7 +385,7 @@ static int dpm_run_callback(pm_callback_t cb, struct device *dev, error = cb(dev); suspend_report_result(cb, error); - initcall_debug_report(dev, calltime, error); + initcall_debug_report(dev, calltime, error, state, info); return error; } @@ -1027,7 +1033,8 @@ EXPORT_SYMBOL_GPL(dpm_suspend_end); * @cb: Suspend callback to execute. */ static int legacy_suspend(struct device *dev, pm_message_t state, - int (*cb)(struct device *dev, pm_message_t state)) + int (*cb)(struct device *dev, pm_message_t state), + char *info) { int error; ktime_t calltime; @@ -1037,7 +1044,7 @@ static int legacy_suspend(struct device *dev, pm_message_t state, error = cb(dev, state); suspend_report_result(cb, error); - initcall_debug_report(dev, calltime, error); + initcall_debug_report(dev, calltime, error, state, info); return error; } @@ -1097,7 +1104,8 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) goto Run; } else if (dev->class->suspend) { pm_dev_dbg(dev, state, "legacy class "); - error = legacy_suspend(dev, state, dev->class->suspend); + error = legacy_suspend(dev, state, dev->class->suspend, + "legacy class "); goto End; } } @@ -1108,7 +1116,8 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) callback = pm_op(dev->bus->pm, state); } else if (dev->bus->suspend) { pm_dev_dbg(dev, state, "legacy bus "); - error = legacy_suspend(dev, state, dev->bus->suspend); + error = legacy_suspend(dev, state, dev->bus->suspend, + "legacy bus "); goto End; } } diff --git a/include/trace/events/power.h b/include/trace/events/power.h index 8e42410bd159..cda100d6762d 100644 --- a/include/trace/events/power.h +++ b/include/trace/events/power.h @@ -66,6 +66,43 @@ TRACE_EVENT(machine_suspend, TP_printk("state=%lu", (unsigned long)__entry->state) ); +TRACE_EVENT(device_pm_report_time, + + TP_PROTO(struct device *dev, const char *pm_ops, s64 ops_time, + char *pm_event_str, int error), + + TP_ARGS(dev, pm_ops, ops_time, pm_event_str, error), + + TP_STRUCT__entry( + __string(device, dev_name(dev)) + __string(driver, dev_driver_string(dev)) + __string(parent, dev->parent ? dev_name(dev->parent) : "none") + __string(pm_ops, pm_ops ? pm_ops : "none ") + __string(pm_event_str, pm_event_str) + __field(s64, ops_time) + __field(int, error) + ), + + TP_fast_assign( + const char *tmp = dev->parent ? dev_name(dev->parent) : "none"; + const char *tmp_i = pm_ops ? pm_ops : "none "; + + __assign_str(device, dev_name(dev)); + __assign_str(driver, dev_driver_string(dev)); + __assign_str(parent, tmp); + __assign_str(pm_ops, tmp_i); + __assign_str(pm_event_str, pm_event_str); + __entry->ops_time = ops_time; + __entry->error = error; + ), + + /* ops_str has an extra space at the end */ + TP_printk("%s %s parent=%s state=%s ops=%snsecs=%lld err=%d", + __get_str(driver), __get_str(device), __get_str(parent), + __get_str(pm_event_str), __get_str(pm_ops), + __entry->ops_time, __entry->error) +); + DECLARE_EVENT_CLASS(wakeup_source, TP_PROTO(const char *name, unsigned int state), From eaf140b60ec961252083ab8adaf67aef29a362dd Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Fri, 26 Jul 2013 15:07:26 -0600 Subject: [PATCH 0911/3400] PNP: convert PNP driver bus legacy pm_ops to dev_pm_ops Convert drivers/pnp/driver.c bus legacy pm_ops to dev_pm_ops using existing suspend and resume routines. Add freeze interface to handle PM_EVENT_FREEZE correctly with dev_pm_ops. pm_op() looks for freeze interface when the event is PM_EVENT_FREEZE. Signed-off-by: Shuah Khan Signed-off-by: Rafael J. Wysocki --- drivers/pnp/driver.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c index 00e94032531a..12adb43a0693 100644 --- a/drivers/pnp/driver.c +++ b/drivers/pnp/driver.c @@ -154,7 +154,7 @@ static int pnp_bus_match(struct device *dev, struct device_driver *drv) return 1; } -static int pnp_bus_suspend(struct device *dev, pm_message_t state) +static int __pnp_bus_suspend(struct device *dev, pm_message_t state) { struct pnp_dev *pnp_dev = to_pnp_dev(dev); struct pnp_driver *pnp_drv = pnp_dev->driver; @@ -180,6 +180,16 @@ static int pnp_bus_suspend(struct device *dev, pm_message_t state) return 0; } +static int pnp_bus_suspend(struct device *dev) +{ + return __pnp_bus_suspend(dev, PMSG_SUSPEND); +} + +static int pnp_bus_freeze(struct device *dev) +{ + return __pnp_bus_suspend(dev, PMSG_FREEZE); +} + static int pnp_bus_resume(struct device *dev) { struct pnp_dev *pnp_dev = to_pnp_dev(dev); @@ -210,14 +220,19 @@ static int pnp_bus_resume(struct device *dev) return 0; } +static const struct dev_pm_ops pnp_bus_dev_pm_ops = { + .suspend = pnp_bus_suspend, + .freeze = pnp_bus_freeze, + .resume = pnp_bus_resume, +}; + struct bus_type pnp_bus_type = { .name = "pnp", .match = pnp_bus_match, .probe = pnp_device_probe, .remove = pnp_device_remove, .shutdown = pnp_device_shutdown, - .suspend = pnp_bus_suspend, - .resume = pnp_bus_resume, + .pm = &pnp_bus_dev_pm_ops, .dev_attrs = pnp_interface_attrs, }; From b98e01ad4ed9da6882b41983319361502aded307 Mon Sep 17 00:00:00 2001 From: Sahara Date: Wed, 3 Jul 2013 17:49:55 +0900 Subject: [PATCH 0912/3400] cpuidle: Add Kconfig.arm and move calxeda, kirkwood and zynq Add Kconfig.arm for ARM cpuidle drivers and moves calxeda, kirkwood and zynq to Kconfig.arm. Like in the cpufreq menu, "CPU Idle" menu is added to drivers/cpuidle/Kconfig. Signed-off-by: Sahara --- drivers/cpuidle/Kconfig | 20 +++++++------------- drivers/cpuidle/Kconfig.arm | 21 +++++++++++++++++++++ drivers/cpuidle/Makefile | 8 +++++--- 3 files changed, 33 insertions(+), 16 deletions(-) create mode 100644 drivers/cpuidle/Kconfig.arm diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig index 0e2cd5cab4d0..b3fb81d7cf04 100644 --- a/drivers/cpuidle/Kconfig +++ b/drivers/cpuidle/Kconfig @@ -1,5 +1,6 @@ +menu "CPU Idle" -menuconfig CPU_IDLE +config CPU_IDLE bool "CPU idle PM support" default y if ACPI || PPC_PSERIES select CPU_IDLE_GOV_LADDER if (!NO_HZ && !NO_HZ_IDLE) @@ -29,20 +30,13 @@ config CPU_IDLE_GOV_MENU bool "Menu governor (for tickless system)" default y -config CPU_IDLE_CALXEDA - bool "CPU Idle Driver for Calxeda processors" - depends on ARCH_HIGHBANK - select ARM_CPU_SUSPEND - help - Select this to enable cpuidle on Calxeda processors. - -config CPU_IDLE_ZYNQ - bool "CPU Idle Driver for Xilinx Zynq processors" - depends on ARCH_ZYNQ - help - Select this to enable cpuidle on Xilinx Zynq processors. +menu "ARM CPU Idle Drivers" +depends on ARM +source "drivers/cpuidle/Kconfig.arm" +endmenu endif config ARCH_NEEDS_CPU_IDLE_COUPLED def_bool n +endmenu diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm new file mode 100644 index 000000000000..2c8f17d33ff4 --- /dev/null +++ b/drivers/cpuidle/Kconfig.arm @@ -0,0 +1,21 @@ +# +# ARM CPU Idle drivers +# + +config ARM_HIGHBANK_CPUIDLE + bool "CPU Idle Driver for Calxeda processors" + depends on ARCH_HIGHBANK + select ARM_CPU_SUSPEND + help + Select this to enable cpuidle on Calxeda processors. + +config ARM_KIRKWOOD_CPUIDLE + bool "CPU Idle Driver for Marvell Kirkwood SoCs" + depends on ARCH_KIRKWOOD + help + This adds the CPU Idle driver for Marvell Kirkwood SoCs. + +config ARM_ZYNQ_CPUIDLE + bool "CPU Idle Driver for Xilinx Zynq processors" + depends on ARCH_ZYNQ + help diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile index 8767a7b3eb91..77cf767b0875 100644 --- a/drivers/cpuidle/Makefile +++ b/drivers/cpuidle/Makefile @@ -5,6 +5,8 @@ obj-y += cpuidle.o driver.o governor.o sysfs.o governors/ obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o -obj-$(CONFIG_CPU_IDLE_CALXEDA) += cpuidle-calxeda.o -obj-$(CONFIG_ARCH_KIRKWOOD) += cpuidle-kirkwood.o -obj-$(CONFIG_CPU_IDLE_ZYNQ) += cpuidle-zynq.o +################################################################################## +# ARM SoC drivers +obj-$(CONFIG_ARM_HIGHBANK_CPUIDLE) += cpuidle-calxeda.o +obj-$(CONFIG_ARM_KIRKWOOD_CPUIDLE) += cpuidle-kirkwood.o +obj-$(CONFIG_ARM_ZYNQ_CPUIDLE) += cpuidle-zynq.o From 7006b8a1facc5dcafb2afa27a1209d924f99a2eb Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 28 Jun 2013 12:09:09 +0200 Subject: [PATCH 0913/3400] ARM: davinci: cpuidle: Fix target residency The commit 19976c2a88d125aec16b9255c7197c297bbdd637 changed the target residency to 100000, assuming this is a careless mistake. The same happened to the at91's cpuidle driver. Fix it by putting the initial value to 10000. Signed-off-by: Daniel Lezcano Acked-by: Sekhar Nori --- arch/arm/mach-davinci/cpuidle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c index 36aef3a7dedb..f1ac1c94ac0f 100644 --- a/arch/arm/mach-davinci/cpuidle.c +++ b/arch/arm/mach-davinci/cpuidle.c @@ -65,7 +65,7 @@ static struct cpuidle_driver davinci_idle_driver = { .states[1] = { .enter = davinci_enter_idle, .exit_latency = 10, - .target_residency = 100000, + .target_residency = 10000, .flags = CPUIDLE_FLAG_TIME_VALID, .name = "DDR SR", .desc = "WFI and DDR Self Refresh", From 8025395f39c97e332362c24f7c33c86acdd4cd90 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 10 Jul 2013 15:35:26 +0200 Subject: [PATCH 0914/3400] ARM: ux500: cpuidle: Instantiate the driver from platform device To break the dependency on the "id.h" file we move the cpuidle driver to a platform device. Now we only call the probe() on this driver if we find a corresponding platform device (which is spawned from the PRCMU MFD driver). Signed-off-by: Linus Walleij Signed-off-by: Daniel Lezcano --- arch/arm/mach-ux500/cpuidle.c | 17 +++++++++++------ drivers/mfd/db8500-prcmu.c | 4 ++++ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-ux500/cpuidle.c b/arch/arm/mach-ux500/cpuidle.c index a45dd09daed9..c0cb37c8086c 100644 --- a/arch/arm/mach-ux500/cpuidle.c +++ b/arch/arm/mach-ux500/cpuidle.c @@ -16,12 +16,12 @@ #include #include #include +#include #include #include #include "db8500-regs.h" -#include "id.h" static atomic_t master = ATOMIC_INIT(0); static DEFINE_SPINLOCK(master_lock); @@ -113,11 +113,8 @@ static struct cpuidle_driver ux500_idle_driver = { .state_count = 2, }; -int __init ux500_idle_init(void) +static int __init dbx500_cpuidle_probe(struct platform_device *pdev) { - if (!(cpu_is_u8500_family() || cpu_is_ux540_family())) - return -ENODEV; - /* Configure wake up reasons */ prcmu_enable_wakeups(PRCMU_WAKEUP(ARM) | PRCMU_WAKEUP(RTC) | PRCMU_WAKEUP(ABB)); @@ -125,4 +122,12 @@ int __init ux500_idle_init(void) return cpuidle_register(&ux500_idle_driver, NULL); } -device_initcall(ux500_idle_init); +static struct platform_driver dbx500_cpuidle_plat_driver = { + .driver = { + .name = "cpuidle-dbx500", + .owner = THIS_MODULE, + }, + .probe = dbx500_cpuidle_probe, +}; + +module_platform_driver(dbx500_cpuidle_plat_driver); diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index 3c157faee645..0d68eb1a5ec5 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c @@ -3093,6 +3093,10 @@ static struct mfd_cell db8500_prcmu_devs[] = { .platform_data = &db8500_cpufreq_table, .pdata_size = sizeof(db8500_cpufreq_table), }, + { + .name = "cpuidle-dbx500", + .of_compatible = "stericsson,cpuidle-dbx500", + }, { .name = "db8500-thermal", .num_resources = ARRAY_SIZE(db8500_thsens_resources), From 8457246b106cc4e53f2534309dbe35a973c7d046 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 10 Jul 2013 15:52:01 +0200 Subject: [PATCH 0915/3400] ARM: ux500: cpuidle: Remove pointless include The db8500-regs.h file does not need to be included by the cpuidle driver. Signed-off-by: Linus Walleij Signed-off-by: Daniel Lezcano --- arch/arm/mach-ux500/cpuidle.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm/mach-ux500/cpuidle.c b/arch/arm/mach-ux500/cpuidle.c index c0cb37c8086c..e0564652af35 100644 --- a/arch/arm/mach-ux500/cpuidle.c +++ b/arch/arm/mach-ux500/cpuidle.c @@ -21,8 +21,6 @@ #include #include -#include "db8500-regs.h" - static atomic_t master = ATOMIC_INIT(0); static DEFINE_SPINLOCK(master_lock); From d3f2950f2adeea3da0317e952914b59adaa4cdb3 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Wed, 10 Jul 2013 16:02:04 +0200 Subject: [PATCH 0916/3400] ARM: ux500: cpuidle: Move ux500 cpuidle driver to drivers/cpuidle There is no more dependency with arch/arm headers, so we can safely move the driver to the drivers/cpuidle directory. Signed-off-by: Daniel Lezcano Acked-by: Linus Walleij --- arch/arm/mach-ux500/Makefile | 1 - drivers/cpuidle/Kconfig.arm | 8 ++++++++ drivers/cpuidle/Makefile | 1 + .../cpuidle.c => drivers/cpuidle/cpuidle-ux500.c | 0 4 files changed, 9 insertions(+), 1 deletion(-) rename arch/arm/mach-ux500/cpuidle.c => drivers/cpuidle/cpuidle-ux500.c (100%) diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index bf9b6be5b180..fe1f3e26b88b 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -4,7 +4,6 @@ obj-y := cpu.o devices.o devices-common.o \ id.o usb.o timer.o pm.o -obj-$(CONFIG_CPU_IDLE) += cpuidle.o obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o obj-$(CONFIG_MACH_MOP500) += board-mop500.o board-mop500-sdi.o \ diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm index 2c8f17d33ff4..b3302193c15a 100644 --- a/drivers/cpuidle/Kconfig.arm +++ b/drivers/cpuidle/Kconfig.arm @@ -19,3 +19,11 @@ config ARM_ZYNQ_CPUIDLE bool "CPU Idle Driver for Xilinx Zynq processors" depends on ARCH_ZYNQ help + Select this to enable cpuidle on Xilinx Zynq processors. + +config ARM_U8500_CPUIDLE + bool "Cpu Idle Driver for the ST-E u8500 processors" + depends on ARCH_U8500 + help + Select this to enable cpuidle for ST-E u8500 processors + diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile index 77cf767b0875..0b9d200c7e45 100644 --- a/drivers/cpuidle/Makefile +++ b/drivers/cpuidle/Makefile @@ -10,3 +10,4 @@ obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o obj-$(CONFIG_ARM_HIGHBANK_CPUIDLE) += cpuidle-calxeda.o obj-$(CONFIG_ARM_KIRKWOOD_CPUIDLE) += cpuidle-kirkwood.o obj-$(CONFIG_ARM_ZYNQ_CPUIDLE) += cpuidle-zynq.o +obj-$(CONFIG_ARM_U8500_CPUIDLE) += cpuidle-ux500.o diff --git a/arch/arm/mach-ux500/cpuidle.c b/drivers/cpuidle/cpuidle-ux500.c similarity index 100% rename from arch/arm/mach-ux500/cpuidle.c rename to drivers/cpuidle/cpuidle-ux500.c From 550bf89366e068cd6e29c36156f700a02dbb6388 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 28 Jul 2013 16:37:23 +0800 Subject: [PATCH 0917/3400] regulator: da903x: Convert da9034 ldo12 to use linear ranges The voltage table of da9034 LDO12 is: 1700000, 1750000, 1800000, 1850000, 1900000, 1950000, 2000000, 2050000 2700000, 2750000, 2800000, 2850000, 2900000, 2950000, 3000000, 3050000 The voltage table is composed of two linear ranges: for selector 0 ... 7: volt = 1700000 + 50000 * selector for selector: 8 ... 15: volt = 2700000 + 50000 * (selector - 8) This patch converts da9034 LDO12 to use newly introduced helpers for multiple linear ranges. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/da903x.c | 45 +++++++++----------------------------- 1 file changed, 10 insertions(+), 35 deletions(-) diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x.c index 2afa5730f324..1378a242a3af 100644 --- a/drivers/regulator/da903x.c +++ b/drivers/regulator/da903x.c @@ -252,39 +252,12 @@ static int da9034_set_dvc_voltage_sel(struct regulator_dev *rdev, return ret; } -static int da9034_map_ldo12_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV) -{ - struct da903x_regulator_info *info = rdev_get_drvdata(rdev); - int sel; - - if (check_range(info, min_uV, max_uV)) { - pr_err("invalid voltage range (%d, %d) uV\n", min_uV, max_uV); - return -EINVAL; - } - - sel = DIV_ROUND_UP(min_uV - info->desc.min_uV, info->desc.uV_step); - sel = (sel >= 20) ? sel - 12 : ((sel > 7) ? 8 : sel); - - return sel; -} - -static int da9034_list_ldo12_voltage(struct regulator_dev *rdev, - unsigned selector) -{ - struct da903x_regulator_info *info = rdev_get_drvdata(rdev); - int volt; - - if (selector >= 8) - volt = 2700000 + rdev->desc->uV_step * (selector - 8); - else - volt = rdev->desc->min_uV + rdev->desc->uV_step * selector; - - if (volt > info->max_uV) - return -EINVAL; - - return volt; -} +static const struct regulator_linear_range da9034_ldo12_ranges[] = { + { .min_uV = 1700000, .max_uV = 2050000, .min_sel = 0, .max_sel = 7, + .uV_step = 50000 }, + { .min_uV = 2700000, .max_uV = 3050000, .min_sel = 8, .max_sel = 15, + .uV_step = 50000 }, +}; static struct regulator_ops da903x_regulator_ldo_ops = { .set_voltage_sel = da903x_set_voltage_sel, @@ -332,8 +305,8 @@ static struct regulator_ops da9034_regulator_dvc_ops = { static struct regulator_ops da9034_regulator_ldo12_ops = { .set_voltage_sel = da903x_set_voltage_sel, .get_voltage_sel = da903x_get_voltage_sel, - .list_voltage = da9034_list_ldo12_voltage, - .map_voltage = da9034_map_ldo12_voltage, + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, .enable = da903x_enable, .disable = da903x_disable, .is_enabled = da903x_is_enabled, @@ -476,6 +449,8 @@ static int da903x_regulator_probe(struct platform_device *pdev) if (ri->desc.id == DA9034_ID_LDO12) { ri->desc.ops = &da9034_regulator_ldo12_ops; ri->desc.n_voltages = 16; + ri->desc.linear_ranges = da9034_ldo12_ranges; + ri->desc.n_linear_ranges = ARRAY_SIZE(da9034_ldo12_ranges); } if (ri->desc.id == DA9030_ID_LDO14) From 8e76fda3e1ea73bc47189ebc49d4228ec86fb1fa Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 28 Jul 2013 15:33:51 +0100 Subject: [PATCH 0918/3400] spi/sh-hspi: Remove noisy print This adds no meaningful value. Signed-off-by: Mark Brown --- drivers/spi/spi-sh-hspi.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/spi/spi-sh-hspi.c b/drivers/spi/spi-sh-hspi.c index 716edf999538..daf2bf2bb59d 100644 --- a/drivers/spi/spi-sh-hspi.c +++ b/drivers/spi/spi-sh-hspi.c @@ -327,8 +327,6 @@ static int hspi_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); - dev_info(&pdev->dev, "probed\n"); - return 0; error1: From 33bf2c0b7d5af73763f41fd10d18f4c1f574c7fb Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 28 Jul 2013 15:36:38 +0100 Subject: [PATCH 0919/3400] spi/sh-msiof: Remove unneeded empty runtime PM callbacks Previously the runtime PM API insisted on having callbacks for everything but this requirement was removed a while ago so the empty callbacks can also be removed. Signed-off-by: Mark Brown --- drivers/spi/spi-sh-msiof.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c index 2bc5a6b86300..6688ce78df78 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c @@ -745,18 +745,6 @@ static int sh_msiof_spi_remove(struct platform_device *pdev) return ret; } -static int sh_msiof_spi_runtime_nop(struct device *dev) -{ - /* Runtime PM callback shared between ->runtime_suspend() - * and ->runtime_resume(). Simply returns success. - * - * This driver re-initializes all registers after - * pm_runtime_get_sync() anyway so there is no need - * to save and restore registers here. - */ - return 0; -} - #ifdef CONFIG_OF static const struct of_device_id sh_msiof_match[] = { { .compatible = "renesas,sh-msiof", }, @@ -766,18 +754,12 @@ static const struct of_device_id sh_msiof_match[] = { MODULE_DEVICE_TABLE(of, sh_msiof_match); #endif -static struct dev_pm_ops sh_msiof_spi_dev_pm_ops = { - .runtime_suspend = sh_msiof_spi_runtime_nop, - .runtime_resume = sh_msiof_spi_runtime_nop, -}; - static struct platform_driver sh_msiof_spi_drv = { .probe = sh_msiof_spi_probe, .remove = sh_msiof_spi_remove, .driver = { .name = "spi_sh_msiof", .owner = THIS_MODULE, - .pm = &sh_msiof_spi_dev_pm_ops, .of_match_table = of_match_ptr(sh_msiof_match), }, }; From 6c07ef298ac2a05e14cdb059169a78c74badf056 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 28 Jul 2013 14:32:27 +0100 Subject: [PATCH 0920/3400] spi/atmel: Annotate lock/unlock functions Let checkers like sparse know that the locking imbalances are intentional in these functions. Signed-off-by: Mark Brown --- drivers/spi/spi-atmel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index 4c6c455685c2..4e406930fa52 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -360,12 +360,12 @@ static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi) gpio_set_value(asd->npcs_pin, !active); } -static void atmel_spi_lock(struct atmel_spi *as) +static void atmel_spi_lock(struct atmel_spi *as) __acquires(&as->lock) { spin_lock_irqsave(&as->lock, as->flags); } -static void atmel_spi_unlock(struct atmel_spi *as) +static void atmel_spi_unlock(struct atmel_spi *as) __releases(&as->lock) { spin_unlock_irqrestore(&as->lock, as->flags); } From 895248f8513b03d7ca81989c02a80777f017d990 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 29 Jul 2013 05:10:21 +0100 Subject: [PATCH 0921/3400] spi/orion: Directly include linux/size.h Signed-off-by: Mark Brown --- drivers/spi/spi-orion.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c index 5d90bebaa0fa..d1bae77f157c 100644 --- a/drivers/spi/spi-orion.c +++ b/drivers/spi/spi-orion.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #define DRIVER_NAME "orion_spi" From dd1053a93fdc11d491f5460f7da5ce70e6c93c9e Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 5 Jul 2013 19:42:58 +0100 Subject: [PATCH 0922/3400] spi/drivers: Enable build of drivers with COMPILE_TEST Enable the build of drivers which don't have any real build time dependency on their architecture or platform with COMPILE_TEST, providing better build time coverage. Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 175491f2bb39..5a9513038d73 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -70,14 +70,14 @@ config SPI_ATH79 config SPI_ATMEL tristate "Atmel SPI Controller" - depends on (ARCH_AT91 || AVR32) + depends on (ARCH_AT91 || AVR32 || COMPILE_TEST) help This selects a driver for the Atmel SPI Controller, present on many AT32 (AVR32) and AT91 (ARM) chips. config SPI_BCM2835 tristate "BCM2835 SPI controller" - depends on ARCH_BCM2835 + depends on ARCH_BCM2835 || COMPILE_TEST help This selects a driver for the Broadcom BCM2835 SPI master. @@ -159,7 +159,7 @@ config SPI_DAVINCI config SPI_EP93XX tristate "Cirrus Logic EP93xx SPI controller" - depends on ARCH_EP93XX + depends on ARCH_EP93XX || COMPILE_TEST help This enables using the Cirrus EP93xx SPI controller in master mode. @@ -191,7 +191,7 @@ config SPI_GPIO config SPI_IMX tristate "Freescale i.MX SPI controllers" - depends on ARCH_MXC + depends on ARCH_MXC || COMPILE_TEST select SPI_BITBANG default m if IMX_HAVE_PLATFORM_SPI_IMX help @@ -280,20 +280,20 @@ config SPI_OMAP_UWIRE config SPI_OMAP24XX tristate "McSPI driver for OMAP" - depends on ARCH_OMAP2PLUS + depends on ARCH_OMAP2PLUS || COMPILE_TEST help SPI master controller for OMAP24XX and later Multichannel SPI (McSPI) modules. config SPI_OMAP_100K tristate "OMAP SPI 100K" - depends on ARCH_OMAP850 || ARCH_OMAP730 + depends on ARCH_OMAP850 || ARCH_OMAP730 || COMPILE_TEST help OMAP SPI 100K master controller for omap7xx boards. config SPI_ORION tristate "Orion SPI master" - depends on PLAT_ORION + depends on PLAT_ORION || COMPILE_TEST help This enables using the SPI master controller on the Orion chips. @@ -385,7 +385,7 @@ config SPI_SH_MSIOF config SPI_SH tristate "SuperH SPI controller" - depends on SUPERH + depends on SUPERH || COMPILE_TEST help SPI driver for SuperH SPI blocks. @@ -398,13 +398,13 @@ config SPI_SH_SCI config SPI_SH_HSPI tristate "SuperH HSPI controller" - depends on ARCH_SHMOBILE + depends on ARCH_SHMOBILE || COMPILE_TEST help SPI driver for SuperH HSPI blocks. config SPI_SIRF tristate "CSR SiRFprimaII SPI controller" - depends on ARCH_SIRF + depends on ARCH_SIRF || COMPILE_TEST select SPI_BITBANG help SPI driver for CSR SiRFprimaII SoCs @@ -418,7 +418,7 @@ config SPI_MXS config SPI_TEGRA114 tristate "NVIDIA Tegra114 SPI Controller" - depends on ARCH_TEGRA && TEGRA20_APB_DMA + depends on (ARCH_TEGRA && TEGRA20_APB_DMA) || COMPILE_TEST help SPI driver for NVIDIA Tegra114 SPI Controller interface. This controller is different than the older SoCs SPI controller and also register interface @@ -426,7 +426,7 @@ config SPI_TEGRA114 config SPI_TEGRA20_SFLASH tristate "Nvidia Tegra20 Serial flash Controller" - depends on ARCH_TEGRA + depends on ARCH_TEGRA || COMPILE_TEST help SPI driver for Nvidia Tegra20 Serial flash Controller interface. The main usecase of this controller is to use spi flash as boot @@ -434,7 +434,7 @@ config SPI_TEGRA20_SFLASH config SPI_TEGRA20_SLINK tristate "Nvidia Tegra20/Tegra30 SLINK Controller" - depends on ARCH_TEGRA && TEGRA20_APB_DMA + depends on (ARCH_TEGRA && TEGRA20_APB_DMA) || COMPILE_TEST help SPI driver for Nvidia Tegra20/Tegra30 SLINK Controller interface. @@ -457,7 +457,7 @@ config SPI_TOPCLIFF_PCH config SPI_TXX9 tristate "Toshiba TXx9 SPI controller" - depends on GPIOLIB && CPU_TX49XX + depends on GPIOLIB && (CPU_TX49XX || COMPILE_TEST) help SPI driver for Toshiba TXx9 MIPS SoCs From 12d20fc2f38fc00152a9eaf8f2a82ff57a4ee06c Mon Sep 17 00:00:00 2001 From: Robin Gong Date: Mon, 29 Jul 2013 11:40:11 +0800 Subject: [PATCH 0923/3400] regulator: pfuze100: add MODULE_LICENSE() in pfuze100 driver Fix building error on x86_64 and i386: WARNING: modpost: missing MODULE_LICENSE() in drivers/regulator/pfuze100-regulator.o Signed-off-by: Robin Gong Signed-off-by: Mark Brown --- drivers/regulator/pfuze100-regulator.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c index e2f9dcf3eb21..2dadc3138ce9 100644 --- a/drivers/regulator/pfuze100-regulator.c +++ b/drivers/regulator/pfuze100-regulator.c @@ -451,4 +451,5 @@ module_i2c_driver(pfuze_driver); MODULE_AUTHOR("Robin Gong "); MODULE_DESCRIPTION("Regulator Driver for Freescale PFUZE100 PMIC"); +MODULE_LICENSE("GPL v2"); MODULE_ALIAS("pfuze100-regulator"); From 057b82be3ca3d066478e43b162fc082930a746c9 Mon Sep 17 00:00:00 2001 From: Amit Shah Date: Mon, 29 Jul 2013 14:16:13 +0930 Subject: [PATCH 0924/3400] virtio: console: fix race with port unplug and open/close There's a window between find_port_by_devt() returning a port and us taking a kref on the port, where the port could get unplugged. Fix it by taking the reference in find_port_by_devt() itself. Problem reported and analyzed by Mateusz Guzik. CC: Reported-by: Mateusz Guzik Signed-off-by: Amit Shah Signed-off-by: Rusty Russell --- drivers/char/virtio_console.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 8a15af3e1a9d..3beea9d478bc 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -272,9 +272,12 @@ static struct port *find_port_by_devt_in_portdev(struct ports_device *portdev, unsigned long flags; spin_lock_irqsave(&portdev->ports_lock, flags); - list_for_each_entry(port, &portdev->ports, list) - if (port->cdev->dev == dev) + list_for_each_entry(port, &portdev->ports, list) { + if (port->cdev->dev == dev) { + kref_get(&port->kref); goto out; + } + } port = NULL; out: spin_unlock_irqrestore(&portdev->ports_lock, flags); @@ -1036,14 +1039,10 @@ static int port_fops_open(struct inode *inode, struct file *filp) struct port *port; int ret; + /* We get the port with a kref here */ port = find_port_by_devt(cdev->dev); filp->private_data = port; - /* Prevent against a port getting hot-unplugged at the same time */ - spin_lock_irq(&port->portdev->ports_lock); - kref_get(&port->kref); - spin_unlock_irq(&port->portdev->ports_lock); - /* * Don't allow opening of console port devices -- that's done * via /dev/hvc From 671bdea2b9f210566610603ecbb6584c8a201c8c Mon Sep 17 00:00:00 2001 From: Amit Shah Date: Mon, 29 Jul 2013 14:17:13 +0930 Subject: [PATCH 0925/3400] virtio: console: fix race in port_fops_open() and port unplug Between open() being called and processed, the port can be unplugged. Check if this happened, and bail out. A simple test script to reproduce this is: while true; do for i in $(seq 1 100); do echo $i > /dev/vport0p3; done; done; This opens and closes the port a lot of times; unplugging the port while this is happening triggers the bug. CC: Signed-off-by: Amit Shah Signed-off-by: Rusty Russell --- drivers/char/virtio_console.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 3beea9d478bc..ffa7e46faff9 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -1041,6 +1041,10 @@ static int port_fops_open(struct inode *inode, struct file *filp) /* We get the port with a kref here */ port = find_port_by_devt(cdev->dev); + if (!port) { + /* Port was unplugged before we could proceed */ + return -ENXIO; + } filp->private_data = port; /* From ea3768b4386a8d1790f4cc9a35de4f55b92d6442 Mon Sep 17 00:00:00 2001 From: Amit Shah Date: Mon, 29 Jul 2013 14:20:29 +0930 Subject: [PATCH 0926/3400] virtio: console: clean up port data immediately at time of unplug We used to keep the port's char device structs and the /sys entries around till the last reference to the port was dropped. This is actually unnecessary, and resulted in buggy behaviour: 1. Open port in guest 2. Hot-unplug port 3. Hot-plug a port with the same 'name' property as the unplugged one This resulted in hot-plug being unsuccessful, as a port with the same name already exists (even though it was unplugged). This behaviour resulted in a warning message like this one: -------------------8<--------------------------------------- WARNING: at fs/sysfs/dir.c:512 sysfs_add_one+0xc9/0x130() (Not tainted) Hardware name: KVM sysfs: cannot create duplicate filename '/devices/pci0000:00/0000:00:04.0/virtio0/virtio-ports/vport0p1' Call Trace: [] ? warn_slowpath_common+0x87/0xc0 [] ? warn_slowpath_fmt+0x46/0x50 [] ? sysfs_add_one+0xc9/0x130 [] ? create_dir+0x68/0xb0 [] ? sysfs_create_dir+0x39/0x50 [] ? kobject_add_internal+0xb9/0x260 [] ? kobject_add_varg+0x38/0x60 [] ? kobject_add+0x44/0x70 [] ? get_device_parent+0xf4/0x1d0 [] ? device_add+0xc9/0x650 -------------------8<--------------------------------------- Instead of relying on guest applications to release all references to the ports, we should go ahead and unregister the port from all the core layers. Any open/read calls on the port will then just return errors, and an unplug/plug operation on the host will succeed as expected. This also caused buggy behaviour in case of the device removal (not just a port): when the device was removed (which means all ports on that device are removed automatically as well), the ports with active users would clean up only when the last references were dropped -- and it would be too late then to be referencing char device pointers, resulting in oopses: -------------------8<--------------------------------------- PID: 6162 TASK: ffff8801147ad500 CPU: 0 COMMAND: "cat" #0 [ffff88011b9d5a90] machine_kexec at ffffffff8103232b #1 [ffff88011b9d5af0] crash_kexec at ffffffff810b9322 #2 [ffff88011b9d5bc0] oops_end at ffffffff814f4a50 #3 [ffff88011b9d5bf0] die at ffffffff8100f26b #4 [ffff88011b9d5c20] do_general_protection at ffffffff814f45e2 #5 [ffff88011b9d5c50] general_protection at ffffffff814f3db5 [exception RIP: strlen+2] RIP: ffffffff81272ae2 RSP: ffff88011b9d5d00 RFLAGS: 00010246 RAX: 0000000000000000 RBX: ffff880118901c18 RCX: 0000000000000000 RDX: ffff88011799982c RSI: 00000000000000d0 RDI: 3a303030302f3030 RBP: ffff88011b9d5d38 R8: 0000000000000006 R9: ffffffffa0134500 R10: 0000000000001000 R11: 0000000000001000 R12: ffff880117a1cc10 R13: 00000000000000d0 R14: 0000000000000017 R15: ffffffff81aff700 ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018 #6 [ffff88011b9d5d00] kobject_get_path at ffffffff8126dc5d #7 [ffff88011b9d5d40] kobject_uevent_env at ffffffff8126e551 #8 [ffff88011b9d5dd0] kobject_uevent at ffffffff8126e9eb #9 [ffff88011b9d5de0] device_del at ffffffff813440c7 -------------------8<--------------------------------------- So clean up when we have all the context, and all that's left to do when the references to the port have dropped is to free up the port struct itself. CC: Reported-by: chayang Reported-by: YOGANANTH SUBRAMANIAN Reported-by: FuXiangChun Reported-by: Qunfang Zhang Reported-by: Sibiao Luo Signed-off-by: Amit Shah Signed-off-by: Rusty Russell --- drivers/char/virtio_console.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index ffa7e46faff9..4e684faee10b 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -1518,14 +1518,6 @@ static void remove_port(struct kref *kref) port = container_of(kref, struct port, kref); - sysfs_remove_group(&port->dev->kobj, &port_attribute_group); - device_destroy(pdrvdata.class, port->dev->devt); - cdev_del(port->cdev); - - kfree(port->name); - - debugfs_remove(port->debugfs_file); - kfree(port); } @@ -1583,6 +1575,14 @@ static void unplug_port(struct port *port) */ port->portdev = NULL; + sysfs_remove_group(&port->dev->kobj, &port_attribute_group); + device_destroy(pdrvdata.class, port->dev->devt); + cdev_del(port->cdev); + + kfree(port->name); + + debugfs_remove(port->debugfs_file); + /* * Locks around here are not necessary - a port can't be * opened after we removed the port struct from ports_list From 92d3453815fbe74d539c86b60dab39ecdf01bb99 Mon Sep 17 00:00:00 2001 From: Amit Shah Date: Mon, 29 Jul 2013 14:21:32 +0930 Subject: [PATCH 0927/3400] virtio: console: fix raising SIGIO after port unplug SIGIO should be sent when a port gets unplugged. It should only be sent to prcesses that have the port opened, and have asked for SIGIO to be delivered. We were clearing out guest_connected before calling send_sigio_to_port(), resulting in a sigio not getting sent to processes. Fix by setting guest_connected to false after invoking the sigio function. CC: Signed-off-by: Amit Shah Signed-off-by: Rusty Russell --- drivers/char/virtio_console.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 4e684faee10b..e4845f1c9a0b 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -1551,12 +1551,14 @@ static void unplug_port(struct port *port) spin_unlock_irq(&port->portdev->ports_lock); if (port->guest_connected) { - port->guest_connected = false; - port->host_connected = false; - wake_up_interruptible(&port->waitqueue); - /* Let the app know the port is going down. */ send_sigio_to_port(port); + + /* Do this after sigio is actually sent */ + port->guest_connected = false; + port->host_connected = false; + + wake_up_interruptible(&port->waitqueue); } if (is_console_port(port)) { From 96f97a83910cdb9d89d127c5ee523f8fc040a804 Mon Sep 17 00:00:00 2001 From: Amit Shah Date: Mon, 29 Jul 2013 14:23:21 +0930 Subject: [PATCH 0928/3400] virtio: console: return -ENODEV on all read operations after unplug If a port gets unplugged while a user is blocked on read(), -ENODEV is returned. However, subsequent read()s returned 0, indicating there's no host-side connection (but not indicating the device went away). This also happened when a port was unplugged and the user didn't have any blocking operation pending. If the user didn't monitor the SIGIO signal, they won't have a chance to find out if the port went away. Fix by returning -ENODEV on all read()s after the port gets unplugged. write() already behaves this way. CC: Signed-off-by: Amit Shah Signed-off-by: Rusty Russell --- drivers/char/virtio_console.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index e4845f1c9a0b..fc45567ad3ac 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -749,6 +749,10 @@ static ssize_t port_fops_read(struct file *filp, char __user *ubuf, port = filp->private_data; + /* Port is hot-unplugged. */ + if (!port->guest_connected) + return -ENODEV; + if (!port_has_data(port)) { /* * If nothing's connected on the host just return 0 in @@ -765,7 +769,7 @@ static ssize_t port_fops_read(struct file *filp, char __user *ubuf, if (ret < 0) return ret; } - /* Port got hot-unplugged. */ + /* Port got hot-unplugged while we were waiting above. */ if (!port->guest_connected) return -ENODEV; /* From 94421b05d3f494943078230871859c5d92ac4505 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 29 Jul 2013 12:08:01 +0800 Subject: [PATCH 0929/3400] regulator: pfuze100: REGULATOR_PFUZE100 needs to select REGMAP_I2C This fixes below build errors: CC [M] drivers/regulator/pfuze100-regulator.o drivers/regulator/pfuze100-regulator.c:342:21: error: variable 'pfuze_regmap_config' has initializer but incomplete type drivers/regulator/pfuze100-regulator.c:343:2: error: unknown field 'reg_bits' specified in initializer drivers/regulator/pfuze100-regulator.c:343:2: warning: excess elements in struct initializer [enabled by default] drivers/regulator/pfuze100-regulator.c:343:2: warning: (near initialization for 'pfuze_regmap_config') [enabled by default] drivers/regulator/pfuze100-regulator.c:344:2: error: unknown field 'val_bits' specified in initializer drivers/regulator/pfuze100-regulator.c:344:2: warning: excess elements in struct initializer [enabled by default] drivers/regulator/pfuze100-regulator.c:344:2: warning: (near initialization for 'pfuze_regmap_config') [enabled by default] drivers/regulator/pfuze100-regulator.c:345:2: error: unknown field 'max_register' specified in initializer drivers/regulator/pfuze100-regulator.c:345:2: warning: excess elements in struct initializer [enabled by default] drivers/regulator/pfuze100-regulator.c:345:2: warning: (near initialization for 'pfuze_regmap_config') [enabled by default] drivers/regulator/pfuze100-regulator.c:346:2: error: unknown field 'cache_type' specified in initializer drivers/regulator/pfuze100-regulator.c:346:2: warning: excess elements in struct initializer [enabled by default] drivers/regulator/pfuze100-regulator.c:346:2: warning: (near initialization for 'pfuze_regmap_config') [enabled by default] drivers/regulator/pfuze100-regulator.c: In function 'pfuze100_regulator_probe': drivers/regulator/pfuze100-regulator.c:370:2: error: implicit declaration of function 'devm_regmap_init_i2c' [-Werror=implicit-function-declaration] drivers/regulator/pfuze100-regulator.c:370:21: warning: assignment makes pointer from integer without a cast [enabled by default] cc1: some warnings being treated as errors make[2]: *** [drivers/regulator/pfuze100-regulator.o] Error 1 make[1]: *** [drivers/regulator] Error 2 make: *** [drivers] Error 2 Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index f9d02aabe306..d32f833a16c9 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -358,6 +358,7 @@ config REGULATOR_PCF50633 config REGULATOR_PFUZE100 tristate "Support regulators on Freescale PFUZE100 PMIC" depends on I2C + select REGMAP_I2C help Say y here to support the regulators found on the Freescale PFUZE100 PMIC. From 8c86ab257d45badfccc18158f38f833c3d49fe8c Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 29 Jul 2013 12:09:12 +0800 Subject: [PATCH 0930/3400] regulator: pfuze100: Use i2c_[set|get]_clientdata Since this is a i2c driver, use i2c_[set|get]_clientdata instead of dev_[set|get]_drvdata. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/pfuze100-regulator.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c index 2dadc3138ce9..471208782b03 100644 --- a/drivers/regulator/pfuze100-regulator.c +++ b/drivers/regulator/pfuze100-regulator.c @@ -360,7 +360,7 @@ static int pfuze100_regulator_probe(struct i2c_client *client, if (!pfuze_chip) return -ENOMEM; - dev_set_drvdata(&client->dev, pfuze_chip); + i2c_set_clientdata(client, pfuze_chip); memcpy(pfuze_chip->regulator_descs, pfuze100_regulators, sizeof(pfuze_chip->regulator_descs)); @@ -429,7 +429,7 @@ static int pfuze100_regulator_probe(struct i2c_client *client, static int pfuze100_regulator_remove(struct i2c_client *client) { int i; - struct pfuze_chip *pfuze_chip = dev_get_drvdata(&client->dev); + struct pfuze_chip *pfuze_chip = i2c_get_clientdata(client); for (i = 0; i < PFUZE100_MAX_REGULATOR; i++) regulator_unregister(pfuze_chip->regulators[i]); From 40839bff8b2c4ae844225e0579fd8b7f1452e0ae Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 29 Jul 2013 12:19:29 +0800 Subject: [PATCH 0931/3400] regulator: pfuze100: Fix module alias prefix i2c drivers use "i2c:" prefix for module alias. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/pfuze100-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c index 471208782b03..6eb5586e6fa4 100644 --- a/drivers/regulator/pfuze100-regulator.c +++ b/drivers/regulator/pfuze100-regulator.c @@ -452,4 +452,4 @@ module_i2c_driver(pfuze_driver); MODULE_AUTHOR("Robin Gong "); MODULE_DESCRIPTION("Regulator Driver for Freescale PFUZE100 PMIC"); MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("pfuze100-regulator"); +MODULE_ALIAS("i2c:pfuze100-regulator"); From 2b29a9fdcb92bfc6b6f4c412d71505869de61a56 Mon Sep 17 00:00:00 2001 From: Dominik Dingel Date: Fri, 26 Jul 2013 15:04:00 +0200 Subject: [PATCH 0932/3400] KVM: s390: move kvm_guest_enter,exit closer to sie Any uaccess between guest_enter and guest_exit could trigger a page fault, the page fault handler would handle it as a guest fault and translate a user address as guest address. Signed-off-by: Dominik Dingel Signed-off-by: Christian Borntraeger CC: stable@vger.kernel.org Signed-off-by: Paolo Bonzini --- arch/s390/kvm/kvm-s390.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index ba694d2ba51e..34c1c9a90be2 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -702,14 +702,25 @@ static int __vcpu_run(struct kvm_vcpu *vcpu) return rc; vcpu->arch.sie_block->icptcode = 0; - preempt_disable(); - kvm_guest_enter(); - preempt_enable(); VCPU_EVENT(vcpu, 6, "entering sie flags %x", atomic_read(&vcpu->arch.sie_block->cpuflags)); trace_kvm_s390_sie_enter(vcpu, atomic_read(&vcpu->arch.sie_block->cpuflags)); + + /* + * As PF_VCPU will be used in fault handler, between guest_enter + * and guest_exit should be no uaccess. + */ + preempt_disable(); + kvm_guest_enter(); + preempt_enable(); rc = sie64a(vcpu->arch.sie_block, vcpu->run->s.regs.gprs); + kvm_guest_exit(); + + VCPU_EVENT(vcpu, 6, "exit sie icptcode %d", + vcpu->arch.sie_block->icptcode); + trace_kvm_s390_sie_exit(vcpu, vcpu->arch.sie_block->icptcode); + if (rc > 0) rc = 0; if (rc < 0) { @@ -721,10 +732,6 @@ static int __vcpu_run(struct kvm_vcpu *vcpu) rc = kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); } } - VCPU_EVENT(vcpu, 6, "exit sie icptcode %d", - vcpu->arch.sie_block->icptcode); - trace_kvm_s390_sie_exit(vcpu, vcpu->arch.sie_block->icptcode); - kvm_guest_exit(); memcpy(&vcpu->run->s.regs.gprs[14], &vcpu->arch.sie_block->gg14, 16); return rc; From e769ece3b129698d2b09811a6f6d304e4eaa8c29 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 26 Jul 2013 15:04:01 +0200 Subject: [PATCH 0933/3400] KVM: s390: fix pfmf non-quiescing control handling Fix the test within handle_pfmf() if the host has the NQ key-setting facility installed. Right now the code would incorrectly generate a program check in the guest if the NQ control bit for a pfmf request was set and if the host has the NQ key-setting facility installed. Signed-off-by: Heiko Carstens Reviewed-by: Thomas Huth Signed-off-by: Christian Borntraeger Signed-off-by: Paolo Bonzini --- arch/s390/kvm/priv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c index 0da3e6eb6be6..4cdc54e63ebc 100644 --- a/arch/s390/kvm/priv.c +++ b/arch/s390/kvm/priv.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -532,8 +533,7 @@ static int handle_pfmf(struct kvm_vcpu *vcpu) return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); /* Only provide non-quiescing support if the host supports it */ - if (vcpu->run->s.regs.gprs[reg1] & PFMF_NQ && - S390_lowcore.stfl_fac_list & 0x00020000) + if (vcpu->run->s.regs.gprs[reg1] & PFMF_NQ && !test_facility(14)) return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); /* No support for conditional-SSKE */ From 9da01759636f519967c0922ae12bd9fff739db9a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Jul 2013 15:05:39 -0700 Subject: [PATCH 0934/3400] pwm: convert class code to use dev_groups The dev_attrs field of struct class is going away soon, dev_groups should be used instead. This converts the PWM class code to use the correct field. Signed-off-by: Greg Kroah-Hartman Signed-off-by: Thierry Reding --- drivers/pwm/sysfs.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c index 8ca5de316d3b..8c20332d4825 100644 --- a/drivers/pwm/sysfs.c +++ b/drivers/pwm/sysfs.c @@ -268,6 +268,7 @@ static ssize_t pwm_export_store(struct device *parent, return ret ? : len; } +static DEVICE_ATTR(export, 0200, NULL, pwm_export_store); static ssize_t pwm_unexport_store(struct device *parent, struct device_attribute *attr, @@ -288,27 +289,29 @@ static ssize_t pwm_unexport_store(struct device *parent, return ret ? : len; } +static DEVICE_ATTR(unexport, 0200, NULL, pwm_unexport_store); -static ssize_t pwm_npwm_show(struct device *parent, - struct device_attribute *attr, - char *buf) +static ssize_t npwm_show(struct device *parent, struct device_attribute *attr, + char *buf) { const struct pwm_chip *chip = dev_get_drvdata(parent); return sprintf(buf, "%u\n", chip->npwm); } +static DEVICE_ATTR_RO(npwm); -static struct device_attribute pwm_chip_attrs[] = { - __ATTR(export, 0200, NULL, pwm_export_store), - __ATTR(unexport, 0200, NULL, pwm_unexport_store), - __ATTR(npwm, 0444, pwm_npwm_show, NULL), - __ATTR_NULL, +static struct attribute *pwm_chip_attrs[] = { + &dev_attr_export.attr, + &dev_attr_unexport.attr, + &dev_attr_npwm.attr, + NULL, }; +ATTRIBUTE_GROUPS(pwm_chip); static struct class pwm_class = { .name = "pwm", .owner = THIS_MODULE, - .dev_attrs = pwm_chip_attrs, + .dev_groups = pwm_chip_groups, }; static int pwmchip_sysfs_match(struct device *parent, const void *data) From 260eba39bcfb5681115ec934cdfbd97e0b3a1775 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 19 Jun 2013 17:38:09 +0200 Subject: [PATCH 0935/3400] usb: musb: replace ifndef with ifdef for CONFIG_MUSB_PIO_ONLY The ifdef reads somehow better than an ifndef Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_dma.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/musb/musb_dma.h b/drivers/usb/musb/musb_dma.h index 1b6b827b769f..8919ce28c3d4 100644 --- a/drivers/usb/musb/musb_dma.h +++ b/drivers/usb/musb/musb_dma.h @@ -62,10 +62,10 @@ struct musb_hw_ep; #define DMA_ADDR_INVALID (~(dma_addr_t)0) -#ifndef CONFIG_MUSB_PIO_ONLY -#define is_dma_capable() (1) -#else +#ifdef CONFIG_MUSB_PIO_ONLY #define is_dma_capable() (0) +#else +#define is_dma_capable() (1) #endif #ifdef CONFIG_USB_TI_CPPI_DMA From ff2283229da616d9a029eaa0d483fa8b0ad55e77 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 19 Jun 2013 17:38:10 +0200 Subject: [PATCH 0936/3400] usb: musb: musbhsdma: drop the controller check in dma_controller_destroy() This check is hardly required and alas is wrong. 'c' might be NULL but the chances are low that 'controller' after the container_of() becomes NULL. Since no other DMA implementation is doing that and musb-core does not call it with a NULL pointer it can dropped. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/musb/musbhsdma.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c index 3d1fd52a15a9..3f5e121dc154 100644 --- a/drivers/usb/musb/musbhsdma.c +++ b/drivers/usb/musb/musbhsdma.c @@ -371,9 +371,6 @@ void dma_controller_destroy(struct dma_controller *c) struct musb_dma_controller *controller = container_of(c, struct musb_dma_controller, controller); - if (!controller) - return; - if (controller->irq) free_irq(controller->irq, c); From 66c01883ef19bf4537b16931567b7d35c65356ad Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 19 Jun 2013 17:38:11 +0200 Subject: [PATCH 0937/3400] usb: musb: dma: merge ->start/stop into create/destroy The core code creates a controller and immediately after that it calls the ->start() callback. This one might drop an error but nobody cares. The same thing happens in the destroy corner: First ->stop() called followed by destroy callback. So why not merge those two into the same function since there is no difference. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/musb/cppi_dma.c | 18 +++++------------- drivers/usb/musb/musb_core.c | 18 ++++-------------- drivers/usb/musb/musb_dma.h | 2 -- drivers/usb/musb/musbhsdma.c | 16 +++------------- drivers/usb/musb/tusb6010_omap.c | 24 ------------------------ drivers/usb/musb/ux500_dma.c | 19 ++++++++----------- 6 files changed, 20 insertions(+), 77 deletions(-) diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c index 9db211ee15b5..904fb85d85a6 100644 --- a/drivers/usb/musb/cppi_dma.c +++ b/drivers/usb/musb/cppi_dma.c @@ -150,14 +150,11 @@ static void cppi_pool_free(struct cppi_channel *c) c->last_processed = NULL; } -static int cppi_controller_start(struct dma_controller *c) +static void cppi_controller_start(struct cppi *controller) { - struct cppi *controller; void __iomem *tibase; int i; - controller = container_of(c, struct cppi, controller); - /* do whatever is necessary to start controller */ for (i = 0; i < ARRAY_SIZE(controller->tx); i++) { controller->tx[i].transmit = true; @@ -212,8 +209,6 @@ static int cppi_controller_start(struct dma_controller *c) /* disable RNDIS mode, also host rx RNDIS autorequest */ musb_writel(tibase, DAVINCI_RNDIS_REG, 0); musb_writel(tibase, DAVINCI_AUTOREQ_REG, 0); - - return 0; } /* @@ -222,14 +217,12 @@ static int cppi_controller_start(struct dma_controller *c) * De-Init the DMA controller as necessary. */ -static int cppi_controller_stop(struct dma_controller *c) +static void cppi_controller_stop(struct cppi *controller) { - struct cppi *controller; void __iomem *tibase; int i; struct musb *musb; - controller = container_of(c, struct cppi, controller); musb = controller->musb; tibase = controller->tibase; @@ -255,8 +248,6 @@ static int cppi_controller_stop(struct dma_controller *c) /*disable tx/rx cppi */ musb_writel(tibase, DAVINCI_TXCPPI_CTRL_REG, DAVINCI_DMA_CTRL_DISABLE); musb_writel(tibase, DAVINCI_RXCPPI_CTRL_REG, DAVINCI_DMA_CTRL_DISABLE); - - return 0; } /* While dma channel is allocated, we only want the core irqs active @@ -1321,8 +1312,6 @@ struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *mr controller->tibase = mregs - DAVINCI_BASE_OFFSET; controller->musb = musb; - controller->controller.start = cppi_controller_start; - controller->controller.stop = cppi_controller_stop; controller->controller.channel_alloc = cppi_channel_allocate; controller->controller.channel_release = cppi_channel_release; controller->controller.channel_program = cppi_channel_program; @@ -1351,6 +1340,7 @@ struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *mr controller->irq = irq; } + cppi_controller_start(controller); return &controller->controller; } @@ -1363,6 +1353,8 @@ void dma_controller_destroy(struct dma_controller *c) cppi = container_of(c, struct cppi, controller); + cppi_controller_stop(cppi); + if (cppi->irq) free_irq(cppi->irq, cppi->musb); diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 29a24ced6748..a4434d22ef13 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1764,12 +1764,8 @@ static void musb_free(struct musb *musb) disable_irq_wake(musb->nIrq); free_irq(musb->nIrq, musb); } - if (is_dma_capable() && musb->dma_controller) { - struct dma_controller *c = musb->dma_controller; - - (void) c->stop(c); - dma_controller_destroy(c); - } + if (is_dma_capable() && musb->dma_controller) + dma_controller_destroy(musb->dma_controller); musb_host_free(musb); } @@ -1845,14 +1841,8 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) pm_runtime_get_sync(musb->controller); #ifndef CONFIG_MUSB_PIO_ONLY - if (use_dma && dev->dma_mask) { - struct dma_controller *c; - - c = dma_controller_create(musb, musb->mregs); - musb->dma_controller = c; - if (c) - (void) c->start(c); - } + if (use_dma && dev->dma_mask) + musb->dma_controller = dma_controller_create(musb, musb->mregs); #endif /* ideally this would be abstracted in platform setup */ if (!is_dma_capable() || !musb->dma_controller) diff --git a/drivers/usb/musb/musb_dma.h b/drivers/usb/musb/musb_dma.h index 8919ce28c3d4..36037114ad4a 100644 --- a/drivers/usb/musb/musb_dma.h +++ b/drivers/usb/musb/musb_dma.h @@ -159,8 +159,6 @@ dma_channel_status(struct dma_channel *c) * Controllers manage dma channels. */ struct dma_controller { - int (*start)(struct dma_controller *); - int (*stop)(struct dma_controller *); struct dma_channel *(*channel_alloc)(struct dma_controller *, struct musb_hw_ep *, u8 is_tx); void (*channel_release)(struct dma_channel *); diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c index 3f5e121dc154..e8e9f9aab203 100644 --- a/drivers/usb/musb/musbhsdma.c +++ b/drivers/usb/musb/musbhsdma.c @@ -37,18 +37,10 @@ #include "musb_core.h" #include "musbhsdma.h" -static int dma_controller_start(struct dma_controller *c) -{ - /* nothing to do */ - return 0; -} - static void dma_channel_release(struct dma_channel *channel); -static int dma_controller_stop(struct dma_controller *c) +static void dma_controller_stop(struct musb_dma_controller *controller) { - struct musb_dma_controller *controller = container_of(c, - struct musb_dma_controller, controller); struct musb *musb = controller->private_data; struct dma_channel *channel; u8 bit; @@ -67,8 +59,6 @@ static int dma_controller_stop(struct dma_controller *c) } } } - - return 0; } static struct dma_channel *dma_channel_allocate(struct dma_controller *c, @@ -371,6 +361,8 @@ void dma_controller_destroy(struct dma_controller *c) struct musb_dma_controller *controller = container_of(c, struct musb_dma_controller, controller); + dma_controller_stop(controller); + if (controller->irq) free_irq(controller->irq, c); @@ -397,8 +389,6 @@ struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *ba controller->private_data = musb; controller->base = base; - controller->controller.start = dma_controller_start; - controller->controller.stop = dma_controller_stop; controller->controller.channel_alloc = dma_channel_allocate; controller->controller.channel_release = dma_channel_release; controller->controller.channel_program = dma_channel_program; diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c index 98df17c984a8..b8794eb81e9c 100644 --- a/drivers/usb/musb/tusb6010_omap.c +++ b/drivers/usb/musb/tusb6010_omap.c @@ -66,28 +66,6 @@ struct tusb_omap_dma { unsigned multichannel:1; }; -static int tusb_omap_dma_start(struct dma_controller *c) -{ - struct tusb_omap_dma *tusb_dma; - - tusb_dma = container_of(c, struct tusb_omap_dma, controller); - - /* dev_dbg(musb->controller, "ep%i ch: %i\n", chdat->epnum, chdat->ch); */ - - return 0; -} - -static int tusb_omap_dma_stop(struct dma_controller *c) -{ - struct tusb_omap_dma *tusb_dma; - - tusb_dma = container_of(c, struct tusb_omap_dma, controller); - - /* dev_dbg(musb->controller, "ep%i ch: %i\n", chdat->epnum, chdat->ch); */ - - return 0; -} - /* * Allocate dmareq0 to the current channel unless it's already taken */ @@ -695,8 +673,6 @@ struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *ba tusb_dma->dmareq = -1; tusb_dma->sync_dev = -1; - tusb_dma->controller.start = tusb_omap_dma_start; - tusb_dma->controller.stop = tusb_omap_dma_stop; tusb_dma->controller.channel_alloc = tusb_omap_dma_allocate; tusb_dma->controller.channel_release = tusb_omap_dma_release; tusb_dma->controller.channel_program = tusb_omap_dma_program; diff --git a/drivers/usb/musb/ux500_dma.c b/drivers/usb/musb/ux500_dma.c index bfb7a65d83cc..1ce214e5b7ad 100644 --- a/drivers/usb/musb/ux500_dma.c +++ b/drivers/usb/musb/ux500_dma.c @@ -254,10 +254,8 @@ static int ux500_dma_channel_abort(struct dma_channel *channel) return 0; } -static int ux500_dma_controller_stop(struct dma_controller *c) +static void ux500_dma_controller_stop(struct ux500_dma_controller *controller) { - struct ux500_dma_controller *controller = container_of(c, - struct ux500_dma_controller, controller); struct ux500_dma_channel *ux500_channel; struct dma_channel *channel; u8 ch_num; @@ -281,14 +279,10 @@ static int ux500_dma_controller_stop(struct dma_controller *c) if (ux500_channel->dma_chan) dma_release_channel(ux500_channel->dma_chan); } - - return 0; } -static int ux500_dma_controller_start(struct dma_controller *c) +static int ux500_dma_controller_start(struct ux500_dma_controller *controller) { - struct ux500_dma_controller *controller = container_of(c, - struct ux500_dma_controller, controller); struct ux500_dma_channel *ux500_channel = NULL; struct musb *musb = controller->private_data; struct device *dev = musb->controller; @@ -347,7 +341,7 @@ static int ux500_dma_controller_start(struct dma_controller *c) dir, ch_num); /* Release already allocated channels */ - ux500_dma_controller_stop(c); + ux500_dma_controller_stop(controller); return -EBUSY; } @@ -369,6 +363,7 @@ void dma_controller_destroy(struct dma_controller *c) struct ux500_dma_controller *controller = container_of(c, struct ux500_dma_controller, controller); + ux500_dma_controller_stop(controller); kfree(controller); } @@ -378,6 +373,7 @@ struct dma_controller *dma_controller_create(struct musb *musb, struct ux500_dma_controller *controller; struct platform_device *pdev = to_platform_device(musb->controller); struct resource *iomem; + int ret; controller = kzalloc(sizeof(*controller), GFP_KERNEL); if (!controller) @@ -394,14 +390,15 @@ struct dma_controller *dma_controller_create(struct musb *musb, controller->phy_base = (dma_addr_t) iomem->start; - controller->controller.start = ux500_dma_controller_start; - controller->controller.stop = ux500_dma_controller_stop; controller->controller.channel_alloc = ux500_dma_channel_allocate; controller->controller.channel_release = ux500_dma_channel_release; controller->controller.channel_program = ux500_dma_channel_program; controller->controller.channel_abort = ux500_dma_channel_abort; controller->controller.is_compatible = ux500_dma_is_compatible; + ret = ux500_dma_controller_start(controller); + if (ret) + goto plat_get_fail; return &controller->controller; plat_get_fail: From a6a20885f1e13340e30ec35acfdcf14756ecf03c Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 19 Jun 2013 17:38:12 +0200 Subject: [PATCH 0938/3400] usb: musb: provide empty dma_controller_create() in PIO mode Add a dma_controller_create() returning NULL so a few ifdefs can dropped. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_dma.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/usb/musb/musb_dma.h b/drivers/usb/musb/musb_dma.h index 36037114ad4a..c8e67fde2156 100644 --- a/drivers/usb/musb/musb_dma.h +++ b/drivers/usb/musb/musb_dma.h @@ -175,9 +175,20 @@ struct dma_controller { /* called after channel_program(), may indicate a fault */ extern void musb_dma_completion(struct musb *musb, u8 epnum, u8 transmit); +#ifdef CONFIG_MUSB_PIO_ONLY +static inline struct dma_controller *dma_controller_create(struct musb *m, + void __iomem *io) +{ + return NULL; +} + +static inline void dma_controller_destroy(struct dma_controller *d) { } + +#else extern struct dma_controller *dma_controller_create(struct musb *, void __iomem *); extern void dma_controller_destroy(struct dma_controller *); +#endif #endif /* __MUSB_DMA_H__ */ From 6904b845e27830ea0dc8d00fada5a3f478924ea3 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 19 Jun 2013 17:38:13 +0200 Subject: [PATCH 0939/3400] usb: musb: remove a few is_dma_capable() in init/exit code This patch removes is_dma_capable() and an ifdef in the init/exit path around init/de-init of the dma_controller. Since we have the empty stubs in the PIO code we can call it without gcc trouble. Earlier we had an ifdef and the is_dma_capable() macro where gcc ignored the if (0) path even that the function was not around :) Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_core.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index a4434d22ef13..b33bed5b0dc8 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1764,7 +1764,7 @@ static void musb_free(struct musb *musb) disable_irq_wake(musb->nIrq); free_irq(musb->nIrq, musb); } - if (is_dma_capable() && musb->dma_controller) + if (musb->dma_controller) dma_controller_destroy(musb->dma_controller); musb_host_free(musb); @@ -1840,12 +1840,11 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) pm_runtime_get_sync(musb->controller); -#ifndef CONFIG_MUSB_PIO_ONLY if (use_dma && dev->dma_mask) musb->dma_controller = dma_controller_create(musb, musb->mregs); -#endif + /* ideally this would be abstracted in platform setup */ - if (!is_dma_capable() || !musb->dma_controller) + if (!musb->dma_controller) dev->dma_mask = NULL; /* be sure interrupts are disabled before connecting ISR */ From f3ce4d5b2d8d714407a646c07505c5174afd7574 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 19 Jun 2013 17:38:14 +0200 Subject: [PATCH 0940/3400] usb: musb: core: call dma_controller_destroy() in the err path The cleanup in the error is missing the dma controller. The structure is allocated at runtime and ux500 allocates even a little more than just this struct. So cleanup! Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index b33bed5b0dc8..9b774e72c0e4 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1933,6 +1933,8 @@ fail4: musb_gadget_cleanup(musb); fail3: + if (musb->dma_controller) + dma_controller_destroy(musb->dma_controller); pm_runtime_put_sync(musb->controller); fail2: From 23a53d9008251825a4c8eea64503ed676e1d0f04 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 19 Jun 2013 17:38:15 +0200 Subject: [PATCH 0941/3400] usb: musb: unmap reqs in musb_gadget_queue()'s error case If the descriptor is missing the reqeust is never unmapped. This patch changes this and renames the cleanup label to unlock since there is no cleanup done. The cleanup would revert the allocation of ressource (i.e. this dma mapping) but it does not, it simply unlocks and returns. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_gadget.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 0414bc19d009..96632f9e3eeb 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1266,7 +1266,8 @@ static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req, dev_dbg(musb->controller, "req %p queued to %s while ep %s\n", req, ep->name, "disabled"); status = -ESHUTDOWN; - goto cleanup; + unmap_dma_buffer(request, musb); + goto unlock; } /* add request to the list */ @@ -1276,7 +1277,7 @@ static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req, if (!musb_ep->busy && &request->list == musb_ep->req_list.next) musb_ep_restart(musb, request); -cleanup: +unlock: spin_unlock_irqrestore(&musb->lock, lockflags); return status; } From 1a356dbc6465b0a87474993dafcd7a101ef57ff9 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 26 Jun 2013 15:14:06 +0300 Subject: [PATCH 0942/3400] usb: dwc3: make glue layers selectable Glue layers are starting to have separate requirements. For example, OMAP's glue layer is starting to use extcon framework which no one else needs. In order to make it clear the proper dependencies, we are now allowing glue layers to be selectable so that each glue layer can list their own dependencies without messing with the core IP driver. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/Kconfig | 32 ++++++++++++++++++++++++++++++++ drivers/usb/dwc3/Makefile | 13 +++---------- 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index 2378958ea63e..3e225d5846f6 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -40,6 +40,38 @@ config USB_DWC3_DUAL_ROLE endchoice +comment "Platform Glue Driver Support" + +config USB_DWC3_OMAP + tristate "Texas Instruments OMAP5 and similar Platforms" + depends on EXTCON + default USB_DWC3 + help + Some platforms from Texas Instruments like OMAP5, DRA7xxx and + AM437x use this IP for USB2/3 functionality. + + Say 'Y' or 'M' here if you have one such device + +config USB_DWC3_EXYNOS + tristate "Samsung Exynos Platform" + default USB_DWC3 + help + Recent Exynos5 SoCs ship with one DesignWare Core USB3 IP inside, + say 'Y' or 'M' if you have one such device. + +config USB_DWC3_PCI + tristate "PCIe-based Platforms" + depends on PCI + default USB_DWC3 + help + If you're using the DesignWare Core IP with a PCIe, please say + 'Y' or 'M' here. + + One such PCIe-based platform is Synopsys' PCIe HAPS model of + this IP. + +comment "Debugging features" + config USB_DWC3_DEBUG bool "Enable Debugging Messages" help diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile index 0c7ac92582be..dd1760145c46 100644 --- a/drivers/usb/dwc3/Makefile +++ b/drivers/usb/dwc3/Makefile @@ -27,15 +27,8 @@ endif # the entire driver (with all its glue layers) on several architectures # and make sure it compiles fine. This will also help with allmodconfig # and allyesconfig builds. -# -# The only exception is the PCI glue layer, but that's only because -# PCI doesn't provide nops if CONFIG_PCI isn't enabled. ## -obj-$(CONFIG_USB_DWC3) += dwc3-omap.o -obj-$(CONFIG_USB_DWC3) += dwc3-exynos.o - -ifneq ($(CONFIG_PCI),) - obj-$(CONFIG_USB_DWC3) += dwc3-pci.o -endif - +obj-$(CONFIG_USB_DWC3_OMAP) += dwc3-omap.o +obj-$(CONFIG_USB_DWC3_EXYNOS) += dwc3-exynos.o +obj-$(CONFIG_USB_DWC3_PCI) += dwc3-pci.o From 2b0c49530bc5fdbde93295e5c8f26f55d0de1e04 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 27 Jun 2013 10:20:44 +0300 Subject: [PATCH 0943/3400] usb: gadget: remove imx_udc That driver hasn't been really maintained for a long time. It doesn't compile in any way, it includes non-existent headers, has no users, and is just plain broken. The person who used to work with that driver has publicly stated that he has no plans to touch that driver again and is ok with removal[1]. Due to these factors, imx_udc is now removed from the tree, if someone really believe it needs to be kept, please fix the bugs in that driver. [1] http://marc.info/?l=linux-usb&m=136197620417636&w=2 Signed-off-by: Felipe Balbi --- drivers/usb/gadget/Kconfig | 15 - drivers/usb/gadget/Makefile | 1 - drivers/usb/gadget/imx_udc.c | 1544 ---------------------------------- drivers/usb/gadget/imx_udc.h | 351 -------- 4 files changed, 1911 deletions(-) delete mode 100644 drivers/usb/gadget/imx_udc.c delete mode 100644 drivers/usb/gadget/imx_udc.h diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 8e9368330b10..08dab3c640fd 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -287,21 +287,6 @@ config USB_S3C_HSOTG The Samsung S3C64XX USB2.0 high-speed gadget controller integrated into the S3C64XX series SoC. -config USB_IMX - tristate "Freescale i.MX1 USB Peripheral Controller" - depends on ARCH_MXC - depends on BROKEN - help - Freescale's i.MX1 includes an integrated full speed - USB 1.1 device controller. - - It has Six fixed-function endpoints, as well as endpoint - zero (for control transfers). - - Say "y" to link the driver statically, or "m" to build a - dynamically linked module called "imx_udc" and force all - gadget drivers to also be dynamically linked. - config USB_S3C2410 tristate "S3C2410 USB Device Controller" depends on ARCH_S3C24XX diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index bad08e66f369..386db9daf1d9 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -13,7 +13,6 @@ obj-$(CONFIG_USB_NET2280) += net2280.o obj-$(CONFIG_USB_AMD5536UDC) += amd5536udc.o obj-$(CONFIG_USB_PXA25X) += pxa25x_udc.o obj-$(CONFIG_USB_PXA27X) += pxa27x_udc.o -obj-$(CONFIG_USB_IMX) += imx_udc.o obj-$(CONFIG_USB_GOKU) += goku_udc.o obj-$(CONFIG_USB_OMAP) += omap_udc.o obj-$(CONFIG_USB_S3C2410) += s3c2410_udc.o diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c deleted file mode 100644 index 9b2d24e4c95f..000000000000 --- a/drivers/usb/gadget/imx_udc.c +++ /dev/null @@ -1,1544 +0,0 @@ -/* - * driver/usb/gadget/imx_udc.c - * - * Copyright (C) 2005 Mike Lee - * Copyright (C) 2008 Darius Augulis - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include "imx_udc.h" - -static const char driver_name[] = "imx_udc"; -static const char ep0name[] = "ep0"; - -void ep0_chg_stat(const char *label, struct imx_udc_struct *imx_usb, - enum ep0_state stat); - -/******************************************************************************* - * IMX UDC hardware related functions - ******************************************************************************* - */ - -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); - imx_usb->gadget.speed = USB_SPEED_FULL; -} - -void imx_udc_disable(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); - - ep0_chg_stat(__func__, imx_usb, EP0_IDLE); - imx_usb->gadget.speed = USB_SPEED_UNKNOWN; -} - -void imx_udc_reset(struct imx_udc_struct *imx_usb) -{ - int temp = __raw_readl(imx_usb->base + USB_ENAB); - - /* set RST bit */ - __raw_writel(temp | ENAB_RST, imx_usb->base + USB_ENAB); - - /* wait RST bit to clear */ - do {} while (__raw_readl(imx_usb->base + USB_ENAB) & ENAB_RST); - - /* wait CFG bit to assert */ - do {} while (!(__raw_readl(imx_usb->base + USB_DADR) & DADR_CFG)); - - /* udc module is now ready */ -} - -void imx_udc_config(struct imx_udc_struct *imx_usb) -{ - u8 ep_conf[5]; - u8 i, j, cfg; - struct imx_ep_struct *imx_ep; - - /* wait CFG bit to assert */ - do {} while (!(__raw_readl(imx_usb->base + USB_DADR) & DADR_CFG)); - - /* Download the endpoint buffer for endpoint 0. */ - for (j = 0; j < 5; j++) { - i = (j == 2 ? imx_usb->imx_ep[0].fifosize : 0x00); - __raw_writeb(i, imx_usb->base + USB_DDAT); - do {} while (__raw_readl(imx_usb->base + USB_DADR) & DADR_BSY); - } - - /* Download the endpoint buffers for endpoints 1-5. - * We specify two configurations, one interface - */ - for (cfg = 1; cfg < 3; cfg++) { - for (i = 1; i < IMX_USB_NB_EP; i++) { - imx_ep = &imx_usb->imx_ep[i]; - /* EP no | Config no */ - ep_conf[0] = (i << 4) | (cfg << 2); - /* Type | Direction */ - ep_conf[1] = (imx_ep->bmAttributes << 3) | - (EP_DIR(imx_ep) << 2); - /* Max packet size */ - ep_conf[2] = imx_ep->fifosize; - /* TRXTYP */ - ep_conf[3] = 0xC0; - /* FIFO no */ - ep_conf[4] = i; - - D_INI(imx_usb->dev, - "<%s> ep%d_conf[%d]:" - "[%02x-%02x-%02x-%02x-%02x]\n", - __func__, i, cfg, - ep_conf[0], ep_conf[1], ep_conf[2], - ep_conf[3], ep_conf[4]); - - 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) - & DADR_BSY); - } - } - } - - /* wait CFG bit to clear */ - do {} while (__raw_readl(imx_usb->base + USB_DADR) & DADR_CFG); -} - -void imx_udc_init_irq(struct imx_udc_struct *imx_usb) -{ - int i; - - /* Mask and clear all irqs */ - __raw_writel(0xFFFFFFFF, imx_usb->base + USB_MASK); - __raw_writel(0xFFFFFFFF, imx_usb->base + USB_INTR); - for (i = 0; i < IMX_USB_NB_EP; i++) { - __raw_writel(0x1FF, imx_usb->base + USB_EP_MASK(i)); - __raw_writel(0x1FF, imx_usb->base + USB_EP_INTR(i)); - } - - /* Enable USB irqs */ - __raw_writel(INTR_MSOF | INTR_FRAME_MATCH, imx_usb->base + USB_MASK); - - /* Enable EP0 irqs */ - __raw_writel(0x1FF & ~(EPINTR_DEVREQ | EPINTR_MDEVREQ | EPINTR_EOT - | EPINTR_EOF | EPINTR_FIFO_EMPTY | EPINTR_FIFO_FULL), - imx_usb->base + USB_EP_MASK(0)); -} - -void imx_udc_init_ep(struct imx_udc_struct *imx_usb) -{ - int i, max, temp; - struct imx_ep_struct *imx_ep; - for (i = 0; i < IMX_USB_NB_EP; i++) { - imx_ep = &imx_usb->imx_ep[i]; - switch (imx_ep->fifosize) { - case 8: - max = 0; - break; - case 16: - max = 1; - break; - case 32: - max = 2; - break; - case 64: - max = 3; - break; - default: - max = 1; - break; - } - 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)); - D_INI(imx_usb->dev, "<%s> ep%d_stat %08x\n", __func__, i, - __raw_readl(imx_usb->base + USB_EP_STAT(i))); - } -} - -void imx_udc_init_fifo(struct imx_udc_struct *imx_usb) -{ - int i, temp; - struct imx_ep_struct *imx_ep; - for (i = 0; i < IMX_USB_NB_EP; i++) { - imx_ep = &imx_usb->imx_ep[i]; - - /* Fifo control */ - temp = EP_DIR(imx_ep) ? 0x0B000000 : 0x0F000000; - __raw_writel(temp, imx_usb->base + USB_EP_FCTRL(i)); - D_INI(imx_usb->dev, "<%s> ep%d_fctrl %08x\n", __func__, i, - __raw_readl(imx_usb->base + USB_EP_FCTRL(i))); - - /* Fifo alarm */ - temp = (i ? imx_ep->fifosize / 2 : 0); - __raw_writel(temp, imx_usb->base + USB_EP_FALRM(i)); - D_INI(imx_usb->dev, "<%s> ep%d_falrm %08x\n", __func__, i, - __raw_readl(imx_usb->base + USB_EP_FALRM(i))); - } -} - -static void imx_udc_init(struct imx_udc_struct *imx_usb) -{ - /* Reset UDC */ - imx_udc_reset(imx_usb); - - /* Download config to enpoint buffer */ - imx_udc_config(imx_usb); - - /* Setup interrups */ - imx_udc_init_irq(imx_usb); - - /* Setup endpoints */ - imx_udc_init_ep(imx_usb); - - /* Setup fifos */ - imx_udc_init_fifo(imx_usb); -} - -void imx_ep_irq_enable(struct imx_ep_struct *imx_ep) -{ - - int i = EP_NO(imx_ep); - - __raw_writel(0x1FF, imx_ep->imx_usb->base + USB_EP_MASK(i)); - __raw_writel(0x1FF, imx_ep->imx_usb->base + USB_EP_INTR(i)); - __raw_writel(0x1FF & ~(EPINTR_EOT | EPINTR_EOF), - imx_ep->imx_usb->base + USB_EP_MASK(i)); -} - -void imx_ep_irq_disable(struct imx_ep_struct *imx_ep) -{ - - int i = EP_NO(imx_ep); - - __raw_writel(0x1FF, imx_ep->imx_usb->base + USB_EP_MASK(i)); - __raw_writel(0x1FF, imx_ep->imx_usb->base + USB_EP_INTR(i)); -} - -int imx_ep_empty(struct imx_ep_struct *imx_ep) -{ - struct imx_udc_struct *imx_usb = imx_ep->imx_usb; - - return __raw_readl(imx_usb->base + USB_EP_FSTAT(EP_NO(imx_ep))) - & FSTAT_EMPTY; -} - -unsigned imx_fifo_bcount(struct imx_ep_struct *imx_ep) -{ - struct imx_udc_struct *imx_usb = imx_ep->imx_usb; - - return (__raw_readl(imx_usb->base + USB_EP_STAT(EP_NO(imx_ep))) - & EPSTAT_BCOUNT) >> 16; -} - -void imx_flush(struct imx_ep_struct *imx_ep) -{ - struct imx_udc_struct *imx_usb = imx_ep->imx_usb; - - int temp = __raw_readl(imx_usb->base + USB_EP_STAT(EP_NO(imx_ep))); - __raw_writel(temp | EPSTAT_FLUSH, - imx_usb->base + USB_EP_STAT(EP_NO(imx_ep))); -} - -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); - - 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); - temp = __raw_readl(imx_usb->base + USB_CTRL); - __raw_writel(temp & ~CTRL_CMDERROR, imx_usb->base + USB_CTRL); - } - else { - temp = __raw_readl(imx_usb->base + USB_EP_STAT(EP_NO(imx_ep))); - __raw_writel(temp | EPSTAT_STALL, - 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))); - if (!(temp & EPSTAT_STALL)) - break; - udelay(20); - } - if (i == 100) - D_ERR(imx_usb->dev, "<%s> Non finished stall on %s\n", - __func__, imx_ep->ep.name); - } -} - -static int imx_udc_get_frame(struct usb_gadget *_gadget) -{ - struct imx_udc_struct *imx_usb = container_of(_gadget, - struct imx_udc_struct, gadget); - - return __raw_readl(imx_usb->base + USB_FRAME) & 0x7FF; -} - -static int imx_udc_wakeup(struct usb_gadget *_gadget) -{ - return 0; -} - -/******************************************************************************* - * USB request control functions - ******************************************************************************* - */ - -static void ep_add_request(struct imx_ep_struct *imx_ep, - struct imx_request *req) -{ - if (unlikely(!req)) - return; - - req->in_use = 1; - list_add_tail(&req->queue, &imx_ep->queue); -} - -static void ep_del_request(struct imx_ep_struct *imx_ep, - struct imx_request *req) -{ - if (unlikely(!req)) - return; - - list_del_init(&req->queue); - req->in_use = 0; -} - -static void done(struct imx_ep_struct *imx_ep, - struct imx_request *req, int status) -{ - ep_del_request(imx_ep, req); - - if (likely(req->req.status == -EINPROGRESS)) - req->req.status = status; - else - status = req->req.status; - - if (status && status != -ESHUTDOWN) - D_ERR(imx_ep->imx_usb->dev, - "<%s> complete %s req %p stat %d len %u/%u\n", __func__, - imx_ep->ep.name, &req->req, status, - req->req.actual, req->req.length); - - req->req.complete(&imx_ep->ep, &req->req); -} - -static void nuke(struct imx_ep_struct *imx_ep, int status) -{ - struct imx_request *req; - - while (!list_empty(&imx_ep->queue)) { - req = list_entry(imx_ep->queue.next, struct imx_request, queue); - done(imx_ep, req, status); - } -} - -/******************************************************************************* - * Data tansfer over USB functions - ******************************************************************************* - */ -static int read_packet(struct imx_ep_struct *imx_ep, struct imx_request *req) -{ - u8 *buf; - int bytes_ep, bufferspace, count, i; - - bytes_ep = imx_fifo_bcount(imx_ep); - bufferspace = req->req.length - req->req.actual; - - buf = req->req.buf + req->req.actual; - prefetchw(buf); - - if (unlikely(imx_ep_empty(imx_ep))) - count = 0; /* zlp */ - else - count = min(bytes_ep, bufferspace); - - for (i = count; i > 0; i--) - *buf++ = __raw_readb(imx_ep->imx_usb->base - + USB_EP_FDAT0(EP_NO(imx_ep))); - req->req.actual += count; - - return count; -} - -static int write_packet(struct imx_ep_struct *imx_ep, struct imx_request *req) -{ - u8 *buf; - int length, count, temp; - - if (unlikely(__raw_readl(imx_ep->imx_usb->base + - USB_EP_STAT(EP_NO(imx_ep))) & EPSTAT_ZLPS)) { - D_TRX(imx_ep->imx_usb->dev, "<%s> zlp still queued in EP %s\n", - __func__, imx_ep->ep.name); - return -1; - } - - buf = req->req.buf + req->req.actual; - prefetch(buf); - - length = min(req->req.length - req->req.actual, (u32)imx_ep->fifosize); - - if (imx_fifo_bcount(imx_ep) + length > imx_ep->fifosize) { - D_TRX(imx_ep->imx_usb->dev, "<%s> packet overfill %s fifo\n", - __func__, imx_ep->ep.name); - return -1; - } - - req->req.actual += length; - count = length; - - if (!count && req->req.zero) { /* zlp */ - temp = __raw_readl(imx_ep->imx_usb->base - + USB_EP_STAT(EP_NO(imx_ep))); - __raw_writel(temp | EPSTAT_ZLPS, imx_ep->imx_usb->base - + USB_EP_STAT(EP_NO(imx_ep))); - D_TRX(imx_ep->imx_usb->dev, "<%s> zero packet\n", __func__); - return 0; - } - - while (count--) { - if (count == 0) { /* last byte */ - temp = __raw_readl(imx_ep->imx_usb->base - + USB_EP_FCTRL(EP_NO(imx_ep))); - __raw_writel(temp | FCTRL_WFR, imx_ep->imx_usb->base - + USB_EP_FCTRL(EP_NO(imx_ep))); - } - __raw_writeb(*buf++, - imx_ep->imx_usb->base + USB_EP_FDAT0(EP_NO(imx_ep))); - } - - return length; -} - -static int read_fifo(struct imx_ep_struct *imx_ep, struct imx_request *req) -{ - int bytes = 0, - count, - completed = 0; - - while (__raw_readl(imx_ep->imx_usb->base + USB_EP_FSTAT(EP_NO(imx_ep))) - & FSTAT_FR) { - count = read_packet(imx_ep, req); - bytes += count; - - completed = (count != imx_ep->fifosize); - if (completed || req->req.actual == req->req.length) { - completed = 1; - break; - } - } - - if (completed || !req->req.length) { - done(imx_ep, req, 0); - D_REQ(imx_ep->imx_usb->dev, "<%s> %s req<%p> %s\n", - __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); - } - - D_TRX(imx_ep->imx_usb->dev, "<%s> bytes read: %d\n", __func__, bytes); - - return completed; -} - -static int write_fifo(struct imx_ep_struct *imx_ep, struct imx_request *req) -{ - int bytes = 0, - count, - completed = 0; - - while (!completed) { - count = write_packet(imx_ep, req); - if (count < 0) - break; /* busy */ - bytes += count; - - /* last packet "must be" short (or a zlp) */ - completed = (count != imx_ep->fifosize); - - if (unlikely(completed)) { - done(imx_ep, req, 0); - D_REQ(imx_ep->imx_usb->dev, "<%s> %s req<%p> %s\n", - __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); - } - } - - D_TRX(imx_ep->imx_usb->dev, "<%s> bytes sent: %d\n", __func__, bytes); - - return completed; -} - -/******************************************************************************* - * Endpoint handlers - ******************************************************************************* - */ -static int handle_ep(struct imx_ep_struct *imx_ep) -{ - struct imx_request *req; - int completed = 0; - - do { - if (!list_empty(&imx_ep->queue)) - req = list_entry(imx_ep->queue.next, - struct imx_request, queue); - else { - D_REQ(imx_ep->imx_usb->dev, "<%s> no request on %s\n", - __func__, imx_ep->ep.name); - return 0; - } - - if (EP_DIR(imx_ep)) /* to host */ - completed = write_fifo(imx_ep, req); - else /* to device */ - completed = read_fifo(imx_ep, req); - - dump_ep_stat(__func__, imx_ep); - - } while (completed); - - return 0; -} - -static int handle_ep0(struct imx_ep_struct *imx_ep) -{ - struct imx_request *req = NULL; - int ret = 0; - - if (!list_empty(&imx_ep->queue)) { - req = list_entry(imx_ep->queue.next, struct imx_request, queue); - - switch (imx_ep->imx_usb->ep0state) { - - case EP0_IN_DATA_PHASE: /* GET_DESCRIPTOR */ - write_fifo(imx_ep, req); - break; - case EP0_OUT_DATA_PHASE: /* SET_DESCRIPTOR */ - read_fifo(imx_ep, req); - break; - default: - D_EP0(imx_ep->imx_usb->dev, - "<%s> ep0 i/o, odd state %d\n", - __func__, imx_ep->imx_usb->ep0state); - ep_del_request(imx_ep, req); - ret = -EL2HLT; - break; - } - } - - else - D_ERR(imx_ep->imx_usb->dev, "<%s> no request on %s\n", - __func__, imx_ep->ep.name); - - return ret; -} - -static void handle_ep0_devreq(struct imx_udc_struct *imx_usb) -{ - struct imx_ep_struct *imx_ep = &imx_usb->imx_ep[0]; - union { - struct usb_ctrlrequest r; - u8 raw[8]; - u32 word[2]; - } u; - int temp, i; - - nuke(imx_ep, -EPROTO); - - /* read SETUP packet */ - for (i = 0; i < 2; i++) { - if (imx_ep_empty(imx_ep)) { - D_ERR(imx_usb->dev, - "<%s> no setup packet received\n", __func__); - goto stall; - } - u.word[i] = __raw_readl(imx_usb->base - + USB_EP_FDAT(EP_NO(imx_ep))); - } - - temp = imx_ep_empty(imx_ep); - while (!imx_ep_empty(imx_ep)) { - i = __raw_readl(imx_usb->base + USB_EP_FDAT(EP_NO(imx_ep))); - D_ERR(imx_usb->dev, - "<%s> wrong to have extra bytes for setup : 0x%08x\n", - __func__, i); - } - if (!temp) - goto stall; - - le16_to_cpus(&u.r.wValue); - le16_to_cpus(&u.r.wIndex); - le16_to_cpus(&u.r.wLength); - - D_REQ(imx_usb->dev, "<%s> SETUP %02x.%02x v%04x i%04x l%04x\n", - __func__, u.r.bRequestType, u.r.bRequest, - u.r.wValue, u.r.wIndex, u.r.wLength); - - if (imx_usb->set_config) { - /* NACK the host by using CMDOVER */ - temp = __raw_readl(imx_usb->base + USB_CTRL); - __raw_writel(temp | CTRL_CMDOVER, imx_usb->base + USB_CTRL); - - D_ERR(imx_usb->dev, - "<%s> set config req is pending, NACK the host\n", - __func__); - return; - } - - if (u.r.bRequestType & USB_DIR_IN) - ep0_chg_stat(__func__, imx_usb, EP0_IN_DATA_PHASE); - else - ep0_chg_stat(__func__, imx_usb, EP0_OUT_DATA_PHASE); - - i = imx_usb->driver->setup(&imx_usb->gadget, &u.r); - if (i < 0) { - D_ERR(imx_usb->dev, "<%s> device setup error %d\n", - __func__, i); - goto stall; - } - - return; -stall: - D_ERR(imx_usb->dev, "<%s> protocol STALL\n", __func__); - imx_ep_stall(imx_ep); - ep0_chg_stat(__func__, imx_usb, EP0_STALL); - return; -} - -/******************************************************************************* - * USB gadget callback functions - ******************************************************************************* - */ - -static int imx_ep_enable(struct usb_ep *usb_ep, - const struct usb_endpoint_descriptor *desc) -{ - struct imx_ep_struct *imx_ep = container_of(usb_ep, - struct imx_ep_struct, ep); - struct imx_udc_struct *imx_usb = imx_ep->imx_usb; - unsigned long flags; - - if (!usb_ep - || !desc - || !EP_NO(imx_ep) - || desc->bDescriptorType != USB_DT_ENDPOINT - || imx_ep->bEndpointAddress != desc->bEndpointAddress) { - D_ERR(imx_usb->dev, - "<%s> bad ep or descriptor\n", __func__); - return -EINVAL; - } - - if (imx_ep->bmAttributes != desc->bmAttributes) { - D_ERR(imx_usb->dev, - "<%s> %s type mismatch\n", __func__, usb_ep->name); - return -EINVAL; - } - - if (imx_ep->fifosize < usb_endpoint_maxp(desc)) { - D_ERR(imx_usb->dev, - "<%s> bad %s maxpacket\n", __func__, usb_ep->name); - return -ERANGE; - } - - if (!imx_usb->driver || imx_usb->gadget.speed == USB_SPEED_UNKNOWN) { - D_ERR(imx_usb->dev, "<%s> bogus device state\n", __func__); - return -ESHUTDOWN; - } - - local_irq_save(flags); - - imx_ep->stopped = 0; - imx_flush(imx_ep); - imx_ep_irq_enable(imx_ep); - - local_irq_restore(flags); - - D_EPX(imx_usb->dev, "<%s> ENABLED %s\n", __func__, usb_ep->name); - return 0; -} - -static int imx_ep_disable(struct usb_ep *usb_ep) -{ - struct imx_ep_struct *imx_ep = container_of(usb_ep, - struct imx_ep_struct, ep); - unsigned long flags; - - if (!usb_ep || !EP_NO(imx_ep) || !list_empty(&imx_ep->queue)) { - D_ERR(imx_ep->imx_usb->dev, "<%s> %s can not be disabled\n", - __func__, usb_ep ? imx_ep->ep.name : NULL); - return -EINVAL; - } - - local_irq_save(flags); - - imx_ep->stopped = 1; - nuke(imx_ep, -ESHUTDOWN); - imx_flush(imx_ep); - imx_ep_irq_disable(imx_ep); - - local_irq_restore(flags); - - D_EPX(imx_ep->imx_usb->dev, - "<%s> DISABLED %s\n", __func__, usb_ep->name); - return 0; -} - -static struct usb_request *imx_ep_alloc_request - (struct usb_ep *usb_ep, gfp_t gfp_flags) -{ - struct imx_request *req; - - if (!usb_ep) - return NULL; - - req = kzalloc(sizeof *req, gfp_flags); - if (!req) - return NULL; - - INIT_LIST_HEAD(&req->queue); - req->in_use = 0; - - return &req->req; -} - -static void imx_ep_free_request - (struct usb_ep *usb_ep, struct usb_request *usb_req) -{ - struct imx_request *req; - - req = container_of(usb_req, struct imx_request, req); - WARN_ON(!list_empty(&req->queue)); - kfree(req); -} - -static int imx_ep_queue - (struct usb_ep *usb_ep, struct usb_request *usb_req, gfp_t gfp_flags) -{ - struct imx_ep_struct *imx_ep; - struct imx_udc_struct *imx_usb; - struct imx_request *req; - unsigned long flags; - int ret = 0; - - imx_ep = container_of(usb_ep, struct imx_ep_struct, ep); - imx_usb = imx_ep->imx_usb; - req = container_of(usb_req, struct imx_request, req); - - /* - Special care on IMX udc. - Ignore enqueue when after set configuration from the - host. This assume all gadget drivers reply set - configuration with the next ep0 req enqueue. - */ - if (imx_usb->set_config && !EP_NO(imx_ep)) { - imx_usb->set_config = 0; - D_ERR(imx_usb->dev, - "<%s> gadget reply set config\n", __func__); - return 0; - } - - if (unlikely(!usb_req || !req || !usb_req->complete || !usb_req->buf)) { - D_ERR(imx_usb->dev, "<%s> bad params\n", __func__); - return -EINVAL; - } - - if (unlikely(!usb_ep || !imx_ep)) { - D_ERR(imx_usb->dev, "<%s> bad ep\n", __func__); - return -EINVAL; - } - - if (!imx_usb->driver || imx_usb->gadget.speed == USB_SPEED_UNKNOWN) { - D_ERR(imx_usb->dev, "<%s> bogus device state\n", __func__); - return -ESHUTDOWN; - } - - /* 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); - dump_req(__func__, imx_ep, usb_req); - - if (imx_ep->stopped) { - usb_req->status = -ESHUTDOWN; - return -ESHUTDOWN; - } - - if (req->in_use) { - D_ERR(imx_usb->dev, - "<%s> refusing to queue req %p (already queued)\n", - __func__, req); - return 0; - } - - local_irq_save(flags); - - usb_req->status = -EINPROGRESS; - usb_req->actual = 0; - - ep_add_request(imx_ep, req); - - if (!EP_NO(imx_ep)) - ret = handle_ep0(imx_ep); - else - ret = handle_ep(imx_ep); - - local_irq_restore(flags); - return ret; -} - -static int imx_ep_dequeue(struct usb_ep *usb_ep, struct usb_request *usb_req) -{ - - struct imx_ep_struct *imx_ep = container_of - (usb_ep, struct imx_ep_struct, ep); - struct imx_request *req; - unsigned long flags; - - if (unlikely(!usb_ep || !EP_NO(imx_ep))) { - D_ERR(imx_ep->imx_usb->dev, "<%s> bad ep\n", __func__); - return -EINVAL; - } - - local_irq_save(flags); - - /* make sure it's actually queued on this endpoint */ - list_for_each_entry(req, &imx_ep->queue, queue) { - if (&req->req == usb_req) - break; - } - if (&req->req != usb_req) { - local_irq_restore(flags); - return -EINVAL; - } - - done(imx_ep, req, -ECONNRESET); - - local_irq_restore(flags); - return 0; -} - -static int imx_ep_set_halt(struct usb_ep *usb_ep, int value) -{ - struct imx_ep_struct *imx_ep = container_of - (usb_ep, struct imx_ep_struct, ep); - unsigned long flags; - - if (unlikely(!usb_ep || !EP_NO(imx_ep))) { - D_ERR(imx_ep->imx_usb->dev, "<%s> bad ep\n", __func__); - return -EINVAL; - } - - local_irq_save(flags); - - if ((imx_ep->bEndpointAddress & USB_DIR_IN) - && !list_empty(&imx_ep->queue)) { - local_irq_restore(flags); - return -EAGAIN; - } - - imx_ep_stall(imx_ep); - - local_irq_restore(flags); - - D_EPX(imx_ep->imx_usb->dev, "<%s> %s halt\n", __func__, usb_ep->name); - return 0; -} - -static int imx_ep_fifo_status(struct usb_ep *usb_ep) -{ - struct imx_ep_struct *imx_ep = container_of - (usb_ep, struct imx_ep_struct, ep); - - if (!usb_ep) { - D_ERR(imx_ep->imx_usb->dev, "<%s> bad ep\n", __func__); - return -ENODEV; - } - - if (imx_ep->imx_usb->gadget.speed == USB_SPEED_UNKNOWN) - return 0; - else - return imx_fifo_bcount(imx_ep); -} - -static void imx_ep_fifo_flush(struct usb_ep *usb_ep) -{ - struct imx_ep_struct *imx_ep = container_of - (usb_ep, struct imx_ep_struct, ep); - unsigned long flags; - - local_irq_save(flags); - - if (!usb_ep || !EP_NO(imx_ep) || !list_empty(&imx_ep->queue)) { - D_ERR(imx_ep->imx_usb->dev, "<%s> bad ep\n", __func__); - local_irq_restore(flags); - return; - } - - /* toggle and halt bits stay unchanged */ - imx_flush(imx_ep); - - local_irq_restore(flags); -} - -static struct usb_ep_ops imx_ep_ops = { - .enable = imx_ep_enable, - .disable = imx_ep_disable, - - .alloc_request = imx_ep_alloc_request, - .free_request = imx_ep_free_request, - - .queue = imx_ep_queue, - .dequeue = imx_ep_dequeue, - - .set_halt = imx_ep_set_halt, - .fifo_status = imx_ep_fifo_status, - .fifo_flush = imx_ep_fifo_flush, -}; - -/******************************************************************************* - * USB endpoint control functions - ******************************************************************************* - */ - -void ep0_chg_stat(const char *label, - struct imx_udc_struct *imx_usb, enum ep0_state stat) -{ - D_EP0(imx_usb->dev, "<%s> from %15s to %15s\n", - label, state_name[imx_usb->ep0state], state_name[stat]); - - if (imx_usb->ep0state == stat) - return; - - imx_usb->ep0state = stat; -} - -static void usb_init_data(struct imx_udc_struct *imx_usb) -{ - struct imx_ep_struct *imx_ep; - u8 i; - - /* device/ep0 records init */ - INIT_LIST_HEAD(&imx_usb->gadget.ep_list); - INIT_LIST_HEAD(&imx_usb->gadget.ep0->ep_list); - ep0_chg_stat(__func__, imx_usb, EP0_IDLE); - - /* basic endpoint records init */ - for (i = 0; i < IMX_USB_NB_EP; i++) { - imx_ep = &imx_usb->imx_ep[i]; - - if (i) { - list_add_tail(&imx_ep->ep.ep_list, - &imx_usb->gadget.ep_list); - imx_ep->stopped = 1; - } else - imx_ep->stopped = 0; - - INIT_LIST_HEAD(&imx_ep->queue); - } -} - -static void udc_stop_activity(struct imx_udc_struct *imx_usb, - struct usb_gadget_driver *driver) -{ - struct imx_ep_struct *imx_ep; - int i; - - if (imx_usb->gadget.speed == USB_SPEED_UNKNOWN) - driver = NULL; - - /* prevent new request submissions, kill any outstanding requests */ - for (i = 1; i < IMX_USB_NB_EP; i++) { - imx_ep = &imx_usb->imx_ep[i]; - imx_flush(imx_ep); - imx_ep->stopped = 1; - imx_ep_irq_disable(imx_ep); - nuke(imx_ep, -ESHUTDOWN); - } - - imx_usb->cfg = 0; - imx_usb->intf = 0; - imx_usb->alt = 0; - - if (driver) - driver->disconnect(&imx_usb->gadget); -} - -/******************************************************************************* - * Interrupt handlers - ******************************************************************************* - */ - -/* - * 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 = (void *)data; - struct usb_ctrlrequest u; - int temp, cfg, intf, alt; - - local_irq_disable(); - - 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); - - if (cfg == 1 || cfg == 2) { - - if (imx_usb->cfg != cfg) { - u.bRequest = USB_REQ_SET_CONFIGURATION; - u.bRequestType = USB_DIR_OUT | - USB_TYPE_STANDARD | - USB_RECIP_DEVICE; - u.wValue = cfg; - u.wIndex = 0; - u.wLength = 0; - imx_usb->cfg = cfg; - imx_usb->driver->setup(&imx_usb->gadget, &u); - - } - if (imx_usb->intf != intf || imx_usb->alt != alt) { - u.bRequest = USB_REQ_SET_INTERFACE; - u.bRequestType = USB_DIR_OUT | - USB_TYPE_STANDARD | - USB_RECIP_INTERFACE; - u.wValue = alt; - u.wIndex = intf; - u.wLength = 0; - imx_usb->intf = intf; - imx_usb->alt = alt; - imx_usb->driver->setup(&imx_usb->gadget, &u); - } - } - - 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. - 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); - } - } - - 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; -} - -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); - - if (!imx_usb->driver) { - __raw_writel(intr, imx_usb->base + USB_EP_INTR(0)); - return IRQ_HANDLED; - } - - /* 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 don't monitor EOF. - * We call handle_ep0() only if a request is queued for ep0. - */ - else if (!list_empty(&imx_ep->queue)) - handle_ep0(imx_ep); - - __raw_writel(intr, imx_usb->base + USB_EP_INTR(0)); - - return IRQ_HANDLED; -} - -#ifndef MX1_INT_USBD0 -#define MX1_INT_USBD0 MX1_USBD_INT0 -#endif - -static irqreturn_t imx_udc_bulk_irq(int irq, void *dev) -{ - struct imx_udc_struct *imx_usb = dev; - struct imx_ep_struct *imx_ep = &imx_usb->imx_ep[irq - MX1_INT_USBD0]; - int intr = __raw_readl(imx_usb->base + USB_EP_INTR(EP_NO(imx_ep))); - - dump_ep_intr(__func__, irq - MX1_INT_USBD0, intr, imx_usb->dev); - - if (!imx_usb->driver) { - __raw_writel(intr, imx_usb->base + USB_EP_INTR(EP_NO(imx_ep))); - return IRQ_HANDLED; - } - - handle_ep(imx_ep); - - __raw_writel(intr, imx_usb->base + USB_EP_INTR(EP_NO(imx_ep))); - - return IRQ_HANDLED; -} - -irq_handler_t intr_handler(int i) -{ - switch (i) { - case 0: - return imx_udc_ctrl_irq; - case 1: - case 2: - case 3: - case 4: - case 5: - return imx_udc_bulk_irq; - default: - return imx_udc_irq; - } -} - -/******************************************************************************* - * Static defined IMX UDC structure - ******************************************************************************* - */ - -static int imx_udc_start(struct usb_gadget *gadget, - struct usb_gadget_driver *driver); -static int imx_udc_stop(struct usb_gadget *gadget, - struct usb_gadget_driver *driver); -static const struct usb_gadget_ops imx_udc_ops = { - .get_frame = imx_udc_get_frame, - .wakeup = imx_udc_wakeup, - .udc_start = imx_udc_start, - .udc_stop = imx_udc_stop, -}; - -static struct imx_udc_struct controller = { - .gadget = { - .ops = &imx_udc_ops, - .ep0 = &controller.imx_ep[0].ep, - .name = driver_name, - .dev = { - .init_name = "gadget", - }, - }, - - .imx_ep[0] = { - .ep = { - .name = ep0name, - .ops = &imx_ep_ops, - .maxpacket = 32, - }, - .imx_usb = &controller, - .fifosize = 32, - .bEndpointAddress = 0, - .bmAttributes = USB_ENDPOINT_XFER_CONTROL, - }, - .imx_ep[1] = { - .ep = { - .name = "ep1in-bulk", - .ops = &imx_ep_ops, - .maxpacket = 64, - }, - .imx_usb = &controller, - .fifosize = 64, - .bEndpointAddress = USB_DIR_IN | 1, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - }, - .imx_ep[2] = { - .ep = { - .name = "ep2out-bulk", - .ops = &imx_ep_ops, - .maxpacket = 64, - }, - .imx_usb = &controller, - .fifosize = 64, - .bEndpointAddress = USB_DIR_OUT | 2, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - }, - .imx_ep[3] = { - .ep = { - .name = "ep3out-bulk", - .ops = &imx_ep_ops, - .maxpacket = 32, - }, - .imx_usb = &controller, - .fifosize = 32, - .bEndpointAddress = USB_DIR_OUT | 3, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - }, - .imx_ep[4] = { - .ep = { - .name = "ep4in-int", - .ops = &imx_ep_ops, - .maxpacket = 32, - }, - .imx_usb = &controller, - .fifosize = 32, - .bEndpointAddress = USB_DIR_IN | 4, - .bmAttributes = USB_ENDPOINT_XFER_INT, - }, - .imx_ep[5] = { - .ep = { - .name = "ep5out-int", - .ops = &imx_ep_ops, - .maxpacket = 32, - }, - .imx_usb = &controller, - .fifosize = 32, - .bEndpointAddress = USB_DIR_OUT | 5, - .bmAttributes = USB_ENDPOINT_XFER_INT, - }, -}; - -/******************************************************************************* - * USB gadget driver functions - ******************************************************************************* - */ -static int imx_udc_start(struct usb_gadget *gadget, - struct usb_gadget_driver *driver) -{ - struct imx_udc_struct *imx_usb; - - imx_usb = container_of(gadget, struct imx_udc_struct, gadget); - /* first hook up the driver ... */ - imx_usb->driver = driver; - - D_INI(imx_usb->dev, "<%s> registered gadget driver '%s'\n", - __func__, driver->driver.name); - - imx_udc_enable(imx_usb); - - return 0; -} - -static int imx_udc_stop(struct usb_gadget *gadget, - struct usb_gadget_driver *driver) -{ - struct imx_udc_struct *imx_usb = container_of(gadget, - struct imx_udc_struct, gadget); - - udc_stop_activity(imx_usb, driver); - imx_udc_disable(imx_usb); - del_timer(&imx_usb->timer); - - imx_usb->driver = NULL; - - D_INI(imx_usb->dev, "<%s> unregistered gadget driver '%s'\n", - __func__, driver->driver.name); - - return 0; -} - -/******************************************************************************* - * Module functions - ******************************************************************************* - */ - -static int __init imx_udc_probe(struct platform_device *pdev) -{ - struct imx_udc_struct *imx_usb = &controller; - struct resource *res; - struct imxusb_platform_data *pdata; - struct clk *clk; - void __iomem *base; - int ret = 0; - int i; - resource_size_t res_size; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "can't get device resources\n"); - return -ENODEV; - } - - pdata = pdev->dev.platform_data; - if (!pdata) { - dev_err(&pdev->dev, "driver needs platform data\n"); - return -ENODEV; - } - - res_size = resource_size(res); - if (!request_mem_region(res->start, res_size, res->name)) { - dev_err(&pdev->dev, "can't allocate %d bytes at %d address\n", - res_size, res->start); - return -ENOMEM; - } - - if (pdata->init) { - ret = pdata->init(&pdev->dev); - if (ret) - goto fail0; - } - - base = ioremap(res->start, res_size); - if (!base) { - dev_err(&pdev->dev, "ioremap failed\n"); - ret = -EIO; - goto fail1; - } - - clk = clk_get(NULL, "usbd_clk"); - if (IS_ERR(clk)) { - ret = PTR_ERR(clk); - dev_err(&pdev->dev, "can't get USB clock\n"); - goto fail2; - } - clk_prepare_enable(clk); - - if (clk_get_rate(clk) != 48000000) { - D_INI(&pdev->dev, - "Bad USB clock (%d Hz), changing to 48000000 Hz\n", - (int)clk_get_rate(clk)); - if (clk_set_rate(clk, 48000000)) { - dev_err(&pdev->dev, - "Unable to set correct USB clock (48MHz)\n"); - ret = -EIO; - goto fail3; - } - } - - for (i = 0; i < IMX_USB_NB_EP + 1; i++) { - imx_usb->usbd_int[i] = platform_get_irq(pdev, i); - if (imx_usb->usbd_int[i] < 0) { - dev_err(&pdev->dev, "can't get irq number\n"); - ret = -ENODEV; - goto fail3; - } - } - - for (i = 0; i < IMX_USB_NB_EP + 1; i++) { - ret = request_irq(imx_usb->usbd_int[i], intr_handler(i), - 0, driver_name, imx_usb); - if (ret) { - dev_err(&pdev->dev, "can't get irq %i, err %d\n", - imx_usb->usbd_int[i], ret); - for (--i; i >= 0; i--) - free_irq(imx_usb->usbd_int[i], imx_usb); - goto fail3; - } - } - - imx_usb->res = res; - imx_usb->base = base; - imx_usb->clk = clk; - imx_usb->dev = &pdev->dev; - - platform_set_drvdata(pdev, imx_usb); - - 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; - - ret = usb_add_gadget_udc(&pdev->dev, &imx_usb->gadget); - if (ret) - goto fail4; - - return 0; -fail4: - for (i = 0; i < IMX_USB_NB_EP + 1; i++) - free_irq(imx_usb->usbd_int[i], imx_usb); -fail3: - clk_put(clk); - clk_disable_unprepare(clk); -fail2: - iounmap(base); -fail1: - if (pdata->exit) - pdata->exit(&pdev->dev); -fail0: - release_mem_region(res->start, res_size); - return ret; -} - -static int __exit imx_udc_remove(struct platform_device *pdev) -{ - struct imx_udc_struct *imx_usb = platform_get_drvdata(pdev); - struct imxusb_platform_data *pdata = pdev->dev.platform_data; - int i; - - usb_del_gadget_udc(&imx_usb->gadget); - 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); - - clk_put(imx_usb->clk); - clk_disable_unprepare(imx_usb->clk); - iounmap(imx_usb->base); - - release_mem_region(imx_usb->res->start, resource_size(imx_usb->res)); - - if (pdata->exit) - pdata->exit(&pdev->dev); - - return 0; -} - -/*----------------------------------------------------------------------------*/ - -#ifdef CONFIG_PM -#define imx_udc_suspend NULL -#define imx_udc_resume NULL -#else -#define imx_udc_suspend NULL -#define imx_udc_resume NULL -#endif - -/*----------------------------------------------------------------------------*/ - -static struct platform_driver udc_driver = { - .driver = { - .name = driver_name, - .owner = THIS_MODULE, - }, - .remove = __exit_p(imx_udc_remove), - .suspend = imx_udc_suspend, - .resume = imx_udc_resume, -}; - -module_platform_driver_probe(udc_driver, imx_udc_probe); - -MODULE_DESCRIPTION("IMX USB Device Controller driver"); -MODULE_AUTHOR("Darius Augulis "); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:imx_udc"); diff --git a/drivers/usb/gadget/imx_udc.h b/drivers/usb/gadget/imx_udc.h deleted file mode 100644 index d118fb777840..000000000000 --- a/drivers/usb/gadget/imx_udc.h +++ /dev/null @@ -1,351 +0,0 @@ -/* - * Copyright (C) 2005 Mike Lee(eemike@gmail.com) - * - * This udc driver is now under testing and code is based on pxa2xx_udc.h - * Please use it with your own risk! - * - * 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 __LINUX_USB_GADGET_IMX_H -#define __LINUX_USB_GADGET_IMX_H - -#include - -/* 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 IMX_USB_NB_EP 6 - -/* Driver structures */ -struct imx_request { - struct usb_request req; - struct list_head queue; - unsigned int in_use; -}; - -enum ep0_state { - EP0_IDLE, - EP0_IN_DATA_PHASE, - EP0_OUT_DATA_PHASE, - EP0_CONFIG, - EP0_STALL, -}; - -struct imx_ep_struct { - struct usb_ep ep; - struct imx_udc_struct *imx_usb; - struct list_head queue; - unsigned char stopped; - unsigned char fifosize; - unsigned char bEndpointAddress; - unsigned char bmAttributes; -}; - -struct imx_udc_struct { - struct usb_gadget gadget; - struct usb_gadget_driver *driver; - 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; - unsigned char set_config; - int cfg, - intf, - alt, - usbd_int[7]; -}; - -/* USB registers */ -#define USB_FRAME (0x00) /* USB frame */ -#define USB_SPEC (0x04) /* USB Spec */ -#define USB_STAT (0x08) /* USB Status */ -#define USB_CTRL (0x0C) /* USB Control */ -#define USB_DADR (0x10) /* USB Desc RAM addr */ -#define USB_DDAT (0x14) /* USB Desc RAM/EP buffer data */ -#define USB_INTR (0x18) /* USB interrupt */ -#define USB_MASK (0x1C) /* USB Mask */ -#define USB_ENAB (0x24) /* USB Enable */ -#define USB_EP_STAT(x) (0x30 + (x*0x30)) /* USB status/control */ -#define USB_EP_INTR(x) (0x34 + (x*0x30)) /* USB interrupt */ -#define USB_EP_MASK(x) (0x38 + (x*0x30)) /* USB mask */ -#define USB_EP_FDAT(x) (0x3C + (x*0x30)) /* USB FIFO data */ -#define USB_EP_FDAT0(x) (0x3C + (x*0x30)) /* USB FIFO data */ -#define USB_EP_FDAT1(x) (0x3D + (x*0x30)) /* USB FIFO data */ -#define USB_EP_FDAT2(x) (0x3E + (x*0x30)) /* USB FIFO data */ -#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 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 */ -/* USB Control Register Bit Fields.*/ -#define CTRL_CMDOVER (1<<6) /* UDC status */ -#define CTRL_CMDERROR (1<<5) /* UDC status */ -#define CTRL_FE_ENA (1<<3) /* Enable Font End logic */ -#define CTRL_UDC_RST (1<<2) /* UDC reset */ -#define CTRL_AFE_ENA (1<<1) /* Analog Font end enable */ -#define CTRL_RESUME (1<<0) /* UDC resume */ -/* USB Status Register Bit Fields.*/ -#define STAT_RST (1<<8) -#define STAT_SUSP (1<<7) -#define STAT_CFG (3<<5) -#define STAT_INTF (3<<3) -#define STAT_ALTSET (7<<0) -/* USB Interrupt Status/Mask Registers Bit fields */ -#define INTR_WAKEUP (1<<31) /* Wake up Interrupt */ -#define INTR_MSOF (1<<7) /* Missed Start of Frame */ -#define INTR_SOF (1<<6) /* Start of Frame */ -#define INTR_RESET_STOP (1<<5) /* Reset Signaling stop */ -#define INTR_RESET_START (1<<4) /* Reset Signaling start */ -#define INTR_RESUME (1<<3) /* Suspend to resume */ -#define INTR_SUSPEND (1<<2) /* Active to suspend */ -#define INTR_FRAME_MATCH (1<<1) /* Frame matched */ -#define INTR_CFG_CHG (1<<0) /* Configuration change occurred */ -/* USB Enable Register Bit Fields.*/ -#define ENAB_RST (1<<31) /* Reset USB modules */ -#define ENAB_ENAB (1<<30) /* Enable USB modules*/ -#define ENAB_SUSPEND (1<<29) /* Suspend USB modules */ -#define ENAB_ENDIAN (1<<28) /* Endian of USB modules */ -#define ENAB_PWRMD (1<<0) /* Power mode of USB modules */ -/* USB Descriptor Ram Address Register bit fields */ -#define DADR_CFG (1<<31) /* Configuration */ -#define DADR_BSY (1<<30) /* Busy status */ -#define DADR_DADR (0x1FF) /* Descriptor Ram Address */ -/* USB Descriptor RAM/Endpoint Buffer Data Register bit fields */ -#define DDAT_DDAT (0xFF) /* Descriptor Endpoint Buffer */ -/* USB Endpoint Status Register bit fields */ -#define EPSTAT_BCOUNT (0x7F<<16) /* Endpoint FIFO byte count */ -#define EPSTAT_SIP (1<<8) /* Endpoint setup in progress */ -#define EPSTAT_DIR (1<<7) /* Endpoint transfer direction */ -#define EPSTAT_MAX (3<<5) /* Endpoint Max packet size */ -#define EPSTAT_TYP (3<<3) /* Endpoint type */ -#define EPSTAT_ZLPS (1<<2) /* Send zero length packet */ -#define EPSTAT_FLUSH (1<<1) /* Endpoint FIFO Flush */ -#define EPSTAT_STALL (1<<0) /* Force stall */ -/* USB Endpoint FIFO Status Register bit fields */ -#define FSTAT_FRAME_STAT (0xF<<24) /* Frame status bit [0-3] */ -#define FSTAT_ERR (1<<22) /* FIFO error */ -#define FSTAT_UF (1<<21) /* FIFO underflow */ -#define FSTAT_OF (1<<20) /* FIFO overflow */ -#define FSTAT_FR (1<<19) /* FIFO frame ready */ -#define FSTAT_FULL (1<<18) /* FIFO full */ -#define FSTAT_ALRM (1<<17) /* FIFO alarm */ -#define FSTAT_EMPTY (1<<16) /* FIFO empty */ -/* USB Endpoint FIFO Control Register bit fields */ -#define FCTRL_WFR (1<<29) /* Write frame end */ -/* USB Endpoint Interrupt Status Regsiter bit fields */ -#define EPINTR_FIFO_FULL (1<<8) /* fifo full */ -#define EPINTR_FIFO_EMPTY (1<<7) /* fifo empty */ -#define EPINTR_FIFO_ERROR (1<<6) /* fifo error */ -#define EPINTR_FIFO_HIGH (1<<5) /* fifo high */ -#define EPINTR_FIFO_LOW (1<<4) /* fifo low */ -#define EPINTR_MDEVREQ (1<<3) /* multi Device request */ -#define EPINTR_EOT (1<<2) /* fifo end of transfer */ -#define EPINTR_DEVREQ (1<<1) /* Device request */ -#define EPINTR_EOF (1<<0) /* fifo end of frame */ - -/* Debug macros */ -#ifdef DEBUG - -/* #define DEBUG_REQ */ -/* #define DEBUG_TRX */ -/* #define DEBUG_INIT */ -/* #define DEBUG_EP0 */ -/* #define DEBUG_EPX */ -/* #define DEBUG_IRQ */ -/* #define DEBUG_EPIRQ */ -/* #define DEBUG_DUMP */ -/* #define DEBUG_ERR */ - -#ifdef DEBUG_REQ - #define D_REQ(dev, args...) dev_dbg(dev, ## args) -#else - #define D_REQ(dev, args...) do {} while (0) -#endif /* DEBUG_REQ */ - -#ifdef DEBUG_TRX - #define D_TRX(dev, args...) dev_dbg(dev, ## args) -#else - #define D_TRX(dev, args...) do {} while (0) -#endif /* DEBUG_TRX */ - -#ifdef DEBUG_INIT - #define D_INI(dev, args...) dev_dbg(dev, ## args) -#else - #define D_INI(dev, args...) do {} while (0) -#endif /* DEBUG_INIT */ - -#ifdef DEBUG_EP0 - static const char *state_name[] = { - "EP0_IDLE", - "EP0_IN_DATA_PHASE", - "EP0_OUT_DATA_PHASE", - "EP0_CONFIG", - "EP0_STALL" - }; - #define D_EP0(dev, args...) dev_dbg(dev, ## args) -#else - #define D_EP0(dev, args...) do {} while (0) -#endif /* DEBUG_EP0 */ - -#ifdef DEBUG_EPX - #define D_EPX(dev, args...) dev_dbg(dev, ## args) -#else - #define D_EPX(dev, args...) do {} while (0) -#endif /* DEBUG_EP0 */ - -#ifdef DEBUG_IRQ - static void dump_intr(const char *label, int irqreg, struct device *dev) - { - dev_dbg(dev, "<%s> USB_INTR=[%s%s%s%s%s%s%s%s%s]\n", label, - (irqreg & INTR_WAKEUP) ? " wake" : "", - (irqreg & INTR_MSOF) ? " msof" : "", - (irqreg & INTR_SOF) ? " sof" : "", - (irqreg & INTR_RESUME) ? " resume" : "", - (irqreg & INTR_SUSPEND) ? " suspend" : "", - (irqreg & INTR_RESET_STOP) ? " noreset" : "", - (irqreg & INTR_RESET_START) ? " reset" : "", - (irqreg & INTR_FRAME_MATCH) ? " fmatch" : "", - (irqreg & INTR_CFG_CHG) ? " config" : ""); - } -#else - #define dump_intr(x, y, z) do {} while (0) -#endif /* DEBUG_IRQ */ - -#ifdef DEBUG_EPIRQ - 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" : "", - (irqreg & EPINTR_FIFO_EMPTY) ? " fempty" : "", - (irqreg & EPINTR_FIFO_ERROR) ? " ferr" : "", - (irqreg & EPINTR_FIFO_HIGH) ? " fhigh" : "", - (irqreg & EPINTR_FIFO_LOW) ? " flow" : "", - (irqreg & EPINTR_MDEVREQ) ? " mreq" : "", - (irqreg & EPINTR_EOF) ? " eof" : "", - (irqreg & EPINTR_DEVREQ) ? " devreq" : "", - (irqreg & EPINTR_EOT) ? " eot" : ""); - } -#else - #define dump_ep_intr(x, y, z, i) do {} while (0) -#endif /* DEBUG_IRQ */ - -#ifdef DEBUG_DUMP - static void dump_usb_stat(const char *label, - struct imx_udc_struct *imx_usb) - { - int temp = __raw_readl(imx_usb->base + USB_STAT); - - dev_dbg(imx_usb->dev, - "<%s> USB_STAT=[%s%s CFG=%d, INTF=%d, ALTR=%d]\n", label, - (temp & STAT_RST) ? " reset" : "", - (temp & STAT_SUSP) ? " suspend" : "", - (temp & STAT_CFG) >> 5, - (temp & STAT_INTF) >> 3, - (temp & STAT_ALTSET)); - } - - 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))); - - 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), - (temp & EPINTR_FIFO_FULL) ? " full" : "", - (temp & EPINTR_FIFO_EMPTY) ? " fempty" : "", - (temp & EPINTR_FIFO_ERROR) ? " ferr" : "", - (temp & EPINTR_FIFO_HIGH) ? " fhigh" : "", - (temp & EPINTR_FIFO_LOW) ? " flow" : "", - (temp & EPINTR_MDEVREQ) ? " mreq" : "", - (temp & EPINTR_EOF) ? " eof" : "", - (temp & EPINTR_DEVREQ) ? " devreq" : "", - (temp & EPINTR_EOT) ? " eot" : ""); - - 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), - (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))); - - dev_dbg(imx_ep->imx_usb->dev, - "<%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" : "", - (temp & FSTAT_FR) ? " fready" : "", - (temp & FSTAT_FULL) ? " ffull" : "", - (temp & FSTAT_ALRM) ? " falarm" : "", - (temp & FSTAT_EMPTY) ? " fempty" : ""); - } - - 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); - return; - } - - 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); - for (i = 0; i < req->length; i++) - printk("%02x-", *((u8 *)req->buf + i)); - printk(">\n"); - } - } - -#else - #define dump_ep_stat(x, y) do {} while (0) - #define dump_usb_stat(x, y) do {} while (0) - #define dump_req(x, y, z) do {} while (0) -#endif /* DEBUG_DUMP */ - -#ifdef DEBUG_ERR - #define D_ERR(dev, args...) dev_dbg(dev, ## args) -#else - #define D_ERR(dev, args...) do {} while (0) -#endif - -#else - #define D_REQ(dev, args...) do {} while (0) - #define D_TRX(dev, args...) do {} while (0) - #define D_INI(dev, args...) do {} while (0) - #define D_EP0(dev, args...) do {} while (0) - #define D_EPX(dev, args...) do {} while (0) - #define dump_ep_intr(x, y, z, i) do {} while (0) - #define dump_intr(x, y, z) do {} while (0) - #define dump_ep_stat(x, y) do {} while (0) - #define dump_usb_stat(x, y) do {} while (0) - #define dump_req(x, y, z) do {} while (0) - #define D_ERR(dev, args...) do {} while (0) -#endif /* DEBUG */ - -#endif /* __LINUX_USB_GADGET_IMX_H */ From b0d7ffd44ba9cd2dfbf299674418193a5f9ed21a Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 27 Jun 2013 10:00:18 +0300 Subject: [PATCH 0944/3400] usb: dwc3: gadget: don't request IRQs in atomic We cannot request an IRQ with spinlocks held as that would trigger a sleeping inside spinlock warning. Cc: # v3.10 Reported-by: Stephen Boyd Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index f77083fedc68..14d28d6184f6 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1508,6 +1508,15 @@ static int dwc3_gadget_start(struct usb_gadget *g, int irq; u32 reg; + irq = platform_get_irq(to_platform_device(dwc->dev), 0); + ret = request_threaded_irq(irq, dwc3_interrupt, dwc3_thread_interrupt, + IRQF_SHARED | IRQF_ONESHOT, "dwc3", dwc); + if (ret) { + dev_err(dwc->dev, "failed to request irq #%d --> %d\n", + irq, ret); + goto err0; + } + spin_lock_irqsave(&dwc->lock, flags); if (dwc->gadget_driver) { @@ -1515,7 +1524,7 @@ static int dwc3_gadget_start(struct usb_gadget *g, dwc->gadget.name, dwc->gadget_driver->driver.name); ret = -EBUSY; - goto err0; + goto err1; } dwc->gadget_driver = driver; @@ -1551,42 +1560,38 @@ static int dwc3_gadget_start(struct usb_gadget *g, ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false); if (ret) { dev_err(dwc->dev, "failed to enable %s\n", dep->name); - goto err0; + goto err2; } dep = dwc->eps[1]; ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false); if (ret) { dev_err(dwc->dev, "failed to enable %s\n", dep->name); - goto err1; + goto err3; } /* begin to receive SETUP packets */ dwc->ep0state = EP0_SETUP_PHASE; dwc3_ep0_out_start(dwc); - irq = platform_get_irq(to_platform_device(dwc->dev), 0); - ret = request_threaded_irq(irq, dwc3_interrupt, dwc3_thread_interrupt, - IRQF_SHARED | IRQF_ONESHOT, "dwc3", dwc); - if (ret) { - dev_err(dwc->dev, "failed to request irq #%d --> %d\n", - irq, ret); - goto err1; - } - dwc3_gadget_enable_irq(dwc); spin_unlock_irqrestore(&dwc->lock, flags); return 0; -err1: +err3: __dwc3_gadget_ep_disable(dwc->eps[0]); -err0: +err2: dwc->gadget_driver = NULL; + +err1: spin_unlock_irqrestore(&dwc->lock, flags); + free_irq(irq, dwc); + +err0: return ret; } @@ -1600,9 +1605,6 @@ static int dwc3_gadget_stop(struct usb_gadget *g, spin_lock_irqsave(&dwc->lock, flags); dwc3_gadget_disable_irq(dwc); - irq = platform_get_irq(to_platform_device(dwc->dev), 0); - free_irq(irq, dwc); - __dwc3_gadget_ep_disable(dwc->eps[0]); __dwc3_gadget_ep_disable(dwc->eps[1]); @@ -1610,6 +1612,9 @@ static int dwc3_gadget_stop(struct usb_gadget *g, spin_unlock_irqrestore(&dwc->lock, flags); + irq = platform_get_irq(to_platform_device(dwc->dev), 0); + free_irq(irq, dwc); + return 0; } From 7bc5a6ba369217e0137833f5955cf0b0f08b0712 Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Thu, 27 Jun 2013 01:08:10 +0800 Subject: [PATCH 0945/3400] usb: dwc3: clean up redundant parameter comment @list is not as a parameter of dwc3_event_buffer, so remove it in comments. Signed-off-by: Huang Rui Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 27dad993b007..00a72e37397d 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -367,7 +367,6 @@ struct dwc3_trb; /** * struct dwc3_event_buffer - Software event buffer representation - * @list: a list of event buffers * @buf: _THE_ buffer * @length: size of this buffer * @lpos: event offset From 5945f789c864d8676b297880cc6961fea4511a7a Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Sun, 30 Jun 2013 14:15:11 +0300 Subject: [PATCH 0946/3400] usb: dwc3: switch to GPL v2 only This is a Linux-only driver which makes use of GPL-only symbols. It makes no sense to maintain Dual BSD/GPL licensing for this driver. Considering that the amount of work to use this driver in any different operating system would likely be as large as developing the driver from scratch and considering that we depend on GPL-only symbols, we will switch over to a GPL v2-only license. Cc: Anton Tikhomirov Acked-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 37 +++++++++------------------------- drivers/usb/dwc3/core.h | 34 +++++++------------------------ drivers/usb/dwc3/debug.h | 34 +++++++------------------------ drivers/usb/dwc3/debugfs.c | 34 +++++++------------------------ drivers/usb/dwc3/dwc3-exynos.c | 14 ++++++++----- drivers/usb/dwc3/dwc3-omap.c | 36 ++++++++------------------------- drivers/usb/dwc3/dwc3-pci.c | 36 ++++++++------------------------- drivers/usb/dwc3/ep0.c | 34 +++++++------------------------ drivers/usb/dwc3/gadget.c | 34 +++++++------------------------ drivers/usb/dwc3/gadget.h | 34 +++++++------------------------ drivers/usb/dwc3/host.c | 34 +++++++------------------------ drivers/usb/dwc3/io.h | 34 +++++++------------------------ 12 files changed, 91 insertions(+), 304 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 358375e0b291..f69e45a50039 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -6,34 +6,17 @@ * Authors: Felipe Balbi , * Sebastian Andrzej Siewior * - * 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 the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The names of the above-listed copyright holders may not be used - * to endorse or promote products derived from this software without - * specific prior written permission. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 of + * the License as published by the Free Software Foundation. * - * 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. + * 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. * - * 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. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ #include @@ -775,5 +758,5 @@ module_platform_driver(dwc3_driver); MODULE_ALIAS("platform:dwc3"); MODULE_AUTHOR("Felipe Balbi "); -MODULE_LICENSE("Dual BSD/GPL"); +MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver"); diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 00a72e37397d..22ada27ad3ff 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -6,34 +6,14 @@ * Authors: Felipe Balbi , * Sebastian Andrzej Siewior * - * 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 the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The names of the above-listed copyright holders may not be used - * to endorse or promote products derived from this software without - * specific prior written permission. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 of + * the License as published by the Free Software Foundation. * - * 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. - * - * 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. + * 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. */ #ifndef __DRIVERS_USB_DWC3_CORE_H diff --git a/drivers/usb/dwc3/debug.h b/drivers/usb/dwc3/debug.h index 5894ee8222af..fceb39dc4bba 100644 --- a/drivers/usb/dwc3/debug.h +++ b/drivers/usb/dwc3/debug.h @@ -6,34 +6,14 @@ * Authors: Felipe Balbi , * Sebastian Andrzej Siewior * - * 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 the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The names of the above-listed copyright holders may not be used - * to endorse or promote products derived from this software without - * specific prior written permission. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 of + * the License as published by the Free Software Foundation. * - * 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. - * - * 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. + * 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. */ #include "core.h" diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index 9e9f122162f2..9ac37fe1b6a7 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c @@ -6,34 +6,14 @@ * Authors: Felipe Balbi , * Sebastian Andrzej Siewior * - * 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 the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The names of the above-listed copyright holders may not be used - * to endorse or promote products derived from this software without - * specific prior written permission. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 of + * the License as published by the Free Software Foundation. * - * 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. - * - * 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. + * 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. */ #include diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c index 8ce9d7fd6cfc..9a8a5e1f394f 100644 --- a/drivers/usb/dwc3/dwc3-exynos.c +++ b/drivers/usb/dwc3/dwc3-exynos.c @@ -6,10 +6,14 @@ * * Author: Anton Tikhomirov * - * 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 version 2 of + * the 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. */ #include @@ -228,5 +232,5 @@ module_platform_driver(dwc3_exynos_driver); MODULE_ALIAS("platform:exynos-dwc3"); MODULE_AUTHOR("Anton Tikhomirov "); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("DesignWare USB3 EXYNOS Glue Layer"); diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 077f110bd746..cf209086f3e8 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -6,34 +6,14 @@ * Authors: Felipe Balbi , * Sebastian Andrzej Siewior * - * 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 the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The names of the above-listed copyright holders may not be used - * to endorse or promote products derived from this software without - * specific prior written permission. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 of + * the License as published by the Free Software Foundation. * - * 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. - * - * 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. + * 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. */ #include @@ -610,5 +590,5 @@ module_platform_driver(dwc3_omap_driver); MODULE_ALIAS("platform:omap-dwc3"); MODULE_AUTHOR("Felipe Balbi "); -MODULE_LICENSE("Dual BSD/GPL"); +MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("DesignWare USB3 OMAP Glue Layer"); diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index ed07ec04a962..5d746e5d6a0a 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c @@ -6,34 +6,14 @@ * Authors: Felipe Balbi , * Sebastian Andrzej Siewior * - * 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 the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The names of the above-listed copyright holders may not be used - * to endorse or promote products derived from this software without - * specific prior written permission. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 of + * the License as published by the Free Software Foundation. * - * 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. - * - * 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. + * 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. */ #include @@ -257,7 +237,7 @@ static struct pci_driver dwc3_pci_driver = { }; MODULE_AUTHOR("Felipe Balbi "); -MODULE_LICENSE("Dual BSD/GPL"); +MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("DesignWare USB3 PCI Glue Layer"); module_pci_driver(dwc3_pci_driver); diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 5acbb948b704..e9d099cee636 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -6,34 +6,14 @@ * Authors: Felipe Balbi , * Sebastian Andrzej Siewior * - * 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 the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The names of the above-listed copyright holders may not be used - * to endorse or promote products derived from this software without - * specific prior written permission. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 of + * the License as published by the Free Software Foundation. * - * 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. - * - * 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. + * 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. */ #include diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 14d28d6184f6..033419be26d4 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -6,34 +6,14 @@ * Authors: Felipe Balbi , * Sebastian Andrzej Siewior * - * 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 the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The names of the above-listed copyright holders may not be used - * to endorse or promote products derived from this software without - * specific prior written permission. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 of + * the License as published by the Free Software Foundation. * - * 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. - * - * 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. + * 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. */ #include diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h index 99e6d7248820..febe1aa7b714 100644 --- a/drivers/usb/dwc3/gadget.h +++ b/drivers/usb/dwc3/gadget.h @@ -6,34 +6,14 @@ * Authors: Felipe Balbi , * Sebastian Andrzej Siewior * - * 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 the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The names of the above-listed copyright holders may not be used - * to endorse or promote products derived from this software without - * specific prior written permission. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 of + * the License as published by the Free Software Foundation. * - * 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. - * - * 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. + * 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. */ #ifndef __DRIVERS_USB_DWC3_GADGET_H diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c index 0fa1846eda4c..32db328cc769 100644 --- a/drivers/usb/dwc3/host.c +++ b/drivers/usb/dwc3/host.c @@ -5,34 +5,14 @@ * * Authors: Felipe Balbi , * - * 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 the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The names of the above-listed copyright holders may not be used - * to endorse or promote products derived from this software without - * specific prior written permission. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 of + * the License as published by the Free Software Foundation. * - * 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. - * - * 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. + * 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. */ #include diff --git a/drivers/usb/dwc3/io.h b/drivers/usb/dwc3/io.h index a50f76b9d19b..d94441c14d8c 100644 --- a/drivers/usb/dwc3/io.h +++ b/drivers/usb/dwc3/io.h @@ -6,34 +6,14 @@ * Authors: Felipe Balbi , * Sebastian Andrzej Siewior * - * 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 the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The names of the above-listed copyright holders may not be used - * to endorse or promote products derived from this software without - * specific prior written permission. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 of + * the License as published by the Free Software Foundation. * - * 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. - * - * 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. + * 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. */ #ifndef __DRIVERS_USB_DWC3_IO_H From 410aee70f06da60dd8f78c3ec3346cc74c9bed46 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Sun, 30 Jun 2013 15:27:26 +0300 Subject: [PATCH 0947/3400] usb: phy: protect against NULL phy pointers In order to decrease the amount of work done by PHY users, allow NULL phy pointers to be passed. Signed-off-by: Felipe Balbi --- include/linux/usb/phy.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/include/linux/usb/phy.h b/include/linux/usb/phy.h index 44036808bf0f..6c0b1c513db7 100644 --- a/include/linux/usb/phy.h +++ b/include/linux/usb/phy.h @@ -142,7 +142,7 @@ extern void usb_remove_phy(struct usb_phy *); /* helpers for direct access thru low-level io interface */ static inline int usb_phy_io_read(struct usb_phy *x, u32 reg) { - if (x->io_ops && x->io_ops->read) + if (x && x->io_ops && x->io_ops->read) return x->io_ops->read(x, reg); return -EINVAL; @@ -150,7 +150,7 @@ static inline int usb_phy_io_read(struct usb_phy *x, u32 reg) static inline int usb_phy_io_write(struct usb_phy *x, u32 val, u32 reg) { - if (x->io_ops && x->io_ops->write) + if (x && x->io_ops && x->io_ops->write) return x->io_ops->write(x, val, reg); return -EINVAL; @@ -159,7 +159,7 @@ static inline int usb_phy_io_write(struct usb_phy *x, u32 val, u32 reg) static inline int usb_phy_init(struct usb_phy *x) { - if (x->init) + if (x && x->init) return x->init(x); return 0; @@ -168,14 +168,14 @@ usb_phy_init(struct usb_phy *x) static inline void usb_phy_shutdown(struct usb_phy *x) { - if (x->shutdown) + if (x && x->shutdown) x->shutdown(x); } static inline int usb_phy_vbus_on(struct usb_phy *x) { - if (!x->set_vbus) + if (!x || !x->set_vbus) return 0; return x->set_vbus(x, true); @@ -184,7 +184,7 @@ usb_phy_vbus_on(struct usb_phy *x) static inline int usb_phy_vbus_off(struct usb_phy *x) { - if (!x->set_vbus) + if (!x || !x->set_vbus) return 0; return x->set_vbus(x, false); @@ -258,7 +258,7 @@ usb_phy_set_power(struct usb_phy *x, unsigned mA) static inline int usb_phy_set_suspend(struct usb_phy *x, int suspend) { - if (x->set_suspend != NULL) + if (x && x->set_suspend != NULL) return x->set_suspend(x, suspend); else return 0; @@ -267,7 +267,7 @@ usb_phy_set_suspend(struct usb_phy *x, int suspend) static inline int usb_phy_notify_connect(struct usb_phy *x, enum usb_device_speed speed) { - if (x->notify_connect) + if (x && x->notify_connect) return x->notify_connect(x, speed); else return 0; @@ -276,7 +276,7 @@ usb_phy_notify_connect(struct usb_phy *x, enum usb_device_speed speed) static inline int usb_phy_notify_disconnect(struct usb_phy *x, enum usb_device_speed speed) { - if (x->notify_disconnect) + if (x && x->notify_disconnect) return x->notify_disconnect(x, speed); else return 0; From 1494a1f62bf7cf57345e9282c8189fe2a21fab64 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Sun, 30 Jun 2013 13:56:45 +0300 Subject: [PATCH 0948/3400] usb: common: introduce of_usb_get_maximum_speed() this helper will be used for controllers which want to work at a lower speed even though they support higher USB transfer rates. One such case is Texas Instruments' AM437x SoC where it uses a USB3 controller without a USB3 PHY, rendering the controller USB2-only. Signed-off-by: Felipe Balbi --- .../devicetree/bindings/usb/generic.txt | 24 +++++++++ drivers/usb/usb-common.c | 49 ++++++++++++++----- include/linux/usb/of.h | 8 +++ 3 files changed, 70 insertions(+), 11 deletions(-) create mode 100644 Documentation/devicetree/bindings/usb/generic.txt diff --git a/Documentation/devicetree/bindings/usb/generic.txt b/Documentation/devicetree/bindings/usb/generic.txt new file mode 100644 index 000000000000..477d5bb5e51c --- /dev/null +++ b/Documentation/devicetree/bindings/usb/generic.txt @@ -0,0 +1,24 @@ +Generic USB Properties + +Optional properties: + - maximum-speed: tells USB controllers we want to work up to a certain + speed. Valid arguments are "super-speed", "high-speed", + "full-speed" and "low-speed". In case this isn't passed + via DT, USB controllers should default to their maximum + HW capability. + - dr_mode: tells Dual-Role USB controllers that we want to work on a + particular mode. Valid arguments are "host", + "peripheral" and "otg". In case this attribute isn't + passed via DT, USB DRD controllers should default to + OTG. + +This is an attribute to a USB controller such as: + +dwc3@4a030000 { + compatible = "synopsys,dwc3"; + reg = <0x4a030000 0xcfff>; + interrupts = <0 92 4> + usb-phy = <&usb2_phy>, <&usb3,phy>; + maximum-speed = "super-speed"; + dr_mode = "otg"; +}; diff --git a/drivers/usb/usb-common.c b/drivers/usb/usb-common.c index 675384dabfe9..d771870a819e 100644 --- a/drivers/usb/usb-common.c +++ b/drivers/usb/usb-common.c @@ -43,20 +43,20 @@ const char *usb_otg_state_string(enum usb_otg_state state) } EXPORT_SYMBOL_GPL(usb_otg_state_string); +static const char *const speed_names[] = { + [USB_SPEED_UNKNOWN] = "UNKNOWN", + [USB_SPEED_LOW] = "low-speed", + [USB_SPEED_FULL] = "full-speed", + [USB_SPEED_HIGH] = "high-speed", + [USB_SPEED_WIRELESS] = "wireless", + [USB_SPEED_SUPER] = "super-speed", +}; + const char *usb_speed_string(enum usb_device_speed speed) { - static const char *const names[] = { - [USB_SPEED_UNKNOWN] = "UNKNOWN", - [USB_SPEED_LOW] = "low-speed", - [USB_SPEED_FULL] = "full-speed", - [USB_SPEED_HIGH] = "high-speed", - [USB_SPEED_WIRELESS] = "wireless", - [USB_SPEED_SUPER] = "super-speed", - }; - - if (speed < 0 || speed >= ARRAY_SIZE(names)) + if (speed < 0 || speed >= ARRAY_SIZE(speed_names)) speed = USB_SPEED_UNKNOWN; - return names[speed]; + return speed_names[speed]; } EXPORT_SYMBOL_GPL(usb_speed_string); @@ -112,6 +112,33 @@ enum usb_dr_mode of_usb_get_dr_mode(struct device_node *np) return USB_DR_MODE_UNKNOWN; } EXPORT_SYMBOL_GPL(of_usb_get_dr_mode); + +/** + * of_usb_get_maximum_speed - Get maximum requested speed for a given USB + * controller. + * @np: Pointer to the given device_node + * + * The function gets the maximum speed string from property "maximum-speed", + * and returns the corresponding enum usb_device_speed. + */ +enum usb_device_speed of_usb_get_maximum_speed(struct device_node *np) +{ + const char *maximum_speed; + int err; + int i; + + err = of_property_read_string(np, "maximum-speed", &maximum_speed); + if (err < 0) + return USB_SPEED_UNKNOWN; + + for (i = 0; i < ARRAY_SIZE(speed_names); i++) + if (strcmp(maximum_speed, speed_names[i]) == 0) + return i; + + return USB_SPEED_UNKNOWN; +} +EXPORT_SYMBOL_GPL(of_usb_get_maximum_speed); + #endif MODULE_LICENSE("GPL"); diff --git a/include/linux/usb/of.h b/include/linux/usb/of.h index a0ef405368b8..5a7cb9ebf0ef 100644 --- a/include/linux/usb/of.h +++ b/include/linux/usb/of.h @@ -7,16 +7,24 @@ #ifndef __LINUX_USB_OF_H #define __LINUX_USB_OF_H +#include #include #include #if IS_ENABLED(CONFIG_OF) enum usb_dr_mode of_usb_get_dr_mode(struct device_node *np); +enum usb_device_speed of_usb_get_maximum_speed(struct device_node *np); #else static inline enum usb_dr_mode of_usb_get_dr_mode(struct device_node *np) { return USB_DR_MODE_UNKNOWN; } + +static inline enum usb_device_speed +of_usb_get_maximum_speed(struct device_node *np) +{ + return USB_SPEED_UNKNOWN; +} #endif #if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_USB_PHY) From 6462cbd54d2fa649b27633267d8ddf835705e47a Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Sun, 30 Jun 2013 14:19:33 +0300 Subject: [PATCH 0949/3400] usb: dwc3: let non-DT platforms pass tx-fifo-resize flag; in case we're not in a DT boot, we should still be able to tell the driver how to behave. In order to be able to pass flags to the driver, we introduce platform_data structure which the core driver should use. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 8 ++++++-- drivers/usb/dwc3/platform_data.h | 22 ++++++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 drivers/usb/dwc3/platform_data.h diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index f69e45a50039..cb1eb37c6d6c 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -37,6 +37,7 @@ #include #include +#include "platform_data.h" #include "core.h" #include "gadget.h" #include "io.h" @@ -350,6 +351,7 @@ static void dwc3_core_exit(struct dwc3 *dwc) static int dwc3_probe(struct platform_device *pdev) { + struct dwc3_platform_data *pdata = pdev->dev.platform_data; struct device_node *node = pdev->dev.of_node; struct resource *res; struct dwc3 *dwc; @@ -412,9 +414,13 @@ static int dwc3_probe(struct platform_device *pdev) if (node) { dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0); dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1); + + dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize"); } else { dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3); + + dwc->needs_fifo_resize = pdata->tx_fifo_resize; } if (IS_ERR(dwc->usb2_phy)) { @@ -472,8 +478,6 @@ static int dwc3_probe(struct platform_device *pdev) else dwc->maximum_speed = DWC3_DCFG_SUPERSPEED; - dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize"); - pm_runtime_enable(dev); pm_runtime_get_sync(dev); pm_runtime_forbid(dev); diff --git a/drivers/usb/dwc3/platform_data.h b/drivers/usb/dwc3/platform_data.h new file mode 100644 index 000000000000..038516489539 --- /dev/null +++ b/drivers/usb/dwc3/platform_data.h @@ -0,0 +1,22 @@ +/** + * platform_data.h - USB DWC3 Platform Data Support + * + * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com + * Author: 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 of + * the 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, see . + */ + +struct dwc3_platform_data { + bool tx_fifo_resize; +}; From f7e846f0956917888b28b52726ee8779a39d84b6 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Sun, 30 Jun 2013 14:29:51 +0300 Subject: [PATCH 0950/3400] usb: dwc3: make maximum-speed a per-instance attribute in order to allow different instances of the core work in different maximum speeds, we will move the maximum_speed module_parameter to both DeviceTree (making use the new maximum-speed DT property) and platform_data. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 24 +++++++++--------------- drivers/usb/dwc3/gadget.c | 21 ++++++++++++++++++--- drivers/usb/dwc3/platform_data.h | 3 +++ 3 files changed, 30 insertions(+), 18 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index cb1eb37c6d6c..0686acff1e22 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -36,6 +36,7 @@ #include #include #include +#include #include "platform_data.h" #include "core.h" @@ -44,10 +45,6 @@ #include "debug.h" -static char *maximum_speed = "super"; -module_param(maximum_speed, charp, 0); -MODULE_PARM_DESC(maximum_speed, "Maximum supported speed."); - /* -------------------------------------------------------------------------- */ void dwc3_set_mode(struct dwc3 *dwc, u32 mode) @@ -412,17 +409,25 @@ static int dwc3_probe(struct platform_device *pdev) } if (node) { + dwc->maximum_speed = of_usb_get_maximum_speed(node); + dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0); dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1); dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize"); } else { + dwc->maximum_speed = pdata->maximum_speed; + dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3); dwc->needs_fifo_resize = pdata->tx_fifo_resize; } + /* default to superspeed if no maximum_speed passed */ + if (dwc->maximum_speed == USB_SPEED_UNKNOWN) + dwc->maximum_speed = USB_SPEED_SUPER; + if (IS_ERR(dwc->usb2_phy)) { ret = PTR_ERR(dwc->usb2_phy); @@ -467,17 +472,6 @@ static int dwc3_probe(struct platform_device *pdev) dev->dma_parms = dev->parent->dma_parms; dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask); - if (!strncmp("super", maximum_speed, 5)) - dwc->maximum_speed = DWC3_DCFG_SUPERSPEED; - else if (!strncmp("high", maximum_speed, 4)) - dwc->maximum_speed = DWC3_DCFG_HIGHSPEED; - else if (!strncmp("full", maximum_speed, 4)) - dwc->maximum_speed = DWC3_DCFG_FULLSPEED1; - else if (!strncmp("low", maximum_speed, 3)) - dwc->maximum_speed = DWC3_DCFG_LOWSPEED; - else - dwc->maximum_speed = DWC3_DCFG_SUPERSPEED; - pm_runtime_enable(dev); pm_runtime_get_sync(dev); pm_runtime_forbid(dev); diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 033419be26d4..4ca5706f3a86 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1525,10 +1525,25 @@ static int dwc3_gadget_start(struct usb_gadget *g, * STAR#9000525659: Clock Domain Crossing on DCTL in * USB 2.0 Mode */ - if (dwc->revision < DWC3_REVISION_220A) + if (dwc->revision < DWC3_REVISION_220A) { reg |= DWC3_DCFG_SUPERSPEED; - else - reg |= dwc->maximum_speed; + } else { + switch (dwc->maximum_speed) { + case USB_SPEED_LOW: + reg |= DWC3_DSTS_LOWSPEED; + break; + case USB_SPEED_FULL: + reg |= DWC3_DSTS_FULLSPEED1; + break; + case USB_SPEED_HIGH: + reg |= DWC3_DSTS_HIGHSPEED; + break; + case USB_SPEED_SUPER: /* FALLTHROUGH */ + case USB_SPEED_UNKNOWN: /* FALTHROUGH */ + default: + reg |= DWC3_DSTS_SUPERSPEED; + } + } dwc3_writel(dwc->regs, DWC3_DCFG, reg); dwc->start_config_issued = false; diff --git a/drivers/usb/dwc3/platform_data.h b/drivers/usb/dwc3/platform_data.h index 038516489539..16ffe1912523 100644 --- a/drivers/usb/dwc3/platform_data.h +++ b/drivers/usb/dwc3/platform_data.h @@ -17,6 +17,9 @@ * along with this program. If not, see . */ +#include + struct dwc3_platform_data { + enum usb_device_speed maximum_speed; bool tx_fifo_resize; }; From 22a5aa170c5231e64e1598a55dee92ea9a26183e Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 2 Jul 2013 21:20:24 +0300 Subject: [PATCH 0951/3400] usb: dwc3: core: switch to snps,dwc3 all other drivers using Synopsys IPs with DT have a compatible of snps,$driver, in order to add consistency, we are switching over to snps,dwc3 but keeping synopsys,dwc3 in the core driver to maintain backwards compatibility. New DTS bindings should NOT use synopsys,dwc3. Signed-off-by: Felipe Balbi --- Documentation/devicetree/bindings/usb/dwc3.txt | 4 ++-- arch/arm/boot/dts/omap5.dtsi | 2 +- drivers/usb/dwc3/core.c | 3 +++ 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt index 7a95c651ceb3..3a64e20f6c32 100644 --- a/Documentation/devicetree/bindings/usb/dwc3.txt +++ b/Documentation/devicetree/bindings/usb/dwc3.txt @@ -3,7 +3,7 @@ synopsys DWC3 CORE DWC3- USB3 CONTROLLER Required properties: - - compatible: must be "synopsys,dwc3" + - compatible: must be "snps,dwc3" - reg : Address and length of the register set for the device - interrupts: Interrupts used by the dwc3 controller. - usb-phy : array of phandle for the PHY device @@ -14,7 +14,7 @@ Optional properties: This is usually a subnode to DWC3 glue to which it is connected. dwc3@4a030000 { - compatible = "synopsys,dwc3"; + compatible = "snps,dwc3"; reg = <0x4a030000 0xcfff>; interrupts = <0 92 4> usb-phy = <&usb2_phy>, <&usb3,phy>; diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi index e643620417a9..07be2cd7b318 100644 --- a/arch/arm/boot/dts/omap5.dtsi +++ b/arch/arm/boot/dts/omap5.dtsi @@ -644,7 +644,7 @@ utmi-mode = <2>; ranges; dwc3@4a030000 { - compatible = "synopsys,dwc3"; + compatible = "snps,dwc3"; reg = <0x4a030000 0x1000>; interrupts = ; usb-phy = <&usb2_phy>, <&usb3_phy>; diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 0686acff1e22..2f5632730ffb 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -734,6 +734,9 @@ static const struct dev_pm_ops dwc3_dev_pm_ops = { #ifdef CONFIG_OF static const struct of_device_id of_dwc3_match[] = { + { + .compatible = "snps,dwc3" + }, { .compatible = "synopsys,dwc3" }, From c50f056c360673ef196b49bfa161d841f0fbe92e Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Tue, 25 Jun 2013 17:38:23 +0200 Subject: [PATCH 0952/3400] usb: gadget: s3c-hsotg: Allow driver instantiation using device tree This patch adds OF match table to the driver to allow instantiating it using device tree. Signed-off-by: Tomasz Figa Signed-off-by: Kyungmin Park Signed-off-by: Felipe Balbi --- .../devicetree/bindings/usb/samsung-hsotg.txt | 40 +++++++++++++++++++ drivers/usb/gadget/s3c-hsotg.c | 10 +++++ 2 files changed, 50 insertions(+) create mode 100644 Documentation/devicetree/bindings/usb/samsung-hsotg.txt diff --git a/Documentation/devicetree/bindings/usb/samsung-hsotg.txt b/Documentation/devicetree/bindings/usb/samsung-hsotg.txt new file mode 100644 index 000000000000..b83d428a265e --- /dev/null +++ b/Documentation/devicetree/bindings/usb/samsung-hsotg.txt @@ -0,0 +1,40 @@ +Samsung High Speed USB OTG controller +----------------------------- + +The Samsung HSOTG IP can be found on Samsung SoCs, from S3C6400 onwards. +It gives functionality of OTG-compliant USB 2.0 host and device with +support for USB 2.0 high-speed (480Mbps) and full-speed (12 Mbps) +operation. + +Currently only device mode is supported. + +Binding details +----- + +Required properties: +- compatible: "samsung,s3c6400-hsotg" should be used for all currently + supported SoC, +- interrupt-parent: phandle for the interrupt controller to which the + interrupt signal of the HSOTG block is routed, +- interrupts: specifier of interrupt signal of interrupt controller, + according to bindings of interrupt controller, +- clocks: contains an array of clock specifiers: + - first entry: OTG clock +- clock-names: contains array of clock names: + - first entry: must be "otg" +- vusb_d-supply: phandle to voltage regulator of digital section, +- vusb_a-supply: phandle to voltage regulator of analog section. + +Example +----- + + hsotg@12480000 { + compatible = "samsung,s3c6400-hsotg"; + reg = <0x12480000 0x20000>; + interrupts = <0 71 0>; + clocks = <&clock 305>; + clock-names = "otg"; + vusb_d-supply = <&vusb_reg>; + vusb_a-supply = <&vusbdac_reg>; + }; + diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index af22f24046b2..616ed51f8585 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -3648,10 +3649,19 @@ static int s3c_hsotg_remove(struct platform_device *pdev) #define s3c_hsotg_resume NULL #endif +#ifdef CONFIG_OF +static const struct of_device_id s3c_hsotg_of_ids[] = { + { .compatible = "samsung,s3c6400-hsotg", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, s3c_hsotg_of_ids); +#endif + static struct platform_driver s3c_hsotg_driver = { .driver = { .name = "s3c-hsotg", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(s3c_hsotg_of_ids), }, .probe = s3c_hsotg_probe, .remove = s3c_hsotg_remove, From 24dc3538bcfb353741e653fab550c4bf0a8dc07d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 1 Jul 2013 21:34:58 -0700 Subject: [PATCH 0953/3400] usb: musb: get rid of unused proc_dir_entry The musb driver no longer uses procfs, so get rid of the proc_dir_entry variable in struct musb. Signed-off-by: Greg Kroah-Hartman Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_core.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 7d341c387eab..65f3917b4fc5 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -83,11 +83,6 @@ enum { MUSB_PORT_MODE_DUAL_ROLE, }; -#ifdef CONFIG_PROC_FS -#include -#define MUSB_CONFIG_PROC_FS -#endif - /****************************** CONSTANTS ********************************/ #ifndef MUSB_C_NUM_EPS @@ -425,9 +420,6 @@ struct musb { struct musb_hdrc_config *config; -#ifdef MUSB_CONFIG_PROC_FS - struct proc_dir_entry *proc_entry; -#endif int xceiv_old_state; #ifdef CONFIG_DEBUG_FS struct dentry *debugfs_root; From 51e563e3c11492748d11d3846b6d325426427a95 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Wed, 3 Jul 2013 16:34:13 -0300 Subject: [PATCH 0954/3400] usb: phy: phy-mxs-usb: Check the return value from stmp_reset_block() stmp_reset_block() may fail, so let's check its return value and propagate it in the case of error. Acked-by: Shawn Guo Signed-off-by: Fabio Estevam Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-mxs-usb.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c index bd601c537c8d..fdd33b44dbd3 100644 --- a/drivers/usb/phy/phy-mxs-usb.c +++ b/drivers/usb/phy/phy-mxs-usb.c @@ -41,11 +41,14 @@ struct mxs_phy { #define to_mxs_phy(p) container_of((p), struct mxs_phy, phy) -static void mxs_phy_hw_init(struct mxs_phy *mxs_phy) +static int mxs_phy_hw_init(struct mxs_phy *mxs_phy) { + int ret; void __iomem *base = mxs_phy->phy.io_priv; - stmp_reset_block(base + HW_USBPHY_CTRL); + ret = stmp_reset_block(base + HW_USBPHY_CTRL); + if (ret) + return ret; /* Power up the PHY */ writel(0, base + HW_USBPHY_PWD); @@ -54,6 +57,8 @@ static void mxs_phy_hw_init(struct mxs_phy *mxs_phy) writel(BM_USBPHY_CTRL_ENUTMILEVEL2 | BM_USBPHY_CTRL_ENUTMILEVEL3, base + HW_USBPHY_CTRL_SET); + + return 0; } static int mxs_phy_init(struct usb_phy *phy) @@ -61,9 +66,7 @@ static int mxs_phy_init(struct usb_phy *phy) struct mxs_phy *mxs_phy = to_mxs_phy(phy); clk_prepare_enable(mxs_phy->clk); - mxs_phy_hw_init(mxs_phy); - - return 0; + return mxs_phy_hw_init(mxs_phy); } static void mxs_phy_shutdown(struct usb_phy *phy) From a45c82b84c844cd85b2ed1aa32596f1bffa32716 Mon Sep 17 00:00:00 2001 From: Ruchika Kharwar Date: Sat, 6 Jul 2013 07:52:49 -0500 Subject: [PATCH 0955/3400] usb: dwc3: adapt to use dr_mode device tree helper This patch adapts the dwc3 to use the device tree helper "of_usb_get_dr_mode" for the mode of operation of the dwc3 instance being probed. [ balbi@ti.com : make of_usb_get_dr_mode() conditional on dev->of_node and let pdata pass dr_mode too ] Reviewed-by: Roger Quadros Signed-off-by: Ruchika Kharwar Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 73 ++++++++++++++++---------------- drivers/usb/dwc3/core.h | 11 ++--- drivers/usb/dwc3/platform_data.h | 2 + 3 files changed, 43 insertions(+), 43 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 2f5632730ffb..df3723a1023e 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -37,6 +37,7 @@ #include #include #include +#include #include "platform_data.h" #include "core.h" @@ -359,8 +360,6 @@ static int dwc3_probe(struct platform_device *pdev) void __iomem *regs; void *mem; - u8 mode; - mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL); if (!mem) { dev_err(dev, "not enough memory\n"); @@ -415,6 +414,7 @@ static int dwc3_probe(struct platform_device *pdev) dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1); dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize"); + dwc->dr_mode = of_usb_get_dr_mode(node); } else { dwc->maximum_speed = pdata->maximum_speed; @@ -422,6 +422,7 @@ static int dwc3_probe(struct platform_device *pdev) dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3); dwc->needs_fifo_resize = pdata->tx_fifo_resize; + dwc->dr_mode = pdata->dr_mode; } /* default to superspeed if no maximum_speed passed */ @@ -498,14 +499,15 @@ static int dwc3_probe(struct platform_device *pdev) } if (IS_ENABLED(CONFIG_USB_DWC3_HOST)) - mode = DWC3_MODE_HOST; + dwc->dr_mode = USB_DR_MODE_HOST; else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET)) - mode = DWC3_MODE_DEVICE; - else - mode = DWC3_MODE_DRD; + dwc->dr_mode = USB_DR_MODE_PERIPHERAL; - switch (mode) { - case DWC3_MODE_DEVICE: + if (dwc->dr_mode == USB_DR_MODE_UNKNOWN) + dwc->dr_mode = USB_DR_MODE_OTG; + + switch (dwc->dr_mode) { + case USB_DR_MODE_PERIPHERAL: dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); ret = dwc3_gadget_init(dwc); if (ret) { @@ -513,7 +515,7 @@ static int dwc3_probe(struct platform_device *pdev) goto err2; } break; - case DWC3_MODE_HOST: + case USB_DR_MODE_HOST: dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST); ret = dwc3_host_init(dwc); if (ret) { @@ -521,7 +523,7 @@ static int dwc3_probe(struct platform_device *pdev) goto err2; } break; - case DWC3_MODE_DRD: + case USB_DR_MODE_OTG: dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG); ret = dwc3_host_init(dwc); if (ret) { @@ -536,10 +538,9 @@ static int dwc3_probe(struct platform_device *pdev) } break; default: - dev_err(dev, "Unsupported mode of operation %d\n", mode); + dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode); goto err2; } - dwc->mode = mode; ret = dwc3_debugfs_init(dwc); if (ret) { @@ -552,14 +553,14 @@ static int dwc3_probe(struct platform_device *pdev) return 0; err3: - switch (mode) { - case DWC3_MODE_DEVICE: + switch (dwc->dr_mode) { + case USB_DR_MODE_PERIPHERAL: dwc3_gadget_exit(dwc); break; - case DWC3_MODE_HOST: + case USB_DR_MODE_HOST: dwc3_host_exit(dwc); break; - case DWC3_MODE_DRD: + case USB_DR_MODE_OTG: dwc3_host_exit(dwc); dwc3_gadget_exit(dwc); break; @@ -592,14 +593,14 @@ static int dwc3_remove(struct platform_device *pdev) dwc3_debugfs_exit(dwc); - switch (dwc->mode) { - case DWC3_MODE_DEVICE: + switch (dwc->dr_mode) { + case USB_DR_MODE_PERIPHERAL: dwc3_gadget_exit(dwc); break; - case DWC3_MODE_HOST: + case USB_DR_MODE_HOST: dwc3_host_exit(dwc); break; - case DWC3_MODE_DRD: + case USB_DR_MODE_OTG: dwc3_host_exit(dwc); dwc3_gadget_exit(dwc); break; @@ -623,12 +624,12 @@ static int dwc3_prepare(struct device *dev) spin_lock_irqsave(&dwc->lock, flags); - switch (dwc->mode) { - case DWC3_MODE_DEVICE: - case DWC3_MODE_DRD: + switch (dwc->dr_mode) { + case USB_DR_MODE_PERIPHERAL: + case USB_DR_MODE_OTG: dwc3_gadget_prepare(dwc); /* FALLTHROUGH */ - case DWC3_MODE_HOST: + case USB_DR_MODE_HOST: default: dwc3_event_buffers_cleanup(dwc); break; @@ -646,12 +647,12 @@ static void dwc3_complete(struct device *dev) spin_lock_irqsave(&dwc->lock, flags); - switch (dwc->mode) { - case DWC3_MODE_DEVICE: - case DWC3_MODE_DRD: + switch (dwc->dr_mode) { + case USB_DR_MODE_PERIPHERAL: + case USB_DR_MODE_OTG: dwc3_gadget_complete(dwc); /* FALLTHROUGH */ - case DWC3_MODE_HOST: + case USB_DR_MODE_HOST: default: dwc3_event_buffers_setup(dwc); break; @@ -667,12 +668,12 @@ static int dwc3_suspend(struct device *dev) spin_lock_irqsave(&dwc->lock, flags); - switch (dwc->mode) { - case DWC3_MODE_DEVICE: - case DWC3_MODE_DRD: + switch (dwc->dr_mode) { + case USB_DR_MODE_PERIPHERAL: + case USB_DR_MODE_OTG: dwc3_gadget_suspend(dwc); /* FALLTHROUGH */ - case DWC3_MODE_HOST: + case USB_DR_MODE_HOST: default: /* do nothing */ break; @@ -700,12 +701,12 @@ static int dwc3_resume(struct device *dev) dwc3_writel(dwc->regs, DWC3_GCTL, dwc->gctl); - switch (dwc->mode) { - case DWC3_MODE_DEVICE: - case DWC3_MODE_DRD: + switch (dwc->dr_mode) { + case USB_DR_MODE_PERIPHERAL: + case USB_DR_MODE_OTG: dwc3_gadget_resume(dwc); /* FALLTHROUGH */ - case DWC3_MODE_HOST: + case USB_DR_MODE_HOST: default: /* do nothing */ break; diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 22ada27ad3ff..db385bda3095 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -29,6 +29,7 @@ #include #include +#include /* Global constants */ #define DWC3_EP0_BOUNCE_SIZE 512 @@ -545,11 +546,6 @@ struct dwc3_hwparams { /* HWPARAMS0 */ #define DWC3_MODE(n) ((n) & 0x7) -#define DWC3_MODE_DEVICE 0 -#define DWC3_MODE_HOST 1 -#define DWC3_MODE_DRD 2 -#define DWC3_MODE_HUB 3 - #define DWC3_MDWIDTH(n) (((n) & 0xff00) >> 8) /* HWPARAMS1 */ @@ -611,7 +607,7 @@ struct dwc3_scratchpad_array { * @u1u2: only used on revisions <1.83a for workaround * @maximum_speed: maximum speed requested (mainly for testing purposes) * @revision: revision register contents - * @mode: mode of operation + * @dr_mode: requested mode of operation * @usb2_phy: pointer to USB2 PHY * @usb3_phy: pointer to USB3 PHY * @dcfg: saved contents of DCFG register @@ -669,6 +665,8 @@ struct dwc3 { void __iomem *regs; size_t regs_size; + enum usb_dr_mode dr_mode; + /* used for suspend/resume */ u32 dcfg; u32 gctl; @@ -677,7 +675,6 @@ struct dwc3 { u32 u1u2; u32 maximum_speed; u32 revision; - u32 mode; #define DWC3_REVISION_173A 0x5533173a #define DWC3_REVISION_175A 0x5533175a diff --git a/drivers/usb/dwc3/platform_data.h b/drivers/usb/dwc3/platform_data.h index 16ffe1912523..7db34f00b89a 100644 --- a/drivers/usb/dwc3/platform_data.h +++ b/drivers/usb/dwc3/platform_data.h @@ -18,8 +18,10 @@ */ #include +#include struct dwc3_platform_data { enum usb_device_speed maximum_speed; + enum usb_dr_mode dr_mode; bool tx_fifo_resize; }; From 636e2a2caeafcb1b55b6799b29fe436039819eb9 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 12 Jul 2013 13:19:52 +0300 Subject: [PATCH 0956/3400] usb: dwc3: gadget: drop dwc3 manual phy control Recent versions of the core, can suspend and resume the PHYs automatically, so we don't need to fiddle with dwc3's Global PHY registers at all. On versions prior to 1.94a this patch will mean that we will never ask dwc3 to suspend the PHY. This is an acceptable behavior or such old versions of the core, specially considering that the only chip known to have a version prior to 1.94a was OMAP5 ES1.0 and that's not supported in mainline kernel, because it was just a test spin of OMAP5. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 61 --------------------------------------- 1 file changed, 61 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 4ca5706f3a86..c7be039d8551 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2105,34 +2105,6 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc) dwc->setup_packet_pending = false; } -static void dwc3_gadget_usb3_phy_suspend(struct dwc3 *dwc, int suspend) -{ - u32 reg; - - reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); - - if (suspend) - reg |= DWC3_GUSB3PIPECTL_SUSPHY; - else - reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; - - dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); -} - -static void dwc3_gadget_usb2_phy_suspend(struct dwc3 *dwc, int suspend) -{ - u32 reg; - - reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); - - if (suspend) - reg |= DWC3_GUSB2PHYCFG_SUSPHY; - else - reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; - - dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); -} - static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc) { u32 reg; @@ -2173,13 +2145,6 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc) /* after reset -> Default State */ usb_gadget_set_state(&dwc->gadget, USB_STATE_DEFAULT); - /* Recent versions support automatic phy suspend and don't need this */ - if (dwc->revision < DWC3_REVISION_194A) { - /* Resume PHYs */ - dwc3_gadget_usb2_phy_suspend(dwc, false); - dwc3_gadget_usb3_phy_suspend(dwc, false); - } - if (dwc->gadget.speed != USB_SPEED_UNKNOWN) dwc3_disconnect_gadget(dwc); @@ -2223,20 +2188,6 @@ static void dwc3_update_ram_clk_sel(struct dwc3 *dwc, u32 speed) dwc3_writel(dwc->regs, DWC3_GCTL, reg); } -static void dwc3_gadget_phy_suspend(struct dwc3 *dwc, u8 speed) -{ - switch (speed) { - case USB_SPEED_SUPER: - dwc3_gadget_usb2_phy_suspend(dwc, true); - break; - case USB_SPEED_HIGH: - case USB_SPEED_FULL: - case USB_SPEED_LOW: - dwc3_gadget_usb3_phy_suspend(dwc, true); - break; - } -} - static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc) { struct dwc3_ep *dep; @@ -2312,12 +2263,6 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc) dwc3_writel(dwc->regs, DWC3_DCTL, reg); } - /* Recent versions support automatic phy suspend and don't need this */ - if (dwc->revision < DWC3_REVISION_194A) { - /* Suspend unneeded PHY */ - dwc3_gadget_phy_suspend(dwc, dwc->gadget.speed); - } - dep = dwc->eps[0]; ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, true); if (ret) { @@ -2647,12 +2592,6 @@ int dwc3_gadget_init(struct dwc3 *dwc) reg |= DWC3_DCFG_LPM_CAP; dwc3_writel(dwc->regs, DWC3_DCFG, reg); - /* Enable USB2 LPM and automatic phy suspend only on recent versions */ - if (dwc->revision >= DWC3_REVISION_194A) { - dwc3_gadget_usb2_phy_suspend(dwc, false); - dwc3_gadget_usb3_phy_suspend(dwc, false); - } - ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget); if (ret) { dev_err(dwc->dev, "failed to register udc\n"); From 8bbcd17d6be41a5c0e4a8562e30c8f15c1ceb836 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 12 Jul 2013 15:33:35 +0300 Subject: [PATCH 0957/3400] usb: dwc3: omap: switch over to devm_ioremap_resource() use the new devm_ioremap_resource on dwc3-omap.c Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-omap.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index cf209086f3e8..ecd99451ee90 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -389,11 +389,9 @@ static int dwc3_omap_probe(struct platform_device *pdev) return -EINVAL; } - base = devm_ioremap_nocache(dev, res->start, resource_size(res)); - if (!base) { - dev_err(dev, "ioremap failed\n"); - return -ENOMEM; - } + base = devm_ioremap_resource(dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); spin_lock_init(&omap->lock); From 6c76e6cb48b240ae3062949cf352971b7b03b106 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 12 Jul 2013 15:34:12 +0300 Subject: [PATCH 0958/3400] usb: dwc3: core: switch over to devm_ioremap_resource() use the new devm_ioremap_resource() on core.c Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index df3723a1023e..25d374c54d73 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -389,23 +389,15 @@ static int dwc3_probe(struct platform_device *pdev) dwc->xhci_resources[0].flags = res->flags; dwc->xhci_resources[0].name = res->name; + res->start += DWC3_GLOBALS_REGS_START; + /* * Request memory region but exclude xHCI regs, * since it will be requested by the xhci-plat driver. */ - res = devm_request_mem_region(dev, res->start + DWC3_GLOBALS_REGS_START, - resource_size(res) - DWC3_GLOBALS_REGS_START, - dev_name(dev)); - if (!res) { - dev_err(dev, "can't request mem region\n"); - return -ENOMEM; - } - - regs = devm_ioremap_nocache(dev, res->start, resource_size(res)); - if (!regs) { - dev_err(dev, "ioremap failed\n"); - return -ENOMEM; - } + regs = devm_ioremap_resource(dev, res); + if (IS_ERR(regs)) + return PTR_ERR(regs); if (node) { dwc->maximum_speed = of_usb_get_maximum_speed(node); From ff62d6b6727360ae73382213bc1ebac6cf5160d7 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 12 Jul 2013 19:09:39 +0300 Subject: [PATCH 0959/3400] usb: dwc3: gadget: move debugging print around by moving that dev_vdbg() to the internal __dwc3_gadget_ep_enable() we get the print even when enable ep0, which calls the internal function directly. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index c7be039d8551..c8d47c12ce33 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -500,6 +500,8 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, u32 reg; int ret = -ENOMEM; + dev_vdbg(dwc->dev, "Enabling %s\n", dep->name); + if (!(dep->flags & DWC3_EP_ENABLED)) { ret = dwc3_gadget_start_config(dwc, dep); if (ret) @@ -656,8 +658,6 @@ static int dwc3_gadget_ep_enable(struct usb_ep *ep, dev_err(dwc->dev, "invalid endpoint transfer type\n"); } - dev_vdbg(dwc->dev, "Enabling %s\n", dep->name); - spin_lock_irqsave(&dwc->lock, flags); ret = __dwc3_gadget_ep_enable(dep, desc, ep->comp_desc, false); spin_unlock_irqrestore(&dwc->lock, flags); From 9aa62ae4292a2450634345d79a7fa1461bf7b39c Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 12 Jul 2013 19:10:59 +0300 Subject: [PATCH 0960/3400] usb: dwc3: gadget: move direction setting up no functional changes, just grouping dep initialization. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index c8d47c12ce33..f5efa03972bc 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1642,13 +1642,13 @@ static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc, dep->dwc = dwc; dep->number = epnum; + dep->direction = !!direction; dwc->eps[epnum] = dep; snprintf(dep->name, sizeof(dep->name), "ep%d%s", epnum >> 1, (epnum & 1) ? "in" : "out"); dep->endpoint.name = dep->name; - dep->direction = (epnum & 1); if (epnum == 0 || epnum == 1) { dep->endpoint.maxpacket = 512; From 653df35e6b3c0df875999a9b842327301269f55d Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 12 Jul 2013 19:11:57 +0300 Subject: [PATCH 0961/3400] usb: dwc3: gadget: add a debugging print when initializing endpoints that way we get debugging information when enabling verbose debug of the driver. It will be no-op otherwise. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index f5efa03972bc..3850ff0b853e 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1650,6 +1650,8 @@ static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc, dep->endpoint.name = dep->name; + dev_vdbg(dwc->dev, "initializing %s\n", dep->name); + if (epnum == 0 || epnum == 1) { dep->endpoint.maxpacket = 512; dep->endpoint.maxburst = 1; From aff310d91b537c29b979f975d4d9b5f26e978378 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 15 Jul 2013 11:30:45 +0300 Subject: [PATCH 0962/3400] usb: dwc3: core: don't redefine DWC3_DCFG_LPM_CAP the macro DWC3_DCFG_LPM_CAP was defined twice. This patch just removes one of the definitions, no functional changes. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index db385bda3095..cb6f8d803bc5 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -188,7 +188,6 @@ #define DWC3_MAX_HIBER_SCRATCHBUFS 15 /* Device Configuration Register */ -#define DWC3_DCFG_LPM_CAP (1 << 22) #define DWC3_DCFG_DEVADDR(addr) ((addr) << 3) #define DWC3_DCFG_DEVADDR_MASK DWC3_DCFG_DEVADDR(0x7f) From fb49740d72a305f2e4110b4dfb53fdd9130d8878 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 15 Jul 2013 11:31:27 +0300 Subject: [PATCH 0963/3400] usb: dwc3: gadget: don't enable LPM early LPM is enabled in Connection Done interrupt, there's no need to enable it early. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 3850ff0b853e..95ef20c5b53b 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2540,7 +2540,6 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc) */ int dwc3_gadget_init(struct dwc3 *dwc) { - u32 reg; int ret; dwc->ctrl_req = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ctrl_req), @@ -2590,10 +2589,6 @@ int dwc3_gadget_init(struct dwc3 *dwc) if (ret) goto err4; - reg = dwc3_readl(dwc->regs, DWC3_DCFG); - reg |= DWC3_DCFG_LPM_CAP; - dwc3_writel(dwc->regs, DWC3_DCFG, reg); - ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget); if (ret) { dev_err(dwc->dev, "failed to register udc\n"); From 68d6a01bdd2a9ebae858271129d0a8d4ae865e93 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 12 Jun 2013 21:09:26 +0300 Subject: [PATCH 0964/3400] usb: dwc3: core: introduce and use macros for Event Size register That register has more than just the event buffer size; we can also mask and unmask that particular interrupter on bit 31 of that register. In this patch we introduce the necessary macros and make sure to use the new macros while also making sure we mask interrupts during driver removal. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 5 +++-- drivers/usb/dwc3/core.h | 4 ++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 25d374c54d73..dfbc1f0fc0e3 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -218,7 +218,7 @@ static int dwc3_event_buffers_setup(struct dwc3 *dwc) dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), upper_32_bits(evt->dma)); dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), - evt->length & 0xffff); + DWC3_GEVNTSIZ_SIZE(evt->length)); dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0); } @@ -237,7 +237,8 @@ static void dwc3_event_buffers_cleanup(struct dwc3 *dwc) dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 0); dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 0); - dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), 0); + dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), DWC3_GEVNTSIZ_INTMASK + | DWC3_GEVNTSIZ_SIZE(0)); dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0); } } diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index cb6f8d803bc5..d30e094faa58 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -175,6 +175,10 @@ #define DWC3_GTXFIFOSIZ_TXFDEF(n) ((n) & 0xffff) #define DWC3_GTXFIFOSIZ_TXFSTADDR(n) ((n) & 0xffff0000) +/* Global Event Size Registers */ +#define DWC3_GEVNTSIZ_INTMASK (1 << 31) +#define DWC3_GEVNTSIZ_SIZE(n) ((n) & 0xffff) + /* Global HWPARAMS1 Register */ #define DWC3_GHWPARAMS1_EN_PWROPT(n) (((n) & (3 << 24)) >> 24) #define DWC3_GHWPARAMS1_EN_PWROPT_NO 0 From e8adfc30ff9282a728fd8b666b6418308164c415 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 12 Jun 2013 21:11:14 +0300 Subject: [PATCH 0965/3400] usb: dwc3: gadget: get rid of IRQF_ONESHOT We can make use of bit 31 of the GEVNTSIZ(n) registers to mask/unmask interrupts from that particular interrupter. With that feature, we can easily drop IRQF_ONESHOT from our driver which makes it possible to properly change IRQ priorities when using RT patchset *and* it allows us to make use of the scheduler to choose the proper time to handle this IRQ thread. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 95ef20c5b53b..bdca5a255a1d 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1490,7 +1490,7 @@ static int dwc3_gadget_start(struct usb_gadget *g, irq = platform_get_irq(to_platform_device(dwc->dev), 0); ret = request_threaded_irq(irq, dwc3_interrupt, dwc3_thread_interrupt, - IRQF_SHARED | IRQF_ONESHOT, "dwc3", dwc); + IRQF_SHARED, "dwc3", dwc); if (ret) { dev_err(dwc->dev, "failed to request irq #%d --> %d\n", irq, ret); @@ -2447,6 +2447,7 @@ static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc) struct dwc3 *dwc = _dwc; unsigned long flags; irqreturn_t ret = IRQ_NONE; + u32 reg; int i; spin_lock_irqsave(&dwc->lock, flags); @@ -2486,6 +2487,11 @@ static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc) evt->count = 0; evt->flags &= ~DWC3_EVENT_PENDING; ret = IRQ_HANDLED; + + /* Unmask interrupt */ + reg = dwc3_readl(dwc->regs, DWC3_GEVNTSIZ(i)); + reg &= ~DWC3_GEVNTSIZ_INTMASK; + dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(i), reg); } spin_unlock_irqrestore(&dwc->lock, flags); @@ -2497,6 +2503,7 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf) { struct dwc3_event_buffer *evt; u32 count; + u32 reg; evt = dwc->ev_buffs[buf]; @@ -2508,6 +2515,11 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf) evt->count = count; evt->flags |= DWC3_EVENT_PENDING; + /* Mask interrupt */ + reg = dwc3_readl(dwc->regs, DWC3_GEVNTSIZ(buf)); + reg |= DWC3_GEVNTSIZ_INTMASK; + dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(buf), reg); + return IRQ_WAKE_THREAD; } From 7f97aa9865800766e570d0e1be772a034dd30388 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 12 Jun 2013 21:16:11 +0300 Subject: [PATCH 0966/3400] usb: dwc3: gadget: rename dwc3_process_event_buf that function isn't really processing any event buffer, rather just checking whether it contains events to be processed. Due to that reason, we're reaning it to dwc3_check_event_buf() instead. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index bdca5a255a1d..8e47eefffeee 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2499,7 +2499,7 @@ static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc) return ret; } -static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf) +static irqreturn_t dwc3_check_event_buf(struct dwc3 *dwc, u32 buf) { struct dwc3_event_buffer *evt; u32 count; @@ -2534,7 +2534,7 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc) for (i = 0; i < dwc->num_event_buffers; i++) { irqreturn_t status; - status = dwc3_process_event_buf(dwc, i); + status = dwc3_check_event_buf(dwc, i); if (status == IRQ_WAKE_THREAD) ret = status; } From f42f2447d66233a5bf86e8631e4eb4e863b2ff0b Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 12 Jun 2013 21:25:08 +0300 Subject: [PATCH 0967/3400] usb: dwc3: gadget: introduce dwc3_process_event_buf in order to make our IRQ handler thread easier to read, we re-factor the inner loop to a separate function. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 91 +++++++++++++++++++++------------------ 1 file changed, 49 insertions(+), 42 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 8e47eefffeee..f168eaebdef8 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2442,57 +2442,64 @@ static void dwc3_process_event_entry(struct dwc3 *dwc, } } +static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf) +{ + struct dwc3_event_buffer *evt; + irqreturn_t ret = IRQ_NONE; + int left; + u32 reg; + + evt = dwc->ev_buffs[buf]; + left = evt->count; + + if (!(evt->flags & DWC3_EVENT_PENDING)) + return IRQ_NONE; + + while (left > 0) { + union dwc3_event event; + + event.raw = *(u32 *) (evt->buf + evt->lpos); + + dwc3_process_event_entry(dwc, &event); + + /* + * FIXME we wrap around correctly to the next entry as + * almost all entries are 4 bytes in size. There is one + * entry which has 12 bytes which is a regular entry + * followed by 8 bytes data. ATM I don't know how + * things are organized if we get next to the a + * boundary so I worry about that once we try to handle + * that. + */ + evt->lpos = (evt->lpos + 4) % DWC3_EVENT_BUFFERS_SIZE; + left -= 4; + + dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(buf), 4); + } + + evt->count = 0; + evt->flags &= ~DWC3_EVENT_PENDING; + ret = IRQ_HANDLED; + + /* Unmask interrupt */ + reg = dwc3_readl(dwc->regs, DWC3_GEVNTSIZ(buf)); + reg &= ~DWC3_GEVNTSIZ_INTMASK; + dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(buf), reg); + + return ret; +} + static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc) { struct dwc3 *dwc = _dwc; unsigned long flags; irqreturn_t ret = IRQ_NONE; - u32 reg; int i; spin_lock_irqsave(&dwc->lock, flags); - for (i = 0; i < dwc->num_event_buffers; i++) { - struct dwc3_event_buffer *evt; - int left; - - evt = dwc->ev_buffs[i]; - left = evt->count; - - if (!(evt->flags & DWC3_EVENT_PENDING)) - continue; - - while (left > 0) { - union dwc3_event event; - - event.raw = *(u32 *) (evt->buf + evt->lpos); - - dwc3_process_event_entry(dwc, &event); - - /* - * FIXME we wrap around correctly to the next entry as - * almost all entries are 4 bytes in size. There is one - * entry which has 12 bytes which is a regular entry - * followed by 8 bytes data. ATM I don't know how - * things are organized if we get next to the a - * boundary so I worry about that once we try to handle - * that. - */ - evt->lpos = (evt->lpos + 4) % DWC3_EVENT_BUFFERS_SIZE; - left -= 4; - - dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(i), 4); - } - - evt->count = 0; - evt->flags &= ~DWC3_EVENT_PENDING; - ret = IRQ_HANDLED; - - /* Unmask interrupt */ - reg = dwc3_readl(dwc->regs, DWC3_GEVNTSIZ(i)); - reg &= ~DWC3_GEVNTSIZ_INTMASK; - dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(i), reg); - } + for (i = 0; i < dwc->num_event_buffers; i++) + ret |= dwc3_process_event_buf(dwc, i); spin_unlock_irqrestore(&dwc->lock, flags); From c75f52fb26aa9c10b3f5ee157bc0c6c8e8e9bb1a Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Wed, 12 Jun 2013 23:43:11 +0800 Subject: [PATCH 0968/3400] usb: dwc3: fix typo in comment of dwc3_ep Change intervall into interval. Signed-off-by: Huang Rui Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index d30e094faa58..f8af8d44af85 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -398,7 +398,7 @@ struct dwc3_event_buffer { * @number: endpoint number (1 - 15) * @type: set to bmAttributes & USB_ENDPOINT_XFERTYPE_MASK * @resource_index: Resource transfer index - * @interval: the intervall on which the ISOC transfer is started + * @interval: the interval on which the ISOC transfer is started * @name: a human readable name e.g. ep1out-bulk * @direction: true for TX, false for RX * @stream_capable: true when streams are enabled From 5702f75375aa9ecf8ad3431aef3fe6ce8c8dbd15 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 17 Jul 2013 11:09:49 +0300 Subject: [PATCH 0969/3400] usb: gadget: udc-core: move sysfs_notify() to a workqueue usb_gadget_set_state() will call sysfs_notify() which might sleep. Some users might want to call usb_gadget_set_state() from the very IRQ handler which actually changes the gadget state. Instead of having every UDC driver add their own workqueue for such a simple notification, we're adding it generically to our struct usb_gadget, so the details are hidden from all UDC drivers. Acked-by: Alan Stern Signed-off-by: Felipe Balbi --- drivers/usb/gadget/udc-core.c | 12 +++++++++++- include/linux/usb/gadget.h | 4 ++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c index c28ac9872030..3122ab942f75 100644 --- a/drivers/usb/gadget/udc-core.c +++ b/drivers/usb/gadget/udc-core.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -105,11 +106,18 @@ EXPORT_SYMBOL_GPL(usb_gadget_unmap_request); /* ------------------------------------------------------------------------- */ +static void usb_gadget_state_work(struct work_struct *work) +{ + struct usb_gadget *gadget = work_to_gadget(work); + + sysfs_notify(&gadget->dev.kobj, NULL, "status"); +} + void usb_gadget_set_state(struct usb_gadget *gadget, enum usb_device_state state) { gadget->state = state; - sysfs_notify(&gadget->dev.kobj, NULL, "status"); + schedule_work(&gadget->work); } EXPORT_SYMBOL_GPL(usb_gadget_set_state); @@ -196,6 +204,7 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget, goto err1; dev_set_name(&gadget->dev, "gadget"); + INIT_WORK(&gadget->work, usb_gadget_state_work); gadget->dev.parent = parent; #ifdef CONFIG_HAS_DMA @@ -315,6 +324,7 @@ found: usb_gadget_remove_driver(udc); kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE); + flush_work(&gadget->work); device_unregister(&udc->dev); device_unregister(&gadget->dev); } diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index f1b0dca60f12..942ef5e053bf 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -22,6 +22,7 @@ #include #include #include +#include #include struct usb_ep; @@ -475,6 +476,7 @@ struct usb_gadget_ops { /** * struct usb_gadget - represents a usb slave device + * @work: (internal use) Workqueue to be used for sysfs_notify() * @ops: Function pointers used to access hardware-specific operations. * @ep0: Endpoint zero, used when reading or writing responses to * driver setup() requests @@ -520,6 +522,7 @@ struct usb_gadget_ops { * device is acting as a B-Peripheral (so is_a_peripheral is false). */ struct usb_gadget { + struct work_struct work; /* readonly to gadget driver */ const struct usb_gadget_ops *ops; struct usb_ep *ep0; @@ -538,6 +541,7 @@ struct usb_gadget { unsigned out_epnum; unsigned in_epnum; }; +#define work_to_gadget(w) (container_of((w), struct usb_gadget, work)) static inline void set_gadget_data(struct usb_gadget *gadget, void *data) { dev_set_drvdata(&gadget->dev, data); } From 7a42d83536a5ea7ea7b4ad279c34c4c4ce509b5a Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 22 Jul 2013 12:31:31 +0300 Subject: [PATCH 0970/3400] usb: dwc3: ep0: only change to ADDRESS if set_config() succeeds In case we're switching back to USB_STATE_ADDRESS from USB_STATE_CONFIGURED (if host sends a set configuration command for configuration zero), we should only switch if the request is successfully processed by the gadget driver. Reported-by: Alan Stern Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/ep0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index e9d099cee636..007651c21638 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -551,7 +551,7 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) case USB_STATE_CONFIGURED: ret = dwc3_ep0_delegate_req(dwc, ctrl); - if (!cfg) + if (!cfg && !ret) usb_gadget_set_state(&dwc->gadget, USB_STATE_ADDRESS); break; From 7c81290e87bf01b507deabf0f478e051367cb416 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 22 Jul 2013 12:41:47 +0300 Subject: [PATCH 0971/3400] usb: dwc3: ep0: don't change to configured state too early before changing to configured state, we need to wait until gadget driver has had a chance to process the request. In case of USB_GADGET_DELAYED_STATUS, that means we need to defer usb_gadget_set_state() until the upcoming usb_ep_queue(). Reported-by: Alan Stern Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/ep0.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 007651c21638..7fa93f4bc507 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -148,6 +148,7 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep, direction = !dwc->ep0_expect_in; dwc->delayed_status = false; + usb_gadget_set_state(&dwc->gadget, USB_STATE_CONFIGURED); if (dwc->ep0state == EP0_STATUS_PHASE) __dwc3_ep0_do_control_status(dwc, dwc->eps[direction]); @@ -533,8 +534,16 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) ret = dwc3_ep0_delegate_req(dwc, ctrl); /* if the cfg matches and the cfg is non zero */ if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) { - usb_gadget_set_state(&dwc->gadget, - USB_STATE_CONFIGURED); + + /* + * only change state if set_config has already + * been processed. If gadget driver returns + * USB_GADGET_DELAYED_STATUS, we will wait + * to change the state on the next usb_ep_queue() + */ + if (ret == 0) + usb_gadget_set_state(&dwc->gadget, + USB_STATE_CONFIGURED); /* * Enable transition to U1/U2 state when From 052a11d13bdecb77ee4cdbdccfce5434a12209af Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Fri, 14 Jun 2013 12:51:41 +0300 Subject: [PATCH 0972/3400] usb: phy: make PHY driver selection possible by controller drivers Convert PHY Drivers from menuconfig to menu so that the PHY drivers can be explicitely selected by the controller drivers. USB_PHY is no longer a user visible option. It is upto to the PHY drivers to select it if needed. This patch does so for the existing PHY drivers that use the USB_PHY library. Doing so moves the USB_PHY and PHY driver selection problem from the end user to the PHY and controller driver developer. e.g. Earlier, a controller driver (e.g. EHCI_OMAP) that needs to select a PHY driver (e.g. NOP_PHY) couldn't do so because the PHY driver depended on USB_PHY. Making the controller driver depend on USB_PHY has a negative effect i.e. it becomes invisible to the user till USB_PHY is enabled. Most end users will not familiar with this. With this patch, the end user just needs to select the controller driver needed for his/her platform without worrying about which PHY driver to select. Also update USB_EHCI_MSM, USB_LPC32XX and USB_OMAP to not depend on USB_PHY any more. They can safely select the necessary PHY drivers. [ balbi@ti.com : refreshed on top of my next branch. Changed bool followed by default n into def_bool n ] CC: Pavankumar Kondeti Acked-by: Roland Stigge Signed-off-by: Roger Quadros Signed-off-by: Felipe Balbi --- drivers/usb/Makefile | 2 +- drivers/usb/gadget/Kconfig | 2 -- drivers/usb/host/Kconfig | 1 - drivers/usb/phy/Kconfig | 36 ++++++++++++++++++++---------------- 4 files changed, 21 insertions(+), 20 deletions(-) diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index 238c5d47cadb..2b3132ede23a 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -45,7 +45,7 @@ obj-$(CONFIG_USB_MICROTEK) += image/ obj-$(CONFIG_USB_SERIAL) += serial/ obj-$(CONFIG_USB) += misc/ -obj-$(CONFIG_USB_PHY) += phy/ +obj-$(CONFIG_USB_SUPPORT) += phy/ obj-$(CONFIG_EARLY_PRINTK_DBGP) += early/ obj-$(CONFIG_USB_ATM) += atm/ diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 08dab3c640fd..1e3f52574367 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -144,7 +144,6 @@ config USB_AT91 config USB_LPC32XX tristate "LPC32XX USB Peripheral Controller" depends on ARCH_LPC32XX - depends on USB_PHY select USB_ISP1301 help This option selects the USB device controller in the LPC32xx SoC. @@ -206,7 +205,6 @@ config USB_FOTG210_UDC config USB_OMAP tristate "OMAP USB Device Controller" depends on ARCH_OMAP1 - depends on USB_PHY select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4_OTG help Many Texas Instruments OMAP processors have flexible full diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 4263d011392c..3102b522ca02 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -186,7 +186,6 @@ config USB_EHCI_HCD_AT91 config USB_EHCI_MSM tristate "Support for Qualcomm QSD/MSM on-chip EHCI USB controller" depends on ARCH_MSM - depends on USB_PHY select USB_EHCI_ROOT_HUB_TT select USB_MSM_OTG ---help--- diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index 3622fff8b798..f5ea339ec155 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -1,22 +1,10 @@ # # Physical Layer USB driver configuration # -menuconfig USB_PHY - bool "USB Physical Layer drivers" - help - Most USB controllers have the physical layer signalling part - (commonly called a PHY) built in. However, dual-role devices - (a.k.a. USB on-the-go) which support being USB master or slave - with the same connector often use an external PHY. +menu "USB Physical Layer drivers" - The drivers in this submenu add support for such PHY devices. - They are not needed for standard master-only (or the vast - majority of slave-only) USB interfaces. - - If you're not sure if this applies to you, it probably doesn't; - say N here. - -if USB_PHY +config USB_PHY + def_bool n # # USB Transceiver Drivers @@ -24,6 +12,7 @@ if USB_PHY config AB8500_USB tristate "AB8500 USB Transceiver Driver" depends on AB8500_CORE + select USB_PHY help Enable this to support the USB OTG transceiver in AB8500 chip. This transceiver supports high and full speed devices plus, @@ -33,12 +22,14 @@ config FSL_USB2_OTG bool "Freescale USB OTG Transceiver Driver" depends on USB_EHCI_FSL && USB_FSL_USB2 && PM_RUNTIME select USB_OTG + select USB_PHY help Enable this to support Freescale USB OTG transceiver. config ISP1301_OMAP tristate "Philips ISP1301 with OMAP OTG" depends on I2C && ARCH_OMAP_OTG + select USB_PHY help If you say yes here you get support for the Philips ISP1301 USB-On-The-Go transceiver working with the OMAP OTG controller. @@ -52,12 +43,14 @@ config ISP1301_OMAP config MV_U3D_PHY bool "Marvell USB 3.0 PHY controller Driver" depends on CPU_MMP3 + select USB_PHY help Enable this to support Marvell USB 3.0 phy controller for Marvell SoC. config NOP_USB_XCEIV tristate "NOP USB Transceiver Driver" + select USB_PHY 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 @@ -76,6 +69,7 @@ config OMAP_USB2 tristate "OMAP USB2 PHY Driver" depends on ARCH_OMAP2PLUS select OMAP_CONTROL_USB + select USB_PHY help Enable this to support the transceiver that is part of SOC. This driver takes care of all the PHY functionality apart from comparator. @@ -85,6 +79,7 @@ config OMAP_USB2 config OMAP_USB3 tristate "OMAP USB3 PHY Driver" select OMAP_CONTROL_USB + select USB_PHY help Enable this to support the USB3 PHY that is part of SOC. This driver takes care of all the PHY functionality apart from comparator. @@ -101,6 +96,7 @@ config SAMSUNG_USBPHY config SAMSUNG_USB2PHY tristate "Samsung USB 2.0 PHY controller Driver" select SAMSUNG_USBPHY + select USB_PHY help Enable this to support Samsung USB 2.0 (High Speed) PHY controller driver for Samsung SoCs. @@ -108,6 +104,7 @@ config SAMSUNG_USB2PHY config SAMSUNG_USB3PHY tristate "Samsung USB 3.0 PHY controller Driver" select SAMSUNG_USBPHY + select USB_PHY help Enable this to support Samsung USB 3.0 (Super Speed) phy controller for samsung SoCs. @@ -115,6 +112,7 @@ config SAMSUNG_USB3PHY config TWL4030_USB tristate "TWL4030 USB Transceiver Driver" depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS + select USB_PHY help Enable this to support the USB OTG transceiver on TWL4030 family chips (including the TWL5030 and TPS659x0 devices). @@ -135,6 +133,7 @@ config TWL6030_USB config USB_GPIO_VBUS tristate "GPIO based peripheral-only VBUS sensing 'transceiver'" depends on GPIOLIB + select USB_PHY help Provides simple GPIO VBUS sensing for controllers with an internal transceiver via the usb_phy interface, and @@ -145,6 +144,7 @@ config USB_ISP1301 tristate "NXP ISP1301 USB transceiver support" depends on USB || USB_GADGET depends on I2C + select USB_PHY help Say Y here to add support for the NXP ISP1301 USB transceiver driver. This chip is typically used as USB transceiver for USB host, gadget @@ -156,6 +156,7 @@ config USB_ISP1301 config USB_MSM_OTG tristate "OTG support for Qualcomm on-chip USB controller" depends on (USB || USB_GADGET) && ARCH_MSM + select USB_PHY help Enable this to support the USB OTG transceiver on MSM chips. It handles PHY initialization, clock management, and workarounds @@ -169,6 +170,7 @@ config USB_MV_OTG tristate "Marvell USB OTG support" depends on USB_EHCI_MV && USB_MV_UDC && PM_RUNTIME select USB_OTG + select USB_PHY help Say Y here if you want to build Marvell USB OTG transciever driver in kernel (including PXA and MMP series). This driver @@ -180,6 +182,7 @@ config USB_MXS_PHY tristate "Freescale MXS USB PHY support" depends on ARCH_MXC || ARCH_MXS select STMP_DEVICE + select USB_PHY help Enable this to support the Freescale MXS USB PHY. @@ -188,6 +191,7 @@ config USB_MXS_PHY config USB_RCAR_PHY tristate "Renesas R-Car USB PHY support" depends on USB || USB_GADGET + select USB_PHY help Say Y here to add support for the Renesas R-Car USB common PHY driver. This chip is typically used as USB PHY for USB host, gadget. @@ -210,4 +214,4 @@ config USB_ULPI_VIEWPORT Provides read/write operations to the ULPI phy register set for controllers with a viewport register (e.g. Chipidea/ARC controllers). -endif # USB_PHY +endmenu From 88650d62a12de7fb9437b5508cc7f6b28da58cbf Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Fri, 14 Jun 2013 12:51:42 +0300 Subject: [PATCH 0973/3400] usb: ehci-omap: select NOP_USB_XCEIV PHY driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ehci-omap needs NOP_USB_XCEIV PHY driver to function properly, so select it. As the USB PHY drivers no longer depend on USB_PHY, it is safe to select the PHY drivers. Signed-off-by: Roger Quadros Tested-by: Adrien Vergé Signed-off-by: Felipe Balbi --- drivers/usb/host/Kconfig | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 3102b522ca02..5064e06e25b4 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -148,13 +148,11 @@ config USB_EHCI_MXC config USB_EHCI_HCD_OMAP tristate "EHCI support for OMAP3 and later chips" depends on ARCH_OMAP + select NOP_USB_XCEIV default y ---help--- Enables support for the on-chip EHCI controller on OMAP3 and later chips. - If your system uses a PHY on the USB port, you will need to - enable USB_PHY and the appropriate PHY driver as well. Most - boards need the NOP_USB_XCEIV PHY driver. config USB_EHCI_HCD_ORION tristate "Support for Marvell EBU on-chip EHCI USB controller" From 519c6013d356fef95c9e45cfb533b3e68b47dbf4 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Tue, 9 Jul 2013 14:38:31 +0300 Subject: [PATCH 0974/3400] usb: phy: omap-usb3: Improve DPLL parameter lookup code Use a mapping table (dpll_map) to match the possible system clock rates to the appropriate DPLL parameters. Introduce a function "omap_usb3_get_dpll_params()" that will return the matching DPLL parameters for the given clock rate. Also, bail out on phy init if DPLL locking fails. Signed-off-by: Roger Quadros Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-omap-usb3.c | 87 ++++++++++++++------------------- 1 file changed, 38 insertions(+), 49 deletions(-) diff --git a/drivers/usb/phy/phy-omap-usb3.c b/drivers/usb/phy/phy-omap-usb3.c index a2fb30bbb971..fc15694d3031 100644 --- a/drivers/usb/phy/phy-omap-usb3.c +++ b/drivers/usb/phy/phy-omap-usb3.c @@ -27,7 +27,6 @@ #include #include -#define NUM_SYS_CLKS 6 #define PLL_STATUS 0x00000004 #define PLL_GO 0x00000008 #define PLL_CONFIGURATION1 0x0000000C @@ -57,26 +56,32 @@ */ # define PLL_IDLE_TIME 100; -enum sys_clk_rate { - CLK_RATE_UNDEFINED = -1, - CLK_RATE_12MHZ, - CLK_RATE_16MHZ, - CLK_RATE_19MHZ, - CLK_RATE_20MHZ, - CLK_RATE_26MHZ, - CLK_RATE_38MHZ +struct usb_dpll_map { + unsigned long rate; + struct usb_dpll_params params; }; -static struct usb_dpll_params omap_usb3_dpll_params[NUM_SYS_CLKS] = { - {1250, 5, 4, 20, 0}, /* 12 MHz */ - {3125, 20, 4, 20, 0}, /* 16.8 MHz */ - {1172, 8, 4, 20, 65537}, /* 19.2 MHz */ - {1000, 7, 4, 10, 0}, /* 20 MHz */ - {1250, 12, 4, 20, 0}, /* 26 MHz */ - {3125, 47, 4, 20, 92843}, /* 38.4 MHz */ - +static struct usb_dpll_map dpll_map[] = { + {12000000, {1250, 5, 4, 20, 0} }, /* 12 MHz */ + {16800000, {3125, 20, 4, 20, 0} }, /* 16.8 MHz */ + {19200000, {1172, 8, 4, 20, 65537} }, /* 19.2 MHz */ + {20000000, {1000, 7, 4, 10, 0} }, /* 20 MHz */ + {26000000, {1250, 12, 4, 20, 0} }, /* 26 MHz */ + {38400000, {3125, 47, 4, 20, 92843} }, /* 38.4 MHz */ }; +static struct usb_dpll_params *omap_usb3_get_dpll_params(unsigned long rate) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(dpll_map); i++) { + if (rate == dpll_map[i].rate) + return &dpll_map[i].params; + } + + return 0; +} + static int omap_usb3_suspend(struct usb_phy *x, int suspend) { struct omap_usb *phy = phy_to_omapusb(x); @@ -116,26 +121,6 @@ static int omap_usb3_suspend(struct usb_phy *x, int suspend) return 0; } -static inline enum sys_clk_rate __get_sys_clk_index(unsigned long rate) -{ - switch (rate) { - case 12000000: - return CLK_RATE_12MHZ; - case 16800000: - return CLK_RATE_16MHZ; - case 19200000: - return CLK_RATE_19MHZ; - case 20000000: - return CLK_RATE_20MHZ; - case 26000000: - return CLK_RATE_26MHZ; - case 38400000: - return CLK_RATE_38MHZ; - default: - return CLK_RATE_UNDEFINED; - } -} - static void omap_usb_dpll_relock(struct omap_usb *phy) { u32 val; @@ -155,39 +140,39 @@ static int omap_usb_dpll_lock(struct omap_usb *phy) { u32 val; unsigned long rate; - enum sys_clk_rate clk_index; + struct usb_dpll_params *dpll_params; - rate = clk_get_rate(phy->sys_clk); - clk_index = __get_sys_clk_index(rate); - - if (clk_index == CLK_RATE_UNDEFINED) { - pr_err("dpll cannot be locked for sys clk freq:%luHz\n", rate); + rate = clk_get_rate(phy->sys_clk); + dpll_params = omap_usb3_get_dpll_params(rate); + if (!dpll_params) { + dev_err(phy->dev, + "No DPLL configuration for %lu Hz SYS CLK\n", rate); return -EINVAL; } val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1); val &= ~PLL_REGN_MASK; - val |= omap_usb3_dpll_params[clk_index].n << PLL_REGN_SHIFT; + val |= dpll_params->n << PLL_REGN_SHIFT; omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val); val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2); val &= ~PLL_SELFREQDCO_MASK; - val |= omap_usb3_dpll_params[clk_index].freq << PLL_SELFREQDCO_SHIFT; + val |= dpll_params->freq << PLL_SELFREQDCO_SHIFT; omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val); val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1); val &= ~PLL_REGM_MASK; - val |= omap_usb3_dpll_params[clk_index].m << PLL_REGM_SHIFT; + val |= dpll_params->m << PLL_REGM_SHIFT; omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val); val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION4); val &= ~PLL_REGM_F_MASK; - val |= omap_usb3_dpll_params[clk_index].mf << PLL_REGM_F_SHIFT; + val |= dpll_params->mf << PLL_REGM_F_SHIFT; omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION4, val); val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION3); val &= ~PLL_SD_MASK; - val |= omap_usb3_dpll_params[clk_index].sd << PLL_SD_SHIFT; + val |= dpll_params->sd << PLL_SD_SHIFT; omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION3, val); omap_usb_dpll_relock(phy); @@ -198,8 +183,12 @@ static int omap_usb_dpll_lock(struct omap_usb *phy) static int omap_usb3_init(struct usb_phy *x) { struct omap_usb *phy = phy_to_omapusb(x); + int ret; + + ret = omap_usb_dpll_lock(phy); + if (ret) + return ret; - omap_usb_dpll_lock(phy); omap_control_usb3_phy_power(phy->control_dev, 1); return 0; From 925403f425a4a9c503f2fc295652647b1eb10d82 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 11 Jul 2013 22:32:31 -0700 Subject: [PATCH 0975/3400] usb: renesas_usbhs: tidyup original usbhsx_for_each_xxx macro Current usbhsx_for_each_xxx macro will read out-of-array's memory after last loop operation. It was not good C language operation, and the binary which was compiled by (at least) gcc 4.8.1 is broken This patch tidyup these issues Reported-by: Yusuke Goda Reviewed-by: Takashi Yoshii Signed-off-by: Kuninori Morimoto Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/mod_gadget.c | 6 +++--- drivers/usb/renesas_usbhs/mod_host.c | 6 +++--- drivers/usb/renesas_usbhs/pipe.h | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index 805940c37353..3385aeb5a364 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -77,9 +77,9 @@ struct usbhsg_recip_handle { struct usbhsg_gpriv, mod) #define __usbhsg_for_each_uep(start, pos, g, i) \ - for (i = start, pos = (g)->uep + i; \ - i < (g)->uep_size; \ - i++, pos = (g)->uep + i) + for ((i) = start; \ + ((i) < (g)->uep_size) && ((pos) = (g)->uep + (i)); \ + (i)++) #define usbhsg_for_each_uep(pos, gpriv, i) \ __usbhsg_for_each_uep(1, pos, gpriv, i) diff --git a/drivers/usb/renesas_usbhs/mod_host.c b/drivers/usb/renesas_usbhs/mod_host.c index b86815421c8d..e40f565004d0 100644 --- a/drivers/usb/renesas_usbhs/mod_host.c +++ b/drivers/usb/renesas_usbhs/mod_host.c @@ -111,9 +111,9 @@ static const char usbhsh_hcd_name[] = "renesas_usbhs host"; container_of(usbhs_mod_get(priv, USBHS_HOST), struct usbhsh_hpriv, mod) #define __usbhsh_for_each_udev(start, pos, h, i) \ - for (i = start, pos = (h)->udev + i; \ - i < USBHSH_DEVICE_MAX; \ - i++, pos = (h)->udev + i) + for ((i) = start; \ + ((i) < USBHSH_DEVICE_MAX) && ((pos) = (h)->udev + (i)); \ + (i)++) #define usbhsh_for_each_udev(pos, hpriv, i) \ __usbhsh_for_each_udev(1, pos, hpriv, i) diff --git a/drivers/usb/renesas_usbhs/pipe.h b/drivers/usb/renesas_usbhs/pipe.h index b476fde955bf..3e5349879838 100644 --- a/drivers/usb/renesas_usbhs/pipe.h +++ b/drivers/usb/renesas_usbhs/pipe.h @@ -54,9 +54,9 @@ struct usbhs_pipe_info { * pipe list */ #define __usbhs_for_each_pipe(start, pos, info, i) \ - for (i = start, pos = (info)->pipe + i; \ - i < (info)->size; \ - i++, pos = (info)->pipe + i) + for ((i) = start; \ + ((i) < (info)->size) && ((pos) = (info)->pipe + (i)); \ + (i)++) #define usbhs_for_each_pipe(pos, priv, i) \ __usbhs_for_each_pipe(1, pos, &((priv)->pipe_info), i) From 0d98b9d6429c21132fa08c452e62127fd5032b55 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 18 Jul 2013 09:43:08 +0200 Subject: [PATCH 0976/3400] usb: gadget: atmel_usba: prepare clk before calling enable Replace clk_enable/disable with clk_prepare_enable/disable_unprepare to avoid common clk framework warnings. Signed-off-by: Boris BREZILLON Signed-off-by: Felipe Balbi --- drivers/usb/gadget/atmel_usba_udc.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c index 1d9722203ca6..f018017e3a77 100644 --- a/drivers/usb/gadget/atmel_usba_udc.c +++ b/drivers/usb/gadget/atmel_usba_udc.c @@ -1772,6 +1772,7 @@ out: static int atmel_usba_start(struct usb_gadget *gadget, struct usb_gadget_driver *driver) { + int ret = 0; struct usba_udc *udc = container_of(gadget, struct usba_udc, gadget); unsigned long flags; @@ -1781,8 +1782,14 @@ static int atmel_usba_start(struct usb_gadget *gadget, udc->driver = driver; spin_unlock_irqrestore(&udc->lock, flags); - clk_enable(udc->pclk); - clk_enable(udc->hclk); + ret = clk_prepare_enable(udc->pclk); + if (ret) + goto out; + ret = clk_prepare_enable(udc->hclk); + if (ret) { + clk_disable_unprepare(udc->pclk); + goto out; + } DBG(DBG_GADGET, "registered driver `%s'\n", driver->driver.name); @@ -1797,9 +1804,11 @@ static int atmel_usba_start(struct usb_gadget *gadget, usba_writel(udc, CTRL, USBA_ENABLE_MASK); usba_writel(udc, INT_ENB, USBA_END_OF_RESET); } + +out: spin_unlock_irqrestore(&udc->lock, flags); - return 0; + return ret; } static int atmel_usba_stop(struct usb_gadget *gadget, @@ -1822,8 +1831,8 @@ static int atmel_usba_stop(struct usb_gadget *gadget, udc->driver = NULL; - clk_disable(udc->hclk); - clk_disable(udc->pclk); + clk_disable_unprepare(udc->hclk); + clk_disable_unprepare(udc->pclk); DBG(DBG_GADGET, "unregistered driver `%s'\n", driver->driver.name); @@ -2022,10 +2031,14 @@ static int __init usba_udc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, udc); /* Make sure we start from a clean slate */ - clk_enable(pclk); + ret = clk_prepare_enable(pclk); + if (ret) { + dev_err(&pdev->dev, "Unable to enable pclk, aborting.\n"); + goto err_clk_enable; + } toggle_bias(0); usba_writel(udc, CTRL, USBA_DISABLE_MASK); - clk_disable(pclk); + clk_disable_unprepare(pclk); if (pdev->dev.of_node) udc->usba_ep = atmel_udc_of_init(pdev, udc); @@ -2081,6 +2094,7 @@ err_add_udc: free_irq(irq, udc); err_request_irq: err_alloc_ep: +err_clk_enable: iounmap(udc->fifo); err_map_fifo: iounmap(udc->regs); From fda7130354271b55eea50a4f58ea8540c9971295 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 23 Jul 2013 20:01:52 +0200 Subject: [PATCH 0977/3400] usb: phy: don't check resource with devm_ioremap_resource devm_ioremap_resource does sanity checks on the given resource. No need to duplicate this in the driver. Signed-off-by: Wolfram Sang Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-rcar-usb.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/usb/phy/phy-rcar-usb.c b/drivers/usb/phy/phy-rcar-usb.c index ae909408958d..deb7f97f37c7 100644 --- a/drivers/usb/phy/phy-rcar-usb.c +++ b/drivers/usb/phy/phy-rcar-usb.c @@ -190,11 +190,6 @@ static int rcar_usb_phy_probe(struct platform_device *pdev) } res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res0) { - dev_err(dev, "Not enough platform resources\n"); - return -EINVAL; - } - reg0 = devm_ioremap_resource(dev, res0); if (IS_ERR(reg0)) return PTR_ERR(reg0); From 7557a57f5e649c99239975529e2b30dc4990c548 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 22 Jul 2013 20:09:52 +0200 Subject: [PATCH 0978/3400] usb: musb: dsps: init / shutdown the phy If the init / shutdown function of the phy moves out of dsps into the phy driver, then dsps needs to call the callbacks of the phy driver to ensure that this happens. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_dsps.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 5233804d66b1..603ea747d882 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -428,6 +428,8 @@ static int dsps_musb_init(struct musb *musb) goto err0; } + usb_phy_init(musb->xceiv); + setup_timer(&glue->timer[pdev->id], otg_timer, (unsigned long) musb); /* Reset the musb */ @@ -463,6 +465,7 @@ static int dsps_musb_exit(struct musb *musb) /* Shutdown the on-chip PHY and its PLL. */ musb_dsps_phy_control(glue, pdev->id, 0); + usb_phy_shutdown(musb->xceiv); /* NOP driver needs change if supporting dual instance */ usb_put_phy(musb->xceiv); From e9eb2e08d93afc8f334ffe269fc84ea6257ff02c Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 22 Jul 2013 20:09:55 +0200 Subject: [PATCH 0979/3400] usb: musb: remove ti81xx pieces from musb ti81xx does not have a baseport mainline i.e. it should not boot. The amount of rework that is required makes it easier to simply remove that platform (i.e. that possible platform device) and add it later once it comes back with DT support. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_dsps.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 603ea747d882..55f5ff9351d6 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -46,9 +46,7 @@ #include "musb_core.h" -#ifdef CONFIG_OF static const struct of_device_id musb_dsps_of_match[]; -#endif /** * avoid using musb_readx()/musb_writex() as glue layer should not be @@ -753,23 +751,12 @@ static const struct dsps_musb_wrapper ti81xx_driver_data = { .instances = 1, }; -static const struct platform_device_id musb_dsps_id_table[] = { - { - .name = "musb-ti81xx", - .driver_data = (kernel_ulong_t) &ti81xx_driver_data, - }, - { }, /* Terminating Entry */ -}; -MODULE_DEVICE_TABLE(platform, musb_dsps_id_table); - -#ifdef CONFIG_OF static const struct of_device_id musb_dsps_of_match[] = { { .compatible = "ti,musb-am33xx", .data = (void *) &ti81xx_driver_data, }, { }, }; MODULE_DEVICE_TABLE(of, musb_dsps_of_match); -#endif static struct platform_driver dsps_usbss_driver = { .probe = dsps_probe, @@ -779,7 +766,6 @@ static struct platform_driver dsps_usbss_driver = { .pm = &dsps_pm_ops, .of_match_table = of_match_ptr(musb_dsps_of_match), }, - .id_table = musb_dsps_id_table, }; MODULE_DESCRIPTION("TI DSPS MUSB Glue Layer"); From 63c5b4ca7d0daadf11662d6419eb7a1c0ce42eb7 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 22 Jul 2013 20:10:04 +0200 Subject: [PATCH 0980/3400] usb: musb: do not change dev's dma_mask Commit 8d2421e ("usb: musb: kill global and static for multi instance") removed the global dma_mask copy and replaced by parent's DMA mask. The problem here is that if the parent does not have a dma_mask then musb_remove() goes kaboom. Instead trying to fix this I was thinking we do we need to erase dma_mask in the first place? Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_core.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 9b774e72c0e4..80ffd7ee55df 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1843,10 +1843,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) if (use_dma && dev->dma_mask) musb->dma_controller = dma_controller_create(musb, musb->mregs); - /* ideally this would be abstracted in platform setup */ - if (!musb->dma_controller) - dev->dma_mask = NULL; - /* be sure interrupts are disabled before connecting ISR */ musb_platform_disable(musb); musb_generic_disable(musb); @@ -1993,9 +1989,6 @@ static int musb_remove(struct platform_device *pdev) musb_free(musb); device_init_wakeup(dev, 0); -#ifndef CONFIG_MUSB_PIO_ONLY - dma_set_mask(dev, *dev->parent->dma_mask); -#endif return 0; } From c49667e56fcb5e92efcbe816c34c3e373b33cd01 Mon Sep 17 00:00:00 2001 From: Mikko Perttunen Date: Wed, 17 Jul 2013 09:31:00 +0300 Subject: [PATCH 0981/3400] arm: dts: tegra20: Rename USB UTMI parameters according to new definitions This patch changes the Tegra20 USB PHY nodes to use the UTMI configuration parameter names as specified in the device tree binding documentation after patch "ARM: tegra: finalize USB EHCI and PHY bindings". Signed-off-by: Mikko Perttunen Acked-by: Stephen Warren Reviewed-by: Stephen Warren Tested-by: Stephen Warren Signed-off-by: Felipe Balbi --- arch/arm/boot/dts/tegra20.dtsi | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi index 9653fd8288d2..e4570834512e 100644 --- a/arch/arm/boot/dts/tegra20.dtsi +++ b/arch/arm/boot/dts/tegra20.dtsi @@ -477,13 +477,13 @@ <&tegra_car TEGRA20_CLK_USBD>; clock-names = "reg", "pll_u", "timer", "utmi-pads"; nvidia,has-legacy-mode; - hssync_start_delay = <9>; - idle_wait_delay = <17>; - elastic_limit = <16>; - term_range_adj = <6>; - xcvr_setup = <9>; - xcvr_lsfslew = <1>; - xcvr_lsrslew = <1>; + nvidia,hssync-start-delay = <9>; + nvidia,idle-wait-delay = <17>; + nvidia,elastic-limit = <16>; + nvidia,term-range-adj = <6>; + nvidia,xcvr-setup = <9>; + nvidia,xcvr-lsfslew = <1>; + nvidia,xcvr-lsrslew = <1>; status = "disabled"; }; @@ -527,13 +527,13 @@ <&tegra_car TEGRA20_CLK_CLK_M>, <&tegra_car TEGRA20_CLK_USBD>; clock-names = "reg", "pll_u", "timer", "utmi-pads"; - hssync_start_delay = <9>; - idle_wait_delay = <17>; - elastic_limit = <16>; - term_range_adj = <6>; - xcvr_setup = <9>; - xcvr_lsfslew = <2>; - xcvr_lsrslew = <2>; + nvidia,hssync-start-delay = <9>; + nvidia,idle-wait-delay = <17>; + nvidia,elastic-limit = <16>; + nvidia,term-range-adj = <6>; + nvidia,xcvr-setup = <9>; + nvidia,xcvr-lsfslew = <2>; + nvidia,xcvr-lsrslew = <2>; status = "disabled"; }; From 81d5dfe6d8b3ba48ffcaa882783185c07b5d2384 Mon Sep 17 00:00:00 2001 From: Mikko Perttunen Date: Wed, 17 Jul 2013 09:31:01 +0300 Subject: [PATCH 0982/3400] usb: phy: tegra: Read UTMIP parameters from device tree UTMIP parameters used to be hardcoded into tables in the PHY driver. This patch reads them from the device tree instead in accordance with the phy-tegra-usb DT documentation. Signed-off-by: Mikko Perttunen Reviewed-by: Stephen Warren Tested-by: Stephen Warren Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-tegra-usb.c | 129 +++++++++++++++++++++----------- 1 file changed, 87 insertions(+), 42 deletions(-) diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c index cec0855ed248..3ecd49871b88 100644 --- a/drivers/usb/phy/phy-tegra-usb.c +++ b/drivers/usb/phy/phy-tegra-usb.c @@ -184,27 +184,6 @@ static const struct tegra_xtal_freq tegra_freq_table[] = { }, }; -static struct tegra_utmip_config utmip_default[] = { - [0] = { - .hssync_start_delay = 9, - .idle_wait_delay = 17, - .elastic_limit = 16, - .term_range_adj = 6, - .xcvr_setup = 9, - .xcvr_lsfslew = 1, - .xcvr_lsrslew = 1, - }, - [2] = { - .hssync_start_delay = 9, - .idle_wait_delay = 17, - .elastic_limit = 16, - .term_range_adj = 6, - .xcvr_setup = 9, - .xcvr_lsfslew = 2, - .xcvr_lsrslew = 2, - }, -}; - static void set_pts(struct tegra_usb_phy *phy, u8 pts_val) { void __iomem *base = phy->regs; @@ -703,13 +682,6 @@ static int tegra_usb_phy_init(struct tegra_usb_phy *phy) int i; int err; - if (!phy->is_ulpi_phy) { - if (phy->is_legacy_phy) - phy->config = &utmip_default[0]; - else - phy->config = &utmip_default[2]; - } - phy->pll_u = devm_clk_get(phy->dev, "pll_u"); if (IS_ERR(phy->pll_u)) { pr_err("Can't get pll_u clock\n"); @@ -784,6 +756,88 @@ void tegra_ehci_phy_restore_end(struct usb_phy *x) } EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_end); +static int read_utmi_param(struct platform_device *pdev, const char *param, + u8 *dest) +{ + u32 value; + int err = of_property_read_u32(pdev->dev.of_node, param, &value); + *dest = (u8)value; + if (err < 0) + dev_err(&pdev->dev, "Failed to read USB UTMI parameter %s: %d\n", + param, err); + return err; +} + +static int utmi_phy_probe(struct tegra_usb_phy *tegra_phy, + struct platform_device *pdev) +{ + struct resource *res; + int err; + struct tegra_utmip_config *config; + + tegra_phy->is_ulpi_phy = false; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!res) { + dev_err(&pdev->dev, "Failed to get UTMI Pad regs\n"); + return -ENXIO; + } + + tegra_phy->pad_regs = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); + if (!tegra_phy->regs) { + dev_err(&pdev->dev, "Failed to remap UTMI Pad regs\n"); + return -ENOMEM; + } + + tegra_phy->config = devm_kzalloc(&pdev->dev, + sizeof(*tegra_phy->config), GFP_KERNEL); + if (!tegra_phy->config) { + dev_err(&pdev->dev, + "unable to allocate memory for USB UTMIP config\n"); + return -ENOMEM; + } + + config = tegra_phy->config; + + err = read_utmi_param(pdev, "nvidia,hssync-start-delay", + &config->hssync_start_delay); + if (err < 0) + return err; + + err = read_utmi_param(pdev, "nvidia,elastic-limit", + &config->elastic_limit); + if (err < 0) + return err; + + err = read_utmi_param(pdev, "nvidia,idle-wait-delay", + &config->idle_wait_delay); + if (err < 0) + return err; + + err = read_utmi_param(pdev, "nvidia,term-range-adj", + &config->term_range_adj); + if (err < 0) + return err; + + err = read_utmi_param(pdev, "nvidia,xcvr-setup", + &config->xcvr_setup); + if (err < 0) + return err; + + err = read_utmi_param(pdev, "nvidia,xcvr-lsfslew", + &config->xcvr_lsfslew); + if (err < 0) + return err; + + err = read_utmi_param(pdev, "nvidia,xcvr-lsrslew", + &config->xcvr_lsrslew); + if (err < 0) + return err; + + return 0; +} + static int tegra_usb_phy_probe(struct platform_device *pdev) { struct resource *res; @@ -815,20 +869,9 @@ static int tegra_usb_phy_probe(struct platform_device *pdev) err = of_property_match_string(np, "phy_type", "ulpi"); if (err < 0) { - tegra_phy->is_ulpi_phy = false; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (!res) { - dev_err(&pdev->dev, "Failed to get UTMI Pad regs\n"); - return -ENXIO; - } - - tegra_phy->pad_regs = devm_ioremap(&pdev->dev, res->start, - resource_size(res)); - if (!tegra_phy->regs) { - dev_err(&pdev->dev, "Failed to remap UTMI Pad regs\n"); - return -ENOMEM; - } + err = utmi_phy_probe(tegra_phy, pdev); + if (err < 0) + return err; } else { tegra_phy->is_ulpi_phy = true; @@ -839,6 +882,8 @@ static int tegra_usb_phy_probe(struct platform_device *pdev) tegra_phy->reset_gpio); return tegra_phy->reset_gpio; } + + tegra_phy->config = NULL; } err = of_property_match_string(np, "dr_mode", "otg"); From f5b8c8b6d3b4697f28b818d8784e3e4b2a290022 Mon Sep 17 00:00:00 2001 From: Mikko Perttunen Date: Wed, 17 Jul 2013 10:37:49 +0300 Subject: [PATCH 0983/3400] usb: tegra: Use regulators instead of GPIOs for USB PHY VBUS The tegra ehci driver has enabled USB vbus regulators directly using GPIOs and the device tree attribute nvidia,vbus-gpio. This is ugly and causes error messages on boot when both the regulator driver and the ehci driver want access to the same GPIO. After this patch, usb vbus regulators for tegra usb phy devices are specified with the device tree attribute vbus-supply = <&x> where x is a regulator defined in the device tree. The old nvidia,vbus-gpio property is no longer supported. Signed-off-by: Mikko Perttunen Reviewed-by: Stephen Warren Tested-by: Stephen Warren Signed-off-by: Felipe Balbi --- drivers/usb/host/ehci-tegra.c | 34 +------------------------------ drivers/usb/phy/phy-tegra-usb.c | 24 ++++++++++++++++++++++ include/linux/usb/tegra_usb_phy.h | 1 + 3 files changed, 26 insertions(+), 33 deletions(-) diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index 6ee7ef79b4f8..14c1f35a4b10 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -322,33 +322,6 @@ static void tegra_ehci_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) free_dma_aligned_buffer(urb); } -static int setup_vbus_gpio(struct platform_device *pdev, - struct tegra_ehci_platform_data *pdata) -{ - int err = 0; - int gpio; - - gpio = pdata->vbus_gpio; - if (!gpio_is_valid(gpio)) - gpio = of_get_named_gpio(pdev->dev.of_node, - "nvidia,vbus-gpio", 0); - if (!gpio_is_valid(gpio)) - return 0; - - err = gpio_request(gpio, "vbus_gpio"); - if (err) { - dev_err(&pdev->dev, "can't request vbus gpio %d", gpio); - return err; - } - err = gpio_direction_output(gpio, 1); - if (err) { - dev_err(&pdev->dev, "can't enable vbus\n"); - return err; - } - - return err; -} - static int tegra_ehci_probe(struct platform_device *pdev) { struct resource *res; @@ -376,14 +349,11 @@ static int tegra_ehci_probe(struct platform_device *pdev) if (!pdev->dev.coherent_dma_mask) pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); - setup_vbus_gpio(pdev, pdata); - hcd = usb_create_hcd(&tegra_ehci_hc_driver, &pdev->dev, dev_name(&pdev->dev)); if (!hcd) { dev_err(&pdev->dev, "Unable to create HCD\n"); - err = -ENOMEM; - goto cleanup_vbus_gpio; + return -ENOMEM; } platform_set_drvdata(pdev, hcd); ehci = hcd_to_ehci(hcd); @@ -494,8 +464,6 @@ cleanup_clk_get: clk_put(tegra->clk); cleanup_hcd_create: usb_put_hcd(hcd); -cleanup_vbus_gpio: - /* FIXME: Undo setup_vbus_gpio() here */ return err; } diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c index 3ecd49871b88..d92a63a5b0c9 100644 --- a/drivers/usb/phy/phy-tegra-usb.c +++ b/drivers/usb/phy/phy-tegra-usb.c @@ -34,6 +34,7 @@ #include #include #include +#include #define ULPI_VIEWPORT 0x170 @@ -613,6 +614,9 @@ static void tegra_usb_phy_close(struct usb_phy *x) { struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy); + if (!IS_ERR(phy->vbus)) + regulator_disable(phy->vbus); + clk_disable_unprepare(phy->pll_u); } @@ -705,6 +709,16 @@ static int tegra_usb_phy_init(struct tegra_usb_phy *phy) goto fail; } + if (!IS_ERR(phy->vbus)) { + err = regulator_enable(phy->vbus); + if (err) { + dev_err(phy->dev, + "failed to enable usb vbus regulator: %d\n", + err); + goto fail; + } + } + if (phy->is_ulpi_phy) err = ulpi_open(phy); else @@ -896,6 +910,16 @@ static int tegra_usb_phy_probe(struct platform_device *pdev) } else tegra_phy->mode = TEGRA_USB_PHY_MODE_OTG; + /* On some boards, the VBUS regulator doesn't need to be controlled */ + if (of_find_property(np, "vbus-supply", NULL)) { + tegra_phy->vbus = devm_regulator_get(&pdev->dev, "vbus"); + if (IS_ERR(tegra_phy->vbus)) + return PTR_ERR(tegra_phy->vbus); + } else { + dev_notice(&pdev->dev, "no vbus regulator"); + tegra_phy->vbus = ERR_PTR(-ENODEV); + } + tegra_phy->dev = &pdev->dev; err = tegra_usb_phy_init(tegra_phy); if (err < 0) diff --git a/include/linux/usb/tegra_usb_phy.h b/include/linux/usb/tegra_usb_phy.h index d2ca919a5b73..2b5fa947980a 100644 --- a/include/linux/usb/tegra_usb_phy.h +++ b/include/linux/usb/tegra_usb_phy.h @@ -55,6 +55,7 @@ struct tegra_usb_phy { struct clk *clk; struct clk *pll_u; struct clk *pad_clk; + struct regulator *vbus; enum tegra_usb_phy_mode mode; void *config; struct usb_phy *ulpi; From 80bd8a94712a0a9f2baeb03ad0546dd70f27ac4e Mon Sep 17 00:00:00 2001 From: Mikko Perttunen Date: Wed, 17 Jul 2013 10:37:50 +0300 Subject: [PATCH 0984/3400] usb: tegra: Add vbus-supply property for host mode PHYs Document vbus-supply as an optional property for host mode phy-tegra-usb PHYs. Signed-off-by: Mikko Perttunen Reviewed-by: Stephen Warren Tested-by: Stephen Warren Signed-off-by: Felipe Balbi --- .../devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt b/Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt index c4c9e9e664aa..59c48542abb9 100644 --- a/Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt +++ b/Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt @@ -48,5 +48,5 @@ Optional properties: peripheral means it is device controller otg means it can operate as either ("on the go") -Required properties for dr_mode == otg: +VBUS control (required for dr_mode == host, optional for dr_mode == otg): - vbus-supply: regulator for VBUS From 103566e40d0a57b028a51671d852b2650947a5ec Mon Sep 17 00:00:00 2001 From: Mikko Perttunen Date: Wed, 17 Jul 2013 10:37:51 +0300 Subject: [PATCH 0985/3400] arm: tegra: Remove obsolete nvidia,vbus-gpio properties USB VBUS regulators are now specified with the vbus-supply property instead of nvidia,vbus-gpio, so remove the obsolete properties. The equivalent vbus-supply properties were already added in patch "ARM: tegra: update device trees for USB binding rework". Signed-off-by: Mikko Perttunen Acked-by: Stephen Warren Reviewed-by: Stephen Warren Tested-by: Stephen Warren Signed-off-by: Felipe Balbi --- arch/arm/boot/dts/tegra20-seaboard.dts | 1 - arch/arm/boot/dts/tegra20-trimslice.dts | 1 - arch/arm/boot/dts/tegra20-whistler.dts | 2 -- 3 files changed, 4 deletions(-) diff --git a/arch/arm/boot/dts/tegra20-seaboard.dts b/arch/arm/boot/dts/tegra20-seaboard.dts index 365760b33a26..52526c9a1329 100644 --- a/arch/arm/boot/dts/tegra20-seaboard.dts +++ b/arch/arm/boot/dts/tegra20-seaboard.dts @@ -566,7 +566,6 @@ usb@c5000000 { status = "okay"; - nvidia,vbus-gpio = <&gpio TEGRA_GPIO(D, 0) GPIO_ACTIVE_HIGH>; dr_mode = "otg"; }; diff --git a/arch/arm/boot/dts/tegra20-trimslice.dts b/arch/arm/boot/dts/tegra20-trimslice.dts index ed4b901b0227..3e57b87cc75f 100644 --- a/arch/arm/boot/dts/tegra20-trimslice.dts +++ b/arch/arm/boot/dts/tegra20-trimslice.dts @@ -312,7 +312,6 @@ usb@c5000000 { status = "okay"; - nvidia,vbus-gpio = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_HIGH>; }; usb-phy@c5000000 { diff --git a/arch/arm/boot/dts/tegra20-whistler.dts b/arch/arm/boot/dts/tegra20-whistler.dts index ab67c94db280..a6b1b5bdf288 100644 --- a/arch/arm/boot/dts/tegra20-whistler.dts +++ b/arch/arm/boot/dts/tegra20-whistler.dts @@ -509,7 +509,6 @@ usb@c5000000 { status = "okay"; - nvidia,vbus-gpio = <&tca6416 0 GPIO_ACTIVE_HIGH>; }; usb-phy@c5000000 { @@ -519,7 +518,6 @@ usb@c5008000 { status = "okay"; - nvidia,vbus-gpio = <&tca6416 1 GPIO_ACTIVE_HIGH>; }; usb-phy@c5008000 { From 185d0fd570c121c0c3d4527842a097e50e3e7a79 Mon Sep 17 00:00:00 2001 From: Tuomas Tynkkynen Date: Thu, 25 Jul 2013 21:38:01 +0300 Subject: [PATCH 0986/3400] usb: phy: tegra: Remove unnecessary 'dev' field struct usb_phy already has a field for the device pointer, so this unnecessary field can be removed. Signed-off-by: Tuomas Tynkkynen Reviewed-by: Stephen Warren Tested-by: Stephen Warren Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-tegra-usb.c | 27 +++++++++++++++------------ include/linux/usb/tegra_usb_phy.h | 1 - 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c index d92a63a5b0c9..311fe03f16e1 100644 --- a/drivers/usb/phy/phy-tegra-usb.c +++ b/drivers/usb/phy/phy-tegra-usb.c @@ -211,7 +211,7 @@ static void set_phcd(struct tegra_usb_phy *phy, bool enable) static int utmip_pad_open(struct tegra_usb_phy *phy) { - phy->pad_clk = devm_clk_get(phy->dev, "utmi-pads"); + phy->pad_clk = devm_clk_get(phy->u_phy.dev, "utmi-pads"); if (IS_ERR(phy->pad_clk)) { pr_err("%s: can't get utmip pad clock\n", __func__); return PTR_ERR(phy->pad_clk); @@ -540,13 +540,15 @@ static int ulpi_phy_power_on(struct tegra_usb_phy *phy) ret = gpio_direction_output(phy->reset_gpio, 0); if (ret < 0) { - dev_err(phy->dev, "gpio %d not set to 0\n", phy->reset_gpio); + dev_err(phy->u_phy.dev, "gpio %d not set to 0\n", + phy->reset_gpio); return ret; } msleep(5); ret = gpio_direction_output(phy->reset_gpio, 1); if (ret < 0) { - dev_err(phy->dev, "gpio %d not set to 1\n", phy->reset_gpio); + dev_err(phy->u_phy.dev, "gpio %d not set to 1\n", + phy->reset_gpio); return ret; } @@ -649,29 +651,30 @@ static int ulpi_open(struct tegra_usb_phy *phy) { int err; - phy->clk = devm_clk_get(phy->dev, "ulpi-link"); + phy->clk = devm_clk_get(phy->u_phy.dev, "ulpi-link"); if (IS_ERR(phy->clk)) { pr_err("%s: can't get ulpi clock\n", __func__); return PTR_ERR(phy->clk); } - err = devm_gpio_request(phy->dev, phy->reset_gpio, "ulpi_phy_reset_b"); + err = devm_gpio_request(phy->u_phy.dev, phy->reset_gpio, + "ulpi_phy_reset_b"); if (err < 0) { - dev_err(phy->dev, "request failed for gpio: %d\n", + dev_err(phy->u_phy.dev, "request failed for gpio: %d\n", phy->reset_gpio); return err; } err = gpio_direction_output(phy->reset_gpio, 0); if (err < 0) { - dev_err(phy->dev, "gpio %d direction not set to output\n", + dev_err(phy->u_phy.dev, "gpio %d direction not set to output\n", phy->reset_gpio); return err; } phy->ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, 0); if (!phy->ulpi) { - dev_err(phy->dev, "otg_ulpi_create returned NULL\n"); + dev_err(phy->u_phy.dev, "otg_ulpi_create returned NULL\n"); err = -ENOMEM; return err; } @@ -686,7 +689,7 @@ static int tegra_usb_phy_init(struct tegra_usb_phy *phy) int i; int err; - phy->pll_u = devm_clk_get(phy->dev, "pll_u"); + phy->pll_u = devm_clk_get(phy->u_phy.dev, "pll_u"); if (IS_ERR(phy->pll_u)) { pr_err("Can't get pll_u clock\n"); return PTR_ERR(phy->pll_u); @@ -712,7 +715,7 @@ static int tegra_usb_phy_init(struct tegra_usb_phy *phy) if (!IS_ERR(phy->vbus)) { err = regulator_enable(phy->vbus); if (err) { - dev_err(phy->dev, + dev_err(phy->u_phy.dev, "failed to enable usb vbus regulator: %d\n", err); goto fail; @@ -920,7 +923,7 @@ static int tegra_usb_phy_probe(struct platform_device *pdev) tegra_phy->vbus = ERR_PTR(-ENODEV); } - tegra_phy->dev = &pdev->dev; + tegra_phy->u_phy.dev = &pdev->dev; err = tegra_usb_phy_init(tegra_phy); if (err < 0) return err; @@ -953,7 +956,7 @@ static int tegra_usb_phy_match(struct device *dev, void *data) struct tegra_usb_phy *tegra_phy = dev_get_drvdata(dev); struct device_node *dn = data; - return (tegra_phy->dev->of_node == dn) ? 1 : 0; + return (tegra_phy->u_phy.dev->of_node == dn) ? 1 : 0; } struct usb_phy *tegra_usb_get_phy(struct device_node *dn) diff --git a/include/linux/usb/tegra_usb_phy.h b/include/linux/usb/tegra_usb_phy.h index 2b5fa947980a..c2bc7106aaa8 100644 --- a/include/linux/usb/tegra_usb_phy.h +++ b/include/linux/usb/tegra_usb_phy.h @@ -60,7 +60,6 @@ struct tegra_usb_phy { void *config; struct usb_phy *ulpi; struct usb_phy u_phy; - struct device *dev; bool is_legacy_phy; bool is_ulpi_phy; int reset_gpio; From de3f233703080bfbbd5861d27660db7a2e476238 Mon Sep 17 00:00:00 2001 From: Tuomas Tynkkynen Date: Thu, 25 Jul 2013 21:38:02 +0300 Subject: [PATCH 0987/3400] usb: host: tegra: Remove leftover code ehci-tegra calls devm_usb_get_phy, which will never succeed since the Tegra PHY does not register itself with the PHY subsystem. It is also completely redundant since the code has already located a PHY via an internal API. Call otg_set_host unconditionally to simplify the code since it should be safe to do so. Signed-off-by: Tuomas Tynkkynen Reviewed-by: Stephen Warren Tested-by: Stephen Warren Signed-off-by: Felipe Balbi --- drivers/usb/host/ehci-tegra.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index 14c1f35a4b10..06e8febdcc2c 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -58,7 +58,6 @@ static int (*orig_hub_control)(struct usb_hcd *hcd, struct tegra_ehci_hcd { struct tegra_usb_phy *phy; struct clk *clk; - struct usb_phy *transceiver; int port_resuming; bool needs_double_reset; enum tegra_usb_phy_port_speed port_speed; @@ -436,26 +435,18 @@ static int tegra_ehci_probe(struct platform_device *pdev) goto cleanup_phy; } - if (pdata->operating_mode == TEGRA_USB_OTG) { - tegra->transceiver = - devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); - if (!IS_ERR(tegra->transceiver)) - otg_set_host(tegra->transceiver->otg, &hcd->self); - } else { - tegra->transceiver = ERR_PTR(-ENODEV); - } + otg_set_host(u_phy->otg, &hcd->self); err = usb_add_hcd(hcd, irq, IRQF_SHARED); if (err) { dev_err(&pdev->dev, "Failed to add USB HCD\n"); - goto cleanup_transceiver; + goto cleanup_otg_set_host; } return err; -cleanup_transceiver: - if (!IS_ERR(tegra->transceiver)) - otg_set_host(tegra->transceiver->otg, NULL); +cleanup_otg_set_host: + otg_set_host(u_phy->otg, NULL); cleanup_phy: usb_phy_shutdown(hcd->phy); cleanup_clk_en: @@ -473,8 +464,7 @@ static int tegra_ehci_remove(struct platform_device *pdev) struct tegra_ehci_hcd *tegra = (struct tegra_ehci_hcd *)hcd_to_ehci(hcd)->priv; - if (!IS_ERR(tegra->transceiver)) - otg_set_host(tegra->transceiver->otg, NULL); + otg_set_host(hcd->phy->otg, NULL); usb_phy_shutdown(hcd->phy); usb_remove_hcd(hcd); From d506427945089ced99cfbc5f53dd5adc5d34a5cd Mon Sep 17 00:00:00 2001 From: Tuomas Tynkkynen Date: Thu, 25 Jul 2013 21:38:03 +0300 Subject: [PATCH 0988/3400] usb: tegra: host: Remove references to plat data Platform data is not used in tegra-ehci anymore, so remove all references to it. Signed-off-by: Tuomas Tynkkynen Reviewed-by: Stephen Warren Tested-by: Stephen Warren Signed-off-by: Felipe Balbi --- drivers/usb/host/ehci-tegra.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index 06e8febdcc2c..a208cea4e4c7 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -327,18 +326,11 @@ static int tegra_ehci_probe(struct platform_device *pdev) struct usb_hcd *hcd; struct ehci_hcd *ehci; struct tegra_ehci_hcd *tegra; - struct tegra_ehci_platform_data *pdata; int err = 0; int irq; struct device_node *np_phy; struct usb_phy *u_phy; - pdata = pdev->dev.platform_data; - if (!pdata) { - dev_err(&pdev->dev, "Platform data missing\n"); - return -EINVAL; - } - /* Right now device-tree probed devices don't get dma_mask set. * Since shared usb code relies on it, set it here for now. * Once we have dma capability bindings this can go away. From 5fed6828318119656e243c4f0a11955cefc8eebd Mon Sep 17 00:00:00 2001 From: Tuomas Tynkkynen Date: Thu, 25 Jul 2013 21:38:04 +0300 Subject: [PATCH 0989/3400] ARM: tegra: Remove USB platform data USB-related platform data is not used anymore in the Tegra USB drivers, so remove all of it. Signed-off-by: Tuomas Tynkkynen Reviewed-by: Stephen Warren Tested-by: Stephen Warren Acked-by: Stephen Warren Signed-off-by: Felipe Balbi --- arch/arm/mach-tegra/tegra.c | 38 +------------------------ include/linux/platform_data/tegra_usb.h | 32 --------------------- include/linux/usb/tegra_usb_phy.h | 5 ---- 3 files changed, 1 insertion(+), 74 deletions(-) delete mode 100644 include/linux/platform_data/tegra_usb.h diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c index 0d1e4128d460..fc97cfd52769 100644 --- a/arch/arm/mach-tegra/tegra.c +++ b/arch/arm/mach-tegra/tegra.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -46,40 +45,6 @@ #include "fuse.h" #include "iomap.h" -static struct tegra_ehci_platform_data tegra_ehci1_pdata = { - .operating_mode = TEGRA_USB_OTG, - .power_down_on_bus_suspend = 1, - .vbus_gpio = -1, -}; - -static struct tegra_ulpi_config tegra_ehci2_ulpi_phy_config = { - .reset_gpio = -1, - .clk = "cdev2", -}; - -static struct tegra_ehci_platform_data tegra_ehci2_pdata = { - .phy_config = &tegra_ehci2_ulpi_phy_config, - .operating_mode = TEGRA_USB_HOST, - .power_down_on_bus_suspend = 1, - .vbus_gpio = -1, -}; - -static struct tegra_ehci_platform_data tegra_ehci3_pdata = { - .operating_mode = TEGRA_USB_HOST, - .power_down_on_bus_suspend = 1, - .vbus_gpio = -1, -}; - -static struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = { - OF_DEV_AUXDATA("nvidia,tegra20-ehci", 0xC5000000, "tegra-ehci.0", - &tegra_ehci1_pdata), - OF_DEV_AUXDATA("nvidia,tegra20-ehci", 0xC5004000, "tegra-ehci.1", - &tegra_ehci2_pdata), - OF_DEV_AUXDATA("nvidia,tegra20-ehci", 0xC5008000, "tegra-ehci.2", - &tegra_ehci3_pdata), - {} -}; - static void __init tegra_dt_init(void) { struct soc_device_attribute *soc_dev_attr; @@ -112,8 +77,7 @@ static void __init tegra_dt_init(void) * devices */ out: - of_platform_populate(NULL, of_default_bus_match_table, - tegra20_auxdata_lookup, parent); + of_platform_populate(NULL, of_default_bus_match_table, NULL, parent); } static void __init trimslice_init(void) diff --git a/include/linux/platform_data/tegra_usb.h b/include/linux/platform_data/tegra_usb.h deleted file mode 100644 index 66c673fef408..000000000000 --- a/include/linux/platform_data/tegra_usb.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2010 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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. - * - */ - -#ifndef _TEGRA_USB_H_ -#define _TEGRA_USB_H_ - -enum tegra_usb_operating_modes { - TEGRA_USB_DEVICE, - TEGRA_USB_HOST, - TEGRA_USB_OTG, -}; - -struct tegra_ehci_platform_data { - enum tegra_usb_operating_modes operating_mode; - /* power down the phy on bus suspend */ - int power_down_on_bus_suspend; - void *phy_config; - int vbus_gpio; -}; - -#endif /* _TEGRA_USB_H_ */ diff --git a/include/linux/usb/tegra_usb_phy.h b/include/linux/usb/tegra_usb_phy.h index c2bc7106aaa8..847415313ad2 100644 --- a/include/linux/usb/tegra_usb_phy.h +++ b/include/linux/usb/tegra_usb_phy.h @@ -28,11 +28,6 @@ struct tegra_utmip_config { u8 xcvr_lsrslew; }; -struct tegra_ulpi_config { - int reset_gpio; - const char *clk; -}; - enum tegra_usb_phy_port_speed { TEGRA_USB_PHY_PORT_SPEED_FULL = 0, TEGRA_USB_PHY_PORT_SPEED_LOW, From 0ee5b4ab79b6be1400f3fa47142e927ddc33a5bd Mon Sep 17 00:00:00 2001 From: Tuomas Tynkkynen Date: Thu, 25 Jul 2013 21:38:05 +0300 Subject: [PATCH 0990/3400] usb: phy: tegra: Register as an USB PHY. Register the Tegra PHY device instances with the PHY subsystem so that the Tegra EHCI driver can locate a PHY via the standard APIs. Signed-off-by: Tuomas Tynkkynen Reviewed-by: Stephen Warren Tested-by: Stephen Warren Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-tegra-usb.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c index 311fe03f16e1..441c306c050f 100644 --- a/drivers/usb/phy/phy-tegra-usb.c +++ b/drivers/usb/phy/phy-tegra-usb.c @@ -932,6 +932,22 @@ static int tegra_usb_phy_probe(struct platform_device *pdev) tegra_phy->u_phy.set_suspend = tegra_usb_phy_suspend; dev_set_drvdata(&pdev->dev, tegra_phy); + + err = usb_add_phy_dev(&tegra_phy->u_phy); + if (err < 0) { + tegra_usb_phy_close(&tegra_phy->u_phy); + return err; + } + + return 0; +} + +static int tegra_usb_phy_remove(struct platform_device *pdev) +{ + struct tegra_usb_phy *tegra_phy = platform_get_drvdata(pdev); + + usb_remove_phy(&tegra_phy->u_phy); + return 0; } @@ -943,6 +959,7 @@ MODULE_DEVICE_TABLE(of, tegra_usb_phy_id_table); static struct platform_driver tegra_usb_phy_driver = { .probe = tegra_usb_phy_probe, + .remove = tegra_usb_phy_remove, .driver = { .name = "tegra-phy", .owner = THIS_MODULE, From 7db71a9a6707284f3d9075fff2ad674f6a51c359 Mon Sep 17 00:00:00 2001 From: Tuomas Tynkkynen Date: Thu, 25 Jul 2013 21:38:06 +0300 Subject: [PATCH 0991/3400] usb: host: tegra: Locate a PHY via standard API Use devm_get_phy_by_phandle to get a PHY device instead of the custom Tegra functions. Signed-off-by: Tuomas Tynkkynen Reviewed-by: Stephen Warren Tested-by: Stephen Warren Signed-off-by: Felipe Balbi --- drivers/usb/host/ehci-tegra.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index a208cea4e4c7..db8031fd5c13 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -328,7 +328,6 @@ static int tegra_ehci_probe(struct platform_device *pdev) struct tegra_ehci_hcd *tegra; int err = 0; int irq; - struct device_node *np_phy; struct usb_phy *u_phy; /* Right now device-tree probed devices don't get dma_mask set. @@ -367,13 +366,7 @@ static int tegra_ehci_probe(struct platform_device *pdev) udelay(1); tegra_periph_reset_deassert(tegra->clk); - np_phy = of_parse_phandle(pdev->dev.of_node, "nvidia,phy", 0); - if (!np_phy) { - err = -ENODEV; - goto cleanup_clk_en; - } - - u_phy = tegra_usb_get_phy(np_phy); + u_phy = devm_usb_get_phy_by_phandle(&pdev->dev, "nvidia,phy", 0); if (IS_ERR(u_phy)) { err = PTR_ERR(u_phy); goto cleanup_clk_en; From 3b102e8bc0e49d417c7d376af857537080335dbf Mon Sep 17 00:00:00 2001 From: Tuomas Tynkkynen Date: Thu, 25 Jul 2013 21:38:07 +0300 Subject: [PATCH 0992/3400] usb: phy: tegra: Remove custom PHY locating APIs The Tegra EHCI driver is no longer using these custom functions, so they can be removed. Signed-off-by: Tuomas Tynkkynen Reviewed-by: Stephen Warren Tested-by: Stephen Warren Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-tegra-usb.c | 24 ------------------------ include/linux/usb/tegra_usb_phy.h | 2 -- 2 files changed, 26 deletions(-) diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c index 441c306c050f..fb5bc8cea680 100644 --- a/drivers/usb/phy/phy-tegra-usb.c +++ b/drivers/usb/phy/phy-tegra-usb.c @@ -968,29 +968,5 @@ static struct platform_driver tegra_usb_phy_driver = { }; module_platform_driver(tegra_usb_phy_driver); -static int tegra_usb_phy_match(struct device *dev, void *data) -{ - struct tegra_usb_phy *tegra_phy = dev_get_drvdata(dev); - struct device_node *dn = data; - - return (tegra_phy->u_phy.dev->of_node == dn) ? 1 : 0; -} - -struct usb_phy *tegra_usb_get_phy(struct device_node *dn) -{ - struct device *dev; - struct tegra_usb_phy *tegra_phy; - - dev = driver_find_device(&tegra_usb_phy_driver.driver, NULL, dn, - tegra_usb_phy_match); - if (!dev) - return ERR_PTR(-EPROBE_DEFER); - - tegra_phy = dev_get_drvdata(dev); - - return &tegra_phy->u_phy; -} -EXPORT_SYMBOL_GPL(tegra_usb_get_phy); - MODULE_DESCRIPTION("Tegra USB PHY driver"); MODULE_LICENSE("GPL v2"); diff --git a/include/linux/usb/tegra_usb_phy.h b/include/linux/usb/tegra_usb_phy.h index 847415313ad2..a095c98184d0 100644 --- a/include/linux/usb/tegra_usb_phy.h +++ b/include/linux/usb/tegra_usb_phy.h @@ -60,8 +60,6 @@ struct tegra_usb_phy { int reset_gpio; }; -struct usb_phy *tegra_usb_get_phy(struct device_node *dn); - void tegra_usb_phy_preresume(struct usb_phy *phy); void tegra_usb_phy_postresume(struct usb_phy *phy); From 9fdb07f72088ab5fc7bd6fd6f070fac53d636bd9 Mon Sep 17 00:00:00 2001 From: Tuomas Tynkkynen Date: Thu, 25 Jul 2013 21:38:08 +0300 Subject: [PATCH 0993/3400] usb: phy: tegra: Use DT helpers for phy_type Use the new of_usb_get_phy_mode helper function for parsing phy_type from the device tree. Signed-off-by: Tuomas Tynkkynen Reviewed-by: Stephen Warren Tested-by: Stephen Warren Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-tegra-usb.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c index fb5bc8cea680..fb469f1e8d10 100644 --- a/drivers/usb/phy/phy-tegra-usb.c +++ b/drivers/usb/phy/phy-tegra-usb.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -860,6 +861,7 @@ static int tegra_usb_phy_probe(struct platform_device *pdev) struct resource *res; struct tegra_usb_phy *tegra_phy = NULL; struct device_node *np = pdev->dev.of_node; + enum usb_phy_interface phy_type; int err; tegra_phy = devm_kzalloc(&pdev->dev, sizeof(*tegra_phy), GFP_KERNEL); @@ -884,12 +886,12 @@ static int tegra_usb_phy_probe(struct platform_device *pdev) tegra_phy->is_legacy_phy = of_property_read_bool(np, "nvidia,has-legacy-mode"); - err = of_property_match_string(np, "phy_type", "ulpi"); - if (err < 0) { + phy_type = of_usb_get_phy_mode(np); + if (phy_type == USBPHY_INTERFACE_MODE_UTMI) { err = utmi_phy_probe(tegra_phy, pdev); if (err < 0) return err; - } else { + } else if (phy_type == USBPHY_INTERFACE_MODE_ULPI) { tegra_phy->is_ulpi_phy = true; tegra_phy->reset_gpio = @@ -899,8 +901,10 @@ static int tegra_usb_phy_probe(struct platform_device *pdev) tegra_phy->reset_gpio); return tegra_phy->reset_gpio; } - tegra_phy->config = NULL; + } else { + dev_err(&pdev->dev, "phy_type is invalid or unsupported\n"); + return -EINVAL; } err = of_property_match_string(np, "dr_mode", "otg"); From 6558d7edbe069df1220b525362d4aa854a65a8bc Mon Sep 17 00:00:00 2001 From: Tuomas Tynkkynen Date: Thu, 25 Jul 2013 21:38:09 +0300 Subject: [PATCH 0994/3400] usb: phy: tegra: Use DT helpers for dr_mode Use the new of_usb_get_dr_mode helper function for parsing dr_mode from the device tree. Also replace the usage of the custom tegra_usb_phy_mode enum with the standard enum. Signed-off-by: Tuomas Tynkkynen Reviewed-by: Stephen Warren Tested-by: Stephen Warren Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-tegra-usb.c | 24 ++++++++++++------------ include/linux/usb/tegra_usb_phy.h | 8 +------- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c index fb469f1e8d10..01c30ff8874e 100644 --- a/drivers/usb/phy/phy-tegra-usb.c +++ b/drivers/usb/phy/phy-tegra-usb.c @@ -377,7 +377,7 @@ static int utmi_phy_power_on(struct tegra_usb_phy *phy) UTMIP_PLLU_ENABLE_DLY_COUNT(phy->freq->enable_delay); writel(val, base + UTMIP_PLL_CFG1); - if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) { + if (phy->mode == USB_DR_MODE_PERIPHERAL) { val = readl(base + USB_SUSP_CTRL); val &= ~(USB_WAKE_ON_CNNT_EN_DEV | USB_WAKE_ON_DISCON_EN_DEV); writel(val, base + USB_SUSP_CTRL); @@ -412,7 +412,7 @@ static int utmi_phy_power_on(struct tegra_usb_phy *phy) if (phy->is_legacy_phy) { val = readl(base + UTMIP_SPARE_CFG0); - if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) + if (phy->mode == USB_DR_MODE_PERIPHERAL) val &= ~FUSE_SETUP_SEL; else val |= FUSE_SETUP_SEL; @@ -453,7 +453,7 @@ static int utmi_phy_power_off(struct tegra_usb_phy *phy) utmi_phy_clk_disable(phy); - if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) { + if (phy->mode == USB_DR_MODE_PERIPHERAL) { val = readl(base + USB_SUSP_CTRL); val &= ~USB_WAKEUP_DEBOUNCE_COUNT(~0); val |= USB_WAKE_ON_CNNT_EN_DEV | USB_WAKEUP_DEBOUNCE_COUNT(5); @@ -907,15 +907,15 @@ static int tegra_usb_phy_probe(struct platform_device *pdev) return -EINVAL; } - err = of_property_match_string(np, "dr_mode", "otg"); - if (err < 0) { - err = of_property_match_string(np, "dr_mode", "peripheral"); - if (err < 0) - tegra_phy->mode = TEGRA_USB_PHY_MODE_HOST; - else - tegra_phy->mode = TEGRA_USB_PHY_MODE_DEVICE; - } else - tegra_phy->mode = TEGRA_USB_PHY_MODE_OTG; + if (of_find_property(np, "dr_mode", NULL)) + tegra_phy->mode = of_usb_get_dr_mode(np); + else + tegra_phy->mode = USB_DR_MODE_HOST; + + if (tegra_phy->mode == USB_DR_MODE_UNKNOWN) { + dev_err(&pdev->dev, "dr_mode is invalid\n"); + return -EINVAL; + } /* On some boards, the VBUS regulator doesn't need to be controlled */ if (of_find_property(np, "vbus-supply", NULL)) { diff --git a/include/linux/usb/tegra_usb_phy.h b/include/linux/usb/tegra_usb_phy.h index a095c98184d0..d3db274610a1 100644 --- a/include/linux/usb/tegra_usb_phy.h +++ b/include/linux/usb/tegra_usb_phy.h @@ -34,12 +34,6 @@ enum tegra_usb_phy_port_speed { TEGRA_USB_PHY_PORT_SPEED_HIGH, }; -enum tegra_usb_phy_mode { - TEGRA_USB_PHY_MODE_DEVICE, - TEGRA_USB_PHY_MODE_HOST, - TEGRA_USB_PHY_MODE_OTG, -}; - struct tegra_xtal_freq; struct tegra_usb_phy { @@ -51,7 +45,7 @@ struct tegra_usb_phy { struct clk *pll_u; struct clk *pad_clk; struct regulator *vbus; - enum tegra_usb_phy_mode mode; + enum usb_dr_mode mode; void *config; struct usb_phy *ulpi; struct usb_phy u_phy; From fa7b4ca50f03b6e71665ccef66ca000311353fc8 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 26 Jul 2013 11:11:37 +0200 Subject: [PATCH 0995/3400] usb: musb: dsps: rename ti81xx_driver_data to am33xx_driver_data The ti81xx platform is not fully supported right now. This patch renames the date structure to a am33xx prefix which is actually used. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_dsps.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 55f5ff9351d6..aba2dc58938d 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -720,7 +720,7 @@ static int dsps_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(dsps_pm_ops, dsps_suspend, dsps_resume); -static const struct dsps_musb_wrapper ti81xx_driver_data = { +static const struct dsps_musb_wrapper am33xx_driver_data = { .revision = 0x00, .control = 0x14, .status = 0x18, @@ -753,7 +753,7 @@ static const struct dsps_musb_wrapper ti81xx_driver_data = { static const struct of_device_id musb_dsps_of_match[] = { { .compatible = "ti,musb-am33xx", - .data = (void *) &ti81xx_driver_data, }, + .data = (void *) &am33xx_driver_data, }, { }, }; MODULE_DEVICE_TABLE(of, musb_dsps_of_match); From 9be73bae70ac5b0149daa243eeae2bdacd970574 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 26 Jul 2013 11:11:38 +0200 Subject: [PATCH 0996/3400] usb: musb: dsps: remove EOI access The EOI register is not present in the AM335x memory space according to the TRM and thus removed. Should any platform using the EOI register get merged then it may be used again if the register address is not zero. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi --- drivers/usb/musb/musb_dsps.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index aba2dc58938d..23f511f7df6d 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -73,7 +73,6 @@ struct dsps_musb_wrapper { u16 revision; u16 control; u16 status; - u16 eoi; u16 epintr_set; u16 epintr_clear; u16 epintr_status; @@ -203,7 +202,6 @@ static void dsps_musb_disable(struct musb *musb) dsps_writel(reg_base, wrp->epintr_clear, wrp->txep_bitmap | wrp->rxep_bitmap); dsps_writeb(musb->mregs, MUSB_DEVCTL, 0); - dsps_writel(reg_base, wrp->eoi, 0); } static void otg_timer(unsigned long _musb) @@ -317,7 +315,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci) /* Get usb core interrupts */ usbintr = dsps_readl(reg_base, wrp->coreintr_status); if (!usbintr && !epintr) - goto eoi; + goto out; musb->int_usb = (usbintr & wrp->usb_bitmap) >> wrp->usb_shift; if (usbintr) @@ -385,16 +383,11 @@ static irqreturn_t dsps_interrupt(int irq, void *hci) if (musb->int_tx || musb->int_rx || musb->int_usb) ret |= musb_interrupt(musb); - eoi: - /* EOI needs to be written for the IRQ to be re-asserted. */ - if (ret == IRQ_HANDLED || epintr || usbintr) - dsps_writel(reg_base, wrp->eoi, 1); - /* Poll for ID change */ if (musb->xceiv->state == OTG_STATE_B_IDLE) mod_timer(&glue->timer[pdev->id], jiffies + wrp->poll_seconds * HZ); - +out: spin_unlock_irqrestore(&musb->lock, flags); return ret; @@ -443,9 +436,6 @@ static int dsps_musb_init(struct musb *musb) val &= ~(1 << wrp->otg_disable); dsps_writel(musb->ctrl_base, wrp->phy_utmi, val); - /* clear level interrupt */ - dsps_writel(reg_base, wrp->eoi, 0); - return 0; err0: usb_put_phy(musb->xceiv); @@ -724,7 +714,6 @@ static const struct dsps_musb_wrapper am33xx_driver_data = { .revision = 0x00, .control = 0x14, .status = 0x18, - .eoi = 0x24, .epintr_set = 0x38, .epintr_clear = 0x40, .epintr_status = 0x30, From 27743e0bfdb227617017d14dcc7fa64f34d48671 Mon Sep 17 00:00:00 2001 From: Niels de Vos Date: Mon, 29 Jul 2013 09:38:05 +0200 Subject: [PATCH 0997/3400] spi/imx: expose module alias for loading from device-tree Enable auto loading by udev when spi-imx is compiled as a module. Signed-off-by: Niels de Vos Signed-off-by: Mark Brown --- drivers/spi/spi-imx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 81c7dd2228f9..15323d8bd9cf 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -619,6 +619,7 @@ static const struct of_device_id spi_imx_dt_ids[] = { { .compatible = "fsl,imx51-ecspi", .data = &imx51_ecspi_devtype_data, }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, spi_imx_dt_ids); static void spi_imx_chipselect(struct spi_device *spi, int is_active) { From 1729ce3441ad849e63403fa4347fa86e052559a5 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 28 Jul 2013 14:38:06 +0100 Subject: [PATCH 0998/3400] spi/orion: Convert to devm_ioremap_resource() Signed-off-by: Mark Brown Acked-by: Andrew Lunn --- drivers/spi/spi-orion.c | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c index 5d90bebaa0fa..551bea774fd8 100644 --- a/drivers/spi/spi-orion.c +++ b/drivers/spi/spi-orion.c @@ -446,30 +446,22 @@ static int orion_spi_probe(struct platform_device *pdev) spi->min_speed = DIV_ROUND_UP(tclk_hz, 30); r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (r == NULL) { - status = -ENODEV; + spi->base = devm_ioremap_resource(&pdev->dev, r); + if (IS_ERR(spi->base)) { + status = PTR_ERR(spi->base); goto out_rel_clk; } - if (!request_mem_region(r->start, resource_size(r), - dev_name(&pdev->dev))) { - status = -EBUSY; - goto out_rel_clk; - } - spi->base = ioremap(r->start, SZ_1K); - if (orion_spi_reset(spi) < 0) - goto out_rel_mem; + goto out_rel_clk; master->dev.of_node = pdev->dev.of_node; status = spi_register_master(master); if (status < 0) - goto out_rel_mem; + goto out_rel_clk; return status; -out_rel_mem: - release_mem_region(r->start, resource_size(r)); out_rel_clk: clk_disable_unprepare(spi->clk); clk_put(spi->clk); @@ -482,7 +474,6 @@ out: static int orion_spi_remove(struct platform_device *pdev) { struct spi_master *master; - struct resource *r; struct orion_spi *spi; master = platform_get_drvdata(pdev); @@ -491,9 +482,6 @@ static int orion_spi_remove(struct platform_device *pdev) clk_disable_unprepare(spi->clk); clk_put(spi->clk); - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(r->start, resource_size(r)); - spi_unregister_master(master); return 0; From 2e04cc41a6d7a561568f3802b61d0987f1ec7e9a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 29 Jul 2013 15:38:58 +0800 Subject: [PATCH 0999/3400] regulator: pfuze100: Use regulator_map_voltage_ascend All table based voltage list have ascendant order. Use regulator_map_voltage_ascend for them. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/pfuze100-regulator.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c index 6eb5586e6fa4..7b24acb66a18 100644 --- a/drivers/regulator/pfuze100-regulator.c +++ b/drivers/regulator/pfuze100-regulator.c @@ -144,6 +144,7 @@ static struct regulator_ops pfuze100_sw_regulator_ops = { static struct regulator_ops pfuze100_swb_regulator_ops = { .list_voltage = regulator_list_voltage_table, + .map_voltage = regulator_map_voltage_ascend, .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, From a554aea67aaadb7f3396b2a8f940ab0b915b2a5e Mon Sep 17 00:00:00 2001 From: Tuomas Tynkkynen Date: Thu, 25 Jul 2013 22:24:09 +0300 Subject: [PATCH 1000/3400] usb: phy: tegra: Use switch instead of if-else Use switch() instead of if-else when checking for the PHY type. Signed-off-by: Tuomas Tynkkynen Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-tegra-usb.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c index 01c30ff8874e..49fa2da56c4b 100644 --- a/drivers/usb/phy/phy-tegra-usb.c +++ b/drivers/usb/phy/phy-tegra-usb.c @@ -887,11 +887,14 @@ static int tegra_usb_phy_probe(struct platform_device *pdev) of_property_read_bool(np, "nvidia,has-legacy-mode"); phy_type = of_usb_get_phy_mode(np); - if (phy_type == USBPHY_INTERFACE_MODE_UTMI) { + switch (phy_type) { + case USBPHY_INTERFACE_MODE_UTMI: err = utmi_phy_probe(tegra_phy, pdev); if (err < 0) return err; - } else if (phy_type == USBPHY_INTERFACE_MODE_ULPI) { + break; + + case USBPHY_INTERFACE_MODE_ULPI: tegra_phy->is_ulpi_phy = true; tegra_phy->reset_gpio = @@ -902,7 +905,9 @@ static int tegra_usb_phy_probe(struct platform_device *pdev) return tegra_phy->reset_gpio; } tegra_phy->config = NULL; - } else { + break; + + default: dev_err(&pdev->dev, "phy_type is invalid or unsupported\n"); return -EINVAL; } From 2e112345c22bcdf5d246db40f0587d7d11f1dc61 Mon Sep 17 00:00:00 2001 From: "Ivan T. Ivanov" Date: Mon, 29 Jul 2013 10:27:02 +0300 Subject: [PATCH 1001/3400] usb: dwc3: core: modify IO memory resource after deferred probe completes When deferred probe happens driver will try to ioremap multiple times and will fail. Memory resource.start variable is a global variable, modifications in this field will be accumulated on every probe. Fix this by moving the above operations after driver hold all required PHY's. Signed-off-by: Ivan T. Ivanov Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index dfbc1f0fc0e3..da0a4b8b33ed 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -384,21 +384,6 @@ static int dwc3_probe(struct platform_device *pdev) dev_err(dev, "missing memory resource\n"); return -ENODEV; } - dwc->xhci_resources[0].start = res->start; - dwc->xhci_resources[0].end = dwc->xhci_resources[0].start + - DWC3_XHCI_REGS_END; - dwc->xhci_resources[0].flags = res->flags; - dwc->xhci_resources[0].name = res->name; - - res->start += DWC3_GLOBALS_REGS_START; - - /* - * Request memory region but exclude xHCI regs, - * since it will be requested by the xhci-plat driver. - */ - regs = devm_ioremap_resource(dev, res); - if (IS_ERR(regs)) - return PTR_ERR(regs); if (node) { dwc->maximum_speed = of_usb_get_maximum_speed(node); @@ -452,6 +437,22 @@ static int dwc3_probe(struct platform_device *pdev) return -EPROBE_DEFER; } + dwc->xhci_resources[0].start = res->start; + dwc->xhci_resources[0].end = dwc->xhci_resources[0].start + + DWC3_XHCI_REGS_END; + dwc->xhci_resources[0].flags = res->flags; + dwc->xhci_resources[0].name = res->name; + + res->start += DWC3_GLOBALS_REGS_START; + + /* + * Request memory region but exclude xHCI regs, + * since it will be requested by the xhci-plat driver. + */ + regs = devm_ioremap_resource(dev, res); + if (IS_ERR(regs)) + return PTR_ERR(regs); + usb_phy_set_suspend(dwc->usb2_phy, 0); usb_phy_set_suspend(dwc->usb3_phy, 0); From e8038ebbd51df65bf5f4728c190397041a42e903 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Mon, 29 Jul 2013 12:21:21 -0300 Subject: [PATCH 1002/3400] sata_mv: Remove unneeded forward declaration These forward declarations are no longer needed, and are probably historical left-over. Signed-off-by: Ezequiel Garcia Signed-off-by: Tejun Heo --- drivers/ata/sata_mv.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 35c6b6d09c27..10ea99a0192d 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -4428,9 +4428,6 @@ static int mv_pci_device_resume(struct pci_dev *pdev) #endif #endif -static int mv_platform_probe(struct platform_device *pdev); -static int mv_platform_remove(struct platform_device *pdev); - static int __init mv_init(void) { int rc = -ENODEV; From bb249aad82b93674281d8b76a0c9be2ba1d92d78 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 27 Jul 2013 12:21:52 +0100 Subject: [PATCH 1003/3400] spi/tegra114: Factor runtime PM out into transfer prepare/unprepare Currently the tegra114 driver acquires a runtime PM reference for the duration of each transfer. This may result in the IP being powered down between transfers which would be at best wasteful. Instead it is better to do this in the callbacks that are generated before and after starting a series of transfers, keeping the IP powered throughout. Signed-off-by: Mark Brown Acked-by: Laxman Dewangan --- drivers/spi/spi-tegra114.c | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index e8f542ab8935..d85882da8532 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -803,6 +803,20 @@ static int tegra_spi_setup(struct spi_device *spi) return 0; } +static int tegra_spi_prepare_transfer(struct spi_master *spi) +{ + struct tegra_spi_data *tspi = spi_master_get_devdata(spi); + int ret; + + ret = pm_runtime_get_sync(tspi->dev); + if (ret < 0) { + dev_err(tspi->dev, "runtime PM get failed: %d\n", ret); + return ret; + } + + return ret; +} + static int tegra_spi_transfer_one_message(struct spi_master *master, struct spi_message *msg) { @@ -816,14 +830,6 @@ static int tegra_spi_transfer_one_message(struct spi_master *master, msg->status = 0; msg->actual_length = 0; - ret = pm_runtime_get_sync(tspi->dev); - if (ret < 0) { - dev_err(tspi->dev, "runtime PM get failed: %d\n", ret); - msg->status = ret; - spi_finalize_current_message(master); - return ret; - } - single_xfer = list_is_singular(&msg->transfers); list_for_each_entry(xfer, &msg->transfers, transfer_list) { INIT_COMPLETION(tspi->xfer_completion); @@ -859,12 +865,20 @@ static int tegra_spi_transfer_one_message(struct spi_master *master, ret = 0; exit: tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1); - pm_runtime_put(tspi->dev); msg->status = ret; spi_finalize_current_message(master); return ret; } +static int tegra_spi_unprepare_transfer(struct spi_master *spi) +{ + struct tegra_spi_data *tspi = spi_master_get_devdata(spi); + + pm_runtime_put(tspi->dev); + + return 0; +} + static irqreturn_t handle_cpu_based_xfer(struct tegra_spi_data *tspi) { struct spi_transfer *t = tspi->curr_xfer; @@ -1050,7 +1064,9 @@ static int tegra_spi_probe(struct platform_device *pdev) /* the spi->mode bits understood by this driver: */ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; master->setup = tegra_spi_setup; + master->prepare_transfer_hardware = tegra_spi_prepare_transfer; master->transfer_one_message = tegra_spi_transfer_one_message; + master->unprepare_transfer_hardware = tegra_spi_unprepare_transfer; master->num_chipselect = MAX_CHIP_SELECT; master->bus_num = -1; From 9f178c22fb0e88f4e84f7a66be8326f63b91e7e3 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 27 Jul 2013 12:29:58 +0100 Subject: [PATCH 1004/3400] spi/tegra-sflash: Factor runtime PM out into transfer prepare/unprepare Currently the tegra sflash driver acquires a runtime PM reference for the duration of each transfer. This may result in the IP being powered down between transfers which would be at best wasteful. Instead it is better to do this in the callbacks that are generated before and after starting a series of transfers, keeping the IP powered throughout. Signed-off-by: Mark Brown Acked-by: Laxman Dewangan --- drivers/spi/spi-tegra20-sflash.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/drivers/spi/spi-tegra20-sflash.c b/drivers/spi/spi-tegra20-sflash.c index c1d5d95e70ea..f871c4ee6ad7 100644 --- a/drivers/spi/spi-tegra20-sflash.c +++ b/drivers/spi/spi-tegra20-sflash.c @@ -325,6 +325,20 @@ static int tegra_sflash_setup(struct spi_device *spi) return 0; } +static int tegra_sflash_prepare_transfer(struct spi_master *spi) +{ + struct tegra_sflash_data *tsd = spi_master_get_devdata(spi); + int ret; + + ret = pm_runtime_get_sync(tsd->dev); + if (ret < 0) { + dev_err(tsd->dev, "runtime PM get failed: %d\n", ret); + return ret; + } + + return ret; +} + static int tegra_sflash_transfer_one_message(struct spi_master *master, struct spi_message *msg) { @@ -335,12 +349,6 @@ static int tegra_sflash_transfer_one_message(struct spi_master *master, struct spi_device *spi = msg->spi; int ret; - ret = pm_runtime_get_sync(tsd->dev); - if (ret < 0) { - dev_err(tsd->dev, "pm_runtime_get() failed, err = %d\n", ret); - return ret; - } - msg->status = 0; msg->actual_length = 0; single_xfer = list_is_singular(&msg->transfers); @@ -380,10 +388,18 @@ exit: tegra_sflash_writel(tsd, tsd->def_command_reg, SPI_COMMAND); msg->status = ret; spi_finalize_current_message(master); - pm_runtime_put(tsd->dev); return ret; } +static int tegra_sflash_unprepare_transfer(struct spi_master *spi) +{ + struct tegra_sflash_data *tsd = spi_master_get_devdata(spi); + + pm_runtime_put(tsd->dev); + + return 0; +} + static irqreturn_t handle_cpu_based_xfer(struct tegra_sflash_data *tsd) { struct spi_transfer *t = tsd->curr_xfer; @@ -476,7 +492,9 @@ static int tegra_sflash_probe(struct platform_device *pdev) /* the spi->mode bits understood by this driver: */ master->mode_bits = SPI_CPOL | SPI_CPHA; master->setup = tegra_sflash_setup; + master->prepare_transfer_hardware = tegra_sflash_prepare_transfer; master->transfer_one_message = tegra_sflash_transfer_one_message; + master->unprepare_transfer_hardware = tegra_sflash_unprepare_transfer; master->num_chipselect = MAX_CHIP_SELECT; master->bus_num = -1; From bafe886936a8982f5780330c901889a37bba7d4c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 27 Jul 2013 12:34:24 +0100 Subject: [PATCH 1005/3400] spi/tegra-slink: Factor runtime PM out into transfer prepare/unprepare Currently the tegra slink driver acquires a runtime PM reference for the duration of each transfer. This may result in the IP being powered down between transfers which would be at best wasteful. Instead it is better to do this in the callbacks that are generated before and after starting a series of transfers, keeping the IP powered throughout. Signed-off-by: Mark Brown Acked-by: Laxman Dewangan --- drivers/spi/spi-tegra20-slink.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c index 80490cc11ce5..b2fb115df027 100644 --- a/drivers/spi/spi-tegra20-slink.c +++ b/drivers/spi/spi-tegra20-slink.c @@ -824,6 +824,20 @@ static int tegra_slink_setup(struct spi_device *spi) return 0; } +static int tegra_slink_prepare_transfer(struct spi_master *spi) +{ + struct tegra_slink_data *tspi = spi_master_get_devdata(spi); + int ret; + + ret = pm_runtime_get_sync(tspi->dev); + if (ret < 0) { + dev_err(tspi->dev, "runtime PM get failed: %d\n", ret); + return ret; + } + + return ret; +} + static int tegra_slink_transfer_one_message(struct spi_master *master, struct spi_message *msg) { @@ -836,11 +850,6 @@ static int tegra_slink_transfer_one_message(struct spi_master *master, msg->status = 0; msg->actual_length = 0; - ret = pm_runtime_get_sync(tspi->dev); - if (ret < 0) { - dev_err(tspi->dev, "runtime get failed: %d\n", ret); - goto done; - } single_xfer = list_is_singular(&msg->transfers); list_for_each_entry(xfer, &msg->transfers, transfer_list) { @@ -878,13 +887,20 @@ static int tegra_slink_transfer_one_message(struct spi_master *master, exit: tegra_slink_writel(tspi, tspi->def_command_reg, SLINK_COMMAND); tegra_slink_writel(tspi, tspi->def_command2_reg, SLINK_COMMAND2); - pm_runtime_put(tspi->dev); -done: msg->status = ret; spi_finalize_current_message(master); return ret; } +static int tegra_slink_unprepare_transfer(struct spi_master *spi) +{ + struct tegra_slink_data *tspi = spi_master_get_devdata(spi); + + pm_runtime_put(tspi->dev); + + return 0; +} + static irqreturn_t handle_cpu_based_xfer(struct tegra_slink_data *tspi) { struct spi_transfer *t = tspi->curr_xfer; @@ -1085,7 +1101,9 @@ static int tegra_slink_probe(struct platform_device *pdev) /* the spi->mode bits understood by this driver: */ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; master->setup = tegra_slink_setup; + master->prepare_transfer_hardware = tegra_slink_prepare_transfer; master->transfer_one_message = tegra_slink_transfer_one_message; + master->unprepare_transfer_hardware = tegra_slink_unprepare_transfer; master->num_chipselect = MAX_CHIP_SELECT; master->bus_num = -1; From 94eec0fc3520c759831763d866421b4d60b599b4 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Mon, 29 Jul 2013 12:12:56 -0400 Subject: [PATCH 1006/3400] ext4: fix retry handling in ext4_ext_truncate() We tested for ENOMEM instead of -ENOMEM. Oops. Signed-off-by: "Theodore Ts'o" Cc: stable@vger.kernel.org --- fs/ext4/extents.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index a61873808f76..72ba4705d4fa 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -4412,7 +4412,7 @@ void ext4_ext_truncate(handle_t *handle, struct inode *inode) retry: err = ext4_es_remove_extent(inode, last_block, EXT_MAX_BLOCKS - last_block); - if (err == ENOMEM) { + if (err == -ENOMEM) { cond_resched(); congestion_wait(BLK_RW_ASYNC, HZ/50); goto retry; From 71ab1d58c26eb7c30711caa95c173d5c39ab8855 Mon Sep 17 00:00:00 2001 From: Niels de Vos Date: Mon, 29 Jul 2013 09:38:38 +0200 Subject: [PATCH 1007/3400] pata_imx: expose module alias for loading from device-tree Enable auto loading by udev when pata_imx is compiled as a module. Signed-off-by: Niels de Vos Cc: Sascha Hauer Signed-off-by: Tejun Heo --- drivers/ata/pata_imx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/ata/pata_imx.c b/drivers/ata/pata_imx.c index 4ec7c04b3f82..26386f0b89a8 100644 --- a/drivers/ata/pata_imx.c +++ b/drivers/ata/pata_imx.c @@ -237,6 +237,7 @@ static const struct of_device_id imx_pata_dt_ids[] = { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, imx_pata_dt_ids); static struct platform_driver pata_imx_driver = { .probe = pata_imx_probe, From 44fb851dfb2f8e3462617e19a7b3b9025db9d919 Mon Sep 17 00:00:00 2001 From: Zheng Liu Date: Mon, 29 Jul 2013 12:51:42 -0400 Subject: [PATCH 1008/3400] ext4: add WARN_ON to check the length of allocated blocks In commit 921f266b: ext4: add self-testing infrastructure to do a sanity check, some sanity checks were added in map_blocks to make sure 'retval == map->m_len'. Enable these checks by default and report any assertion failures using ext4_warning() and WARN_ON() since they can help us to figure out some bugs that are otherwise hard to hit. Signed-off-by: Zheng Liu Signed-off-by: "Theodore Ts'o" --- fs/ext4/inode.c | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index ba33c67d6e48..dd32a2eacd0d 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -555,14 +555,13 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, int ret; unsigned long long status; -#ifdef ES_AGGRESSIVE_TEST - if (retval != map->m_len) { - printk("ES len assertion failed for inode: %lu " - "retval %d != map->m_len %d " - "in %s (lookup)\n", inode->i_ino, retval, - map->m_len, __func__); + if (unlikely(retval != map->m_len)) { + ext4_warning(inode->i_sb, + "ES len assertion failed for inode " + "%lu: retval %d != map->m_len %d", + inode->i_ino, retval, map->m_len); + WARN_ON(1); } -#endif status = map->m_flags & EXT4_MAP_UNWRITTEN ? EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN; @@ -656,14 +655,13 @@ found: int ret; unsigned long long status; -#ifdef ES_AGGRESSIVE_TEST - if (retval != map->m_len) { - printk("ES len assertion failed for inode: %lu " - "retval %d != map->m_len %d " - "in %s (allocation)\n", inode->i_ino, retval, - map->m_len, __func__); + if (unlikely(retval != map->m_len)) { + ext4_warning(inode->i_sb, + "ES len assertion failed for inode " + "%lu: retval %d != map->m_len %d", + inode->i_ino, retval, map->m_len); + WARN_ON(1); } -#endif /* * If the extent has been zeroed out, we don't need to update @@ -1637,14 +1635,13 @@ add_delayed: int ret; unsigned long long status; -#ifdef ES_AGGRESSIVE_TEST - if (retval != map->m_len) { - printk("ES len assertion failed for inode: %lu " - "retval %d != map->m_len %d " - "in %s (lookup)\n", inode->i_ino, retval, - map->m_len, __func__); + if (unlikely(retval != map->m_len)) { + ext4_warning(inode->i_sb, + "ES len assertion failed for inode " + "%lu: retval %d != map->m_len %d", + inode->i_ino, retval, map->m_len); + WARN_ON(1); } -#endif status = map->m_flags & EXT4_MAP_UNWRITTEN ? EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN; From 49834de234f3cf592c3d242c889ca603db8e7050 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 28 Jul 2013 14:47:02 +0100 Subject: [PATCH 1009/3400] spi: Provide core support for runtime PM during transfers Most SPI drivers that implement runtime PM support use identical code to do so: they acquire a runtime PM lock in prepare_transfer_hardware() and then they release it in unprepare_transfer_hardware(). The variations in this are mostly missing error checking and the choice to use autosuspend. Since these runtime PM calls are normally the only thing in the prepare and unprepare callbacks and the autosuspend API transparently does the right thing on devices with autosuspend disabled factor all of this out into the core with a flag to enable the behaviour. Signed-off-by: Mark Brown Reviewed-by: Stephen Warren Acked-by: Linus Walleij --- drivers/spi/spi.c | 16 ++++++++++++++++ include/linux/spi/spi.h | 5 +++++ 2 files changed, 21 insertions(+) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 978dda2c5239..361cced68069 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -553,6 +553,10 @@ static void spi_pump_messages(struct kthread_work *work) master->unprepare_transfer_hardware(master)) dev_err(&master->dev, "failed to unprepare transfer hardware\n"); + if (master->auto_runtime_pm) { + pm_runtime_mark_last_busy(master->dev.parent); + pm_runtime_put_autosuspend(master->dev.parent); + } return; } @@ -572,11 +576,23 @@ static void spi_pump_messages(struct kthread_work *work) master->busy = true; spin_unlock_irqrestore(&master->queue_lock, flags); + if (!was_busy && master->auto_runtime_pm) { + ret = pm_runtime_get_sync(master->dev.parent); + if (ret < 0) { + dev_err(&master->dev, "Failed to power device: %d\n", + ret); + return; + } + } + if (!was_busy && master->prepare_transfer_hardware) { ret = master->prepare_transfer_hardware(master); if (ret) { dev_err(&master->dev, "failed to prepare transfer hardware\n"); + + if (master->auto_runtime_pm) + pm_runtime_put(master->dev.parent); return; } } diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 28e440be1c07..bf0204c00053 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -254,6 +254,9 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) * @busy: message pump is busy * @running: message pump is running * @rt: whether this queue is set to run as a realtime task + * @auto_runtime_pm: the core should ensure a runtime PM reference is held + * while the hardware is prepared, using the parent + * device for the spidev * @prepare_transfer_hardware: a message will soon arrive from the queue * so the subsystem requests the driver to prepare the transfer hardware * by issuing this call @@ -374,11 +377,13 @@ struct spi_master { bool busy; bool running; bool rt; + bool auto_runtime_pm; int (*prepare_transfer_hardware)(struct spi_master *master); int (*transfer_one_message)(struct spi_master *master, struct spi_message *mesg); int (*unprepare_transfer_hardware)(struct spi_master *master); + /* gpio chip select */ int *cs_gpios; }; From 5355d96d6fb56507761f261a23c0831f67fa0e0f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 28 Jul 2013 15:34:06 +0100 Subject: [PATCH 1010/3400] spi/bcm63xx: Convert to core runtime PM Signed-off-by: Mark Brown --- drivers/spi/spi-bcm63xx.c | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index 9fd7a39b8029..4ac028d6b2d8 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c @@ -231,24 +231,6 @@ static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *first, return 0; } -static int bcm63xx_spi_prepare_transfer(struct spi_master *master) -{ - struct bcm63xx_spi *bs = spi_master_get_devdata(master); - - pm_runtime_get_sync(&bs->pdev->dev); - - return 0; -} - -static int bcm63xx_spi_unprepare_transfer(struct spi_master *master) -{ - struct bcm63xx_spi *bs = spi_master_get_devdata(master); - - pm_runtime_put(&bs->pdev->dev); - - return 0; -} - static int bcm63xx_spi_transfer_one(struct spi_master *master, struct spi_message *m) { @@ -412,11 +394,10 @@ static int bcm63xx_spi_probe(struct platform_device *pdev) master->bus_num = pdata->bus_num; master->num_chipselect = pdata->num_chipselect; - master->prepare_transfer_hardware = bcm63xx_spi_prepare_transfer; - master->unprepare_transfer_hardware = bcm63xx_spi_unprepare_transfer; master->transfer_one_message = bcm63xx_spi_transfer_one; master->mode_bits = MODEBITS; master->bits_per_word_mask = SPI_BPW_MASK(8); + master->auto_runtime_pm = true; bs->msg_type_shift = pdata->msg_type_shift; bs->msg_ctl_width = pdata->msg_ctl_width; bs->tx_io = (u8 *)(bs->regs + bcm63xx_spireg(SPI_MSG_DATA)); From 3f36e80ab9325bff1e0d4ab72f0efba679bc212f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 28 Jul 2013 15:34:21 +0100 Subject: [PATCH 1011/3400] spi/coldfire-qspi: Convert to core runtime PM Signed-off-by: Mark Brown --- drivers/spi/spi-coldfire-qspi.c | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/drivers/spi/spi-coldfire-qspi.c b/drivers/spi/spi-coldfire-qspi.c index 0631b9d4a5de..e4265eaf0548 100644 --- a/drivers/spi/spi-coldfire-qspi.c +++ b/drivers/spi/spi-coldfire-qspi.c @@ -354,24 +354,6 @@ static int mcfqspi_transfer_one_message(struct spi_master *master, } -static int mcfqspi_prepare_transfer_hw(struct spi_master *master) -{ - struct mcfqspi *mcfqspi = spi_master_get_devdata(master); - - pm_runtime_get_sync(mcfqspi->dev); - - return 0; -} - -static int mcfqspi_unprepare_transfer_hw(struct spi_master *master) -{ - struct mcfqspi *mcfqspi = spi_master_get_devdata(master); - - pm_runtime_put_sync(mcfqspi->dev); - - return 0; -} - static int mcfqspi_setup(struct spi_device *spi) { if (spi->chip_select >= spi->master->num_chipselect) { @@ -473,8 +455,7 @@ static int mcfqspi_probe(struct platform_device *pdev) master->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 16); master->setup = mcfqspi_setup; master->transfer_one_message = mcfqspi_transfer_one_message; - master->prepare_transfer_hardware = mcfqspi_prepare_transfer_hw; - master->unprepare_transfer_hardware = mcfqspi_unprepare_transfer_hw; + master->auto_runtime_pm = true; platform_set_drvdata(pdev, master); From f0278a1a40f895095201b08ff5d0168b8fbd26a5 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 28 Jul 2013 15:34:37 +0100 Subject: [PATCH 1012/3400] spi/omap2: Covert to core runtime PM Signed-off-by: Mark Brown Reviewed-by: Felipe Balbi --- drivers/spi/spi-omap2-mcspi.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 5994039758de..973c1cb42c9c 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -335,23 +335,6 @@ static void omap2_mcspi_restore_ctx(struct omap2_mcspi *mcspi) __raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0); } -static int omap2_prepare_transfer(struct spi_master *master) -{ - struct omap2_mcspi *mcspi = spi_master_get_devdata(master); - - pm_runtime_get_sync(mcspi->dev); - return 0; -} - -static int omap2_unprepare_transfer(struct spi_master *master) -{ - struct omap2_mcspi *mcspi = spi_master_get_devdata(master); - - pm_runtime_mark_last_busy(mcspi->dev); - pm_runtime_put_autosuspend(mcspi->dev); - return 0; -} - static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit) { unsigned long timeout; @@ -1318,8 +1301,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev) master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); master->setup = omap2_mcspi_setup; - master->prepare_transfer_hardware = omap2_prepare_transfer; - master->unprepare_transfer_hardware = omap2_unprepare_transfer; + master->auto_runtime_pm = true; master->transfer_one_message = omap2_mcspi_transfer_one_message; master->cleanup = omap2_mcspi_cleanup; master->dev.of_node = node; From 29b6e906a70a47c9cdd7406a8c20ef5098f0b4e8 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 28 Jul 2013 15:35:08 +0100 Subject: [PATCH 1013/3400] spi/pl022: Convert to core runtime PM Signed-off-by: Mark Brown Reviewed-by: Linus Walleij --- drivers/spi/spi-pl022.c | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index abef061fb84a..07e6db6c810f 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -1555,18 +1555,6 @@ static int pl022_transfer_one_message(struct spi_master *master, return 0; } -static int pl022_prepare_transfer_hardware(struct spi_master *master) -{ - struct pl022 *pl022 = spi_master_get_devdata(master); - - /* - * Just make sure we have all we need to run the transfer by syncing - * with the runtime PM framework. - */ - pm_runtime_get_sync(&pl022->adev->dev); - return 0; -} - static int pl022_unprepare_transfer_hardware(struct spi_master *master) { struct pl022 *pl022 = spi_master_get_devdata(master); @@ -1575,13 +1563,6 @@ static int pl022_unprepare_transfer_hardware(struct spi_master *master) writew((readw(SSP_CR1(pl022->virtbase)) & (~SSP_CR1_MASK_SSE)), SSP_CR1(pl022->virtbase)); - if (pl022->master_info->autosuspend_delay > 0) { - pm_runtime_mark_last_busy(&pl022->adev->dev); - pm_runtime_put_autosuspend(&pl022->adev->dev); - } else { - pm_runtime_put(&pl022->adev->dev); - } - return 0; } @@ -2139,7 +2120,7 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) master->num_chipselect = num_cs; master->cleanup = pl022_cleanup; master->setup = pl022_setup; - master->prepare_transfer_hardware = pl022_prepare_transfer_hardware; + master->auto_runtime_pm = true; master->transfer_one_message = pl022_transfer_one_message; master->unprepare_transfer_hardware = pl022_unprepare_transfer_hardware; master->rt = platform_info->rt; From 7dd62787334ac6e0e2a0ef3f20bb1936ac431b04 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 28 Jul 2013 15:35:21 +0100 Subject: [PATCH 1014/3400] spi/pxa2xx: Convert to core runtime PM Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index f440dcee852b..a8c85424eb8d 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -804,14 +804,6 @@ static int pxa2xx_spi_transfer_one_message(struct spi_master *master, return 0; } -static int pxa2xx_spi_prepare_transfer(struct spi_master *master) -{ - struct driver_data *drv_data = spi_master_get_devdata(master); - - pm_runtime_get_sync(&drv_data->pdev->dev); - return 0; -} - static int pxa2xx_spi_unprepare_transfer(struct spi_master *master) { struct driver_data *drv_data = spi_master_get_devdata(master); @@ -820,8 +812,6 @@ static int pxa2xx_spi_unprepare_transfer(struct spi_master *master) write_SSCR0(read_SSCR0(drv_data->ioaddr) & ~SSCR0_SSE, drv_data->ioaddr); - pm_runtime_mark_last_busy(&drv_data->pdev->dev); - pm_runtime_put_autosuspend(&drv_data->pdev->dev); return 0; } @@ -1134,8 +1124,8 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) master->cleanup = cleanup; master->setup = setup; master->transfer_one_message = pxa2xx_spi_transfer_one_message; - master->prepare_transfer_hardware = pxa2xx_spi_prepare_transfer; master->unprepare_transfer_hardware = pxa2xx_spi_unprepare_transfer; + master->auto_runtime_pm = true; drv_data->ssp_type = ssp->type; drv_data->null_dma_buf = (u32 *)PTR_ALIGN(&drv_data[1], DMA_ALIGNMENT); From 3e00a09d2fbd64f0ad98e7c8c29dbf9e038fc746 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 28 Jul 2013 15:35:36 +0100 Subject: [PATCH 1015/3400] spi/hspi: Convert to core runtime PM Signed-off-by: Mark Brown --- drivers/spi/spi-sh-hspi.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/drivers/spi/spi-sh-hspi.c b/drivers/spi/spi-sh-hspi.c index 716edf999538..b95d6a9fb80e 100644 --- a/drivers/spi/spi-sh-hspi.c +++ b/drivers/spi/spi-sh-hspi.c @@ -99,21 +99,6 @@ static int hspi_status_check_timeout(struct hspi_priv *hspi, u32 mask, u32 val) /* * spi master function */ -static int hspi_prepare_transfer(struct spi_master *master) -{ - struct hspi_priv *hspi = spi_master_get_devdata(master); - - pm_runtime_get_sync(hspi->dev); - return 0; -} - -static int hspi_unprepare_transfer(struct spi_master *master) -{ - struct hspi_priv *hspi = spi_master_get_devdata(master); - - pm_runtime_put_sync(hspi->dev); - return 0; -} #define hspi_hw_cs_enable(hspi) hspi_hw_cs_ctrl(hspi, 0) #define hspi_hw_cs_disable(hspi) hspi_hw_cs_ctrl(hspi, 1) @@ -316,9 +301,8 @@ static int hspi_probe(struct platform_device *pdev) master->setup = hspi_setup; master->cleanup = hspi_cleanup; master->mode_bits = SPI_CPOL | SPI_CPHA; - master->prepare_transfer_hardware = hspi_prepare_transfer; + master->auto_runtime_pm = true; master->transfer_one_message = hspi_transfer_one_message; - master->unprepare_transfer_hardware = hspi_unprepare_transfer; ret = spi_register_master(master); if (ret < 0) { dev_err(&pdev->dev, "spi_register_master error.\n"); From fc0f81b76a6e5c1f1c5e672420595347d846b2f9 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 28 Jul 2013 15:24:54 +0100 Subject: [PATCH 1016/3400] spi/s3c64xx: Use core for runtime PM Signed-off-by: Mark Brown --- drivers/spi/spi-s3c64xx.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 63e2070c6c14..a73d0a3a35df 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -356,8 +356,6 @@ static int s3c64xx_spi_prepare_transfer(struct spi_master *spi) while (!is_polling(sdd) && !acquire_dma(sdd)) usleep_range(10000, 11000); - pm_runtime_get_sync(&sdd->pdev->dev); - return 0; } @@ -372,7 +370,6 @@ static int s3c64xx_spi_unprepare_transfer(struct spi_master *spi) sdd->ops->release((enum dma_ch)sdd->tx_dma.ch, &s3c64xx_spi_dma_client); } - pm_runtime_put(&sdd->pdev->dev); return 0; } @@ -1395,6 +1392,7 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) SPI_BPW_MASK(8); /* the spi->mode bits understood by this driver: */ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; + master->auto_runtime_pm = true; sdd->regs = devm_ioremap_resource(&pdev->dev, mem_res); if (IS_ERR(sdd->regs)) { From 612aa5ced770b7ec02d37dd63fd4c7dd2f6e5f37 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 28 Jul 2013 15:37:31 +0100 Subject: [PATCH 1017/3400] spi/tegra114: Use core runtime PM Signed-off-by: Mark Brown Reviewed-by: Stephen Warren --- drivers/spi/spi-tegra114.c | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index d85882da8532..c14e30c8af2e 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -803,20 +803,6 @@ static int tegra_spi_setup(struct spi_device *spi) return 0; } -static int tegra_spi_prepare_transfer(struct spi_master *spi) -{ - struct tegra_spi_data *tspi = spi_master_get_devdata(spi); - int ret; - - ret = pm_runtime_get_sync(tspi->dev); - if (ret < 0) { - dev_err(tspi->dev, "runtime PM get failed: %d\n", ret); - return ret; - } - - return ret; -} - static int tegra_spi_transfer_one_message(struct spi_master *master, struct spi_message *msg) { @@ -870,15 +856,6 @@ exit: return ret; } -static int tegra_spi_unprepare_transfer(struct spi_master *spi) -{ - struct tegra_spi_data *tspi = spi_master_get_devdata(spi); - - pm_runtime_put(tspi->dev); - - return 0; -} - static irqreturn_t handle_cpu_based_xfer(struct tegra_spi_data *tspi) { struct spi_transfer *t = tspi->curr_xfer; @@ -1064,11 +1041,10 @@ static int tegra_spi_probe(struct platform_device *pdev) /* the spi->mode bits understood by this driver: */ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; master->setup = tegra_spi_setup; - master->prepare_transfer_hardware = tegra_spi_prepare_transfer; master->transfer_one_message = tegra_spi_transfer_one_message; - master->unprepare_transfer_hardware = tegra_spi_unprepare_transfer; master->num_chipselect = MAX_CHIP_SELECT; master->bus_num = -1; + master->auto_runtime_pm = true; tspi->master = master; tspi->dev = &pdev->dev; From 38315fd48d3de6e9a53b86dfd27684970cd092e9 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 28 Jul 2013 15:37:46 +0100 Subject: [PATCH 1018/3400] spi/tegra20-sflash: Use core runtime PM Signed-off-by: Mark Brown Reviewed-by: Stephen Warren --- drivers/spi/spi-tegra20-sflash.c | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/drivers/spi/spi-tegra20-sflash.c b/drivers/spi/spi-tegra20-sflash.c index f871c4ee6ad7..1d814dc6e000 100644 --- a/drivers/spi/spi-tegra20-sflash.c +++ b/drivers/spi/spi-tegra20-sflash.c @@ -325,20 +325,6 @@ static int tegra_sflash_setup(struct spi_device *spi) return 0; } -static int tegra_sflash_prepare_transfer(struct spi_master *spi) -{ - struct tegra_sflash_data *tsd = spi_master_get_devdata(spi); - int ret; - - ret = pm_runtime_get_sync(tsd->dev); - if (ret < 0) { - dev_err(tsd->dev, "runtime PM get failed: %d\n", ret); - return ret; - } - - return ret; -} - static int tegra_sflash_transfer_one_message(struct spi_master *master, struct spi_message *msg) { @@ -391,15 +377,6 @@ exit: return ret; } -static int tegra_sflash_unprepare_transfer(struct spi_master *spi) -{ - struct tegra_sflash_data *tsd = spi_master_get_devdata(spi); - - pm_runtime_put(tsd->dev); - - return 0; -} - static irqreturn_t handle_cpu_based_xfer(struct tegra_sflash_data *tsd) { struct spi_transfer *t = tsd->curr_xfer; @@ -492,9 +469,8 @@ static int tegra_sflash_probe(struct platform_device *pdev) /* the spi->mode bits understood by this driver: */ master->mode_bits = SPI_CPOL | SPI_CPHA; master->setup = tegra_sflash_setup; - master->prepare_transfer_hardware = tegra_sflash_prepare_transfer; master->transfer_one_message = tegra_sflash_transfer_one_message; - master->unprepare_transfer_hardware = tegra_sflash_unprepare_transfer; + master->auto_runtime_pm = true; master->num_chipselect = MAX_CHIP_SELECT; master->bus_num = -1; From ce74ac80d25bcb1bf5c6638cf376054c9b7c4b0b Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 28 Jul 2013 15:37:59 +0100 Subject: [PATCH 1019/3400] spi/tegra20-slink: Use core runtime PM Signed-off-by: Mark Brown Reviewed-by: Stephen Warren --- drivers/spi/spi-tegra20-slink.c | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c index b2fb115df027..c70353672a23 100644 --- a/drivers/spi/spi-tegra20-slink.c +++ b/drivers/spi/spi-tegra20-slink.c @@ -824,20 +824,6 @@ static int tegra_slink_setup(struct spi_device *spi) return 0; } -static int tegra_slink_prepare_transfer(struct spi_master *spi) -{ - struct tegra_slink_data *tspi = spi_master_get_devdata(spi); - int ret; - - ret = pm_runtime_get_sync(tspi->dev); - if (ret < 0) { - dev_err(tspi->dev, "runtime PM get failed: %d\n", ret); - return ret; - } - - return ret; -} - static int tegra_slink_transfer_one_message(struct spi_master *master, struct spi_message *msg) { @@ -892,15 +878,6 @@ exit: return ret; } -static int tegra_slink_unprepare_transfer(struct spi_master *spi) -{ - struct tegra_slink_data *tspi = spi_master_get_devdata(spi); - - pm_runtime_put(tspi->dev); - - return 0; -} - static irqreturn_t handle_cpu_based_xfer(struct tegra_slink_data *tspi) { struct spi_transfer *t = tspi->curr_xfer; @@ -1101,9 +1078,8 @@ static int tegra_slink_probe(struct platform_device *pdev) /* the spi->mode bits understood by this driver: */ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; master->setup = tegra_slink_setup; - master->prepare_transfer_hardware = tegra_slink_prepare_transfer; master->transfer_one_message = tegra_slink_transfer_one_message; - master->unprepare_transfer_hardware = tegra_slink_unprepare_transfer; + master->auto_runtime_pm = true; master->num_chipselect = MAX_CHIP_SELECT; master->bus_num = -1; From 9ad9d25a1ec82d6e52d687348e8cdd4942e7d393 Mon Sep 17 00:00:00 2001 From: Zhao Hongjiang Date: Sat, 27 Jul 2013 11:56:49 +0800 Subject: [PATCH 1020/3400] cpuset: get rid of the useless forward declaration of cpuset get rid of the useless forward declaration of the struct cpuset cause the below define it. Signed-off-by: Zhao Hongjiang Acked-by: Li Zefan Signed-off-by: Tejun Heo --- kernel/cpuset.c | 1 - 1 file changed, 1 deletion(-) diff --git a/kernel/cpuset.c b/kernel/cpuset.c index e5657788fedd..2ddd9b93feaa 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -70,7 +70,6 @@ int number_of_cpusets __read_mostly; /* Forward declare cgroup structures */ struct cgroup_subsys cpuset_subsys; -struct cpuset; /* See "Frequency meter" comments, below. */ From 0b9e6965add0701e5cbf56d5bab6d9181e948359 Mon Sep 17 00:00:00 2001 From: Zhao Hongjiang Date: Sat, 27 Jul 2013 11:56:53 +0800 Subject: [PATCH 1021/3400] cpuset: relocate a misplaced comment Comment for cpuset_css_offline() was on top of cpuset_css_free(). Move it. Signed-off-by: Zhao Hongjiang Acked-by: Li Zefan Signed-off-by: Tejun Heo --- kernel/cpuset.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 2ddd9b93feaa..703bfd5a32a9 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -2020,6 +2020,12 @@ out_unlock: return 0; } +/* + * If the cpuset being removed has its flag 'sched_load_balance' + * enabled, then simulate turning sched_load_balance off, which + * will call rebuild_sched_domains_locked(). + */ + static void cpuset_css_offline(struct cgroup *cgrp) { struct cpuset *cs = cgroup_cs(cgrp); @@ -2035,12 +2041,6 @@ static void cpuset_css_offline(struct cgroup *cgrp) mutex_unlock(&cpuset_mutex); } -/* - * If the cpuset being removed has its flag 'sched_load_balance' - * enabled, then simulate turning sched_load_balance off, which - * will call rebuild_sched_domains_locked(). - */ - static void cpuset_css_free(struct cgroup *cgrp) { struct cpuset *cs = cgroup_cs(cgrp); From 02f00c4a9183ebf15aa50e57391b0f44e2f092c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frank=20Sch=C3=A4fer?= Date: Mon, 29 Jul 2013 18:33:22 +0200 Subject: [PATCH 1022/3400] USB: serial: pl2303: fix the upper baud rate limit check for type_0/1 chips MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the following regression that has been introduced recently with commit b2d6d98fc7: With type_0 and type_1 chips - all baud rates < 1228800 baud are rounded up to 1228800 baud - the device silently runs at 9600 baud for all baud rates > 1228800 baud Signed-off-by: Frank Schäfer Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/pl2303.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 299a0ffcb165..1e6de4cd079d 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -303,7 +303,7 @@ static void pl2303_encode_baudrate(struct tty_struct *tty, /* type_0, type_1 only support up to 1228800 baud */ if (spriv->type != HX) - baud = max_t(int, baud, 1228800); + baud = min_t(int, baud, 1228800); if (baud <= 115200) { put_unaligned_le32(baud, buf); From 7d50195f6c5005d6ae7a789d9a7f0a94d104ee96 Mon Sep 17 00:00:00 2001 From: Feng-Hsin Chiang Date: Mon, 29 Jul 2013 16:48:32 +0000 Subject: [PATCH 1023/3400] usb: host: Faraday fotg210-hcd driver FOTG210 is an OTG controller which can be configured as an USB2.0 host. FOTG210 host is an ehci-like controller with some differences. First, register layout of FOTG210 is incompatible with EHCI. Furthermore, FOTG210 is lack of siTDs which means iTDs are used for both HS and FS ISO transfer. Signed-off-by: Feng-Hsin Chiang Signed-off-by: Greg Kroah-Hartman --- drivers/usb/Makefile | 1 + drivers/usb/host/Kconfig | 12 + drivers/usb/host/Makefile | 1 + drivers/usb/host/fotg210-hcd.c | 6049 ++++++++++++++++++++++++++++++++ drivers/usb/host/fotg210.h | 750 ++++ 5 files changed, 6813 insertions(+) create mode 100644 drivers/usb/host/fotg210-hcd.c create mode 100644 drivers/usb/host/fotg210.h diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index 238c5d47cadb..5460abf045de 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_USB_ISP1760_HCD) += host/ obj-$(CONFIG_USB_IMX21_HCD) += host/ obj-$(CONFIG_USB_FSL_MPH_DR_OF) += host/ obj-$(CONFIG_USB_FUSBH200_HCD) += host/ +obj-$(CONFIG_USB_FOTG210_HCD) += host/ obj-$(CONFIG_USB_C67X00_HCD) += c67x00/ diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 4263d011392c..cf521d6551dd 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -354,6 +354,18 @@ config USB_FUSBH200_HCD To compile this driver as a module, choose M here: the module will be called fusbh200-hcd. +config USB_FOTG210_HCD + tristate "FOTG210 HCD support" + depends on USB + default N + ---help--- + Faraday FOTG210 is an OTG controller which can be configured as + an USB2.0 host. It is designed to meet USB2.0 EHCI specification + with minor modification. + + To compile this driver as a module, choose M here: the + module will be called fotg210-hcd. + config USB_OHCI_HCD tristate "OHCI HCD (USB 1.1) support" select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index bea71127b15f..829a3397882a 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -58,3 +58,4 @@ obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o obj-$(CONFIG_USB_HCD_BCMA) += bcma-hcd.o obj-$(CONFIG_USB_HCD_SSB) += ssb-hcd.o obj-$(CONFIG_USB_FUSBH200_HCD) += fusbh200-hcd.o +obj-$(CONFIG_USB_FOTG210_HCD) += fotg210-hcd.o diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c new file mode 100644 index 000000000000..fce13bcc4a3e --- /dev/null +++ b/drivers/usb/host/fotg210-hcd.c @@ -0,0 +1,6049 @@ +/* + * Faraday FOTG210 EHCI-like driver + * + * Copyright (c) 2013 Faraday Technology Corporation + * + * Author: Yuan-Hsin Chen + * Feng-Hsin Chiang + * Po-Yu Chuang + * + * Most of code borrowed from the Linux-3.7 EHCI 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 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/*-------------------------------------------------------------------------*/ +#define DRIVER_AUTHOR "Yuan-Hsin Chen" +#define DRIVER_DESC "FOTG210 Host Controller (EHCI) Driver" + +static const char hcd_name[] = "fotg210_hcd"; + +#undef VERBOSE_DEBUG +#undef FOTG210_URB_TRACE + +#ifdef DEBUG +#define FOTG210_STATS +#endif + +/* magic numbers that can affect system performance */ +#define FOTG210_TUNE_CERR 3 /* 0-3 qtd retries; 0 == don't stop */ +#define FOTG210_TUNE_RL_HS 4 /* nak throttle; see 4.9 */ +#define FOTG210_TUNE_RL_TT 0 +#define FOTG210_TUNE_MULT_HS 1 /* 1-3 transactions/uframe; 4.10.3 */ +#define FOTG210_TUNE_MULT_TT 1 +/* + * Some drivers think it's safe to schedule isochronous transfers more than + * 256 ms into the future (partly as a result of an old bug in the scheduling + * code). In an attempt to avoid trouble, we will use a minimum scheduling + * length of 512 frames instead of 256. + */ +#define FOTG210_TUNE_FLS 1 /* (medium) 512-frame schedule */ + +/* Initial IRQ latency: faster than hw default */ +static int log2_irq_thresh; /* 0 to 6 */ +module_param(log2_irq_thresh, int, S_IRUGO); +MODULE_PARM_DESC(log2_irq_thresh, "log2 IRQ latency, 1-64 microframes"); + +/* initial park setting: slower than hw default */ +static unsigned park; +module_param(park, uint, S_IRUGO); +MODULE_PARM_DESC(park, "park setting; 1-3 back-to-back async packets"); + +/* for link power management(LPM) feature */ +static unsigned int hird; +module_param(hird, int, S_IRUGO); +MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us"); + +#define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT) + +#include "fotg210.h" + +/*-------------------------------------------------------------------------*/ + +#define fotg210_dbg(fotg210, fmt, args...) \ + dev_dbg(fotg210_to_hcd(fotg210)->self.controller , fmt , ## args) +#define fotg210_err(fotg210, fmt, args...) \ + dev_err(fotg210_to_hcd(fotg210)->self.controller , fmt , ## args) +#define fotg210_info(fotg210, fmt, args...) \ + dev_info(fotg210_to_hcd(fotg210)->self.controller , fmt , ## args) +#define fotg210_warn(fotg210, fmt, args...) \ + dev_warn(fotg210_to_hcd(fotg210)->self.controller , fmt , ## args) + +#ifdef VERBOSE_DEBUG +# define fotg210_vdbg fotg210_dbg +#else + static inline void fotg210_vdbg(struct fotg210_hcd *fotg210, ...) {} +#endif + +#ifdef DEBUG + +/* check the values in the HCSPARAMS register + * (host controller _Structural_ parameters) + * see EHCI spec, Table 2-4 for each value + */ +static void dbg_hcs_params(struct fotg210_hcd *fotg210, char *label) +{ + u32 params = fotg210_readl(fotg210, &fotg210->caps->hcs_params); + + fotg210_dbg(fotg210, + "%s hcs_params 0x%x ports=%d\n", + label, params, + HCS_N_PORTS(params) + ); +} +#else + +static inline void dbg_hcs_params(struct fotg210_hcd *fotg210, char *label) {} + +#endif + +#ifdef DEBUG + +/* check the values in the HCCPARAMS register + * (host controller _Capability_ parameters) + * see EHCI Spec, Table 2-5 for each value + * */ +static void dbg_hcc_params(struct fotg210_hcd *fotg210, char *label) +{ + u32 params = fotg210_readl(fotg210, &fotg210->caps->hcc_params); + + fotg210_dbg(fotg210, + "%s hcc_params %04x uframes %s%s\n", + label, + params, + HCC_PGM_FRAMELISTLEN(params) ? "256/512/1024" : "1024", + HCC_CANPARK(params) ? " park" : ""); +} +#else + +static inline void dbg_hcc_params(struct fotg210_hcd *fotg210, char *label) {} + +#endif + +#ifdef DEBUG + +static void __maybe_unused +dbg_qtd(const char *label, struct fotg210_hcd *fotg210, struct fotg210_qtd *qtd) +{ + fotg210_dbg(fotg210, "%s td %p n%08x %08x t%08x p0=%08x\n", label, qtd, + hc32_to_cpup(fotg210, &qtd->hw_next), + hc32_to_cpup(fotg210, &qtd->hw_alt_next), + hc32_to_cpup(fotg210, &qtd->hw_token), + hc32_to_cpup(fotg210, &qtd->hw_buf[0])); + if (qtd->hw_buf[1]) + fotg210_dbg(fotg210, " p1=%08x p2=%08x p3=%08x p4=%08x\n", + hc32_to_cpup(fotg210, &qtd->hw_buf[1]), + hc32_to_cpup(fotg210, &qtd->hw_buf[2]), + hc32_to_cpup(fotg210, &qtd->hw_buf[3]), + hc32_to_cpup(fotg210, &qtd->hw_buf[4])); +} + +static void __maybe_unused +dbg_qh(const char *label, struct fotg210_hcd *fotg210, struct fotg210_qh *qh) +{ + struct fotg210_qh_hw *hw = qh->hw; + + fotg210_dbg(fotg210, "%s qh %p n%08x info %x %x qtd %x\n", label, + qh, hw->hw_next, hw->hw_info1, hw->hw_info2, hw->hw_current); + dbg_qtd("overlay", fotg210, (struct fotg210_qtd *) &hw->hw_qtd_next); +} + +static void __maybe_unused +dbg_itd(const char *label, struct fotg210_hcd *fotg210, struct fotg210_itd *itd) +{ + fotg210_dbg(fotg210, "%s[%d] itd %p, next %08x, urb %p\n", + label, itd->frame, itd, hc32_to_cpu(fotg210, itd->hw_next), + itd->urb); + fotg210_dbg(fotg210, + " trans: %08x %08x %08x %08x %08x %08x %08x %08x\n", + hc32_to_cpu(fotg210, itd->hw_transaction[0]), + hc32_to_cpu(fotg210, itd->hw_transaction[1]), + hc32_to_cpu(fotg210, itd->hw_transaction[2]), + hc32_to_cpu(fotg210, itd->hw_transaction[3]), + hc32_to_cpu(fotg210, itd->hw_transaction[4]), + hc32_to_cpu(fotg210, itd->hw_transaction[5]), + hc32_to_cpu(fotg210, itd->hw_transaction[6]), + hc32_to_cpu(fotg210, itd->hw_transaction[7])); + fotg210_dbg(fotg210, + " buf: %08x %08x %08x %08x %08x %08x %08x\n", + hc32_to_cpu(fotg210, itd->hw_bufp[0]), + hc32_to_cpu(fotg210, itd->hw_bufp[1]), + hc32_to_cpu(fotg210, itd->hw_bufp[2]), + hc32_to_cpu(fotg210, itd->hw_bufp[3]), + hc32_to_cpu(fotg210, itd->hw_bufp[4]), + hc32_to_cpu(fotg210, itd->hw_bufp[5]), + hc32_to_cpu(fotg210, itd->hw_bufp[6])); + fotg210_dbg(fotg210, " index: %d %d %d %d %d %d %d %d\n", + itd->index[0], itd->index[1], itd->index[2], + itd->index[3], itd->index[4], itd->index[5], + itd->index[6], itd->index[7]); +} + +static int __maybe_unused +dbg_status_buf(char *buf, unsigned len, const char *label, u32 status) +{ + return scnprintf(buf, len, + "%s%sstatus %04x%s%s%s%s%s%s%s%s%s%s", + label, label[0] ? " " : "", status, + (status & STS_ASS) ? " Async" : "", + (status & STS_PSS) ? " Periodic" : "", + (status & STS_RECL) ? " Recl" : "", + (status & STS_HALT) ? " Halt" : "", + (status & STS_IAA) ? " IAA" : "", + (status & STS_FATAL) ? " FATAL" : "", + (status & STS_FLR) ? " FLR" : "", + (status & STS_PCD) ? " PCD" : "", + (status & STS_ERR) ? " ERR" : "", + (status & STS_INT) ? " INT" : "" + ); +} + +static int __maybe_unused +dbg_intr_buf(char *buf, unsigned len, const char *label, u32 enable) +{ + return scnprintf(buf, len, + "%s%sintrenable %02x%s%s%s%s%s%s", + label, label[0] ? " " : "", enable, + (enable & STS_IAA) ? " IAA" : "", + (enable & STS_FATAL) ? " FATAL" : "", + (enable & STS_FLR) ? " FLR" : "", + (enable & STS_PCD) ? " PCD" : "", + (enable & STS_ERR) ? " ERR" : "", + (enable & STS_INT) ? " INT" : "" + ); +} + +static const char *const fls_strings[] = { "1024", "512", "256", "??" }; + +static int +dbg_command_buf(char *buf, unsigned len, const char *label, u32 command) +{ + return scnprintf(buf, len, + "%s%scommand %07x %s=%d ithresh=%d%s%s%s " + "period=%s%s %s", + label, label[0] ? " " : "", command, + (command & CMD_PARK) ? " park" : "(park)", + CMD_PARK_CNT(command), + (command >> 16) & 0x3f, + (command & CMD_IAAD) ? " IAAD" : "", + (command & CMD_ASE) ? " Async" : "", + (command & CMD_PSE) ? " Periodic" : "", + fls_strings[(command >> 2) & 0x3], + (command & CMD_RESET) ? " Reset" : "", + (command & CMD_RUN) ? "RUN" : "HALT" + ); +} + +static int +dbg_port_buf(char *buf, unsigned len, const char *label, int port, u32 status) +{ + char *sig; + + /* signaling state */ + switch (status & (3 << 10)) { + case 0 << 10: + sig = "se0"; + break; + case 1 << 10: + sig = "k"; + break; /* low speed */ + case 2 << 10: + sig = "j"; + break; + default: + sig = "?"; + break; + } + + return scnprintf(buf, len, + "%s%sport:%d status %06x %d " + "sig=%s%s%s%s%s%s%s%s", + label, label[0] ? " " : "", port, status, + status>>25,/*device address */ + sig, + (status & PORT_RESET) ? " RESET" : "", + (status & PORT_SUSPEND) ? " SUSPEND" : "", + (status & PORT_RESUME) ? " RESUME" : "", + (status & PORT_PEC) ? " PEC" : "", + (status & PORT_PE) ? " PE" : "", + (status & PORT_CSC) ? " CSC" : "", + (status & PORT_CONNECT) ? " CONNECT" : ""); +} + +#else +static inline void __maybe_unused +dbg_qh(char *label, struct fotg210_hcd *fotg210, struct fotg210_qh *qh) +{} + +static inline int __maybe_unused +dbg_status_buf(char *buf, unsigned len, const char *label, u32 status) +{ return 0; } + +static inline int __maybe_unused +dbg_command_buf(char *buf, unsigned len, const char *label, u32 command) +{ return 0; } + +static inline int __maybe_unused +dbg_intr_buf(char *buf, unsigned len, const char *label, u32 enable) +{ return 0; } + +static inline int __maybe_unused +dbg_port_buf(char *buf, unsigned len, const char *label, int port, u32 status) +{ return 0; } + +#endif /* DEBUG */ + +/* functions have the "wrong" filename when they're output... */ +#define dbg_status(fotg210, label, status) { \ + char _buf[80]; \ + dbg_status_buf(_buf, sizeof(_buf), label, status); \ + fotg210_dbg(fotg210, "%s\n", _buf); \ +} + +#define dbg_cmd(fotg210, label, command) { \ + char _buf[80]; \ + dbg_command_buf(_buf, sizeof(_buf), label, command); \ + fotg210_dbg(fotg210, "%s\n", _buf); \ +} + +#define dbg_port(fotg210, label, port, status) { \ + char _buf[80]; \ + dbg_port_buf(_buf, sizeof(_buf), label, port, status); \ + fotg210_dbg(fotg210, "%s\n", _buf); \ +} + +/*-------------------------------------------------------------------------*/ + +#ifdef STUB_DEBUG_FILES + +static inline void create_debug_files(struct fotg210_hcd *bus) { } +static inline void remove_debug_files(struct fotg210_hcd *bus) { } + +#else + +/* troubleshooting help: expose state in debugfs */ + +static int debug_async_open(struct inode *, struct file *); +static int debug_periodic_open(struct inode *, struct file *); +static int debug_registers_open(struct inode *, struct file *); +static int debug_async_open(struct inode *, struct file *); + +static ssize_t debug_output(struct file*, char __user*, size_t, loff_t*); +static int debug_close(struct inode *, struct file *); + +static const struct file_operations debug_async_fops = { + .owner = THIS_MODULE, + .open = debug_async_open, + .read = debug_output, + .release = debug_close, + .llseek = default_llseek, +}; +static const struct file_operations debug_periodic_fops = { + .owner = THIS_MODULE, + .open = debug_periodic_open, + .read = debug_output, + .release = debug_close, + .llseek = default_llseek, +}; +static const struct file_operations debug_registers_fops = { + .owner = THIS_MODULE, + .open = debug_registers_open, + .read = debug_output, + .release = debug_close, + .llseek = default_llseek, +}; + +static struct dentry *fotg210_debug_root; + +struct debug_buffer { + ssize_t (*fill_func)(struct debug_buffer *); /* fill method */ + struct usb_bus *bus; + struct mutex mutex; /* protect filling of buffer */ + size_t count; /* number of characters filled into buffer */ + char *output_buf; + size_t alloc_size; +}; + +#define speed_char(info1)({ char tmp; \ + switch (info1 & (3 << 12)) { \ + case QH_FULL_SPEED: \ + tmp = 'f'; break; \ + case QH_LOW_SPEED: \ + tmp = 'l'; break; \ + case QH_HIGH_SPEED: \ + tmp = 'h'; break; \ + default: \ + tmp = '?'; break; \ + }; tmp; }) + +static inline char token_mark(struct fotg210_hcd *fotg210, __hc32 token) +{ + __u32 v = hc32_to_cpu(fotg210, token); + + if (v & QTD_STS_ACTIVE) + return '*'; + if (v & QTD_STS_HALT) + return '-'; + if (!IS_SHORT_READ(v)) + return ' '; + /* tries to advance through hw_alt_next */ + return '/'; +} + +static void qh_lines( + struct fotg210_hcd *fotg210, + struct fotg210_qh *qh, + char **nextp, + unsigned *sizep +) +{ + u32 scratch; + u32 hw_curr; + struct fotg210_qtd *td; + unsigned temp; + unsigned size = *sizep; + char *next = *nextp; + char mark; + __le32 list_end = FOTG210_LIST_END(fotg210); + struct fotg210_qh_hw *hw = qh->hw; + + if (hw->hw_qtd_next == list_end) /* NEC does this */ + mark = '@'; + else + mark = token_mark(fotg210, hw->hw_token); + if (mark == '/') { /* qh_alt_next controls qh advance? */ + if ((hw->hw_alt_next & QTD_MASK(fotg210)) + == fotg210->async->hw->hw_alt_next) + mark = '#'; /* blocked */ + else if (hw->hw_alt_next == list_end) + mark = '.'; /* use hw_qtd_next */ + /* else alt_next points to some other qtd */ + } + scratch = hc32_to_cpup(fotg210, &hw->hw_info1); + hw_curr = (mark == '*') ? hc32_to_cpup(fotg210, &hw->hw_current) : 0; + temp = scnprintf(next, size, + "qh/%p dev%d %cs ep%d %08x %08x(%08x%c %s nak%d)", + qh, scratch & 0x007f, + speed_char(scratch), + (scratch >> 8) & 0x000f, + scratch, hc32_to_cpup(fotg210, &hw->hw_info2), + hc32_to_cpup(fotg210, &hw->hw_token), mark, + (cpu_to_hc32(fotg210, QTD_TOGGLE) & hw->hw_token) + ? "data1" : "data0", + (hc32_to_cpup(fotg210, &hw->hw_alt_next) >> 1) & 0x0f); + size -= temp; + next += temp; + + /* hc may be modifying the list as we read it ... */ + list_for_each_entry(td, &qh->qtd_list, qtd_list) { + scratch = hc32_to_cpup(fotg210, &td->hw_token); + mark = ' '; + if (hw_curr == td->qtd_dma) + mark = '*'; + else if (hw->hw_qtd_next == cpu_to_hc32(fotg210, td->qtd_dma)) + mark = '+'; + else if (QTD_LENGTH(scratch)) { + if (td->hw_alt_next == fotg210->async->hw->hw_alt_next) + mark = '#'; + else if (td->hw_alt_next != list_end) + mark = '/'; + } + temp = snprintf(next, size, + "\n\t%p%c%s len=%d %08x urb %p", + td, mark, ({ char *tmp; + switch ((scratch>>8)&0x03) { + case 0: + tmp = "out"; + break; + case 1: + tmp = "in"; + break; + case 2: + tmp = "setup"; + break; + default: + tmp = "?"; + break; + } tmp; }), + (scratch >> 16) & 0x7fff, + scratch, + td->urb); + if (size < temp) + temp = size; + size -= temp; + next += temp; + if (temp == size) + goto done; + } + + temp = snprintf(next, size, "\n"); + if (size < temp) + temp = size; + size -= temp; + next += temp; + +done: + *sizep = size; + *nextp = next; +} + +static ssize_t fill_async_buffer(struct debug_buffer *buf) +{ + struct usb_hcd *hcd; + struct fotg210_hcd *fotg210; + unsigned long flags; + unsigned temp, size; + char *next; + struct fotg210_qh *qh; + + hcd = bus_to_hcd(buf->bus); + fotg210 = hcd_to_fotg210(hcd); + next = buf->output_buf; + size = buf->alloc_size; + + *next = 0; + + /* dumps a snapshot of the async schedule. + * usually empty except for long-term bulk reads, or head. + * one QH per line, and TDs we know about + */ + spin_lock_irqsave(&fotg210->lock, flags); + for (qh = fotg210->async->qh_next.qh; size > 0 && qh; + qh = qh->qh_next.qh) + qh_lines(fotg210, qh, &next, &size); + if (fotg210->async_unlink && size > 0) { + temp = scnprintf(next, size, "\nunlink =\n"); + size -= temp; + next += temp; + + for (qh = fotg210->async_unlink; size > 0 && qh; + qh = qh->unlink_next) + qh_lines(fotg210, qh, &next, &size); + } + spin_unlock_irqrestore(&fotg210->lock, flags); + + return strlen(buf->output_buf); +} + +#define DBG_SCHED_LIMIT 64 +static ssize_t fill_periodic_buffer(struct debug_buffer *buf) +{ + struct usb_hcd *hcd; + struct fotg210_hcd *fotg210; + unsigned long flags; + union fotg210_shadow p, *seen; + unsigned temp, size, seen_count; + char *next; + unsigned i; + __hc32 tag; + + seen = kmalloc(DBG_SCHED_LIMIT * sizeof(*seen), GFP_ATOMIC); + if (!seen) + return 0; + seen_count = 0; + + hcd = bus_to_hcd(buf->bus); + fotg210 = hcd_to_fotg210(hcd); + next = buf->output_buf; + size = buf->alloc_size; + + temp = scnprintf(next, size, "size = %d\n", fotg210->periodic_size); + size -= temp; + next += temp; + + /* dump a snapshot of the periodic schedule. + * iso changes, interrupt usually doesn't. + */ + spin_lock_irqsave(&fotg210->lock, flags); + for (i = 0; i < fotg210->periodic_size; i++) { + p = fotg210->pshadow[i]; + if (likely(!p.ptr)) + continue; + tag = Q_NEXT_TYPE(fotg210, fotg210->periodic[i]); + + temp = scnprintf(next, size, "%4d: ", i); + size -= temp; + next += temp; + + do { + struct fotg210_qh_hw *hw; + + switch (hc32_to_cpu(fotg210, tag)) { + case Q_TYPE_QH: + hw = p.qh->hw; + temp = scnprintf(next, size, " qh%d-%04x/%p", + p.qh->period, + hc32_to_cpup(fotg210, + &hw->hw_info2) + /* uframe masks */ + & (QH_CMASK | QH_SMASK), + p.qh); + size -= temp; + next += temp; + /* don't repeat what follows this qh */ + for (temp = 0; temp < seen_count; temp++) { + if (seen[temp].ptr != p.ptr) + continue; + if (p.qh->qh_next.ptr) { + temp = scnprintf(next, size, + " ..."); + size -= temp; + next += temp; + } + break; + } + /* show more info the first time around */ + if (temp == seen_count) { + u32 scratch = hc32_to_cpup(fotg210, + &hw->hw_info1); + struct fotg210_qtd *qtd; + char *type = ""; + + /* count tds, get ep direction */ + temp = 0; + list_for_each_entry(qtd, + &p.qh->qtd_list, + qtd_list) { + temp++; + switch (0x03 & (hc32_to_cpu( + fotg210, + qtd->hw_token) >> 8)) { + case 0: + type = "out"; + continue; + case 1: + type = "in"; + continue; + } + } + + temp = scnprintf(next, size, + "(%c%d ep%d%s " + "[%d/%d] q%d p%d)", + speed_char(scratch), + scratch & 0x007f, + (scratch >> 8) & 0x000f, type, + p.qh->usecs, p.qh->c_usecs, + temp, + 0x7ff & (scratch >> 16)); + + if (seen_count < DBG_SCHED_LIMIT) + seen[seen_count++].qh = p.qh; + } else + temp = 0; + tag = Q_NEXT_TYPE(fotg210, hw->hw_next); + p = p.qh->qh_next; + break; + case Q_TYPE_FSTN: + temp = scnprintf(next, size, + " fstn-%8x/%p", p.fstn->hw_prev, + p.fstn); + tag = Q_NEXT_TYPE(fotg210, p.fstn->hw_next); + p = p.fstn->fstn_next; + break; + case Q_TYPE_ITD: + temp = scnprintf(next, size, + " itd/%p", p.itd); + tag = Q_NEXT_TYPE(fotg210, p.itd->hw_next); + p = p.itd->itd_next; + break; + } + size -= temp; + next += temp; + } while (p.ptr); + + temp = scnprintf(next, size, "\n"); + size -= temp; + next += temp; + } + spin_unlock_irqrestore(&fotg210->lock, flags); + kfree(seen); + + return buf->alloc_size - size; +} +#undef DBG_SCHED_LIMIT + +static const char *rh_state_string(struct fotg210_hcd *fotg210) +{ + switch (fotg210->rh_state) { + case FOTG210_RH_HALTED: + return "halted"; + case FOTG210_RH_SUSPENDED: + return "suspended"; + case FOTG210_RH_RUNNING: + return "running"; + case FOTG210_RH_STOPPING: + return "stopping"; + } + return "?"; +} + +static ssize_t fill_registers_buffer(struct debug_buffer *buf) +{ + struct usb_hcd *hcd; + struct fotg210_hcd *fotg210; + unsigned long flags; + unsigned temp, size, i; + char *next, scratch[80]; + static const char fmt[] = "%*s\n"; + static const char label[] = ""; + + hcd = bus_to_hcd(buf->bus); + fotg210 = hcd_to_fotg210(hcd); + next = buf->output_buf; + size = buf->alloc_size; + + spin_lock_irqsave(&fotg210->lock, flags); + + if (!HCD_HW_ACCESSIBLE(hcd)) { + size = scnprintf(next, size, + "bus %s, device %s\n" + "%s\n" + "SUSPENDED(no register access)\n", + hcd->self.controller->bus->name, + dev_name(hcd->self.controller), + hcd->product_desc); + goto done; + } + + /* Capability Registers */ + i = HC_VERSION(fotg210, fotg210_readl(fotg210, + &fotg210->caps->hc_capbase)); + temp = scnprintf(next, size, + "bus %s, device %s\n" + "%s\n" + "EHCI %x.%02x, rh state %s\n", + hcd->self.controller->bus->name, + dev_name(hcd->self.controller), + hcd->product_desc, + i >> 8, i & 0x0ff, rh_state_string(fotg210)); + size -= temp; + next += temp; + + /* FIXME interpret both types of params */ + i = fotg210_readl(fotg210, &fotg210->caps->hcs_params); + temp = scnprintf(next, size, "structural params 0x%08x\n", i); + size -= temp; + next += temp; + + i = fotg210_readl(fotg210, &fotg210->caps->hcc_params); + temp = scnprintf(next, size, "capability params 0x%08x\n", i); + size -= temp; + next += temp; + + /* Operational Registers */ + temp = dbg_status_buf(scratch, sizeof(scratch), label, + fotg210_readl(fotg210, &fotg210->regs->status)); + temp = scnprintf(next, size, fmt, temp, scratch); + size -= temp; + next += temp; + + temp = dbg_command_buf(scratch, sizeof(scratch), label, + fotg210_readl(fotg210, &fotg210->regs->command)); + temp = scnprintf(next, size, fmt, temp, scratch); + size -= temp; + next += temp; + + temp = dbg_intr_buf(scratch, sizeof(scratch), label, + fotg210_readl(fotg210, &fotg210->regs->intr_enable)); + temp = scnprintf(next, size, fmt, temp, scratch); + size -= temp; + next += temp; + + temp = scnprintf(next, size, "uframe %04x\n", + fotg210_read_frame_index(fotg210)); + size -= temp; + next += temp; + + if (fotg210->async_unlink) { + temp = scnprintf(next, size, "async unlink qh %p\n", + fotg210->async_unlink); + size -= temp; + next += temp; + } + +#ifdef FOTG210_STATS + temp = scnprintf(next, size, + "irq normal %ld err %ld iaa %ld(lost %ld)\n", + fotg210->stats.normal, fotg210->stats.error, fotg210->stats.iaa, + fotg210->stats.lost_iaa); + size -= temp; + next += temp; + + temp = scnprintf(next, size, "complete %ld unlink %ld\n", + fotg210->stats.complete, fotg210->stats.unlink); + size -= temp; + next += temp; +#endif + +done: + spin_unlock_irqrestore(&fotg210->lock, flags); + + return buf->alloc_size - size; +} + +static struct debug_buffer *alloc_buffer(struct usb_bus *bus, + ssize_t (*fill_func)(struct debug_buffer *)) +{ + struct debug_buffer *buf; + + buf = kzalloc(sizeof(struct debug_buffer), GFP_KERNEL); + + if (buf) { + buf->bus = bus; + buf->fill_func = fill_func; + mutex_init(&buf->mutex); + buf->alloc_size = PAGE_SIZE; + } + + return buf; +} + +static int fill_buffer(struct debug_buffer *buf) +{ + int ret = 0; + + if (!buf->output_buf) + buf->output_buf = vmalloc(buf->alloc_size); + + if (!buf->output_buf) { + ret = -ENOMEM; + goto out; + } + + ret = buf->fill_func(buf); + + if (ret >= 0) { + buf->count = ret; + ret = 0; + } + +out: + return ret; +} + +static ssize_t debug_output(struct file *file, char __user *user_buf, + size_t len, loff_t *offset) +{ + struct debug_buffer *buf = file->private_data; + int ret = 0; + + mutex_lock(&buf->mutex); + if (buf->count == 0) { + ret = fill_buffer(buf); + if (ret != 0) { + mutex_unlock(&buf->mutex); + goto out; + } + } + mutex_unlock(&buf->mutex); + + ret = simple_read_from_buffer(user_buf, len, offset, + buf->output_buf, buf->count); + +out: + return ret; + +} + +static int debug_close(struct inode *inode, struct file *file) +{ + struct debug_buffer *buf = file->private_data; + + if (buf) { + vfree(buf->output_buf); + kfree(buf); + } + + return 0; +} +static int debug_async_open(struct inode *inode, struct file *file) +{ + file->private_data = alloc_buffer(inode->i_private, fill_async_buffer); + + return file->private_data ? 0 : -ENOMEM; +} + +static int debug_periodic_open(struct inode *inode, struct file *file) +{ + struct debug_buffer *buf; + buf = alloc_buffer(inode->i_private, fill_periodic_buffer); + if (!buf) + return -ENOMEM; + + buf->alloc_size = (sizeof(void *) == 4 ? 6 : 8)*PAGE_SIZE; + file->private_data = buf; + return 0; +} + +static int debug_registers_open(struct inode *inode, struct file *file) +{ + file->private_data = alloc_buffer(inode->i_private, + fill_registers_buffer); + + return file->private_data ? 0 : -ENOMEM; +} + +static inline void create_debug_files(struct fotg210_hcd *fotg210) +{ + struct usb_bus *bus = &fotg210_to_hcd(fotg210)->self; + + fotg210->debug_dir = debugfs_create_dir(bus->bus_name, + fotg210_debug_root); + if (!fotg210->debug_dir) + return; + + if (!debugfs_create_file("async", S_IRUGO, fotg210->debug_dir, bus, + &debug_async_fops)) + goto file_error; + + if (!debugfs_create_file("periodic", S_IRUGO, fotg210->debug_dir, bus, + &debug_periodic_fops)) + goto file_error; + + if (!debugfs_create_file("registers", S_IRUGO, fotg210->debug_dir, bus, + &debug_registers_fops)) + goto file_error; + + return; + +file_error: + debugfs_remove_recursive(fotg210->debug_dir); +} + +static inline void remove_debug_files(struct fotg210_hcd *fotg210) +{ + debugfs_remove_recursive(fotg210->debug_dir); +} + +#endif /* STUB_DEBUG_FILES */ +/*-------------------------------------------------------------------------*/ + +/* + * handshake - spin reading hc until handshake completes or fails + * @ptr: address of hc register to be read + * @mask: bits to look at in result of read + * @done: value of those bits when handshake succeeds + * @usec: timeout in microseconds + * + * Returns negative errno, or zero on success + * + * Success happens when the "mask" bits have the specified value (hardware + * handshake done). There are two failure modes: "usec" have passed (major + * hardware flakeout), or the register reads as all-ones (hardware removed). + * + * That last failure should_only happen in cases like physical cardbus eject + * before driver shutdown. But it also seems to be caused by bugs in cardbus + * bridge shutdown: shutting down the bridge before the devices using it. + */ +static int handshake(struct fotg210_hcd *fotg210, void __iomem *ptr, + u32 mask, u32 done, int usec) +{ + u32 result; + + do { + result = fotg210_readl(fotg210, ptr); + if (result == ~(u32)0) /* card removed */ + return -ENODEV; + result &= mask; + if (result == done) + return 0; + udelay(1); + usec--; + } while (usec > 0); + return -ETIMEDOUT; +} + +/* + * Force HC to halt state from unknown (EHCI spec section 2.3). + * Must be called with interrupts enabled and the lock not held. + */ +static int fotg210_halt(struct fotg210_hcd *fotg210) +{ + u32 temp; + + spin_lock_irq(&fotg210->lock); + + /* disable any irqs left enabled by previous code */ + fotg210_writel(fotg210, 0, &fotg210->regs->intr_enable); + + /* + * This routine gets called during probe before fotg210->command + * has been initialized, so we can't rely on its value. + */ + fotg210->command &= ~CMD_RUN; + temp = fotg210_readl(fotg210, &fotg210->regs->command); + temp &= ~(CMD_RUN | CMD_IAAD); + fotg210_writel(fotg210, temp, &fotg210->regs->command); + + spin_unlock_irq(&fotg210->lock); + synchronize_irq(fotg210_to_hcd(fotg210)->irq); + + return handshake(fotg210, &fotg210->regs->status, + STS_HALT, STS_HALT, 16 * 125); +} + +/* + * Reset a non-running (STS_HALT == 1) controller. + * Must be called with interrupts enabled and the lock not held. + */ +static int fotg210_reset(struct fotg210_hcd *fotg210) +{ + int retval; + u32 command = fotg210_readl(fotg210, &fotg210->regs->command); + + /* If the EHCI debug controller is active, special care must be + * taken before and after a host controller reset */ + if (fotg210->debug && !dbgp_reset_prep(fotg210_to_hcd(fotg210))) + fotg210->debug = NULL; + + command |= CMD_RESET; + dbg_cmd(fotg210, "reset", command); + fotg210_writel(fotg210, command, &fotg210->regs->command); + fotg210->rh_state = FOTG210_RH_HALTED; + fotg210->next_statechange = jiffies; + retval = handshake(fotg210, &fotg210->regs->command, + CMD_RESET, 0, 250 * 1000); + + if (retval) + return retval; + + if (fotg210->debug) + dbgp_external_startup(fotg210_to_hcd(fotg210)); + + fotg210->port_c_suspend = fotg210->suspended_ports = + fotg210->resuming_ports = 0; + return retval; +} + +/* + * Idle the controller (turn off the schedules). + * Must be called with interrupts enabled and the lock not held. + */ +static void fotg210_quiesce(struct fotg210_hcd *fotg210) +{ + u32 temp; + + if (fotg210->rh_state != FOTG210_RH_RUNNING) + return; + + /* wait for any schedule enables/disables to take effect */ + temp = (fotg210->command << 10) & (STS_ASS | STS_PSS); + handshake(fotg210, &fotg210->regs->status, STS_ASS | STS_PSS, temp, + 16 * 125); + + /* then disable anything that's still active */ + spin_lock_irq(&fotg210->lock); + fotg210->command &= ~(CMD_ASE | CMD_PSE); + fotg210_writel(fotg210, fotg210->command, &fotg210->regs->command); + spin_unlock_irq(&fotg210->lock); + + /* hardware can take 16 microframes to turn off ... */ + handshake(fotg210, &fotg210->regs->status, STS_ASS | STS_PSS, 0, + 16 * 125); +} + +/*-------------------------------------------------------------------------*/ + +static void end_unlink_async(struct fotg210_hcd *fotg210); +static void unlink_empty_async(struct fotg210_hcd *fotg210); +static void fotg210_work(struct fotg210_hcd *fotg210); +static void start_unlink_intr(struct fotg210_hcd *fotg210, + struct fotg210_qh *qh); +static void end_unlink_intr(struct fotg210_hcd *fotg210, struct fotg210_qh *qh); + +/*-------------------------------------------------------------------------*/ + +/* Set a bit in the USBCMD register */ +static void fotg210_set_command_bit(struct fotg210_hcd *fotg210, u32 bit) +{ + fotg210->command |= bit; + fotg210_writel(fotg210, fotg210->command, &fotg210->regs->command); + + /* unblock posted write */ + fotg210_readl(fotg210, &fotg210->regs->command); +} + +/* Clear a bit in the USBCMD register */ +static void fotg210_clear_command_bit(struct fotg210_hcd *fotg210, u32 bit) +{ + fotg210->command &= ~bit; + fotg210_writel(fotg210, fotg210->command, &fotg210->regs->command); + + /* unblock posted write */ + fotg210_readl(fotg210, &fotg210->regs->command); +} + +/*-------------------------------------------------------------------------*/ + +/* + * EHCI timer support... Now using hrtimers. + * + * Lots of different events are triggered from fotg210->hrtimer. Whenever + * the timer routine runs, it checks each possible event; events that are + * currently enabled and whose expiration time has passed get handled. + * The set of enabled events is stored as a collection of bitflags in + * fotg210->enabled_hrtimer_events, and they are numbered in order of + * increasing delay values (ranging between 1 ms and 100 ms). + * + * Rather than implementing a sorted list or tree of all pending events, + * we keep track only of the lowest-numbered pending event, in + * fotg210->next_hrtimer_event. Whenever fotg210->hrtimer gets restarted, its + * expiration time is set to the timeout value for this event. + * + * As a result, events might not get handled right away; the actual delay + * could be anywhere up to twice the requested delay. This doesn't + * matter, because none of the events are especially time-critical. The + * ones that matter most all have a delay of 1 ms, so they will be + * handled after 2 ms at most, which is okay. In addition to this, we + * allow for an expiration range of 1 ms. + */ + +/* + * Delay lengths for the hrtimer event types. + * Keep this list sorted by delay length, in the same order as + * the event types indexed by enum fotg210_hrtimer_event in fotg210.h. + */ +static unsigned event_delays_ns[] = { + 1 * NSEC_PER_MSEC, /* FOTG210_HRTIMER_POLL_ASS */ + 1 * NSEC_PER_MSEC, /* FOTG210_HRTIMER_POLL_PSS */ + 1 * NSEC_PER_MSEC, /* FOTG210_HRTIMER_POLL_DEAD */ + 1125 * NSEC_PER_USEC, /* FOTG210_HRTIMER_UNLINK_INTR */ + 2 * NSEC_PER_MSEC, /* FOTG210_HRTIMER_FREE_ITDS */ + 6 * NSEC_PER_MSEC, /* FOTG210_HRTIMER_ASYNC_UNLINKS */ + 10 * NSEC_PER_MSEC, /* FOTG210_HRTIMER_IAA_WATCHDOG */ + 10 * NSEC_PER_MSEC, /* FOTG210_HRTIMER_DISABLE_PERIODIC */ + 15 * NSEC_PER_MSEC, /* FOTG210_HRTIMER_DISABLE_ASYNC */ + 100 * NSEC_PER_MSEC, /* FOTG210_HRTIMER_IO_WATCHDOG */ +}; + +/* Enable a pending hrtimer event */ +static void fotg210_enable_event(struct fotg210_hcd *fotg210, unsigned event, + bool resched) +{ + ktime_t *timeout = &fotg210->hr_timeouts[event]; + + if (resched) + *timeout = ktime_add(ktime_get(), + ktime_set(0, event_delays_ns[event])); + fotg210->enabled_hrtimer_events |= (1 << event); + + /* Track only the lowest-numbered pending event */ + if (event < fotg210->next_hrtimer_event) { + fotg210->next_hrtimer_event = event; + hrtimer_start_range_ns(&fotg210->hrtimer, *timeout, + NSEC_PER_MSEC, HRTIMER_MODE_ABS); + } +} + + +/* Poll the STS_ASS status bit; see when it agrees with CMD_ASE */ +static void fotg210_poll_ASS(struct fotg210_hcd *fotg210) +{ + unsigned actual, want; + + /* Don't enable anything if the controller isn't running (e.g., died) */ + if (fotg210->rh_state != FOTG210_RH_RUNNING) + return; + + want = (fotg210->command & CMD_ASE) ? STS_ASS : 0; + actual = fotg210_readl(fotg210, &fotg210->regs->status) & STS_ASS; + + if (want != actual) { + + /* Poll again later, but give up after about 20 ms */ + if (fotg210->ASS_poll_count++ < 20) { + fotg210_enable_event(fotg210, FOTG210_HRTIMER_POLL_ASS, + true); + return; + } + fotg210_dbg(fotg210, "Waited too long for the async schedule status (%x/%x), giving up\n", + want, actual); + } + fotg210->ASS_poll_count = 0; + + /* The status is up-to-date; restart or stop the schedule as needed */ + if (want == 0) { /* Stopped */ + if (fotg210->async_count > 0) + fotg210_set_command_bit(fotg210, CMD_ASE); + + } else { /* Running */ + if (fotg210->async_count == 0) { + + /* Turn off the schedule after a while */ + fotg210_enable_event(fotg210, + FOTG210_HRTIMER_DISABLE_ASYNC, + true); + } + } +} + +/* Turn off the async schedule after a brief delay */ +static void fotg210_disable_ASE(struct fotg210_hcd *fotg210) +{ + fotg210_clear_command_bit(fotg210, CMD_ASE); +} + + +/* Poll the STS_PSS status bit; see when it agrees with CMD_PSE */ +static void fotg210_poll_PSS(struct fotg210_hcd *fotg210) +{ + unsigned actual, want; + + /* Don't do anything if the controller isn't running (e.g., died) */ + if (fotg210->rh_state != FOTG210_RH_RUNNING) + return; + + want = (fotg210->command & CMD_PSE) ? STS_PSS : 0; + actual = fotg210_readl(fotg210, &fotg210->regs->status) & STS_PSS; + + if (want != actual) { + + /* Poll again later, but give up after about 20 ms */ + if (fotg210->PSS_poll_count++ < 20) { + fotg210_enable_event(fotg210, FOTG210_HRTIMER_POLL_PSS, + true); + return; + } + fotg210_dbg(fotg210, "Waited too long for the periodic schedule status (%x/%x), giving up\n", + want, actual); + } + fotg210->PSS_poll_count = 0; + + /* The status is up-to-date; restart or stop the schedule as needed */ + if (want == 0) { /* Stopped */ + if (fotg210->periodic_count > 0) + fotg210_set_command_bit(fotg210, CMD_PSE); + + } else { /* Running */ + if (fotg210->periodic_count == 0) { + + /* Turn off the schedule after a while */ + fotg210_enable_event(fotg210, + FOTG210_HRTIMER_DISABLE_PERIODIC, + true); + } + } +} + +/* Turn off the periodic schedule after a brief delay */ +static void fotg210_disable_PSE(struct fotg210_hcd *fotg210) +{ + fotg210_clear_command_bit(fotg210, CMD_PSE); +} + + +/* Poll the STS_HALT status bit; see when a dead controller stops */ +static void fotg210_handle_controller_death(struct fotg210_hcd *fotg210) +{ + if (!(fotg210_readl(fotg210, &fotg210->regs->status) & STS_HALT)) { + + /* Give up after a few milliseconds */ + if (fotg210->died_poll_count++ < 5) { + /* Try again later */ + fotg210_enable_event(fotg210, + FOTG210_HRTIMER_POLL_DEAD, true); + return; + } + fotg210_warn(fotg210, "Waited too long for the controller to stop, giving up\n"); + } + + /* Clean up the mess */ + fotg210->rh_state = FOTG210_RH_HALTED; + fotg210_writel(fotg210, 0, &fotg210->regs->intr_enable); + fotg210_work(fotg210); + end_unlink_async(fotg210); + + /* Not in process context, so don't try to reset the controller */ +} + + +/* Handle unlinked interrupt QHs once they are gone from the hardware */ +static void fotg210_handle_intr_unlinks(struct fotg210_hcd *fotg210) +{ + bool stopped = (fotg210->rh_state < FOTG210_RH_RUNNING); + + /* + * Process all the QHs on the intr_unlink list that were added + * before the current unlink cycle began. The list is in + * temporal order, so stop when we reach the first entry in the + * current cycle. But if the root hub isn't running then + * process all the QHs on the list. + */ + fotg210->intr_unlinking = true; + while (fotg210->intr_unlink) { + struct fotg210_qh *qh = fotg210->intr_unlink; + + if (!stopped && qh->unlink_cycle == fotg210->intr_unlink_cycle) + break; + fotg210->intr_unlink = qh->unlink_next; + qh->unlink_next = NULL; + end_unlink_intr(fotg210, qh); + } + + /* Handle remaining entries later */ + if (fotg210->intr_unlink) { + fotg210_enable_event(fotg210, FOTG210_HRTIMER_UNLINK_INTR, + true); + ++fotg210->intr_unlink_cycle; + } + fotg210->intr_unlinking = false; +} + + +/* Start another free-iTDs/siTDs cycle */ +static void start_free_itds(struct fotg210_hcd *fotg210) +{ + if (!(fotg210->enabled_hrtimer_events & + BIT(FOTG210_HRTIMER_FREE_ITDS))) { + fotg210->last_itd_to_free = list_entry( + fotg210->cached_itd_list.prev, + struct fotg210_itd, itd_list); + fotg210_enable_event(fotg210, FOTG210_HRTIMER_FREE_ITDS, true); + } +} + +/* Wait for controller to stop using old iTDs and siTDs */ +static void end_free_itds(struct fotg210_hcd *fotg210) +{ + struct fotg210_itd *itd, *n; + + if (fotg210->rh_state < FOTG210_RH_RUNNING) + fotg210->last_itd_to_free = NULL; + + list_for_each_entry_safe(itd, n, &fotg210->cached_itd_list, itd_list) { + list_del(&itd->itd_list); + dma_pool_free(fotg210->itd_pool, itd, itd->itd_dma); + if (itd == fotg210->last_itd_to_free) + break; + } + + if (!list_empty(&fotg210->cached_itd_list)) + start_free_itds(fotg210); +} + + +/* Handle lost (or very late) IAA interrupts */ +static void fotg210_iaa_watchdog(struct fotg210_hcd *fotg210) +{ + if (fotg210->rh_state != FOTG210_RH_RUNNING) + return; + + /* + * Lost IAA irqs wedge things badly; seen first with a vt8235. + * So we need this watchdog, but must protect it against both + * (a) SMP races against real IAA firing and retriggering, and + * (b) clean HC shutdown, when IAA watchdog was pending. + */ + if (fotg210->async_iaa) { + u32 cmd, status; + + /* If we get here, IAA is *REALLY* late. It's barely + * conceivable that the system is so busy that CMD_IAAD + * is still legitimately set, so let's be sure it's + * clear before we read STS_IAA. (The HC should clear + * CMD_IAAD when it sets STS_IAA.) + */ + cmd = fotg210_readl(fotg210, &fotg210->regs->command); + + /* + * If IAA is set here it either legitimately triggered + * after the watchdog timer expired (_way_ late, so we'll + * still count it as lost) ... or a silicon erratum: + * - VIA seems to set IAA without triggering the IRQ; + * - IAAD potentially cleared without setting IAA. + */ + status = fotg210_readl(fotg210, &fotg210->regs->status); + if ((status & STS_IAA) || !(cmd & CMD_IAAD)) { + COUNT(fotg210->stats.lost_iaa); + fotg210_writel(fotg210, STS_IAA, + &fotg210->regs->status); + } + + fotg210_vdbg(fotg210, "IAA watchdog: status %x cmd %x\n", + status, cmd); + end_unlink_async(fotg210); + } +} + + +/* Enable the I/O watchdog, if appropriate */ +static void turn_on_io_watchdog(struct fotg210_hcd *fotg210) +{ + /* Not needed if the controller isn't running or it's already enabled */ + if (fotg210->rh_state != FOTG210_RH_RUNNING || + (fotg210->enabled_hrtimer_events & + BIT(FOTG210_HRTIMER_IO_WATCHDOG))) + return; + + /* + * Isochronous transfers always need the watchdog. + * For other sorts we use it only if the flag is set. + */ + if (fotg210->isoc_count > 0 || (fotg210->need_io_watchdog && + fotg210->async_count + fotg210->intr_count > 0)) + fotg210_enable_event(fotg210, FOTG210_HRTIMER_IO_WATCHDOG, + true); +} + + +/* + * Handler functions for the hrtimer event types. + * Keep this array in the same order as the event types indexed by + * enum fotg210_hrtimer_event in fotg210.h. + */ +static void (*event_handlers[])(struct fotg210_hcd *) = { + fotg210_poll_ASS, /* FOTG210_HRTIMER_POLL_ASS */ + fotg210_poll_PSS, /* FOTG210_HRTIMER_POLL_PSS */ + fotg210_handle_controller_death, /* FOTG210_HRTIMER_POLL_DEAD */ + fotg210_handle_intr_unlinks, /* FOTG210_HRTIMER_UNLINK_INTR */ + end_free_itds, /* FOTG210_HRTIMER_FREE_ITDS */ + unlink_empty_async, /* FOTG210_HRTIMER_ASYNC_UNLINKS */ + fotg210_iaa_watchdog, /* FOTG210_HRTIMER_IAA_WATCHDOG */ + fotg210_disable_PSE, /* FOTG210_HRTIMER_DISABLE_PERIODIC */ + fotg210_disable_ASE, /* FOTG210_HRTIMER_DISABLE_ASYNC */ + fotg210_work, /* FOTG210_HRTIMER_IO_WATCHDOG */ +}; + +static enum hrtimer_restart fotg210_hrtimer_func(struct hrtimer *t) +{ + struct fotg210_hcd *fotg210 = + container_of(t, struct fotg210_hcd, hrtimer); + ktime_t now; + unsigned long events; + unsigned long flags; + unsigned e; + + spin_lock_irqsave(&fotg210->lock, flags); + + events = fotg210->enabled_hrtimer_events; + fotg210->enabled_hrtimer_events = 0; + fotg210->next_hrtimer_event = FOTG210_HRTIMER_NO_EVENT; + + /* + * Check each pending event. If its time has expired, handle + * the event; otherwise re-enable it. + */ + now = ktime_get(); + for_each_set_bit(e, &events, FOTG210_HRTIMER_NUM_EVENTS) { + if (now.tv64 >= fotg210->hr_timeouts[e].tv64) + event_handlers[e](fotg210); + else + fotg210_enable_event(fotg210, e, false); + } + + spin_unlock_irqrestore(&fotg210->lock, flags); + return HRTIMER_NORESTART; +} + +/*-------------------------------------------------------------------------*/ + +#define fotg210_bus_suspend NULL +#define fotg210_bus_resume NULL + +/*-------------------------------------------------------------------------*/ + +static int check_reset_complete( + struct fotg210_hcd *fotg210, + int index, + u32 __iomem *status_reg, + int port_status +) { + if (!(port_status & PORT_CONNECT)) + return port_status; + + /* if reset finished and it's still not enabled -- handoff */ + if (!(port_status & PORT_PE)) { + /* with integrated TT, there's nobody to hand it to! */ + fotg210_dbg(fotg210, + "Failed to enable port %d on root hub TT\n", + index+1); + return port_status; + } else { + fotg210_dbg(fotg210, "port %d reset complete, port enabled\n", + index + 1); + } + + return port_status; +} + +/*-------------------------------------------------------------------------*/ + + +/* build "status change" packet (one or two bytes) from HC registers */ + +static int +fotg210_hub_status_data(struct usb_hcd *hcd, char *buf) +{ + struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); + u32 temp, status; + u32 mask; + int retval = 1; + unsigned long flags; + + /* init status to no-changes */ + buf[0] = 0; + + /* Inform the core about resumes-in-progress by returning + * a non-zero value even if there are no status changes. + */ + status = fotg210->resuming_ports; + + mask = PORT_CSC | PORT_PEC; + /* PORT_RESUME from hardware ~= PORT_STAT_C_SUSPEND */ + + /* no hub change reports (bit 0) for now (power, ...) */ + + /* port N changes (bit N)? */ + spin_lock_irqsave(&fotg210->lock, flags); + + temp = fotg210_readl(fotg210, &fotg210->regs->port_status); + + /* + * Return status information even for ports with OWNER set. + * Otherwise khubd wouldn't see the disconnect event when a + * high-speed device is switched over to the companion + * controller by the user. + */ + + if ((temp & mask) != 0 || test_bit(0, &fotg210->port_c_suspend) + || (fotg210->reset_done[0] && time_after_eq( + jiffies, fotg210->reset_done[0]))) { + buf[0] |= 1 << 1; + status = STS_PCD; + } + /* FIXME autosuspend idle root hubs */ + spin_unlock_irqrestore(&fotg210->lock, flags); + return status ? retval : 0; +} + +/*-------------------------------------------------------------------------*/ + +static void +fotg210_hub_descriptor( + struct fotg210_hcd *fotg210, + struct usb_hub_descriptor *desc +) { + int ports = HCS_N_PORTS(fotg210->hcs_params); + u16 temp; + + desc->bDescriptorType = 0x29; + desc->bPwrOn2PwrGood = 10; /* fotg210 1.0, 2.3.9 says 20ms max */ + desc->bHubContrCurrent = 0; + + desc->bNbrPorts = ports; + temp = 1 + (ports / 8); + desc->bDescLength = 7 + 2 * temp; + + /* two bitmaps: ports removable, and usb 1.0 legacy PortPwrCtrlMask */ + memset(&desc->u.hs.DeviceRemovable[0], 0, temp); + memset(&desc->u.hs.DeviceRemovable[temp], 0xff, temp); + + temp = 0x0008; /* per-port overcurrent reporting */ + temp |= 0x0002; /* no power switching */ + desc->wHubCharacteristics = cpu_to_le16(temp); +} + +/*-------------------------------------------------------------------------*/ + +static int fotg210_hub_control( + struct usb_hcd *hcd, + u16 typeReq, + u16 wValue, + u16 wIndex, + char *buf, + u16 wLength +) { + struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); + int ports = HCS_N_PORTS(fotg210->hcs_params); + u32 __iomem *status_reg = &fotg210->regs->port_status; + u32 temp, temp1, status; + unsigned long flags; + int retval = 0; + unsigned selector; + + /* + * FIXME: support SetPortFeatures USB_PORT_FEAT_INDICATOR. + * HCS_INDICATOR may say we can change LEDs to off/amber/green. + * (track current state ourselves) ... blink for diagnostics, + * power, "this is the one", etc. EHCI spec supports this. + */ + + spin_lock_irqsave(&fotg210->lock, flags); + switch (typeReq) { + case ClearHubFeature: + switch (wValue) { + case C_HUB_LOCAL_POWER: + case C_HUB_OVER_CURRENT: + /* no hub-wide feature/status flags */ + break; + default: + goto error; + } + break; + case ClearPortFeature: + if (!wIndex || wIndex > ports) + goto error; + wIndex--; + temp = fotg210_readl(fotg210, status_reg); + temp &= ~PORT_RWC_BITS; + + /* + * Even if OWNER is set, so the port is owned by the + * companion controller, khubd needs to be able to clear + * the port-change status bits (especially + * USB_PORT_STAT_C_CONNECTION). + */ + + switch (wValue) { + case USB_PORT_FEAT_ENABLE: + fotg210_writel(fotg210, temp & ~PORT_PE, status_reg); + break; + case USB_PORT_FEAT_C_ENABLE: + fotg210_writel(fotg210, temp | PORT_PEC, status_reg); + break; + case USB_PORT_FEAT_SUSPEND: + if (temp & PORT_RESET) + goto error; + if (!(temp & PORT_SUSPEND)) + break; + if ((temp & PORT_PE) == 0) + goto error; + + /* resume signaling for 20 msec */ + fotg210_writel(fotg210, temp | PORT_RESUME, status_reg); + fotg210->reset_done[wIndex] = jiffies + + msecs_to_jiffies(20); + break; + case USB_PORT_FEAT_C_SUSPEND: + clear_bit(wIndex, &fotg210->port_c_suspend); + break; + case USB_PORT_FEAT_C_CONNECTION: + fotg210_writel(fotg210, temp | PORT_CSC, status_reg); + break; + case USB_PORT_FEAT_C_OVER_CURRENT: + fotg210_writel(fotg210, temp | OTGISR_OVC, + &fotg210->regs->otgisr); + break; + case USB_PORT_FEAT_C_RESET: + /* GetPortStatus clears reset */ + break; + default: + goto error; + } + fotg210_readl(fotg210, &fotg210->regs->command); + break; + case GetHubDescriptor: + fotg210_hub_descriptor(fotg210, (struct usb_hub_descriptor *) + buf); + break; + case GetHubStatus: + /* no hub-wide feature/status flags */ + memset(buf, 0, 4); + /*cpu_to_le32s ((u32 *) buf); */ + break; + case GetPortStatus: + if (!wIndex || wIndex > ports) + goto error; + wIndex--; + status = 0; + temp = fotg210_readl(fotg210, status_reg); + + /* wPortChange bits */ + if (temp & PORT_CSC) + status |= USB_PORT_STAT_C_CONNECTION << 16; + if (temp & PORT_PEC) + status |= USB_PORT_STAT_C_ENABLE << 16; + + temp1 = fotg210_readl(fotg210, &fotg210->regs->otgisr); + if (temp1 & OTGISR_OVC) + status |= USB_PORT_STAT_C_OVERCURRENT << 16; + + /* whoever resumes must GetPortStatus to complete it!! */ + if (temp & PORT_RESUME) { + + /* Remote Wakeup received? */ + if (!fotg210->reset_done[wIndex]) { + /* resume signaling for 20 msec */ + fotg210->reset_done[wIndex] = jiffies + + msecs_to_jiffies(20); + /* check the port again */ + mod_timer(&fotg210_to_hcd(fotg210)->rh_timer, + fotg210->reset_done[wIndex]); + } + + /* resume completed? */ + else if (time_after_eq(jiffies, + fotg210->reset_done[wIndex])) { + clear_bit(wIndex, &fotg210->suspended_ports); + set_bit(wIndex, &fotg210->port_c_suspend); + fotg210->reset_done[wIndex] = 0; + + /* stop resume signaling */ + temp = fotg210_readl(fotg210, status_reg); + fotg210_writel(fotg210, + temp & ~(PORT_RWC_BITS | PORT_RESUME), + status_reg); + clear_bit(wIndex, &fotg210->resuming_ports); + retval = handshake(fotg210, status_reg, + PORT_RESUME, 0, 2000 /* 2msec */); + if (retval != 0) { + fotg210_err(fotg210, + "port %d resume error %d\n", + wIndex + 1, retval); + goto error; + } + temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10)); + } + } + + /* whoever resets must GetPortStatus to complete it!! */ + if ((temp & PORT_RESET) + && time_after_eq(jiffies, + fotg210->reset_done[wIndex])) { + status |= USB_PORT_STAT_C_RESET << 16; + fotg210->reset_done[wIndex] = 0; + clear_bit(wIndex, &fotg210->resuming_ports); + + /* force reset to complete */ + fotg210_writel(fotg210, + temp & ~(PORT_RWC_BITS | PORT_RESET), + status_reg); + /* REVISIT: some hardware needs 550+ usec to clear + * this bit; seems too long to spin routinely... + */ + retval = handshake(fotg210, status_reg, + PORT_RESET, 0, 1000); + if (retval != 0) { + fotg210_err(fotg210, "port %d reset error %d\n", + wIndex + 1, retval); + goto error; + } + + /* see what we found out */ + temp = check_reset_complete(fotg210, wIndex, status_reg, + fotg210_readl(fotg210, status_reg)); + } + + if (!(temp & (PORT_RESUME|PORT_RESET))) { + fotg210->reset_done[wIndex] = 0; + clear_bit(wIndex, &fotg210->resuming_ports); + } + + /* transfer dedicated ports to the companion hc */ + if ((temp & PORT_CONNECT) && + test_bit(wIndex, &fotg210->companion_ports)) { + temp &= ~PORT_RWC_BITS; + fotg210_writel(fotg210, temp, status_reg); + fotg210_dbg(fotg210, "port %d --> companion\n", + wIndex + 1); + temp = fotg210_readl(fotg210, status_reg); + } + + /* + * Even if OWNER is set, there's no harm letting khubd + * see the wPortStatus values (they should all be 0 except + * for PORT_POWER anyway). + */ + + if (temp & PORT_CONNECT) { + status |= USB_PORT_STAT_CONNECTION; + status |= fotg210_port_speed(fotg210, temp); + } + if (temp & PORT_PE) + status |= USB_PORT_STAT_ENABLE; + + /* maybe the port was unsuspended without our knowledge */ + if (temp & (PORT_SUSPEND|PORT_RESUME)) { + status |= USB_PORT_STAT_SUSPEND; + } else if (test_bit(wIndex, &fotg210->suspended_ports)) { + clear_bit(wIndex, &fotg210->suspended_ports); + clear_bit(wIndex, &fotg210->resuming_ports); + fotg210->reset_done[wIndex] = 0; + if (temp & PORT_PE) + set_bit(wIndex, &fotg210->port_c_suspend); + } + + temp1 = fotg210_readl(fotg210, &fotg210->regs->otgisr); + if (temp1 & OTGISR_OVC) + status |= USB_PORT_STAT_OVERCURRENT; + if (temp & PORT_RESET) + status |= USB_PORT_STAT_RESET; + if (test_bit(wIndex, &fotg210->port_c_suspend)) + status |= USB_PORT_STAT_C_SUSPEND << 16; + +#ifndef VERBOSE_DEBUG + if (status & ~0xffff) /* only if wPortChange is interesting */ +#endif + dbg_port(fotg210, "GetStatus", wIndex + 1, temp); + put_unaligned_le32(status, buf); + break; + case SetHubFeature: + switch (wValue) { + case C_HUB_LOCAL_POWER: + case C_HUB_OVER_CURRENT: + /* no hub-wide feature/status flags */ + break; + default: + goto error; + } + break; + case SetPortFeature: + selector = wIndex >> 8; + wIndex &= 0xff; + + if (!wIndex || wIndex > ports) + goto error; + wIndex--; + temp = fotg210_readl(fotg210, status_reg); + temp &= ~PORT_RWC_BITS; + switch (wValue) { + case USB_PORT_FEAT_SUSPEND: + if ((temp & PORT_PE) == 0 + || (temp & PORT_RESET) != 0) + goto error; + + /* After above check the port must be connected. + * Set appropriate bit thus could put phy into low power + * mode if we have hostpc feature + */ + fotg210_writel(fotg210, temp | PORT_SUSPEND, + status_reg); + set_bit(wIndex, &fotg210->suspended_ports); + break; + case USB_PORT_FEAT_RESET: + if (temp & PORT_RESUME) + goto error; + /* line status bits may report this as low speed, + * which can be fine if this root hub has a + * transaction translator built in. + */ + fotg210_vdbg(fotg210, "port %d reset\n", wIndex + 1); + temp |= PORT_RESET; + temp &= ~PORT_PE; + + /* + * caller must wait, then call GetPortStatus + * usb 2.0 spec says 50 ms resets on root + */ + fotg210->reset_done[wIndex] = jiffies + + msecs_to_jiffies(50); + fotg210_writel(fotg210, temp, status_reg); + break; + + /* For downstream facing ports (these): one hub port is put + * into test mode according to USB2 11.24.2.13, then the hub + * must be reset (which for root hub now means rmmod+modprobe, + * or else system reboot). See EHCI 2.3.9 and 4.14 for info + * about the EHCI-specific stuff. + */ + case USB_PORT_FEAT_TEST: + if (!selector || selector > 5) + goto error; + spin_unlock_irqrestore(&fotg210->lock, flags); + fotg210_quiesce(fotg210); + spin_lock_irqsave(&fotg210->lock, flags); + + /* Put all enabled ports into suspend */ + temp = fotg210_readl(fotg210, status_reg) & + ~PORT_RWC_BITS; + if (temp & PORT_PE) + fotg210_writel(fotg210, temp | PORT_SUSPEND, + status_reg); + + spin_unlock_irqrestore(&fotg210->lock, flags); + fotg210_halt(fotg210); + spin_lock_irqsave(&fotg210->lock, flags); + + temp = fotg210_readl(fotg210, status_reg); + temp |= selector << 16; + fotg210_writel(fotg210, temp, status_reg); + break; + + default: + goto error; + } + fotg210_readl(fotg210, &fotg210->regs->command); + break; + + default: +error: + /* "stall" on error */ + retval = -EPIPE; + } + spin_unlock_irqrestore(&fotg210->lock, flags); + return retval; +} + +static void __maybe_unused fotg210_relinquish_port(struct usb_hcd *hcd, + int portnum) +{ + return; +} + +static int __maybe_unused fotg210_port_handed_over(struct usb_hcd *hcd, + int portnum) +{ + return 0; +} +/*-------------------------------------------------------------------------*/ +/* + * There's basically three types of memory: + * - data used only by the HCD ... kmalloc is fine + * - async and periodic schedules, shared by HC and HCD ... these + * need to use dma_pool or dma_alloc_coherent + * - driver buffers, read/written by HC ... single shot DMA mapped + * + * There's also "register" data (e.g. PCI or SOC), which is memory mapped. + * No memory seen by this driver is pageable. + */ + +/*-------------------------------------------------------------------------*/ + +/* Allocate the key transfer structures from the previously allocated pool */ + +static inline void fotg210_qtd_init(struct fotg210_hcd *fotg210, + struct fotg210_qtd *qtd, dma_addr_t dma) +{ + memset(qtd, 0, sizeof(*qtd)); + qtd->qtd_dma = dma; + qtd->hw_token = cpu_to_hc32(fotg210, QTD_STS_HALT); + qtd->hw_next = FOTG210_LIST_END(fotg210); + qtd->hw_alt_next = FOTG210_LIST_END(fotg210); + INIT_LIST_HEAD(&qtd->qtd_list); +} + +static struct fotg210_qtd *fotg210_qtd_alloc(struct fotg210_hcd *fotg210, + gfp_t flags) +{ + struct fotg210_qtd *qtd; + dma_addr_t dma; + + qtd = dma_pool_alloc(fotg210->qtd_pool, flags, &dma); + if (qtd != NULL) + fotg210_qtd_init(fotg210, qtd, dma); + + return qtd; +} + +static inline void fotg210_qtd_free(struct fotg210_hcd *fotg210, + struct fotg210_qtd *qtd) +{ + dma_pool_free(fotg210->qtd_pool, qtd, qtd->qtd_dma); +} + + +static void qh_destroy(struct fotg210_hcd *fotg210, struct fotg210_qh *qh) +{ + /* clean qtds first, and know this is not linked */ + if (!list_empty(&qh->qtd_list) || qh->qh_next.ptr) { + fotg210_dbg(fotg210, "unused qh not empty!\n"); + BUG(); + } + if (qh->dummy) + fotg210_qtd_free(fotg210, qh->dummy); + dma_pool_free(fotg210->qh_pool, qh->hw, qh->qh_dma); + kfree(qh); +} + +static struct fotg210_qh *fotg210_qh_alloc(struct fotg210_hcd *fotg210, + gfp_t flags) +{ + struct fotg210_qh *qh; + dma_addr_t dma; + + qh = kzalloc(sizeof(*qh), GFP_ATOMIC); + if (!qh) + goto done; + qh->hw = (struct fotg210_qh_hw *) + dma_pool_alloc(fotg210->qh_pool, flags, &dma); + if (!qh->hw) + goto fail; + memset(qh->hw, 0, sizeof(*qh->hw)); + qh->qh_dma = dma; + INIT_LIST_HEAD(&qh->qtd_list); + + /* dummy td enables safe urb queuing */ + qh->dummy = fotg210_qtd_alloc(fotg210, flags); + if (qh->dummy == NULL) { + fotg210_dbg(fotg210, "no dummy td\n"); + goto fail1; + } +done: + return qh; +fail1: + dma_pool_free(fotg210->qh_pool, qh->hw, qh->qh_dma); +fail: + kfree(qh); + return NULL; +} + +/*-------------------------------------------------------------------------*/ + +/* The queue heads and transfer descriptors are managed from pools tied + * to each of the "per device" structures. + * This is the initialisation and cleanup code. + */ + +static void fotg210_mem_cleanup(struct fotg210_hcd *fotg210) +{ + if (fotg210->async) + qh_destroy(fotg210, fotg210->async); + fotg210->async = NULL; + + if (fotg210->dummy) + qh_destroy(fotg210, fotg210->dummy); + fotg210->dummy = NULL; + + /* DMA consistent memory and pools */ + if (fotg210->qtd_pool) + dma_pool_destroy(fotg210->qtd_pool); + fotg210->qtd_pool = NULL; + + if (fotg210->qh_pool) { + dma_pool_destroy(fotg210->qh_pool); + fotg210->qh_pool = NULL; + } + + if (fotg210->itd_pool) + dma_pool_destroy(fotg210->itd_pool); + fotg210->itd_pool = NULL; + + if (fotg210->periodic) + dma_free_coherent(fotg210_to_hcd(fotg210)->self.controller, + fotg210->periodic_size * sizeof(u32), + fotg210->periodic, fotg210->periodic_dma); + fotg210->periodic = NULL; + + /* shadow periodic table */ + kfree(fotg210->pshadow); + fotg210->pshadow = NULL; +} + +/* remember to add cleanup code (above) if you add anything here */ +static int fotg210_mem_init(struct fotg210_hcd *fotg210, gfp_t flags) +{ + int i; + + /* QTDs for control/bulk/intr transfers */ + fotg210->qtd_pool = dma_pool_create("fotg210_qtd", + fotg210_to_hcd(fotg210)->self.controller, + sizeof(struct fotg210_qtd), + 32 /* byte alignment (for hw parts) */, + 4096 /* can't cross 4K */); + if (!fotg210->qtd_pool) + goto fail; + + /* QHs for control/bulk/intr transfers */ + fotg210->qh_pool = dma_pool_create("fotg210_qh", + fotg210_to_hcd(fotg210)->self.controller, + sizeof(struct fotg210_qh_hw), + 32 /* byte alignment (for hw parts) */, + 4096 /* can't cross 4K */); + if (!fotg210->qh_pool) + goto fail; + + fotg210->async = fotg210_qh_alloc(fotg210, flags); + if (!fotg210->async) + goto fail; + + /* ITD for high speed ISO transfers */ + fotg210->itd_pool = dma_pool_create("fotg210_itd", + fotg210_to_hcd(fotg210)->self.controller, + sizeof(struct fotg210_itd), + 64 /* byte alignment (for hw parts) */, + 4096 /* can't cross 4K */); + if (!fotg210->itd_pool) + goto fail; + + /* Hardware periodic table */ + fotg210->periodic = (__le32 *) + dma_alloc_coherent(fotg210_to_hcd(fotg210)->self.controller, + fotg210->periodic_size * sizeof(__le32), + &fotg210->periodic_dma, 0); + if (fotg210->periodic == NULL) + goto fail; + + for (i = 0; i < fotg210->periodic_size; i++) + fotg210->periodic[i] = FOTG210_LIST_END(fotg210); + + /* software shadow of hardware table */ + fotg210->pshadow = kcalloc(fotg210->periodic_size, sizeof(void *), + flags); + if (fotg210->pshadow != NULL) + return 0; + +fail: + fotg210_dbg(fotg210, "couldn't init memory\n"); + fotg210_mem_cleanup(fotg210); + return -ENOMEM; +} +/*-------------------------------------------------------------------------*/ +/* + * EHCI hardware queue manipulation ... the core. QH/QTD manipulation. + * + * Control, bulk, and interrupt traffic all use "qh" lists. They list "qtd" + * entries describing USB transactions, max 16-20kB/entry (with 4kB-aligned + * buffers needed for the larger number). We use one QH per endpoint, queue + * multiple urbs (all three types) per endpoint. URBs may need several qtds. + * + * ISO traffic uses "ISO TD" (itd) records, and (along with + * interrupts) needs careful scheduling. Performance improvements can be + * an ongoing challenge. That's in "ehci-sched.c". + * + * USB 1.1 devices are handled (a) by "companion" OHCI or UHCI root hubs, + * or otherwise through transaction translators (TTs) in USB 2.0 hubs using + * (b) special fields in qh entries or (c) split iso entries. TTs will + * buffer low/full speed data so the host collects it at high speed. + */ + +/*-------------------------------------------------------------------------*/ + +/* fill a qtd, returning how much of the buffer we were able to queue up */ + +static int +qtd_fill(struct fotg210_hcd *fotg210, struct fotg210_qtd *qtd, dma_addr_t buf, + size_t len, int token, int maxpacket) +{ + int i, count; + u64 addr = buf; + + /* one buffer entry per 4K ... first might be short or unaligned */ + qtd->hw_buf[0] = cpu_to_hc32(fotg210, (u32)addr); + qtd->hw_buf_hi[0] = cpu_to_hc32(fotg210, (u32)(addr >> 32)); + count = 0x1000 - (buf & 0x0fff); /* rest of that page */ + if (likely(len < count)) /* ... iff needed */ + count = len; + else { + buf += 0x1000; + buf &= ~0x0fff; + + /* per-qtd limit: from 16K to 20K (best alignment) */ + for (i = 1; count < len && i < 5; i++) { + addr = buf; + qtd->hw_buf[i] = cpu_to_hc32(fotg210, (u32)addr); + qtd->hw_buf_hi[i] = cpu_to_hc32(fotg210, + (u32)(addr >> 32)); + buf += 0x1000; + if ((count + 0x1000) < len) + count += 0x1000; + else + count = len; + } + + /* short packets may only terminate transfers */ + if (count != len) + count -= (count % maxpacket); + } + qtd->hw_token = cpu_to_hc32(fotg210, (count << 16) | token); + qtd->length = count; + + return count; +} + +/*-------------------------------------------------------------------------*/ + +static inline void +qh_update(struct fotg210_hcd *fotg210, struct fotg210_qh *qh, + struct fotg210_qtd *qtd) +{ + struct fotg210_qh_hw *hw = qh->hw; + + /* writes to an active overlay are unsafe */ + BUG_ON(qh->qh_state != QH_STATE_IDLE); + + hw->hw_qtd_next = QTD_NEXT(fotg210, qtd->qtd_dma); + hw->hw_alt_next = FOTG210_LIST_END(fotg210); + + /* Except for control endpoints, we make hardware maintain data + * toggle (like OHCI) ... here (re)initialize the toggle in the QH, + * and set the pseudo-toggle in udev. Only usb_clear_halt() will + * ever clear it. + */ + if (!(hw->hw_info1 & cpu_to_hc32(fotg210, QH_TOGGLE_CTL))) { + unsigned is_out, epnum; + + is_out = qh->is_out; + epnum = (hc32_to_cpup(fotg210, &hw->hw_info1) >> 8) & 0x0f; + if (unlikely(!usb_gettoggle(qh->dev, epnum, is_out))) { + hw->hw_token &= ~cpu_to_hc32(fotg210, QTD_TOGGLE); + usb_settoggle(qh->dev, epnum, is_out, 1); + } + } + + hw->hw_token &= cpu_to_hc32(fotg210, QTD_TOGGLE | QTD_STS_PING); +} + +/* if it weren't for a common silicon quirk (writing the dummy into the qh + * overlay, so qh->hw_token wrongly becomes inactive/halted), only fault + * recovery (including urb dequeue) would need software changes to a QH... + */ +static void +qh_refresh(struct fotg210_hcd *fotg210, struct fotg210_qh *qh) +{ + struct fotg210_qtd *qtd; + + if (list_empty(&qh->qtd_list)) + qtd = qh->dummy; + else { + qtd = list_entry(qh->qtd_list.next, + struct fotg210_qtd, qtd_list); + /* + * first qtd may already be partially processed. + * If we come here during unlink, the QH overlay region + * might have reference to the just unlinked qtd. The + * qtd is updated in qh_completions(). Update the QH + * overlay here. + */ + if (cpu_to_hc32(fotg210, qtd->qtd_dma) == qh->hw->hw_current) { + qh->hw->hw_qtd_next = qtd->hw_next; + qtd = NULL; + } + } + + if (qtd) + qh_update(fotg210, qh, qtd); +} + +/*-------------------------------------------------------------------------*/ + +static void qh_link_async(struct fotg210_hcd *fotg210, struct fotg210_qh *qh); + +static void fotg210_clear_tt_buffer_complete(struct usb_hcd *hcd, + struct usb_host_endpoint *ep) +{ + struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); + struct fotg210_qh *qh = ep->hcpriv; + unsigned long flags; + + spin_lock_irqsave(&fotg210->lock, flags); + qh->clearing_tt = 0; + if (qh->qh_state == QH_STATE_IDLE && !list_empty(&qh->qtd_list) + && fotg210->rh_state == FOTG210_RH_RUNNING) + qh_link_async(fotg210, qh); + spin_unlock_irqrestore(&fotg210->lock, flags); +} + +static void fotg210_clear_tt_buffer(struct fotg210_hcd *fotg210, + struct fotg210_qh *qh, + struct urb *urb, u32 token) +{ + + /* If an async split transaction gets an error or is unlinked, + * the TT buffer may be left in an indeterminate state. We + * have to clear the TT buffer. + * + * Note: this routine is never called for Isochronous transfers. + */ + if (urb->dev->tt && !usb_pipeint(urb->pipe) && !qh->clearing_tt) { +#ifdef DEBUG + struct usb_device *tt = urb->dev->tt->hub; + dev_dbg(&tt->dev, + "clear tt buffer port %d, a%d ep%d t%08x\n", + urb->dev->ttport, urb->dev->devnum, + usb_pipeendpoint(urb->pipe), token); +#endif /* DEBUG */ + if (urb->dev->tt->hub != + fotg210_to_hcd(fotg210)->self.root_hub) { + if (usb_hub_clear_tt_buffer(urb) == 0) + qh->clearing_tt = 1; + } + } +} + +static int qtd_copy_status( + struct fotg210_hcd *fotg210, + struct urb *urb, + size_t length, + u32 token +) +{ + int status = -EINPROGRESS; + + /* count IN/OUT bytes, not SETUP (even short packets) */ + if (likely(QTD_PID(token) != 2)) + urb->actual_length += length - QTD_LENGTH(token); + + /* don't modify error codes */ + if (unlikely(urb->unlinked)) + return status; + + /* force cleanup after short read; not always an error */ + if (unlikely(IS_SHORT_READ(token))) + status = -EREMOTEIO; + + /* serious "can't proceed" faults reported by the hardware */ + if (token & QTD_STS_HALT) { + if (token & QTD_STS_BABBLE) { + /* FIXME "must" disable babbling device's port too */ + status = -EOVERFLOW; + /* CERR nonzero + halt --> stall */ + } else if (QTD_CERR(token)) { + status = -EPIPE; + + /* In theory, more than one of the following bits can be set + * since they are sticky and the transaction is retried. + * Which to test first is rather arbitrary. + */ + } else if (token & QTD_STS_MMF) { + /* fs/ls interrupt xfer missed the complete-split */ + status = -EPROTO; + } else if (token & QTD_STS_DBE) { + status = (QTD_PID(token) == 1) /* IN ? */ + ? -ENOSR /* hc couldn't read data */ + : -ECOMM; /* hc couldn't write data */ + } else if (token & QTD_STS_XACT) { + /* timeout, bad CRC, wrong PID, etc */ + fotg210_dbg(fotg210, "devpath %s ep%d%s 3strikes\n", + urb->dev->devpath, + usb_pipeendpoint(urb->pipe), + usb_pipein(urb->pipe) ? "in" : "out"); + status = -EPROTO; + } else { /* unknown */ + status = -EPROTO; + } + + fotg210_vdbg(fotg210, + "dev%d ep%d%s qtd token %08x --> status %d\n", + usb_pipedevice(urb->pipe), + usb_pipeendpoint(urb->pipe), + usb_pipein(urb->pipe) ? "in" : "out", + token, status); + } + + return status; +} + +static void +fotg210_urb_done(struct fotg210_hcd *fotg210, struct urb *urb, int status) +__releases(fotg210->lock) +__acquires(fotg210->lock) +{ + if (likely(urb->hcpriv != NULL)) { + struct fotg210_qh *qh = (struct fotg210_qh *) urb->hcpriv; + + /* S-mask in a QH means it's an interrupt urb */ + if ((qh->hw->hw_info2 & cpu_to_hc32(fotg210, QH_SMASK)) != 0) { + + /* ... update hc-wide periodic stats (for usbfs) */ + fotg210_to_hcd(fotg210)->self.bandwidth_int_reqs--; + } + } + + if (unlikely(urb->unlinked)) { + COUNT(fotg210->stats.unlink); + } else { + /* report non-error and short read status as zero */ + if (status == -EINPROGRESS || status == -EREMOTEIO) + status = 0; + COUNT(fotg210->stats.complete); + } + +#ifdef FOTG210_URB_TRACE + fotg210_dbg(fotg210, + "%s %s urb %p ep%d%s status %d len %d/%d\n", + __func__, urb->dev->devpath, urb, + usb_pipeendpoint(urb->pipe), + usb_pipein(urb->pipe) ? "in" : "out", + status, + urb->actual_length, urb->transfer_buffer_length); +#endif + + /* complete() can reenter this HCD */ + usb_hcd_unlink_urb_from_ep(fotg210_to_hcd(fotg210), urb); + spin_unlock(&fotg210->lock); + usb_hcd_giveback_urb(fotg210_to_hcd(fotg210), urb, status); + spin_lock(&fotg210->lock); +} + +static int qh_schedule(struct fotg210_hcd *fotg210, struct fotg210_qh *qh); + +/* + * Process and free completed qtds for a qh, returning URBs to drivers. + * Chases up to qh->hw_current. Returns number of completions called, + * indicating how much "real" work we did. + */ +static unsigned +qh_completions(struct fotg210_hcd *fotg210, struct fotg210_qh *qh) +{ + struct fotg210_qtd *last, *end = qh->dummy; + struct list_head *entry, *tmp; + int last_status; + int stopped; + unsigned count = 0; + u8 state; + struct fotg210_qh_hw *hw = qh->hw; + + if (unlikely(list_empty(&qh->qtd_list))) + return count; + + /* completions (or tasks on other cpus) must never clobber HALT + * till we've gone through and cleaned everything up, even when + * they add urbs to this qh's queue or mark them for unlinking. + * + * NOTE: unlinking expects to be done in queue order. + * + * It's a bug for qh->qh_state to be anything other than + * QH_STATE_IDLE, unless our caller is scan_async() or + * scan_intr(). + */ + state = qh->qh_state; + qh->qh_state = QH_STATE_COMPLETING; + stopped = (state == QH_STATE_IDLE); + + rescan: + last = NULL; + last_status = -EINPROGRESS; + qh->needs_rescan = 0; + + /* remove de-activated QTDs from front of queue. + * after faults (including short reads), cleanup this urb + * then let the queue advance. + * if queue is stopped, handles unlinks. + */ + list_for_each_safe(entry, tmp, &qh->qtd_list) { + struct fotg210_qtd *qtd; + struct urb *urb; + u32 token = 0; + + qtd = list_entry(entry, struct fotg210_qtd, qtd_list); + urb = qtd->urb; + + /* clean up any state from previous QTD ...*/ + if (last) { + if (likely(last->urb != urb)) { + fotg210_urb_done(fotg210, last->urb, + last_status); + count++; + last_status = -EINPROGRESS; + } + fotg210_qtd_free(fotg210, last); + last = NULL; + } + + /* ignore urbs submitted during completions we reported */ + if (qtd == end) + break; + + /* hardware copies qtd out of qh overlay */ + rmb(); + token = hc32_to_cpu(fotg210, qtd->hw_token); + + /* always clean up qtds the hc de-activated */ + retry_xacterr: + if ((token & QTD_STS_ACTIVE) == 0) { + + /* Report Data Buffer Error: non-fatal but useful */ + if (token & QTD_STS_DBE) + fotg210_dbg(fotg210, + "detected DataBufferErr for urb %p ep%d%s len %d, qtd %p [qh %p]\n", + urb, + usb_endpoint_num(&urb->ep->desc), + usb_endpoint_dir_in(&urb->ep->desc) + ? "in" : "out", + urb->transfer_buffer_length, + qtd, + qh); + + /* 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 < QH_XACTERR_MAX && + !urb->unlinked) { + fotg210_dbg(fotg210, + "detected XactErr len %zu/%zu retry %d\n", + qtd->length - QTD_LENGTH(token), qtd->length, 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 | + (FOTG210_TUNE_CERR << 10); + qtd->hw_token = cpu_to_hc32(fotg210, + token); + wmb(); + hw->hw_token = cpu_to_hc32(fotg210, + token); + goto retry_xacterr; + } + stopped = 1; + + /* magic dummy for some short reads; qh won't advance. + * that silicon quirk can kick in with this dummy too. + * + * other short reads won't stop the queue, including + * control transfers (status stage handles that) or + * most other single-qtd reads ... the queue stops if + * URB_SHORT_NOT_OK was set so the driver submitting + * the urbs could clean it up. + */ + } else if (IS_SHORT_READ(token) + && !(qtd->hw_alt_next + & FOTG210_LIST_END(fotg210))) { + stopped = 1; + } + + /* stop scanning when we reach qtds the hc is using */ + } else if (likely(!stopped + && fotg210->rh_state >= FOTG210_RH_RUNNING)) { + break; + + /* scan the whole queue for unlinks whenever it stops */ + } else { + stopped = 1; + + /* cancel everything if we halt, suspend, etc */ + if (fotg210->rh_state < FOTG210_RH_RUNNING) + last_status = -ESHUTDOWN; + + /* this qtd is active; skip it unless a previous qtd + * for its urb faulted, or its urb was canceled. + */ + else if (last_status == -EINPROGRESS && !urb->unlinked) + continue; + + /* qh unlinked; token in overlay may be most current */ + if (state == QH_STATE_IDLE + && cpu_to_hc32(fotg210, qtd->qtd_dma) + == hw->hw_current) { + token = hc32_to_cpu(fotg210, hw->hw_token); + + /* An unlink may leave an incomplete + * async transaction in the TT buffer. + * We have to clear it. + */ + fotg210_clear_tt_buffer(fotg210, qh, urb, + token); + } + } + + /* unless we already know the urb's status, collect qtd status + * and update count of bytes transferred. in common short read + * cases with only one data qtd (including control transfers), + * queue processing won't halt. but with two or more qtds (for + * example, with a 32 KB transfer), when the first qtd gets a + * short read the second must be removed by hand. + */ + if (last_status == -EINPROGRESS) { + last_status = qtd_copy_status(fotg210, urb, + qtd->length, token); + if (last_status == -EREMOTEIO + && (qtd->hw_alt_next + & FOTG210_LIST_END(fotg210))) + last_status = -EINPROGRESS; + + /* As part of low/full-speed endpoint-halt processing + * we must clear the TT buffer (11.17.5). + */ + if (unlikely(last_status != -EINPROGRESS && + last_status != -EREMOTEIO)) { + /* The TT's in some hubs malfunction when they + * receive this request following a STALL (they + * stop sending isochronous packets). Since a + * STALL can't leave the TT buffer in a busy + * state (if you believe Figures 11-48 - 11-51 + * in the USB 2.0 spec), we won't clear the TT + * buffer in this case. Strictly speaking this + * is a violation of the spec. + */ + if (last_status != -EPIPE) + fotg210_clear_tt_buffer(fotg210, qh, + urb, token); + } + } + + /* if we're removing something not at the queue head, + * patch the hardware queue pointer. + */ + if (stopped && qtd->qtd_list.prev != &qh->qtd_list) { + last = list_entry(qtd->qtd_list.prev, + struct fotg210_qtd, qtd_list); + last->hw_next = qtd->hw_next; + } + + /* 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 = 0; + } + + /* last urb's completion might still need calling */ + if (likely(last != NULL)) { + fotg210_urb_done(fotg210, last->urb, last_status); + count++; + fotg210_qtd_free(fotg210, last); + } + + /* Do we need to rescan for URBs dequeued during a giveback? */ + if (unlikely(qh->needs_rescan)) { + /* If the QH is already unlinked, do the rescan now. */ + if (state == QH_STATE_IDLE) + goto rescan; + + /* Otherwise we have to wait until the QH is fully unlinked. + * Our caller will start an unlink if qh->needs_rescan is + * set. But if an unlink has already started, nothing needs + * to be done. + */ + if (state != QH_STATE_LINKED) + qh->needs_rescan = 0; + } + + /* restore original state; caller must unlink or relink */ + qh->qh_state = state; + + /* be sure the hardware's done with the qh before refreshing + * it after fault cleanup, or recovering from silicon wrongly + * overlaying the dummy qtd (which reduces DMA chatter). + */ + if (stopped != 0 || hw->hw_qtd_next == FOTG210_LIST_END(fotg210)) { + switch (state) { + case QH_STATE_IDLE: + qh_refresh(fotg210, qh); + break; + case QH_STATE_LINKED: + /* We won't refresh a QH that's linked (after the HC + * stopped the queue). That avoids a race: + * - HC reads first part of QH; + * - CPU updates that first part and the token; + * - HC reads rest of that QH, including token + * Result: HC gets an inconsistent image, and then + * DMAs to/from the wrong memory (corrupting it). + * + * That should be rare for interrupt transfers, + * except maybe high bandwidth ... + */ + + /* Tell the caller to start an unlink */ + qh->needs_rescan = 1; + break; + /* otherwise, unlink already started */ + } + } + + return count; +} + +/*-------------------------------------------------------------------------*/ + +/* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */ +#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03)) +/* ... and packet size, for any kind of endpoint descriptor */ +#define max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff) + +/* + * reverse of qh_urb_transaction: free a list of TDs. + * used for cleanup after errors, before HC sees an URB's TDs. + */ +static void qtd_list_free( + struct fotg210_hcd *fotg210, + struct urb *urb, + struct list_head *qtd_list +) { + struct list_head *entry, *temp; + + list_for_each_safe(entry, temp, qtd_list) { + struct fotg210_qtd *qtd; + + qtd = list_entry(entry, struct fotg210_qtd, qtd_list); + list_del(&qtd->qtd_list); + fotg210_qtd_free(fotg210, qtd); + } +} + +/* + * create a list of filled qtds for this URB; won't link into qh. + */ +static struct list_head * +qh_urb_transaction( + struct fotg210_hcd *fotg210, + struct urb *urb, + struct list_head *head, + gfp_t flags +) { + struct fotg210_qtd *qtd, *qtd_prev; + dma_addr_t buf; + int len, this_sg_len, maxpacket; + int is_input; + u32 token; + int i; + struct scatterlist *sg; + + /* + * URBs map to sequences of QTDs: one logical transaction + */ + qtd = fotg210_qtd_alloc(fotg210, flags); + if (unlikely(!qtd)) + return NULL; + list_add_tail(&qtd->qtd_list, head); + qtd->urb = urb; + + token = QTD_STS_ACTIVE; + token |= (FOTG210_TUNE_CERR << 10); + /* for split transactions, SplitXState initialized to zero */ + + len = urb->transfer_buffer_length; + is_input = usb_pipein(urb->pipe); + if (usb_pipecontrol(urb->pipe)) { + /* SETUP pid */ + qtd_fill(fotg210, qtd, urb->setup_dma, + sizeof(struct usb_ctrlrequest), + token | (2 /* "setup" */ << 8), 8); + + /* ... and always at least one more pid */ + token ^= QTD_TOGGLE; + qtd_prev = qtd; + qtd = fotg210_qtd_alloc(fotg210, flags); + if (unlikely(!qtd)) + goto cleanup; + qtd->urb = urb; + qtd_prev->hw_next = QTD_NEXT(fotg210, qtd->qtd_dma); + list_add_tail(&qtd->qtd_list, head); + + /* for zero length DATA stages, STATUS is always IN */ + if (len == 0) + token |= (1 /* "in" */ << 8); + } + + /* + * data transfer stage: buffer setup + */ + i = urb->num_mapped_sgs; + if (len > 0 && i > 0) { + sg = urb->sg; + buf = sg_dma_address(sg); + + /* urb->transfer_buffer_length may be smaller than the + * size of the scatterlist (or vice versa) + */ + this_sg_len = min_t(int, sg_dma_len(sg), len); + } else { + sg = NULL; + buf = urb->transfer_dma; + this_sg_len = len; + } + + if (is_input) + token |= (1 /* "in" */ << 8); + /* else it's already initted to "out" pid (0 << 8) */ + + maxpacket = max_packet(usb_maxpacket(urb->dev, urb->pipe, !is_input)); + + /* + * buffer gets wrapped in one or more qtds; + * last one may be "short" (including zero len) + * and may serve as a control status ack + */ + for (;;) { + int this_qtd_len; + + this_qtd_len = qtd_fill(fotg210, qtd, buf, this_sg_len, token, + maxpacket); + this_sg_len -= this_qtd_len; + len -= this_qtd_len; + buf += this_qtd_len; + + /* + * short reads advance to a "magic" dummy instead of the next + * qtd ... that forces the queue to stop, for manual cleanup. + * (this will usually be overridden later.) + */ + if (is_input) + qtd->hw_alt_next = fotg210->async->hw->hw_alt_next; + + /* qh makes control packets use qtd toggle; maybe switch it */ + if ((maxpacket & (this_qtd_len + (maxpacket - 1))) == 0) + token ^= QTD_TOGGLE; + + if (likely(this_sg_len <= 0)) { + if (--i <= 0 || len <= 0) + break; + sg = sg_next(sg); + buf = sg_dma_address(sg); + this_sg_len = min_t(int, sg_dma_len(sg), len); + } + + qtd_prev = qtd; + qtd = fotg210_qtd_alloc(fotg210, flags); + if (unlikely(!qtd)) + goto cleanup; + qtd->urb = urb; + qtd_prev->hw_next = QTD_NEXT(fotg210, qtd->qtd_dma); + list_add_tail(&qtd->qtd_list, head); + } + + /* + * unless the caller requires manual cleanup after short reads, + * have the alt_next mechanism keep the queue running after the + * last data qtd (the only one, for control and most other cases). + */ + if (likely((urb->transfer_flags & URB_SHORT_NOT_OK) == 0 + || usb_pipecontrol(urb->pipe))) + qtd->hw_alt_next = FOTG210_LIST_END(fotg210); + + /* + * control requests may need a terminating data "status" ack; + * other OUT ones may need a terminating short packet + * (zero length). + */ + if (likely(urb->transfer_buffer_length != 0)) { + int one_more = 0; + + if (usb_pipecontrol(urb->pipe)) { + one_more = 1; + token ^= 0x0100; /* "in" <--> "out" */ + token |= QTD_TOGGLE; /* force DATA1 */ + } else if (usb_pipeout(urb->pipe) + && (urb->transfer_flags & URB_ZERO_PACKET) + && !(urb->transfer_buffer_length % maxpacket)) { + one_more = 1; + } + if (one_more) { + qtd_prev = qtd; + qtd = fotg210_qtd_alloc(fotg210, flags); + if (unlikely(!qtd)) + goto cleanup; + qtd->urb = urb; + qtd_prev->hw_next = QTD_NEXT(fotg210, qtd->qtd_dma); + list_add_tail(&qtd->qtd_list, head); + + /* never any data in such packets */ + qtd_fill(fotg210, qtd, 0, 0, token, 0); + } + } + + /* by default, enable interrupt on urb completion */ + if (likely(!(urb->transfer_flags & URB_NO_INTERRUPT))) + qtd->hw_token |= cpu_to_hc32(fotg210, QTD_IOC); + return head; + +cleanup: + qtd_list_free(fotg210, urb, head); + return NULL; +} + +/*-------------------------------------------------------------------------*/ +/* + * Would be best to create all qh's from config descriptors, + * when each interface/altsetting is established. Unlink + * any previous qh and cancel its urbs first; endpoints are + * implicitly reset then (data toggle too). + * That'd mean updating how usbcore talks to HCDs. (2.7?) +*/ + + +/* + * Each QH holds a qtd list; a QH is used for everything except iso. + * + * For interrupt urbs, the scheduler must set the microframe scheduling + * mask(s) each time the QH gets scheduled. For highspeed, that's + * just one microframe in the s-mask. For split interrupt transactions + * there are additional complications: c-mask, maybe FSTNs. + */ +static struct fotg210_qh * +qh_make( + struct fotg210_hcd *fotg210, + struct urb *urb, + gfp_t flags +) { + struct fotg210_qh *qh = fotg210_qh_alloc(fotg210, flags); + u32 info1 = 0, info2 = 0; + int is_input, type; + int maxp = 0; + struct usb_tt *tt = urb->dev->tt; + struct fotg210_qh_hw *hw; + + if (!qh) + return qh; + + /* + * init endpoint/device data for this QH + */ + info1 |= usb_pipeendpoint(urb->pipe) << 8; + info1 |= usb_pipedevice(urb->pipe) << 0; + + is_input = usb_pipein(urb->pipe); + type = usb_pipetype(urb->pipe); + maxp = usb_maxpacket(urb->dev, urb->pipe, !is_input); + + /* 1024 byte maxpacket is a hardware ceiling. High bandwidth + * acts like up to 3KB, but is built from smaller packets. + */ + if (max_packet(maxp) > 1024) { + fotg210_dbg(fotg210, "bogus qh maxpacket %d\n", + max_packet(maxp)); + goto done; + } + + /* Compute interrupt scheduling parameters just once, and save. + * - allowing for high bandwidth, how many nsec/uframe are used? + * - split transactions need a second CSPLIT uframe; same question + * - splits also need a schedule gap (for full/low speed I/O) + * - qh has a polling interval + * + * For control/bulk requests, the HC or TT handles these. + */ + if (type == PIPE_INTERRUPT) { + qh->usecs = NS_TO_US(usb_calc_bus_time(USB_SPEED_HIGH, + is_input, 0, + hb_mult(maxp) * max_packet(maxp))); + qh->start = NO_FRAME; + + if (urb->dev->speed == USB_SPEED_HIGH) { + qh->c_usecs = 0; + qh->gap_uf = 0; + + qh->period = urb->interval >> 3; + if (qh->period == 0 && urb->interval != 1) { + /* NOTE interval 2 or 4 uframes could work. + * But interval 1 scheduling is simpler, and + * includes high bandwidth. + */ + urb->interval = 1; + } else if (qh->period > fotg210->periodic_size) { + qh->period = fotg210->periodic_size; + urb->interval = qh->period << 3; + } + } else { + int think_time; + + /* gap is f(FS/LS transfer times) */ + qh->gap_uf = 1 + usb_calc_bus_time(urb->dev->speed, + is_input, 0, maxp) / (125 * 1000); + + /* FIXME this just approximates SPLIT/CSPLIT times */ + if (is_input) { /* SPLIT, gap, CSPLIT+DATA */ + qh->c_usecs = qh->usecs + HS_USECS(0); + qh->usecs = HS_USECS(1); + } else { /* SPLIT+DATA, gap, CSPLIT */ + qh->usecs += HS_USECS(1); + qh->c_usecs = HS_USECS(0); + } + + think_time = tt ? tt->think_time : 0; + qh->tt_usecs = NS_TO_US(think_time + + usb_calc_bus_time(urb->dev->speed, + is_input, 0, max_packet(maxp))); + qh->period = urb->interval; + if (qh->period > fotg210->periodic_size) { + qh->period = fotg210->periodic_size; + urb->interval = qh->period; + } + } + } + + /* support for tt scheduling, and access to toggles */ + qh->dev = urb->dev; + + /* using TT? */ + switch (urb->dev->speed) { + case USB_SPEED_LOW: + info1 |= QH_LOW_SPEED; + /* FALL THROUGH */ + + case USB_SPEED_FULL: + /* EPS 0 means "full" */ + if (type != PIPE_INTERRUPT) + info1 |= (FOTG210_TUNE_RL_TT << 28); + if (type == PIPE_CONTROL) { + info1 |= QH_CONTROL_EP; /* for TT */ + info1 |= QH_TOGGLE_CTL; /* toggle from qtd */ + } + info1 |= maxp << 16; + + info2 |= (FOTG210_TUNE_MULT_TT << 30); + + /* Some Freescale processors have an erratum in which the + * port number in the queue head was 0..N-1 instead of 1..N. + */ + if (fotg210_has_fsl_portno_bug(fotg210)) + info2 |= (urb->dev->ttport-1) << 23; + else + info2 |= urb->dev->ttport << 23; + + /* set the address of the TT; for TDI's integrated + * root hub tt, leave it zeroed. + */ + if (tt && tt->hub != fotg210_to_hcd(fotg210)->self.root_hub) + info2 |= tt->hub->devnum << 16; + + /* NOTE: if (PIPE_INTERRUPT) { scheduler sets c-mask } */ + + break; + + case USB_SPEED_HIGH: /* no TT involved */ + info1 |= QH_HIGH_SPEED; + if (type == PIPE_CONTROL) { + info1 |= (FOTG210_TUNE_RL_HS << 28); + info1 |= 64 << 16; /* usb2 fixed maxpacket */ + info1 |= QH_TOGGLE_CTL; /* toggle from qtd */ + info2 |= (FOTG210_TUNE_MULT_HS << 30); + } else if (type == PIPE_BULK) { + info1 |= (FOTG210_TUNE_RL_HS << 28); + /* The USB spec says that high speed bulk endpoints + * always use 512 byte maxpacket. But some device + * vendors decided to ignore that, and MSFT is happy + * to help them do so. So now people expect to use + * such nonconformant devices with Linux too; sigh. + */ + info1 |= max_packet(maxp) << 16; + info2 |= (FOTG210_TUNE_MULT_HS << 30); + } else { /* PIPE_INTERRUPT */ + info1 |= max_packet(maxp) << 16; + info2 |= hb_mult(maxp) << 30; + } + break; + default: + fotg210_dbg(fotg210, "bogus dev %p speed %d\n", urb->dev, + urb->dev->speed); +done: + qh_destroy(fotg210, qh); + return NULL; + } + + /* NOTE: if (PIPE_INTERRUPT) { scheduler sets s-mask } */ + + /* init as live, toggle clear, advance to dummy */ + qh->qh_state = QH_STATE_IDLE; + hw = qh->hw; + hw->hw_info1 = cpu_to_hc32(fotg210, info1); + hw->hw_info2 = cpu_to_hc32(fotg210, info2); + qh->is_out = !is_input; + usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), !is_input, 1); + qh_refresh(fotg210, qh); + return qh; +} + +/*-------------------------------------------------------------------------*/ + +static void enable_async(struct fotg210_hcd *fotg210) +{ + if (fotg210->async_count++) + return; + + /* Stop waiting to turn off the async schedule */ + fotg210->enabled_hrtimer_events &= ~BIT(FOTG210_HRTIMER_DISABLE_ASYNC); + + /* Don't start the schedule until ASS is 0 */ + fotg210_poll_ASS(fotg210); + turn_on_io_watchdog(fotg210); +} + +static void disable_async(struct fotg210_hcd *fotg210) +{ + if (--fotg210->async_count) + return; + + /* The async schedule and async_unlink list are supposed to be empty */ + WARN_ON(fotg210->async->qh_next.qh || fotg210->async_unlink); + + /* Don't turn off the schedule until ASS is 1 */ + fotg210_poll_ASS(fotg210); +} + +/* move qh (and its qtds) onto async queue; maybe enable queue. */ + +static void qh_link_async(struct fotg210_hcd *fotg210, struct fotg210_qh *qh) +{ + __hc32 dma = QH_NEXT(fotg210, qh->qh_dma); + struct fotg210_qh *head; + + /* Don't link a QH if there's a Clear-TT-Buffer pending */ + if (unlikely(qh->clearing_tt)) + return; + + WARN_ON(qh->qh_state != QH_STATE_IDLE); + + /* clear halt and/or toggle; and maybe recover from silicon quirk */ + qh_refresh(fotg210, qh); + + /* splice right after start */ + head = fotg210->async; + qh->qh_next = head->qh_next; + qh->hw->hw_next = head->hw->hw_next; + wmb(); + + head->qh_next.qh = qh; + head->hw->hw_next = dma; + + qh->xacterrs = 0; + qh->qh_state = QH_STATE_LINKED; + /* qtd completions reported later by interrupt */ + + enable_async(fotg210); +} + +/*-------------------------------------------------------------------------*/ + +/* + * For control/bulk/interrupt, return QH with these TDs appended. + * Allocates and initializes the QH if necessary. + * Returns null if it can't allocate a QH it needs to. + * If the QH has TDs (urbs) already, that's great. + */ +static struct fotg210_qh *qh_append_tds( + struct fotg210_hcd *fotg210, + struct urb *urb, + struct list_head *qtd_list, + int epnum, + void **ptr +) +{ + struct fotg210_qh *qh = NULL; + __hc32 qh_addr_mask = cpu_to_hc32(fotg210, 0x7f); + + qh = (struct fotg210_qh *) *ptr; + if (unlikely(qh == NULL)) { + /* can't sleep here, we have fotg210->lock... */ + qh = qh_make(fotg210, urb, GFP_ATOMIC); + *ptr = qh; + } + if (likely(qh != NULL)) { + struct fotg210_qtd *qtd; + + if (unlikely(list_empty(qtd_list))) + qtd = NULL; + else + qtd = list_entry(qtd_list->next, struct fotg210_qtd, + qtd_list); + + /* control qh may need patching ... */ + if (unlikely(epnum == 0)) { + /* usb_reset_device() briefly reverts to address 0 */ + if (usb_pipedevice(urb->pipe) == 0) + qh->hw->hw_info1 &= ~qh_addr_mask; + } + + /* just one way to queue requests: swap with the dummy qtd. + * only hc or qh_refresh() ever modify the overlay. + */ + if (likely(qtd != NULL)) { + struct fotg210_qtd *dummy; + dma_addr_t dma; + __hc32 token; + + /* to avoid racing the HC, use the dummy td instead of + * the first td of our list (becomes new dummy). both + * tds stay deactivated until we're done, when the + * HC is allowed to fetch the old dummy (4.10.2). + */ + token = qtd->hw_token; + qtd->hw_token = HALT_BIT(fotg210); + + dummy = qh->dummy; + + dma = dummy->qtd_dma; + *dummy = *qtd; + dummy->qtd_dma = dma; + + list_del(&qtd->qtd_list); + list_add(&dummy->qtd_list, qtd_list); + list_splice_tail(qtd_list, &qh->qtd_list); + + fotg210_qtd_init(fotg210, qtd, qtd->qtd_dma); + qh->dummy = qtd; + + /* hc must see the new dummy at list end */ + dma = qtd->qtd_dma; + qtd = list_entry(qh->qtd_list.prev, + struct fotg210_qtd, qtd_list); + qtd->hw_next = QTD_NEXT(fotg210, dma); + + /* let the hc process these next qtds */ + wmb(); + dummy->hw_token = token; + + urb->hcpriv = qh; + } + } + return qh; +} + +/*-------------------------------------------------------------------------*/ + +static int +submit_async( + struct fotg210_hcd *fotg210, + struct urb *urb, + struct list_head *qtd_list, + gfp_t mem_flags +) { + int epnum; + unsigned long flags; + struct fotg210_qh *qh = NULL; + int rc; + + epnum = urb->ep->desc.bEndpointAddress; + +#ifdef FOTG210_URB_TRACE + { + struct fotg210_qtd *qtd; + qtd = list_entry(qtd_list->next, struct fotg210_qtd, qtd_list); + fotg210_dbg(fotg210, + "%s %s urb %p ep%d%s len %d, qtd %p [qh %p]\n", + __func__, urb->dev->devpath, urb, + epnum & 0x0f, (epnum & USB_DIR_IN) ? "in" : "out", + urb->transfer_buffer_length, + qtd, urb->ep->hcpriv); + } +#endif + + spin_lock_irqsave(&fotg210->lock, flags); + if (unlikely(!HCD_HW_ACCESSIBLE(fotg210_to_hcd(fotg210)))) { + rc = -ESHUTDOWN; + goto done; + } + rc = usb_hcd_link_urb_to_ep(fotg210_to_hcd(fotg210), urb); + if (unlikely(rc)) + goto done; + + qh = qh_append_tds(fotg210, urb, qtd_list, epnum, &urb->ep->hcpriv); + if (unlikely(qh == NULL)) { + usb_hcd_unlink_urb_from_ep(fotg210_to_hcd(fotg210), urb); + rc = -ENOMEM; + goto done; + } + + /* Control/bulk operations through TTs don't need scheduling, + * the HC and TT handle it when the TT has a buffer ready. + */ + if (likely(qh->qh_state == QH_STATE_IDLE)) + qh_link_async(fotg210, qh); + done: + spin_unlock_irqrestore(&fotg210->lock, flags); + if (unlikely(qh == NULL)) + qtd_list_free(fotg210, urb, qtd_list); + return rc; +} + +/*-------------------------------------------------------------------------*/ + +static void single_unlink_async(struct fotg210_hcd *fotg210, + struct fotg210_qh *qh) +{ + struct fotg210_qh *prev; + + /* Add to the end of the list of QHs waiting for the next IAAD */ + qh->qh_state = QH_STATE_UNLINK; + if (fotg210->async_unlink) + fotg210->async_unlink_last->unlink_next = qh; + else + fotg210->async_unlink = qh; + fotg210->async_unlink_last = qh; + + /* Unlink it from the schedule */ + prev = fotg210->async; + while (prev->qh_next.qh != qh) + prev = prev->qh_next.qh; + + prev->hw->hw_next = qh->hw->hw_next; + prev->qh_next = qh->qh_next; + if (fotg210->qh_scan_next == qh) + fotg210->qh_scan_next = qh->qh_next.qh; +} + +static void start_iaa_cycle(struct fotg210_hcd *fotg210, bool nested) +{ + /* + * Do nothing if an IAA cycle is already running or + * if one will be started shortly. + */ + if (fotg210->async_iaa || fotg210->async_unlinking) + return; + + /* Do all the waiting QHs at once */ + fotg210->async_iaa = fotg210->async_unlink; + fotg210->async_unlink = NULL; + + /* If the controller isn't running, we don't have to wait for it */ + if (unlikely(fotg210->rh_state < FOTG210_RH_RUNNING)) { + if (!nested) /* Avoid recursion */ + end_unlink_async(fotg210); + + /* Otherwise start a new IAA cycle */ + } else if (likely(fotg210->rh_state == FOTG210_RH_RUNNING)) { + /* Make sure the unlinks are all visible to the hardware */ + wmb(); + + fotg210_writel(fotg210, fotg210->command | CMD_IAAD, + &fotg210->regs->command); + fotg210_readl(fotg210, &fotg210->regs->command); + fotg210_enable_event(fotg210, FOTG210_HRTIMER_IAA_WATCHDOG, + true); + } +} + +/* the async qh for the qtds being unlinked are now gone from the HC */ + +static void end_unlink_async(struct fotg210_hcd *fotg210) +{ + struct fotg210_qh *qh; + + /* Process the idle QHs */ + restart: + fotg210->async_unlinking = true; + while (fotg210->async_iaa) { + qh = fotg210->async_iaa; + fotg210->async_iaa = qh->unlink_next; + qh->unlink_next = NULL; + + qh->qh_state = QH_STATE_IDLE; + qh->qh_next.qh = NULL; + + qh_completions(fotg210, qh); + if (!list_empty(&qh->qtd_list) && + fotg210->rh_state == FOTG210_RH_RUNNING) + qh_link_async(fotg210, qh); + disable_async(fotg210); + } + fotg210->async_unlinking = false; + + /* Start a new IAA cycle if any QHs are waiting for it */ + if (fotg210->async_unlink) { + start_iaa_cycle(fotg210, true); + if (unlikely(fotg210->rh_state < FOTG210_RH_RUNNING)) + goto restart; + } +} + +static void unlink_empty_async(struct fotg210_hcd *fotg210) +{ + struct fotg210_qh *qh, *next; + bool stopped = (fotg210->rh_state < FOTG210_RH_RUNNING); + bool check_unlinks_later = false; + + /* Unlink all the async QHs that have been empty for a timer cycle */ + next = fotg210->async->qh_next.qh; + while (next) { + qh = next; + next = qh->qh_next.qh; + + if (list_empty(&qh->qtd_list) && + qh->qh_state == QH_STATE_LINKED) { + if (!stopped && qh->unlink_cycle == + fotg210->async_unlink_cycle) + check_unlinks_later = true; + else + single_unlink_async(fotg210, qh); + } + } + + /* Start a new IAA cycle if any QHs are waiting for it */ + if (fotg210->async_unlink) + start_iaa_cycle(fotg210, false); + + /* QHs that haven't been empty for long enough will be handled later */ + if (check_unlinks_later) { + fotg210_enable_event(fotg210, FOTG210_HRTIMER_ASYNC_UNLINKS, + true); + ++fotg210->async_unlink_cycle; + } +} + +/* makes sure the async qh will become idle */ +/* caller must own fotg210->lock */ + +static void start_unlink_async(struct fotg210_hcd *fotg210, + struct fotg210_qh *qh) +{ + /* + * If the QH isn't linked then there's nothing we can do + * unless we were called during a giveback, in which case + * qh_completions() has to deal with it. + */ + if (qh->qh_state != QH_STATE_LINKED) { + if (qh->qh_state == QH_STATE_COMPLETING) + qh->needs_rescan = 1; + return; + } + + single_unlink_async(fotg210, qh); + start_iaa_cycle(fotg210, false); +} + +/*-------------------------------------------------------------------------*/ + +static void scan_async(struct fotg210_hcd *fotg210) +{ + struct fotg210_qh *qh; + bool check_unlinks_later = false; + + fotg210->qh_scan_next = fotg210->async->qh_next.qh; + while (fotg210->qh_scan_next) { + qh = fotg210->qh_scan_next; + fotg210->qh_scan_next = qh->qh_next.qh; + rescan: + /* clean any finished work for this qh */ + if (!list_empty(&qh->qtd_list)) { + int temp; + + /* + * Unlinks could happen here; completion reporting + * drops the lock. That's why fotg210->qh_scan_next + * always holds the next qh to scan; if the next qh + * gets unlinked then fotg210->qh_scan_next is adjusted + * in single_unlink_async(). + */ + temp = qh_completions(fotg210, qh); + if (qh->needs_rescan) { + start_unlink_async(fotg210, qh); + } else if (list_empty(&qh->qtd_list) + && qh->qh_state == QH_STATE_LINKED) { + qh->unlink_cycle = fotg210->async_unlink_cycle; + check_unlinks_later = true; + } else if (temp != 0) + goto rescan; + } + } + + /* + * Unlink empty entries, reducing DMA usage as well + * as HCD schedule-scanning costs. Delay for any qh + * we just scanned, there's a not-unusual case that it + * doesn't stay idle for long. + */ + if (check_unlinks_later && fotg210->rh_state == FOTG210_RH_RUNNING && + !(fotg210->enabled_hrtimer_events & + BIT(FOTG210_HRTIMER_ASYNC_UNLINKS))) { + fotg210_enable_event(fotg210, + FOTG210_HRTIMER_ASYNC_UNLINKS, true); + ++fotg210->async_unlink_cycle; + } +} +/*-------------------------------------------------------------------------*/ +/* + * EHCI scheduled transaction support: interrupt, iso, split iso + * These are called "periodic" transactions in the EHCI spec. + * + * Note that for interrupt transfers, the QH/QTD manipulation is shared + * with the "asynchronous" transaction support (control/bulk transfers). + * The only real difference is in how interrupt transfers are scheduled. + * + * For ISO, we make an "iso_stream" head to serve the same role as a QH. + * It keeps track of every ITD (or SITD) that's linked, and holds enough + * pre-calculated schedule data to make appending to the queue be quick. + */ + +static int fotg210_get_frame(struct usb_hcd *hcd); + +/*-------------------------------------------------------------------------*/ + +/* + * periodic_next_shadow - return "next" pointer on shadow list + * @periodic: host pointer to qh/itd + * @tag: hardware tag for type of this record + */ +static union fotg210_shadow * +periodic_next_shadow(struct fotg210_hcd *fotg210, + union fotg210_shadow *periodic, __hc32 tag) +{ + switch (hc32_to_cpu(fotg210, tag)) { + case Q_TYPE_QH: + return &periodic->qh->qh_next; + case Q_TYPE_FSTN: + return &periodic->fstn->fstn_next; + default: + return &periodic->itd->itd_next; + } +} + +static __hc32 * +shadow_next_periodic(struct fotg210_hcd *fotg210, + union fotg210_shadow *periodic, __hc32 tag) +{ + switch (hc32_to_cpu(fotg210, tag)) { + /* our fotg210_shadow.qh is actually software part */ + case Q_TYPE_QH: + return &periodic->qh->hw->hw_next; + /* others are hw parts */ + default: + return periodic->hw_next; + } +} + +/* caller must hold fotg210->lock */ +static void periodic_unlink(struct fotg210_hcd *fotg210, unsigned frame, + void *ptr) +{ + union fotg210_shadow *prev_p = &fotg210->pshadow[frame]; + __hc32 *hw_p = &fotg210->periodic[frame]; + union fotg210_shadow here = *prev_p; + + /* find predecessor of "ptr"; hw and shadow lists are in sync */ + while (here.ptr && here.ptr != ptr) { + prev_p = periodic_next_shadow(fotg210, prev_p, + Q_NEXT_TYPE(fotg210, *hw_p)); + hw_p = shadow_next_periodic(fotg210, &here, + Q_NEXT_TYPE(fotg210, *hw_p)); + here = *prev_p; + } + /* an interrupt entry (at list end) could have been shared */ + if (!here.ptr) + return; + + /* update shadow and hardware lists ... the old "next" pointers + * from ptr may still be in use, the caller updates them. + */ + *prev_p = *periodic_next_shadow(fotg210, &here, + Q_NEXT_TYPE(fotg210, *hw_p)); + + *hw_p = *shadow_next_periodic(fotg210, &here, + Q_NEXT_TYPE(fotg210, *hw_p)); +} + +/* how many of the uframe's 125 usecs are allocated? */ +static unsigned short +periodic_usecs(struct fotg210_hcd *fotg210, unsigned frame, unsigned uframe) +{ + __hc32 *hw_p = &fotg210->periodic[frame]; + union fotg210_shadow *q = &fotg210->pshadow[frame]; + unsigned usecs = 0; + struct fotg210_qh_hw *hw; + + while (q->ptr) { + switch (hc32_to_cpu(fotg210, Q_NEXT_TYPE(fotg210, *hw_p))) { + case Q_TYPE_QH: + hw = q->qh->hw; + /* is it in the S-mask? */ + if (hw->hw_info2 & cpu_to_hc32(fotg210, 1 << uframe)) + usecs += q->qh->usecs; + /* ... or C-mask? */ + if (hw->hw_info2 & cpu_to_hc32(fotg210, + 1 << (8 + uframe))) + usecs += q->qh->c_usecs; + hw_p = &hw->hw_next; + q = &q->qh->qh_next; + break; + /* case Q_TYPE_FSTN: */ + default: + /* for "save place" FSTNs, count the relevant INTR + * bandwidth from the previous frame + */ + if (q->fstn->hw_prev != FOTG210_LIST_END(fotg210)) + fotg210_dbg(fotg210, "ignoring FSTN cost ...\n"); + + hw_p = &q->fstn->hw_next; + q = &q->fstn->fstn_next; + break; + case Q_TYPE_ITD: + if (q->itd->hw_transaction[uframe]) + usecs += q->itd->stream->usecs; + hw_p = &q->itd->hw_next; + q = &q->itd->itd_next; + break; + } + } +#ifdef DEBUG + if (usecs > fotg210->uframe_periodic_max) + fotg210_err(fotg210, "uframe %d sched overrun: %d usecs\n", + frame * 8 + uframe, usecs); +#endif + return usecs; +} + +/*-------------------------------------------------------------------------*/ + +static int same_tt(struct usb_device *dev1, struct usb_device *dev2) +{ + if (!dev1->tt || !dev2->tt) + return 0; + if (dev1->tt != dev2->tt) + return 0; + if (dev1->tt->multi) + return dev1->ttport == dev2->ttport; + else + return 1; +} + +/* return true iff the device's transaction translator is available + * for a periodic transfer starting at the specified frame, using + * all the uframes in the mask. + */ +static int tt_no_collision( + struct fotg210_hcd *fotg210, + unsigned period, + struct usb_device *dev, + unsigned frame, + u32 uf_mask +) +{ + if (period == 0) /* error */ + return 0; + + /* note bandwidth wastage: split never follows csplit + * (different dev or endpoint) until the next uframe. + * calling convention doesn't make that distinction. + */ + for (; frame < fotg210->periodic_size; frame += period) { + union fotg210_shadow here; + __hc32 type; + struct fotg210_qh_hw *hw; + + here = fotg210->pshadow[frame]; + type = Q_NEXT_TYPE(fotg210, fotg210->periodic[frame]); + while (here.ptr) { + switch (hc32_to_cpu(fotg210, type)) { + case Q_TYPE_ITD: + type = Q_NEXT_TYPE(fotg210, here.itd->hw_next); + here = here.itd->itd_next; + continue; + case Q_TYPE_QH: + hw = here.qh->hw; + if (same_tt(dev, here.qh->dev)) { + u32 mask; + + mask = hc32_to_cpu(fotg210, + hw->hw_info2); + /* "knows" no gap is needed */ + mask |= mask >> 8; + if (mask & uf_mask) + break; + } + type = Q_NEXT_TYPE(fotg210, hw->hw_next); + here = here.qh->qh_next; + continue; + /* case Q_TYPE_FSTN: */ + default: + fotg210_dbg(fotg210, + "periodic frame %d bogus type %d\n", + frame, type); + } + + /* collision or error */ + return 0; + } + } + + /* no collision */ + return 1; +} + +/*-------------------------------------------------------------------------*/ + +static void enable_periodic(struct fotg210_hcd *fotg210) +{ + if (fotg210->periodic_count++) + return; + + /* Stop waiting to turn off the periodic schedule */ + fotg210->enabled_hrtimer_events &= + ~BIT(FOTG210_HRTIMER_DISABLE_PERIODIC); + + /* Don't start the schedule until PSS is 0 */ + fotg210_poll_PSS(fotg210); + turn_on_io_watchdog(fotg210); +} + +static void disable_periodic(struct fotg210_hcd *fotg210) +{ + if (--fotg210->periodic_count) + return; + + /* Don't turn off the schedule until PSS is 1 */ + fotg210_poll_PSS(fotg210); +} + +/*-------------------------------------------------------------------------*/ + +/* periodic schedule slots have iso tds (normal or split) first, then a + * sparse tree for active interrupt transfers. + * + * this just links in a qh; caller guarantees uframe masks are set right. + * no FSTN support (yet; fotg210 0.96+) + */ +static void qh_link_periodic(struct fotg210_hcd *fotg210, struct fotg210_qh *qh) +{ + unsigned i; + unsigned period = qh->period; + + dev_dbg(&qh->dev->dev, + "link qh%d-%04x/%p start %d [%d/%d us]\n", + period, hc32_to_cpup(fotg210, &qh->hw->hw_info2) + & (QH_CMASK | QH_SMASK), + qh, qh->start, qh->usecs, qh->c_usecs); + + /* high bandwidth, or otherwise every microframe */ + if (period == 0) + period = 1; + + for (i = qh->start; i < fotg210->periodic_size; i += period) { + union fotg210_shadow *prev = &fotg210->pshadow[i]; + __hc32 *hw_p = &fotg210->periodic[i]; + union fotg210_shadow here = *prev; + __hc32 type = 0; + + /* skip the iso nodes at list head */ + while (here.ptr) { + type = Q_NEXT_TYPE(fotg210, *hw_p); + if (type == cpu_to_hc32(fotg210, Q_TYPE_QH)) + break; + prev = periodic_next_shadow(fotg210, prev, type); + hw_p = shadow_next_periodic(fotg210, &here, type); + here = *prev; + } + + /* sorting each branch by period (slow-->fast) + * enables sharing interior tree nodes + */ + while (here.ptr && qh != here.qh) { + if (qh->period > here.qh->period) + break; + prev = &here.qh->qh_next; + hw_p = &here.qh->hw->hw_next; + here = *prev; + } + /* link in this qh, unless some earlier pass did that */ + if (qh != here.qh) { + qh->qh_next = here; + if (here.qh) + qh->hw->hw_next = *hw_p; + wmb(); + prev->qh = qh; + *hw_p = QH_NEXT(fotg210, qh->qh_dma); + } + } + qh->qh_state = QH_STATE_LINKED; + qh->xacterrs = 0; + + /* update per-qh bandwidth for usbfs */ + fotg210_to_hcd(fotg210)->self.bandwidth_allocated += qh->period + ? ((qh->usecs + qh->c_usecs) / qh->period) + : (qh->usecs * 8); + + list_add(&qh->intr_node, &fotg210->intr_qh_list); + + /* maybe enable periodic schedule processing */ + ++fotg210->intr_count; + enable_periodic(fotg210); +} + +static void qh_unlink_periodic(struct fotg210_hcd *fotg210, + struct fotg210_qh *qh) +{ + unsigned i; + unsigned period; + + /* + * If qh is for a low/full-speed device, simply unlinking it + * could interfere with an ongoing split transaction. To unlink + * it safely would require setting the QH_INACTIVATE bit and + * waiting at least one frame, as described in EHCI 4.12.2.5. + * + * We won't bother with any of this. Instead, we assume that the + * only reason for unlinking an interrupt QH while the current URB + * is still active is to dequeue all the URBs (flush the whole + * endpoint queue). + * + * If rebalancing the periodic schedule is ever implemented, this + * approach will no longer be valid. + */ + + /* high bandwidth, or otherwise part of every microframe */ + period = qh->period; + if (!period) + period = 1; + + for (i = qh->start; i < fotg210->periodic_size; i += period) + periodic_unlink(fotg210, i, qh); + + /* update per-qh bandwidth for usbfs */ + fotg210_to_hcd(fotg210)->self.bandwidth_allocated -= qh->period + ? ((qh->usecs + qh->c_usecs) / qh->period) + : (qh->usecs * 8); + + dev_dbg(&qh->dev->dev, + "unlink qh%d-%04x/%p start %d [%d/%d us]\n", + qh->period, + hc32_to_cpup(fotg210, &qh->hw->hw_info2) & + (QH_CMASK | QH_SMASK), qh, qh->start, qh->usecs, qh->c_usecs); + + /* qh->qh_next still "live" to HC */ + qh->qh_state = QH_STATE_UNLINK; + qh->qh_next.ptr = NULL; + + if (fotg210->qh_scan_next == qh) + fotg210->qh_scan_next = list_entry(qh->intr_node.next, + struct fotg210_qh, intr_node); + list_del(&qh->intr_node); +} + +static void start_unlink_intr(struct fotg210_hcd *fotg210, + struct fotg210_qh *qh) +{ + /* If the QH isn't linked then there's nothing we can do + * unless we were called during a giveback, in which case + * qh_completions() has to deal with it. + */ + if (qh->qh_state != QH_STATE_LINKED) { + if (qh->qh_state == QH_STATE_COMPLETING) + qh->needs_rescan = 1; + return; + } + + qh_unlink_periodic(fotg210, qh); + + /* Make sure the unlinks are visible before starting the timer */ + wmb(); + + /* + * The EHCI spec doesn't say how long it takes the controller to + * stop accessing an unlinked interrupt QH. The timer delay is + * 9 uframes; presumably that will be long enough. + */ + qh->unlink_cycle = fotg210->intr_unlink_cycle; + + /* New entries go at the end of the intr_unlink list */ + if (fotg210->intr_unlink) + fotg210->intr_unlink_last->unlink_next = qh; + else + fotg210->intr_unlink = qh; + fotg210->intr_unlink_last = qh; + + if (fotg210->intr_unlinking) + ; /* Avoid recursive calls */ + else if (fotg210->rh_state < FOTG210_RH_RUNNING) + fotg210_handle_intr_unlinks(fotg210); + else if (fotg210->intr_unlink == qh) { + fotg210_enable_event(fotg210, FOTG210_HRTIMER_UNLINK_INTR, + true); + ++fotg210->intr_unlink_cycle; + } +} + +static void end_unlink_intr(struct fotg210_hcd *fotg210, struct fotg210_qh *qh) +{ + struct fotg210_qh_hw *hw = qh->hw; + int rc; + + qh->qh_state = QH_STATE_IDLE; + hw->hw_next = FOTG210_LIST_END(fotg210); + + qh_completions(fotg210, qh); + + /* reschedule QH iff another request is queued */ + if (!list_empty(&qh->qtd_list) && + fotg210->rh_state == FOTG210_RH_RUNNING) { + rc = qh_schedule(fotg210, qh); + + /* An error here likely indicates handshake failure + * or no space left in the schedule. Neither fault + * should happen often ... + * + * FIXME kill the now-dysfunctional queued urbs + */ + if (rc != 0) + fotg210_err(fotg210, "can't reschedule qh %p, err %d\n", + qh, rc); + } + + /* maybe turn off periodic schedule */ + --fotg210->intr_count; + disable_periodic(fotg210); +} + +/*-------------------------------------------------------------------------*/ + +static int check_period( + struct fotg210_hcd *fotg210, + unsigned frame, + unsigned uframe, + unsigned period, + unsigned usecs +) { + int claimed; + + /* complete split running into next frame? + * given FSTN support, we could sometimes check... + */ + if (uframe >= 8) + return 0; + + /* convert "usecs we need" to "max already claimed" */ + usecs = fotg210->uframe_periodic_max - usecs; + + /* we "know" 2 and 4 uframe intervals were rejected; so + * for period 0, check _every_ microframe in the schedule. + */ + if (unlikely(period == 0)) { + do { + for (uframe = 0; uframe < 7; uframe++) { + claimed = periodic_usecs(fotg210, frame, + uframe); + if (claimed > usecs) + return 0; + } + } while ((frame += 1) < fotg210->periodic_size); + + /* just check the specified uframe, at that period */ + } else { + do { + claimed = periodic_usecs(fotg210, frame, uframe); + if (claimed > usecs) + return 0; + } while ((frame += period) < fotg210->periodic_size); + } + + /* success! */ + return 1; +} + +static int check_intr_schedule( + struct fotg210_hcd *fotg210, + unsigned frame, + unsigned uframe, + const struct fotg210_qh *qh, + __hc32 *c_maskp +) +{ + int retval = -ENOSPC; + u8 mask = 0; + + if (qh->c_usecs && uframe >= 6) /* FSTN territory? */ + goto done; + + if (!check_period(fotg210, frame, uframe, qh->period, qh->usecs)) + goto done; + if (!qh->c_usecs) { + retval = 0; + *c_maskp = 0; + goto done; + } + + /* Make sure this tt's buffer is also available for CSPLITs. + * We pessimize a bit; probably the typical full speed case + * doesn't need the second CSPLIT. + * + * NOTE: both SPLIT and CSPLIT could be checked in just + * one smart pass... + */ + mask = 0x03 << (uframe + qh->gap_uf); + *c_maskp = cpu_to_hc32(fotg210, mask << 8); + + mask |= 1 << uframe; + if (tt_no_collision(fotg210, qh->period, qh->dev, frame, mask)) { + if (!check_period(fotg210, frame, uframe + qh->gap_uf + 1, + qh->period, qh->c_usecs)) + goto done; + if (!check_period(fotg210, frame, uframe + qh->gap_uf, + qh->period, qh->c_usecs)) + goto done; + retval = 0; + } +done: + return retval; +} + +/* "first fit" scheduling policy used the first time through, + * or when the previous schedule slot can't be re-used. + */ +static int qh_schedule(struct fotg210_hcd *fotg210, struct fotg210_qh *qh) +{ + int status; + unsigned uframe; + __hc32 c_mask; + unsigned frame; /* 0..(qh->period - 1), or NO_FRAME */ + struct fotg210_qh_hw *hw = qh->hw; + + qh_refresh(fotg210, qh); + hw->hw_next = FOTG210_LIST_END(fotg210); + frame = qh->start; + + /* reuse the previous schedule slots, if we can */ + if (frame < qh->period) { + uframe = ffs(hc32_to_cpup(fotg210, &hw->hw_info2) & QH_SMASK); + status = check_intr_schedule(fotg210, frame, --uframe, + qh, &c_mask); + } else { + uframe = 0; + c_mask = 0; + status = -ENOSPC; + } + + /* else scan the schedule to find a group of slots such that all + * uframes have enough periodic bandwidth available. + */ + if (status) { + /* "normal" case, uframing flexible except with splits */ + if (qh->period) { + int i; + + for (i = qh->period; status && i > 0; --i) { + frame = ++fotg210->random_frame % qh->period; + for (uframe = 0; uframe < 8; uframe++) { + status = check_intr_schedule(fotg210, + frame, uframe, qh, + &c_mask); + if (status == 0) + break; + } + } + + /* qh->period == 0 means every uframe */ + } else { + frame = 0; + status = check_intr_schedule(fotg210, 0, 0, qh, + &c_mask); + } + if (status) + goto done; + qh->start = frame; + + /* reset S-frame and (maybe) C-frame masks */ + hw->hw_info2 &= cpu_to_hc32(fotg210, ~(QH_CMASK | QH_SMASK)); + hw->hw_info2 |= qh->period + ? cpu_to_hc32(fotg210, 1 << uframe) + : cpu_to_hc32(fotg210, QH_SMASK); + hw->hw_info2 |= c_mask; + } else + fotg210_dbg(fotg210, "reused qh %p schedule\n", qh); + + /* stuff into the periodic schedule */ + qh_link_periodic(fotg210, qh); +done: + return status; +} + +static int intr_submit( + struct fotg210_hcd *fotg210, + struct urb *urb, + struct list_head *qtd_list, + gfp_t mem_flags +) { + unsigned epnum; + unsigned long flags; + struct fotg210_qh *qh; + int status; + struct list_head empty; + + /* get endpoint and transfer/schedule data */ + epnum = urb->ep->desc.bEndpointAddress; + + spin_lock_irqsave(&fotg210->lock, flags); + + if (unlikely(!HCD_HW_ACCESSIBLE(fotg210_to_hcd(fotg210)))) { + status = -ESHUTDOWN; + goto done_not_linked; + } + status = usb_hcd_link_urb_to_ep(fotg210_to_hcd(fotg210), urb); + if (unlikely(status)) + goto done_not_linked; + + /* get qh and force any scheduling errors */ + INIT_LIST_HEAD(&empty); + qh = qh_append_tds(fotg210, urb, &empty, epnum, &urb->ep->hcpriv); + if (qh == NULL) { + status = -ENOMEM; + goto done; + } + if (qh->qh_state == QH_STATE_IDLE) { + status = qh_schedule(fotg210, qh); + if (status) + goto done; + } + + /* then queue the urb's tds to the qh */ + qh = qh_append_tds(fotg210, urb, qtd_list, epnum, &urb->ep->hcpriv); + BUG_ON(qh == NULL); + + /* ... update usbfs periodic stats */ + fotg210_to_hcd(fotg210)->self.bandwidth_int_reqs++; + +done: + if (unlikely(status)) + usb_hcd_unlink_urb_from_ep(fotg210_to_hcd(fotg210), urb); +done_not_linked: + spin_unlock_irqrestore(&fotg210->lock, flags); + if (status) + qtd_list_free(fotg210, urb, qtd_list); + + return status; +} + +static void scan_intr(struct fotg210_hcd *fotg210) +{ + struct fotg210_qh *qh; + + list_for_each_entry_safe(qh, fotg210->qh_scan_next, + &fotg210->intr_qh_list, intr_node) { + rescan: + /* clean any finished work for this qh */ + if (!list_empty(&qh->qtd_list)) { + int temp; + + /* + * Unlinks could happen here; completion reporting + * drops the lock. That's why fotg210->qh_scan_next + * always holds the next qh to scan; if the next qh + * gets unlinked then fotg210->qh_scan_next is adjusted + * in qh_unlink_periodic(). + */ + temp = qh_completions(fotg210, qh); + if (unlikely(qh->needs_rescan || + (list_empty(&qh->qtd_list) && + qh->qh_state == QH_STATE_LINKED))) + start_unlink_intr(fotg210, qh); + else if (temp != 0) + goto rescan; + } + } +} + +/*-------------------------------------------------------------------------*/ + +/* fotg210_iso_stream ops work with both ITD and SITD */ + +static struct fotg210_iso_stream * +iso_stream_alloc(gfp_t mem_flags) +{ + struct fotg210_iso_stream *stream; + + stream = kzalloc(sizeof(*stream), mem_flags); + if (likely(stream != NULL)) { + INIT_LIST_HEAD(&stream->td_list); + INIT_LIST_HEAD(&stream->free_list); + stream->next_uframe = -1; + } + return stream; +} + +static void +iso_stream_init( + struct fotg210_hcd *fotg210, + struct fotg210_iso_stream *stream, + struct usb_device *dev, + int pipe, + unsigned interval +) +{ + u32 buf1; + unsigned epnum, maxp; + int is_input; + long bandwidth; + unsigned multi; + + /* + * this might be a "high bandwidth" highspeed endpoint, + * as encoded in the ep descriptor's wMaxPacket field + */ + epnum = usb_pipeendpoint(pipe); + is_input = usb_pipein(pipe) ? USB_DIR_IN : 0; + maxp = usb_maxpacket(dev, pipe, !is_input); + if (is_input) + buf1 = (1 << 11); + else + buf1 = 0; + + maxp = max_packet(maxp); + multi = hb_mult(maxp); + buf1 |= maxp; + maxp *= multi; + + stream->buf0 = cpu_to_hc32(fotg210, (epnum << 8) | dev->devnum); + stream->buf1 = cpu_to_hc32(fotg210, buf1); + stream->buf2 = cpu_to_hc32(fotg210, multi); + + /* usbfs wants to report the average usecs per frame tied up + * when transfers on this endpoint are scheduled ... + */ + if (dev->speed == USB_SPEED_FULL) { + interval <<= 3; + stream->usecs = NS_TO_US(usb_calc_bus_time(dev->speed, + is_input, 1, maxp)); + stream->usecs /= 8; + } else { + stream->highspeed = 1; + stream->usecs = HS_USECS_ISO(maxp); + } + bandwidth = stream->usecs * 8; + bandwidth /= interval; + + stream->bandwidth = bandwidth; + stream->udev = dev; + stream->bEndpointAddress = is_input | epnum; + stream->interval = interval; + stream->maxp = maxp; +} + +static struct fotg210_iso_stream * +iso_stream_find(struct fotg210_hcd *fotg210, struct urb *urb) +{ + unsigned epnum; + struct fotg210_iso_stream *stream; + struct usb_host_endpoint *ep; + unsigned long flags; + + epnum = usb_pipeendpoint(urb->pipe); + if (usb_pipein(urb->pipe)) + ep = urb->dev->ep_in[epnum]; + else + ep = urb->dev->ep_out[epnum]; + + spin_lock_irqsave(&fotg210->lock, flags); + stream = ep->hcpriv; + + if (unlikely(stream == NULL)) { + stream = iso_stream_alloc(GFP_ATOMIC); + if (likely(stream != NULL)) { + ep->hcpriv = stream; + stream->ep = ep; + iso_stream_init(fotg210, stream, urb->dev, urb->pipe, + urb->interval); + } + + /* if dev->ep[epnum] is a QH, hw is set */ + } else if (unlikely(stream->hw != NULL)) { + fotg210_dbg(fotg210, "dev %s ep%d%s, not iso??\n", + urb->dev->devpath, epnum, + usb_pipein(urb->pipe) ? "in" : "out"); + stream = NULL; + } + + spin_unlock_irqrestore(&fotg210->lock, flags); + return stream; +} + +/*-------------------------------------------------------------------------*/ + +/* fotg210_iso_sched ops can be ITD-only or SITD-only */ + +static struct fotg210_iso_sched * +iso_sched_alloc(unsigned packets, gfp_t mem_flags) +{ + struct fotg210_iso_sched *iso_sched; + int size = sizeof(*iso_sched); + + size += packets * sizeof(struct fotg210_iso_packet); + iso_sched = kzalloc(size, mem_flags); + if (likely(iso_sched != NULL)) + INIT_LIST_HEAD(&iso_sched->td_list); + + return iso_sched; +} + +static inline void +itd_sched_init( + struct fotg210_hcd *fotg210, + struct fotg210_iso_sched *iso_sched, + struct fotg210_iso_stream *stream, + struct urb *urb +) +{ + unsigned i; + dma_addr_t dma = urb->transfer_dma; + + /* how many uframes are needed for these transfers */ + iso_sched->span = urb->number_of_packets * stream->interval; + + /* figure out per-uframe itd fields that we'll need later + * when we fit new itds into the schedule. + */ + for (i = 0; i < urb->number_of_packets; i++) { + struct fotg210_iso_packet *uframe = &iso_sched->packet[i]; + unsigned length; + dma_addr_t buf; + u32 trans; + + length = urb->iso_frame_desc[i].length; + buf = dma + urb->iso_frame_desc[i].offset; + + trans = FOTG210_ISOC_ACTIVE; + trans |= buf & 0x0fff; + if (unlikely(((i + 1) == urb->number_of_packets)) + && !(urb->transfer_flags & URB_NO_INTERRUPT)) + trans |= FOTG210_ITD_IOC; + trans |= length << 16; + uframe->transaction = cpu_to_hc32(fotg210, trans); + + /* might need to cross a buffer page within a uframe */ + uframe->bufp = (buf & ~(u64)0x0fff); + buf += length; + if (unlikely((uframe->bufp != (buf & ~(u64)0x0fff)))) + uframe->cross = 1; + } +} + +static void +iso_sched_free( + struct fotg210_iso_stream *stream, + struct fotg210_iso_sched *iso_sched +) +{ + if (!iso_sched) + return; + /* caller must hold fotg210->lock!*/ + list_splice(&iso_sched->td_list, &stream->free_list); + kfree(iso_sched); +} + +static int +itd_urb_transaction( + struct fotg210_iso_stream *stream, + struct fotg210_hcd *fotg210, + struct urb *urb, + gfp_t mem_flags +) +{ + struct fotg210_itd *itd; + dma_addr_t itd_dma; + int i; + unsigned num_itds; + struct fotg210_iso_sched *sched; + unsigned long flags; + + sched = iso_sched_alloc(urb->number_of_packets, mem_flags); + if (unlikely(sched == NULL)) + return -ENOMEM; + + itd_sched_init(fotg210, sched, stream, urb); + + if (urb->interval < 8) + num_itds = 1 + (sched->span + 7) / 8; + else + num_itds = urb->number_of_packets; + + /* allocate/init ITDs */ + spin_lock_irqsave(&fotg210->lock, flags); + for (i = 0; i < num_itds; i++) { + + /* + * Use iTDs from the free list, but not iTDs that may + * still be in use by the hardware. + */ + if (likely(!list_empty(&stream->free_list))) { + itd = list_first_entry(&stream->free_list, + struct fotg210_itd, itd_list); + if (itd->frame == fotg210->now_frame) + goto alloc_itd; + list_del(&itd->itd_list); + itd_dma = itd->itd_dma; + } else { + alloc_itd: + spin_unlock_irqrestore(&fotg210->lock, flags); + itd = dma_pool_alloc(fotg210->itd_pool, mem_flags, + &itd_dma); + spin_lock_irqsave(&fotg210->lock, flags); + if (!itd) { + iso_sched_free(stream, sched); + spin_unlock_irqrestore(&fotg210->lock, flags); + return -ENOMEM; + } + } + + memset(itd, 0, sizeof(*itd)); + itd->itd_dma = itd_dma; + list_add(&itd->itd_list, &sched->td_list); + } + spin_unlock_irqrestore(&fotg210->lock, flags); + + /* temporarily store schedule info in hcpriv */ + urb->hcpriv = sched; + urb->error_count = 0; + return 0; +} + +/*-------------------------------------------------------------------------*/ + +static inline int +itd_slot_ok( + struct fotg210_hcd *fotg210, + u32 mod, + u32 uframe, + u8 usecs, + u32 period +) +{ + uframe %= period; + do { + /* can't commit more than uframe_periodic_max usec */ + if (periodic_usecs(fotg210, uframe >> 3, uframe & 0x7) + > (fotg210->uframe_periodic_max - usecs)) + return 0; + + /* we know urb->interval is 2^N uframes */ + uframe += period; + } while (uframe < mod); + return 1; +} + +/* + * This scheduler plans almost as far into the future as it has actual + * periodic schedule slots. (Affected by TUNE_FLS, which defaults to + * "as small as possible" to be cache-friendlier.) That limits the size + * transfers you can stream reliably; avoid more than 64 msec per urb. + * Also avoid queue depths of less than fotg210's worst irq latency (affected + * by the per-urb URB_NO_INTERRUPT hint, the log2_irq_thresh module parameter, + * and other factors); or more than about 230 msec total (for portability, + * given FOTG210_TUNE_FLS and the slop). Or, write a smarter scheduler! + */ + +#define SCHEDULE_SLOP 80 /* microframes */ + +static int +iso_stream_schedule( + struct fotg210_hcd *fotg210, + struct urb *urb, + struct fotg210_iso_stream *stream +) +{ + u32 now, next, start, period, span; + int status; + unsigned mod = fotg210->periodic_size << 3; + struct fotg210_iso_sched *sched = urb->hcpriv; + + period = urb->interval; + span = sched->span; + + if (span > mod - SCHEDULE_SLOP) { + fotg210_dbg(fotg210, "iso request %p too long\n", urb); + status = -EFBIG; + goto fail; + } + + now = fotg210_read_frame_index(fotg210) & (mod - 1); + + /* Typical case: reuse current schedule, stream is still active. + * Hopefully there are no gaps from the host falling behind + * (irq delays etc), but if there are we'll take the next + * slot in the schedule, implicitly assuming URB_ISO_ASAP. + */ + if (likely(!list_empty(&stream->td_list))) { + u32 excess; + + /* For high speed devices, allow scheduling within the + * isochronous scheduling threshold. For full speed devices + * and Intel PCI-based controllers, don't (work around for + * Intel ICH9 bug). + */ + if (!stream->highspeed && fotg210->fs_i_thresh) + next = now + fotg210->i_thresh; + else + next = now; + + /* Fell behind (by up to twice the slop amount)? + * We decide based on the time of the last currently-scheduled + * slot, not the time of the next available slot. + */ + excess = (stream->next_uframe - period - next) & (mod - 1); + if (excess >= mod - 2 * SCHEDULE_SLOP) + start = next + excess - mod + period * + DIV_ROUND_UP(mod - excess, period); + else + start = next + excess + period; + if (start - now >= mod) { + fotg210_dbg(fotg210, "request %p would overflow (%d+%d >= %d)\n", + urb, start - now - period, period, + mod); + status = -EFBIG; + goto fail; + } + } + + /* need to schedule; when's the next (u)frame we could start? + * this is bigger than fotg210->i_thresh allows; scheduling itself + * isn't free, the slop should handle reasonably slow cpus. it + * can also help high bandwidth if the dma and irq loads don't + * jump until after the queue is primed. + */ + else { + int done = 0; + start = SCHEDULE_SLOP + (now & ~0x07); + + /* NOTE: assumes URB_ISO_ASAP, to limit complexity/bugs */ + + /* find a uframe slot with enough bandwidth. + * Early uframes are more precious because full-speed + * iso IN transfers can't use late uframes, + * and therefore they should be allocated last. + */ + next = start; + start += period; + do { + start--; + /* check schedule: enough space? */ + if (itd_slot_ok(fotg210, mod, start, + stream->usecs, period)) + done = 1; + } while (start > next && !done); + + /* no room in the schedule */ + if (!done) { + fotg210_dbg(fotg210, "iso resched full %p (now %d max %d)\n", + urb, now, now + mod); + status = -ENOSPC; + goto fail; + } + } + + /* Tried to schedule too far into the future? */ + if (unlikely(start - now + span - period + >= mod - 2 * SCHEDULE_SLOP)) { + fotg210_dbg(fotg210, "request %p would overflow (%d+%d >= %d)\n", + urb, start - now, span - period, + mod - 2 * SCHEDULE_SLOP); + status = -EFBIG; + goto fail; + } + + stream->next_uframe = start & (mod - 1); + + /* report high speed start in uframes; full speed, in frames */ + urb->start_frame = stream->next_uframe; + if (!stream->highspeed) + urb->start_frame >>= 3; + + /* Make sure scan_isoc() sees these */ + if (fotg210->isoc_count == 0) + fotg210->next_frame = now >> 3; + return 0; + + fail: + iso_sched_free(stream, sched); + urb->hcpriv = NULL; + return status; +} + +/*-------------------------------------------------------------------------*/ + +static inline void +itd_init(struct fotg210_hcd *fotg210, struct fotg210_iso_stream *stream, + struct fotg210_itd *itd) +{ + int i; + + /* it's been recently zeroed */ + itd->hw_next = FOTG210_LIST_END(fotg210); + itd->hw_bufp[0] = stream->buf0; + itd->hw_bufp[1] = stream->buf1; + itd->hw_bufp[2] = stream->buf2; + + for (i = 0; i < 8; i++) + itd->index[i] = -1; + + /* All other fields are filled when scheduling */ +} + +static inline void +itd_patch( + struct fotg210_hcd *fotg210, + struct fotg210_itd *itd, + struct fotg210_iso_sched *iso_sched, + unsigned index, + u16 uframe +) +{ + struct fotg210_iso_packet *uf = &iso_sched->packet[index]; + unsigned pg = itd->pg; + + uframe &= 0x07; + itd->index[uframe] = index; + + itd->hw_transaction[uframe] = uf->transaction; + itd->hw_transaction[uframe] |= cpu_to_hc32(fotg210, pg << 12); + itd->hw_bufp[pg] |= cpu_to_hc32(fotg210, uf->bufp & ~(u32)0); + itd->hw_bufp_hi[pg] |= cpu_to_hc32(fotg210, (u32)(uf->bufp >> 32)); + + /* iso_frame_desc[].offset must be strictly increasing */ + if (unlikely(uf->cross)) { + u64 bufp = uf->bufp + 4096; + + itd->pg = ++pg; + itd->hw_bufp[pg] |= cpu_to_hc32(fotg210, bufp & ~(u32)0); + itd->hw_bufp_hi[pg] |= cpu_to_hc32(fotg210, (u32)(bufp >> 32)); + } +} + +static inline void +itd_link(struct fotg210_hcd *fotg210, unsigned frame, struct fotg210_itd *itd) +{ + union fotg210_shadow *prev = &fotg210->pshadow[frame]; + __hc32 *hw_p = &fotg210->periodic[frame]; + union fotg210_shadow here = *prev; + __hc32 type = 0; + + /* skip any iso nodes which might belong to previous microframes */ + while (here.ptr) { + type = Q_NEXT_TYPE(fotg210, *hw_p); + if (type == cpu_to_hc32(fotg210, Q_TYPE_QH)) + break; + prev = periodic_next_shadow(fotg210, prev, type); + hw_p = shadow_next_periodic(fotg210, &here, type); + here = *prev; + } + + itd->itd_next = here; + itd->hw_next = *hw_p; + prev->itd = itd; + itd->frame = frame; + wmb(); + *hw_p = cpu_to_hc32(fotg210, itd->itd_dma | Q_TYPE_ITD); +} + +/* fit urb's itds into the selected schedule slot; activate as needed */ +static void itd_link_urb( + struct fotg210_hcd *fotg210, + struct urb *urb, + unsigned mod, + struct fotg210_iso_stream *stream +) +{ + int packet; + unsigned next_uframe, uframe, frame; + struct fotg210_iso_sched *iso_sched = urb->hcpriv; + struct fotg210_itd *itd; + + next_uframe = stream->next_uframe & (mod - 1); + + if (unlikely(list_empty(&stream->td_list))) { + fotg210_to_hcd(fotg210)->self.bandwidth_allocated + += stream->bandwidth; + fotg210_vdbg(fotg210, + "schedule devp %s ep%d%s-iso period %d start %d.%d\n", + urb->dev->devpath, stream->bEndpointAddress & 0x0f, + (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out", + urb->interval, + next_uframe >> 3, next_uframe & 0x7); + } + + /* fill iTDs uframe by uframe */ + for (packet = 0, itd = NULL; packet < urb->number_of_packets;) { + if (itd == NULL) { + /* ASSERT: we have all necessary itds */ + + /* ASSERT: no itds for this endpoint in this uframe */ + + itd = list_entry(iso_sched->td_list.next, + struct fotg210_itd, itd_list); + list_move_tail(&itd->itd_list, &stream->td_list); + itd->stream = stream; + itd->urb = urb; + itd_init(fotg210, stream, itd); + } + + uframe = next_uframe & 0x07; + frame = next_uframe >> 3; + + itd_patch(fotg210, itd, iso_sched, packet, uframe); + + next_uframe += stream->interval; + next_uframe &= mod - 1; + packet++; + + /* link completed itds into the schedule */ + if (((next_uframe >> 3) != frame) + || packet == urb->number_of_packets) { + itd_link(fotg210, frame & (fotg210->periodic_size - 1), + itd); + itd = NULL; + } + } + stream->next_uframe = next_uframe; + + /* don't need that schedule data any more */ + iso_sched_free(stream, iso_sched); + urb->hcpriv = NULL; + + ++fotg210->isoc_count; + enable_periodic(fotg210); +} + +#define ISO_ERRS (FOTG210_ISOC_BUF_ERR | FOTG210_ISOC_BABBLE |\ + FOTG210_ISOC_XACTERR) + +/* Process and recycle a completed ITD. Return true iff its urb completed, + * and hence its completion callback probably added things to the hardware + * schedule. + * + * Note that we carefully avoid recycling this descriptor until after any + * completion callback runs, so that it won't be reused quickly. That is, + * assuming (a) no more than two urbs per frame on this endpoint, and also + * (b) only this endpoint's completions submit URBs. It seems some silicon + * corrupts things if you reuse completed descriptors very quickly... + */ +static bool itd_complete(struct fotg210_hcd *fotg210, struct fotg210_itd *itd) +{ + struct urb *urb = itd->urb; + struct usb_iso_packet_descriptor *desc; + u32 t; + unsigned uframe; + int urb_index = -1; + struct fotg210_iso_stream *stream = itd->stream; + struct usb_device *dev; + bool retval = false; + + /* for each uframe with a packet */ + for (uframe = 0; uframe < 8; uframe++) { + if (likely(itd->index[uframe] == -1)) + continue; + urb_index = itd->index[uframe]; + desc = &urb->iso_frame_desc[urb_index]; + + t = hc32_to_cpup(fotg210, &itd->hw_transaction[uframe]); + itd->hw_transaction[uframe] = 0; + + /* report transfer status */ + if (unlikely(t & ISO_ERRS)) { + urb->error_count++; + if (t & FOTG210_ISOC_BUF_ERR) + desc->status = usb_pipein(urb->pipe) + ? -ENOSR /* hc couldn't read */ + : -ECOMM; /* hc couldn't write */ + else if (t & FOTG210_ISOC_BABBLE) + desc->status = -EOVERFLOW; + else /* (t & FOTG210_ISOC_XACTERR) */ + desc->status = -EPROTO; + + /* HC need not update length with this error */ + if (!(t & FOTG210_ISOC_BABBLE)) { + desc->actual_length = + fotg210_itdlen(urb, desc, t); + urb->actual_length += desc->actual_length; + } + } else if (likely((t & FOTG210_ISOC_ACTIVE) == 0)) { + desc->status = 0; + desc->actual_length = fotg210_itdlen(urb, desc, t); + urb->actual_length += desc->actual_length; + } else { + /* URB was too late */ + desc->status = -EXDEV; + } + } + + /* handle completion now? */ + if (likely((urb_index + 1) != urb->number_of_packets)) + goto done; + + /* ASSERT: it's really the last itd for this urb + list_for_each_entry (itd, &stream->td_list, itd_list) + BUG_ON (itd->urb == urb); + */ + + /* give urb back to the driver; completion often (re)submits */ + dev = urb->dev; + fotg210_urb_done(fotg210, urb, 0); + retval = true; + urb = NULL; + + --fotg210->isoc_count; + disable_periodic(fotg210); + + if (unlikely(list_is_singular(&stream->td_list))) { + fotg210_to_hcd(fotg210)->self.bandwidth_allocated + -= stream->bandwidth; + fotg210_vdbg(fotg210, + "deschedule devp %s ep%d%s-iso\n", + dev->devpath, stream->bEndpointAddress & 0x0f, + (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out"); + } + +done: + itd->urb = NULL; + + /* Add to the end of the free list for later reuse */ + list_move_tail(&itd->itd_list, &stream->free_list); + + /* Recycle the iTDs when the pipeline is empty (ep no longer in use) */ + if (list_empty(&stream->td_list)) { + list_splice_tail_init(&stream->free_list, + &fotg210->cached_itd_list); + start_free_itds(fotg210); + } + + return retval; +} + +/*-------------------------------------------------------------------------*/ + +static int itd_submit(struct fotg210_hcd *fotg210, struct urb *urb, + gfp_t mem_flags) +{ + int status = -EINVAL; + unsigned long flags; + struct fotg210_iso_stream *stream; + + /* Get iso_stream head */ + stream = iso_stream_find(fotg210, urb); + if (unlikely(stream == NULL)) { + fotg210_dbg(fotg210, "can't get iso stream\n"); + return -ENOMEM; + } + if (unlikely(urb->interval != stream->interval && + fotg210_port_speed(fotg210, 0) == + USB_PORT_STAT_HIGH_SPEED)) { + fotg210_dbg(fotg210, "can't change iso interval %d --> %d\n", + stream->interval, urb->interval); + goto done; + } + +#ifdef FOTG210_URB_TRACE + fotg210_dbg(fotg210, + "%s %s urb %p ep%d%s len %d, %d pkts %d uframes[%p]\n", + __func__, urb->dev->devpath, urb, + usb_pipeendpoint(urb->pipe), + usb_pipein(urb->pipe) ? "in" : "out", + urb->transfer_buffer_length, + urb->number_of_packets, urb->interval, + stream); +#endif + + /* allocate ITDs w/o locking anything */ + status = itd_urb_transaction(stream, fotg210, urb, mem_flags); + if (unlikely(status < 0)) { + fotg210_dbg(fotg210, "can't init itds\n"); + goto done; + } + + /* schedule ... need to lock */ + spin_lock_irqsave(&fotg210->lock, flags); + if (unlikely(!HCD_HW_ACCESSIBLE(fotg210_to_hcd(fotg210)))) { + status = -ESHUTDOWN; + goto done_not_linked; + } + status = usb_hcd_link_urb_to_ep(fotg210_to_hcd(fotg210), urb); + if (unlikely(status)) + goto done_not_linked; + status = iso_stream_schedule(fotg210, urb, stream); + if (likely(status == 0)) + itd_link_urb(fotg210, urb, fotg210->periodic_size << 3, stream); + else + usb_hcd_unlink_urb_from_ep(fotg210_to_hcd(fotg210), urb); + done_not_linked: + spin_unlock_irqrestore(&fotg210->lock, flags); + done: + return status; +} + +/*-------------------------------------------------------------------------*/ + +static void scan_isoc(struct fotg210_hcd *fotg210) +{ + unsigned uf, now_frame, frame; + unsigned fmask = fotg210->periodic_size - 1; + bool modified, live; + + /* + * When running, scan from last scan point up to "now" + * else clean up by scanning everything that's left. + * Touches as few pages as possible: cache-friendly. + */ + if (fotg210->rh_state >= FOTG210_RH_RUNNING) { + uf = fotg210_read_frame_index(fotg210); + now_frame = (uf >> 3) & fmask; + live = true; + } else { + now_frame = (fotg210->next_frame - 1) & fmask; + live = false; + } + fotg210->now_frame = now_frame; + + frame = fotg210->next_frame; + for (;;) { + union fotg210_shadow q, *q_p; + __hc32 type, *hw_p; + +restart: + /* scan each element in frame's queue for completions */ + q_p = &fotg210->pshadow[frame]; + hw_p = &fotg210->periodic[frame]; + q.ptr = q_p->ptr; + type = Q_NEXT_TYPE(fotg210, *hw_p); + modified = false; + + while (q.ptr != NULL) { + switch (hc32_to_cpu(fotg210, type)) { + case Q_TYPE_ITD: + /* If this ITD is still active, leave it for + * later processing ... check the next entry. + * No need to check for activity unless the + * frame is current. + */ + if (frame == now_frame && live) { + rmb(); + for (uf = 0; uf < 8; uf++) { + if (q.itd->hw_transaction[uf] & + ITD_ACTIVE(fotg210)) + break; + } + if (uf < 8) { + q_p = &q.itd->itd_next; + hw_p = &q.itd->hw_next; + type = Q_NEXT_TYPE(fotg210, + q.itd->hw_next); + q = *q_p; + break; + } + } + + /* Take finished ITDs out of the schedule + * and process them: recycle, maybe report + * URB completion. HC won't cache the + * pointer for much longer, if at all. + */ + *q_p = q.itd->itd_next; + *hw_p = q.itd->hw_next; + type = Q_NEXT_TYPE(fotg210, q.itd->hw_next); + wmb(); + modified = itd_complete(fotg210, q.itd); + q = *q_p; + break; + default: + fotg210_dbg(fotg210, "corrupt type %d frame %d shadow %p\n", + type, frame, q.ptr); + /* FALL THROUGH */ + case Q_TYPE_QH: + case Q_TYPE_FSTN: + /* End of the iTDs and siTDs */ + q.ptr = NULL; + break; + } + + /* assume completion callbacks modify the queue */ + if (unlikely(modified && fotg210->isoc_count > 0)) + goto restart; + } + + /* Stop when we have reached the current frame */ + if (frame == now_frame) + break; + frame = (frame + 1) & fmask; + } + fotg210->next_frame = now_frame; +} +/*-------------------------------------------------------------------------*/ +/* + * Display / Set uframe_periodic_max + */ +static ssize_t show_uframe_periodic_max(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct fotg210_hcd *fotg210; + int n; + + fotg210 = hcd_to_fotg210(bus_to_hcd(dev_get_drvdata(dev))); + n = scnprintf(buf, PAGE_SIZE, "%d\n", fotg210->uframe_periodic_max); + return n; +} + + +static ssize_t store_uframe_periodic_max(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct fotg210_hcd *fotg210; + unsigned uframe_periodic_max; + unsigned frame, uframe; + unsigned short allocated_max; + unsigned long flags; + ssize_t ret; + + fotg210 = hcd_to_fotg210(bus_to_hcd(dev_get_drvdata(dev))); + if (kstrtouint(buf, 0, &uframe_periodic_max) < 0) + return -EINVAL; + + if (uframe_periodic_max < 100 || uframe_periodic_max >= 125) { + fotg210_info(fotg210, "rejecting invalid request for uframe_periodic_max=%u\n", + uframe_periodic_max); + return -EINVAL; + } + + ret = -EINVAL; + + /* + * lock, so that our checking does not race with possible periodic + * bandwidth allocation through submitting new urbs. + */ + spin_lock_irqsave(&fotg210->lock, flags); + + /* + * for request to decrease max periodic bandwidth, we have to check + * every microframe in the schedule to see whether the decrease is + * possible. + */ + if (uframe_periodic_max < fotg210->uframe_periodic_max) { + allocated_max = 0; + + for (frame = 0; frame < fotg210->periodic_size; ++frame) + for (uframe = 0; uframe < 7; ++uframe) + allocated_max = max(allocated_max, + periodic_usecs(fotg210, frame, uframe)); + + if (allocated_max > uframe_periodic_max) { + fotg210_info(fotg210, + "cannot decrease uframe_periodic_max becase " + "periodic bandwidth is already allocated " + "(%u > %u)\n", + allocated_max, uframe_periodic_max); + goto out_unlock; + } + } + + /* increasing is always ok */ + + fotg210_info(fotg210, "setting max periodic bandwidth to %u%% (== %u usec/uframe)\n", + 100 * uframe_periodic_max/125, uframe_periodic_max); + + if (uframe_periodic_max != 100) + fotg210_warn(fotg210, "max periodic bandwidth set is non-standard\n"); + + fotg210->uframe_periodic_max = uframe_periodic_max; + ret = count; + +out_unlock: + spin_unlock_irqrestore(&fotg210->lock, flags); + return ret; +} + +static DEVICE_ATTR(uframe_periodic_max, 0644, show_uframe_periodic_max, + store_uframe_periodic_max); + +static inline int create_sysfs_files(struct fotg210_hcd *fotg210) +{ + struct device *controller = fotg210_to_hcd(fotg210)->self.controller; + int i = 0; + + if (i) + goto out; + + i = device_create_file(controller, &dev_attr_uframe_periodic_max); +out: + return i; +} + +static inline void remove_sysfs_files(struct fotg210_hcd *fotg210) +{ + struct device *controller = fotg210_to_hcd(fotg210)->self.controller; + + device_remove_file(controller, &dev_attr_uframe_periodic_max); +} +/*-------------------------------------------------------------------------*/ + +/* On some systems, leaving remote wakeup enabled prevents system shutdown. + * The firmware seems to think that powering off is a wakeup event! + * This routine turns off remote wakeup and everything else, on all ports. + */ +static void fotg210_turn_off_all_ports(struct fotg210_hcd *fotg210) +{ + u32 __iomem *status_reg = &fotg210->regs->port_status; + + fotg210_writel(fotg210, PORT_RWC_BITS, status_reg); +} + +/* + * Halt HC, turn off all ports, and let the BIOS use the companion controllers. + * Must be called with interrupts enabled and the lock not held. + */ +static void fotg210_silence_controller(struct fotg210_hcd *fotg210) +{ + fotg210_halt(fotg210); + + spin_lock_irq(&fotg210->lock); + fotg210->rh_state = FOTG210_RH_HALTED; + fotg210_turn_off_all_ports(fotg210); + spin_unlock_irq(&fotg210->lock); +} + +/* fotg210_shutdown kick in for silicon on any bus (not just pci, etc). + * This forcibly disables dma and IRQs, helping kexec and other cases + * where the next system software may expect clean state. + */ +static void fotg210_shutdown(struct usb_hcd *hcd) +{ + struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); + + spin_lock_irq(&fotg210->lock); + fotg210->shutdown = true; + fotg210->rh_state = FOTG210_RH_STOPPING; + fotg210->enabled_hrtimer_events = 0; + spin_unlock_irq(&fotg210->lock); + + fotg210_silence_controller(fotg210); + + hrtimer_cancel(&fotg210->hrtimer); +} + +/*-------------------------------------------------------------------------*/ + +/* + * fotg210_work is called from some interrupts, timers, and so on. + * it calls driver completion functions, after dropping fotg210->lock. + */ +static void fotg210_work(struct fotg210_hcd *fotg210) +{ + /* another CPU may drop fotg210->lock during a schedule scan while + * it reports urb completions. this flag guards against bogus + * attempts at re-entrant schedule scanning. + */ + if (fotg210->scanning) { + fotg210->need_rescan = true; + return; + } + fotg210->scanning = true; + + rescan: + fotg210->need_rescan = false; + if (fotg210->async_count) + scan_async(fotg210); + if (fotg210->intr_count > 0) + scan_intr(fotg210); + if (fotg210->isoc_count > 0) + scan_isoc(fotg210); + if (fotg210->need_rescan) + goto rescan; + fotg210->scanning = false; + + /* the IO watchdog guards against hardware or driver bugs that + * misplace IRQs, and should let us run completely without IRQs. + * such lossage has been observed on both VT6202 and VT8235. + */ + turn_on_io_watchdog(fotg210); +} + +/* + * Called when the fotg210_hcd module is removed. + */ +static void fotg210_stop(struct usb_hcd *hcd) +{ + struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); + + fotg210_dbg(fotg210, "stop\n"); + + /* no more interrupts ... */ + + spin_lock_irq(&fotg210->lock); + fotg210->enabled_hrtimer_events = 0; + spin_unlock_irq(&fotg210->lock); + + fotg210_quiesce(fotg210); + fotg210_silence_controller(fotg210); + fotg210_reset(fotg210); + + hrtimer_cancel(&fotg210->hrtimer); + remove_sysfs_files(fotg210); + remove_debug_files(fotg210); + + /* root hub is shut down separately (first, when possible) */ + spin_lock_irq(&fotg210->lock); + end_free_itds(fotg210); + spin_unlock_irq(&fotg210->lock); + fotg210_mem_cleanup(fotg210); + +#ifdef FOTG210_STATS + fotg210_dbg(fotg210, "irq normal %ld err %ld iaa %ld (lost %ld)\n", + fotg210->stats.normal, fotg210->stats.error, fotg210->stats.iaa, + fotg210->stats.lost_iaa); + fotg210_dbg(fotg210, "complete %ld unlink %ld\n", + fotg210->stats.complete, fotg210->stats.unlink); +#endif + + dbg_status(fotg210, "fotg210_stop completed", + fotg210_readl(fotg210, &fotg210->regs->status)); +} + +/* one-time init, only for memory state */ +static int hcd_fotg210_init(struct usb_hcd *hcd) +{ + struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); + u32 temp; + int retval; + u32 hcc_params; + struct fotg210_qh_hw *hw; + + spin_lock_init(&fotg210->lock); + + /* + * keep io watchdog by default, those good HCDs could turn off it later + */ + fotg210->need_io_watchdog = 1; + + hrtimer_init(&fotg210->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); + fotg210->hrtimer.function = fotg210_hrtimer_func; + fotg210->next_hrtimer_event = FOTG210_HRTIMER_NO_EVENT; + + hcc_params = fotg210_readl(fotg210, &fotg210->caps->hcc_params); + + /* + * by default set standard 80% (== 100 usec/uframe) max periodic + * bandwidth as required by USB 2.0 + */ + fotg210->uframe_periodic_max = 100; + + /* + * hw default: 1K periodic list heads, one per frame. + * periodic_size can shrink by USBCMD update if hcc_params allows. + */ + fotg210->periodic_size = DEFAULT_I_TDPS; + INIT_LIST_HEAD(&fotg210->intr_qh_list); + INIT_LIST_HEAD(&fotg210->cached_itd_list); + + if (HCC_PGM_FRAMELISTLEN(hcc_params)) { + /* periodic schedule size can be smaller than default */ + switch (FOTG210_TUNE_FLS) { + case 0: + fotg210->periodic_size = 1024; + break; + case 1: + fotg210->periodic_size = 512; + break; + case 2: + fotg210->periodic_size = 256; + break; + default: + BUG(); + } + } + retval = fotg210_mem_init(fotg210, GFP_KERNEL); + if (retval < 0) + return retval; + + /* controllers may cache some of the periodic schedule ... */ + fotg210->i_thresh = 2; + + /* + * dedicate a qh for the async ring head, since we couldn't unlink + * a 'real' qh without stopping the async schedule [4.8]. use it + * as the 'reclamation list head' too. + * its dummy is used in hw_alt_next of many tds, to prevent the qh + * from automatically advancing to the next td after short reads. + */ + fotg210->async->qh_next.qh = NULL; + hw = fotg210->async->hw; + hw->hw_next = QH_NEXT(fotg210, fotg210->async->qh_dma); + hw->hw_info1 = cpu_to_hc32(fotg210, QH_HEAD); + hw->hw_token = cpu_to_hc32(fotg210, QTD_STS_HALT); + hw->hw_qtd_next = FOTG210_LIST_END(fotg210); + fotg210->async->qh_state = QH_STATE_LINKED; + hw->hw_alt_next = QTD_NEXT(fotg210, fotg210->async->dummy->qtd_dma); + + /* clear interrupt enables, set irq latency */ + if (log2_irq_thresh < 0 || log2_irq_thresh > 6) + log2_irq_thresh = 0; + temp = 1 << (16 + log2_irq_thresh); + if (HCC_CANPARK(hcc_params)) { + /* HW default park == 3, on hardware that supports it (like + * NVidia and ALI silicon), maximizes throughput on the async + * schedule by avoiding QH fetches between transfers. + * + * With fast usb storage devices and NForce2, "park" seems to + * make problems: throughput reduction (!), data errors... + */ + if (park) { + park = min_t(unsigned, park, 3); + temp |= CMD_PARK; + temp |= park << 8; + } + fotg210_dbg(fotg210, "park %d\n", park); + } + if (HCC_PGM_FRAMELISTLEN(hcc_params)) { + /* periodic schedule size can be smaller than default */ + temp &= ~(3 << 2); + temp |= (FOTG210_TUNE_FLS << 2); + } + fotg210->command = temp; + + /* Accept arbitrarily long scatter-gather lists */ + if (!(hcd->driver->flags & HCD_LOCAL_MEM)) + hcd->self.sg_tablesize = ~0; + return 0; +} + +/* start HC running; it's halted, hcd_fotg210_init() has been run (once) */ +static int fotg210_run(struct usb_hcd *hcd) +{ + struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); + u32 temp; + u32 hcc_params; + + hcd->uses_new_polling = 1; + + /* EHCI spec section 4.1 */ + + fotg210_writel(fotg210, fotg210->periodic_dma, + &fotg210->regs->frame_list); + fotg210_writel(fotg210, (u32)fotg210->async->qh_dma, + &fotg210->regs->async_next); + + /* + * hcc_params controls whether fotg210->regs->segment must (!!!) + * be used; it constrains QH/ITD/SITD and QTD locations. + * pci_pool consistent memory always uses segment zero. + * streaming mappings for I/O buffers, like pci_map_single(), + * can return segments above 4GB, if the device allows. + * + * NOTE: the dma mask is visible through dma_supported(), so + * drivers can pass this info along ... like NETIF_F_HIGHDMA, + * Scsi_Host.highmem_io, and so forth. It's readonly to all + * host side drivers though. + */ + hcc_params = fotg210_readl(fotg210, &fotg210->caps->hcc_params); + + /* + * Philips, Intel, and maybe others need CMD_RUN before the + * root hub will detect new devices (why?); NEC doesn't + */ + fotg210->command &= ~(CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET); + fotg210->command |= CMD_RUN; + fotg210_writel(fotg210, fotg210->command, &fotg210->regs->command); + dbg_cmd(fotg210, "init", fotg210->command); + + /* + * Start, enabling full USB 2.0 functionality ... usb 1.1 devices + * are explicitly handed to companion controller(s), so no TT is + * involved with the root hub. (Except where one is integrated, + * and there's no companion controller unless maybe for USB OTG.) + * + * Turning on the CF flag will transfer ownership of all ports + * from the companions to the EHCI controller. If any of the + * companions are in the middle of a port reset at the time, it + * could cause trouble. Write-locking ehci_cf_port_reset_rwsem + * guarantees that no resets are in progress. After we set CF, + * a short delay lets the hardware catch up; new resets shouldn't + * be started before the port switching actions could complete. + */ + down_write(&ehci_cf_port_reset_rwsem); + fotg210->rh_state = FOTG210_RH_RUNNING; + /* unblock posted writes */ + fotg210_readl(fotg210, &fotg210->regs->command); + msleep(5); + up_write(&ehci_cf_port_reset_rwsem); + fotg210->last_periodic_enable = ktime_get_real(); + + temp = HC_VERSION(fotg210, + fotg210_readl(fotg210, &fotg210->caps->hc_capbase)); + fotg210_info(fotg210, + "USB %x.%x started, EHCI %x.%02x\n", + ((fotg210->sbrn & 0xf0)>>4), (fotg210->sbrn & 0x0f), + temp >> 8, temp & 0xff); + + fotg210_writel(fotg210, INTR_MASK, + &fotg210->regs->intr_enable); /* Turn On Interrupts */ + + /* GRR this is run-once init(), being done every time the HC starts. + * So long as they're part of class devices, we can't do it init() + * since the class device isn't created that early. + */ + create_debug_files(fotg210); + create_sysfs_files(fotg210); + + return 0; +} + +static int fotg210_setup(struct usb_hcd *hcd) +{ + struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); + int retval; + + fotg210->regs = (void __iomem *)fotg210->caps + + HC_LENGTH(fotg210, + fotg210_readl(fotg210, &fotg210->caps->hc_capbase)); + dbg_hcs_params(fotg210, "reset"); + dbg_hcc_params(fotg210, "reset"); + + /* cache this readonly data; minimize chip reads */ + fotg210->hcs_params = fotg210_readl(fotg210, + &fotg210->caps->hcs_params); + + fotg210->sbrn = HCD_USB2; + + /* data structure init */ + retval = hcd_fotg210_init(hcd); + if (retval) + return retval; + + retval = fotg210_halt(fotg210); + if (retval) + return retval; + + fotg210_reset(fotg210); + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +static irqreturn_t fotg210_irq(struct usb_hcd *hcd) +{ + struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); + u32 status, masked_status, pcd_status = 0, cmd; + int bh; + + spin_lock(&fotg210->lock); + + status = fotg210_readl(fotg210, &fotg210->regs->status); + + /* e.g. cardbus physical eject */ + if (status == ~(u32) 0) { + fotg210_dbg(fotg210, "device removed\n"); + goto dead; + } + + /* + * We don't use STS_FLR, but some controllers don't like it to + * remain on, so mask it out along with the other status bits. + */ + masked_status = status & (INTR_MASK | STS_FLR); + + /* Shared IRQ? */ + if (!masked_status || + unlikely(fotg210->rh_state == FOTG210_RH_HALTED)) { + spin_unlock(&fotg210->lock); + return IRQ_NONE; + } + + /* clear (just) interrupts */ + fotg210_writel(fotg210, masked_status, &fotg210->regs->status); + cmd = fotg210_readl(fotg210, &fotg210->regs->command); + bh = 0; + +#ifdef VERBOSE_DEBUG + /* unrequested/ignored: Frame List Rollover */ + dbg_status(fotg210, "irq", status); +#endif + + /* INT, ERR, and IAA interrupt rates can be throttled */ + + /* normal [4.15.1.2] or error [4.15.1.1] completion */ + if (likely((status & (STS_INT|STS_ERR)) != 0)) { + if (likely((status & STS_ERR) == 0)) + COUNT(fotg210->stats.normal); + else + COUNT(fotg210->stats.error); + bh = 1; + } + + /* complete the unlinking of some qh [4.15.2.3] */ + if (status & STS_IAA) { + + /* Turn off the IAA watchdog */ + fotg210->enabled_hrtimer_events &= + ~BIT(FOTG210_HRTIMER_IAA_WATCHDOG); + + /* + * Mild optimization: Allow another IAAD to reset the + * hrtimer, if one occurs before the next expiration. + * In theory we could always cancel the hrtimer, but + * tests show that about half the time it will be reset + * for some other event anyway. + */ + if (fotg210->next_hrtimer_event == FOTG210_HRTIMER_IAA_WATCHDOG) + ++fotg210->next_hrtimer_event; + + /* guard against (alleged) silicon errata */ + if (cmd & CMD_IAAD) + fotg210_dbg(fotg210, "IAA with IAAD still set?\n"); + if (fotg210->async_iaa) { + COUNT(fotg210->stats.iaa); + end_unlink_async(fotg210); + } else + fotg210_dbg(fotg210, "IAA with nothing unlinked?\n"); + } + + /* remote wakeup [4.3.1] */ + if (status & STS_PCD) { + int pstatus; + u32 __iomem *status_reg = &fotg210->regs->port_status; + + /* kick root hub later */ + pcd_status = status; + + /* resume root hub? */ + if (fotg210->rh_state == FOTG210_RH_SUSPENDED) + usb_hcd_resume_root_hub(hcd); + + pstatus = fotg210_readl(fotg210, status_reg); + + if (test_bit(0, &fotg210->suspended_ports) && + ((pstatus & PORT_RESUME) || + !(pstatus & PORT_SUSPEND)) && + (pstatus & PORT_PE) && + fotg210->reset_done[0] == 0) { + + /* start 20 msec resume signaling from this port, + * and make khubd collect PORT_STAT_C_SUSPEND to + * stop that signaling. Use 5 ms extra for safety, + * like usb_port_resume() does. + */ + fotg210->reset_done[0] = jiffies + msecs_to_jiffies(25); + set_bit(0, &fotg210->resuming_ports); + fotg210_dbg(fotg210, "port 1 remote wakeup\n"); + mod_timer(&hcd->rh_timer, fotg210->reset_done[0]); + } + } + + /* PCI errors [4.15.2.4] */ + if (unlikely((status & STS_FATAL) != 0)) { + fotg210_err(fotg210, "fatal error\n"); + dbg_cmd(fotg210, "fatal", cmd); + dbg_status(fotg210, "fatal", status); +dead: + usb_hc_died(hcd); + + /* Don't let the controller do anything more */ + fotg210->shutdown = true; + fotg210->rh_state = FOTG210_RH_STOPPING; + fotg210->command &= ~(CMD_RUN | CMD_ASE | CMD_PSE); + fotg210_writel(fotg210, fotg210->command, + &fotg210->regs->command); + fotg210_writel(fotg210, 0, &fotg210->regs->intr_enable); + fotg210_handle_controller_death(fotg210); + + /* Handle completions when the controller stops */ + bh = 0; + } + + if (bh) + fotg210_work(fotg210); + spin_unlock(&fotg210->lock); + if (pcd_status) + usb_hcd_poll_rh_status(hcd); + return IRQ_HANDLED; +} + +/*-------------------------------------------------------------------------*/ + +/* + * non-error returns are a promise to giveback() the urb later + * we drop ownership so next owner (or urb unlink) can get it + * + * urb + dev is in hcd.self.controller.urb_list + * we're queueing TDs onto software and hardware lists + * + * hcd-specific init for hcpriv hasn't been done yet + * + * NOTE: control, bulk, and interrupt share the same code to append TDs + * to a (possibly active) QH, and the same QH scanning code. + */ +static int fotg210_urb_enqueue( + struct usb_hcd *hcd, + struct urb *urb, + gfp_t mem_flags +) { + struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); + struct list_head qtd_list; + + INIT_LIST_HEAD(&qtd_list); + + switch (usb_pipetype(urb->pipe)) { + case PIPE_CONTROL: + /* qh_completions() code doesn't handle all the fault cases + * in multi-TD control transfers. Even 1KB is rare anyway. + */ + if (urb->transfer_buffer_length > (16 * 1024)) + return -EMSGSIZE; + /* FALLTHROUGH */ + /* case PIPE_BULK: */ + default: + if (!qh_urb_transaction(fotg210, urb, &qtd_list, mem_flags)) + return -ENOMEM; + return submit_async(fotg210, urb, &qtd_list, mem_flags); + + case PIPE_INTERRUPT: + if (!qh_urb_transaction(fotg210, urb, &qtd_list, mem_flags)) + return -ENOMEM; + return intr_submit(fotg210, urb, &qtd_list, mem_flags); + + case PIPE_ISOCHRONOUS: + return itd_submit(fotg210, urb, mem_flags); + } +} + +/* remove from hardware lists + * completions normally happen asynchronously + */ + +static int fotg210_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) +{ + struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); + struct fotg210_qh *qh; + unsigned long flags; + int rc; + + spin_lock_irqsave(&fotg210->lock, flags); + rc = usb_hcd_check_unlink_urb(hcd, urb, status); + if (rc) + goto done; + + switch (usb_pipetype(urb->pipe)) { + /* case PIPE_CONTROL: */ + /* case PIPE_BULK:*/ + default: + qh = (struct fotg210_qh *) urb->hcpriv; + if (!qh) + break; + switch (qh->qh_state) { + case QH_STATE_LINKED: + case QH_STATE_COMPLETING: + start_unlink_async(fotg210, qh); + break; + case QH_STATE_UNLINK: + case QH_STATE_UNLINK_WAIT: + /* already started */ + break; + case QH_STATE_IDLE: + /* QH might be waiting for a Clear-TT-Buffer */ + qh_completions(fotg210, qh); + break; + } + break; + + case PIPE_INTERRUPT: + qh = (struct fotg210_qh *) urb->hcpriv; + if (!qh) + break; + switch (qh->qh_state) { + case QH_STATE_LINKED: + case QH_STATE_COMPLETING: + start_unlink_intr(fotg210, qh); + break; + case QH_STATE_IDLE: + qh_completions(fotg210, qh); + break; + default: + fotg210_dbg(fotg210, "bogus qh %p state %d\n", + qh, qh->qh_state); + goto done; + } + break; + + case PIPE_ISOCHRONOUS: + /* itd... */ + + /* wait till next completion, do it then. */ + /* completion irqs can wait up to 1024 msec, */ + break; + } +done: + spin_unlock_irqrestore(&fotg210->lock, flags); + return rc; +} + +/*-------------------------------------------------------------------------*/ + +/* bulk qh holds the data toggle */ + +static void +fotg210_endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep) +{ + struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); + unsigned long flags; + struct fotg210_qh *qh, *tmp; + + /* ASSERT: any requests/urbs are being unlinked */ + /* ASSERT: nobody can be submitting urbs for this any more */ + +rescan: + spin_lock_irqsave(&fotg210->lock, flags); + qh = ep->hcpriv; + if (!qh) + goto done; + + /* endpoints can be iso streams. for now, we don't + * accelerate iso completions ... so spin a while. + */ + if (qh->hw == NULL) { + struct fotg210_iso_stream *stream = ep->hcpriv; + + if (!list_empty(&stream->td_list)) + goto idle_timeout; + + /* BUG_ON(!list_empty(&stream->free_list)); */ + kfree(stream); + goto done; + } + + if (fotg210->rh_state < FOTG210_RH_RUNNING) + qh->qh_state = QH_STATE_IDLE; + switch (qh->qh_state) { + case QH_STATE_LINKED: + case QH_STATE_COMPLETING: + for (tmp = fotg210->async->qh_next.qh; + tmp && tmp != qh; + tmp = tmp->qh_next.qh) + continue; + /* periodic qh self-unlinks on empty, and a COMPLETING qh + * may already be unlinked. + */ + if (tmp) + start_unlink_async(fotg210, qh); + /* FALL THROUGH */ + case QH_STATE_UNLINK: /* wait for hw to finish? */ + case QH_STATE_UNLINK_WAIT: +idle_timeout: + spin_unlock_irqrestore(&fotg210->lock, flags); + schedule_timeout_uninterruptible(1); + goto rescan; + case QH_STATE_IDLE: /* fully unlinked */ + if (qh->clearing_tt) + goto idle_timeout; + if (list_empty(&qh->qtd_list)) { + qh_destroy(fotg210, qh); + break; + } + /* else FALL THROUGH */ + default: + /* caller was supposed to have unlinked any requests; + * that's not our job. just leak this memory. + */ + fotg210_err(fotg210, "qh %p (#%02x) state %d%s\n", + qh, ep->desc.bEndpointAddress, qh->qh_state, + list_empty(&qh->qtd_list) ? "" : "(has tds)"); + break; + } + done: + ep->hcpriv = NULL; + spin_unlock_irqrestore(&fotg210->lock, flags); +} + +static void +fotg210_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep) +{ + struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); + struct fotg210_qh *qh; + int eptype = usb_endpoint_type(&ep->desc); + int epnum = usb_endpoint_num(&ep->desc); + int is_out = usb_endpoint_dir_out(&ep->desc); + unsigned long flags; + + if (eptype != USB_ENDPOINT_XFER_BULK && eptype != USB_ENDPOINT_XFER_INT) + return; + + spin_lock_irqsave(&fotg210->lock, flags); + qh = ep->hcpriv; + + /* For Bulk and Interrupt endpoints we maintain the toggle state + * in the hardware; the toggle bits in udev aren't used at all. + * When an endpoint is reset by usb_clear_halt() we must reset + * the toggle bit in the QH. + */ + if (qh) { + usb_settoggle(qh->dev, epnum, is_out, 0); + if (!list_empty(&qh->qtd_list)) { + WARN_ONCE(1, "clear_halt for a busy endpoint\n"); + } else if (qh->qh_state == QH_STATE_LINKED || + qh->qh_state == QH_STATE_COMPLETING) { + + /* The toggle value in the QH can't be updated + * while the QH is active. Unlink it now; + * re-linking will call qh_refresh(). + */ + if (eptype == USB_ENDPOINT_XFER_BULK) + start_unlink_async(fotg210, qh); + else + start_unlink_intr(fotg210, qh); + } + } + spin_unlock_irqrestore(&fotg210->lock, flags); +} + +static int fotg210_get_frame(struct usb_hcd *hcd) +{ + struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd); + return (fotg210_read_frame_index(fotg210) >> 3) % + fotg210->periodic_size; +} + +/*-------------------------------------------------------------------------*/ + +/* + * The EHCI in ChipIdea HDRC cannot be a separate module or device, + * because its registers (and irq) are shared between host/gadget/otg + * functions and in order to facilitate role switching we cannot + * give the fotg210 driver exclusive access to those. + */ +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_LICENSE("GPL"); + +static const struct hc_driver fotg210_fotg210_hc_driver = { + .description = hcd_name, + .product_desc = "Faraday USB2.0 Host Controller", + .hcd_priv_size = sizeof(struct fotg210_hcd), + + /* + * generic hardware linkage + */ + .irq = fotg210_irq, + .flags = HCD_MEMORY | HCD_USB2, + + /* + * basic lifecycle operations + */ + .reset = hcd_fotg210_init, + .start = fotg210_run, + .stop = fotg210_stop, + .shutdown = fotg210_shutdown, + + /* + * managing i/o requests and associated device resources + */ + .urb_enqueue = fotg210_urb_enqueue, + .urb_dequeue = fotg210_urb_dequeue, + .endpoint_disable = fotg210_endpoint_disable, + .endpoint_reset = fotg210_endpoint_reset, + + /* + * scheduling support + */ + .get_frame_number = fotg210_get_frame, + + /* + * root hub support + */ + .hub_status_data = fotg210_hub_status_data, + .hub_control = fotg210_hub_control, + .bus_suspend = fotg210_bus_suspend, + .bus_resume = fotg210_bus_resume, + + .relinquish_port = fotg210_relinquish_port, + .port_handed_over = fotg210_port_handed_over, + + .clear_tt_buffer_complete = fotg210_clear_tt_buffer_complete, +}; + +static void fotg210_init(struct fotg210_hcd *fotg210) +{ + u32 value; + + iowrite32(GMIR_MDEV_INT | GMIR_MOTG_INT | GMIR_INT_POLARITY, + &fotg210->regs->gmir); + + value = ioread32(&fotg210->regs->otgcsr); + value &= ~OTGCSR_A_BUS_DROP; + value |= OTGCSR_A_BUS_REQ; + iowrite32(value, &fotg210->regs->otgcsr); +} + +/** + * fotg210_hcd_probe - initialize faraday FOTG210 HCDs + * + * Allocates basic resources for this USB host controller, and + * then invokes the start() method for the HCD associated with it + * through the hotplug entry's driver_data. + */ +static int fotg210_hcd_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct usb_hcd *hcd; + struct resource *res; + int irq; + int retval = -ENODEV; + struct fotg210_hcd *fotg210; + + if (usb_disabled()) + return -ENODEV; + + pdev->dev.power.power_state = PMSG_ON; + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res) { + dev_err(dev, + "Found HC with no IRQ. Check %s setup!\n", + dev_name(dev)); + return -ENODEV; + } + + irq = res->start; + + hcd = usb_create_hcd(&fotg210_fotg210_hc_driver, dev, + dev_name(dev)); + if (!hcd) { + dev_err(dev, "failed to create hcd with err %d\n", retval); + retval = -ENOMEM; + goto fail_create_hcd; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, + "Found HC with no register addr. Check %s setup!\n", + dev_name(dev)); + retval = -ENODEV; + goto fail_request_resource; + } + + hcd->rsrc_start = res->start; + hcd->rsrc_len = resource_size(res); + hcd->has_tt = 1; + + if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, + fotg210_fotg210_hc_driver.description)) { + dev_dbg(dev, "controller already in use\n"); + retval = -EBUSY; + goto fail_request_resource; + } + + res = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (!res) { + dev_err(dev, + "Found HC with no register addr. Check %s setup!\n", + dev_name(dev)); + retval = -ENODEV; + goto fail_request_resource; + } + + hcd->regs = ioremap_nocache(res->start, resource_size(res)); + if (hcd->regs == NULL) { + dev_dbg(dev, "error mapping memory\n"); + retval = -EFAULT; + goto fail_ioremap; + } + + fotg210 = hcd_to_fotg210(hcd); + + fotg210->caps = hcd->regs; + + retval = fotg210_setup(hcd); + if (retval) + goto fail_add_hcd; + + fotg210_init(fotg210); + + retval = usb_add_hcd(hcd, irq, IRQF_SHARED); + if (retval) { + dev_err(dev, "failed to add hcd with err %d\n", retval); + goto fail_add_hcd; + } + + return retval; + +fail_add_hcd: + iounmap(hcd->regs); +fail_ioremap: + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); +fail_request_resource: + usb_put_hcd(hcd); +fail_create_hcd: + dev_err(dev, "init %s fail, %d\n", dev_name(dev), retval); + return retval; +} + +/** + * fotg210_hcd_remove - shutdown processing for EHCI HCDs + * @dev: USB Host Controller being removed + * + */ +static int fotg210_hcd_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct usb_hcd *hcd = dev_get_drvdata(dev); + + if (!hcd) + return 0; + + usb_remove_hcd(hcd); + iounmap(hcd->regs); + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + usb_put_hcd(hcd); + + return 0; +} + +static struct platform_driver fotg210_hcd_driver = { + .driver = { + .name = "fotg210-hcd", + }, + .probe = fotg210_hcd_probe, + .remove = fotg210_hcd_remove, +}; + +static int __init fotg210_hcd_init(void) +{ + int retval = 0; + + if (usb_disabled()) + return -ENODEV; + + pr_info("%s: " DRIVER_DESC "\n", hcd_name); + set_bit(USB_EHCI_LOADED, &usb_hcds_loaded); + if (test_bit(USB_UHCI_LOADED, &usb_hcds_loaded) || + test_bit(USB_OHCI_LOADED, &usb_hcds_loaded)) + pr_warn(KERN_WARNING "Warning! fotg210_hcd should always be loaded before uhci_hcd and ohci_hcd, not after\n"); + + pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd\n", + hcd_name, + sizeof(struct fotg210_qh), sizeof(struct fotg210_qtd), + sizeof(struct fotg210_itd)); + +#ifdef DEBUG + fotg210_debug_root = debugfs_create_dir("fotg210", usb_debug_root); + if (!fotg210_debug_root) { + retval = -ENOENT; + goto err_debug; + } +#endif + + retval = platform_driver_register(&fotg210_hcd_driver); + if (retval < 0) + goto clean; + return retval; + + platform_driver_unregister(&fotg210_hcd_driver); +clean: +#ifdef DEBUG + debugfs_remove(fotg210_debug_root); + fotg210_debug_root = NULL; +err_debug: +#endif + clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded); + return retval; +} +module_init(fotg210_hcd_init); + +static void __exit fotg210_hcd_cleanup(void) +{ + platform_driver_unregister(&fotg210_hcd_driver); +#ifdef DEBUG + debugfs_remove(fotg210_debug_root); +#endif + clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded); +} +module_exit(fotg210_hcd_cleanup); diff --git a/drivers/usb/host/fotg210.h b/drivers/usb/host/fotg210.h new file mode 100644 index 000000000000..8920f9d32564 --- /dev/null +++ b/drivers/usb/host/fotg210.h @@ -0,0 +1,750 @@ +#ifndef __LINUX_FOTG210_H +#define __LINUX_FOTG210_H + +/* definitions used for the EHCI driver */ + +/* + * __hc32 and __hc16 are "Host Controller" types, they may be equivalent to + * __leXX (normally) or __beXX (given FOTG210_BIG_ENDIAN_DESC), depending on + * the host controller implementation. + * + * To facilitate the strongest possible byte-order checking from "sparse" + * and so on, we use __leXX unless that's not practical. + */ +#define __hc32 __le32 +#define __hc16 __le16 + +/* statistics can be kept for tuning/monitoring */ +struct fotg210_stats { + /* irq usage */ + unsigned long normal; + unsigned long error; + unsigned long iaa; + unsigned long lost_iaa; + + /* termination of urbs from core */ + unsigned long complete; + unsigned long unlink; +}; + +/* fotg210_hcd->lock guards shared data against other CPUs: + * fotg210_hcd: async, unlink, periodic (and shadow), ... + * usb_host_endpoint: hcpriv + * fotg210_qh: qh_next, qtd_list + * fotg210_qtd: qtd_list + * + * Also, hold this lock when talking to HC registers or + * when updating hw_* fields in shared qh/qtd/... structures. + */ + +#define FOTG210_MAX_ROOT_PORTS 1 /* see HCS_N_PORTS */ + +/* + * fotg210_rh_state values of FOTG210_RH_RUNNING or above mean that the + * controller may be doing DMA. Lower values mean there's no DMA. + */ +enum fotg210_rh_state { + FOTG210_RH_HALTED, + FOTG210_RH_SUSPENDED, + FOTG210_RH_RUNNING, + FOTG210_RH_STOPPING +}; + +/* + * Timer events, ordered by increasing delay length. + * Always update event_delays_ns[] and event_handlers[] (defined in + * ehci-timer.c) in parallel with this list. + */ +enum fotg210_hrtimer_event { + FOTG210_HRTIMER_POLL_ASS, /* Poll for async schedule off */ + FOTG210_HRTIMER_POLL_PSS, /* Poll for periodic schedule off */ + FOTG210_HRTIMER_POLL_DEAD, /* Wait for dead controller to stop */ + FOTG210_HRTIMER_UNLINK_INTR, /* Wait for interrupt QH unlink */ + FOTG210_HRTIMER_FREE_ITDS, /* Wait for unused iTDs and siTDs */ + FOTG210_HRTIMER_ASYNC_UNLINKS, /* Unlink empty async QHs */ + FOTG210_HRTIMER_IAA_WATCHDOG, /* Handle lost IAA interrupts */ + FOTG210_HRTIMER_DISABLE_PERIODIC, /* Wait to disable periodic sched */ + FOTG210_HRTIMER_DISABLE_ASYNC, /* Wait to disable async sched */ + FOTG210_HRTIMER_IO_WATCHDOG, /* Check for missing IRQs */ + FOTG210_HRTIMER_NUM_EVENTS /* Must come last */ +}; +#define FOTG210_HRTIMER_NO_EVENT 99 + +struct fotg210_hcd { /* one per controller */ + /* timing support */ + enum fotg210_hrtimer_event next_hrtimer_event; + unsigned enabled_hrtimer_events; + ktime_t hr_timeouts[FOTG210_HRTIMER_NUM_EVENTS]; + struct hrtimer hrtimer; + + int PSS_poll_count; + int ASS_poll_count; + int died_poll_count; + + /* glue to PCI and HCD framework */ + struct fotg210_caps __iomem *caps; + struct fotg210_regs __iomem *regs; + struct fotg210_dbg_port __iomem *debug; + + __u32 hcs_params; /* cached register copy */ + spinlock_t lock; + enum fotg210_rh_state rh_state; + + /* general schedule support */ + bool scanning:1; + bool need_rescan:1; + bool intr_unlinking:1; + bool async_unlinking:1; + bool shutdown:1; + struct fotg210_qh *qh_scan_next; + + /* async schedule support */ + struct fotg210_qh *async; + struct fotg210_qh *dummy; /* For AMD quirk use */ + struct fotg210_qh *async_unlink; + struct fotg210_qh *async_unlink_last; + struct fotg210_qh *async_iaa; + unsigned async_unlink_cycle; + unsigned async_count; /* async activity count */ + + /* periodic schedule support */ +#define DEFAULT_I_TDPS 1024 /* some HCs can do less */ + unsigned periodic_size; + __hc32 *periodic; /* hw periodic table */ + dma_addr_t periodic_dma; + struct list_head intr_qh_list; + unsigned i_thresh; /* uframes HC might cache */ + + union fotg210_shadow *pshadow; /* mirror hw periodic table */ + struct fotg210_qh *intr_unlink; + struct fotg210_qh *intr_unlink_last; + unsigned intr_unlink_cycle; + unsigned now_frame; /* frame from HC hardware */ + unsigned next_frame; /* scan periodic, start here */ + unsigned intr_count; /* intr activity count */ + unsigned isoc_count; /* isoc activity count */ + unsigned periodic_count; /* periodic activity count */ + /* max periodic time per uframe */ + unsigned uframe_periodic_max; + + + /* list of itds completed while now_frame was still active */ + struct list_head cached_itd_list; + struct fotg210_itd *last_itd_to_free; + + /* per root hub port */ + unsigned long reset_done[FOTG210_MAX_ROOT_PORTS]; + + /* bit vectors (one bit per port) */ + unsigned long bus_suspended; /* which ports were + already suspended at the start of a bus suspend */ + unsigned long companion_ports; /* which ports are + dedicated to the companion controller */ + unsigned long owned_ports; /* which ports are + owned by the companion during a bus suspend */ + unsigned long port_c_suspend; /* which ports have + the change-suspend feature turned on */ + unsigned long suspended_ports; /* which ports are + suspended */ + unsigned long resuming_ports; /* which ports have + started to resume */ + + /* per-HC memory pools (could be per-bus, but ...) */ + struct dma_pool *qh_pool; /* qh per active urb */ + struct dma_pool *qtd_pool; /* one or more per qh */ + struct dma_pool *itd_pool; /* itd per iso urb */ + + unsigned random_frame; + unsigned long next_statechange; + ktime_t last_periodic_enable; + u32 command; + + /* SILICON QUIRKS */ + unsigned need_io_watchdog:1; + unsigned fs_i_thresh:1; /* Intel iso scheduling */ + + u8 sbrn; /* packed release number */ + + /* irq statistics */ +#ifdef FOTG210_STATS + struct fotg210_stats stats; +# define COUNT(x) ((x)++) +#else +# define COUNT(x) +#endif + + /* debug files */ +#ifdef DEBUG + struct dentry *debug_dir; +#endif +}; + +/* convert between an HCD pointer and the corresponding FOTG210_HCD */ +static inline struct fotg210_hcd *hcd_to_fotg210(struct usb_hcd *hcd) +{ + return (struct fotg210_hcd *)(hcd->hcd_priv); +} +static inline struct usb_hcd *fotg210_to_hcd(struct fotg210_hcd *fotg210) +{ + return container_of((void *) fotg210, struct usb_hcd, hcd_priv); +} + +/*-------------------------------------------------------------------------*/ + +/* EHCI register interface, corresponds to EHCI Revision 0.95 specification */ + +/* Section 2.2 Host Controller Capability Registers */ +struct fotg210_caps { + /* these fields are specified as 8 and 16 bit registers, + * but some hosts can't perform 8 or 16 bit PCI accesses. + * some hosts treat caplength and hciversion as parts of a 32-bit + * register, others treat them as two separate registers, this + * affects the memory map for big endian controllers. + */ + u32 hc_capbase; +#define HC_LENGTH(fotg210, p) (0x00ff&((p) >> /* bits 7:0 / offset 00h */ \ + (fotg210_big_endian_capbase(fotg210) ? 24 : 0))) +#define HC_VERSION(fotg210, p) (0xffff&((p) >> /* bits 31:16 / offset 02h */ \ + (fotg210_big_endian_capbase(fotg210) ? 0 : 16))) + u32 hcs_params; /* HCSPARAMS - offset 0x4 */ +#define HCS_N_PORTS(p) (((p)>>0)&0xf) /* bits 3:0, ports on HC */ + + u32 hcc_params; /* HCCPARAMS - offset 0x8 */ +#define HCC_CANPARK(p) ((p)&(1 << 2)) /* true: can park on async qh */ +#define HCC_PGM_FRAMELISTLEN(p) ((p)&(1 << 1)) /* true: periodic_size changes*/ + u8 portroute[8]; /* nibbles for routing - offset 0xC */ +}; + + +/* Section 2.3 Host Controller Operational Registers */ +struct fotg210_regs { + + /* USBCMD: offset 0x00 */ + u32 command; + +/* EHCI 1.1 addendum */ +/* 23:16 is r/w intr rate, in microframes; default "8" == 1/msec */ +#define CMD_PARK (1<<11) /* enable "park" on async qh */ +#define CMD_PARK_CNT(c) (((c)>>8)&3) /* how many transfers to park for */ +#define CMD_IAAD (1<<6) /* "doorbell" interrupt async advance */ +#define CMD_ASE (1<<5) /* async schedule enable */ +#define CMD_PSE (1<<4) /* periodic schedule enable */ +/* 3:2 is periodic frame list size */ +#define CMD_RESET (1<<1) /* reset HC not bus */ +#define CMD_RUN (1<<0) /* start/stop HC */ + + /* USBSTS: offset 0x04 */ + u32 status; +#define STS_ASS (1<<15) /* Async Schedule Status */ +#define STS_PSS (1<<14) /* Periodic Schedule Status */ +#define STS_RECL (1<<13) /* Reclamation */ +#define STS_HALT (1<<12) /* Not running (any reason) */ +/* some bits reserved */ + /* these STS_* flags are also intr_enable bits (USBINTR) */ +#define STS_IAA (1<<5) /* Interrupted on async advance */ +#define STS_FATAL (1<<4) /* such as some PCI access errors */ +#define STS_FLR (1<<3) /* frame list rolled over */ +#define STS_PCD (1<<2) /* port change detect */ +#define STS_ERR (1<<1) /* "error" completion (overflow, ...) */ +#define STS_INT (1<<0) /* "normal" completion (short, ...) */ + + /* USBINTR: offset 0x08 */ + u32 intr_enable; + + /* FRINDEX: offset 0x0C */ + u32 frame_index; /* current microframe number */ + /* CTRLDSSEGMENT: offset 0x10 */ + u32 segment; /* address bits 63:32 if needed */ + /* PERIODICLISTBASE: offset 0x14 */ + u32 frame_list; /* points to periodic list */ + /* ASYNCLISTADDR: offset 0x18 */ + u32 async_next; /* address of next async queue head */ + + u32 reserved1; + /* PORTSC: offset 0x20 */ + u32 port_status; +/* 31:23 reserved */ +#define PORT_USB11(x) (((x)&(3<<10)) == (1<<10)) /* USB 1.1 device */ +#define PORT_RESET (1<<8) /* reset port */ +#define PORT_SUSPEND (1<<7) /* suspend port */ +#define PORT_RESUME (1<<6) /* resume it */ +#define PORT_PEC (1<<3) /* port enable change */ +#define PORT_PE (1<<2) /* port enable */ +#define PORT_CSC (1<<1) /* connect status change */ +#define PORT_CONNECT (1<<0) /* device connected */ +#define PORT_RWC_BITS (PORT_CSC | PORT_PEC) + u32 reserved2[19]; + + /* OTGCSR: offet 0x70 */ + u32 otgcsr; +#define OTGCSR_HOST_SPD_TYP (3 << 22) +#define OTGCSR_A_BUS_DROP (1 << 5) +#define OTGCSR_A_BUS_REQ (1 << 4) + + /* OTGISR: offset 0x74 */ + u32 otgisr; +#define OTGISR_OVC (1 << 10) + + u32 reserved3[15]; + + /* GMIR: offset 0xB4 */ + u32 gmir; +#define GMIR_INT_POLARITY (1 << 3) /*Active High*/ +#define GMIR_MHC_INT (1 << 2) +#define GMIR_MOTG_INT (1 << 1) +#define GMIR_MDEV_INT (1 << 0) +}; + +/* Appendix C, Debug port ... intended for use with special "debug devices" + * that can help if there's no serial console. (nonstandard enumeration.) + */ +struct fotg210_dbg_port { + u32 control; +#define DBGP_OWNER (1<<30) +#define DBGP_ENABLED (1<<28) +#define DBGP_DONE (1<<16) +#define DBGP_INUSE (1<<10) +#define DBGP_ERRCODE(x) (((x)>>7)&0x07) +# define DBGP_ERR_BAD 1 +# define DBGP_ERR_SIGNAL 2 +#define DBGP_ERROR (1<<6) +#define DBGP_GO (1<<5) +#define DBGP_OUT (1<<4) +#define DBGP_LEN(x) (((x)>>0)&0x0f) + u32 pids; +#define DBGP_PID_GET(x) (((x)>>16)&0xff) +#define DBGP_PID_SET(data, tok) (((data)<<8)|(tok)) + u32 data03; + u32 data47; + u32 address; +#define DBGP_EPADDR(dev, ep) (((dev)<<8)|(ep)) +}; + +#ifdef CONFIG_EARLY_PRINTK_DBGP +#include +extern int __init early_dbgp_init(char *s); +extern struct console early_dbgp_console; +#endif /* CONFIG_EARLY_PRINTK_DBGP */ + +struct usb_hcd; + +static inline int xen_dbgp_reset_prep(struct usb_hcd *hcd) +{ + return 1; /* Shouldn't this be 0? */ +} + +static inline int xen_dbgp_external_startup(struct usb_hcd *hcd) +{ + return -1; +} + +#ifdef CONFIG_EARLY_PRINTK_DBGP +/* Call backs from fotg210 host driver to fotg210 debug driver */ +extern int dbgp_external_startup(struct usb_hcd *); +extern int dbgp_reset_prep(struct usb_hcd *hcd); +#else +static inline int dbgp_reset_prep(struct usb_hcd *hcd) +{ + return xen_dbgp_reset_prep(hcd); +} +static inline int dbgp_external_startup(struct usb_hcd *hcd) +{ + return xen_dbgp_external_startup(hcd); +} +#endif + +/*-------------------------------------------------------------------------*/ + +#define QTD_NEXT(fotg210, dma) cpu_to_hc32(fotg210, (u32)dma) + +/* + * EHCI Specification 0.95 Section 3.5 + * QTD: describe data transfer components (buffer, direction, ...) + * See Fig 3-6 "Queue Element Transfer Descriptor Block Diagram". + * + * These are associated only with "QH" (Queue Head) structures, + * used with control, bulk, and interrupt transfers. + */ +struct fotg210_qtd { + /* first part defined by EHCI spec */ + __hc32 hw_next; /* see EHCI 3.5.1 */ + __hc32 hw_alt_next; /* see EHCI 3.5.2 */ + __hc32 hw_token; /* see EHCI 3.5.3 */ +#define QTD_TOGGLE (1 << 31) /* data toggle */ +#define QTD_LENGTH(tok) (((tok)>>16) & 0x7fff) +#define QTD_IOC (1 << 15) /* interrupt on complete */ +#define QTD_CERR(tok) (((tok)>>10) & 0x3) +#define QTD_PID(tok) (((tok)>>8) & 0x3) +#define QTD_STS_ACTIVE (1 << 7) /* HC may execute this */ +#define QTD_STS_HALT (1 << 6) /* halted on error */ +#define QTD_STS_DBE (1 << 5) /* data buffer error (in HC) */ +#define QTD_STS_BABBLE (1 << 4) /* device was babbling (qtd halted) */ +#define QTD_STS_XACT (1 << 3) /* device gave illegal response */ +#define QTD_STS_MMF (1 << 2) /* incomplete split transaction */ +#define QTD_STS_STS (1 << 1) /* split transaction state */ +#define QTD_STS_PING (1 << 0) /* issue PING? */ + +#define ACTIVE_BIT(fotg210) cpu_to_hc32(fotg210, QTD_STS_ACTIVE) +#define HALT_BIT(fotg210) cpu_to_hc32(fotg210, QTD_STS_HALT) +#define STATUS_BIT(fotg210) cpu_to_hc32(fotg210, QTD_STS_STS) + + __hc32 hw_buf[5]; /* see EHCI 3.5.4 */ + __hc32 hw_buf_hi[5]; /* Appendix B */ + + /* the rest is HCD-private */ + dma_addr_t qtd_dma; /* qtd address */ + struct list_head qtd_list; /* sw qtd list */ + struct urb *urb; /* qtd's urb */ + size_t length; /* length of buffer */ +} __aligned(32); + +/* mask NakCnt+T in qh->hw_alt_next */ +#define QTD_MASK(fotg210) cpu_to_hc32(fotg210, ~0x1f) + +#define IS_SHORT_READ(token) (QTD_LENGTH(token) != 0 && QTD_PID(token) == 1) + +/*-------------------------------------------------------------------------*/ + +/* type tag from {qh,itd,fstn}->hw_next */ +#define Q_NEXT_TYPE(fotg210, dma) ((dma) & cpu_to_hc32(fotg210, 3 << 1)) + +/* + * Now the following defines are not converted using the + * 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. + */ +/* values for that type tag */ +#define Q_TYPE_ITD (0 << 1) +#define Q_TYPE_QH (1 << 1) +#define Q_TYPE_SITD (2 << 1) +#define Q_TYPE_FSTN (3 << 1) + +/* next async queue entry, or pointer to interrupt/periodic QH */ +#define QH_NEXT(fotg210, dma) \ + (cpu_to_hc32(fotg210, (((u32)dma)&~0x01f)|Q_TYPE_QH)) + +/* for periodic/async schedules and qtd lists, mark end of list */ +#define FOTG210_LIST_END(fotg210) \ + cpu_to_hc32(fotg210, 1) /* "null pointer" to hw */ + +/* + * Entries in periodic shadow table are pointers to one of four kinds + * of data structure. That's dictated by the hardware; a type tag is + * encoded in the low bits of the hardware's periodic schedule. Use + * Q_NEXT_TYPE to get the tag. + * + * For entries in the async schedule, the type tag always says "qh". + */ +union fotg210_shadow { + struct fotg210_qh *qh; /* Q_TYPE_QH */ + struct fotg210_itd *itd; /* Q_TYPE_ITD */ + struct fotg210_fstn *fstn; /* Q_TYPE_FSTN */ + __hc32 *hw_next; /* (all types) */ + void *ptr; +}; + +/*-------------------------------------------------------------------------*/ + +/* + * EHCI Specification 0.95 Section 3.6 + * QH: describes control/bulk/interrupt endpoints + * See Fig 3-7 "Queue Head Structure Layout". + * + * These appear in both the async and (for interrupt) periodic schedules. + */ + +/* first part defined by EHCI spec */ +struct fotg210_qh_hw { + __hc32 hw_next; /* see EHCI 3.6.1 */ + __hc32 hw_info1; /* see EHCI 3.6.2 */ +#define QH_CONTROL_EP (1 << 27) /* FS/LS control endpoint */ +#define QH_HEAD (1 << 15) /* Head of async reclamation list */ +#define QH_TOGGLE_CTL (1 << 14) /* Data toggle control */ +#define QH_HIGH_SPEED (2 << 12) /* Endpoint speed */ +#define QH_LOW_SPEED (1 << 12) +#define QH_FULL_SPEED (0 << 12) +#define QH_INACTIVATE (1 << 7) /* Inactivate on next transaction */ + __hc32 hw_info2; /* see EHCI 3.6.2 */ +#define QH_SMASK 0x000000ff +#define QH_CMASK 0x0000ff00 +#define QH_HUBADDR 0x007f0000 +#define QH_HUBPORT 0x3f800000 +#define QH_MULT 0xc0000000 + __hc32 hw_current; /* qtd list - see EHCI 3.6.4 */ + + /* qtd overlay (hardware parts of a struct fotg210_qtd) */ + __hc32 hw_qtd_next; + __hc32 hw_alt_next; + __hc32 hw_token; + __hc32 hw_buf[5]; + __hc32 hw_buf_hi[5]; +} __aligned(32); + +struct fotg210_qh { + struct fotg210_qh_hw *hw; /* Must come first */ + /* the rest is HCD-private */ + dma_addr_t qh_dma; /* address of qh */ + union fotg210_shadow qh_next; /* ptr to qh; or periodic */ + struct list_head qtd_list; /* sw qtd list */ + struct list_head intr_node; /* list of intr QHs */ + struct fotg210_qtd *dummy; + struct fotg210_qh *unlink_next; /* next on unlink list */ + + unsigned unlink_cycle; + + u8 needs_rescan; /* Dequeue during giveback */ + u8 qh_state; +#define QH_STATE_LINKED 1 /* HC sees this */ +#define QH_STATE_UNLINK 2 /* HC may still see this */ +#define QH_STATE_IDLE 3 /* HC doesn't see this */ +#define QH_STATE_UNLINK_WAIT 4 /* LINKED and on unlink 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 */ + u8 c_usecs; /* ... split completion bw */ + u16 tt_usecs; /* tt downstream bandwidth */ + unsigned short period; /* polling interval */ + unsigned short start; /* where polling starts */ +#define NO_FRAME ((unsigned short)~0) /* pick new start */ + + struct usb_device *dev; /* access to TT */ + unsigned is_out:1; /* bulk or intr OUT */ + unsigned clearing_tt:1; /* Clear-TT-Buf in progress */ +}; + +/*-------------------------------------------------------------------------*/ + +/* description of one iso transaction (up to 3 KB data if highspeed) */ +struct fotg210_iso_packet { + /* These will be copied to iTD when scheduling */ + u64 bufp; /* itd->hw_bufp{,_hi}[pg] |= */ + __hc32 transaction; /* itd->hw_transaction[i] |= */ + u8 cross; /* buf crosses pages */ + /* for full speed OUT splits */ + u32 buf1; +}; + +/* temporary schedule data for packets from iso urbs (both speeds) + * each packet is one logical usb transaction to the device (not TT), + * beginning at stream->next_uframe + */ +struct fotg210_iso_sched { + struct list_head td_list; + unsigned span; + struct fotg210_iso_packet packet[0]; +}; + +/* + * fotg210_iso_stream - groups all (s)itds for this endpoint. + * acts like a qh would, if EHCI had them for ISO. + */ +struct fotg210_iso_stream { + /* first field matches fotg210_hq, but is NULL */ + struct fotg210_qh_hw *hw; + + u8 bEndpointAddress; + u8 highspeed; + struct list_head td_list; /* queued itds */ + struct list_head free_list; /* list of unused itds */ + struct usb_device *udev; + struct usb_host_endpoint *ep; + + /* output of (re)scheduling */ + int next_uframe; + __hc32 splits; + + /* the rest is derived from the endpoint descriptor, + * trusting urb->interval == f(epdesc->bInterval) and + * including the extra info for hw_bufp[0..2] + */ + u8 usecs, c_usecs; + u16 interval; + u16 tt_usecs; + u16 maxp; + u16 raw_mask; + unsigned bandwidth; + + /* This is used to initialize iTD's hw_bufp fields */ + __hc32 buf0; + __hc32 buf1; + __hc32 buf2; + + /* this is used to initialize sITD's tt info */ + __hc32 address; +}; + +/*-------------------------------------------------------------------------*/ + +/* + * EHCI Specification 0.95 Section 3.3 + * Fig 3-4 "Isochronous Transaction Descriptor (iTD)" + * + * Schedule records for high speed iso xfers + */ +struct fotg210_itd { + /* first part defined by EHCI spec */ + __hc32 hw_next; /* see EHCI 3.3.1 */ + __hc32 hw_transaction[8]; /* see EHCI 3.3.2 */ +#define FOTG210_ISOC_ACTIVE (1<<31) /* activate transfer this slot */ +#define FOTG210_ISOC_BUF_ERR (1<<30) /* Data buffer error */ +#define FOTG210_ISOC_BABBLE (1<<29) /* babble detected */ +#define FOTG210_ISOC_XACTERR (1<<28) /* XactErr - transaction error */ +#define FOTG210_ITD_LENGTH(tok) (((tok)>>16) & 0x0fff) +#define FOTG210_ITD_IOC (1 << 15) /* interrupt on complete */ + +#define ITD_ACTIVE(fotg210) cpu_to_hc32(fotg210, FOTG210_ISOC_ACTIVE) + + __hc32 hw_bufp[7]; /* see EHCI 3.3.3 */ + __hc32 hw_bufp_hi[7]; /* Appendix B */ + + /* the rest is HCD-private */ + dma_addr_t itd_dma; /* for this itd */ + union fotg210_shadow itd_next; /* ptr to periodic q entry */ + + struct urb *urb; + struct fotg210_iso_stream *stream; /* endpoint's queue */ + struct list_head itd_list; /* list of stream's itds */ + + /* any/all hw_transactions here may be used by that urb */ + unsigned frame; /* where scheduled */ + unsigned pg; + unsigned index[8]; /* in urb->iso_frame_desc */ +} __aligned(32); + +/*-------------------------------------------------------------------------*/ + +/* + * EHCI Specification 0.96 Section 3.7 + * Periodic Frame Span Traversal Node (FSTN) + * + * Manages split interrupt transactions (using TT) that span frame boundaries + * into uframes 0/1; see 4.12.2.2. In those uframes, a "save place" FSTN + * makes the HC jump (back) to a QH to scan for fs/ls QH completions until + * it hits a "restore" FSTN; then it returns to finish other uframe 0/1 work. + */ +struct fotg210_fstn { + __hc32 hw_next; /* any periodic q entry */ + __hc32 hw_prev; /* qh or FOTG210_LIST_END */ + + /* the rest is HCD-private */ + dma_addr_t fstn_dma; + union fotg210_shadow fstn_next; /* ptr to periodic q entry */ +} __aligned(32); + +/*-------------------------------------------------------------------------*/ + +/* Prepare the PORTSC wakeup flags during controller suspend/resume */ + +#define fotg210_prepare_ports_for_controller_suspend(fotg210, do_wakeup) \ + fotg210_adjust_port_wakeup_flags(fotg210, true, do_wakeup); + +#define fotg210_prepare_ports_for_controller_resume(fotg210) \ + fotg210_adjust_port_wakeup_flags(fotg210, false, false); + +/*-------------------------------------------------------------------------*/ + +/* + * Some EHCI controllers have a Transaction Translator built into the + * root hub. This is a non-standard feature. Each controller will need + * to add code to the following inline functions, and call them as + * needed (mostly in root hub code). + */ + +static inline unsigned int +fotg210_get_speed(struct fotg210_hcd *fotg210, unsigned int portsc) +{ + return (readl(&fotg210->regs->otgcsr) + & OTGCSR_HOST_SPD_TYP) >> 22; +} + +/* Returns the speed of a device attached to a port on the root hub. */ +static inline unsigned int +fotg210_port_speed(struct fotg210_hcd *fotg210, unsigned int portsc) +{ + switch (fotg210_get_speed(fotg210, portsc)) { + case 0: + return 0; + case 1: + return USB_PORT_STAT_LOW_SPEED; + case 2: + default: + return USB_PORT_STAT_HIGH_SPEED; + } +} + +/*-------------------------------------------------------------------------*/ + +#define fotg210_has_fsl_portno_bug(e) (0) + +/* + * While most USB host controllers implement their registers in + * little-endian format, a minority (celleb companion chip) implement + * them in big endian format. + * + * This attempts to support either format at compile time without a + * runtime penalty, or both formats with the additional overhead + * of checking a flag bit. + * + */ + +#define fotg210_big_endian_mmio(e) 0 +#define fotg210_big_endian_capbase(e) 0 + +static inline unsigned int fotg210_readl(const struct fotg210_hcd *fotg210, + __u32 __iomem *regs) +{ + return readl(regs); +} + +static inline void fotg210_writel(const struct fotg210_hcd *fotg210, + const unsigned int val, __u32 __iomem *regs) +{ + writel(val, regs); +} + +/* cpu to fotg210 */ +static inline __hc32 cpu_to_hc32(const struct fotg210_hcd *fotg210, const u32 x) +{ + return cpu_to_le32(x); +} + +/* fotg210 to cpu */ +static inline u32 hc32_to_cpu(const struct fotg210_hcd *fotg210, const __hc32 x) +{ + return le32_to_cpu(x); +} + +static inline u32 hc32_to_cpup(const struct fotg210_hcd *fotg210, + const __hc32 *x) +{ + return le32_to_cpup(x); +} + +/*-------------------------------------------------------------------------*/ + +static inline unsigned fotg210_read_frame_index(struct fotg210_hcd *fotg210) +{ + return fotg210_readl(fotg210, &fotg210->regs->frame_index); +} + +#define fotg210_itdlen(urb, desc, t) ({ \ + usb_pipein((urb)->pipe) ? \ + (desc)->length - FOTG210_ITD_LENGTH(t) : \ + FOTG210_ITD_LENGTH(t); \ +}) +/*-------------------------------------------------------------------------*/ + +#ifndef DEBUG +#define STUB_DEBUG_FILES +#endif /* DEBUG */ + +/*-------------------------------------------------------------------------*/ + +#endif /* __LINUX_FOTG210_H */ From 7d46a21a1e27e1b4138feab42130861def57f4fc Mon Sep 17 00:00:00 2001 From: Emil Goode Date: Sun, 28 Jul 2013 00:38:55 +0200 Subject: [PATCH 1024/3400] staging: lustre: Fix non-ANSI sparse warnings This patch fixes a lot of non-ANSI sparse warnings by adding void to parameterless functions. Signed-off-by: Emil Goode Signed-off-by: Greg Kroah-Hartman --- .../lustre/lnet/klnds/socklnd/socklnd_lib-linux.c | 6 +++--- drivers/staging/lustre/lnet/lnet/api-ni.c | 2 +- drivers/staging/lustre/lnet/selftest/console.c | 2 +- .../lustre/lustre/libcfs/linux/linux-tracefile.c | 14 +++++++------- .../staging/lustre/lustre/ptlrpc/pack_generic.c | 2 +- drivers/staging/lustre/lustre/ptlrpc/pinger.c | 4 ++-- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.c index 3e08fe2d1489..76e442be5582 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.c @@ -325,20 +325,20 @@ ksocknal_lib_tunables_init () } void -ksocknal_lib_tunables_fini () +ksocknal_lib_tunables_fini(void) { if (ksocknal_tunables.ksnd_sysctl != NULL) unregister_sysctl_table(ksocknal_tunables.ksnd_sysctl); } #else int -ksocknal_lib_tunables_init () +ksocknal_lib_tunables_init(void) { return 0; } void -ksocknal_lib_tunables_fini () +ksocknal_lib_tunables_fini(void) { } #endif /* # if CONFIG_SYSCTL && !CFS_SYSFS_MODULE_PARM */ diff --git a/drivers/staging/lustre/lnet/lnet/api-ni.c b/drivers/staging/lustre/lnet/lnet/api-ni.c index 250c61868704..160a4292c6ce 100644 --- a/drivers/staging/lustre/lnet/lnet/api-ni.c +++ b/drivers/staging/lustre/lnet/lnet/api-ni.c @@ -1371,7 +1371,7 @@ EXPORT_SYMBOL(LNetNIInit); * \return always 0 for current implementation. */ int -LNetNIFini() +LNetNIFini(void) { LNET_MUTEX_LOCK(&the_lnet.ln_api_mutex); diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c index 78e8d0467267..09e4700af640 100644 --- a/drivers/staging/lustre/lnet/selftest/console.c +++ b/drivers/staging/lustre/lnet/selftest/console.c @@ -1773,7 +1773,7 @@ lstcon_session_info(lst_sid_t *sid_up, int *key_up, unsigned *featp, } int -lstcon_session_end() +lstcon_session_end(void) { lstcon_rpc_trans_t *trans; lstcon_group_t *grp; diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-tracefile.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-tracefile.c index a500a0b5ba9f..162beee24a73 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-tracefile.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-tracefile.c @@ -51,7 +51,7 @@ char *cfs_trace_console_buffers[NR_CPUS][CFS_TCD_TYPE_MAX]; struct rw_semaphore cfs_tracefile_sem; -int cfs_tracefile_init_arch() +int cfs_tracefile_init_arch(void) { int i; int j; @@ -96,7 +96,7 @@ out: return -ENOMEM; } -void cfs_tracefile_fini_arch() +void cfs_tracefile_fini_arch(void) { int i; int j; @@ -116,27 +116,27 @@ void cfs_tracefile_fini_arch() fini_rwsem(&cfs_tracefile_sem); } -void cfs_tracefile_read_lock() +void cfs_tracefile_read_lock(void) { down_read(&cfs_tracefile_sem); } -void cfs_tracefile_read_unlock() +void cfs_tracefile_read_unlock(void) { up_read(&cfs_tracefile_sem); } -void cfs_tracefile_write_lock() +void cfs_tracefile_write_lock(void) { down_write(&cfs_tracefile_sem); } -void cfs_tracefile_write_unlock() +void cfs_tracefile_write_unlock(void) { up_write(&cfs_tracefile_sem); } -cfs_trace_buf_type_t cfs_trace_buf_idx_get() +cfs_trace_buf_type_t cfs_trace_buf_idx_get(void) { if (in_irq()) return CFS_TCD_TYPE_IRQ; diff --git a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c index ffff64833557..9c20d0c60678 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c @@ -115,7 +115,7 @@ int lustre_msg_check_version(struct lustre_msg *msg, __u32 version) EXPORT_SYMBOL(lustre_msg_check_version); /* early reply size */ -int lustre_msg_early_size() +int lustre_msg_early_size(void) { static int size = 0; if (!size) { diff --git a/drivers/staging/lustre/lustre/ptlrpc/pinger.c b/drivers/staging/lustre/lustre/ptlrpc/pinger.c index f521251a1a6e..79e7d0852e95 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pinger.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pinger.c @@ -51,7 +51,7 @@ struct mutex pinger_mutex; static LIST_HEAD(pinger_imports); static struct list_head timeout_list = LIST_HEAD_INIT(timeout_list); -int ptlrpc_pinger_suppress_pings() +int ptlrpc_pinger_suppress_pings(void) { return suppress_pings; } @@ -608,7 +608,7 @@ int ptlrpc_pinger_remove_timeouts(void) return 0; } -void ptlrpc_pinger_wake_up() +void ptlrpc_pinger_wake_up(void) { thread_add_flags(&pinger_thread, SVC_EVENT); wake_up(&pinger_thread.t_ctl_waitq); From 805e517aae4a8d47f5a5069eabfded1f26e95343 Mon Sep 17 00:00:00 2001 From: Emil Goode Date: Sun, 28 Jul 2013 00:38:56 +0200 Subject: [PATCH 1025/3400] staging: lustre: Fix sparse warnings about use of obsolete initializer This patch fixes a lot of sparse warnings about use of obsolete struct and array initializer. Signed-off-by: Emil Goode Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ldlm/ldlm_lib.c | 16 +++--- .../staging/lustre/lustre/ldlm/ldlm_lock.c | 50 +++++++++---------- .../staging/lustre/lustre/ldlm/ldlm_request.c | 5 +- .../lustre/lustre/libcfs/linux/linux-debug.c | 6 +-- .../lustre/lustre/libcfs/linux/linux-module.c | 6 +-- .../staging/lustre/lustre/mdc/mdc_request.c | 2 +- 6 files changed, 44 insertions(+), 41 deletions(-) diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c index aace5342b76a..950f90acec04 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c @@ -762,14 +762,14 @@ void target_send_reply(struct ptlrpc_request *req, int rc, int fail_id) EXPORT_SYMBOL(target_send_reply); ldlm_mode_t lck_compat_array[] = { - [LCK_EX] LCK_COMPAT_EX, - [LCK_PW] LCK_COMPAT_PW, - [LCK_PR] LCK_COMPAT_PR, - [LCK_CW] LCK_COMPAT_CW, - [LCK_CR] LCK_COMPAT_CR, - [LCK_NL] LCK_COMPAT_NL, - [LCK_GROUP] LCK_COMPAT_GROUP, - [LCK_COS] LCK_COMPAT_COS, + [LCK_EX] = LCK_COMPAT_EX, + [LCK_PW] = LCK_COMPAT_PW, + [LCK_PR] = LCK_COMPAT_PR, + [LCK_CW] = LCK_COMPAT_CW, + [LCK_CR] = LCK_COMPAT_CR, + [LCK_NL] = LCK_COMPAT_NL, + [LCK_GROUP] = LCK_COMPAT_GROUP, + [LCK_COS] = LCK_COMPAT_COS, }; /** diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c index ce1add149f52..a9174209aa8f 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c @@ -49,45 +49,45 @@ /* lock types */ char *ldlm_lockname[] = { - [0] "--", - [LCK_EX] "EX", - [LCK_PW] "PW", - [LCK_PR] "PR", - [LCK_CW] "CW", - [LCK_CR] "CR", - [LCK_NL] "NL", - [LCK_GROUP] "GROUP", - [LCK_COS] "COS" + [0] = "--", + [LCK_EX] = "EX", + [LCK_PW] = "PW", + [LCK_PR] = "PR", + [LCK_CW] = "CW", + [LCK_CR] = "CR", + [LCK_NL] = "NL", + [LCK_GROUP] = "GROUP", + [LCK_COS] = "COS", }; EXPORT_SYMBOL(ldlm_lockname); char *ldlm_typename[] = { - [LDLM_PLAIN] "PLN", - [LDLM_EXTENT] "EXT", - [LDLM_FLOCK] "FLK", - [LDLM_IBITS] "IBT", + [LDLM_PLAIN] = "PLN", + [LDLM_EXTENT] = "EXT", + [LDLM_FLOCK] = "FLK", + [LDLM_IBITS] = "IBT", }; EXPORT_SYMBOL(ldlm_typename); static ldlm_policy_wire_to_local_t ldlm_policy_wire18_to_local[] = { - [LDLM_PLAIN - LDLM_MIN_TYPE] ldlm_plain_policy_wire_to_local, - [LDLM_EXTENT - LDLM_MIN_TYPE] ldlm_extent_policy_wire_to_local, - [LDLM_FLOCK - LDLM_MIN_TYPE] ldlm_flock_policy_wire18_to_local, - [LDLM_IBITS - LDLM_MIN_TYPE] ldlm_ibits_policy_wire_to_local, + [LDLM_PLAIN - LDLM_MIN_TYPE] = ldlm_plain_policy_wire_to_local, + [LDLM_EXTENT - LDLM_MIN_TYPE] = ldlm_extent_policy_wire_to_local, + [LDLM_FLOCK - LDLM_MIN_TYPE] = ldlm_flock_policy_wire18_to_local, + [LDLM_IBITS - LDLM_MIN_TYPE] = ldlm_ibits_policy_wire_to_local, }; static ldlm_policy_wire_to_local_t ldlm_policy_wire21_to_local[] = { - [LDLM_PLAIN - LDLM_MIN_TYPE] ldlm_plain_policy_wire_to_local, - [LDLM_EXTENT - LDLM_MIN_TYPE] ldlm_extent_policy_wire_to_local, - [LDLM_FLOCK - LDLM_MIN_TYPE] ldlm_flock_policy_wire21_to_local, - [LDLM_IBITS - LDLM_MIN_TYPE] ldlm_ibits_policy_wire_to_local, + [LDLM_PLAIN - LDLM_MIN_TYPE] = ldlm_plain_policy_wire_to_local, + [LDLM_EXTENT - LDLM_MIN_TYPE] = ldlm_extent_policy_wire_to_local, + [LDLM_FLOCK - LDLM_MIN_TYPE] = ldlm_flock_policy_wire21_to_local, + [LDLM_IBITS - LDLM_MIN_TYPE] = ldlm_ibits_policy_wire_to_local, }; static ldlm_policy_local_to_wire_t ldlm_policy_local_to_wire[] = { - [LDLM_PLAIN - LDLM_MIN_TYPE] ldlm_plain_policy_local_to_wire, - [LDLM_EXTENT - LDLM_MIN_TYPE] ldlm_extent_policy_local_to_wire, - [LDLM_FLOCK - LDLM_MIN_TYPE] ldlm_flock_policy_local_to_wire, - [LDLM_IBITS - LDLM_MIN_TYPE] ldlm_ibits_policy_local_to_wire, + [LDLM_PLAIN - LDLM_MIN_TYPE] = ldlm_plain_policy_local_to_wire, + [LDLM_EXTENT - LDLM_MIN_TYPE] = ldlm_extent_policy_local_to_wire, + [LDLM_FLOCK - LDLM_MIN_TYPE] = ldlm_flock_policy_local_to_wire, + [LDLM_IBITS - LDLM_MIN_TYPE] = ldlm_ibits_policy_local_to_wire, }; /** diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c index c900706a9c8d..6f21a1204a64 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c @@ -2068,7 +2068,10 @@ void ldlm_namespace_foreach(struct ldlm_namespace *ns, ldlm_iterator_t iter, void *closure) { - struct iter_helper_data helper = { iter: iter, closure: closure }; + struct iter_helper_data helper = { + .iter = iter, + .closure = closure, + }; cfs_hash_for_each_nolock(ns->ns_rs_hash, ldlm_res_iter_helper, &helper); diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c index 6afb35073141..9b57304e6caa 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c @@ -194,9 +194,9 @@ static int panic_notifier(struct notifier_block *self, unsigned long unused1, } static struct notifier_block libcfs_panic_notifier = { - notifier_call : panic_notifier, - next : NULL, - priority : 10000 + .notifier_call = panic_notifier, + .next = NULL, + .priority = 10000, }; void libcfs_register_panic_notifier(void) diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c index d8f320e6f4b6..7449f4f18640 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c @@ -171,9 +171,9 @@ static long libcfs_ioctl(struct file *file, } static struct file_operations libcfs_fops = { - unlocked_ioctl: libcfs_ioctl, - open : libcfs_psdev_open, - release : libcfs_psdev_release + .unlocked_ioctl = libcfs_ioctl, + .open = libcfs_psdev_open, + .release = libcfs_psdev_release, }; struct miscdevice libcfs_dev = { diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 191edc6470cd..2dabfc01d224 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -2378,7 +2378,7 @@ static int mdc_resource_inode_free(struct ldlm_resource *res) } struct ldlm_valblock_ops inode_lvbo = { - lvbo_free: mdc_resource_inode_free + .lvbo_free = mdc_resource_inode_free, }; static int mdc_setup(struct obd_device *obd, struct lustre_cfg *cfg) From fc4360d66472f33970c51464eb3b3a77f956d13e Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 29 Jul 2013 12:59:30 +0800 Subject: [PATCH 1026/3400] staging: xillybus: remove duplicated include from xillybus_core.c Remove duplicated include. Signed-off-by: Wei Yongjun Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xillybus/xillybus_core.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/xillybus/xillybus_core.c b/drivers/staging/xillybus/xillybus_core.c index 7991e572ef04..9ccd6aa7e8c5 100644 --- a/drivers/staging/xillybus/xillybus_core.c +++ b/drivers/staging/xillybus/xillybus_core.c @@ -27,11 +27,9 @@ #include #include #include -#include #include #include #include -#include #include #include #include "xillybus.h" From 485754f5cc79e438e81909e72a14d0a402d70f83 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 29 Jul 2013 12:33:24 +0800 Subject: [PATCH 1027/3400] staging: gdm724x: remove duplicated include from gdm_lte.c Remove duplicated include. Signed-off-by: Wei Yongjun Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gdm724x/gdm_lte.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/gdm724x/gdm_lte.c b/drivers/staging/gdm724x/gdm_lte.c index 68ebc7d1eae6..7165d3a1490e 100644 --- a/drivers/staging/gdm724x/gdm_lte.c +++ b/drivers/staging/gdm724x/gdm_lte.c @@ -21,9 +21,7 @@ #include #include #include -#include #include -#include #include #include #include From a66b0f039cddfd01152eb773c4f60b246f612516 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 29 Jul 2013 12:28:51 +0800 Subject: [PATCH 1028/3400] staging: comedi: dt9812: remove duplicated include from dt9812.c Remove duplicated include. Signed-off-by: Wei Yongjun Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt9812.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c index bd14017b798c..7d78c78a4a27 100644 --- a/drivers/staging/comedi/drivers/dt9812.c +++ b/drivers/staging/comedi/drivers/dt9812.c @@ -42,7 +42,6 @@ for my needs. #include #include #include -#include #include #include From 9c02d0dbdefdb8953f6bce698bcce651a13f3a19 Mon Sep 17 00:00:00 2001 From: Won Kang Date: Sat, 27 Jul 2013 15:42:18 +0900 Subject: [PATCH 1029/3400] staging: gdm724x: Modified function name conflict set_endian Conflict resolution for function name set_endian when building for powerpc The name changed to gdm_set_endian Reported-by: kbuild test robot Signed-off-by: Won Kang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gdm724x/gdm_endian.c | 2 +- drivers/staging/gdm724x/gdm_endian.h | 2 +- drivers/staging/gdm724x/gdm_usb.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/gdm724x/gdm_endian.c b/drivers/staging/gdm724x/gdm_endian.c index 02934093ce7f..f6cc90ae9ba6 100644 --- a/drivers/staging/gdm724x/gdm_endian.c +++ b/drivers/staging/gdm724x/gdm_endian.c @@ -14,7 +14,7 @@ #include #include "gdm_endian.h" -void set_endian(struct gdm_endian *ed, u8 dev_endian) +void gdm_set_endian(struct gdm_endian *ed, u8 dev_endian) { u8 a[2] = {0x12, 0x34}; u8 b[2] = {0, }; diff --git a/drivers/staging/gdm724x/gdm_endian.h b/drivers/staging/gdm724x/gdm_endian.h index 775794db6ab6..9b2531ff908e 100644 --- a/drivers/staging/gdm724x/gdm_endian.h +++ b/drivers/staging/gdm724x/gdm_endian.h @@ -40,7 +40,7 @@ struct gdm_endian { u8 host_ed; }; -void set_endian(struct gdm_endian *ed, u8 dev_endian); +void gdm_set_endian(struct gdm_endian *ed, u8 dev_endian); u16 gdm_cpu_to_dev16(struct gdm_endian *ed, u16 x); u16 gdm_dev16_to_cpu(struct gdm_endian *ed, u16 x); u32 gdm_cpu_to_dev32(struct gdm_endian *ed, u32 x); diff --git a/drivers/staging/gdm724x/gdm_usb.c b/drivers/staging/gdm724x/gdm_usb.c index 4b10f23845ad..bdc96370e430 100644 --- a/drivers/staging/gdm724x/gdm_usb.c +++ b/drivers/staging/gdm724x/gdm_usb.c @@ -870,9 +870,9 @@ static int gdm_usb_probe(struct usb_interface *intf, const struct usb_device_id /* List up hosts with big endians, otherwise, defaults to little endian */ if (idProduct == PID_GDM7243) - set_endian(&udev->gdm_ed, ENDIANNESS_BIG); + gdm_set_endian(&udev->gdm_ed, ENDIANNESS_BIG); else - set_endian(&udev->gdm_ed, ENDIANNESS_LITTLE); + gdm_set_endian(&udev->gdm_ed, ENDIANNESS_LITTLE); ret = request_mac_address(udev); if (ret < 0) { From ca250b6017910ca6edca4cbd6eaa7452a13b5c03 Mon Sep 17 00:00:00 2001 From: Marc Dietrich Date: Sat, 27 Jul 2013 18:20:58 +0200 Subject: [PATCH 1030/3400] staging: nvec: re-enable the clock on resume On resume the slave controller is reinitialized. The tegra i2c master controller disables the clock at the end of the initialiation, propably to save some power, and enables it again on each transfer. We don't do this yet and also forgot to enable the clock on resume. Fix this copy-paste error by not disabling the clock after initialization. This didn't striked us yet because suspend/resume hasn't landed in mainline yet, but will soon. Signed-off-by: Marc Dietrich Signed-off-by: Greg Kroah-Hartman --- drivers/staging/nvec/nvec.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c index 10393da315d7..5a5c6397e740 100644 --- a/drivers/staging/nvec/nvec.c +++ b/drivers/staging/nvec/nvec.c @@ -750,8 +750,6 @@ static void tegra_init_i2c_slave(struct nvec_chip *nvec) writel(0, nvec->base + I2C_SL_ADDR2); enable_irq(nvec->irq); - - clk_disable_unprepare(nvec->i2c_clk); } #ifdef CONFIG_PM_SLEEP @@ -872,9 +870,6 @@ static int tegra_nvec_probe(struct platform_device *pdev) tegra_init_i2c_slave(nvec); - clk_prepare_enable(i2c_clk); - - /* enable event reporting */ nvec_toggle_global_events(nvec, true); From 37c79c711dc382e3408964a839f5fbb9a5b6d14f Mon Sep 17 00:00:00 2001 From: Lilis Iskandar Date: Sun, 28 Jul 2013 03:34:43 +0800 Subject: [PATCH 1031/3400] Staging: bcm: LeakyBucket: Fixed spacing/tabing issues This one fixes spacing/tabbing issues. Signed-off-by: Lilis Iskandar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/LeakyBucket.c | 170 +++++++++++++++--------------- 1 file changed, 85 insertions(+), 85 deletions(-) diff --git a/drivers/staging/bcm/LeakyBucket.c b/drivers/staging/bcm/LeakyBucket.c index 877cf0b2bee1..ee1d9f6ca0d2 100644 --- a/drivers/staging/bcm/LeakyBucket.c +++ b/drivers/staging/bcm/LeakyBucket.c @@ -17,30 +17,30 @@ static VOID UpdateTokenCount(register struct bcm_mini_adapter *Adapter) { - ULONG liCurrentTime; - INT i = 0; + ULONG liCurrentTime; + INT i = 0; struct timeval tv; BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "=====>\n"); - if(NULL == Adapter) + if (NULL == Adapter) { - BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "Adapter found NULL!\n"); return; } do_gettimeofday(&tv); - for(i = 0; i < NO_OF_QUEUES; i++) + for (i = 0; i < NO_OF_QUEUES; i++) { - if(TRUE == Adapter->PackInfo[i].bValid && + if (TRUE == Adapter->PackInfo[i].bValid && (1 == Adapter->PackInfo[i].ucDirection)) { liCurrentTime = ((tv.tv_sec- Adapter->PackInfo[i].stLastUpdateTokenAt.tv_sec)*1000 + (tv.tv_usec-Adapter->PackInfo[i].stLastUpdateTokenAt.tv_usec)/ 1000); - if(0!=liCurrentTime) + if (0 != liCurrentTime) { Adapter->PackInfo[i].uiCurrentTokenCount += (ULONG) ((Adapter->PackInfo[i].uiMaxAllowedRate) * @@ -48,7 +48,7 @@ static VOID UpdateTokenCount(register struct bcm_mini_adapter *Adapter) memcpy(&Adapter->PackInfo[i].stLastUpdateTokenAt, &tv, sizeof(struct timeval)); Adapter->PackInfo[i].liLastUpdateTokenAt = liCurrentTime; - if((Adapter->PackInfo[i].uiCurrentTokenCount) >= + if ((Adapter->PackInfo[i].uiCurrentTokenCount) >= Adapter->PackInfo[i].uiMaxBucketSize) { Adapter->PackInfo[i].uiCurrentTokenCount = @@ -57,7 +57,7 @@ static VOID UpdateTokenCount(register struct bcm_mini_adapter *Adapter) } } } - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "<=====\n"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "<=====\n"); return; } @@ -79,33 +79,33 @@ static VOID UpdateTokenCount(register struct bcm_mini_adapter *Adapter) ***********************************************************************/ static ULONG GetSFTokenCount(struct bcm_mini_adapter *Adapter, struct bcm_packet_info *psSF) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IsPacketAllowedForFlow ===>"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IsPacketAllowedForFlow ===>"); /* Validate the parameters */ - if(NULL == Adapter || (psSF < Adapter->PackInfo && + if (NULL == Adapter || (psSF < Adapter->PackInfo && (uintptr_t)psSF > (uintptr_t) &Adapter->PackInfo[HiPriority])) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IPAFF: Got wrong Parameters:Adapter: %p, QIndex: %zd\n", Adapter, (psSF-Adapter->PackInfo)); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IPAFF: Got wrong Parameters:Adapter: %p, QIndex: %zd\n", Adapter, (psSF-Adapter->PackInfo)); return 0; } - if(FALSE != psSF->bValid && psSF->ucDirection) + if (FALSE != psSF->bValid && psSF->ucDirection) { - if(0 != psSF->uiCurrentTokenCount) + if (0 != psSF->uiCurrentTokenCount) { return psSF->uiCurrentTokenCount; } else { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "Not enough tokens in queue %zd Available %u\n", + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "Not enough tokens in queue %zd Available %u\n", psSF-Adapter->PackInfo, psSF->uiCurrentTokenCount); psSF->uiPendedLast = 1; } } else { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IPAFF: Queue %zd not valid\n", psSF-Adapter->PackInfo); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IPAFF: Queue %zd not valid\n", psSF-Adapter->PackInfo); } - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IsPacketAllowedForFlow <==="); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IsPacketAllowedForFlow <==="); return 0; } @@ -118,31 +118,31 @@ static INT SendPacketFromQueue(struct bcm_mini_adapter *Adapter,/**"); - if(!Adapter || !Packet || !psSF) + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, "=====>"); + if (!Adapter || !Packet || !psSF) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, "Got NULL Adapter or Packet"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, "Got NULL Adapter or Packet"); return -EINVAL; } - if(psSF->liDrainCalculated==0) + if (psSF->liDrainCalculated == 0) { psSF->liDrainCalculated = jiffies; } ///send the packet to the fifo.. PktLen = Packet->len; Status = SetupNextSend(Adapter, Packet, psSF->usVCID_Value); - if(Status == 0) + if (Status == 0) { - for(uiIndex = 0 ; uiIndex < MIBS_MAX_HIST_ENTRIES ; uiIndex++) - { if((PktLen <= MIBS_PKTSIZEHIST_RANGE*(uiIndex+1)) && (PktLen > MIBS_PKTSIZEHIST_RANGE*(uiIndex))) + for (uiIndex = 0; uiIndex < MIBS_MAX_HIST_ENTRIES; uiIndex++) + { if ((PktLen <= MIBS_PKTSIZEHIST_RANGE*(uiIndex+1)) && (PktLen > MIBS_PKTSIZEHIST_RANGE*(uiIndex))) Adapter->aTxPktSizeHist[uiIndex]++; } } - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, "<====="); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, "<====="); return Status; } @@ -160,48 +160,48 @@ static INT SendPacketFromQueue(struct bcm_mini_adapter *Adapter,/**", (psSF-Adapter->PackInfo)); - if((psSF != &Adapter->PackInfo[HiPriority]) && Adapter->LinkUpStatus && atomic_read(&psSF->uiPerSFTxResourceCount))//Get data packet - { - if(!psSF->ucDirection ) + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "%zd ====>", (psSF-Adapter->PackInfo)); + if ((psSF != &Adapter->PackInfo[HiPriority]) && Adapter->LinkUpStatus && atomic_read(&psSF->uiPerSFTxResourceCount))//Get data packet + { + if (!psSF->ucDirection) return; - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "UpdateTokenCount "); - if(Adapter->IdleMode || Adapter->bPreparingForLowPowerMode) + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "UpdateTokenCount "); + if (Adapter->IdleMode || Adapter->bPreparingForLowPowerMode) return; /* in idle mode */ // Check for Free Descriptors - if(atomic_read(&Adapter->CurrNumFreeTxDesc) <= MINIMUM_PENDING_DESCRIPTORS) + if (atomic_read(&Adapter->CurrNumFreeTxDesc) <= MINIMUM_PENDING_DESCRIPTORS) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, " No Free Tx Descriptor(%d) is available for Data pkt..",atomic_read(&Adapter->CurrNumFreeTxDesc)); - return ; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, " No Free Tx Descriptor(%d) is available for Data pkt..", atomic_read(&Adapter->CurrNumFreeTxDesc)); + return; } spin_lock_bh(&psSF->SFQueueLock); - QueuePacket=psSF->FirstTxQueue; + QueuePacket = psSF->FirstTxQueue; - if(QueuePacket) + if (QueuePacket) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Dequeuing Data Packet"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Dequeuing Data Packet"); - if(psSF->bEthCSSupport) + if (psSF->bEthCSSupport) iPacketLen = QueuePacket->len; else iPacketLen = QueuePacket->len-ETH_HLEN; - iPacketLen<<=3; - if(iPacketLen <= GetSFTokenCount(Adapter, psSF)) + iPacketLen <<= 3; + if (iPacketLen <= GetSFTokenCount(Adapter, psSF)) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Allowed bytes %d", + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Allowed bytes %d", (iPacketLen >> 3)); - DEQUEUEPACKET(psSF->FirstTxQueue,psSF->LastTxQueue); + DEQUEUEPACKET(psSF->FirstTxQueue, psSF->LastTxQueue); psSF->uiCurrentBytesOnHost -= (QueuePacket->len); psSF->uiCurrentPacketsOnHost--; atomic_dec(&Adapter->TotalPacketCount); @@ -212,8 +212,8 @@ static VOID CheckAndSendPacketFromIndex(struct bcm_mini_adapter *Adapter, struct } else { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "For Queue: %zd\n", psSF-Adapter->PackInfo); - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nAvailable Tokens = %d required = %d\n", + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "For Queue: %zd\n", psSF-Adapter->PackInfo); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nAvailable Tokens = %d required = %d\n", psSF->uiCurrentTokenCount, iPacketLen); //this part indicates that because of non-availability of the tokens //pkt has not been send out hence setting the pending flag indicating the host to send it out @@ -230,22 +230,22 @@ static VOID CheckAndSendPacketFromIndex(struct bcm_mini_adapter *Adapter, struct else { - if((atomic_read(&Adapter->CurrNumFreeTxDesc) > 0 ) && + if ((atomic_read(&Adapter->CurrNumFreeTxDesc) > 0) && (atomic_read(&Adapter->index_rd_txcntrlpkt) != atomic_read(&Adapter->index_wr_txcntrlpkt)) ) { pControlPacket = Adapter->txctlpacket [(atomic_read(&Adapter->index_rd_txcntrlpkt)%MAX_CNTRL_PKTS)]; - if(pControlPacket) + if (pControlPacket) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Sending Control packet"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Sending Control packet"); Status = SendControlPacket(Adapter, pControlPacket); - if(STATUS_SUCCESS==Status) + if (STATUS_SUCCESS == Status) { spin_lock_bh(&psSF->SFQueueLock); psSF->NumOfPacketsSent++; - psSF->uiSentBytes+=((struct bcm_leader *)pControlPacket)->PLength; + psSF->uiSentBytes += ((struct bcm_leader *)pControlPacket)->PLength; psSF->uiSentPackets++; atomic_dec(&Adapter->TotalPacketCount); psSF->uiCurrentBytesOnHost -= ((struct bcm_leader *)pControlPacket)->PLength; @@ -254,11 +254,11 @@ static VOID CheckAndSendPacketFromIndex(struct bcm_mini_adapter *Adapter, struct spin_unlock_bh(&psSF->SFQueueLock); } else - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "SendControlPacket Failed\n"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "SendControlPacket Failed\n"); } else { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, " Control Pkt is not available, Indexing is wrong...."); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, " Control Pkt is not available, Indexing is wrong...."); } } } @@ -277,79 +277,79 @@ static VOID CheckAndSendPacketFromIndex(struct bcm_mini_adapter *Adapter, struct ********************************************************************/ VOID transmit_packets(struct bcm_mini_adapter *Adapter) { - UINT uiPrevTotalCount = 0; + UINT uiPrevTotalCount = 0; int iIndex = 0; - BOOLEAN exit_flag = TRUE ; + BOOLEAN exit_flag = TRUE; - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "=====>"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "=====>"); - if(NULL == Adapter) + if (NULL == Adapter) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX,TX_PACKETS, DBG_LVL_ALL, "Got NULL Adapter"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Got NULL Adapter"); return; } - if(Adapter->device_removed == TRUE) + if (Adapter->device_removed == TRUE) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Device removed"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Device removed"); return; } - BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nUpdateTokenCount ====>\n"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nUpdateTokenCount ====>\n"); UpdateTokenCount(Adapter); - BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nPruneQueueAllSF ====>\n"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nPruneQueueAllSF ====>\n"); PruneQueueAllSF(Adapter); uiPrevTotalCount = atomic_read(&Adapter->TotalPacketCount); - for(iIndex=HiPriority;iIndex>=0;iIndex--) + for (iIndex = HiPriority; iIndex >= 0; iIndex--) { - if( !uiPrevTotalCount || (TRUE == Adapter->device_removed)) + if (!uiPrevTotalCount || (TRUE == Adapter->device_removed)) break; - if(Adapter->PackInfo[iIndex].bValid && + if (Adapter->PackInfo[iIndex].bValid && Adapter->PackInfo[iIndex].uiPendedLast && Adapter->PackInfo[iIndex].uiCurrentBytesOnHost) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling CheckAndSendPacketFromIndex.."); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling CheckAndSendPacketFromIndex.."); CheckAndSendPacketFromIndex(Adapter, &Adapter->PackInfo[iIndex]); uiPrevTotalCount--; } } - while(uiPrevTotalCount > 0 && !Adapter->device_removed) + while (uiPrevTotalCount > 0 && !Adapter->device_removed) { - exit_flag = TRUE ; + exit_flag = TRUE; //second iteration to parse non-pending queues - for(iIndex=HiPriority;iIndex>=0;iIndex--) + for (iIndex = HiPriority; iIndex >= 0; iIndex--) { - if( !uiPrevTotalCount || (TRUE == Adapter->device_removed)) - break; + if (!uiPrevTotalCount || (TRUE == Adapter->device_removed)) + break; - if(Adapter->PackInfo[iIndex].bValid && + if (Adapter->PackInfo[iIndex].bValid && Adapter->PackInfo[iIndex].uiCurrentBytesOnHost && - !Adapter->PackInfo[iIndex].uiPendedLast ) + !Adapter->PackInfo[iIndex].uiPendedLast) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling CheckAndSendPacketFromIndex.."); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling CheckAndSendPacketFromIndex.."); CheckAndSendPacketFromIndex(Adapter, &Adapter->PackInfo[iIndex]); uiPrevTotalCount--; exit_flag = FALSE; } } - if(Adapter->IdleMode || Adapter->bPreparingForLowPowerMode) + if (Adapter->IdleMode || Adapter->bPreparingForLowPowerMode) { - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "In Idle Mode\n"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "In Idle Mode\n"); break; } - if(exit_flag == TRUE ) - break ; - }/* end of inner while loop */ + if (exit_flag == TRUE) + break; + } /* end of inner while loop */ - update_per_cid_rx (Adapter); + update_per_cid_rx(Adapter); Adapter->txtransmit_running = 0; - BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "<======"); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "<======"); } From 68f4f09b9a58345452211a5ad1d7f2b50a23a00e Mon Sep 17 00:00:00 2001 From: Lilis Iskandar Date: Sun, 28 Jul 2013 03:34:44 +0800 Subject: [PATCH 1032/3400] Staging: bcm: LeakyBucket: Fixed brace issues Fixed brace issues Signed-off-by: Lilis Iskandar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/LeakyBucket.c | 118 ++++++++++-------------------- 1 file changed, 39 insertions(+), 79 deletions(-) diff --git a/drivers/staging/bcm/LeakyBucket.c b/drivers/staging/bcm/LeakyBucket.c index ee1d9f6ca0d2..52e6e0583157 100644 --- a/drivers/staging/bcm/LeakyBucket.c +++ b/drivers/staging/bcm/LeakyBucket.c @@ -23,34 +23,29 @@ static VOID UpdateTokenCount(register struct bcm_mini_adapter *Adapter) BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "=====>\n"); - if (NULL == Adapter) - { + if (NULL == Adapter) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "Adapter found NULL!\n"); return; } do_gettimeofday(&tv); - for (i = 0; i < NO_OF_QUEUES; i++) - { + for (i = 0; i < NO_OF_QUEUES; i++) { if (TRUE == Adapter->PackInfo[i].bValid && - (1 == Adapter->PackInfo[i].ucDirection)) - { + (1 == Adapter->PackInfo[i].ucDirection)) { liCurrentTime = ((tv.tv_sec- Adapter->PackInfo[i].stLastUpdateTokenAt.tv_sec)*1000 + (tv.tv_usec-Adapter->PackInfo[i].stLastUpdateTokenAt.tv_usec)/ 1000); - if (0 != liCurrentTime) - { + if (0 != liCurrentTime) { Adapter->PackInfo[i].uiCurrentTokenCount += (ULONG) ((Adapter->PackInfo[i].uiMaxAllowedRate) * ((ULONG)((liCurrentTime)))/1000); memcpy(&Adapter->PackInfo[i].stLastUpdateTokenAt, &tv, sizeof(struct timeval)); Adapter->PackInfo[i].liLastUpdateTokenAt = liCurrentTime; - if ((Adapter->PackInfo[i].uiCurrentTokenCount) >= - Adapter->PackInfo[i].uiMaxBucketSize) - { + if (Adapter->PackInfo[i].uiCurrentTokenCount >= + Adapter->PackInfo[i].uiMaxBucketSize) { Adapter->PackInfo[i].uiCurrentTokenCount = Adapter->PackInfo[i].uiMaxBucketSize; } @@ -82,27 +77,20 @@ static ULONG GetSFTokenCount(struct bcm_mini_adapter *Adapter, struct bcm_packet BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IsPacketAllowedForFlow ===>"); /* Validate the parameters */ if (NULL == Adapter || (psSF < Adapter->PackInfo && - (uintptr_t)psSF > (uintptr_t) &Adapter->PackInfo[HiPriority])) - { + (uintptr_t)psSF > (uintptr_t) &Adapter->PackInfo[HiPriority])) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IPAFF: Got wrong Parameters:Adapter: %p, QIndex: %zd\n", Adapter, (psSF-Adapter->PackInfo)); return 0; } - if (FALSE != psSF->bValid && psSF->ucDirection) - { - if (0 != psSF->uiCurrentTokenCount) - { + if (FALSE != psSF->bValid && psSF->ucDirection) { + if (0 != psSF->uiCurrentTokenCount) { return psSF->uiCurrentTokenCount; - } - else - { + } else { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "Not enough tokens in queue %zd Available %u\n", psSF-Adapter->PackInfo, psSF->uiCurrentTokenCount); psSF->uiPendedLast = 1; } - } - else - { + } else { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IPAFF: Queue %zd not valid\n", psSF-Adapter->PackInfo); } BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IsPacketAllowedForFlow <==="); @@ -122,23 +110,19 @@ static INT SendPacketFromQueue(struct bcm_mini_adapter *Adapter,/**"); - if (!Adapter || !Packet || !psSF) - { + if (!Adapter || !Packet || !psSF) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, "Got NULL Adapter or Packet"); return -EINVAL; } if (psSF->liDrainCalculated == 0) - { psSF->liDrainCalculated = jiffies; - } ///send the packet to the fifo.. PktLen = Packet->len; Status = SetupNextSend(Adapter, Packet, psSF->usVCID_Value); - if (Status == 0) - { - for (uiIndex = 0; uiIndex < MIBS_MAX_HIST_ENTRIES; uiIndex++) - { if ((PktLen <= MIBS_PKTSIZEHIST_RANGE*(uiIndex+1)) && (PktLen > MIBS_PKTSIZEHIST_RANGE*(uiIndex))) + if (Status == 0) { + for (uiIndex = 0; uiIndex < MIBS_MAX_HIST_ENTRIES; uiIndex++) { + if ((PktLen <= MIBS_PKTSIZEHIST_RANGE*(uiIndex+1)) && (PktLen > MIBS_PKTSIZEHIST_RANGE*(uiIndex))) Adapter->aTxPktSizeHist[uiIndex]++; } } @@ -167,8 +151,7 @@ static VOID CheckAndSendPacketFromIndex(struct bcm_mini_adapter *Adapter, struct BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "%zd ====>", (psSF-Adapter->PackInfo)); - if ((psSF != &Adapter->PackInfo[HiPriority]) && Adapter->LinkUpStatus && atomic_read(&psSF->uiPerSFTxResourceCount))//Get data packet - { + if ((psSF != &Adapter->PackInfo[HiPriority]) && Adapter->LinkUpStatus && atomic_read(&psSF->uiPerSFTxResourceCount)) { //Get data packet if (!psSF->ucDirection) return; @@ -177,8 +160,7 @@ static VOID CheckAndSendPacketFromIndex(struct bcm_mini_adapter *Adapter, struct return; /* in idle mode */ // Check for Free Descriptors - if (atomic_read(&Adapter->CurrNumFreeTxDesc) <= MINIMUM_PENDING_DESCRIPTORS) - { + if (atomic_read(&Adapter->CurrNumFreeTxDesc) <= MINIMUM_PENDING_DESCRIPTORS) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, " No Free Tx Descriptor(%d) is available for Data pkt..", atomic_read(&Adapter->CurrNumFreeTxDesc)); return; } @@ -186,8 +168,7 @@ static VOID CheckAndSendPacketFromIndex(struct bcm_mini_adapter *Adapter, struct spin_lock_bh(&psSF->SFQueueLock); QueuePacket = psSF->FirstTxQueue; - if (QueuePacket) - { + if (QueuePacket) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Dequeuing Data Packet"); if (psSF->bEthCSSupport) @@ -196,8 +177,7 @@ static VOID CheckAndSendPacketFromIndex(struct bcm_mini_adapter *Adapter, struct iPacketLen = QueuePacket->len-ETH_HLEN; iPacketLen <<= 3; - if (iPacketLen <= GetSFTokenCount(Adapter, psSF)) - { + if (iPacketLen <= GetSFTokenCount(Adapter, psSF)) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Allowed bytes %d", (iPacketLen >> 3)); @@ -209,9 +189,7 @@ static VOID CheckAndSendPacketFromIndex(struct bcm_mini_adapter *Adapter, struct Status = SendPacketFromQueue(Adapter, psSF, QueuePacket); psSF->uiPendedLast = FALSE; - } - else - { + } else { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "For Queue: %zd\n", psSF-Adapter->PackInfo); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nAvailable Tokens = %d required = %d\n", psSF->uiCurrentTokenCount, iPacketLen); @@ -221,28 +199,20 @@ static VOID CheckAndSendPacketFromIndex(struct bcm_mini_adapter *Adapter, struct psSF->uiPendedLast = TRUE; spin_unlock_bh(&psSF->SFQueueLock); } - } - else - { + } else { spin_unlock_bh(&psSF->SFQueueLock); } - } - else - { + } else { if ((atomic_read(&Adapter->CurrNumFreeTxDesc) > 0) && - (atomic_read(&Adapter->index_rd_txcntrlpkt) != - atomic_read(&Adapter->index_wr_txcntrlpkt)) - ) - { + (atomic_read(&Adapter->index_rd_txcntrlpkt) != + atomic_read(&Adapter->index_wr_txcntrlpkt))) { pControlPacket = Adapter->txctlpacket [(atomic_read(&Adapter->index_rd_txcntrlpkt)%MAX_CNTRL_PKTS)]; - if (pControlPacket) - { + if (pControlPacket) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Sending Control packet"); Status = SendControlPacket(Adapter, pControlPacket); - if (STATUS_SUCCESS == Status) - { + if (STATUS_SUCCESS == Status) { spin_lock_bh(&psSF->SFQueueLock); psSF->NumOfPacketsSent++; psSF->uiSentBytes += ((struct bcm_leader *)pControlPacket)->PLength; @@ -252,12 +222,10 @@ static VOID CheckAndSendPacketFromIndex(struct bcm_mini_adapter *Adapter, struct psSF->uiCurrentPacketsOnHost--; atomic_inc(&Adapter->index_rd_txcntrlpkt); spin_unlock_bh(&psSF->SFQueueLock); - } - else + } else { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "SendControlPacket Failed\n"); - } - else - { + } + } else { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, " Control Pkt is not available, Indexing is wrong...."); } } @@ -284,13 +252,11 @@ VOID transmit_packets(struct bcm_mini_adapter *Adapter) BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "=====>"); - if (NULL == Adapter) - { + if (NULL == Adapter) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Got NULL Adapter"); return; } - if (Adapter->device_removed == TRUE) - { + if (Adapter->device_removed == TRUE) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Device removed"); return; } @@ -305,34 +271,29 @@ VOID transmit_packets(struct bcm_mini_adapter *Adapter) uiPrevTotalCount = atomic_read(&Adapter->TotalPacketCount); - for (iIndex = HiPriority; iIndex >= 0; iIndex--) - { + for (iIndex = HiPriority; iIndex >= 0; iIndex--) { if (!uiPrevTotalCount || (TRUE == Adapter->device_removed)) break; if (Adapter->PackInfo[iIndex].bValid && - Adapter->PackInfo[iIndex].uiPendedLast && - Adapter->PackInfo[iIndex].uiCurrentBytesOnHost) - { + Adapter->PackInfo[iIndex].uiPendedLast && + Adapter->PackInfo[iIndex].uiCurrentBytesOnHost) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling CheckAndSendPacketFromIndex.."); CheckAndSendPacketFromIndex(Adapter, &Adapter->PackInfo[iIndex]); uiPrevTotalCount--; } } - while (uiPrevTotalCount > 0 && !Adapter->device_removed) - { + while (uiPrevTotalCount > 0 && !Adapter->device_removed) { exit_flag = TRUE; //second iteration to parse non-pending queues - for (iIndex = HiPriority; iIndex >= 0; iIndex--) - { + for (iIndex = HiPriority; iIndex >= 0; iIndex--) { if (!uiPrevTotalCount || (TRUE == Adapter->device_removed)) break; if (Adapter->PackInfo[iIndex].bValid && - Adapter->PackInfo[iIndex].uiCurrentBytesOnHost && - !Adapter->PackInfo[iIndex].uiPendedLast) - { + Adapter->PackInfo[iIndex].uiCurrentBytesOnHost && + !Adapter->PackInfo[iIndex].uiPendedLast) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling CheckAndSendPacketFromIndex.."); CheckAndSendPacketFromIndex(Adapter, &Adapter->PackInfo[iIndex]); uiPrevTotalCount--; @@ -340,8 +301,7 @@ VOID transmit_packets(struct bcm_mini_adapter *Adapter) } } - if (Adapter->IdleMode || Adapter->bPreparingForLowPowerMode) - { + if (Adapter->IdleMode || Adapter->bPreparingForLowPowerMode) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "In Idle Mode\n"); break; } From ea20a1ec00c3c7a7e03cf7c4a7426262d6d7a102 Mon Sep 17 00:00:00 2001 From: Lilis Iskandar Date: Sun, 28 Jul 2013 03:34:45 +0800 Subject: [PATCH 1033/3400] Staging: bcm: LeakyBucket: Fixed C99 comments Fixed C99 comments Signed-off-by: Lilis Iskandar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/LeakyBucket.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/staging/bcm/LeakyBucket.c b/drivers/staging/bcm/LeakyBucket.c index 52e6e0583157..75d77c2e83d4 100644 --- a/drivers/staging/bcm/LeakyBucket.c +++ b/drivers/staging/bcm/LeakyBucket.c @@ -117,7 +117,7 @@ static INT SendPacketFromQueue(struct bcm_mini_adapter *Adapter,/**liDrainCalculated == 0) psSF->liDrainCalculated = jiffies; - ///send the packet to the fifo.. + /* send the packet to the fifo.. */ PktLen = Packet->len; Status = SetupNextSend(Adapter, Packet, psSF->usVCID_Value); if (Status == 0) { @@ -151,7 +151,7 @@ static VOID CheckAndSendPacketFromIndex(struct bcm_mini_adapter *Adapter, struct BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "%zd ====>", (psSF-Adapter->PackInfo)); - if ((psSF != &Adapter->PackInfo[HiPriority]) && Adapter->LinkUpStatus && atomic_read(&psSF->uiPerSFTxResourceCount)) { //Get data packet + if ((psSF != &Adapter->PackInfo[HiPriority]) && Adapter->LinkUpStatus && atomic_read(&psSF->uiPerSFTxResourceCount)) { /* Get data packet */ if (!psSF->ucDirection) return; @@ -159,7 +159,7 @@ static VOID CheckAndSendPacketFromIndex(struct bcm_mini_adapter *Adapter, struct if (Adapter->IdleMode || Adapter->bPreparingForLowPowerMode) return; /* in idle mode */ - // Check for Free Descriptors + /* Check for Free Descriptors */ if (atomic_read(&Adapter->CurrNumFreeTxDesc) <= MINIMUM_PENDING_DESCRIPTORS) { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, " No Free Tx Descriptor(%d) is available for Data pkt..", atomic_read(&Adapter->CurrNumFreeTxDesc)); return; @@ -193,9 +193,11 @@ static VOID CheckAndSendPacketFromIndex(struct bcm_mini_adapter *Adapter, struct BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "For Queue: %zd\n", psSF-Adapter->PackInfo); BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nAvailable Tokens = %d required = %d\n", psSF->uiCurrentTokenCount, iPacketLen); - //this part indicates that because of non-availability of the tokens - //pkt has not been send out hence setting the pending flag indicating the host to send it out - //first next iteration . + /* + this part indicates that because of non-availability of the tokens + pkt has not been send out hence setting the pending flag indicating the host to send it out + first next iteration. + */ psSF->uiPendedLast = TRUE; spin_unlock_bh(&psSF->SFQueueLock); } @@ -286,7 +288,7 @@ VOID transmit_packets(struct bcm_mini_adapter *Adapter) while (uiPrevTotalCount > 0 && !Adapter->device_removed) { exit_flag = TRUE; - //second iteration to parse non-pending queues + /* second iteration to parse non-pending queues */ for (iIndex = HiPriority; iIndex >= 0; iIndex--) { if (!uiPrevTotalCount || (TRUE == Adapter->device_removed)) break; From 0a6765361c59a3d05818a1e658e917703538fa06 Mon Sep 17 00:00:00 2001 From: Lilis Iskandar Date: Sun, 28 Jul 2013 03:34:46 +0800 Subject: [PATCH 1034/3400] Staging: bcm: LeakyBucket: Fixed code indent issues Fixed code indent issues Signed-off-by: Lilis Iskandar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/LeakyBucket.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/bcm/LeakyBucket.c b/drivers/staging/bcm/LeakyBucket.c index 75d77c2e83d4..fb18ae054ed1 100644 --- a/drivers/staging/bcm/LeakyBucket.c +++ b/drivers/staging/bcm/LeakyBucket.c @@ -187,7 +187,7 @@ static VOID CheckAndSendPacketFromIndex(struct bcm_mini_adapter *Adapter, struct atomic_dec(&Adapter->TotalPacketCount); spin_unlock_bh(&psSF->SFQueueLock); - Status = SendPacketFromQueue(Adapter, psSF, QueuePacket); + Status = SendPacketFromQueue(Adapter, psSF, QueuePacket); psSF->uiPendedLast = FALSE; } else { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "For Queue: %zd\n", psSF-Adapter->PackInfo); @@ -230,7 +230,7 @@ static VOID CheckAndSendPacketFromIndex(struct bcm_mini_adapter *Adapter, struct } else { BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, " Control Pkt is not available, Indexing is wrong...."); } - } + } } } @@ -308,7 +308,7 @@ VOID transmit_packets(struct bcm_mini_adapter *Adapter) break; } if (exit_flag == TRUE) - break; + break; } /* end of inner while loop */ update_per_cid_rx(Adapter); From fd18e9febe24d14164f27fca1a6beb9527c77364 Mon Sep 17 00:00:00 2001 From: Lilis Iskandar Date: Sun, 28 Jul 2013 03:34:47 +0800 Subject: [PATCH 1035/3400] Staging: bcm: LeakyBucket: Fixed a pointer asterisk placement issue Fixed a pointer asterisk placement issue Signed-off-by: Lilis Iskandar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/bcm/LeakyBucket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/bcm/LeakyBucket.c b/drivers/staging/bcm/LeakyBucket.c index fb18ae054ed1..bc486163332d 100644 --- a/drivers/staging/bcm/LeakyBucket.c +++ b/drivers/staging/bcm/LeakyBucket.c @@ -104,7 +104,7 @@ This function despatches packet from the specified queue. */ static INT SendPacketFromQueue(struct bcm_mini_adapter *Adapter,/** Date: Mon, 29 Jul 2013 20:07:41 +0300 Subject: [PATCH 1036/3400] staging: octeon-usb: depend on CAVIUM_OCTEON_SOC The USB driver should depend on SOC instead of CPU. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/octeon-usb/Kconfig b/drivers/staging/octeon-usb/Kconfig index 018af6db08c8..16ea17ff3fd2 100644 --- a/drivers/staging/octeon-usb/Kconfig +++ b/drivers/staging/octeon-usb/Kconfig @@ -1,6 +1,6 @@ config OCTEON_USB tristate "Cavium Networks Octeon USB support" - depends on CPU_CAVIUM_OCTEON && USB + depends on CAVIUM_OCTEON_SOC && USB help This driver supports USB host controller on some Cavium Networks' products in the Octeon family. From f6ba63fce2ccf3f48d0d643bd93d32509c90cade Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Mon, 29 Jul 2013 20:07:42 +0300 Subject: [PATCH 1037/3400] staging: octeon-usb: use correct board type for EdgeRouter Lite Use CVMX_BOARD_TYPE_UBNT_E100 for EdgeRouter Lite. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.c b/drivers/staging/octeon-usb/cvmx-usb.c index bf366495fdd1..6c7bcf33ee34 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.c +++ b/drivers/staging/octeon-usb/cvmx-usb.c @@ -280,14 +280,9 @@ static int octeon_usb_get_clock_type(void) case CVMX_BOARD_TYPE_LANAI2_A: case CVMX_BOARD_TYPE_LANAI2_U: case CVMX_BOARD_TYPE_LANAI2_G: + case CVMX_BOARD_TYPE_UBNT_E100: return USB_CLOCK_TYPE_CRYSTAL_12; } - - /* FIXME: This should use CVMX_BOARD_TYPE_UBNT_E100 */ - if (OCTEON_IS_MODEL(OCTEON_CN50XX) && - cvmx_sysinfo_get()->board_type == 20002) - return USB_CLOCK_TYPE_CRYSTAL_12; - return USB_CLOCK_TYPE_REF_48; } From 1b50850d01f8996d0247ddc461eab372499d47c6 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Mon, 29 Jul 2013 20:07:43 +0300 Subject: [PATCH 1038/3400] staging: octeon-usb: cvmx-usb: delete driver-specific tracing code Delete call, parameter, and return value tracing. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.c | 325 +++++++------------------- 1 file changed, 87 insertions(+), 238 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.c b/drivers/staging/octeon-usb/cvmx-usb.c index 6c7bcf33ee34..6a1e14a37e3e 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.c +++ b/drivers/staging/octeon-usb/cvmx-usb.c @@ -211,33 +211,6 @@ typedef struct { cvmx_usb_tx_fifo_t nonperiodic; } cvmx_usb_internal_state_t; -/* This macro logs out whenever a function is called if debugging is on */ -#define CVMX_USB_LOG_CALLED() \ - if (cvmx_unlikely(usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_DEBUG_CALLS)) \ - cvmx_dprintf("%*s%s: called\n", 2*usb->indent++, "", __FUNCTION__); - -/* This macro logs out each function parameter if debugging is on */ -#define CVMX_USB_LOG_PARAM(format, param) \ - if (cvmx_unlikely(usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_DEBUG_CALLS)) \ - cvmx_dprintf("%*s%s: param %s = " format "\n", 2*usb->indent, "", __FUNCTION__, #param, param); - -/* This macro logs out when a function returns a value */ -#define CVMX_USB_RETURN(v) \ - do { \ - typeof(v) r = v; \ - if (cvmx_unlikely(usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_DEBUG_CALLS)) \ - cvmx_dprintf("%*s%s: returned %s(%d)\n", 2*--usb->indent, "", __FUNCTION__, #v, r); \ - return r; \ - } while (0); - -/* This macro logs out when a function doesn't return a value */ -#define CVMX_USB_RETURN_NOTHING() \ - do { \ - if (cvmx_unlikely(usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_DEBUG_CALLS)) \ - cvmx_dprintf("%*s%s: returned\n", 2*--usb->indent, "", __FUNCTION__); \ - return; \ - } while (0); - /* This macro spins on a field waiting for it to reach a value */ #define CVMX_WAIT_FOR_FIELD32(address, type, field, op, value, timeout_usec)\ ({int result; \ @@ -574,20 +547,16 @@ cvmx_usb_status_t cvmx_usb_initialize(cvmx_usb_state_t *state, cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; usb->init_flags = flags; - CVMX_USB_LOG_CALLED(); - CVMX_USB_LOG_PARAM("%p", state); - CVMX_USB_LOG_PARAM("%d", usb_port_number); - CVMX_USB_LOG_PARAM("0x%x", flags); /* Make sure that state is large enough to store the internal state */ if (sizeof(*state) < sizeof(*usb)) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; /* At first allow 0-1 for the usb port number */ if ((usb_port_number < 0) || (usb_port_number > 1)) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; /* For all chips except 52XX there is only one port */ if (!OCTEON_IS_MODEL(OCTEON_CN52XX) && (usb_port_number > 0)) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; /* Try to determine clock type automatically */ if ((flags & (CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI | CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND)) == 0) { @@ -611,7 +580,7 @@ cvmx_usb_status_t cvmx_usb_initialize(cvmx_usb_state_t *state, flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ; break; default: - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; break; } } @@ -847,7 +816,7 @@ cvmx_usb_status_t cvmx_usb_initialize(cvmx_usb_state_t *state, /* Steps 4-15 from the manual are done later in the port enable */ } - CVMX_USB_RETURN(CVMX_USB_SUCCESS); + return CVMX_USB_SUCCESS; } @@ -867,16 +836,13 @@ cvmx_usb_status_t cvmx_usb_shutdown(cvmx_usb_state_t *state) cvmx_usbnx_clk_ctl_t usbn_clk_ctl; cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; - CVMX_USB_LOG_CALLED(); - CVMX_USB_LOG_PARAM("%p", state); - /* Make sure all pipes are closed */ if (usb->idle_pipes.head || usb->active_pipes[CVMX_USB_TRANSFER_ISOCHRONOUS].head || usb->active_pipes[CVMX_USB_TRANSFER_INTERRUPT].head || usb->active_pipes[CVMX_USB_TRANSFER_CONTROL].head || usb->active_pipes[CVMX_USB_TRANSFER_BULK].head) - CVMX_USB_RETURN(CVMX_USB_BUSY); + return CVMX_USB_BUSY; /* Disable the clocks and put them in power on reset */ usbn_clk_ctl.u64 = __cvmx_usb_read_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index)); @@ -887,7 +853,7 @@ cvmx_usb_status_t cvmx_usb_shutdown(cvmx_usb_state_t *state) usbn_clk_ctl.s.hrst = 0; __cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index), usbn_clk_ctl.u64); - CVMX_USB_RETURN(CVMX_USB_SUCCESS); + return CVMX_USB_SUCCESS; } @@ -906,21 +872,18 @@ cvmx_usb_status_t cvmx_usb_enable(cvmx_usb_state_t *state) cvmx_usbcx_ghwcfg3_t usbcx_ghwcfg3; cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; - CVMX_USB_LOG_CALLED(); - CVMX_USB_LOG_PARAM("%p", state); - usb->usbcx_hprt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPRT(usb->index)); /* If the port is already enabled the just return. We don't need to do anything */ if (usb->usbcx_hprt.s.prtena) - CVMX_USB_RETURN(CVMX_USB_SUCCESS); + return CVMX_USB_SUCCESS; /* If there is nothing plugged into the port then fail immediately */ if (!usb->usbcx_hprt.s.prtconnsts) { if (cvmx_unlikely(usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_DEBUG_INFO)) cvmx_dprintf("%s: USB%d Nothing plugged into the port\n", __FUNCTION__, usb->index); - CVMX_USB_RETURN(CVMX_USB_TIMEOUT); + return CVMX_USB_TIMEOUT; } /* Program the port reset bit to start the reset process */ @@ -939,7 +902,7 @@ cvmx_usb_status_t cvmx_usb_enable(cvmx_usb_state_t *state) if (cvmx_unlikely(usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_DEBUG_INFO)) cvmx_dprintf("%s: Timeout waiting for the port to finish reset\n", __FUNCTION__); - CVMX_USB_RETURN(CVMX_USB_TIMEOUT); + return CVMX_USB_TIMEOUT; } /* Read the port speed field to get the enumerated speed, USBC_HPRT[PRTSPD]. */ @@ -984,7 +947,7 @@ cvmx_usb_status_t cvmx_usb_enable(cvmx_usb_state_t *state) CVMX_WAIT_FOR_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), cvmx_usbcx_grstctl_t, rxfflsh, ==, 0, 100); - CVMX_USB_RETURN(CVMX_USB_SUCCESS); + return CVMX_USB_SUCCESS; } @@ -1004,12 +967,9 @@ cvmx_usb_status_t cvmx_usb_disable(cvmx_usb_state_t *state) { cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; - CVMX_USB_LOG_CALLED(); - CVMX_USB_LOG_PARAM("%p", state); - /* Disable the port */ USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt_t, prtena, 1); - CVMX_USB_RETURN(CVMX_USB_SUCCESS); + return CVMX_USB_SUCCESS; } @@ -1035,9 +995,6 @@ cvmx_usb_port_status_t cvmx_usb_get_status(cvmx_usb_state_t *state) memset(&result, 0, sizeof(result)); - CVMX_USB_LOG_CALLED(); - CVMX_USB_LOG_PARAM("%p", state); - usbc_hprt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPRT(usb->index)); result.port_enabled = usbc_hprt.s.prtena; result.port_over_current = usbc_hprt.s.prtovrcurract; @@ -1074,10 +1031,8 @@ cvmx_usb_port_status_t cvmx_usb_get_status(cvmx_usb_state_t *state) void cvmx_usb_set_status(cvmx_usb_state_t *state, cvmx_usb_port_status_t port_status) { cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; - CVMX_USB_LOG_CALLED(); - CVMX_USB_LOG_PARAM("%p", state); usb->port_status = port_status; - CVMX_USB_RETURN_NOTHING(); + return; } @@ -1183,51 +1138,37 @@ int cvmx_usb_open_pipe(cvmx_usb_state_t *state, cvmx_usb_pipe_flags_t flags, cvmx_usb_pipe_t *pipe; cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; - CVMX_USB_LOG_CALLED(); - CVMX_USB_LOG_PARAM("%p", state); - CVMX_USB_LOG_PARAM("0x%x", flags); - CVMX_USB_LOG_PARAM("%d", device_addr); - CVMX_USB_LOG_PARAM("%d", endpoint_num); - CVMX_USB_LOG_PARAM("%d", device_speed); - CVMX_USB_LOG_PARAM("%d", max_packet); - CVMX_USB_LOG_PARAM("%d", transfer_type); - CVMX_USB_LOG_PARAM("%d", transfer_dir); - CVMX_USB_LOG_PARAM("%d", interval); - CVMX_USB_LOG_PARAM("%d", multi_count); - CVMX_USB_LOG_PARAM("%d", hub_device_addr); - CVMX_USB_LOG_PARAM("%d", hub_port); - if (cvmx_unlikely((device_addr < 0) || (device_addr > MAX_USB_ADDRESS))) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; if (cvmx_unlikely((endpoint_num < 0) || (endpoint_num > MAX_USB_ENDPOINT))) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; if (cvmx_unlikely(device_speed > CVMX_USB_SPEED_LOW)) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; if (cvmx_unlikely((max_packet <= 0) || (max_packet > 1024))) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; if (cvmx_unlikely(transfer_type > CVMX_USB_TRANSFER_INTERRUPT)) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; if (cvmx_unlikely((transfer_dir != CVMX_USB_DIRECTION_OUT) && (transfer_dir != CVMX_USB_DIRECTION_IN))) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; if (cvmx_unlikely(interval < 0)) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; if (cvmx_unlikely((transfer_type == CVMX_USB_TRANSFER_CONTROL) && interval)) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; if (cvmx_unlikely(multi_count < 0)) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; if (cvmx_unlikely((device_speed != CVMX_USB_SPEED_HIGH) && (multi_count != 0))) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; if (cvmx_unlikely((hub_device_addr < 0) || (hub_device_addr > MAX_USB_ADDRESS))) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; if (cvmx_unlikely((hub_port < 0) || (hub_port > MAX_USB_HUB_PORT))) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; /* Find a free pipe */ pipe = usb->free_pipes.head; if (!pipe) - CVMX_USB_RETURN(CVMX_USB_NO_MEMORY); + return CVMX_USB_NO_MEMORY; __cvmx_usb_remove_pipe(&usb->free_pipes, pipe); pipe->flags = flags | __CVMX_USB_PIPE_FLAGS_OPEN; if ((device_speed == CVMX_USB_SPEED_HIGH) && @@ -1263,7 +1204,7 @@ int cvmx_usb_open_pipe(cvmx_usb_state_t *state, cvmx_usb_pipe_flags_t flags, /* We don't need to tell the hardware about this pipe yet since it doesn't have any submitted requests */ - CVMX_USB_RETURN(__cvmx_usb_get_pipe_handle(usb, pipe)); + return __cvmx_usb_get_pipe_handle(usb, pipe); } @@ -1284,21 +1225,18 @@ static void __cvmx_usb_poll_rx_fifo(cvmx_usb_internal_state_t *usb) uint64_t address; uint32_t *ptr; - CVMX_USB_LOG_CALLED(); - CVMX_USB_LOG_PARAM("%p", usb); - rx_status.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GRXSTSPH(usb->index)); /* Only read data if IN data is there */ if (rx_status.s.pktsts != 2) - CVMX_USB_RETURN_NOTHING(); + return; /* Check if no data is available */ if (!rx_status.s.bcnt) - CVMX_USB_RETURN_NOTHING(); + return; channel = rx_status.s.chnum; bytes = rx_status.s.bcnt; if (!bytes) - CVMX_USB_RETURN_NOTHING(); + return; /* Get where the DMA engine would have written this data */ address = __cvmx_usb_read_csr64(usb, CVMX_USBNX_DMA0_INB_CHN0(usb->index) + channel*8); @@ -1312,7 +1250,7 @@ static void __cvmx_usb_poll_rx_fifo(cvmx_usb_internal_state_t *usb) } CVMX_SYNCW; - CVMX_USB_RETURN_NOTHING(); + return; } @@ -1330,11 +1268,6 @@ static void __cvmx_usb_poll_rx_fifo(cvmx_usb_internal_state_t *usb) */ static int __cvmx_usb_fill_tx_hw(cvmx_usb_internal_state_t *usb, cvmx_usb_tx_fifo_t *fifo, int available) { - CVMX_USB_LOG_CALLED(); - CVMX_USB_LOG_PARAM("%p", usb); - CVMX_USB_LOG_PARAM("%p", fifo); - CVMX_USB_LOG_PARAM("%d", available); - /* We're done either when there isn't anymore space or the software FIFO is empty */ while (available && (fifo->head != fifo->tail)) { @@ -1373,7 +1306,7 @@ static int __cvmx_usb_fill_tx_hw(cvmx_usb_internal_state_t *usb, cvmx_usb_tx_fif } cvmx_read64_uint64(CVMX_USBNX_DMA0_INB_CHN0(usb->index)); } - CVMX_USB_RETURN(fifo->head != fifo->tail); + return fifo->head != fifo->tail; } @@ -1385,9 +1318,6 @@ static int __cvmx_usb_fill_tx_hw(cvmx_usb_internal_state_t *usb, cvmx_usb_tx_fif */ static void __cvmx_usb_poll_tx_fifo(cvmx_usb_internal_state_t *usb) { - CVMX_USB_LOG_CALLED(); - CVMX_USB_LOG_PARAM("%p", usb); - if (usb->periodic.head != usb->periodic.tail) { cvmx_usbcx_hptxsts_t tx_status; tx_status.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPTXSTS(usb->index)); @@ -1406,7 +1336,7 @@ static void __cvmx_usb_poll_tx_fifo(cvmx_usb_internal_state_t *usb) USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), cvmx_usbcx_gintmsk_t, nptxfempmsk, 0); } - CVMX_USB_RETURN_NOTHING(); + return; } @@ -1425,24 +1355,20 @@ static void __cvmx_usb_fill_tx_fifo(cvmx_usb_internal_state_t *usb, int channel) cvmx_usbcx_hctsizx_t usbc_hctsiz; cvmx_usb_tx_fifo_t *fifo; - CVMX_USB_LOG_CALLED(); - CVMX_USB_LOG_PARAM("%p", usb); - CVMX_USB_LOG_PARAM("%d", channel); - /* We only need to fill data on outbound channels */ hcchar.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index)); if (hcchar.s.epdir != CVMX_USB_DIRECTION_OUT) - CVMX_USB_RETURN_NOTHING(); + return; /* OUT Splits only have data on the start and not the complete */ usbc_hcsplt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCSPLTX(channel, usb->index)); if (usbc_hcsplt.s.spltena && usbc_hcsplt.s.compsplt) - CVMX_USB_RETURN_NOTHING(); + return; /* Find out how many bytes we need to fill and convert it into 32bit words */ usbc_hctsiz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index)); if (!usbc_hctsiz.s.xfersize) - CVMX_USB_RETURN_NOTHING(); + return; if ((hcchar.s.eptype == CVMX_USB_TRANSFER_INTERRUPT) || (hcchar.s.eptype == CVMX_USB_TRANSFER_ISOCHRONOUS)) @@ -1459,7 +1385,7 @@ static void __cvmx_usb_fill_tx_fifo(cvmx_usb_internal_state_t *usb, int channel) __cvmx_usb_poll_tx_fifo(usb); - CVMX_USB_RETURN_NOTHING(); + return; } /** @@ -1483,11 +1409,6 @@ static void __cvmx_usb_start_channel_control(cvmx_usb_internal_state_t *usb, int packets_to_transfer; cvmx_usbcx_hctsizx_t usbc_hctsiz; - CVMX_USB_LOG_CALLED(); - CVMX_USB_LOG_PARAM("%p", usb); - CVMX_USB_LOG_PARAM("%d", channel); - CVMX_USB_LOG_PARAM("%p", pipe); - usbc_hctsiz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index)); switch (transaction->stage) { @@ -1586,7 +1507,7 @@ static void __cvmx_usb_start_channel_control(cvmx_usb_internal_state_t *usb, usbc_hctsiz.s.pktcnt = packets_to_transfer; __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index), usbc_hctsiz.u32); - CVMX_USB_RETURN_NOTHING(); + return; } @@ -1605,11 +1526,6 @@ static void __cvmx_usb_start_channel(cvmx_usb_internal_state_t *usb, { cvmx_usb_transaction_t *transaction = pipe->head; - CVMX_USB_LOG_CALLED(); - CVMX_USB_LOG_PARAM("%p", usb); - CVMX_USB_LOG_PARAM("%d", channel); - CVMX_USB_LOG_PARAM("%p", pipe); - if (cvmx_unlikely((usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_DEBUG_TRANSFERS) || (pipe->flags & CVMX_USB_PIPE_FLAGS_DEBUG_TRANSFERS))) cvmx_dprintf("%s: Channel %d started. Pipe %d transaction %d stage %d\n", @@ -1843,7 +1759,7 @@ static void __cvmx_usb_start_channel(cvmx_usb_internal_state_t *usb, USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), cvmx_usbcx_hccharx_t, chena, 1); if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) __cvmx_usb_fill_tx_fifo(usb, channel); - CVMX_USB_RETURN_NOTHING(); + return; } @@ -1892,9 +1808,6 @@ static void __cvmx_usb_schedule(cvmx_usb_internal_state_t *usb, int is_sof) int need_sof; cvmx_usb_transfer_t ttype; - CVMX_USB_LOG_CALLED(); - CVMX_USB_LOG_PARAM("%p", usb); - if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) { /* Without DMA we need to be careful to not schedule something at the end of a frame and cause an overrun */ cvmx_usbcx_hfnum_t hfnum = {.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HFNUM(usb->index))}; @@ -1931,9 +1844,6 @@ static void __cvmx_usb_schedule(cvmx_usb_internal_state_t *usb, int is_sof) if (!pipe) break; - CVMX_USB_LOG_PARAM("%d", channel); - CVMX_USB_LOG_PARAM("%p", pipe); - if (cvmx_unlikely((usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_DEBUG_TRANSFERS) || (pipe->flags & CVMX_USB_PIPE_FLAGS_DEBUG_TRANSFERS))) { cvmx_usb_transaction_t *transaction = pipe->head; @@ -1980,7 +1890,7 @@ done: } } USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), cvmx_usbcx_gintmsk_t, sofmsk, need_sof); - CVMX_USB_RETURN_NOTHING(); + return; } @@ -2059,12 +1969,6 @@ static void __cvmx_usb_perform_complete(cvmx_usb_internal_state_t * usb, cvmx_usb_transaction_t *transaction, cvmx_usb_complete_t complete_code) { - CVMX_USB_LOG_CALLED(); - CVMX_USB_LOG_PARAM("%p", usb); - CVMX_USB_LOG_PARAM("%p", pipe); - CVMX_USB_LOG_PARAM("%p", transaction); - CVMX_USB_LOG_PARAM("%d", complete_code); - /* If this was a split then clear our split in progress marker */ if (usb->active_split == transaction) usb->active_split = NULL; @@ -2106,7 +2010,7 @@ static void __cvmx_usb_perform_complete(cvmx_usb_internal_state_t * usb, complete_code); __cvmx_usb_free_transaction(usb, transaction); done: - CVMX_USB_RETURN_NOTHING(); + return; } @@ -2154,18 +2058,17 @@ static int __cvmx_usb_submit_transaction(cvmx_usb_internal_state_t *usb, cvmx_usb_transaction_t *transaction; cvmx_usb_pipe_t *pipe = usb->pipe + pipe_handle; - CVMX_USB_LOG_CALLED(); if (cvmx_unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES))) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; /* Fail if the pipe isn't open */ if (cvmx_unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0)) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; if (cvmx_unlikely(pipe->transfer_type != type)) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; transaction = __cvmx_usb_alloc_transaction(usb); if (cvmx_unlikely(!transaction)) - CVMX_USB_RETURN(CVMX_USB_NO_MEMORY); + return CVMX_USB_NO_MEMORY; transaction->type = type; transaction->flags |= flags; @@ -2204,7 +2107,7 @@ static int __cvmx_usb_submit_transaction(cvmx_usb_internal_state_t *usb, if (!transaction->prev) __cvmx_usb_schedule(usb, 0); - CVMX_USB_RETURN(submit_handle); + return submit_handle; } @@ -2247,17 +2150,11 @@ int cvmx_usb_submit_bulk(cvmx_usb_state_t *state, int pipe_handle, int submit_handle; cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; - CVMX_USB_LOG_CALLED(); - CVMX_USB_LOG_PARAM("%p", state); - CVMX_USB_LOG_PARAM("%d", pipe_handle); - CVMX_USB_LOG_PARAM("0x%llx", (unsigned long long)buffer); - CVMX_USB_LOG_PARAM("%d", buffer_length); - /* Pipe handle checking is done later in a common place */ if (cvmx_unlikely(!buffer)) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; if (cvmx_unlikely(buffer_length < 0)) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; submit_handle = __cvmx_usb_submit_transaction(usb, pipe_handle, CVMX_USB_TRANSFER_BULK, @@ -2270,7 +2167,7 @@ int cvmx_usb_submit_bulk(cvmx_usb_state_t *state, int pipe_handle, NULL, /* iso_packets */ callback, user_data); - CVMX_USB_RETURN(submit_handle); + return submit_handle; } @@ -2313,17 +2210,11 @@ int cvmx_usb_submit_interrupt(cvmx_usb_state_t *state, int pipe_handle, int submit_handle; cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; - CVMX_USB_LOG_CALLED(); - CVMX_USB_LOG_PARAM("%p", state); - CVMX_USB_LOG_PARAM("%d", pipe_handle); - CVMX_USB_LOG_PARAM("0x%llx", (unsigned long long)buffer); - CVMX_USB_LOG_PARAM("%d", buffer_length); - /* Pipe handle checking is done later in a common place */ if (cvmx_unlikely(!buffer)) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; if (cvmx_unlikely(buffer_length < 0)) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; submit_handle = __cvmx_usb_submit_transaction(usb, pipe_handle, CVMX_USB_TRANSFER_INTERRUPT, @@ -2336,7 +2227,7 @@ int cvmx_usb_submit_interrupt(cvmx_usb_state_t *state, int pipe_handle, NULL, /* iso_packets */ callback, user_data); - CVMX_USB_RETURN(submit_handle); + return submit_handle; } @@ -2385,21 +2276,14 @@ int cvmx_usb_submit_control(cvmx_usb_state_t *state, int pipe_handle, cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; cvmx_usb_control_header_t *header = cvmx_phys_to_ptr(control_header); - CVMX_USB_LOG_CALLED(); - CVMX_USB_LOG_PARAM("%p", state); - CVMX_USB_LOG_PARAM("%d", pipe_handle); - CVMX_USB_LOG_PARAM("0x%llx", (unsigned long long)control_header); - CVMX_USB_LOG_PARAM("0x%llx", (unsigned long long)buffer); - CVMX_USB_LOG_PARAM("%d", buffer_length); - /* Pipe handle checking is done later in a common place */ if (cvmx_unlikely(!control_header)) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; /* Some drivers send a buffer with a zero length. God only knows why */ if (cvmx_unlikely(buffer && (buffer_length < 0))) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; if (cvmx_unlikely(!buffer && (buffer_length != 0))) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; if ((header->s.request_type & 0x80) == 0) buffer_length = cvmx_le16_to_cpu(header->s.length); @@ -2414,7 +2298,7 @@ int cvmx_usb_submit_control(cvmx_usb_state_t *state, int pipe_handle, NULL, /* iso_packets */ callback, user_data); - CVMX_USB_RETURN(submit_handle); + return submit_handle; } @@ -2474,29 +2358,19 @@ int cvmx_usb_submit_isochronous(cvmx_usb_state_t *state, int pipe_handle, int submit_handle; cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; - CVMX_USB_LOG_CALLED(); - CVMX_USB_LOG_PARAM("%p", state); - CVMX_USB_LOG_PARAM("%d", pipe_handle); - CVMX_USB_LOG_PARAM("%d", start_frame); - CVMX_USB_LOG_PARAM("0x%x", flags); - CVMX_USB_LOG_PARAM("%d", number_packets); - CVMX_USB_LOG_PARAM("%p", packets); - CVMX_USB_LOG_PARAM("0x%llx", (unsigned long long)buffer); - CVMX_USB_LOG_PARAM("%d", buffer_length); - /* Pipe handle checking is done later in a common place */ if (cvmx_unlikely(start_frame < 0)) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; if (cvmx_unlikely(flags & ~(CVMX_USB_ISOCHRONOUS_FLAGS_ALLOW_SHORT | CVMX_USB_ISOCHRONOUS_FLAGS_ASAP))) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; if (cvmx_unlikely(number_packets < 1)) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; if (cvmx_unlikely(!packets)) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; if (cvmx_unlikely(!buffer)) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; if (cvmx_unlikely(buffer_length < 0)) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; submit_handle = __cvmx_usb_submit_transaction(usb, pipe_handle, CVMX_USB_TRANSFER_ISOCHRONOUS, @@ -2509,7 +2383,7 @@ int cvmx_usb_submit_isochronous(cvmx_usb_state_t *state, int pipe_handle, packets, callback, user_data); - CVMX_USB_RETURN(submit_handle); + return submit_handle; } @@ -2537,25 +2411,20 @@ cvmx_usb_status_t cvmx_usb_cancel(cvmx_usb_state_t *state, int pipe_handle, cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; cvmx_usb_pipe_t *pipe = usb->pipe + pipe_handle; - CVMX_USB_LOG_CALLED(); - CVMX_USB_LOG_PARAM("%p", state); - CVMX_USB_LOG_PARAM("%d", pipe_handle); - CVMX_USB_LOG_PARAM("%d", submit_handle); - if (cvmx_unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES))) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; if (cvmx_unlikely((submit_handle < 0) || (submit_handle >= MAX_TRANSACTIONS))) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; /* Fail if the pipe isn't open */ if (cvmx_unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0)) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; transaction = usb->transaction + submit_handle; /* Fail if this transaction already completed */ if (cvmx_unlikely((transaction->flags & __CVMX_USB_TRANSACTION_FLAGS_IN_USE) == 0)) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; /* If the transaction is the HEAD of the queue and scheduled. We need to treat it special */ @@ -2576,7 +2445,7 @@ cvmx_usb_status_t cvmx_usb_cancel(cvmx_usb_state_t *state, int pipe_handle, } } __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_CANCEL); - CVMX_USB_RETURN(CVMX_USB_SUCCESS); + return CVMX_USB_SUCCESS; } @@ -2597,24 +2466,21 @@ cvmx_usb_status_t cvmx_usb_cancel_all(cvmx_usb_state_t *state, int pipe_handle) cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; cvmx_usb_pipe_t *pipe = usb->pipe + pipe_handle; - CVMX_USB_LOG_CALLED(); - CVMX_USB_LOG_PARAM("%p", state); - CVMX_USB_LOG_PARAM("%d", pipe_handle); if (cvmx_unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES))) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; /* Fail if the pipe isn't open */ if (cvmx_unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0)) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; /* Simply loop through and attempt to cancel each transaction */ while (pipe->head) { cvmx_usb_status_t result = cvmx_usb_cancel(state, pipe_handle, __cvmx_usb_get_submit_handle(usb, pipe->head)); if (cvmx_unlikely(result != CVMX_USB_SUCCESS)) - CVMX_USB_RETURN(result); + return result; } - CVMX_USB_RETURN(CVMX_USB_SUCCESS); + return CVMX_USB_SUCCESS; } @@ -2635,25 +2501,22 @@ cvmx_usb_status_t cvmx_usb_close_pipe(cvmx_usb_state_t *state, int pipe_handle) cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; cvmx_usb_pipe_t *pipe = usb->pipe + pipe_handle; - CVMX_USB_LOG_CALLED(); - CVMX_USB_LOG_PARAM("%p", state); - CVMX_USB_LOG_PARAM("%d", pipe_handle); if (cvmx_unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES))) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; /* Fail if the pipe isn't open */ if (cvmx_unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0)) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; /* Fail if the pipe has pending transactions */ if (cvmx_unlikely(pipe->head)) - CVMX_USB_RETURN(CVMX_USB_BUSY); + return CVMX_USB_BUSY; pipe->flags = 0; __cvmx_usb_remove_pipe(&usb->idle_pipes, pipe); __cvmx_usb_append_pipe(&usb->free_pipes, pipe); - CVMX_USB_RETURN(CVMX_USB_SUCCESS); + return CVMX_USB_SUCCESS; } @@ -2676,20 +2539,15 @@ cvmx_usb_status_t cvmx_usb_register_callback(cvmx_usb_state_t *state, { cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; - CVMX_USB_LOG_CALLED(); - CVMX_USB_LOG_PARAM("%p", state); - CVMX_USB_LOG_PARAM("%d", reason); - CVMX_USB_LOG_PARAM("%p", callback); - CVMX_USB_LOG_PARAM("%p", user_data); if (cvmx_unlikely(reason >= __CVMX_USB_CALLBACK_END)) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; if (cvmx_unlikely(!callback)) - CVMX_USB_RETURN(CVMX_USB_INVALID_PARAM); + return CVMX_USB_INVALID_PARAM; usb->callback[reason] = callback; usb->callback_data[reason] = user_data; - CVMX_USB_RETURN(CVMX_USB_SUCCESS); + return CVMX_USB_SUCCESS; } @@ -2708,13 +2566,10 @@ int cvmx_usb_get_frame_number(cvmx_usb_state_t *state) cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; cvmx_usbcx_hfnum_t usbc_hfnum; - CVMX_USB_LOG_CALLED(); - CVMX_USB_LOG_PARAM("%p", state); - usbc_hfnum.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HFNUM(usb->index)); frame_number = usbc_hfnum.s.frnum; - CVMX_USB_RETURN(frame_number); + return frame_number; } @@ -2738,9 +2593,6 @@ static int __cvmx_usb_poll_channel(cvmx_usb_internal_state_t *usb, int channel) int bytes_in_last_packet; int packets_processed; int buffer_space_left; - CVMX_USB_LOG_CALLED(); - CVMX_USB_LOG_PARAM("%p", usb); - CVMX_USB_LOG_PARAM("%d", channel); /* Read the interrupt status bits for the channel */ usbc_hcint.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCINTX(channel, usb->index)); @@ -2753,7 +2605,7 @@ static int __cvmx_usb_poll_channel(cvmx_usb_internal_state_t *usb, int channel) IN transfers to get stuck until we do a write of HCCHARX without changing things */ __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index), usbc_hcchar.u32); - CVMX_USB_RETURN(0); + return 0; } /* In non DMA mode the channels don't halt themselves. We need to @@ -2767,14 +2619,14 @@ static int __cvmx_usb_poll_channel(cvmx_usb_internal_state_t *usb, int channel) __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCINTMSKX(channel, usb->index), hcintmsk.u32); usbc_hcchar.s.chdis = 1; __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index), usbc_hcchar.u32); - CVMX_USB_RETURN(0); + return 0; } else if (usbc_hcint.s.xfercompl) { /* Successful IN/OUT with transfer complete. Channel halt isn't needed */ } else { cvmx_dprintf("USB%d: Channel %d interrupt without halt\n", usb->index, channel); - CVMX_USB_RETURN(0); + return 0; } } } @@ -2782,7 +2634,7 @@ static int __cvmx_usb_poll_channel(cvmx_usb_internal_state_t *usb, int channel) /* There is are no interrupts that we need to process when the channel is still running */ if (!usbc_hcint.s.chhltd) - CVMX_USB_RETURN(0); + return 0; } /* Disable the channel interrupts now that it is done */ @@ -2794,7 +2646,7 @@ static int __cvmx_usb_poll_channel(cvmx_usb_internal_state_t *usb, int channel) CVMX_PREFETCH(pipe, 0); CVMX_PREFETCH(pipe, 128); if (!pipe) - CVMX_USB_RETURN(0); + return 0; transaction = pipe->head; CVMX_PREFETCH0(transaction); @@ -3118,7 +2970,7 @@ static int __cvmx_usb_poll_channel(cvmx_usb_internal_state_t *usb, int channel) __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_ERROR); } } - CVMX_USB_RETURN(0); + return 0; } @@ -3146,9 +2998,6 @@ cvmx_usb_status_t cvmx_usb_poll(cvmx_usb_state_t *state) CVMX_PREFETCH(usb, 3*128); CVMX_PREFETCH(usb, 4*128); - CVMX_USB_LOG_CALLED(); - CVMX_USB_LOG_PARAM("%p", state); - /* Update the frame counter */ usbc_hfnum.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HFNUM(usb->index)); if ((usb->frame_number&0x3fff) > usbc_hfnum.s.frnum) @@ -3220,5 +3069,5 @@ cvmx_usb_status_t cvmx_usb_poll(cvmx_usb_state_t *state) __cvmx_usb_schedule(usb, usbc_gintsts.s.sof); - CVMX_USB_RETURN(CVMX_USB_SUCCESS); + return CVMX_USB_SUCCESS; } From a7c679482d9f548e6ec3cfba35472ed6afb13274 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Mon, 29 Jul 2013 20:07:44 +0300 Subject: [PATCH 1039/3400] staging: octeon-usb: cvmx-usb: delete redundant debug flags Delete redudant debug flags and dead code behind them. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.c | 87 +-------------------------- drivers/staging/octeon-usb/cvmx-usb.h | 7 --- 2 files changed, 2 insertions(+), 92 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.c b/drivers/staging/octeon-usb/cvmx-usb.c index 6a1e14a37e3e..dd8653c9e5e3 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.c +++ b/drivers/staging/octeon-usb/cvmx-usb.c @@ -439,8 +439,6 @@ static inline cvmx_usb_transaction_t *__cvmx_usb_alloc_transaction(cvmx_usb_inte if (!usb->free_transaction_head) usb->free_transaction_tail = NULL; } - else if (cvmx_unlikely(usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_DEBUG_INFO)) - cvmx_dprintf("%s: Failed to allocate a transaction\n", __FUNCTION__); if (t) { memset(t, 0, sizeof(*t)); t->flags = __CVMX_USB_TRANSACTION_FLAGS_IN_USE; @@ -791,8 +789,6 @@ cvmx_usb_status_t cvmx_usb_initialize(cvmx_usb_state_t *state, { /* Host Port Initialization */ - if (cvmx_unlikely(usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_DEBUG_INFO)) - cvmx_dprintf("%s: USB%d is in host mode\n", __FUNCTION__, usb->index); /* 1. Program the host-port interrupt-mask field to unmask, USBC_GINTMSK[PRTINT] = 1 */ @@ -881,8 +877,6 @@ cvmx_usb_status_t cvmx_usb_enable(cvmx_usb_state_t *state) /* If there is nothing plugged into the port then fail immediately */ if (!usb->usbcx_hprt.s.prtconnsts) { - if (cvmx_unlikely(usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_DEBUG_INFO)) - cvmx_dprintf("%s: USB%d Nothing plugged into the port\n", __FUNCTION__, usb->index); return CVMX_USB_TIMEOUT; } @@ -898,21 +892,11 @@ cvmx_usb_status_t cvmx_usb_enable(cvmx_usb_state_t *state) /* Wait for the USBC_HPRT[PRTENA]. */ if (CVMX_WAIT_FOR_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt_t, - prtena, ==, 1, 100000)) { - if (cvmx_unlikely(usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_DEBUG_INFO)) - cvmx_dprintf("%s: Timeout waiting for the port to finish reset\n", - __FUNCTION__); + prtena, ==, 1, 100000)) return CVMX_USB_TIMEOUT; - } /* Read the port speed field to get the enumerated speed, USBC_HPRT[PRTSPD]. */ usb->usbcx_hprt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPRT(usb->index)); - if (cvmx_unlikely(usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_DEBUG_INFO)) - cvmx_dprintf("%s: USB%d is in %s speed mode\n", __FUNCTION__, usb->index, - (usb->usbcx_hprt.s.prtspd == CVMX_USB_SPEED_HIGH) ? "high" : - (usb->usbcx_hprt.s.prtspd == CVMX_USB_SPEED_FULL) ? "full" : - "low"); - usbcx_ghwcfg3.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GHWCFG3(usb->index)); /* 13. Program the USBC_GRXFSIZ register to select the size of the receive @@ -1003,15 +987,6 @@ cvmx_usb_port_status_t cvmx_usb_get_status(cvmx_usb_state_t *state) result.connected = usbc_hprt.s.prtconnsts; result.connect_change = (result.connected != usb->port_status.connected); - if (cvmx_unlikely(usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_DEBUG_CALLS)) - cvmx_dprintf("%*s%s: returned port enabled=%d, over_current=%d, powered=%d, speed=%d, connected=%d, connect_change=%d\n", - 2*(--usb->indent), "", __FUNCTION__, - result.port_enabled, - result.port_over_current, - result.port_powered, - result.port_speed, - result.connected, - result.connect_change); return result; } @@ -1526,13 +1501,6 @@ static void __cvmx_usb_start_channel(cvmx_usb_internal_state_t *usb, { cvmx_usb_transaction_t *transaction = pipe->head; - if (cvmx_unlikely((usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_DEBUG_TRANSFERS) || - (pipe->flags & CVMX_USB_PIPE_FLAGS_DEBUG_TRANSFERS))) - cvmx_dprintf("%s: Channel %d started. Pipe %d transaction %d stage %d\n", - __FUNCTION__, channel, __cvmx_usb_get_pipe_handle(usb, pipe), - __cvmx_usb_get_submit_handle(usb, transaction), - transaction->stage); - /* Make sure all writes to the DMA region get flushed */ CVMX_SYNCW; @@ -1820,11 +1788,8 @@ static void __cvmx_usb_schedule(cvmx_usb_internal_state_t *usb, int is_sof) /* Find an idle channel */ CVMX_CLZ(channel, usb->idle_hardware_channels); channel = 31 - channel; - if (cvmx_unlikely(channel > 7)) { - if (cvmx_unlikely(usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_DEBUG_INFO)) - cvmx_dprintf("%s: Idle hardware channels has a channel higher than 7. This is wrong\n", __FUNCTION__); + if (cvmx_unlikely(channel > 7)) break; - } /* Find a pipe needing service */ pipe = NULL; @@ -1844,34 +1809,6 @@ static void __cvmx_usb_schedule(cvmx_usb_internal_state_t *usb, int is_sof) if (!pipe) break; - if (cvmx_unlikely((usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_DEBUG_TRANSFERS) || - (pipe->flags & CVMX_USB_PIPE_FLAGS_DEBUG_TRANSFERS))) { - cvmx_usb_transaction_t *transaction = pipe->head; - const cvmx_usb_control_header_t *header = (transaction->control_header) ? cvmx_phys_to_ptr(transaction->control_header) : NULL; - const char *dir = (pipe->transfer_dir == CVMX_USB_DIRECTION_IN) ? "IN" : "OUT"; - const char *type; - switch (pipe->transfer_type) { - case CVMX_USB_TRANSFER_CONTROL: - type = "SETUP"; - dir = (header->s.request_type & 0x80) ? "IN" : "OUT"; - break; - case CVMX_USB_TRANSFER_ISOCHRONOUS: - type = "ISOCHRONOUS"; - break; - case CVMX_USB_TRANSFER_BULK: - type = "BULK"; - break; - default: /* CVMX_USB_TRANSFER_INTERRUPT */ - type = "INTERRUPT"; - break; - } - cvmx_dprintf("%s: Starting pipe %d, transaction %d on channel %d. %s %s len=%d header=0x%llx\n", - __FUNCTION__, __cvmx_usb_get_pipe_handle(usb, pipe), - __cvmx_usb_get_submit_handle(usb, transaction), - channel, type, dir, - transaction->buffer_length, - (header) ? (unsigned long long)header->u64 : 0ull); - } __cvmx_usb_start_channel(usb, channel, pipe); } @@ -1935,19 +1872,8 @@ static void __cvmx_usb_perform_callback(cvmx_usb_internal_state_t *usb, if (!callback) return; - if (cvmx_unlikely(usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_DEBUG_CALLBACKS)) - cvmx_dprintf("%*s%s: calling callback %p(usb=%p, complete_code=%s, " - "pipe_handle=%d, submit_handle=%d, bytes_transferred=%d, user_data=%p);\n", - 2*usb->indent, "", __FUNCTION__, callback, usb, - __cvmx_usb_complete_to_string(complete_code), - pipe_handle, submit_handle, bytes_transferred, user_data); - callback((cvmx_usb_state_t *)usb, reason, complete_code, pipe_handle, submit_handle, bytes_transferred, user_data); - - if (cvmx_unlikely(usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_DEBUG_CALLBACKS)) - cvmx_dprintf("%*s%s: callback %p complete\n", 2*usb->indent, "", - __FUNCTION__, callback); } @@ -2694,15 +2620,6 @@ static int __cvmx_usb_poll_channel(cvmx_usb_internal_state_t *usb, int channel) (transaction->stage == CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE)) bytes_this_transfer = 0; - /* Optional debug output */ - if (cvmx_unlikely((usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_DEBUG_TRANSFERS) || - (pipe->flags & CVMX_USB_PIPE_FLAGS_DEBUG_TRANSFERS))) - cvmx_dprintf("%s: Channel %d halted. Pipe %d transaction %d stage %d bytes=%d\n", - __FUNCTION__, channel, - __cvmx_usb_get_pipe_handle(usb, pipe), - __cvmx_usb_get_submit_handle(usb, transaction), - transaction->stage, bytes_this_transfer); - /* Add the bytes transferred to the running total. It is important that bytes_this_transfer doesn't count any data that needs to be retransmitted */ diff --git a/drivers/staging/octeon-usb/cvmx-usb.h b/drivers/staging/octeon-usb/cvmx-usb.h index db9cc05e5d3c..eed6ba43cf59 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.h +++ b/drivers/staging/octeon-usb/cvmx-usb.h @@ -622,12 +622,6 @@ typedef enum CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ = 3<<3, /**< Speed of reference clock */ /* Bits 3-4 used to encode the clock frequency */ CVMX_USB_INITIALIZE_FLAGS_NO_DMA = 1<<5, /**< Disable DMA and used polled IO for data transfer use for the USB */ - CVMX_USB_INITIALIZE_FLAGS_DEBUG_TRANSFERS = 1<<16, /**< Enable extra console output for debugging USB transfers */ - CVMX_USB_INITIALIZE_FLAGS_DEBUG_CALLBACKS = 1<<17, /**< Enable extra console output for debugging USB callbacks */ - CVMX_USB_INITIALIZE_FLAGS_DEBUG_INFO = 1<<18, /**< Enable extra console output for USB informational data */ - CVMX_USB_INITIALIZE_FLAGS_DEBUG_CALLS = 1<<19, /**< Enable extra console output for every function call */ - CVMX_USB_INITIALIZE_FLAGS_DEBUG_CSRS = 1<<20, /**< Enable extra console output for every CSR access */ - CVMX_USB_INITIALIZE_FLAGS_DEBUG_ALL = ((CVMX_USB_INITIALIZE_FLAGS_DEBUG_CSRS<<1)-1) - (CVMX_USB_INITIALIZE_FLAGS_DEBUG_TRANSFERS-1), } cvmx_usb_initialize_flags_t; /** @@ -636,7 +630,6 @@ typedef enum */ typedef enum { - CVMX_USB_PIPE_FLAGS_DEBUG_TRANSFERS = 1<<15,/**< Used to display CVMX_USB_INITIALIZE_FLAGS_DEBUG_TRANSFERS for a specific pipe only */ __CVMX_USB_PIPE_FLAGS_OPEN = 1<<16, /**< Used internally to determine if a pipe is open. Do not use */ __CVMX_USB_PIPE_FLAGS_SCHEDULED = 1<<17, /**< Used internally to determine if a pipe is actively using hardware. Do not use */ __CVMX_USB_PIPE_FLAGS_NEED_PING = 1<<18, /**< Used internally to determine if a high speed pipe is in the ping state. Do not use */ From 67f70fc624e2aa06291c70d1671f43950a03f3c5 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Mon, 29 Jul 2013 20:07:45 +0300 Subject: [PATCH 1040/3400] staging: octeon-usb: cvmx-usb: delete redundant example code Delete redundant example code found in comments. It's already there in the driver proper. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.h | 209 +------------------------- 1 file changed, 1 insertion(+), 208 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.h b/drivers/staging/octeon-usb/cvmx-usb.h index eed6ba43cf59..ffabfbe321f5 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.h +++ b/drivers/staging/octeon-usb/cvmx-usb.h @@ -217,214 +217,7 @@ * messages similar to the usb 2.0 spec for hub control and * status. For these systems it may be necessary to write * function to decode standard usb control messages into - * equivalent cvmx-usb API calls. As an example, the following - * code is used under Linux for some of the basic hub control - * messages. - * - * @code - * static int octeon_usb_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength) - * { - * cvmx_usb_state_t *usb = (cvmx_usb_state_t *)hcd->hcd_priv; - * cvmx_usb_port_status_t usb_port_status; - * int port_status; - * struct usb_hub_descriptor *desc; - * unsigned long flags; - * - * switch (typeReq) - * { - * case ClearHubFeature: - * DEBUG_ROOT_HUB("OcteonUSB: ClearHubFeature\n"); - * switch (wValue) - * { - * case C_HUB_LOCAL_POWER: - * case C_HUB_OVER_CURRENT: - * // Nothing required here - * break; - * default: - * return -EINVAL; - * } - * break; - * case ClearPortFeature: - * DEBUG_ROOT_HUB("OcteonUSB: ClearPortFeature"); - * if (wIndex != 1) - * { - * DEBUG_ROOT_HUB(" INVALID\n"); - * return -EINVAL; - * } - * - * switch (wValue) - * { - * case USB_PORT_FEAT_ENABLE: - * DEBUG_ROOT_HUB(" ENABLE"); - * local_irq_save(flags); - * cvmx_usb_disable(usb); - * local_irq_restore(flags); - * break; - * case USB_PORT_FEAT_SUSPEND: - * DEBUG_ROOT_HUB(" SUSPEND"); - * // Not supported on Octeon - * break; - * case USB_PORT_FEAT_POWER: - * DEBUG_ROOT_HUB(" POWER"); - * // Not supported on Octeon - * break; - * case USB_PORT_FEAT_INDICATOR: - * DEBUG_ROOT_HUB(" INDICATOR"); - * // Port inidicator not supported - * break; - * case USB_PORT_FEAT_C_CONNECTION: - * DEBUG_ROOT_HUB(" C_CONNECTION"); - * // Clears drivers internal connect status change flag - * cvmx_usb_set_status(usb, cvmx_usb_get_status(usb)); - * break; - * case USB_PORT_FEAT_C_RESET: - * DEBUG_ROOT_HUB(" C_RESET"); - * // Clears the driver's internal Port Reset Change flag - * cvmx_usb_set_status(usb, cvmx_usb_get_status(usb)); - * break; - * case USB_PORT_FEAT_C_ENABLE: - * DEBUG_ROOT_HUB(" C_ENABLE"); - * // Clears the driver's internal Port Enable/Disable Change flag - * cvmx_usb_set_status(usb, cvmx_usb_get_status(usb)); - * break; - * case USB_PORT_FEAT_C_SUSPEND: - * DEBUG_ROOT_HUB(" C_SUSPEND"); - * // Clears the driver's internal Port Suspend Change flag, - * which is set when resume signaling on the host port is - * complete - * break; - * case USB_PORT_FEAT_C_OVER_CURRENT: - * DEBUG_ROOT_HUB(" C_OVER_CURRENT"); - * // Clears the driver's overcurrent Change flag - * cvmx_usb_set_status(usb, cvmx_usb_get_status(usb)); - * break; - * default: - * DEBUG_ROOT_HUB(" UNKNOWN\n"); - * return -EINVAL; - * } - * DEBUG_ROOT_HUB("\n"); - * break; - * case GetHubDescriptor: - * DEBUG_ROOT_HUB("OcteonUSB: GetHubDescriptor\n"); - * desc = (struct usb_hub_descriptor *)buf; - * desc->bDescLength = 9; - * desc->bDescriptorType = 0x29; - * desc->bNbrPorts = 1; - * desc->wHubCharacteristics = 0x08; - * desc->bPwrOn2PwrGood = 1; - * desc->bHubContrCurrent = 0; - * desc->bitmap[0] = 0; - * desc->bitmap[1] = 0xff; - * break; - * case GetHubStatus: - * DEBUG_ROOT_HUB("OcteonUSB: GetHubStatus\n"); - * *(__le32 *)buf = 0; - * break; - * case GetPortStatus: - * DEBUG_ROOT_HUB("OcteonUSB: GetPortStatus"); - * if (wIndex != 1) - * { - * DEBUG_ROOT_HUB(" INVALID\n"); - * return -EINVAL; - * } - * - * usb_port_status = cvmx_usb_get_status(usb); - * port_status = 0; - * - * if (usb_port_status.connect_change) - * { - * port_status |= (1 << USB_PORT_FEAT_C_CONNECTION); - * DEBUG_ROOT_HUB(" C_CONNECTION"); - * } - * - * if (usb_port_status.port_enabled) - * { - * port_status |= (1 << USB_PORT_FEAT_C_ENABLE); - * DEBUG_ROOT_HUB(" C_ENABLE"); - * } - * - * if (usb_port_status.connected) - * { - * port_status |= (1 << USB_PORT_FEAT_CONNECTION); - * DEBUG_ROOT_HUB(" CONNECTION"); - * } - * - * if (usb_port_status.port_enabled) - * { - * port_status |= (1 << USB_PORT_FEAT_ENABLE); - * DEBUG_ROOT_HUB(" ENABLE"); - * } - * - * if (usb_port_status.port_over_current) - * { - * port_status |= (1 << USB_PORT_FEAT_OVER_CURRENT); - * DEBUG_ROOT_HUB(" OVER_CURRENT"); - * } - * - * if (usb_port_status.port_powered) - * { - * port_status |= (1 << USB_PORT_FEAT_POWER); - * DEBUG_ROOT_HUB(" POWER"); - * } - * - * if (usb_port_status.port_speed == CVMX_USB_SPEED_HIGH) - * { - * port_status |= (1 << USB_PORT_FEAT_HIGHSPEED); - * DEBUG_ROOT_HUB(" HIGHSPEED"); - * } - * else if (usb_port_status.port_speed == CVMX_USB_SPEED_LOW) - * { - * port_status |= (1 << USB_PORT_FEAT_LOWSPEED); - * DEBUG_ROOT_HUB(" LOWSPEED"); - * } - * - * *((__le32 *)buf) = cpu_to_le32(port_status); - * DEBUG_ROOT_HUB("\n"); - * break; - * case SetHubFeature: - * DEBUG_ROOT_HUB("OcteonUSB: SetHubFeature\n"); - * // No HUB features supported - * break; - * case SetPortFeature: - * DEBUG_ROOT_HUB("OcteonUSB: SetPortFeature"); - * if (wIndex != 1) - * { - * DEBUG_ROOT_HUB(" INVALID\n"); - * return -EINVAL; - * } - * - * switch (wValue) - * { - * case USB_PORT_FEAT_SUSPEND: - * DEBUG_ROOT_HUB(" SUSPEND\n"); - * return -EINVAL; - * case USB_PORT_FEAT_POWER: - * DEBUG_ROOT_HUB(" POWER\n"); - * return -EINVAL; - * case USB_PORT_FEAT_RESET: - * DEBUG_ROOT_HUB(" RESET\n"); - * local_irq_save(flags); - * cvmx_usb_disable(usb); - * if (cvmx_usb_enable(usb)) - * DEBUG_ERROR("Failed to enable the port\n"); - * local_irq_restore(flags); - * return 0; - * case USB_PORT_FEAT_INDICATOR: - * DEBUG_ROOT_HUB(" INDICATOR\n"); - * // Not supported - * break; - * default: - * DEBUG_ROOT_HUB(" UNKNOWN\n"); - * return -EINVAL; - * } - * break; - * default: - * DEBUG_ROOT_HUB("OcteonUSB: Unknown root hub request\n"); - * return -EINVAL; - * } - * return 0; - * } - * @endcode + * equivalent cvmx-usb API calls. * *

Interrupts

* From 684f94ccbda9757b3a0efbdb5072b53b75a82b49 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Mon, 29 Jul 2013 20:07:46 +0300 Subject: [PATCH 1041/3400] staging: octeon-usb: cvmx-usb: delete __cplusplus Delete __cplusplus. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.h b/drivers/staging/octeon-usb/cvmx-usb.h index ffabfbe321f5..e7b524b7de16 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.h +++ b/drivers/staging/octeon-usb/cvmx-usb.h @@ -241,10 +241,6 @@ #ifndef __CVMX_USB_H__ #define __CVMX_USB_H__ -#ifdef __cplusplus -extern "C" { -#endif - /** * Enumerations representing the status of function calls. */ @@ -864,8 +860,4 @@ extern int cvmx_usb_get_frame_number(cvmx_usb_state_t *state); */ extern cvmx_usb_status_t cvmx_usb_poll(cvmx_usb_state_t *state); -#ifdef __cplusplus -} -#endif - #endif /* __CVMX_USB_H__ */ From 6d658cb2abe8560e047c57f0f68ac5162b917ddb Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Mon, 29 Jul 2013 20:07:47 +0300 Subject: [PATCH 1042/3400] staging: octeon-usb: cvmx-usb: utilize Linux error codes Use generic Linux error codes to replace cvmx_usb_status_t. The conversion table: Before After cvmx_usb_status_t int CVMX_USB_SUCCESS 0 CVMX_USB_INVALID_PARAM -EINVAL CVMX_USB_NO_MEMORY -ENOMEM CVMX_USB_BUSY -EBUSY CVMX_USB_TIMEOUT -ETIMEDOUT CVMX_USB_INCORRECT_MODE Deleted (was never used) Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.c | 191 ++++++++++++-------------- drivers/staging/octeon-usb/cvmx-usb.h | 89 ++++-------- 2 files changed, 117 insertions(+), 163 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.c b/drivers/staging/octeon-usb/cvmx-usb.c index dd8653c9e5e3..960435393583 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.c +++ b/drivers/staging/octeon-usb/cvmx-usb.c @@ -533,12 +533,10 @@ static inline void __cvmx_usb_remove_pipe(cvmx_usb_pipe_list_t *list, cvmx_usb_p * cvmx_usb_initialize_flags_t for the flag * definitions. Some flags are mandatory. * - * @return CVMX_USB_SUCCESS or a negative error code defined in - * cvmx_usb_status_t. + * @return 0 or a negative error code. */ -cvmx_usb_status_t cvmx_usb_initialize(cvmx_usb_state_t *state, - int usb_port_number, - cvmx_usb_initialize_flags_t flags) +int cvmx_usb_initialize(cvmx_usb_state_t *state, int usb_port_number, + cvmx_usb_initialize_flags_t flags) { cvmx_usbnx_clk_ctl_t usbn_clk_ctl; cvmx_usbnx_usbp_ctl_status_t usbn_usbp_ctl_status; @@ -548,13 +546,13 @@ cvmx_usb_status_t cvmx_usb_initialize(cvmx_usb_state_t *state, /* Make sure that state is large enough to store the internal state */ if (sizeof(*state) < sizeof(*usb)) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; /* At first allow 0-1 for the usb port number */ if ((usb_port_number < 0) || (usb_port_number > 1)) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; /* For all chips except 52XX there is only one port */ if (!OCTEON_IS_MODEL(OCTEON_CN52XX) && (usb_port_number > 0)) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; /* Try to determine clock type automatically */ if ((flags & (CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI | CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND)) == 0) { @@ -578,7 +576,7 @@ cvmx_usb_status_t cvmx_usb_initialize(cvmx_usb_state_t *state, flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ; break; default: - return CVMX_USB_INVALID_PARAM; + return -EINVAL; break; } } @@ -812,7 +810,7 @@ cvmx_usb_status_t cvmx_usb_initialize(cvmx_usb_state_t *state, /* Steps 4-15 from the manual are done later in the port enable */ } - return CVMX_USB_SUCCESS; + return 0; } @@ -824,10 +822,9 @@ cvmx_usb_status_t cvmx_usb_initialize(cvmx_usb_state_t *state, * @param state USB device state populated by * cvmx_usb_initialize(). * - * @return CVMX_USB_SUCCESS or a negative error code defined in - * cvmx_usb_status_t. + * @return 0 or a negative error code. */ -cvmx_usb_status_t cvmx_usb_shutdown(cvmx_usb_state_t *state) +int cvmx_usb_shutdown(cvmx_usb_state_t *state) { cvmx_usbnx_clk_ctl_t usbn_clk_ctl; cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; @@ -838,7 +835,7 @@ cvmx_usb_status_t cvmx_usb_shutdown(cvmx_usb_state_t *state) usb->active_pipes[CVMX_USB_TRANSFER_INTERRUPT].head || usb->active_pipes[CVMX_USB_TRANSFER_CONTROL].head || usb->active_pipes[CVMX_USB_TRANSFER_BULK].head) - return CVMX_USB_BUSY; + return -EBUSY; /* Disable the clocks and put them in power on reset */ usbn_clk_ctl.u64 = __cvmx_usb_read_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index)); @@ -849,7 +846,7 @@ cvmx_usb_status_t cvmx_usb_shutdown(cvmx_usb_state_t *state) usbn_clk_ctl.s.hrst = 0; __cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index), usbn_clk_ctl.u64); - return CVMX_USB_SUCCESS; + return 0; } @@ -860,10 +857,9 @@ cvmx_usb_status_t cvmx_usb_shutdown(cvmx_usb_state_t *state) * @param state USB device state populated by * cvmx_usb_initialize(). * - * @return CVMX_USB_SUCCESS or a negative error code defined in - * cvmx_usb_status_t. + * @return 0 or a negative error code. */ -cvmx_usb_status_t cvmx_usb_enable(cvmx_usb_state_t *state) +int cvmx_usb_enable(cvmx_usb_state_t *state) { cvmx_usbcx_ghwcfg3_t usbcx_ghwcfg3; cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; @@ -873,11 +869,11 @@ cvmx_usb_status_t cvmx_usb_enable(cvmx_usb_state_t *state) /* If the port is already enabled the just return. We don't need to do anything */ if (usb->usbcx_hprt.s.prtena) - return CVMX_USB_SUCCESS; + return 0; /* If there is nothing plugged into the port then fail immediately */ if (!usb->usbcx_hprt.s.prtconnsts) { - return CVMX_USB_TIMEOUT; + return -ETIMEDOUT; } /* Program the port reset bit to start the reset process */ @@ -893,7 +889,7 @@ cvmx_usb_status_t cvmx_usb_enable(cvmx_usb_state_t *state) /* Wait for the USBC_HPRT[PRTENA]. */ if (CVMX_WAIT_FOR_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt_t, prtena, ==, 1, 100000)) - return CVMX_USB_TIMEOUT; + return -ETIMEDOUT; /* Read the port speed field to get the enumerated speed, USBC_HPRT[PRTSPD]. */ usb->usbcx_hprt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPRT(usb->index)); @@ -931,7 +927,7 @@ cvmx_usb_status_t cvmx_usb_enable(cvmx_usb_state_t *state) CVMX_WAIT_FOR_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), cvmx_usbcx_grstctl_t, rxfflsh, ==, 0, 100); - return CVMX_USB_SUCCESS; + return 0; } @@ -944,16 +940,15 @@ cvmx_usb_status_t cvmx_usb_enable(cvmx_usb_state_t *state) * @param state USB device state populated by * cvmx_usb_initialize(). * - * @return CVMX_USB_SUCCESS or a negative error code defined in - * cvmx_usb_status_t. + * @return 0 or a negative error code. */ -cvmx_usb_status_t cvmx_usb_disable(cvmx_usb_state_t *state) +int cvmx_usb_disable(cvmx_usb_state_t *state) { cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; /* Disable the port */ USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt_t, prtena, 1); - return CVMX_USB_SUCCESS; + return 0; } @@ -1101,7 +1096,7 @@ static inline int __cvmx_usb_get_pipe_handle(cvmx_usb_internal_state_t *usb, * devices behind a high speed hub. * * @return A non negative value is a pipe handle. Negative - * values are failure codes from cvmx_usb_status_t. + * values are error codes. */ int cvmx_usb_open_pipe(cvmx_usb_state_t *state, cvmx_usb_pipe_flags_t flags, int device_addr, int endpoint_num, @@ -1114,36 +1109,36 @@ int cvmx_usb_open_pipe(cvmx_usb_state_t *state, cvmx_usb_pipe_flags_t flags, cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; if (cvmx_unlikely((device_addr < 0) || (device_addr > MAX_USB_ADDRESS))) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; if (cvmx_unlikely((endpoint_num < 0) || (endpoint_num > MAX_USB_ENDPOINT))) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; if (cvmx_unlikely(device_speed > CVMX_USB_SPEED_LOW)) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; if (cvmx_unlikely((max_packet <= 0) || (max_packet > 1024))) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; if (cvmx_unlikely(transfer_type > CVMX_USB_TRANSFER_INTERRUPT)) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; if (cvmx_unlikely((transfer_dir != CVMX_USB_DIRECTION_OUT) && (transfer_dir != CVMX_USB_DIRECTION_IN))) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; if (cvmx_unlikely(interval < 0)) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; if (cvmx_unlikely((transfer_type == CVMX_USB_TRANSFER_CONTROL) && interval)) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; if (cvmx_unlikely(multi_count < 0)) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; if (cvmx_unlikely((device_speed != CVMX_USB_SPEED_HIGH) && (multi_count != 0))) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; if (cvmx_unlikely((hub_device_addr < 0) || (hub_device_addr > MAX_USB_ADDRESS))) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; if (cvmx_unlikely((hub_port < 0) || (hub_port > MAX_USB_HUB_PORT))) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; /* Find a free pipe */ pipe = usb->free_pipes.head; if (!pipe) - return CVMX_USB_NO_MEMORY; + return -ENOMEM; __cvmx_usb_remove_pipe(&usb->free_pipes, pipe); pipe->flags = flags | __CVMX_USB_PIPE_FLAGS_OPEN; if ((device_speed == CVMX_USB_SPEED_HIGH) && @@ -1985,16 +1980,16 @@ static int __cvmx_usb_submit_transaction(cvmx_usb_internal_state_t *usb, cvmx_usb_pipe_t *pipe = usb->pipe + pipe_handle; if (cvmx_unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES))) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; /* Fail if the pipe isn't open */ if (cvmx_unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0)) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; if (cvmx_unlikely(pipe->transfer_type != type)) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; transaction = __cvmx_usb_alloc_transaction(usb); if (cvmx_unlikely(!transaction)) - return CVMX_USB_NO_MEMORY; + return -ENOMEM; transaction->type = type; transaction->flags |= flags; @@ -2065,8 +2060,7 @@ static int __cvmx_usb_submit_transaction(cvmx_usb_internal_state_t *usb, * callback in not NULL. * * @return A submitted transaction handle or negative on - * failure. Negative values are failure codes from - * cvmx_usb_status_t. + * failure. Negative values are error codes. */ int cvmx_usb_submit_bulk(cvmx_usb_state_t *state, int pipe_handle, uint64_t buffer, int buffer_length, @@ -2078,9 +2072,9 @@ int cvmx_usb_submit_bulk(cvmx_usb_state_t *state, int pipe_handle, /* Pipe handle checking is done later in a common place */ if (cvmx_unlikely(!buffer)) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; if (cvmx_unlikely(buffer_length < 0)) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; submit_handle = __cvmx_usb_submit_transaction(usb, pipe_handle, CVMX_USB_TRANSFER_BULK, @@ -2125,8 +2119,7 @@ int cvmx_usb_submit_bulk(cvmx_usb_state_t *state, int pipe_handle, * callback in not NULL. * * @return A submitted transaction handle or negative on - * failure. Negative values are failure codes from - * cvmx_usb_status_t. + * failure. Negative values are error codes. */ int cvmx_usb_submit_interrupt(cvmx_usb_state_t *state, int pipe_handle, uint64_t buffer, int buffer_length, @@ -2138,9 +2131,9 @@ int cvmx_usb_submit_interrupt(cvmx_usb_state_t *state, int pipe_handle, /* Pipe handle checking is done later in a common place */ if (cvmx_unlikely(!buffer)) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; if (cvmx_unlikely(buffer_length < 0)) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; submit_handle = __cvmx_usb_submit_transaction(usb, pipe_handle, CVMX_USB_TRANSFER_INTERRUPT, @@ -2189,8 +2182,7 @@ int cvmx_usb_submit_interrupt(cvmx_usb_state_t *state, int pipe_handle, * callback in not NULL. * * @return A submitted transaction handle or negative on - * failure. Negative values are failure codes from - * cvmx_usb_status_t. + * failure. Negative values are error codes. */ int cvmx_usb_submit_control(cvmx_usb_state_t *state, int pipe_handle, uint64_t control_header, @@ -2204,12 +2196,12 @@ int cvmx_usb_submit_control(cvmx_usb_state_t *state, int pipe_handle, /* Pipe handle checking is done later in a common place */ if (cvmx_unlikely(!control_header)) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; /* Some drivers send a buffer with a zero length. God only knows why */ if (cvmx_unlikely(buffer && (buffer_length < 0))) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; if (cvmx_unlikely(!buffer && (buffer_length != 0))) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; if ((header->s.request_type & 0x80) == 0) buffer_length = cvmx_le16_to_cpu(header->s.length); @@ -2270,8 +2262,7 @@ int cvmx_usb_submit_control(cvmx_usb_state_t *state, int pipe_handle, * callback in not NULL. * * @return A submitted transaction handle or negative on - * failure. Negative values are failure codes from - * cvmx_usb_status_t. + * failure. Negative values are error codes. */ int cvmx_usb_submit_isochronous(cvmx_usb_state_t *state, int pipe_handle, int start_frame, int flags, @@ -2286,17 +2277,17 @@ int cvmx_usb_submit_isochronous(cvmx_usb_state_t *state, int pipe_handle, /* Pipe handle checking is done later in a common place */ if (cvmx_unlikely(start_frame < 0)) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; if (cvmx_unlikely(flags & ~(CVMX_USB_ISOCHRONOUS_FLAGS_ALLOW_SHORT | CVMX_USB_ISOCHRONOUS_FLAGS_ASAP))) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; if (cvmx_unlikely(number_packets < 1)) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; if (cvmx_unlikely(!packets)) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; if (cvmx_unlikely(!buffer)) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; if (cvmx_unlikely(buffer_length < 0)) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; submit_handle = __cvmx_usb_submit_transaction(usb, pipe_handle, CVMX_USB_TRANSFER_ISOCHRONOUS, @@ -2327,30 +2318,28 @@ int cvmx_usb_submit_isochronous(cvmx_usb_state_t *state, int pipe_handle, * @param submit_handle * Handle to transaction to cancel, returned by the submit function. * - * @return CVMX_USB_SUCCESS or a negative error code defined in - * cvmx_usb_status_t. + * @return 0 or a negative error code. */ -cvmx_usb_status_t cvmx_usb_cancel(cvmx_usb_state_t *state, int pipe_handle, - int submit_handle) +int cvmx_usb_cancel(cvmx_usb_state_t *state, int pipe_handle, int submit_handle) { cvmx_usb_transaction_t *transaction; cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; cvmx_usb_pipe_t *pipe = usb->pipe + pipe_handle; if (cvmx_unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES))) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; if (cvmx_unlikely((submit_handle < 0) || (submit_handle >= MAX_TRANSACTIONS))) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; /* Fail if the pipe isn't open */ if (cvmx_unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0)) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; transaction = usb->transaction + submit_handle; /* Fail if this transaction already completed */ if (cvmx_unlikely((transaction->flags & __CVMX_USB_TRANSACTION_FLAGS_IN_USE) == 0)) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; /* If the transaction is the HEAD of the queue and scheduled. We need to treat it special */ @@ -2371,7 +2360,7 @@ cvmx_usb_status_t cvmx_usb_cancel(cvmx_usb_state_t *state, int pipe_handle, } } __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_CANCEL); - return CVMX_USB_SUCCESS; + return 0; } @@ -2384,29 +2373,28 @@ cvmx_usb_status_t cvmx_usb_cancel(cvmx_usb_state_t *state, int pipe_handle, * @param pipe_handle * Pipe handle to cancel requests in. * - * @return CVMX_USB_SUCCESS or a negative error code defined in - * cvmx_usb_status_t. + * @return 0 or a negative error code. */ -cvmx_usb_status_t cvmx_usb_cancel_all(cvmx_usb_state_t *state, int pipe_handle) +int cvmx_usb_cancel_all(cvmx_usb_state_t *state, int pipe_handle) { cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; cvmx_usb_pipe_t *pipe = usb->pipe + pipe_handle; if (cvmx_unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES))) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; /* Fail if the pipe isn't open */ if (cvmx_unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0)) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; /* Simply loop through and attempt to cancel each transaction */ while (pipe->head) { - cvmx_usb_status_t result = cvmx_usb_cancel(state, pipe_handle, + int result = cvmx_usb_cancel(state, pipe_handle, __cvmx_usb_get_submit_handle(usb, pipe->head)); - if (cvmx_unlikely(result != CVMX_USB_SUCCESS)) + if (cvmx_unlikely(result != 0)) return result; } - return CVMX_USB_SUCCESS; + return 0; } @@ -2418,31 +2406,30 @@ cvmx_usb_status_t cvmx_usb_cancel_all(cvmx_usb_state_t *state, int pipe_handle) * @param pipe_handle * Pipe handle to close. * - * @return CVMX_USB_SUCCESS or a negative error code defined in - * cvmx_usb_status_t. CVMX_USB_BUSY is returned if the - * pipe has outstanding transfers. + * @return 0 or a negative error code. EBUSY is returned if the pipe has + * outstanding transfers. */ -cvmx_usb_status_t cvmx_usb_close_pipe(cvmx_usb_state_t *state, int pipe_handle) +int cvmx_usb_close_pipe(cvmx_usb_state_t *state, int pipe_handle) { cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; cvmx_usb_pipe_t *pipe = usb->pipe + pipe_handle; if (cvmx_unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES))) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; /* Fail if the pipe isn't open */ if (cvmx_unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0)) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; /* Fail if the pipe has pending transactions */ if (cvmx_unlikely(pipe->head)) - return CVMX_USB_BUSY; + return -EBUSY; pipe->flags = 0; __cvmx_usb_remove_pipe(&usb->idle_pipes, pipe); __cvmx_usb_append_pipe(&usb->free_pipes, pipe); - return CVMX_USB_SUCCESS; + return 0; } @@ -2455,25 +2442,24 @@ cvmx_usb_status_t cvmx_usb_close_pipe(cvmx_usb_state_t *state, int pipe_handle) * @param callback Function to call when the event occurs. * @param user_data User data parameter to the function. * - * @return CVMX_USB_SUCCESS or a negative error code defined in - * cvmx_usb_status_t. + * @return 0 or a negative error code. */ -cvmx_usb_status_t cvmx_usb_register_callback(cvmx_usb_state_t *state, - cvmx_usb_callback_t reason, - cvmx_usb_callback_func_t callback, - void *user_data) +int cvmx_usb_register_callback(cvmx_usb_state_t *state, + cvmx_usb_callback_t reason, + cvmx_usb_callback_func_t callback, + void *user_data) { cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; if (cvmx_unlikely(reason >= __CVMX_USB_CALLBACK_END)) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; if (cvmx_unlikely(!callback)) - return CVMX_USB_INVALID_PARAM; + return -EINVAL; usb->callback[reason] = callback; usb->callback_data[reason] = user_data; - return CVMX_USB_SUCCESS; + return 0; } @@ -2900,10 +2886,9 @@ static int __cvmx_usb_poll_channel(cvmx_usb_internal_state_t *usb, int channel) * @param state USB device state populated by * cvmx_usb_initialize(). * - * @return CVMX_USB_SUCCESS or a negative error code defined in - * cvmx_usb_status_t. + * @return 0 or a negative error code. */ -cvmx_usb_status_t cvmx_usb_poll(cvmx_usb_state_t *state) +int cvmx_usb_poll(cvmx_usb_state_t *state) { cvmx_usbcx_hfnum_t usbc_hfnum; cvmx_usbcx_gintsts_t usbc_gintsts; @@ -2986,5 +2971,5 @@ cvmx_usb_status_t cvmx_usb_poll(cvmx_usb_state_t *state) __cvmx_usb_schedule(usb, usbc_gintsts.s.sof); - return CVMX_USB_SUCCESS; + return 0; } diff --git a/drivers/staging/octeon-usb/cvmx-usb.h b/drivers/staging/octeon-usb/cvmx-usb.h index e7b524b7de16..dc366c8e7171 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.h +++ b/drivers/staging/octeon-usb/cvmx-usb.h @@ -241,21 +241,6 @@ #ifndef __CVMX_USB_H__ #define __CVMX_USB_H__ -/** - * Enumerations representing the status of function calls. - */ -typedef enum -{ - CVMX_USB_SUCCESS = 0, /**< There were no errors */ - CVMX_USB_INVALID_PARAM = -1, /**< A parameter to the function was invalid */ - CVMX_USB_NO_MEMORY = -2, /**< Insufficient resources were available for the request */ - CVMX_USB_BUSY = -3, /**< The resource is busy and cannot service the request */ - CVMX_USB_TIMEOUT = -4, /**< Waiting for an action timed out */ - CVMX_USB_INCORRECT_MODE = -5, /**< The function call doesn't work in the current USB - mode. This happens when host only functions are - called in device mode or vice versa */ -} cvmx_usb_status_t; - /** * Enumerations representing the possible USB device speeds */ @@ -451,12 +436,10 @@ extern int cvmx_usb_get_num_ports(void); * cvmx_usb_initialize_flags_t for the flag * definitions. Some flags are mandatory. * - * @return CVMX_USB_SUCCESS or a negative error code defined in - * cvmx_usb_status_t. + * @return 0 or a negative error code. */ -extern cvmx_usb_status_t cvmx_usb_initialize(cvmx_usb_state_t *state, - int usb_port_number, - cvmx_usb_initialize_flags_t flags); +extern int cvmx_usb_initialize(cvmx_usb_state_t *state, int usb_port_number, + cvmx_usb_initialize_flags_t flags); /** * Shutdown a USB port after a call to cvmx_usb_initialize(). @@ -466,10 +449,9 @@ extern cvmx_usb_status_t cvmx_usb_initialize(cvmx_usb_state_t *state, * @param state USB device state populated by * cvmx_usb_initialize(). * - * @return CVMX_USB_SUCCESS or a negative error code defined in - * cvmx_usb_status_t. + * @return 0 or a negative error code. */ -extern cvmx_usb_status_t cvmx_usb_shutdown(cvmx_usb_state_t *state); +extern int cvmx_usb_shutdown(cvmx_usb_state_t *state); /** * Enable a USB port. After this call succeeds, the USB port is @@ -478,10 +460,9 @@ extern cvmx_usb_status_t cvmx_usb_shutdown(cvmx_usb_state_t *state); * @param state USB device state populated by * cvmx_usb_initialize(). * - * @return CVMX_USB_SUCCESS or a negative error code defined in - * cvmx_usb_status_t. + * @return 0 or a negative error code. */ -extern cvmx_usb_status_t cvmx_usb_enable(cvmx_usb_state_t *state); +extern int cvmx_usb_enable(cvmx_usb_state_t *state); /** * Disable a USB port. After this call the USB port will not @@ -492,10 +473,9 @@ extern cvmx_usb_status_t cvmx_usb_enable(cvmx_usb_state_t *state); * @param state USB device state populated by * cvmx_usb_initialize(). * - * @return CVMX_USB_SUCCESS or a negative error code defined in - * cvmx_usb_status_t. + * @return 0 or a negative error code. */ -extern cvmx_usb_status_t cvmx_usb_disable(cvmx_usb_state_t *state); +extern int cvmx_usb_disable(cvmx_usb_state_t *state); /** * Get the current state of the USB port. Use this call to @@ -581,7 +561,7 @@ extern void cvmx_usb_set_status(cvmx_usb_state_t *state, cvmx_usb_port_status_t * devices behind a high speed hub. * * @return A non negative value is a pipe handle. Negative - * values are failure codes from cvmx_usb_status_t. + * values are error codes. */ extern int cvmx_usb_open_pipe(cvmx_usb_state_t *state, cvmx_usb_pipe_flags_t flags, @@ -620,8 +600,7 @@ extern int cvmx_usb_open_pipe(cvmx_usb_state_t *state, * callback in not NULL. * * @return A submitted transaction handle or negative on - * failure. Negative values are failure codes from - * cvmx_usb_status_t. + * failure. Negative values are error codes. */ extern int cvmx_usb_submit_bulk(cvmx_usb_state_t *state, int pipe_handle, uint64_t buffer, int buffer_length, @@ -656,8 +635,7 @@ extern int cvmx_usb_submit_bulk(cvmx_usb_state_t *state, int pipe_handle, * callback in not NULL. * * @return A submitted transaction handle or negative on - * failure. Negative values are failure codes from - * cvmx_usb_status_t. + * failure. Negative values are error codes. */ extern int cvmx_usb_submit_interrupt(cvmx_usb_state_t *state, int pipe_handle, uint64_t buffer, int buffer_length, @@ -696,8 +674,7 @@ extern int cvmx_usb_submit_interrupt(cvmx_usb_state_t *state, int pipe_handle, * callback in not NULL. * * @return A submitted transaction handle or negative on - * failure. Negative values are failure codes from - * cvmx_usb_status_t. + * failure. Negative values are error codes. */ extern int cvmx_usb_submit_control(cvmx_usb_state_t *state, int pipe_handle, uint64_t control_header, @@ -756,8 +733,7 @@ typedef enum * callback in not NULL. * * @return A submitted transaction handle or negative on - * failure. Negative values are failure codes from - * cvmx_usb_status_t. + * failure. Negative values are error codes. */ extern int cvmx_usb_submit_isochronous(cvmx_usb_state_t *state, int pipe_handle, int start_frame, int flags, @@ -781,11 +757,10 @@ extern int cvmx_usb_submit_isochronous(cvmx_usb_state_t *state, int pipe_handle, * @param submit_handle * Handle to transaction to cancel, returned by the submit function. * - * @return CVMX_USB_SUCCESS or a negative error code defined in - * cvmx_usb_status_t. + * @return 0 or a negative error code. */ -extern cvmx_usb_status_t cvmx_usb_cancel(cvmx_usb_state_t *state, - int pipe_handle, int submit_handle); +extern int cvmx_usb_cancel(cvmx_usb_state_t *state, int pipe_handle, + int submit_handle); /** @@ -797,11 +772,9 @@ extern cvmx_usb_status_t cvmx_usb_cancel(cvmx_usb_state_t *state, * @param pipe_handle * Pipe handle to cancel requests in. * - * @return CVMX_USB_SUCCESS or a negative error code defined in - * cvmx_usb_status_t. + * @return 0 or a negative error code. */ -extern cvmx_usb_status_t cvmx_usb_cancel_all(cvmx_usb_state_t *state, - int pipe_handle); +extern int cvmx_usb_cancel_all(cvmx_usb_state_t *state, int pipe_handle); /** * Close a pipe created with cvmx_usb_open_pipe(). @@ -811,12 +784,10 @@ extern cvmx_usb_status_t cvmx_usb_cancel_all(cvmx_usb_state_t *state, * @param pipe_handle * Pipe handle to close. * - * @return CVMX_USB_SUCCESS or a negative error code defined in - * cvmx_usb_status_t. CVMX_USB_BUSY is returned if the - * pipe has outstanding transfers. + * @return 0 or a negative error code. EBUSY is returned if the pipe has + * outstanding transfers. */ -extern cvmx_usb_status_t cvmx_usb_close_pipe(cvmx_usb_state_t *state, - int pipe_handle); +extern int cvmx_usb_close_pipe(cvmx_usb_state_t *state, int pipe_handle); /** * Register a function to be called when various USB events occur. @@ -827,13 +798,12 @@ extern cvmx_usb_status_t cvmx_usb_close_pipe(cvmx_usb_state_t *state, * @param callback Function to call when the event occurs. * @param user_data User data parameter to the function. * - * @return CVMX_USB_SUCCESS or a negative error code defined in - * cvmx_usb_status_t. + * @return 0 or a negative error code. */ -extern cvmx_usb_status_t cvmx_usb_register_callback(cvmx_usb_state_t *state, - cvmx_usb_callback_t reason, - cvmx_usb_callback_func_t callback, - void *user_data); +extern int cvmx_usb_register_callback(cvmx_usb_state_t *state, + cvmx_usb_callback_t reason, + cvmx_usb_callback_func_t callback, + void *user_data); /** * Get the current USB protocol level frame number. The frame @@ -855,9 +825,8 @@ extern int cvmx_usb_get_frame_number(cvmx_usb_state_t *state); * @param state USB device state populated by * cvmx_usb_initialize(). * - * @return CVMX_USB_SUCCESS or a negative error code defined in - * cvmx_usb_status_t. + * @return 0 or a negative error code. */ -extern cvmx_usb_status_t cvmx_usb_poll(cvmx_usb_state_t *state); +extern int cvmx_usb_poll(cvmx_usb_state_t *state); #endif /* __CVMX_USB_H__ */ From 27bf55251ce33be83e668718e3ad04fa0c245218 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Mon, 29 Jul 2013 20:07:48 +0300 Subject: [PATCH 1043/3400] staging: octeon-usb: cvmx-usb: eliminate cvmx_likely/unlikely Just use likely/unlikely. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.c | 94 +++++++++++++-------------- 1 file changed, 46 insertions(+), 48 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.c b/drivers/staging/octeon-usb/cvmx-usb.c index 960435393583..efea87b98833 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.c +++ b/drivers/staging/octeon-usb/cvmx-usb.c @@ -68,9 +68,7 @@ #define CVMX_PREFETCH_PREF0(address, offset) CVMX_PREFETCH_PREFX(0, address, offset) #define CVMX_CLZ(result, input) asm ("clz %[rd],%[rs]" : [rd] "=d" (result) : [rs] "d" (input)) -#define cvmx_likely likely #define cvmx_wait_usec udelay -#define cvmx_unlikely unlikely #define cvmx_le16_to_cpu le16_to_cpu #define MAX_RETRIES 3 /* Maximum number of times to retry failed transactions */ @@ -1108,31 +1106,31 @@ int cvmx_usb_open_pipe(cvmx_usb_state_t *state, cvmx_usb_pipe_flags_t flags, cvmx_usb_pipe_t *pipe; cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; - if (cvmx_unlikely((device_addr < 0) || (device_addr > MAX_USB_ADDRESS))) + if (unlikely((device_addr < 0) || (device_addr > MAX_USB_ADDRESS))) return -EINVAL; - if (cvmx_unlikely((endpoint_num < 0) || (endpoint_num > MAX_USB_ENDPOINT))) + if (unlikely((endpoint_num < 0) || (endpoint_num > MAX_USB_ENDPOINT))) return -EINVAL; - if (cvmx_unlikely(device_speed > CVMX_USB_SPEED_LOW)) + if (unlikely(device_speed > CVMX_USB_SPEED_LOW)) return -EINVAL; - if (cvmx_unlikely((max_packet <= 0) || (max_packet > 1024))) + if (unlikely((max_packet <= 0) || (max_packet > 1024))) return -EINVAL; - if (cvmx_unlikely(transfer_type > CVMX_USB_TRANSFER_INTERRUPT)) + if (unlikely(transfer_type > CVMX_USB_TRANSFER_INTERRUPT)) return -EINVAL; - if (cvmx_unlikely((transfer_dir != CVMX_USB_DIRECTION_OUT) && + if (unlikely((transfer_dir != CVMX_USB_DIRECTION_OUT) && (transfer_dir != CVMX_USB_DIRECTION_IN))) return -EINVAL; - if (cvmx_unlikely(interval < 0)) + if (unlikely(interval < 0)) return -EINVAL; - if (cvmx_unlikely((transfer_type == CVMX_USB_TRANSFER_CONTROL) && interval)) + if (unlikely((transfer_type == CVMX_USB_TRANSFER_CONTROL) && interval)) return -EINVAL; - if (cvmx_unlikely(multi_count < 0)) + if (unlikely(multi_count < 0)) return -EINVAL; - if (cvmx_unlikely((device_speed != CVMX_USB_SPEED_HIGH) && + if (unlikely((device_speed != CVMX_USB_SPEED_HIGH) && (multi_count != 0))) return -EINVAL; - if (cvmx_unlikely((hub_device_addr < 0) || (hub_device_addr > MAX_USB_ADDRESS))) + if (unlikely((hub_device_addr < 0) || (hub_device_addr > MAX_USB_ADDRESS))) return -EINVAL; - if (cvmx_unlikely((hub_port < 0) || (hub_port > MAX_USB_HUB_PORT))) + if (unlikely((hub_port < 0) || (hub_port > MAX_USB_HUB_PORT))) return -EINVAL; /* Find a free pipe */ @@ -1783,7 +1781,7 @@ static void __cvmx_usb_schedule(cvmx_usb_internal_state_t *usb, int is_sof) /* Find an idle channel */ CVMX_CLZ(channel, usb->idle_hardware_channels); channel = 31 - channel; - if (cvmx_unlikely(channel > 7)) + if (unlikely(channel > 7)) break; /* Find a pipe needing service */ @@ -1793,12 +1791,12 @@ static void __cvmx_usb_schedule(cvmx_usb_internal_state_t *usb, int is_sof) sure that the periodic data is sent in the beginning of the frame */ pipe = __cvmx_usb_find_ready_pipe(usb, usb->active_pipes + CVMX_USB_TRANSFER_ISOCHRONOUS, usb->frame_number); - if (cvmx_likely(!pipe)) + if (likely(!pipe)) pipe = __cvmx_usb_find_ready_pipe(usb, usb->active_pipes + CVMX_USB_TRANSFER_INTERRUPT, usb->frame_number); } - if (cvmx_likely(!pipe)) { + if (likely(!pipe)) { pipe = __cvmx_usb_find_ready_pipe(usb, usb->active_pipes + CVMX_USB_TRANSFER_CONTROL, usb->frame_number); - if (cvmx_likely(!pipe)) + if (likely(!pipe)) pipe = __cvmx_usb_find_ready_pipe(usb, usb->active_pipes + CVMX_USB_TRANSFER_BULK, usb->frame_number); } if (!pipe) @@ -1896,7 +1894,7 @@ static void __cvmx_usb_perform_complete(cvmx_usb_internal_state_t * usb, /* Isochronous transactions need extra processing as they might not be done after a single data transfer */ - if (cvmx_unlikely(transaction->type == CVMX_USB_TRANSFER_ISOCHRONOUS)) { + if (unlikely(transaction->type == CVMX_USB_TRANSFER_ISOCHRONOUS)) { /* Update the number of bytes transferred in this ISO packet */ transaction->iso_packets[0].length = transaction->actual_bytes; transaction->iso_packets[0].status = complete_code; @@ -1979,16 +1977,16 @@ static int __cvmx_usb_submit_transaction(cvmx_usb_internal_state_t *usb, cvmx_usb_transaction_t *transaction; cvmx_usb_pipe_t *pipe = usb->pipe + pipe_handle; - if (cvmx_unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES))) + if (unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES))) return -EINVAL; /* Fail if the pipe isn't open */ - if (cvmx_unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0)) + if (unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0)) return -EINVAL; - if (cvmx_unlikely(pipe->transfer_type != type)) + if (unlikely(pipe->transfer_type != type)) return -EINVAL; transaction = __cvmx_usb_alloc_transaction(usb); - if (cvmx_unlikely(!transaction)) + if (unlikely(!transaction)) return -ENOMEM; transaction->type = type; @@ -2071,9 +2069,9 @@ int cvmx_usb_submit_bulk(cvmx_usb_state_t *state, int pipe_handle, cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; /* Pipe handle checking is done later in a common place */ - if (cvmx_unlikely(!buffer)) + if (unlikely(!buffer)) return -EINVAL; - if (cvmx_unlikely(buffer_length < 0)) + if (unlikely(buffer_length < 0)) return -EINVAL; submit_handle = __cvmx_usb_submit_transaction(usb, pipe_handle, @@ -2130,9 +2128,9 @@ int cvmx_usb_submit_interrupt(cvmx_usb_state_t *state, int pipe_handle, cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; /* Pipe handle checking is done later in a common place */ - if (cvmx_unlikely(!buffer)) + if (unlikely(!buffer)) return -EINVAL; - if (cvmx_unlikely(buffer_length < 0)) + if (unlikely(buffer_length < 0)) return -EINVAL; submit_handle = __cvmx_usb_submit_transaction(usb, pipe_handle, @@ -2195,12 +2193,12 @@ int cvmx_usb_submit_control(cvmx_usb_state_t *state, int pipe_handle, cvmx_usb_control_header_t *header = cvmx_phys_to_ptr(control_header); /* Pipe handle checking is done later in a common place */ - if (cvmx_unlikely(!control_header)) + if (unlikely(!control_header)) return -EINVAL; /* Some drivers send a buffer with a zero length. God only knows why */ - if (cvmx_unlikely(buffer && (buffer_length < 0))) + if (unlikely(buffer && (buffer_length < 0))) return -EINVAL; - if (cvmx_unlikely(!buffer && (buffer_length != 0))) + if (unlikely(!buffer && (buffer_length != 0))) return -EINVAL; if ((header->s.request_type & 0x80) == 0) buffer_length = cvmx_le16_to_cpu(header->s.length); @@ -2276,17 +2274,17 @@ int cvmx_usb_submit_isochronous(cvmx_usb_state_t *state, int pipe_handle, cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; /* Pipe handle checking is done later in a common place */ - if (cvmx_unlikely(start_frame < 0)) + if (unlikely(start_frame < 0)) return -EINVAL; - if (cvmx_unlikely(flags & ~(CVMX_USB_ISOCHRONOUS_FLAGS_ALLOW_SHORT | CVMX_USB_ISOCHRONOUS_FLAGS_ASAP))) + if (unlikely(flags & ~(CVMX_USB_ISOCHRONOUS_FLAGS_ALLOW_SHORT | CVMX_USB_ISOCHRONOUS_FLAGS_ASAP))) return -EINVAL; - if (cvmx_unlikely(number_packets < 1)) + if (unlikely(number_packets < 1)) return -EINVAL; - if (cvmx_unlikely(!packets)) + if (unlikely(!packets)) return -EINVAL; - if (cvmx_unlikely(!buffer)) + if (unlikely(!buffer)) return -EINVAL; - if (cvmx_unlikely(buffer_length < 0)) + if (unlikely(buffer_length < 0)) return -EINVAL; submit_handle = __cvmx_usb_submit_transaction(usb, pipe_handle, @@ -2326,19 +2324,19 @@ int cvmx_usb_cancel(cvmx_usb_state_t *state, int pipe_handle, int submit_handle) cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; cvmx_usb_pipe_t *pipe = usb->pipe + pipe_handle; - if (cvmx_unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES))) + if (unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES))) return -EINVAL; - if (cvmx_unlikely((submit_handle < 0) || (submit_handle >= MAX_TRANSACTIONS))) + if (unlikely((submit_handle < 0) || (submit_handle >= MAX_TRANSACTIONS))) return -EINVAL; /* Fail if the pipe isn't open */ - if (cvmx_unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0)) + if (unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0)) return -EINVAL; transaction = usb->transaction + submit_handle; /* Fail if this transaction already completed */ - if (cvmx_unlikely((transaction->flags & __CVMX_USB_TRANSACTION_FLAGS_IN_USE) == 0)) + if (unlikely((transaction->flags & __CVMX_USB_TRANSACTION_FLAGS_IN_USE) == 0)) return -EINVAL; /* If the transaction is the HEAD of the queue and scheduled. We need to @@ -2380,18 +2378,18 @@ int cvmx_usb_cancel_all(cvmx_usb_state_t *state, int pipe_handle) cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; cvmx_usb_pipe_t *pipe = usb->pipe + pipe_handle; - if (cvmx_unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES))) + if (unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES))) return -EINVAL; /* Fail if the pipe isn't open */ - if (cvmx_unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0)) + if (unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0)) return -EINVAL; /* Simply loop through and attempt to cancel each transaction */ while (pipe->head) { int result = cvmx_usb_cancel(state, pipe_handle, __cvmx_usb_get_submit_handle(usb, pipe->head)); - if (cvmx_unlikely(result != 0)) + if (unlikely(result != 0)) return result; } return 0; @@ -2414,15 +2412,15 @@ int cvmx_usb_close_pipe(cvmx_usb_state_t *state, int pipe_handle) cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; cvmx_usb_pipe_t *pipe = usb->pipe + pipe_handle; - if (cvmx_unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES))) + if (unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES))) return -EINVAL; /* Fail if the pipe isn't open */ - if (cvmx_unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0)) + if (unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0)) return -EINVAL; /* Fail if the pipe has pending transactions */ - if (cvmx_unlikely(pipe->head)) + if (unlikely(pipe->head)) return -EBUSY; pipe->flags = 0; @@ -2451,9 +2449,9 @@ int cvmx_usb_register_callback(cvmx_usb_state_t *state, { cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; - if (cvmx_unlikely(reason >= __CVMX_USB_CALLBACK_END)) + if (unlikely(reason >= __CVMX_USB_CALLBACK_END)) return -EINVAL; - if (cvmx_unlikely(!callback)) + if (unlikely(!callback)) return -EINVAL; usb->callback[reason] = callback; From 2e5ae89870a6a9898e88e56be2740c4656322288 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Mon, 29 Jul 2013 20:07:49 +0300 Subject: [PATCH 1044/3400] staging: octeon-usb: cvmx-usb: replace long udelays with mdelays Replace long udelays with mdelays. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.c b/drivers/staging/octeon-usb/cvmx-usb.c index efea87b98833..fadc695c7d56 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.c +++ b/drivers/staging/octeon-usb/cvmx-usb.c @@ -672,7 +672,7 @@ int cvmx_usb_initialize(cvmx_usb_state_t *state, int usb_port_number, __cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index), usbn_clk_ctl.u64); /* 4. Wait 1 ms for PHY clock to start */ - cvmx_wait_usec(1000); + mdelay(1); /* 5. Program the Reset input from automatic test equipment field in the USBP control and status register: USBN_USBP_CTL_STATUS[ATE_RESET] = 1 */ usbn_usbp_ctl_status.u64 = __cvmx_usb_read_csr64(usb, CVMX_USBNX_USBP_CTL_STATUS(usb->index)); @@ -879,7 +879,7 @@ int cvmx_usb_enable(cvmx_usb_state_t *state) /* Wait at least 50ms (high speed), or 10ms (full speed) for the reset process to complete. */ - cvmx_wait_usec(50000); + mdelay(50); /* Program the port reset bit to 0, USBC_HPRT[PRTRST] = 0 */ USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt_t, prtrst, 0); From ee7d14ce5ebd4f6588da19ae8c76261a4f77d652 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Mon, 29 Jul 2013 20:07:50 +0300 Subject: [PATCH 1045/3400] staging: octeon-usb: cvmx-usb: replace cvmx_wait_usec with udelay Just use udelay(). Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.c b/drivers/staging/octeon-usb/cvmx-usb.c index fadc695c7d56..906c7d8b2f1e 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.c +++ b/drivers/staging/octeon-usb/cvmx-usb.c @@ -68,7 +68,6 @@ #define CVMX_PREFETCH_PREF0(address, offset) CVMX_PREFETCH_PREFX(0, address, offset) #define CVMX_CLZ(result, input) asm ("clz %[rd],%[rs]" : [rd] "=d" (result) : [rs] "d" (input)) -#define cvmx_wait_usec udelay #define cvmx_le16_to_cpu le16_to_cpu #define MAX_RETRIES 3 /* Maximum number of times to retry failed transactions */ @@ -698,7 +697,7 @@ int cvmx_usb_initialize(cvmx_usb_state_t *state, int usb_port_number, __cvmx_usb_write_csr64(usb, CVMX_USBNX_USBP_CTL_STATUS(usb->index), usbn_usbp_ctl_status.u64); /* 10. Wait 1 us */ - cvmx_wait_usec(1); + udelay(1); /* 11. Program the hreset_n field in the USBN clock-control register: USBN_CLK_CTL[HRST] = 1 */ usbn_clk_ctl.s.hrst = 1; @@ -708,7 +707,7 @@ int cvmx_usb_initialize(cvmx_usb_state_t *state, int usb_port_number, usbn_clk_ctl.s.enable = 1; __cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index), usbn_clk_ctl.u64); - cvmx_wait_usec(1); + udelay(1); /* USB Core Initialization */ From 5645bcf98b80280d4b73f314af9caa311add2fa7 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Mon, 29 Jul 2013 20:07:51 +0300 Subject: [PATCH 1046/3400] staging: octeon-usb: cvmx-usb: replace cvmx_le16_to_cpu with le16_to_cpu Replace cvmx_le16_to_cpu() with le16_to_cpu(). Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.c b/drivers/staging/octeon-usb/cvmx-usb.c index 906c7d8b2f1e..49a1794998e8 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.c +++ b/drivers/staging/octeon-usb/cvmx-usb.c @@ -68,8 +68,6 @@ #define CVMX_PREFETCH_PREF0(address, offset) CVMX_PREFETCH_PREFX(0, address, offset) #define CVMX_CLZ(result, input) asm ("clz %[rd],%[rs]" : [rd] "=d" (result) : [rs] "d" (input)) -#define cvmx_le16_to_cpu le16_to_cpu - #define MAX_RETRIES 3 /* Maximum number of times to retry failed transactions */ #define MAX_PIPES 32 /* Maximum number of pipes that can be open at once */ #define MAX_TRANSACTIONS 256 /* Maximum number of outstanding transactions across all pipes */ @@ -2200,7 +2198,7 @@ int cvmx_usb_submit_control(cvmx_usb_state_t *state, int pipe_handle, if (unlikely(!buffer && (buffer_length != 0))) return -EINVAL; if ((header->s.request_type & 0x80) == 0) - buffer_length = cvmx_le16_to_cpu(header->s.length); + buffer_length = le16_to_cpu(header->s.length); submit_handle = __cvmx_usb_submit_transaction(usb, pipe_handle, CVMX_USB_TRANSFER_CONTROL, From 95e67a7a29b56b5012f3dd4e01b8f5ebfa7b2b75 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Mon, 29 Jul 2013 20:07:52 +0300 Subject: [PATCH 1047/3400] staging: octeon-usb: cvmx-usb: delete __cvmx_usb_complete_to_string() Delete a redundant function. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.c | 28 --------------------------- 1 file changed, 28 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.c b/drivers/staging/octeon-usb/cvmx-usb.c index 49a1794998e8..976ba1970b90 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.c +++ b/drivers/staging/octeon-usb/cvmx-usb.c @@ -324,34 +324,6 @@ static inline void __cvmx_usb_write_csr64(cvmx_usb_internal_state_t *usb, cvmx_write64_uint64(address, value); } - -/** - * @INTERNAL - * Utility function to convert complete codes into strings - * - * @param complete_code - * Code to convert - * - * @return Human readable string - */ -static const char *__cvmx_usb_complete_to_string(cvmx_usb_complete_t complete_code) -{ - switch (complete_code) - { - case CVMX_USB_COMPLETE_SUCCESS: return "SUCCESS"; - case CVMX_USB_COMPLETE_SHORT: return "SHORT"; - case CVMX_USB_COMPLETE_CANCEL: return "CANCEL"; - case CVMX_USB_COMPLETE_ERROR: return "ERROR"; - case CVMX_USB_COMPLETE_STALL: return "STALL"; - case CVMX_USB_COMPLETE_XACTERR: return "XACTERR"; - case CVMX_USB_COMPLETE_DATATGLERR: return "DATATGLERR"; - case CVMX_USB_COMPLETE_BABBLEERR: return "BABBLEERR"; - case CVMX_USB_COMPLETE_FRAMEERR: return "FRAMEERR"; - } - return "Update __cvmx_usb_complete_to_string"; -} - - /** * @INTERNAL * Return non zero if this pipe connects to a non HIGH speed From eeb90cb28718d80fb55993f690f8e1aa21b90f06 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Mon, 29 Jul 2013 20:07:53 +0300 Subject: [PATCH 1048/3400] staging: octeon-usb: cvmx-usb: fix whitespace issues Fix most of the whitespace issues reported by checkpatch: - use tabs for indentation - brace placement vs. newlines - (foo_t*) -> (foo_t *) - i=0 -> i = 0 Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.c | 4034 ++++++++++++------------- 1 file changed, 1998 insertions(+), 2036 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.c b/drivers/staging/octeon-usb/cvmx-usb.c index 976ba1970b90..e8fad48b1bb5 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.c +++ b/drivers/staging/octeon-usb/cvmx-usb.c @@ -68,24 +68,24 @@ #define CVMX_PREFETCH_PREF0(address, offset) CVMX_PREFETCH_PREFX(0, address, offset) #define CVMX_CLZ(result, input) asm ("clz %[rd],%[rs]" : [rd] "=d" (result) : [rs] "d" (input)) -#define MAX_RETRIES 3 /* Maximum number of times to retry failed transactions */ -#define MAX_PIPES 32 /* Maximum number of pipes that can be open at once */ -#define MAX_TRANSACTIONS 256 /* Maximum number of outstanding transactions across all pipes */ -#define MAX_CHANNELS 8 /* Maximum number of hardware channels supported by the USB block */ -#define MAX_USB_ADDRESS 127 /* The highest valid USB device address */ -#define MAX_USB_ENDPOINT 15 /* The highest valid USB endpoint number */ -#define MAX_USB_HUB_PORT 15 /* The highest valid port number on a hub */ -#define MAX_TRANSFER_BYTES ((1<<19)-1) /* The low level hardware can transfer a maximum of this number of bytes in each transfer. The field is 19 bits wide */ -#define MAX_TRANSFER_PACKETS ((1<<10)-1) /* The low level hardware can transfer a maximum of this number of packets in each transfer. The field is 10 bits wide */ +#define MAX_RETRIES 3 /* Maximum number of times to retry failed transactions */ +#define MAX_PIPES 32 /* Maximum number of pipes that can be open at once */ +#define MAX_TRANSACTIONS 256 /* Maximum number of outstanding transactions across all pipes */ +#define MAX_CHANNELS 8 /* Maximum number of hardware channels supported by the USB block */ +#define MAX_USB_ADDRESS 127 /* The highest valid USB device address */ +#define MAX_USB_ENDPOINT 15 /* The highest valid USB endpoint number */ +#define MAX_USB_HUB_PORT 15 /* The highest valid port number on a hub */ +#define MAX_TRANSFER_BYTES ((1<<19)-1) /* The low level hardware can transfer a maximum of this number of bytes in each transfer. The field is 19 bits wide */ +#define MAX_TRANSFER_PACKETS ((1<<10)-1) /* The low level hardware can transfer a maximum of this number of packets in each transfer. The field is 10 bits wide */ /* These defines disable the normal read and write csr. This is so I can add - extra debug stuff to the usb specific version and I won't use the normal - version by mistake */ + extra debug stuff to the usb specific version and I won't use the normal + version by mistake */ #define cvmx_read_csr use_cvmx_usb_read_csr64_instead_of_cvmx_read_csr #define cvmx_write_csr use_cvmx_usb_write_csr64_instead_of_cvmx_write_csr typedef enum { - __CVMX_USB_TRANSACTION_FLAGS_IN_USE = 1<<16, + __CVMX_USB_TRANSACTION_FLAGS_IN_USE = 1<<16, } cvmx_usb_transaction_flags_t; enum { @@ -104,14 +104,14 @@ enum { * transaction with a simple clearing of bit 0. */ typedef enum { - CVMX_USB_STAGE_NON_CONTROL, - CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE, - CVMX_USB_STAGE_SETUP, - CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE, - CVMX_USB_STAGE_DATA, - CVMX_USB_STAGE_DATA_SPLIT_COMPLETE, - CVMX_USB_STAGE_STATUS, - CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE, + CVMX_USB_STAGE_NON_CONTROL, + CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE, + CVMX_USB_STAGE_SETUP, + CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE, + CVMX_USB_STAGE_DATA, + CVMX_USB_STAGE_DATA_SPLIT_COMPLETE, + CVMX_USB_STAGE_STATUS, + CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE, } cvmx_usb_stage_t; /** @@ -120,23 +120,23 @@ typedef enum { * of pending requests for a pipe. */ typedef struct cvmx_usb_transaction { - struct cvmx_usb_transaction *prev; /**< Transaction before this one in the pipe */ - struct cvmx_usb_transaction *next; /**< Transaction after this one in the pipe */ - cvmx_usb_transfer_t type; /**< Type of transaction, duplicated of the pipe */ - cvmx_usb_transaction_flags_t flags; /**< State flags for this transaction */ - uint64_t buffer; /**< User's physical buffer address to read/write */ - int buffer_length; /**< Size of the user's buffer in bytes */ - uint64_t control_header; /**< For control transactions, physical address of the 8 byte standard header */ - int iso_start_frame; /**< For ISO transactions, the starting frame number */ - int iso_number_packets; /**< For ISO transactions, the number of packets in the request */ - cvmx_usb_iso_packet_t *iso_packets; /**< For ISO transactions, the sub packets in the request */ - int xfersize; - int pktcnt; - int retries; - int actual_bytes; /**< Actual bytes transfer for this transaction */ - cvmx_usb_stage_t stage; /**< For control transactions, the current stage */ - cvmx_usb_callback_func_t callback; /**< User's callback function when complete */ - void *callback_data; /**< User's data */ + struct cvmx_usb_transaction *prev; /**< Transaction before this one in the pipe */ + struct cvmx_usb_transaction *next; /**< Transaction after this one in the pipe */ + cvmx_usb_transfer_t type; /**< Type of transaction, duplicated of the pipe */ + cvmx_usb_transaction_flags_t flags; /**< State flags for this transaction */ + uint64_t buffer; /**< User's physical buffer address to read/write */ + int buffer_length; /**< Size of the user's buffer in bytes */ + uint64_t control_header; /**< For control transactions, physical address of the 8 byte standard header */ + int iso_start_frame; /**< For ISO transactions, the starting frame number */ + int iso_number_packets; /**< For ISO transactions, the number of packets in the request */ + cvmx_usb_iso_packet_t *iso_packets; /**< For ISO transactions, the sub packets in the request */ + int xfersize; + int pktcnt; + int retries; + int actual_bytes; /**< Actual bytes transfer for this transaction */ + cvmx_usb_stage_t stage; /**< For control transactions, the current stage */ + cvmx_usb_callback_func_t callback; /**< User's callback function when complete */ + void *callback_data; /**< User's data */ } cvmx_usb_transaction_t; /** @@ -144,99 +144,98 @@ typedef struct cvmx_usb_transaction { * USB device. It contains a list of pending request to the device. */ typedef struct cvmx_usb_pipe { - struct cvmx_usb_pipe *prev; /**< Pipe before this one in the list */ - struct cvmx_usb_pipe *next; /**< Pipe after this one in the list */ - cvmx_usb_transaction_t *head; /**< The first pending transaction */ - cvmx_usb_transaction_t *tail; /**< The last pending transaction */ - uint64_t interval; /**< For periodic pipes, the interval between packets in frames */ - uint64_t next_tx_frame; /**< The next frame this pipe is allowed to transmit on */ - cvmx_usb_pipe_flags_t flags; /**< State flags for this pipe */ - cvmx_usb_speed_t device_speed; /**< Speed of device connected to this pipe */ - cvmx_usb_transfer_t transfer_type; /**< Type of transaction supported by this pipe */ - cvmx_usb_direction_t transfer_dir; /**< IN or OUT. Ignored for Control */ - int multi_count; /**< Max packet in a row for the device */ - uint16_t max_packet; /**< The device's maximum packet size in bytes */ - uint8_t device_addr; /**< USB device address at other end of pipe */ - uint8_t endpoint_num; /**< USB endpoint number at other end of pipe */ - uint8_t hub_device_addr; /**< Hub address this device is connected to */ - uint8_t hub_port; /**< Hub port this device is connected to */ - uint8_t pid_toggle; /**< This toggles between 0/1 on every packet send to track the data pid needed */ - uint8_t channel; /**< Hardware DMA channel for this pipe */ - int8_t split_sc_frame; /**< The low order bits of the frame number the split complete should be sent on */ + struct cvmx_usb_pipe *prev; /**< Pipe before this one in the list */ + struct cvmx_usb_pipe *next; /**< Pipe after this one in the list */ + cvmx_usb_transaction_t *head; /**< The first pending transaction */ + cvmx_usb_transaction_t *tail; /**< The last pending transaction */ + uint64_t interval; /**< For periodic pipes, the interval between packets in frames */ + uint64_t next_tx_frame; /**< The next frame this pipe is allowed to transmit on */ + cvmx_usb_pipe_flags_t flags; /**< State flags for this pipe */ + cvmx_usb_speed_t device_speed; /**< Speed of device connected to this pipe */ + cvmx_usb_transfer_t transfer_type; /**< Type of transaction supported by this pipe */ + cvmx_usb_direction_t transfer_dir; /**< IN or OUT. Ignored for Control */ + int multi_count; /**< Max packet in a row for the device */ + uint16_t max_packet; /**< The device's maximum packet size in bytes */ + uint8_t device_addr; /**< USB device address at other end of pipe */ + uint8_t endpoint_num; /**< USB endpoint number at other end of pipe */ + uint8_t hub_device_addr; /**< Hub address this device is connected to */ + uint8_t hub_port; /**< Hub port this device is connected to */ + uint8_t pid_toggle; /**< This toggles between 0/1 on every packet send to track the data pid needed */ + uint8_t channel; /**< Hardware DMA channel for this pipe */ + int8_t split_sc_frame; /**< The low order bits of the frame number the split complete should be sent on */ } cvmx_usb_pipe_t; typedef struct { - cvmx_usb_pipe_t *head; /**< Head of the list, or NULL if empty */ - cvmx_usb_pipe_t *tail; /**< Tail if the list, or NULL if empty */ + cvmx_usb_pipe_t *head; /**< Head of the list, or NULL if empty */ + cvmx_usb_pipe_t *tail; /**< Tail if the list, or NULL if empty */ } cvmx_usb_pipe_list_t; typedef struct { - struct { - int channel; - int size; - uint64_t address; - } entry[MAX_CHANNELS+1]; - int head; - int tail; + struct { + int channel; + int size; + uint64_t address; + } entry[MAX_CHANNELS+1]; + int head; + int tail; } cvmx_usb_tx_fifo_t; /** * The state of the USB block is stored in this structure */ typedef struct { - int init_flags; /**< Flags passed to initialize */ - int index; /**< Which USB block this is for */ - int idle_hardware_channels; /**< Bit set for every idle hardware channel */ - cvmx_usbcx_hprt_t usbcx_hprt; /**< Stored port status so we don't need to read a CSR to determine splits */ - cvmx_usb_pipe_t *pipe_for_channel[MAX_CHANNELS]; /**< Map channels to pipes */ - cvmx_usb_transaction_t *free_transaction_head; /**< List of free transactions head */ - cvmx_usb_transaction_t *free_transaction_tail; /**< List of free transactions tail */ - cvmx_usb_pipe_t pipe[MAX_PIPES]; /**< Storage for pipes */ - cvmx_usb_transaction_t transaction[MAX_TRANSACTIONS]; /**< Storage for transactions */ - cvmx_usb_callback_func_t callback[__CVMX_USB_CALLBACK_END]; /**< User global callbacks */ - void *callback_data[__CVMX_USB_CALLBACK_END]; /**< User data for each callback */ - int indent; /**< Used by debug output to indent functions */ - cvmx_usb_port_status_t port_status; /**< Last port status used for change notification */ - cvmx_usb_pipe_list_t free_pipes; /**< List of all pipes that are currently closed */ - cvmx_usb_pipe_list_t idle_pipes; /**< List of open pipes that have no transactions */ - cvmx_usb_pipe_list_t active_pipes[4]; /**< Active pipes indexed by transfer type */ - uint64_t frame_number; /**< Increments every SOF interrupt for time keeping */ - cvmx_usb_transaction_t *active_split; /**< Points to the current active split, or NULL */ - cvmx_usb_tx_fifo_t periodic; - cvmx_usb_tx_fifo_t nonperiodic; + int init_flags; /**< Flags passed to initialize */ + int index; /**< Which USB block this is for */ + int idle_hardware_channels; /**< Bit set for every idle hardware channel */ + cvmx_usbcx_hprt_t usbcx_hprt; /**< Stored port status so we don't need to read a CSR to determine splits */ + cvmx_usb_pipe_t *pipe_for_channel[MAX_CHANNELS]; /**< Map channels to pipes */ + cvmx_usb_transaction_t *free_transaction_head; /**< List of free transactions head */ + cvmx_usb_transaction_t *free_transaction_tail; /**< List of free transactions tail */ + cvmx_usb_pipe_t pipe[MAX_PIPES]; /**< Storage for pipes */ + cvmx_usb_transaction_t transaction[MAX_TRANSACTIONS]; /**< Storage for transactions */ + cvmx_usb_callback_func_t callback[__CVMX_USB_CALLBACK_END]; /**< User global callbacks */ + void *callback_data[__CVMX_USB_CALLBACK_END]; /**< User data for each callback */ + int indent; /**< Used by debug output to indent functions */ + cvmx_usb_port_status_t port_status; /**< Last port status used for change notification */ + cvmx_usb_pipe_list_t free_pipes; /**< List of all pipes that are currently closed */ + cvmx_usb_pipe_list_t idle_pipes; /**< List of open pipes that have no transactions */ + cvmx_usb_pipe_list_t active_pipes[4]; /**< Active pipes indexed by transfer type */ + uint64_t frame_number; /**< Increments every SOF interrupt for time keeping */ + cvmx_usb_transaction_t *active_split; /**< Points to the current active split, or NULL */ + cvmx_usb_tx_fifo_t periodic; + cvmx_usb_tx_fifo_t nonperiodic; } cvmx_usb_internal_state_t; /* This macro spins on a field waiting for it to reach a value */ #define CVMX_WAIT_FOR_FIELD32(address, type, field, op, value, timeout_usec)\ - ({int result; \ - do { \ - uint64_t done = cvmx_get_cycle() + (uint64_t)timeout_usec * \ - octeon_get_clock_rate() / 1000000; \ - type c; \ - while (1) \ - { \ - c.u32 = __cvmx_usb_read_csr32(usb, address); \ - if (c.s.field op (value)) { \ - result = 0; \ - break; \ - } else if (cvmx_get_cycle() > done) { \ - result = -1; \ - break; \ - } else \ - cvmx_wait(100); \ - } \ - } while (0); \ - result;}) + ({int result; \ + do { \ + uint64_t done = cvmx_get_cycle() + (uint64_t)timeout_usec * \ + octeon_get_clock_rate() / 1000000; \ + type c; \ + while (1) { \ + c.u32 = __cvmx_usb_read_csr32(usb, address); \ + if (c.s.field op (value)) { \ + result = 0; \ + break; \ + } else if (cvmx_get_cycle() > done) { \ + result = -1; \ + break; \ + } else \ + cvmx_wait(100); \ + } \ + } while (0); \ + result; }) /* This macro logically sets a single field in a CSR. It does the sequence - read, modify, and write */ -#define USB_SET_FIELD32(address, type, field, value)\ - do { \ - type c; \ - c.u32 = __cvmx_usb_read_csr32(usb, address);\ - c.s.field = value; \ - __cvmx_usb_write_csr32(usb, address, c.u32);\ - } while (0) + read, modify, and write */ +#define USB_SET_FIELD32(address, type, field, value) \ + do { \ + type c; \ + c.u32 = __cvmx_usb_read_csr32(usb, address); \ + c.s.field = value; \ + __cvmx_usb_write_csr32(usb, address, c.u32); \ + } while (0) /* Returns the IO address to push/pop stuff data from the FIFOs */ #define USB_FIFO_ADDRESS(channel, usb_index) (CVMX_USBCX_GOTGCTL(usb_index) + ((channel)+1)*0x1000) @@ -266,10 +265,10 @@ static int octeon_usb_get_clock_type(void) * @return Result of the read */ static inline uint32_t __cvmx_usb_read_csr32(cvmx_usb_internal_state_t *usb, - uint64_t address) + uint64_t address) { - uint32_t result = cvmx_read64_uint32(address ^ 4); - return result; + uint32_t result = cvmx_read64_uint32(address ^ 4); + return result; } @@ -284,10 +283,10 @@ static inline uint32_t __cvmx_usb_read_csr32(cvmx_usb_internal_state_t *usb, * @param value Value to write */ static inline void __cvmx_usb_write_csr32(cvmx_usb_internal_state_t *usb, - uint64_t address, uint32_t value) + uint64_t address, uint32_t value) { - cvmx_write64_uint32(address ^ 4, value); - cvmx_read64_uint64(CVMX_USBNX_DMA0_INB_CHN0(usb->index)); + cvmx_write64_uint32(address ^ 4, value); + cvmx_read64_uint64(CVMX_USBNX_DMA0_INB_CHN0(usb->index)); } @@ -302,10 +301,10 @@ static inline void __cvmx_usb_write_csr32(cvmx_usb_internal_state_t *usb, * @return Result of the read */ static inline uint64_t __cvmx_usb_read_csr64(cvmx_usb_internal_state_t *usb, - uint64_t address) + uint64_t address) { - uint64_t result = cvmx_read64_uint64(address); - return result; + uint64_t result = cvmx_read64_uint64(address); + return result; } @@ -319,9 +318,9 @@ static inline uint64_t __cvmx_usb_read_csr64(cvmx_usb_internal_state_t *usb, * @param value Value to write */ static inline void __cvmx_usb_write_csr64(cvmx_usb_internal_state_t *usb, - uint64_t address, uint64_t value) + uint64_t address, uint64_t value) { - cvmx_write64_uint64(address, value); + cvmx_write64_uint64(address, value); } /** @@ -336,7 +335,7 @@ static inline void __cvmx_usb_write_csr64(cvmx_usb_internal_state_t *usb, */ static inline int __cvmx_usb_pipe_needs_split(cvmx_usb_internal_state_t *usb, cvmx_usb_pipe_t *pipe) { - return ((pipe->device_speed != CVMX_USB_SPEED_HIGH) && (usb->usbcx_hprt.s.prtspd == CVMX_USB_SPEED_HIGH)); + return ((pipe->device_speed != CVMX_USB_SPEED_HIGH) && (usb->usbcx_hprt.s.prtspd == CVMX_USB_SPEED_HIGH)); } @@ -350,10 +349,10 @@ static inline int __cvmx_usb_pipe_needs_split(cvmx_usb_internal_state_t *usb, cv */ static inline int __cvmx_usb_get_data_pid(cvmx_usb_pipe_t *pipe) { - if (pipe->pid_toggle) - return 2; /* Data1 */ - else - return 0; /* Data0 */ + if (pipe->pid_toggle) + return 2; /* Data1 */ + else + return 0; /* Data0 */ } @@ -369,22 +368,22 @@ static inline int __cvmx_usb_get_data_pid(cvmx_usb_pipe_t *pipe) */ int cvmx_usb_get_num_ports(void) { - int arch_ports = 0; + int arch_ports = 0; - if (OCTEON_IS_MODEL(OCTEON_CN56XX)) - arch_ports = 1; - else if (OCTEON_IS_MODEL(OCTEON_CN52XX)) - arch_ports = 2; - else if (OCTEON_IS_MODEL(OCTEON_CN50XX)) - arch_ports = 1; - else if (OCTEON_IS_MODEL(OCTEON_CN31XX)) - arch_ports = 1; - else if (OCTEON_IS_MODEL(OCTEON_CN30XX)) - arch_ports = 1; - else - arch_ports = 0; + if (OCTEON_IS_MODEL(OCTEON_CN56XX)) + arch_ports = 1; + else if (OCTEON_IS_MODEL(OCTEON_CN52XX)) + arch_ports = 2; + else if (OCTEON_IS_MODEL(OCTEON_CN50XX)) + arch_ports = 1; + else if (OCTEON_IS_MODEL(OCTEON_CN31XX)) + arch_ports = 1; + else if (OCTEON_IS_MODEL(OCTEON_CN30XX)) + arch_ports = 1; + else + arch_ports = 0; - return arch_ports; + return arch_ports; } @@ -392,25 +391,25 @@ int cvmx_usb_get_num_ports(void) * @INTERNAL * Allocate a usb transaction for use * - * @param usb USB device state populated by - * cvmx_usb_initialize(). + * @param usb USB device state populated by + * cvmx_usb_initialize(). * * @return Transaction or NULL */ static inline cvmx_usb_transaction_t *__cvmx_usb_alloc_transaction(cvmx_usb_internal_state_t *usb) { - cvmx_usb_transaction_t *t; - t = usb->free_transaction_head; - if (t) { - usb->free_transaction_head = t->next; - if (!usb->free_transaction_head) - usb->free_transaction_tail = NULL; - } - if (t) { - memset(t, 0, sizeof(*t)); - t->flags = __CVMX_USB_TRANSACTION_FLAGS_IN_USE; - } - return t; + cvmx_usb_transaction_t *t; + t = usb->free_transaction_head; + if (t) { + usb->free_transaction_head = t->next; + if (!usb->free_transaction_head) + usb->free_transaction_tail = NULL; + } + if (t) { + memset(t, 0, sizeof(*t)); + t->flags = __CVMX_USB_TRANSACTION_FLAGS_IN_USE; + } + return t; } @@ -418,22 +417,22 @@ static inline cvmx_usb_transaction_t *__cvmx_usb_alloc_transaction(cvmx_usb_inte * @INTERNAL * Free a usb transaction * - * @param usb USB device state populated by - * cvmx_usb_initialize(). + * @param usb USB device state populated by + * cvmx_usb_initialize(). * @param transaction - * Transaction to free + * Transaction to free */ static inline void __cvmx_usb_free_transaction(cvmx_usb_internal_state_t *usb, - cvmx_usb_transaction_t *transaction) + cvmx_usb_transaction_t *transaction) { - transaction->flags = 0; - transaction->prev = NULL; - transaction->next = NULL; - if (usb->free_transaction_tail) - usb->free_transaction_tail->next = transaction; - else - usb->free_transaction_head = transaction; - usb->free_transaction_tail = transaction; + transaction->flags = 0; + transaction->prev = NULL; + transaction->next = NULL; + if (usb->free_transaction_tail) + usb->free_transaction_tail->next = transaction; + else + usb->free_transaction_head = transaction; + usb->free_transaction_tail = transaction; } @@ -445,13 +444,13 @@ static inline void __cvmx_usb_free_transaction(cvmx_usb_internal_state_t *usb, */ static inline void __cvmx_usb_append_pipe(cvmx_usb_pipe_list_t *list, cvmx_usb_pipe_t *pipe) { - pipe->next = NULL; - pipe->prev = list->tail; - if (list->tail) - list->tail->next = pipe; - else - list->head = pipe; - list->tail = pipe; + pipe->next = NULL; + pipe->prev = list->tail; + if (list->tail) + list->tail->next = pipe; + else + list->head = pipe; + list->tail = pipe; } @@ -463,25 +462,23 @@ static inline void __cvmx_usb_append_pipe(cvmx_usb_pipe_list_t *list, cvmx_usb_p */ static inline void __cvmx_usb_remove_pipe(cvmx_usb_pipe_list_t *list, cvmx_usb_pipe_t *pipe) { - if (list->head == pipe) { - list->head = pipe->next; - pipe->next = NULL; - if (list->head) - list->head->prev = NULL; - else - list->tail = NULL; - } - else if (list->tail == pipe) { - list->tail = pipe->prev; - list->tail->next = NULL; - pipe->prev = NULL; - } - else { - pipe->prev->next = pipe->next; - pipe->next->prev = pipe->prev; - pipe->prev = NULL; - pipe->next = NULL; - } + if (list->head == pipe) { + list->head = pipe->next; + pipe->next = NULL; + if (list->head) + list->head->prev = NULL; + else + list->tail = NULL; + } else if (list->tail == pipe) { + list->tail = pipe->prev; + list->tail->next = NULL; + pipe->prev = NULL; + } else { + pipe->prev->next = pipe->next; + pipe->next->prev = pipe->prev; + pipe->prev = NULL; + pipe->next = NULL; + } } @@ -491,293 +488,290 @@ static inline void __cvmx_usb_remove_pipe(cvmx_usb_pipe_list_t *list, cvmx_usb_p * off in the disabled state. * * @param state Pointer to an empty cvmx_usb_state_t structure - * that will be populated by the initialize call. - * This structure is then passed to all other USB - * functions. + * that will be populated by the initialize call. + * This structure is then passed to all other USB + * functions. * @param usb_port_number - * Which Octeon USB port to initialize. + * Which Octeon USB port to initialize. * @param flags Flags to control hardware initialization. See - * cvmx_usb_initialize_flags_t for the flag - * definitions. Some flags are mandatory. + * cvmx_usb_initialize_flags_t for the flag + * definitions. Some flags are mandatory. * * @return 0 or a negative error code. */ int cvmx_usb_initialize(cvmx_usb_state_t *state, int usb_port_number, cvmx_usb_initialize_flags_t flags) { - cvmx_usbnx_clk_ctl_t usbn_clk_ctl; - cvmx_usbnx_usbp_ctl_status_t usbn_usbp_ctl_status; - cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; + cvmx_usbnx_clk_ctl_t usbn_clk_ctl; + cvmx_usbnx_usbp_ctl_status_t usbn_usbp_ctl_status; + cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; - usb->init_flags = flags; + usb->init_flags = flags; - /* Make sure that state is large enough to store the internal state */ - if (sizeof(*state) < sizeof(*usb)) - return -EINVAL; - /* At first allow 0-1 for the usb port number */ - if ((usb_port_number < 0) || (usb_port_number > 1)) - return -EINVAL; - /* For all chips except 52XX there is only one port */ - if (!OCTEON_IS_MODEL(OCTEON_CN52XX) && (usb_port_number > 0)) - return -EINVAL; - /* Try to determine clock type automatically */ - if ((flags & (CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI | - CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND)) == 0) { - if (octeon_usb_get_clock_type() == USB_CLOCK_TYPE_CRYSTAL_12) - flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI; /* Only 12 MHZ crystals are supported */ - else - flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND; - } + /* Make sure that state is large enough to store the internal state */ + if (sizeof(*state) < sizeof(*usb)) + return -EINVAL; + /* At first allow 0-1 for the usb port number */ + if ((usb_port_number < 0) || (usb_port_number > 1)) + return -EINVAL; + /* For all chips except 52XX there is only one port */ + if (!OCTEON_IS_MODEL(OCTEON_CN52XX) && (usb_port_number > 0)) + return -EINVAL; + /* Try to determine clock type automatically */ + if ((flags & (CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI | + CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND)) == 0) { + if (octeon_usb_get_clock_type() == USB_CLOCK_TYPE_CRYSTAL_12) + flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI; /* Only 12 MHZ crystals are supported */ + else + flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND; + } - if (flags & CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND) { - /* Check for auto ref clock frequency */ - if (!(flags & CVMX_USB_INITIALIZE_FLAGS_CLOCK_MHZ_MASK)) - switch (octeon_usb_get_clock_type()) { - case USB_CLOCK_TYPE_REF_12: - flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ; - break; - case USB_CLOCK_TYPE_REF_24: - flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ; - break; - case USB_CLOCK_TYPE_REF_48: - flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ; - break; - default: - return -EINVAL; - break; - } - } + if (flags & CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND) { + /* Check for auto ref clock frequency */ + if (!(flags & CVMX_USB_INITIALIZE_FLAGS_CLOCK_MHZ_MASK)) + switch (octeon_usb_get_clock_type()) { + case USB_CLOCK_TYPE_REF_12: + flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ; + break; + case USB_CLOCK_TYPE_REF_24: + flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ; + break; + case USB_CLOCK_TYPE_REF_48: + flags |= CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ; + break; + default: + return -EINVAL; + break; + } + } - memset(usb, 0, sizeof(usb)); - usb->init_flags = flags; + memset(usb, 0, sizeof(usb)); + usb->init_flags = flags; - /* Initialize the USB state structure */ - { - int i; - usb->index = usb_port_number; + /* Initialize the USB state structure */ + { + int i; + usb->index = usb_port_number; - /* Initialize the transaction double linked list */ - usb->free_transaction_head = NULL; - usb->free_transaction_tail = NULL; - for (i=0; itransaction + i); - for (i=0; ifree_pipes, usb->pipe + i); - } + /* Initialize the transaction double linked list */ + usb->free_transaction_head = NULL; + usb->free_transaction_tail = NULL; + for (i = 0; i < MAX_TRANSACTIONS; i++) + __cvmx_usb_free_transaction(usb, usb->transaction + i); + for (i = 0; i < MAX_PIPES; i++) + __cvmx_usb_append_pipe(&usb->free_pipes, usb->pipe + i); + } - /* Power On Reset and PHY Initialization */ + /* Power On Reset and PHY Initialization */ - /* 1. Wait for DCOK to assert (nothing to do) */ - /* 2a. Write USBN0/1_CLK_CTL[POR] = 1 and - USBN0/1_CLK_CTL[HRST,PRST,HCLK_RST] = 0 */ - usbn_clk_ctl.u64 = __cvmx_usb_read_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index)); - usbn_clk_ctl.s.por = 1; - usbn_clk_ctl.s.hrst = 0; - usbn_clk_ctl.s.prst = 0; - usbn_clk_ctl.s.hclk_rst = 0; - usbn_clk_ctl.s.enable = 0; - /* 2b. Select the USB reference clock/crystal parameters by writing - appropriate values to USBN0/1_CLK_CTL[P_C_SEL, P_RTYPE, P_COM_ON] */ - if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND) { - /* The USB port uses 12/24/48MHz 2.5V board clock - source at USB_XO. USB_XI should be tied to GND. - Most Octeon evaluation boards require this setting */ - if (OCTEON_IS_MODEL(OCTEON_CN3XXX)) { - usbn_clk_ctl.cn31xx.p_rclk = 1; /* From CN31XX,CN30XX manual */ - usbn_clk_ctl.cn31xx.p_xenbn = 0; - } - else if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN50XX)) - usbn_clk_ctl.cn56xx.p_rtype = 2; /* From CN56XX,CN50XX manual */ - else - usbn_clk_ctl.cn52xx.p_rtype = 1; /* From CN52XX manual */ + /* 1. Wait for DCOK to assert (nothing to do) */ + /* 2a. Write USBN0/1_CLK_CTL[POR] = 1 and + USBN0/1_CLK_CTL[HRST,PRST,HCLK_RST] = 0 */ + usbn_clk_ctl.u64 = __cvmx_usb_read_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index)); + usbn_clk_ctl.s.por = 1; + usbn_clk_ctl.s.hrst = 0; + usbn_clk_ctl.s.prst = 0; + usbn_clk_ctl.s.hclk_rst = 0; + usbn_clk_ctl.s.enable = 0; + /* 2b. Select the USB reference clock/crystal parameters by writing + appropriate values to USBN0/1_CLK_CTL[P_C_SEL, P_RTYPE, P_COM_ON] */ + if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND) { + /* The USB port uses 12/24/48MHz 2.5V board clock + source at USB_XO. USB_XI should be tied to GND. + Most Octeon evaluation boards require this setting */ + if (OCTEON_IS_MODEL(OCTEON_CN3XXX)) { + usbn_clk_ctl.cn31xx.p_rclk = 1; /* From CN31XX,CN30XX manual */ + usbn_clk_ctl.cn31xx.p_xenbn = 0; + } else if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN50XX)) + usbn_clk_ctl.cn56xx.p_rtype = 2; /* From CN56XX,CN50XX manual */ + else + usbn_clk_ctl.cn52xx.p_rtype = 1; /* From CN52XX manual */ - switch (flags & CVMX_USB_INITIALIZE_FLAGS_CLOCK_MHZ_MASK) { - case CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ: - usbn_clk_ctl.s.p_c_sel = 0; - break; - case CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ: - usbn_clk_ctl.s.p_c_sel = 1; - break; - case CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ: - usbn_clk_ctl.s.p_c_sel = 2; - break; - } - } - else { - /* The USB port uses a 12MHz crystal as clock source - at USB_XO and USB_XI */ - if (OCTEON_IS_MODEL(OCTEON_CN3XXX)) { - usbn_clk_ctl.cn31xx.p_rclk = 1; /* From CN31XX,CN30XX manual */ - usbn_clk_ctl.cn31xx.p_xenbn = 1; - } - else if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN50XX)) - usbn_clk_ctl.cn56xx.p_rtype = 0; /* From CN56XX,CN50XX manual */ - else - usbn_clk_ctl.cn52xx.p_rtype = 0; /* From CN52XX manual */ + switch (flags & CVMX_USB_INITIALIZE_FLAGS_CLOCK_MHZ_MASK) { + case CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ: + usbn_clk_ctl.s.p_c_sel = 0; + break; + case CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ: + usbn_clk_ctl.s.p_c_sel = 1; + break; + case CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ: + usbn_clk_ctl.s.p_c_sel = 2; + break; + } + } else { + /* The USB port uses a 12MHz crystal as clock source + at USB_XO and USB_XI */ + if (OCTEON_IS_MODEL(OCTEON_CN3XXX)) { + usbn_clk_ctl.cn31xx.p_rclk = 1; /* From CN31XX,CN30XX manual */ + usbn_clk_ctl.cn31xx.p_xenbn = 1; + } else if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN50XX)) + usbn_clk_ctl.cn56xx.p_rtype = 0; /* From CN56XX,CN50XX manual */ + else + usbn_clk_ctl.cn52xx.p_rtype = 0; /* From CN52XX manual */ - usbn_clk_ctl.s.p_c_sel = 0; - } - /* 2c. Select the HCLK via writing USBN0/1_CLK_CTL[DIVIDE, DIVIDE2] and - setting USBN0/1_CLK_CTL[ENABLE] = 1. Divide the core clock down such - that USB is as close as possible to 125Mhz */ - { - int divisor = (octeon_get_clock_rate()+125000000-1)/125000000; - if (divisor < 4) /* Lower than 4 doesn't seem to work properly */ - divisor = 4; - usbn_clk_ctl.s.divide = divisor; - usbn_clk_ctl.s.divide2 = 0; - } - __cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index), - usbn_clk_ctl.u64); - /* 2d. Write USBN0/1_CLK_CTL[HCLK_RST] = 1 */ - usbn_clk_ctl.s.hclk_rst = 1; - __cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index), - usbn_clk_ctl.u64); - /* 2e. Wait 64 core-clock cycles for HCLK to stabilize */ - cvmx_wait(64); - /* 3. Program the power-on reset field in the USBN clock-control register: - USBN_CLK_CTL[POR] = 0 */ - usbn_clk_ctl.s.por = 0; - __cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index), - usbn_clk_ctl.u64); - /* 4. Wait 1 ms for PHY clock to start */ - mdelay(1); - /* 5. Program the Reset input from automatic test equipment field in the - USBP control and status register: USBN_USBP_CTL_STATUS[ATE_RESET] = 1 */ - usbn_usbp_ctl_status.u64 = __cvmx_usb_read_csr64(usb, CVMX_USBNX_USBP_CTL_STATUS(usb->index)); - usbn_usbp_ctl_status.s.ate_reset = 1; - __cvmx_usb_write_csr64(usb, CVMX_USBNX_USBP_CTL_STATUS(usb->index), - usbn_usbp_ctl_status.u64); - /* 6. Wait 10 cycles */ - cvmx_wait(10); - /* 7. Clear ATE_RESET field in the USBN clock-control register: - USBN_USBP_CTL_STATUS[ATE_RESET] = 0 */ - usbn_usbp_ctl_status.s.ate_reset = 0; - __cvmx_usb_write_csr64(usb, CVMX_USBNX_USBP_CTL_STATUS(usb->index), - usbn_usbp_ctl_status.u64); - /* 8. Program the PHY reset field in the USBN clock-control register: - USBN_CLK_CTL[PRST] = 1 */ - usbn_clk_ctl.s.prst = 1; - __cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index), - usbn_clk_ctl.u64); - /* 9. Program the USBP control and status register to select host or - device mode. USBN_USBP_CTL_STATUS[HST_MODE] = 0 for host, = 1 for - device */ - usbn_usbp_ctl_status.s.hst_mode = 0; - __cvmx_usb_write_csr64(usb, CVMX_USBNX_USBP_CTL_STATUS(usb->index), - usbn_usbp_ctl_status.u64); - /* 10. Wait 1 us */ - udelay(1); - /* 11. Program the hreset_n field in the USBN clock-control register: - USBN_CLK_CTL[HRST] = 1 */ - usbn_clk_ctl.s.hrst = 1; - __cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index), - usbn_clk_ctl.u64); - /* 12. Proceed to USB core initialization */ - usbn_clk_ctl.s.enable = 1; - __cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index), - usbn_clk_ctl.u64); - udelay(1); + usbn_clk_ctl.s.p_c_sel = 0; + } + /* 2c. Select the HCLK via writing USBN0/1_CLK_CTL[DIVIDE, DIVIDE2] and + setting USBN0/1_CLK_CTL[ENABLE] = 1. Divide the core clock down such + that USB is as close as possible to 125Mhz */ + { + int divisor = (octeon_get_clock_rate()+125000000-1)/125000000; + if (divisor < 4) /* Lower than 4 doesn't seem to work properly */ + divisor = 4; + usbn_clk_ctl.s.divide = divisor; + usbn_clk_ctl.s.divide2 = 0; + } + __cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index), + usbn_clk_ctl.u64); + /* 2d. Write USBN0/1_CLK_CTL[HCLK_RST] = 1 */ + usbn_clk_ctl.s.hclk_rst = 1; + __cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index), + usbn_clk_ctl.u64); + /* 2e. Wait 64 core-clock cycles for HCLK to stabilize */ + cvmx_wait(64); + /* 3. Program the power-on reset field in the USBN clock-control register: + USBN_CLK_CTL[POR] = 0 */ + usbn_clk_ctl.s.por = 0; + __cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index), + usbn_clk_ctl.u64); + /* 4. Wait 1 ms for PHY clock to start */ + mdelay(1); + /* 5. Program the Reset input from automatic test equipment field in the + USBP control and status register: USBN_USBP_CTL_STATUS[ATE_RESET] = 1 */ + usbn_usbp_ctl_status.u64 = __cvmx_usb_read_csr64(usb, CVMX_USBNX_USBP_CTL_STATUS(usb->index)); + usbn_usbp_ctl_status.s.ate_reset = 1; + __cvmx_usb_write_csr64(usb, CVMX_USBNX_USBP_CTL_STATUS(usb->index), + usbn_usbp_ctl_status.u64); + /* 6. Wait 10 cycles */ + cvmx_wait(10); + /* 7. Clear ATE_RESET field in the USBN clock-control register: + USBN_USBP_CTL_STATUS[ATE_RESET] = 0 */ + usbn_usbp_ctl_status.s.ate_reset = 0; + __cvmx_usb_write_csr64(usb, CVMX_USBNX_USBP_CTL_STATUS(usb->index), + usbn_usbp_ctl_status.u64); + /* 8. Program the PHY reset field in the USBN clock-control register: + USBN_CLK_CTL[PRST] = 1 */ + usbn_clk_ctl.s.prst = 1; + __cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index), + usbn_clk_ctl.u64); + /* 9. Program the USBP control and status register to select host or + device mode. USBN_USBP_CTL_STATUS[HST_MODE] = 0 for host, = 1 for + device */ + usbn_usbp_ctl_status.s.hst_mode = 0; + __cvmx_usb_write_csr64(usb, CVMX_USBNX_USBP_CTL_STATUS(usb->index), + usbn_usbp_ctl_status.u64); + /* 10. Wait 1 us */ + udelay(1); + /* 11. Program the hreset_n field in the USBN clock-control register: + USBN_CLK_CTL[HRST] = 1 */ + usbn_clk_ctl.s.hrst = 1; + __cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index), + usbn_clk_ctl.u64); + /* 12. Proceed to USB core initialization */ + usbn_clk_ctl.s.enable = 1; + __cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index), + usbn_clk_ctl.u64); + udelay(1); - /* USB Core Initialization */ + /* USB Core Initialization */ - /* 1. Read USBC_GHWCFG1, USBC_GHWCFG2, USBC_GHWCFG3, USBC_GHWCFG4 to - determine USB core configuration parameters. */ - /* Nothing needed */ - /* 2. Program the following fields in the global AHB configuration - register (USBC_GAHBCFG) - DMA mode, USBC_GAHBCFG[DMAEn]: 1 = DMA mode, 0 = slave mode - Burst length, USBC_GAHBCFG[HBSTLEN] = 0 - Nonperiodic TxFIFO empty level (slave mode only), - USBC_GAHBCFG[NPTXFEMPLVL] - Periodic TxFIFO empty level (slave mode only), - USBC_GAHBCFG[PTXFEMPLVL] - Global interrupt mask, USBC_GAHBCFG[GLBLINTRMSK] = 1 */ - { - cvmx_usbcx_gahbcfg_t usbcx_gahbcfg; - /* Due to an errata, CN31XX doesn't support DMA */ - if (OCTEON_IS_MODEL(OCTEON_CN31XX)) - usb->init_flags |= CVMX_USB_INITIALIZE_FLAGS_NO_DMA; - usbcx_gahbcfg.u32 = 0; - usbcx_gahbcfg.s.dmaen = !(usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA); - if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) - usb->idle_hardware_channels = 0x1; /* Only use one channel with non DMA */ - else if (OCTEON_IS_MODEL(OCTEON_CN5XXX)) - usb->idle_hardware_channels = 0xf7; /* CN5XXX have an errata with channel 3 */ - else - usb->idle_hardware_channels = 0xff; - usbcx_gahbcfg.s.hbstlen = 0; - usbcx_gahbcfg.s.nptxfemplvl = 1; - usbcx_gahbcfg.s.ptxfemplvl = 1; - usbcx_gahbcfg.s.glblintrmsk = 1; - __cvmx_usb_write_csr32(usb, CVMX_USBCX_GAHBCFG(usb->index), - usbcx_gahbcfg.u32); - } - /* 3. Program the following fields in USBC_GUSBCFG register. - HS/FS timeout calibration, USBC_GUSBCFG[TOUTCAL] = 0 - ULPI DDR select, USBC_GUSBCFG[DDRSEL] = 0 - USB turnaround time, USBC_GUSBCFG[USBTRDTIM] = 0x5 - PHY low-power clock select, USBC_GUSBCFG[PHYLPWRCLKSEL] = 0 */ - { - cvmx_usbcx_gusbcfg_t usbcx_gusbcfg; - usbcx_gusbcfg.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GUSBCFG(usb->index)); - usbcx_gusbcfg.s.toutcal = 0; - usbcx_gusbcfg.s.ddrsel = 0; - usbcx_gusbcfg.s.usbtrdtim = 0x5; - usbcx_gusbcfg.s.phylpwrclksel = 0; - __cvmx_usb_write_csr32(usb, CVMX_USBCX_GUSBCFG(usb->index), - usbcx_gusbcfg.u32); - } - /* 4. The software must unmask the following bits in the USBC_GINTMSK - register. - OTG interrupt mask, USBC_GINTMSK[OTGINTMSK] = 1 - Mode mismatch interrupt mask, USBC_GINTMSK[MODEMISMSK] = 1 */ - { - cvmx_usbcx_gintmsk_t usbcx_gintmsk; - int channel; + /* 1. Read USBC_GHWCFG1, USBC_GHWCFG2, USBC_GHWCFG3, USBC_GHWCFG4 to + determine USB core configuration parameters. */ + /* Nothing needed */ + /* 2. Program the following fields in the global AHB configuration + register (USBC_GAHBCFG) + DMA mode, USBC_GAHBCFG[DMAEn]: 1 = DMA mode, 0 = slave mode + Burst length, USBC_GAHBCFG[HBSTLEN] = 0 + Nonperiodic TxFIFO empty level (slave mode only), + USBC_GAHBCFG[NPTXFEMPLVL] + Periodic TxFIFO empty level (slave mode only), + USBC_GAHBCFG[PTXFEMPLVL] + Global interrupt mask, USBC_GAHBCFG[GLBLINTRMSK] = 1 */ + { + cvmx_usbcx_gahbcfg_t usbcx_gahbcfg; + /* Due to an errata, CN31XX doesn't support DMA */ + if (OCTEON_IS_MODEL(OCTEON_CN31XX)) + usb->init_flags |= CVMX_USB_INITIALIZE_FLAGS_NO_DMA; + usbcx_gahbcfg.u32 = 0; + usbcx_gahbcfg.s.dmaen = !(usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA); + if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) + usb->idle_hardware_channels = 0x1; /* Only use one channel with non DMA */ + else if (OCTEON_IS_MODEL(OCTEON_CN5XXX)) + usb->idle_hardware_channels = 0xf7; /* CN5XXX have an errata with channel 3 */ + else + usb->idle_hardware_channels = 0xff; + usbcx_gahbcfg.s.hbstlen = 0; + usbcx_gahbcfg.s.nptxfemplvl = 1; + usbcx_gahbcfg.s.ptxfemplvl = 1; + usbcx_gahbcfg.s.glblintrmsk = 1; + __cvmx_usb_write_csr32(usb, CVMX_USBCX_GAHBCFG(usb->index), + usbcx_gahbcfg.u32); + } + /* 3. Program the following fields in USBC_GUSBCFG register. + HS/FS timeout calibration, USBC_GUSBCFG[TOUTCAL] = 0 + ULPI DDR select, USBC_GUSBCFG[DDRSEL] = 0 + USB turnaround time, USBC_GUSBCFG[USBTRDTIM] = 0x5 + PHY low-power clock select, USBC_GUSBCFG[PHYLPWRCLKSEL] = 0 */ + { + cvmx_usbcx_gusbcfg_t usbcx_gusbcfg; + usbcx_gusbcfg.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GUSBCFG(usb->index)); + usbcx_gusbcfg.s.toutcal = 0; + usbcx_gusbcfg.s.ddrsel = 0; + usbcx_gusbcfg.s.usbtrdtim = 0x5; + usbcx_gusbcfg.s.phylpwrclksel = 0; + __cvmx_usb_write_csr32(usb, CVMX_USBCX_GUSBCFG(usb->index), + usbcx_gusbcfg.u32); + } + /* 4. The software must unmask the following bits in the USBC_GINTMSK + register. + OTG interrupt mask, USBC_GINTMSK[OTGINTMSK] = 1 + Mode mismatch interrupt mask, USBC_GINTMSK[MODEMISMSK] = 1 */ + { + cvmx_usbcx_gintmsk_t usbcx_gintmsk; + int channel; - usbcx_gintmsk.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GINTMSK(usb->index)); - usbcx_gintmsk.s.otgintmsk = 1; - usbcx_gintmsk.s.modemismsk = 1; - usbcx_gintmsk.s.hchintmsk = 1; - usbcx_gintmsk.s.sofmsk = 0; - /* We need RX FIFO interrupts if we don't have DMA */ - if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) - usbcx_gintmsk.s.rxflvlmsk = 1; - __cvmx_usb_write_csr32(usb, CVMX_USBCX_GINTMSK(usb->index), - usbcx_gintmsk.u32); + usbcx_gintmsk.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GINTMSK(usb->index)); + usbcx_gintmsk.s.otgintmsk = 1; + usbcx_gintmsk.s.modemismsk = 1; + usbcx_gintmsk.s.hchintmsk = 1; + usbcx_gintmsk.s.sofmsk = 0; + /* We need RX FIFO interrupts if we don't have DMA */ + if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) + usbcx_gintmsk.s.rxflvlmsk = 1; + __cvmx_usb_write_csr32(usb, CVMX_USBCX_GINTMSK(usb->index), + usbcx_gintmsk.u32); - /* Disable all channel interrupts. We'll enable them per channel later */ - for (channel=0; channel<8; channel++) - __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCINTMSKX(channel, usb->index), 0); - } + /* Disable all channel interrupts. We'll enable them per channel later */ + for (channel = 0; channel < 8; channel++) + __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCINTMSKX(channel, usb->index), 0); + } - { - /* Host Port Initialization */ + { + /* Host Port Initialization */ - /* 1. Program the host-port interrupt-mask field to unmask, - USBC_GINTMSK[PRTINT] = 1 */ - USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), cvmx_usbcx_gintmsk_t, - prtintmsk, 1); - USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), cvmx_usbcx_gintmsk_t, - disconnintmsk, 1); - /* 2. Program the USBC_HCFG register to select full-speed host or - high-speed host. */ - { - cvmx_usbcx_hcfg_t usbcx_hcfg; - usbcx_hcfg.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCFG(usb->index)); - usbcx_hcfg.s.fslssupp = 0; - usbcx_hcfg.s.fslspclksel = 0; - __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCFG(usb->index), usbcx_hcfg.u32); - } - /* 3. Program the port power bit to drive VBUS on the USB, - USBC_HPRT[PRTPWR] = 1 */ - USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt_t, prtpwr, 1); + /* 1. Program the host-port interrupt-mask field to unmask, + USBC_GINTMSK[PRTINT] = 1 */ + USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), cvmx_usbcx_gintmsk_t, + prtintmsk, 1); + USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), cvmx_usbcx_gintmsk_t, + disconnintmsk, 1); + /* 2. Program the USBC_HCFG register to select full-speed host or + high-speed host. */ + { + cvmx_usbcx_hcfg_t usbcx_hcfg; + usbcx_hcfg.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCFG(usb->index)); + usbcx_hcfg.s.fslssupp = 0; + usbcx_hcfg.s.fslspclksel = 0; + __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCFG(usb->index), usbcx_hcfg.u32); + } + /* 3. Program the port power bit to drive VBUS on the USB, + USBC_HPRT[PRTPWR] = 1 */ + USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt_t, prtpwr, 1); - /* Steps 4-15 from the manual are done later in the port enable */ - } + /* Steps 4-15 from the manual are done later in the port enable */ + } - return 0; + return 0; } @@ -787,33 +781,33 @@ int cvmx_usb_initialize(cvmx_usb_state_t *state, int usb_port_number, * function is called. * * @param state USB device state populated by - * cvmx_usb_initialize(). + * cvmx_usb_initialize(). * * @return 0 or a negative error code. */ int cvmx_usb_shutdown(cvmx_usb_state_t *state) { - cvmx_usbnx_clk_ctl_t usbn_clk_ctl; - cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; + cvmx_usbnx_clk_ctl_t usbn_clk_ctl; + cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; - /* Make sure all pipes are closed */ - if (usb->idle_pipes.head || - usb->active_pipes[CVMX_USB_TRANSFER_ISOCHRONOUS].head || - usb->active_pipes[CVMX_USB_TRANSFER_INTERRUPT].head || - usb->active_pipes[CVMX_USB_TRANSFER_CONTROL].head || - usb->active_pipes[CVMX_USB_TRANSFER_BULK].head) - return -EBUSY; + /* Make sure all pipes are closed */ + if (usb->idle_pipes.head || + usb->active_pipes[CVMX_USB_TRANSFER_ISOCHRONOUS].head || + usb->active_pipes[CVMX_USB_TRANSFER_INTERRUPT].head || + usb->active_pipes[CVMX_USB_TRANSFER_CONTROL].head || + usb->active_pipes[CVMX_USB_TRANSFER_BULK].head) + return -EBUSY; - /* Disable the clocks and put them in power on reset */ - usbn_clk_ctl.u64 = __cvmx_usb_read_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index)); - usbn_clk_ctl.s.enable = 1; - usbn_clk_ctl.s.por = 1; - usbn_clk_ctl.s.hclk_rst = 1; - usbn_clk_ctl.s.prst = 0; - usbn_clk_ctl.s.hrst = 0; - __cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index), - usbn_clk_ctl.u64); - return 0; + /* Disable the clocks and put them in power on reset */ + usbn_clk_ctl.u64 = __cvmx_usb_read_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index)); + usbn_clk_ctl.s.enable = 1; + usbn_clk_ctl.s.por = 1; + usbn_clk_ctl.s.hclk_rst = 1; + usbn_clk_ctl.s.prst = 0; + usbn_clk_ctl.s.hrst = 0; + __cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index), + usbn_clk_ctl.u64); + return 0; } @@ -822,79 +816,79 @@ int cvmx_usb_shutdown(cvmx_usb_state_t *state) * online and servicing requests. * * @param state USB device state populated by - * cvmx_usb_initialize(). + * cvmx_usb_initialize(). * * @return 0 or a negative error code. */ int cvmx_usb_enable(cvmx_usb_state_t *state) { - cvmx_usbcx_ghwcfg3_t usbcx_ghwcfg3; - cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; + cvmx_usbcx_ghwcfg3_t usbcx_ghwcfg3; + cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; - usb->usbcx_hprt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPRT(usb->index)); + usb->usbcx_hprt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPRT(usb->index)); - /* If the port is already enabled the just return. We don't need to do - anything */ - if (usb->usbcx_hprt.s.prtena) - return 0; + /* If the port is already enabled the just return. We don't need to do + anything */ + if (usb->usbcx_hprt.s.prtena) + return 0; - /* If there is nothing plugged into the port then fail immediately */ - if (!usb->usbcx_hprt.s.prtconnsts) { - return -ETIMEDOUT; - } + /* If there is nothing plugged into the port then fail immediately */ + if (!usb->usbcx_hprt.s.prtconnsts) { + return -ETIMEDOUT; + } - /* Program the port reset bit to start the reset process */ - USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt_t, prtrst, 1); + /* Program the port reset bit to start the reset process */ + USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt_t, prtrst, 1); - /* Wait at least 50ms (high speed), or 10ms (full speed) for the reset - process to complete. */ - mdelay(50); + /* Wait at least 50ms (high speed), or 10ms (full speed) for the reset + process to complete. */ + mdelay(50); - /* Program the port reset bit to 0, USBC_HPRT[PRTRST] = 0 */ - USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt_t, prtrst, 0); + /* Program the port reset bit to 0, USBC_HPRT[PRTRST] = 0 */ + USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt_t, prtrst, 0); - /* Wait for the USBC_HPRT[PRTENA]. */ - if (CVMX_WAIT_FOR_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt_t, - prtena, ==, 1, 100000)) - return -ETIMEDOUT; + /* Wait for the USBC_HPRT[PRTENA]. */ + if (CVMX_WAIT_FOR_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt_t, + prtena, ==, 1, 100000)) + return -ETIMEDOUT; - /* Read the port speed field to get the enumerated speed, USBC_HPRT[PRTSPD]. */ - usb->usbcx_hprt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPRT(usb->index)); - usbcx_ghwcfg3.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GHWCFG3(usb->index)); + /* Read the port speed field to get the enumerated speed, USBC_HPRT[PRTSPD]. */ + usb->usbcx_hprt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPRT(usb->index)); + usbcx_ghwcfg3.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GHWCFG3(usb->index)); - /* 13. Program the USBC_GRXFSIZ register to select the size of the receive - FIFO (25%). */ - USB_SET_FIELD32(CVMX_USBCX_GRXFSIZ(usb->index), cvmx_usbcx_grxfsiz_t, - rxfdep, usbcx_ghwcfg3.s.dfifodepth / 4); - /* 14. Program the USBC_GNPTXFSIZ register to select the size and the - start address of the non- periodic transmit FIFO for nonperiodic - transactions (50%). */ - { - cvmx_usbcx_gnptxfsiz_t siz; - siz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GNPTXFSIZ(usb->index)); - siz.s.nptxfdep = usbcx_ghwcfg3.s.dfifodepth / 2; - siz.s.nptxfstaddr = usbcx_ghwcfg3.s.dfifodepth / 4; - __cvmx_usb_write_csr32(usb, CVMX_USBCX_GNPTXFSIZ(usb->index), siz.u32); - } - /* 15. Program the USBC_HPTXFSIZ register to select the size and start - address of the periodic transmit FIFO for periodic transactions (25%). */ - { - cvmx_usbcx_hptxfsiz_t siz; - siz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPTXFSIZ(usb->index)); - siz.s.ptxfsize = usbcx_ghwcfg3.s.dfifodepth / 4; - siz.s.ptxfstaddr = 3 * usbcx_ghwcfg3.s.dfifodepth / 4; - __cvmx_usb_write_csr32(usb, CVMX_USBCX_HPTXFSIZ(usb->index), siz.u32); - } - /* Flush all FIFOs */ - USB_SET_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), cvmx_usbcx_grstctl_t, txfnum, 0x10); - USB_SET_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), cvmx_usbcx_grstctl_t, txfflsh, 1); - CVMX_WAIT_FOR_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), cvmx_usbcx_grstctl_t, - txfflsh, ==, 0, 100); - USB_SET_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), cvmx_usbcx_grstctl_t, rxfflsh, 1); - CVMX_WAIT_FOR_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), cvmx_usbcx_grstctl_t, - rxfflsh, ==, 0, 100); + /* 13. Program the USBC_GRXFSIZ register to select the size of the receive + FIFO (25%). */ + USB_SET_FIELD32(CVMX_USBCX_GRXFSIZ(usb->index), cvmx_usbcx_grxfsiz_t, + rxfdep, usbcx_ghwcfg3.s.dfifodepth / 4); + /* 14. Program the USBC_GNPTXFSIZ register to select the size and the + start address of the non- periodic transmit FIFO for nonperiodic + transactions (50%). */ + { + cvmx_usbcx_gnptxfsiz_t siz; + siz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GNPTXFSIZ(usb->index)); + siz.s.nptxfdep = usbcx_ghwcfg3.s.dfifodepth / 2; + siz.s.nptxfstaddr = usbcx_ghwcfg3.s.dfifodepth / 4; + __cvmx_usb_write_csr32(usb, CVMX_USBCX_GNPTXFSIZ(usb->index), siz.u32); + } + /* 15. Program the USBC_HPTXFSIZ register to select the size and start + address of the periodic transmit FIFO for periodic transactions (25%). */ + { + cvmx_usbcx_hptxfsiz_t siz; + siz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPTXFSIZ(usb->index)); + siz.s.ptxfsize = usbcx_ghwcfg3.s.dfifodepth / 4; + siz.s.ptxfstaddr = 3 * usbcx_ghwcfg3.s.dfifodepth / 4; + __cvmx_usb_write_csr32(usb, CVMX_USBCX_HPTXFSIZ(usb->index), siz.u32); + } + /* Flush all FIFOs */ + USB_SET_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), cvmx_usbcx_grstctl_t, txfnum, 0x10); + USB_SET_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), cvmx_usbcx_grstctl_t, txfflsh, 1); + CVMX_WAIT_FOR_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), cvmx_usbcx_grstctl_t, + txfflsh, ==, 0, 100); + USB_SET_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), cvmx_usbcx_grstctl_t, rxfflsh, 1); + CVMX_WAIT_FOR_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), cvmx_usbcx_grstctl_t, + rxfflsh, ==, 0, 100); - return 0; + return 0; } @@ -905,17 +899,17 @@ int cvmx_usb_enable(cvmx_usb_state_t *state) * associated callbacks. * * @param state USB device state populated by - * cvmx_usb_initialize(). + * cvmx_usb_initialize(). * * @return 0 or a negative error code. */ int cvmx_usb_disable(cvmx_usb_state_t *state) { - cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; + cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; - /* Disable the port */ - USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt_t, prtena, 1); - return 0; + /* Disable the port */ + USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt_t, prtena, 1); + return 0; } @@ -929,27 +923,27 @@ int cvmx_usb_disable(cvmx_usb_state_t *state) * them, you must update the status through cvmx_usb_set_status(). * * @param state USB device state populated by - * cvmx_usb_initialize(). + * cvmx_usb_initialize(). * * @return Port status information */ cvmx_usb_port_status_t cvmx_usb_get_status(cvmx_usb_state_t *state) { - cvmx_usbcx_hprt_t usbc_hprt; - cvmx_usb_port_status_t result; - cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; + cvmx_usbcx_hprt_t usbc_hprt; + cvmx_usb_port_status_t result; + cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; - memset(&result, 0, sizeof(result)); + memset(&result, 0, sizeof(result)); - usbc_hprt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPRT(usb->index)); - result.port_enabled = usbc_hprt.s.prtena; - result.port_over_current = usbc_hprt.s.prtovrcurract; - result.port_powered = usbc_hprt.s.prtpwr; - result.port_speed = usbc_hprt.s.prtspd; - result.connected = usbc_hprt.s.prtconnsts; - result.connect_change = (result.connected != usb->port_status.connected); + usbc_hprt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPRT(usb->index)); + result.port_enabled = usbc_hprt.s.prtena; + result.port_over_current = usbc_hprt.s.prtovrcurract; + result.port_powered = usbc_hprt.s.prtpwr; + result.port_speed = usbc_hprt.s.prtspd; + result.connected = usbc_hprt.s.prtconnsts; + result.connect_change = (result.connected != usb->port_status.connected); - return result; + return result; } @@ -961,15 +955,15 @@ cvmx_usb_port_status_t cvmx_usb_get_status(cvmx_usb_state_t *state) * changed through this call. * * @param state USB device state populated by - * cvmx_usb_initialize(). + * cvmx_usb_initialize(). * @param port_status - * Port status to set, most like returned by cvmx_usb_get_status() + * Port status to set, most like returned by cvmx_usb_get_status() */ void cvmx_usb_set_status(cvmx_usb_state_t *state, cvmx_usb_port_status_t port_status) { - cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; - usb->port_status = port_status; - return; + cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; + usb->port_status = port_status; + return; } @@ -978,17 +972,17 @@ void cvmx_usb_set_status(cvmx_usb_state_t *state, cvmx_usb_port_status_t port_st * Convert a USB transaction into a handle * * @param usb USB device state populated by - * cvmx_usb_initialize(). + * cvmx_usb_initialize(). * @param transaction - * Transaction to get handle for + * Transaction to get handle for * * @return Handle */ static inline int __cvmx_usb_get_submit_handle(cvmx_usb_internal_state_t *usb, - cvmx_usb_transaction_t *transaction) + cvmx_usb_transaction_t *transaction) { - return ((unsigned long)transaction - (unsigned long)usb->transaction) / - sizeof(*transaction); + return ((unsigned long)transaction - (unsigned long)usb->transaction) / + sizeof(*transaction); } @@ -997,15 +991,15 @@ static inline int __cvmx_usb_get_submit_handle(cvmx_usb_internal_state_t *usb, * Convert a USB pipe into a handle * * @param usb USB device state populated by - * cvmx_usb_initialize(). + * cvmx_usb_initialize(). * @param pipe Pipe to get handle for * * @return Handle */ static inline int __cvmx_usb_get_pipe_handle(cvmx_usb_internal_state_t *usb, - cvmx_usb_pipe_t *pipe) + cvmx_usb_pipe_t *pipe) { - return ((unsigned long)pipe - (unsigned long)usb->pipe) / sizeof(*pipe); + return ((unsigned long)pipe - (unsigned long)usb->pipe) / sizeof(*pipe); } @@ -1014,134 +1008,133 @@ static inline int __cvmx_usb_get_pipe_handle(cvmx_usb_internal_state_t *usb, * must be opened before data can be transferred between a device * and Octeon. * - * @param state USB device state populated by - * cvmx_usb_initialize(). - * @param flags Optional pipe flags defined in - * cvmx_usb_pipe_flags_t. + * @param state USB device state populated by + * cvmx_usb_initialize(). + * @param flags Optional pipe flags defined in + * cvmx_usb_pipe_flags_t. * @param device_addr - * USB device address to open the pipe to - * (0-127). + * USB device address to open the pipe to + * (0-127). * @param endpoint_num - * USB endpoint number to open the pipe to - * (0-15). + * USB endpoint number to open the pipe to + * (0-15). * @param device_speed - * The speed of the device the pipe is going - * to. This must match the device's speed, - * which may be different than the port speed. + * The speed of the device the pipe is going + * to. This must match the device's speed, + * which may be different than the port speed. * @param max_packet The maximum packet length the device can - * transmit/receive (low speed=0-8, full - * speed=0-1023, high speed=0-1024). This value - * comes from the standard endpoint descriptor - * field wMaxPacketSize bits <10:0>. + * transmit/receive (low speed=0-8, full + * speed=0-1023, high speed=0-1024). This value + * comes from the standard endpoint descriptor + * field wMaxPacketSize bits <10:0>. * @param transfer_type - * The type of transfer this pipe is for. + * The type of transfer this pipe is for. * @param transfer_dir - * The direction the pipe is in. This is not - * used for control pipes. + * The direction the pipe is in. This is not + * used for control pipes. * @param interval For ISOCHRONOUS and INTERRUPT transfers, - * this is how often the transfer is scheduled - * for. All other transfers should specify - * zero. The units are in frames (8000/sec at - * high speed, 1000/sec for full speed). + * this is how often the transfer is scheduled + * for. All other transfers should specify + * zero. The units are in frames (8000/sec at + * high speed, 1000/sec for full speed). * @param multi_count - * For high speed devices, this is the maximum - * allowed number of packet per microframe. - * Specify zero for non high speed devices. This - * value comes from the standard endpoint descriptor - * field wMaxPacketSize bits <12:11>. + * For high speed devices, this is the maximum + * allowed number of packet per microframe. + * Specify zero for non high speed devices. This + * value comes from the standard endpoint descriptor + * field wMaxPacketSize bits <12:11>. * @param hub_device_addr - * Hub device address this device is connected - * to. Devices connected directly to Octeon - * use zero. This is only used when the device - * is full/low speed behind a high speed hub. - * The address will be of the high speed hub, - * not and full speed hubs after it. + * Hub device address this device is connected + * to. Devices connected directly to Octeon + * use zero. This is only used when the device + * is full/low speed behind a high speed hub. + * The address will be of the high speed hub, + * not and full speed hubs after it. * @param hub_port Which port on the hub the device is - * connected. Use zero for devices connected - * directly to Octeon. Like hub_device_addr, - * this is only used for full/low speed - * devices behind a high speed hub. + * connected. Use zero for devices connected + * directly to Octeon. Like hub_device_addr, + * this is only used for full/low speed + * devices behind a high speed hub. * * @return A non negative value is a pipe handle. Negative - * values are error codes. + * values are error codes. */ int cvmx_usb_open_pipe(cvmx_usb_state_t *state, cvmx_usb_pipe_flags_t flags, - int device_addr, int endpoint_num, - cvmx_usb_speed_t device_speed, int max_packet, - cvmx_usb_transfer_t transfer_type, - cvmx_usb_direction_t transfer_dir, int interval, - int multi_count, int hub_device_addr, int hub_port) + int device_addr, int endpoint_num, + cvmx_usb_speed_t device_speed, int max_packet, + cvmx_usb_transfer_t transfer_type, + cvmx_usb_direction_t transfer_dir, int interval, + int multi_count, int hub_device_addr, int hub_port) { - cvmx_usb_pipe_t *pipe; - cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; + cvmx_usb_pipe_t *pipe; + cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; - if (unlikely((device_addr < 0) || (device_addr > MAX_USB_ADDRESS))) - return -EINVAL; - if (unlikely((endpoint_num < 0) || (endpoint_num > MAX_USB_ENDPOINT))) - return -EINVAL; - if (unlikely(device_speed > CVMX_USB_SPEED_LOW)) - return -EINVAL; - if (unlikely((max_packet <= 0) || (max_packet > 1024))) - return -EINVAL; - if (unlikely(transfer_type > CVMX_USB_TRANSFER_INTERRUPT)) - return -EINVAL; - if (unlikely((transfer_dir != CVMX_USB_DIRECTION_OUT) && - (transfer_dir != CVMX_USB_DIRECTION_IN))) - return -EINVAL; - if (unlikely(interval < 0)) - return -EINVAL; - if (unlikely((transfer_type == CVMX_USB_TRANSFER_CONTROL) && interval)) - return -EINVAL; - if (unlikely(multi_count < 0)) - return -EINVAL; - if (unlikely((device_speed != CVMX_USB_SPEED_HIGH) && - (multi_count != 0))) - return -EINVAL; - if (unlikely((hub_device_addr < 0) || (hub_device_addr > MAX_USB_ADDRESS))) - return -EINVAL; - if (unlikely((hub_port < 0) || (hub_port > MAX_USB_HUB_PORT))) - return -EINVAL; + if (unlikely((device_addr < 0) || (device_addr > MAX_USB_ADDRESS))) + return -EINVAL; + if (unlikely((endpoint_num < 0) || (endpoint_num > MAX_USB_ENDPOINT))) + return -EINVAL; + if (unlikely(device_speed > CVMX_USB_SPEED_LOW)) + return -EINVAL; + if (unlikely((max_packet <= 0) || (max_packet > 1024))) + return -EINVAL; + if (unlikely(transfer_type > CVMX_USB_TRANSFER_INTERRUPT)) + return -EINVAL; + if (unlikely((transfer_dir != CVMX_USB_DIRECTION_OUT) && + (transfer_dir != CVMX_USB_DIRECTION_IN))) + return -EINVAL; + if (unlikely(interval < 0)) + return -EINVAL; + if (unlikely((transfer_type == CVMX_USB_TRANSFER_CONTROL) && interval)) + return -EINVAL; + if (unlikely(multi_count < 0)) + return -EINVAL; + if (unlikely((device_speed != CVMX_USB_SPEED_HIGH) && + (multi_count != 0))) + return -EINVAL; + if (unlikely((hub_device_addr < 0) || (hub_device_addr > MAX_USB_ADDRESS))) + return -EINVAL; + if (unlikely((hub_port < 0) || (hub_port > MAX_USB_HUB_PORT))) + return -EINVAL; - /* Find a free pipe */ - pipe = usb->free_pipes.head; - if (!pipe) - return -ENOMEM; - __cvmx_usb_remove_pipe(&usb->free_pipes, pipe); - pipe->flags = flags | __CVMX_USB_PIPE_FLAGS_OPEN; - if ((device_speed == CVMX_USB_SPEED_HIGH) && - (transfer_dir == CVMX_USB_DIRECTION_OUT) && - (transfer_type == CVMX_USB_TRANSFER_BULK)) - pipe->flags |= __CVMX_USB_PIPE_FLAGS_NEED_PING; - pipe->device_addr = device_addr; - pipe->endpoint_num = endpoint_num; - pipe->device_speed = device_speed; - pipe->max_packet = max_packet; - pipe->transfer_type = transfer_type; - pipe->transfer_dir = transfer_dir; - /* All pipes use interval to rate limit NAK processing. Force an interval - if one wasn't supplied */ - if (!interval) - interval = 1; - if (__cvmx_usb_pipe_needs_split(usb, pipe)) { - pipe->interval = interval*8; - /* Force start splits to be schedule on uFrame 0 */ - pipe->next_tx_frame = ((usb->frame_number+7)&~7) + pipe->interval; - } - else { - pipe->interval = interval; - pipe->next_tx_frame = usb->frame_number + pipe->interval; - } - pipe->multi_count = multi_count; - pipe->hub_device_addr = hub_device_addr; - pipe->hub_port = hub_port; - pipe->pid_toggle = 0; - pipe->split_sc_frame = -1; - __cvmx_usb_append_pipe(&usb->idle_pipes, pipe); + /* Find a free pipe */ + pipe = usb->free_pipes.head; + if (!pipe) + return -ENOMEM; + __cvmx_usb_remove_pipe(&usb->free_pipes, pipe); + pipe->flags = flags | __CVMX_USB_PIPE_FLAGS_OPEN; + if ((device_speed == CVMX_USB_SPEED_HIGH) && + (transfer_dir == CVMX_USB_DIRECTION_OUT) && + (transfer_type == CVMX_USB_TRANSFER_BULK)) + pipe->flags |= __CVMX_USB_PIPE_FLAGS_NEED_PING; + pipe->device_addr = device_addr; + pipe->endpoint_num = endpoint_num; + pipe->device_speed = device_speed; + pipe->max_packet = max_packet; + pipe->transfer_type = transfer_type; + pipe->transfer_dir = transfer_dir; + /* All pipes use interval to rate limit NAK processing. Force an interval + if one wasn't supplied */ + if (!interval) + interval = 1; + if (__cvmx_usb_pipe_needs_split(usb, pipe)) { + pipe->interval = interval*8; + /* Force start splits to be schedule on uFrame 0 */ + pipe->next_tx_frame = ((usb->frame_number+7)&~7) + pipe->interval; + } else { + pipe->interval = interval; + pipe->next_tx_frame = usb->frame_number + pipe->interval; + } + pipe->multi_count = multi_count; + pipe->hub_device_addr = hub_device_addr; + pipe->hub_port = hub_port; + pipe->pid_toggle = 0; + pipe->split_sc_frame = -1; + __cvmx_usb_append_pipe(&usb->idle_pipes, pipe); - /* We don't need to tell the hardware about this pipe yet since - it doesn't have any submitted requests */ + /* We don't need to tell the hardware about this pipe yet since + it doesn't have any submitted requests */ - return __cvmx_usb_get_pipe_handle(usb, pipe); + return __cvmx_usb_get_pipe_handle(usb, pipe); } @@ -1151,43 +1144,43 @@ int cvmx_usb_open_pipe(cvmx_usb_state_t *state, cvmx_usb_pipe_flags_t flags, * in non DMA mode. It is very important that this function be called quickly * enough to prevent FIFO overflow. * - * @param usb USB device state populated by - * cvmx_usb_initialize(). + * @param usb USB device state populated by + * cvmx_usb_initialize(). */ static void __cvmx_usb_poll_rx_fifo(cvmx_usb_internal_state_t *usb) { - cvmx_usbcx_grxstsph_t rx_status; - int channel; - int bytes; - uint64_t address; - uint32_t *ptr; + cvmx_usbcx_grxstsph_t rx_status; + int channel; + int bytes; + uint64_t address; + uint32_t *ptr; - rx_status.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GRXSTSPH(usb->index)); - /* Only read data if IN data is there */ - if (rx_status.s.pktsts != 2) - return; - /* Check if no data is available */ - if (!rx_status.s.bcnt) - return; + rx_status.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GRXSTSPH(usb->index)); + /* Only read data if IN data is there */ + if (rx_status.s.pktsts != 2) + return; + /* Check if no data is available */ + if (!rx_status.s.bcnt) + return; - channel = rx_status.s.chnum; - bytes = rx_status.s.bcnt; - if (!bytes) - return; + channel = rx_status.s.chnum; + bytes = rx_status.s.bcnt; + if (!bytes) + return; - /* Get where the DMA engine would have written this data */ - address = __cvmx_usb_read_csr64(usb, CVMX_USBNX_DMA0_INB_CHN0(usb->index) + channel*8); - ptr = cvmx_phys_to_ptr(address); - __cvmx_usb_write_csr64(usb, CVMX_USBNX_DMA0_INB_CHN0(usb->index) + channel*8, address + bytes); + /* Get where the DMA engine would have written this data */ + address = __cvmx_usb_read_csr64(usb, CVMX_USBNX_DMA0_INB_CHN0(usb->index) + channel*8); + ptr = cvmx_phys_to_ptr(address); + __cvmx_usb_write_csr64(usb, CVMX_USBNX_DMA0_INB_CHN0(usb->index) + channel*8, address + bytes); - /* Loop writing the FIFO data for this packet into memory */ - while (bytes > 0) { - *ptr++ = __cvmx_usb_read_csr32(usb, USB_FIFO_ADDRESS(channel, usb->index)); - bytes -= 4; - } - CVMX_SYNCW; + /* Loop writing the FIFO data for this packet into memory */ + while (bytes > 0) { + *ptr++ = __cvmx_usb_read_csr32(usb, USB_FIFO_ADDRESS(channel, usb->index)); + bytes -= 4; + } + CVMX_SYNCW; - return; + return; } @@ -1195,85 +1188,85 @@ static void __cvmx_usb_poll_rx_fifo(cvmx_usb_internal_state_t *usb) * Fill the TX hardware fifo with data out of the software * fifos * - * @param usb USB device state populated by - * cvmx_usb_initialize(). - * @param fifo Software fifo to use + * @param usb USB device state populated by + * cvmx_usb_initialize(). + * @param fifo Software fifo to use * @param available Amount of space in the hardware fifo * * @return Non zero if the hardware fifo was too small and needs - * to be serviced again. + * to be serviced again. */ static int __cvmx_usb_fill_tx_hw(cvmx_usb_internal_state_t *usb, cvmx_usb_tx_fifo_t *fifo, int available) { - /* We're done either when there isn't anymore space or the software FIFO - is empty */ - while (available && (fifo->head != fifo->tail)) { - int i = fifo->tail; - const uint32_t *ptr = cvmx_phys_to_ptr(fifo->entry[i].address); - uint64_t csr_address = USB_FIFO_ADDRESS(fifo->entry[i].channel, usb->index) ^ 4; - int words = available; + /* We're done either when there isn't anymore space or the software FIFO + is empty */ + while (available && (fifo->head != fifo->tail)) { + int i = fifo->tail; + const uint32_t *ptr = cvmx_phys_to_ptr(fifo->entry[i].address); + uint64_t csr_address = USB_FIFO_ADDRESS(fifo->entry[i].channel, usb->index) ^ 4; + int words = available; - /* Limit the amount of data to waht the SW fifo has */ - if (fifo->entry[i].size <= available) { - words = fifo->entry[i].size; - fifo->tail++; - if (fifo->tail > MAX_CHANNELS) - fifo->tail = 0; - } + /* Limit the amount of data to waht the SW fifo has */ + if (fifo->entry[i].size <= available) { + words = fifo->entry[i].size; + fifo->tail++; + if (fifo->tail > MAX_CHANNELS) + fifo->tail = 0; + } - /* Update the next locations and counts */ - available -= words; - fifo->entry[i].address += words * 4; - fifo->entry[i].size -= words; + /* Update the next locations and counts */ + available -= words; + fifo->entry[i].address += words * 4; + fifo->entry[i].size -= words; - /* Write the HW fifo data. The read every three writes is due - to an errata on CN3XXX chips */ - while (words > 3) { - cvmx_write64_uint32(csr_address, *ptr++); - cvmx_write64_uint32(csr_address, *ptr++); - cvmx_write64_uint32(csr_address, *ptr++); - cvmx_read64_uint64(CVMX_USBNX_DMA0_INB_CHN0(usb->index)); - words -= 3; - } - cvmx_write64_uint32(csr_address, *ptr++); - if (--words) { - cvmx_write64_uint32(csr_address, *ptr++); - if (--words) - cvmx_write64_uint32(csr_address, *ptr++); - } - cvmx_read64_uint64(CVMX_USBNX_DMA0_INB_CHN0(usb->index)); - } - return fifo->head != fifo->tail; + /* Write the HW fifo data. The read every three writes is due + to an errata on CN3XXX chips */ + while (words > 3) { + cvmx_write64_uint32(csr_address, *ptr++); + cvmx_write64_uint32(csr_address, *ptr++); + cvmx_write64_uint32(csr_address, *ptr++); + cvmx_read64_uint64(CVMX_USBNX_DMA0_INB_CHN0(usb->index)); + words -= 3; + } + cvmx_write64_uint32(csr_address, *ptr++); + if (--words) { + cvmx_write64_uint32(csr_address, *ptr++); + if (--words) + cvmx_write64_uint32(csr_address, *ptr++); + } + cvmx_read64_uint64(CVMX_USBNX_DMA0_INB_CHN0(usb->index)); + } + return fifo->head != fifo->tail; } /** * Check the hardware FIFOs and fill them as needed * - * @param usb USB device state populated by - * cvmx_usb_initialize(). + * @param usb USB device state populated by + * cvmx_usb_initialize(). */ static void __cvmx_usb_poll_tx_fifo(cvmx_usb_internal_state_t *usb) { - if (usb->periodic.head != usb->periodic.tail) { - cvmx_usbcx_hptxsts_t tx_status; - tx_status.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPTXSTS(usb->index)); - if (__cvmx_usb_fill_tx_hw(usb, &usb->periodic, tx_status.s.ptxfspcavail)) - USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), cvmx_usbcx_gintmsk_t, ptxfempmsk, 1); - else - USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), cvmx_usbcx_gintmsk_t, ptxfempmsk, 0); - } + if (usb->periodic.head != usb->periodic.tail) { + cvmx_usbcx_hptxsts_t tx_status; + tx_status.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPTXSTS(usb->index)); + if (__cvmx_usb_fill_tx_hw(usb, &usb->periodic, tx_status.s.ptxfspcavail)) + USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), cvmx_usbcx_gintmsk_t, ptxfempmsk, 1); + else + USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), cvmx_usbcx_gintmsk_t, ptxfempmsk, 0); + } - if (usb->nonperiodic.head != usb->nonperiodic.tail) { - cvmx_usbcx_gnptxsts_t tx_status; - tx_status.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GNPTXSTS(usb->index)); - if (__cvmx_usb_fill_tx_hw(usb, &usb->nonperiodic, tx_status.s.nptxfspcavail)) - USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), cvmx_usbcx_gintmsk_t, nptxfempmsk, 1); - else - USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), cvmx_usbcx_gintmsk_t, nptxfempmsk, 0); - } + if (usb->nonperiodic.head != usb->nonperiodic.tail) { + cvmx_usbcx_gnptxsts_t tx_status; + tx_status.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GNPTXSTS(usb->index)); + if (__cvmx_usb_fill_tx_hw(usb, &usb->nonperiodic, tx_status.s.nptxfspcavail)) + USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), cvmx_usbcx_gintmsk_t, nptxfempmsk, 1); + else + USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), cvmx_usbcx_gintmsk_t, nptxfempmsk, 0); + } - return; + return; } @@ -1281,48 +1274,48 @@ static void __cvmx_usb_poll_tx_fifo(cvmx_usb_internal_state_t *usb) * @INTERNAL * Fill the TX FIFO with an outgoing packet * - * @param usb USB device state populated by - * cvmx_usb_initialize(). + * @param usb USB device state populated by + * cvmx_usb_initialize(). * @param channel Channel number to get packet from */ static void __cvmx_usb_fill_tx_fifo(cvmx_usb_internal_state_t *usb, int channel) { - cvmx_usbcx_hccharx_t hcchar; - cvmx_usbcx_hcspltx_t usbc_hcsplt; - cvmx_usbcx_hctsizx_t usbc_hctsiz; - cvmx_usb_tx_fifo_t *fifo; + cvmx_usbcx_hccharx_t hcchar; + cvmx_usbcx_hcspltx_t usbc_hcsplt; + cvmx_usbcx_hctsizx_t usbc_hctsiz; + cvmx_usb_tx_fifo_t *fifo; - /* We only need to fill data on outbound channels */ - hcchar.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index)); - if (hcchar.s.epdir != CVMX_USB_DIRECTION_OUT) - return; + /* We only need to fill data on outbound channels */ + hcchar.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index)); + if (hcchar.s.epdir != CVMX_USB_DIRECTION_OUT) + return; - /* OUT Splits only have data on the start and not the complete */ - usbc_hcsplt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCSPLTX(channel, usb->index)); - if (usbc_hcsplt.s.spltena && usbc_hcsplt.s.compsplt) - return; + /* OUT Splits only have data on the start and not the complete */ + usbc_hcsplt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCSPLTX(channel, usb->index)); + if (usbc_hcsplt.s.spltena && usbc_hcsplt.s.compsplt) + return; - /* Find out how many bytes we need to fill and convert it into 32bit words */ - usbc_hctsiz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index)); - if (!usbc_hctsiz.s.xfersize) - return; + /* Find out how many bytes we need to fill and convert it into 32bit words */ + usbc_hctsiz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index)); + if (!usbc_hctsiz.s.xfersize) + return; - if ((hcchar.s.eptype == CVMX_USB_TRANSFER_INTERRUPT) || - (hcchar.s.eptype == CVMX_USB_TRANSFER_ISOCHRONOUS)) - fifo = &usb->periodic; - else - fifo = &usb->nonperiodic; + if ((hcchar.s.eptype == CVMX_USB_TRANSFER_INTERRUPT) || + (hcchar.s.eptype == CVMX_USB_TRANSFER_ISOCHRONOUS)) + fifo = &usb->periodic; + else + fifo = &usb->nonperiodic; - fifo->entry[fifo->head].channel = channel; - fifo->entry[fifo->head].address = __cvmx_usb_read_csr64(usb, CVMX_USBNX_DMA0_OUTB_CHN0(usb->index) + channel*8); - fifo->entry[fifo->head].size = (usbc_hctsiz.s.xfersize+3)>>2; - fifo->head++; - if (fifo->head > MAX_CHANNELS) - fifo->head = 0; + fifo->entry[fifo->head].channel = channel; + fifo->entry[fifo->head].address = __cvmx_usb_read_csr64(usb, CVMX_USBNX_DMA0_OUTB_CHN0(usb->index) + channel*8); + fifo->entry[fifo->head].size = (usbc_hctsiz.s.xfersize+3)>>2; + fifo->head++; + if (fifo->head > MAX_CHANNELS) + fifo->head = 0; - __cvmx_usb_poll_tx_fifo(usb); + __cvmx_usb_poll_tx_fifo(usb); - return; + return; } /** @@ -1331,120 +1324,119 @@ static void __cvmx_usb_fill_tx_fifo(cvmx_usb_internal_state_t *usb, int channel) * the generic stuff will already have been done in * __cvmx_usb_start_channel() * - * @param usb USB device state populated by - * cvmx_usb_initialize(). + * @param usb USB device state populated by + * cvmx_usb_initialize(). * @param channel Channel to setup - * @param pipe Pipe for control transaction + * @param pipe Pipe for control transaction */ static void __cvmx_usb_start_channel_control(cvmx_usb_internal_state_t *usb, - int channel, - cvmx_usb_pipe_t *pipe) + int channel, + cvmx_usb_pipe_t *pipe) { - cvmx_usb_transaction_t *transaction = pipe->head; - cvmx_usb_control_header_t *header = cvmx_phys_to_ptr(transaction->control_header); - int bytes_to_transfer = transaction->buffer_length - transaction->actual_bytes; - int packets_to_transfer; - cvmx_usbcx_hctsizx_t usbc_hctsiz; + cvmx_usb_transaction_t *transaction = pipe->head; + cvmx_usb_control_header_t *header = cvmx_phys_to_ptr(transaction->control_header); + int bytes_to_transfer = transaction->buffer_length - transaction->actual_bytes; + int packets_to_transfer; + cvmx_usbcx_hctsizx_t usbc_hctsiz; - usbc_hctsiz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index)); + usbc_hctsiz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index)); - switch (transaction->stage) { - case CVMX_USB_STAGE_NON_CONTROL: - case CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE: - cvmx_dprintf("%s: ERROR - Non control stage\n", __FUNCTION__); - break; - case CVMX_USB_STAGE_SETUP: - usbc_hctsiz.s.pid = 3; /* Setup */ - bytes_to_transfer = sizeof(*header); - /* All Control operations start with a setup going OUT */ - USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), cvmx_usbcx_hccharx_t, epdir, CVMX_USB_DIRECTION_OUT); - /* Setup send the control header instead of the buffer data. The - buffer data will be used in the next stage */ - __cvmx_usb_write_csr64(usb, CVMX_USBNX_DMA0_OUTB_CHN0(usb->index) + channel*8, transaction->control_header); - break; - case CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE: - usbc_hctsiz.s.pid = 3; /* Setup */ - bytes_to_transfer = 0; - /* All Control operations start with a setup going OUT */ - USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), cvmx_usbcx_hccharx_t, epdir, CVMX_USB_DIRECTION_OUT); - USB_SET_FIELD32(CVMX_USBCX_HCSPLTX(channel, usb->index), cvmx_usbcx_hcspltx_t, compsplt, 1); - break; - case CVMX_USB_STAGE_DATA: - usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe); - if (__cvmx_usb_pipe_needs_split(usb, pipe)) { - if (header->s.request_type & 0x80) - bytes_to_transfer = 0; - else if (bytes_to_transfer > pipe->max_packet) - bytes_to_transfer = pipe->max_packet; - } - USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), - cvmx_usbcx_hccharx_t, epdir, - ((header->s.request_type & 0x80) ? - CVMX_USB_DIRECTION_IN : - CVMX_USB_DIRECTION_OUT)); - break; - case CVMX_USB_STAGE_DATA_SPLIT_COMPLETE: - usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe); - if (!(header->s.request_type & 0x80)) - bytes_to_transfer = 0; - USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), - cvmx_usbcx_hccharx_t, epdir, - ((header->s.request_type & 0x80) ? - CVMX_USB_DIRECTION_IN : - CVMX_USB_DIRECTION_OUT)); - USB_SET_FIELD32(CVMX_USBCX_HCSPLTX(channel, usb->index), cvmx_usbcx_hcspltx_t, compsplt, 1); - break; - case CVMX_USB_STAGE_STATUS: - usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe); - bytes_to_transfer = 0; - USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), cvmx_usbcx_hccharx_t, epdir, - ((header->s.request_type & 0x80) ? - CVMX_USB_DIRECTION_OUT : - CVMX_USB_DIRECTION_IN)); - break; - case CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE: - usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe); - bytes_to_transfer = 0; - USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), cvmx_usbcx_hccharx_t, epdir, - ((header->s.request_type & 0x80) ? - CVMX_USB_DIRECTION_OUT : - CVMX_USB_DIRECTION_IN)); - USB_SET_FIELD32(CVMX_USBCX_HCSPLTX(channel, usb->index), cvmx_usbcx_hcspltx_t, compsplt, 1); - break; - } + switch (transaction->stage) { + case CVMX_USB_STAGE_NON_CONTROL: + case CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE: + cvmx_dprintf("%s: ERROR - Non control stage\n", __FUNCTION__); + break; + case CVMX_USB_STAGE_SETUP: + usbc_hctsiz.s.pid = 3; /* Setup */ + bytes_to_transfer = sizeof(*header); + /* All Control operations start with a setup going OUT */ + USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), cvmx_usbcx_hccharx_t, epdir, CVMX_USB_DIRECTION_OUT); + /* Setup send the control header instead of the buffer data. The + buffer data will be used in the next stage */ + __cvmx_usb_write_csr64(usb, CVMX_USBNX_DMA0_OUTB_CHN0(usb->index) + channel*8, transaction->control_header); + break; + case CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE: + usbc_hctsiz.s.pid = 3; /* Setup */ + bytes_to_transfer = 0; + /* All Control operations start with a setup going OUT */ + USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), cvmx_usbcx_hccharx_t, epdir, CVMX_USB_DIRECTION_OUT); + USB_SET_FIELD32(CVMX_USBCX_HCSPLTX(channel, usb->index), cvmx_usbcx_hcspltx_t, compsplt, 1); + break; + case CVMX_USB_STAGE_DATA: + usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe); + if (__cvmx_usb_pipe_needs_split(usb, pipe)) { + if (header->s.request_type & 0x80) + bytes_to_transfer = 0; + else if (bytes_to_transfer > pipe->max_packet) + bytes_to_transfer = pipe->max_packet; + } + USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), + cvmx_usbcx_hccharx_t, epdir, + ((header->s.request_type & 0x80) ? + CVMX_USB_DIRECTION_IN : + CVMX_USB_DIRECTION_OUT)); + break; + case CVMX_USB_STAGE_DATA_SPLIT_COMPLETE: + usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe); + if (!(header->s.request_type & 0x80)) + bytes_to_transfer = 0; + USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), + cvmx_usbcx_hccharx_t, epdir, + ((header->s.request_type & 0x80) ? + CVMX_USB_DIRECTION_IN : + CVMX_USB_DIRECTION_OUT)); + USB_SET_FIELD32(CVMX_USBCX_HCSPLTX(channel, usb->index), cvmx_usbcx_hcspltx_t, compsplt, 1); + break; + case CVMX_USB_STAGE_STATUS: + usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe); + bytes_to_transfer = 0; + USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), cvmx_usbcx_hccharx_t, epdir, + ((header->s.request_type & 0x80) ? + CVMX_USB_DIRECTION_OUT : + CVMX_USB_DIRECTION_IN)); + break; + case CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE: + usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe); + bytes_to_transfer = 0; + USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), cvmx_usbcx_hccharx_t, epdir, + ((header->s.request_type & 0x80) ? + CVMX_USB_DIRECTION_OUT : + CVMX_USB_DIRECTION_IN)); + USB_SET_FIELD32(CVMX_USBCX_HCSPLTX(channel, usb->index), cvmx_usbcx_hcspltx_t, compsplt, 1); + break; + } - /* Make sure the transfer never exceeds the byte limit of the hardware. - Further bytes will be sent as continued transactions */ - if (bytes_to_transfer > MAX_TRANSFER_BYTES) { - /* Round MAX_TRANSFER_BYTES to a multiple of out packet size */ - bytes_to_transfer = MAX_TRANSFER_BYTES / pipe->max_packet; - bytes_to_transfer *= pipe->max_packet; - } + /* Make sure the transfer never exceeds the byte limit of the hardware. + Further bytes will be sent as continued transactions */ + if (bytes_to_transfer > MAX_TRANSFER_BYTES) { + /* Round MAX_TRANSFER_BYTES to a multiple of out packet size */ + bytes_to_transfer = MAX_TRANSFER_BYTES / pipe->max_packet; + bytes_to_transfer *= pipe->max_packet; + } - /* Calculate the number of packets to transfer. If the length is zero - we still need to transfer one packet */ - packets_to_transfer = (bytes_to_transfer + pipe->max_packet - 1) / pipe->max_packet; - if (packets_to_transfer == 0) - packets_to_transfer = 1; - else if ((packets_to_transfer>1) && (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)) { - /* Limit to one packet when not using DMA. Channels must be restarted - between every packet for IN transactions, so there is no reason to - do multiple packets in a row */ - packets_to_transfer = 1; - bytes_to_transfer = packets_to_transfer * pipe->max_packet; - } - else if (packets_to_transfer > MAX_TRANSFER_PACKETS) { - /* Limit the number of packet and data transferred to what the - hardware can handle */ - packets_to_transfer = MAX_TRANSFER_PACKETS; - bytes_to_transfer = packets_to_transfer * pipe->max_packet; - } + /* Calculate the number of packets to transfer. If the length is zero + we still need to transfer one packet */ + packets_to_transfer = (bytes_to_transfer + pipe->max_packet - 1) / pipe->max_packet; + if (packets_to_transfer == 0) + packets_to_transfer = 1; + else if ((packets_to_transfer > 1) && (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)) { + /* Limit to one packet when not using DMA. Channels must be restarted + between every packet for IN transactions, so there is no reason to + do multiple packets in a row */ + packets_to_transfer = 1; + bytes_to_transfer = packets_to_transfer * pipe->max_packet; + } else if (packets_to_transfer > MAX_TRANSFER_PACKETS) { + /* Limit the number of packet and data transferred to what the + hardware can handle */ + packets_to_transfer = MAX_TRANSFER_PACKETS; + bytes_to_transfer = packets_to_transfer * pipe->max_packet; + } - usbc_hctsiz.s.xfersize = bytes_to_transfer; - usbc_hctsiz.s.pktcnt = packets_to_transfer; + usbc_hctsiz.s.xfersize = bytes_to_transfer; + usbc_hctsiz.s.pktcnt = packets_to_transfer; - __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index), usbc_hctsiz.u32); - return; + __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index), usbc_hctsiz.u32); + return; } @@ -1452,273 +1444,270 @@ static void __cvmx_usb_start_channel_control(cvmx_usb_internal_state_t *usb, * @INTERNAL * Start a channel to perform the pipe's head transaction * - * @param usb USB device state populated by - * cvmx_usb_initialize(). + * @param usb USB device state populated by + * cvmx_usb_initialize(). * @param channel Channel to setup - * @param pipe Pipe to start + * @param pipe Pipe to start */ static void __cvmx_usb_start_channel(cvmx_usb_internal_state_t *usb, - int channel, - cvmx_usb_pipe_t *pipe) + int channel, + cvmx_usb_pipe_t *pipe) { - cvmx_usb_transaction_t *transaction = pipe->head; + cvmx_usb_transaction_t *transaction = pipe->head; - /* Make sure all writes to the DMA region get flushed */ - CVMX_SYNCW; + /* Make sure all writes to the DMA region get flushed */ + CVMX_SYNCW; - /* Attach the channel to the pipe */ - usb->pipe_for_channel[channel] = pipe; - pipe->channel = channel; - pipe->flags |= __CVMX_USB_PIPE_FLAGS_SCHEDULED; + /* Attach the channel to the pipe */ + usb->pipe_for_channel[channel] = pipe; + pipe->channel = channel; + pipe->flags |= __CVMX_USB_PIPE_FLAGS_SCHEDULED; - /* Mark this channel as in use */ - usb->idle_hardware_channels &= ~(1<idle_hardware_channels &= ~(1<index)); - __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCINTX(channel, usb->index), usbc_hcint.u32); + /* Clear all channel status bits */ + usbc_hcint.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCINTX(channel, usb->index)); + __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCINTX(channel, usb->index), usbc_hcint.u32); - usbc_hcintmsk.u32 = 0; - usbc_hcintmsk.s.chhltdmsk = 1; - if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) { - /* Channels need these extra interrupts when we aren't in DMA mode */ - usbc_hcintmsk.s.datatglerrmsk = 1; - usbc_hcintmsk.s.frmovrunmsk = 1; - usbc_hcintmsk.s.bblerrmsk = 1; - usbc_hcintmsk.s.xacterrmsk = 1; - if (__cvmx_usb_pipe_needs_split(usb, pipe)) { - /* Splits don't generate xfercompl, so we need ACK and NYET */ - usbc_hcintmsk.s.nyetmsk = 1; - usbc_hcintmsk.s.ackmsk = 1; - } - usbc_hcintmsk.s.nakmsk = 1; - usbc_hcintmsk.s.stallmsk = 1; - usbc_hcintmsk.s.xfercomplmsk = 1; - } - __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCINTMSKX(channel, usb->index), usbc_hcintmsk.u32); + usbc_hcintmsk.u32 = 0; + usbc_hcintmsk.s.chhltdmsk = 1; + if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) { + /* Channels need these extra interrupts when we aren't in DMA mode */ + usbc_hcintmsk.s.datatglerrmsk = 1; + usbc_hcintmsk.s.frmovrunmsk = 1; + usbc_hcintmsk.s.bblerrmsk = 1; + usbc_hcintmsk.s.xacterrmsk = 1; + if (__cvmx_usb_pipe_needs_split(usb, pipe)) { + /* Splits don't generate xfercompl, so we need ACK and NYET */ + usbc_hcintmsk.s.nyetmsk = 1; + usbc_hcintmsk.s.ackmsk = 1; + } + usbc_hcintmsk.s.nakmsk = 1; + usbc_hcintmsk.s.stallmsk = 1; + usbc_hcintmsk.s.xfercomplmsk = 1; + } + __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCINTMSKX(channel, usb->index), usbc_hcintmsk.u32); - /* Enable the channel interrupt to propagate */ - usbc_haintmsk.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HAINTMSK(usb->index)); - usbc_haintmsk.s.haintmsk |= 1<index), usbc_haintmsk.u32); - } + /* Enable the channel interrupt to propagate */ + usbc_haintmsk.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HAINTMSK(usb->index)); + usbc_haintmsk.s.haintmsk |= 1<index), usbc_haintmsk.u32); + } - /* Setup the locations the DMA engines use */ - { - uint64_t dma_address = transaction->buffer + transaction->actual_bytes; - if (transaction->type == CVMX_USB_TRANSFER_ISOCHRONOUS) - dma_address = transaction->buffer + transaction->iso_packets[0].offset + transaction->actual_bytes; - __cvmx_usb_write_csr64(usb, CVMX_USBNX_DMA0_OUTB_CHN0(usb->index) + channel*8, dma_address); - __cvmx_usb_write_csr64(usb, CVMX_USBNX_DMA0_INB_CHN0(usb->index) + channel*8, dma_address); - } + /* Setup the locations the DMA engines use */ + { + uint64_t dma_address = transaction->buffer + transaction->actual_bytes; + if (transaction->type == CVMX_USB_TRANSFER_ISOCHRONOUS) + dma_address = transaction->buffer + transaction->iso_packets[0].offset + transaction->actual_bytes; + __cvmx_usb_write_csr64(usb, CVMX_USBNX_DMA0_OUTB_CHN0(usb->index) + channel*8, dma_address); + __cvmx_usb_write_csr64(usb, CVMX_USBNX_DMA0_INB_CHN0(usb->index) + channel*8, dma_address); + } - /* Setup both the size of the transfer and the SPLIT characteristics */ - { - cvmx_usbcx_hcspltx_t usbc_hcsplt = {.u32 = 0}; - cvmx_usbcx_hctsizx_t usbc_hctsiz = {.u32 = 0}; - int packets_to_transfer; - int bytes_to_transfer = transaction->buffer_length - transaction->actual_bytes; + /* Setup both the size of the transfer and the SPLIT characteristics */ + { + cvmx_usbcx_hcspltx_t usbc_hcsplt = {.u32 = 0}; + cvmx_usbcx_hctsizx_t usbc_hctsiz = {.u32 = 0}; + int packets_to_transfer; + int bytes_to_transfer = transaction->buffer_length - transaction->actual_bytes; - /* ISOCHRONOUS transactions store each individual transfer size in the - packet structure, not the global buffer_length */ - if (transaction->type == CVMX_USB_TRANSFER_ISOCHRONOUS) - bytes_to_transfer = transaction->iso_packets[0].length - transaction->actual_bytes; + /* ISOCHRONOUS transactions store each individual transfer size in the + packet structure, not the global buffer_length */ + if (transaction->type == CVMX_USB_TRANSFER_ISOCHRONOUS) + bytes_to_transfer = transaction->iso_packets[0].length - transaction->actual_bytes; - /* We need to do split transactions when we are talking to non high - speed devices that are behind a high speed hub */ - if (__cvmx_usb_pipe_needs_split(usb, pipe)) { - /* On the start split phase (stage is even) record the frame number we - will need to send the split complete. We only store the lower two bits - since the time ahead can only be two frames */ - if ((transaction->stage&1) == 0) { - if (transaction->type == CVMX_USB_TRANSFER_BULK) - pipe->split_sc_frame = (usb->frame_number + 1) & 0x7f; - else - pipe->split_sc_frame = (usb->frame_number + 2) & 0x7f; - } - else - pipe->split_sc_frame = -1; + /* We need to do split transactions when we are talking to non high + speed devices that are behind a high speed hub */ + if (__cvmx_usb_pipe_needs_split(usb, pipe)) { + /* On the start split phase (stage is even) record the frame number we + will need to send the split complete. We only store the lower two bits + since the time ahead can only be two frames */ + if ((transaction->stage&1) == 0) { + if (transaction->type == CVMX_USB_TRANSFER_BULK) + pipe->split_sc_frame = (usb->frame_number + 1) & 0x7f; + else + pipe->split_sc_frame = (usb->frame_number + 2) & 0x7f; + } else + pipe->split_sc_frame = -1; - usbc_hcsplt.s.spltena = 1; - usbc_hcsplt.s.hubaddr = pipe->hub_device_addr; - usbc_hcsplt.s.prtaddr = pipe->hub_port; - usbc_hcsplt.s.compsplt = (transaction->stage == CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE); + usbc_hcsplt.s.spltena = 1; + usbc_hcsplt.s.hubaddr = pipe->hub_device_addr; + usbc_hcsplt.s.prtaddr = pipe->hub_port; + usbc_hcsplt.s.compsplt = (transaction->stage == CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE); - /* SPLIT transactions can only ever transmit one data packet so - limit the transfer size to the max packet size */ - if (bytes_to_transfer > pipe->max_packet) - bytes_to_transfer = pipe->max_packet; + /* SPLIT transactions can only ever transmit one data packet so + limit the transfer size to the max packet size */ + if (bytes_to_transfer > pipe->max_packet) + bytes_to_transfer = pipe->max_packet; - /* ISOCHRONOUS OUT splits are unique in that they limit - data transfers to 188 byte chunks representing the - begin/middle/end of the data or all */ - if (!usbc_hcsplt.s.compsplt && - (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT) && - (pipe->transfer_type == CVMX_USB_TRANSFER_ISOCHRONOUS)) { - /* Clear the split complete frame number as there isn't going - to be a split complete */ - pipe->split_sc_frame = -1; - /* See if we've started this transfer and sent data */ - if (transaction->actual_bytes == 0) { - /* Nothing sent yet, this is either a begin or the - entire payload */ - if (bytes_to_transfer <= 188) - usbc_hcsplt.s.xactpos = 3; /* Entire payload in one go */ - else - usbc_hcsplt.s.xactpos = 2; /* First part of payload */ - } - else { - /* Continuing the previous data, we must either be - in the middle or at the end */ - if (bytes_to_transfer <= 188) - usbc_hcsplt.s.xactpos = 1; /* End of payload */ - else - usbc_hcsplt.s.xactpos = 0; /* Middle of payload */ - } - /* Again, the transfer size is limited to 188 bytes */ - if (bytes_to_transfer > 188) - bytes_to_transfer = 188; - } - } + /* ISOCHRONOUS OUT splits are unique in that they limit + data transfers to 188 byte chunks representing the + begin/middle/end of the data or all */ + if (!usbc_hcsplt.s.compsplt && + (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT) && + (pipe->transfer_type == CVMX_USB_TRANSFER_ISOCHRONOUS)) { + /* Clear the split complete frame number as there isn't going + to be a split complete */ + pipe->split_sc_frame = -1; + /* See if we've started this transfer and sent data */ + if (transaction->actual_bytes == 0) { + /* Nothing sent yet, this is either a begin or the + entire payload */ + if (bytes_to_transfer <= 188) + usbc_hcsplt.s.xactpos = 3; /* Entire payload in one go */ + else + usbc_hcsplt.s.xactpos = 2; /* First part of payload */ + } else { + /* Continuing the previous data, we must either be + in the middle or at the end */ + if (bytes_to_transfer <= 188) + usbc_hcsplt.s.xactpos = 1; /* End of payload */ + else + usbc_hcsplt.s.xactpos = 0; /* Middle of payload */ + } + /* Again, the transfer size is limited to 188 bytes */ + if (bytes_to_transfer > 188) + bytes_to_transfer = 188; + } + } - /* Make sure the transfer never exceeds the byte limit of the hardware. - Further bytes will be sent as continued transactions */ - if (bytes_to_transfer > MAX_TRANSFER_BYTES) { - /* Round MAX_TRANSFER_BYTES to a multiple of out packet size */ - bytes_to_transfer = MAX_TRANSFER_BYTES / pipe->max_packet; - bytes_to_transfer *= pipe->max_packet; - } + /* Make sure the transfer never exceeds the byte limit of the hardware. + Further bytes will be sent as continued transactions */ + if (bytes_to_transfer > MAX_TRANSFER_BYTES) { + /* Round MAX_TRANSFER_BYTES to a multiple of out packet size */ + bytes_to_transfer = MAX_TRANSFER_BYTES / pipe->max_packet; + bytes_to_transfer *= pipe->max_packet; + } - /* Calculate the number of packets to transfer. If the length is zero - we still need to transfer one packet */ - packets_to_transfer = (bytes_to_transfer + pipe->max_packet - 1) / pipe->max_packet; - if (packets_to_transfer == 0) - packets_to_transfer = 1; - else if ((packets_to_transfer>1) && (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)) { - /* Limit to one packet when not using DMA. Channels must be restarted - between every packet for IN transactions, so there is no reason to - do multiple packets in a row */ - packets_to_transfer = 1; - bytes_to_transfer = packets_to_transfer * pipe->max_packet; - } - else if (packets_to_transfer > MAX_TRANSFER_PACKETS) { - /* Limit the number of packet and data transferred to what the - hardware can handle */ - packets_to_transfer = MAX_TRANSFER_PACKETS; - bytes_to_transfer = packets_to_transfer * pipe->max_packet; - } + /* Calculate the number of packets to transfer. If the length is zero + we still need to transfer one packet */ + packets_to_transfer = (bytes_to_transfer + pipe->max_packet - 1) / pipe->max_packet; + if (packets_to_transfer == 0) + packets_to_transfer = 1; + else if ((packets_to_transfer > 1) && (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)) { + /* Limit to one packet when not using DMA. Channels must be restarted + between every packet for IN transactions, so there is no reason to + do multiple packets in a row */ + packets_to_transfer = 1; + bytes_to_transfer = packets_to_transfer * pipe->max_packet; + } else if (packets_to_transfer > MAX_TRANSFER_PACKETS) { + /* Limit the number of packet and data transferred to what the + hardware can handle */ + packets_to_transfer = MAX_TRANSFER_PACKETS; + bytes_to_transfer = packets_to_transfer * pipe->max_packet; + } - usbc_hctsiz.s.xfersize = bytes_to_transfer; - usbc_hctsiz.s.pktcnt = packets_to_transfer; + usbc_hctsiz.s.xfersize = bytes_to_transfer; + usbc_hctsiz.s.pktcnt = packets_to_transfer; - /* Update the DATA0/DATA1 toggle */ - usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe); - /* High speed pipes may need a hardware ping before they start */ - if (pipe->flags & __CVMX_USB_PIPE_FLAGS_NEED_PING) - usbc_hctsiz.s.dopng = 1; + /* Update the DATA0/DATA1 toggle */ + usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe); + /* High speed pipes may need a hardware ping before they start */ + if (pipe->flags & __CVMX_USB_PIPE_FLAGS_NEED_PING) + usbc_hctsiz.s.dopng = 1; - __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCSPLTX(channel, usb->index), usbc_hcsplt.u32); - __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index), usbc_hctsiz.u32); - } + __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCSPLTX(channel, usb->index), usbc_hcsplt.u32); + __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index), usbc_hctsiz.u32); + } - /* Setup the Host Channel Characteristics Register */ - { - cvmx_usbcx_hccharx_t usbc_hcchar = {.u32 = 0}; + /* Setup the Host Channel Characteristics Register */ + { + cvmx_usbcx_hccharx_t usbc_hcchar = {.u32 = 0}; - /* Set the startframe odd/even properly. This is only used for periodic */ - usbc_hcchar.s.oddfrm = usb->frame_number&1; + /* Set the startframe odd/even properly. This is only used for periodic */ + usbc_hcchar.s.oddfrm = usb->frame_number&1; - /* Set the number of back to back packets allowed by this endpoint. - Split transactions interpret "ec" as the number of immediate - retries of failure. These retries happen too quickly, so we - disable these entirely for splits */ - if (__cvmx_usb_pipe_needs_split(usb, pipe)) - usbc_hcchar.s.ec = 1; - else if (pipe->multi_count < 1) - usbc_hcchar.s.ec = 1; - else if (pipe->multi_count > 3) - usbc_hcchar.s.ec = 3; - else - usbc_hcchar.s.ec = pipe->multi_count; + /* Set the number of back to back packets allowed by this endpoint. + Split transactions interpret "ec" as the number of immediate + retries of failure. These retries happen too quickly, so we + disable these entirely for splits */ + if (__cvmx_usb_pipe_needs_split(usb, pipe)) + usbc_hcchar.s.ec = 1; + else if (pipe->multi_count < 1) + usbc_hcchar.s.ec = 1; + else if (pipe->multi_count > 3) + usbc_hcchar.s.ec = 3; + else + usbc_hcchar.s.ec = pipe->multi_count; - /* Set the rest of the endpoint specific settings */ - usbc_hcchar.s.devaddr = pipe->device_addr; - usbc_hcchar.s.eptype = transaction->type; - usbc_hcchar.s.lspddev = (pipe->device_speed == CVMX_USB_SPEED_LOW); - usbc_hcchar.s.epdir = pipe->transfer_dir; - usbc_hcchar.s.epnum = pipe->endpoint_num; - usbc_hcchar.s.mps = pipe->max_packet; - __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index), usbc_hcchar.u32); - } + /* Set the rest of the endpoint specific settings */ + usbc_hcchar.s.devaddr = pipe->device_addr; + usbc_hcchar.s.eptype = transaction->type; + usbc_hcchar.s.lspddev = (pipe->device_speed == CVMX_USB_SPEED_LOW); + usbc_hcchar.s.epdir = pipe->transfer_dir; + usbc_hcchar.s.epnum = pipe->endpoint_num; + usbc_hcchar.s.mps = pipe->max_packet; + __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index), usbc_hcchar.u32); + } - /* Do transaction type specific fixups as needed */ - switch (transaction->type) { - case CVMX_USB_TRANSFER_CONTROL: - __cvmx_usb_start_channel_control(usb, channel, pipe); - break; - case CVMX_USB_TRANSFER_BULK: - case CVMX_USB_TRANSFER_INTERRUPT: - break; - case CVMX_USB_TRANSFER_ISOCHRONOUS: - if (!__cvmx_usb_pipe_needs_split(usb, pipe)) { - /* ISO transactions require different PIDs depending on direction - and how many packets are needed */ - if (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT) { - if (pipe->multi_count < 2) /* Need DATA0 */ - USB_SET_FIELD32(CVMX_USBCX_HCTSIZX(channel, usb->index), cvmx_usbcx_hctsizx_t, pid, 0); - else /* Need MDATA */ - USB_SET_FIELD32(CVMX_USBCX_HCTSIZX(channel, usb->index), cvmx_usbcx_hctsizx_t, pid, 3); - } - } - break; - } - { - cvmx_usbcx_hctsizx_t usbc_hctsiz = {.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index))}; - transaction->xfersize = usbc_hctsiz.s.xfersize; - transaction->pktcnt = usbc_hctsiz.s.pktcnt; - } - /* Remeber when we start a split transaction */ - if (__cvmx_usb_pipe_needs_split(usb, pipe)) - usb->active_split = transaction; - USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), cvmx_usbcx_hccharx_t, chena, 1); - if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) - __cvmx_usb_fill_tx_fifo(usb, channel); - return; + /* Do transaction type specific fixups as needed */ + switch (transaction->type) { + case CVMX_USB_TRANSFER_CONTROL: + __cvmx_usb_start_channel_control(usb, channel, pipe); + break; + case CVMX_USB_TRANSFER_BULK: + case CVMX_USB_TRANSFER_INTERRUPT: + break; + case CVMX_USB_TRANSFER_ISOCHRONOUS: + if (!__cvmx_usb_pipe_needs_split(usb, pipe)) { + /* ISO transactions require different PIDs depending on direction + and how many packets are needed */ + if (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT) { + if (pipe->multi_count < 2) /* Need DATA0 */ + USB_SET_FIELD32(CVMX_USBCX_HCTSIZX(channel, usb->index), cvmx_usbcx_hctsizx_t, pid, 0); + else /* Need MDATA */ + USB_SET_FIELD32(CVMX_USBCX_HCTSIZX(channel, usb->index), cvmx_usbcx_hctsizx_t, pid, 3); + } + } + break; + } + { + cvmx_usbcx_hctsizx_t usbc_hctsiz = {.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index))}; + transaction->xfersize = usbc_hctsiz.s.xfersize; + transaction->pktcnt = usbc_hctsiz.s.pktcnt; + } + /* Remeber when we start a split transaction */ + if (__cvmx_usb_pipe_needs_split(usb, pipe)) + usb->active_split = transaction; + USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), cvmx_usbcx_hccharx_t, chena, 1); + if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) + __cvmx_usb_fill_tx_fifo(usb, channel); + return; } /** * @INTERNAL * Find a pipe that is ready to be scheduled to hardware. - * @param usb USB device state populated by - * cvmx_usb_initialize(). - * @param list Pipe list to search + * @param usb USB device state populated by + * cvmx_usb_initialize(). + * @param list Pipe list to search * @param current_frame - * Frame counter to use as a time reference. + * Frame counter to use as a time reference. * * @return Pipe or NULL if none are ready */ static cvmx_usb_pipe_t *__cvmx_usb_find_ready_pipe(cvmx_usb_internal_state_t *usb, cvmx_usb_pipe_list_t *list, uint64_t current_frame) { - cvmx_usb_pipe_t *pipe = list->head; - while (pipe) { - if (!(pipe->flags & __CVMX_USB_PIPE_FLAGS_SCHEDULED) && pipe->head && - (pipe->next_tx_frame <= current_frame) && - ((pipe->split_sc_frame == -1) || ((((int)current_frame - (int)pipe->split_sc_frame) & 0x7f) < 0x40)) && - (!usb->active_split || (usb->active_split == pipe->head))) { - CVMX_PREFETCH(pipe, 128); - CVMX_PREFETCH(pipe->head, 0); - return pipe; - } - pipe = pipe->next; - } - return NULL; + cvmx_usb_pipe_t *pipe = list->head; + while (pipe) { + if (!(pipe->flags & __CVMX_USB_PIPE_FLAGS_SCHEDULED) && pipe->head && + (pipe->next_tx_frame <= current_frame) && + ((pipe->split_sc_frame == -1) || ((((int)current_frame - (int)pipe->split_sc_frame) & 0x7f) < 0x40)) && + (!usb->active_split || (usb->active_split == pipe->head))) { + CVMX_PREFETCH(pipe, 128); + CVMX_PREFETCH(pipe->head, 0); + return pipe; + } + pipe = pipe->next; + } + return NULL; } @@ -1727,69 +1716,69 @@ static cvmx_usb_pipe_t *__cvmx_usb_find_ready_pipe(cvmx_usb_internal_state_t *us * Called whenever a pipe might need to be scheduled to the * hardware. * - * @param usb USB device state populated by - * cvmx_usb_initialize(). + * @param usb USB device state populated by + * cvmx_usb_initialize(). * @param is_sof True if this schedule was called on a SOF interrupt. */ static void __cvmx_usb_schedule(cvmx_usb_internal_state_t *usb, int is_sof) { - int channel; - cvmx_usb_pipe_t *pipe; - int need_sof; - cvmx_usb_transfer_t ttype; + int channel; + cvmx_usb_pipe_t *pipe; + int need_sof; + cvmx_usb_transfer_t ttype; - if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) { - /* Without DMA we need to be careful to not schedule something at the end of a frame and cause an overrun */ - cvmx_usbcx_hfnum_t hfnum = {.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HFNUM(usb->index))}; - cvmx_usbcx_hfir_t hfir = {.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HFIR(usb->index))}; - if (hfnum.s.frrem < hfir.s.frint/4) - goto done; - } + if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) { + /* Without DMA we need to be careful to not schedule something at the end of a frame and cause an overrun */ + cvmx_usbcx_hfnum_t hfnum = {.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HFNUM(usb->index))}; + cvmx_usbcx_hfir_t hfir = {.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HFIR(usb->index))}; + if (hfnum.s.frrem < hfir.s.frint/4) + goto done; + } - while (usb->idle_hardware_channels) { - /* Find an idle channel */ - CVMX_CLZ(channel, usb->idle_hardware_channels); - channel = 31 - channel; - if (unlikely(channel > 7)) - break; + while (usb->idle_hardware_channels) { + /* Find an idle channel */ + CVMX_CLZ(channel, usb->idle_hardware_channels); + channel = 31 - channel; + if (unlikely(channel > 7)) + break; - /* Find a pipe needing service */ - pipe = NULL; - if (is_sof) { - /* Only process periodic pipes on SOF interrupts. This way we are - sure that the periodic data is sent in the beginning of the - frame */ - pipe = __cvmx_usb_find_ready_pipe(usb, usb->active_pipes + CVMX_USB_TRANSFER_ISOCHRONOUS, usb->frame_number); - if (likely(!pipe)) - pipe = __cvmx_usb_find_ready_pipe(usb, usb->active_pipes + CVMX_USB_TRANSFER_INTERRUPT, usb->frame_number); - } - if (likely(!pipe)) { - pipe = __cvmx_usb_find_ready_pipe(usb, usb->active_pipes + CVMX_USB_TRANSFER_CONTROL, usb->frame_number); - if (likely(!pipe)) - pipe = __cvmx_usb_find_ready_pipe(usb, usb->active_pipes + CVMX_USB_TRANSFER_BULK, usb->frame_number); - } - if (!pipe) - break; + /* Find a pipe needing service */ + pipe = NULL; + if (is_sof) { + /* Only process periodic pipes on SOF interrupts. This way we are + sure that the periodic data is sent in the beginning of the + frame */ + pipe = __cvmx_usb_find_ready_pipe(usb, usb->active_pipes + CVMX_USB_TRANSFER_ISOCHRONOUS, usb->frame_number); + if (likely(!pipe)) + pipe = __cvmx_usb_find_ready_pipe(usb, usb->active_pipes + CVMX_USB_TRANSFER_INTERRUPT, usb->frame_number); + } + if (likely(!pipe)) { + pipe = __cvmx_usb_find_ready_pipe(usb, usb->active_pipes + CVMX_USB_TRANSFER_CONTROL, usb->frame_number); + if (likely(!pipe)) + pipe = __cvmx_usb_find_ready_pipe(usb, usb->active_pipes + CVMX_USB_TRANSFER_BULK, usb->frame_number); + } + if (!pipe) + break; - __cvmx_usb_start_channel(usb, channel, pipe); - } + __cvmx_usb_start_channel(usb, channel, pipe); + } done: - /* Only enable SOF interrupts when we have transactions pending in the - future that might need to be scheduled */ - need_sof = 0; - for (ttype=CVMX_USB_TRANSFER_CONTROL; ttype<=CVMX_USB_TRANSFER_INTERRUPT; ttype++) { - pipe = usb->active_pipes[ttype].head; - while (pipe) { - if (pipe->next_tx_frame > usb->frame_number) { - need_sof = 1; - break; - } - pipe=pipe->next; - } - } - USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), cvmx_usbcx_gintmsk_t, sofmsk, need_sof); - return; + /* Only enable SOF interrupts when we have transactions pending in the + future that might need to be scheduled */ + need_sof = 0; + for (ttype = CVMX_USB_TRANSFER_CONTROL; ttype <= CVMX_USB_TRANSFER_INTERRUPT; ttype++) { + pipe = usb->active_pipes[ttype].head; + while (pipe) { + if (pipe->next_tx_frame > usb->frame_number) { + need_sof = 1; + break; + } + pipe = pipe->next; + } + } + USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), cvmx_usbcx_gintmsk_t, sofmsk, need_sof); + return; } @@ -1797,45 +1786,45 @@ done: * @INTERNAL * Call a user's callback for a specific reason. * - * @param usb USB device state populated by - * cvmx_usb_initialize(). - * @param pipe Pipe the callback is for or NULL + * @param usb USB device state populated by + * cvmx_usb_initialize(). + * @param pipe Pipe the callback is for or NULL * @param transaction - * Transaction the callback is for or NULL + * Transaction the callback is for or NULL * @param reason Reason this callback is being called * @param complete_code - * Completion code for the transaction, if any + * Completion code for the transaction, if any */ static void __cvmx_usb_perform_callback(cvmx_usb_internal_state_t *usb, - cvmx_usb_pipe_t *pipe, - cvmx_usb_transaction_t *transaction, - cvmx_usb_callback_t reason, - cvmx_usb_complete_t complete_code) + cvmx_usb_pipe_t *pipe, + cvmx_usb_transaction_t *transaction, + cvmx_usb_callback_t reason, + cvmx_usb_complete_t complete_code) { - cvmx_usb_callback_func_t callback = usb->callback[reason]; - void *user_data = usb->callback_data[reason]; - int submit_handle = -1; - int pipe_handle = -1; - int bytes_transferred = 0; + cvmx_usb_callback_func_t callback = usb->callback[reason]; + void *user_data = usb->callback_data[reason]; + int submit_handle = -1; + int pipe_handle = -1; + int bytes_transferred = 0; - if (pipe) - pipe_handle = __cvmx_usb_get_pipe_handle(usb, pipe); + if (pipe) + pipe_handle = __cvmx_usb_get_pipe_handle(usb, pipe); - if (transaction) { - submit_handle = __cvmx_usb_get_submit_handle(usb, transaction); - bytes_transferred = transaction->actual_bytes; - /* Transactions are allowed to override the default callback */ - if ((reason == CVMX_USB_CALLBACK_TRANSFER_COMPLETE) && transaction->callback) { - callback = transaction->callback; - user_data = transaction->callback_data; - } - } + if (transaction) { + submit_handle = __cvmx_usb_get_submit_handle(usb, transaction); + bytes_transferred = transaction->actual_bytes; + /* Transactions are allowed to override the default callback */ + if ((reason == CVMX_USB_CALLBACK_TRANSFER_COMPLETE) && transaction->callback) { + callback = transaction->callback; + user_data = transaction->callback_data; + } + } - if (!callback) - return; + if (!callback) + return; - callback((cvmx_usb_state_t *)usb, reason, complete_code, pipe_handle, submit_handle, - bytes_transferred, user_data); + callback((cvmx_usb_state_t *)usb, reason, complete_code, pipe_handle, submit_handle, + bytes_transferred, user_data); } @@ -1844,61 +1833,61 @@ static void __cvmx_usb_perform_callback(cvmx_usb_internal_state_t *usb, * Signal the completion of a transaction and free it. The * transaction will be removed from the pipe transaction list. * - * @param usb USB device state populated by - * cvmx_usb_initialize(). - * @param pipe Pipe the transaction is on + * @param usb USB device state populated by + * cvmx_usb_initialize(). + * @param pipe Pipe the transaction is on * @param transaction - * Transaction that completed + * Transaction that completed * @param complete_code - * Completion code + * Completion code */ -static void __cvmx_usb_perform_complete(cvmx_usb_internal_state_t * usb, - cvmx_usb_pipe_t *pipe, - cvmx_usb_transaction_t *transaction, - cvmx_usb_complete_t complete_code) +static void __cvmx_usb_perform_complete(cvmx_usb_internal_state_t *usb, + cvmx_usb_pipe_t *pipe, + cvmx_usb_transaction_t *transaction, + cvmx_usb_complete_t complete_code) { - /* If this was a split then clear our split in progress marker */ - if (usb->active_split == transaction) - usb->active_split = NULL; + /* If this was a split then clear our split in progress marker */ + if (usb->active_split == transaction) + usb->active_split = NULL; - /* Isochronous transactions need extra processing as they might not be done - after a single data transfer */ - if (unlikely(transaction->type == CVMX_USB_TRANSFER_ISOCHRONOUS)) { - /* Update the number of bytes transferred in this ISO packet */ - transaction->iso_packets[0].length = transaction->actual_bytes; - transaction->iso_packets[0].status = complete_code; + /* Isochronous transactions need extra processing as they might not be done + after a single data transfer */ + if (unlikely(transaction->type == CVMX_USB_TRANSFER_ISOCHRONOUS)) { + /* Update the number of bytes transferred in this ISO packet */ + transaction->iso_packets[0].length = transaction->actual_bytes; + transaction->iso_packets[0].status = complete_code; - /* If there are more ISOs pending and we succeeded, schedule the next - one */ - if ((transaction->iso_number_packets > 1) && (complete_code == CVMX_USB_COMPLETE_SUCCESS)) { - transaction->actual_bytes = 0; /* No bytes transferred for this packet as of yet */ - transaction->iso_number_packets--; /* One less ISO waiting to transfer */ - transaction->iso_packets++; /* Increment to the next location in our packet array */ - transaction->stage = CVMX_USB_STAGE_NON_CONTROL; - goto done; - } - } + /* If there are more ISOs pending and we succeeded, schedule the next + one */ + if ((transaction->iso_number_packets > 1) && (complete_code == CVMX_USB_COMPLETE_SUCCESS)) { + transaction->actual_bytes = 0; /* No bytes transferred for this packet as of yet */ + transaction->iso_number_packets--; /* One less ISO waiting to transfer */ + transaction->iso_packets++; /* Increment to the next location in our packet array */ + transaction->stage = CVMX_USB_STAGE_NON_CONTROL; + goto done; + } + } - /* Remove the transaction from the pipe list */ - if (transaction->next) - transaction->next->prev = transaction->prev; - else - pipe->tail = transaction->prev; - if (transaction->prev) - transaction->prev->next = transaction->next; - else - pipe->head = transaction->next; - if (!pipe->head) { - __cvmx_usb_remove_pipe(usb->active_pipes + pipe->transfer_type, pipe); - __cvmx_usb_append_pipe(&usb->idle_pipes, pipe); + /* Remove the transaction from the pipe list */ + if (transaction->next) + transaction->next->prev = transaction->prev; + else + pipe->tail = transaction->prev; + if (transaction->prev) + transaction->prev->next = transaction->next; + else + pipe->head = transaction->next; + if (!pipe->head) { + __cvmx_usb_remove_pipe(usb->active_pipes + pipe->transfer_type, pipe); + __cvmx_usb_append_pipe(&usb->idle_pipes, pipe); - } - __cvmx_usb_perform_callback(usb, pipe, transaction, - CVMX_USB_CALLBACK_TRANSFER_COMPLETE, - complete_code); - __cvmx_usb_free_transaction(usb, transaction); + } + __cvmx_usb_perform_callback(usb, pipe, transaction, + CVMX_USB_CALLBACK_TRANSFER_COMPLETE, + complete_code); + __cvmx_usb_free_transaction(usb, transaction); done: - return; + return; } @@ -1909,365 +1898,364 @@ done: * * @param usb * @param pipe_handle - * Which pipe to submit to. Will be validated in this function. - * @param type Transaction type - * @param flags Flags for the transaction + * Which pipe to submit to. Will be validated in this function. + * @param type Transaction type + * @param flags Flags for the transaction * @param buffer User buffer for the transaction * @param buffer_length - * User buffer's length in bytes + * User buffer's length in bytes * @param control_header - * For control transactions, the 8 byte standard header + * For control transactions, the 8 byte standard header * @param iso_start_frame - * For ISO transactions, the start frame + * For ISO transactions, the start frame * @param iso_number_packets - * For ISO, the number of packet in the transaction. + * For ISO, the number of packet in the transaction. * @param iso_packets - * A description of each ISO packet + * A description of each ISO packet * @param callback User callback to call when the transaction completes * @param user_data User's data for the callback * * @return Submit handle or negative on failure. Matches the result - * in the external API. + * in the external API. */ static int __cvmx_usb_submit_transaction(cvmx_usb_internal_state_t *usb, - int pipe_handle, - cvmx_usb_transfer_t type, - int flags, - uint64_t buffer, - int buffer_length, - uint64_t control_header, - int iso_start_frame, - int iso_number_packets, - cvmx_usb_iso_packet_t *iso_packets, - cvmx_usb_callback_func_t callback, - void *user_data) + int pipe_handle, + cvmx_usb_transfer_t type, + int flags, + uint64_t buffer, + int buffer_length, + uint64_t control_header, + int iso_start_frame, + int iso_number_packets, + cvmx_usb_iso_packet_t *iso_packets, + cvmx_usb_callback_func_t callback, + void *user_data) { - int submit_handle; - cvmx_usb_transaction_t *transaction; - cvmx_usb_pipe_t *pipe = usb->pipe + pipe_handle; + int submit_handle; + cvmx_usb_transaction_t *transaction; + cvmx_usb_pipe_t *pipe = usb->pipe + pipe_handle; - if (unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES))) - return -EINVAL; - /* Fail if the pipe isn't open */ - if (unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0)) - return -EINVAL; - if (unlikely(pipe->transfer_type != type)) - return -EINVAL; + if (unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES))) + return -EINVAL; + /* Fail if the pipe isn't open */ + if (unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0)) + return -EINVAL; + if (unlikely(pipe->transfer_type != type)) + return -EINVAL; - transaction = __cvmx_usb_alloc_transaction(usb); - if (unlikely(!transaction)) - return -ENOMEM; + transaction = __cvmx_usb_alloc_transaction(usb); + if (unlikely(!transaction)) + return -ENOMEM; - transaction->type = type; - transaction->flags |= flags; - transaction->buffer = buffer; - transaction->buffer_length = buffer_length; - transaction->control_header = control_header; - transaction->iso_start_frame = iso_start_frame; // FIXME: This is not used, implement it - transaction->iso_number_packets = iso_number_packets; - transaction->iso_packets = iso_packets; - transaction->callback = callback; - transaction->callback_data = user_data; - if (transaction->type == CVMX_USB_TRANSFER_CONTROL) - transaction->stage = CVMX_USB_STAGE_SETUP; - else - transaction->stage = CVMX_USB_STAGE_NON_CONTROL; + transaction->type = type; + transaction->flags |= flags; + transaction->buffer = buffer; + transaction->buffer_length = buffer_length; + transaction->control_header = control_header; + transaction->iso_start_frame = iso_start_frame; // FIXME: This is not used, implement it + transaction->iso_number_packets = iso_number_packets; + transaction->iso_packets = iso_packets; + transaction->callback = callback; + transaction->callback_data = user_data; + if (transaction->type == CVMX_USB_TRANSFER_CONTROL) + transaction->stage = CVMX_USB_STAGE_SETUP; + else + transaction->stage = CVMX_USB_STAGE_NON_CONTROL; - transaction->next = NULL; - if (pipe->tail) { - transaction->prev = pipe->tail; - transaction->prev->next = transaction; - } - else { - if (pipe->next_tx_frame < usb->frame_number) - pipe->next_tx_frame = usb->frame_number + pipe->interval - - (usb->frame_number - pipe->next_tx_frame) % pipe->interval; - transaction->prev = NULL; - pipe->head = transaction; - __cvmx_usb_remove_pipe(&usb->idle_pipes, pipe); - __cvmx_usb_append_pipe(usb->active_pipes + pipe->transfer_type, pipe); - } - pipe->tail = transaction; + transaction->next = NULL; + if (pipe->tail) { + transaction->prev = pipe->tail; + transaction->prev->next = transaction; + } else { + if (pipe->next_tx_frame < usb->frame_number) + pipe->next_tx_frame = usb->frame_number + pipe->interval - + (usb->frame_number - pipe->next_tx_frame) % pipe->interval; + transaction->prev = NULL; + pipe->head = transaction; + __cvmx_usb_remove_pipe(&usb->idle_pipes, pipe); + __cvmx_usb_append_pipe(usb->active_pipes + pipe->transfer_type, pipe); + } + pipe->tail = transaction; - submit_handle = __cvmx_usb_get_submit_handle(usb, transaction); + submit_handle = __cvmx_usb_get_submit_handle(usb, transaction); - /* We may need to schedule the pipe if this was the head of the pipe */ - if (!transaction->prev) - __cvmx_usb_schedule(usb, 0); + /* We may need to schedule the pipe if this was the head of the pipe */ + if (!transaction->prev) + __cvmx_usb_schedule(usb, 0); - return submit_handle; + return submit_handle; } /** * Call to submit a USB Bulk transfer to a pipe. * - * @param state USB device state populated by - * cvmx_usb_initialize(). + * @param state USB device state populated by + * cvmx_usb_initialize(). * @param pipe_handle - * Handle to the pipe for the transfer. + * Handle to the pipe for the transfer. * @param buffer Physical address of the data buffer in - * memory. Note that this is NOT A POINTER, but - * the full 64bit physical address of the - * buffer. This may be zero if buffer_length is - * zero. + * memory. Note that this is NOT A POINTER, but + * the full 64bit physical address of the + * buffer. This may be zero if buffer_length is + * zero. * @param buffer_length - * Length of buffer in bytes. + * Length of buffer in bytes. * @param callback Function to call when this transaction - * completes. If the return value of this - * function isn't an error, then this function - * is guaranteed to be called when the - * transaction completes. If this parameter is - * NULL, then the generic callback registered - * through cvmx_usb_register_callback is - * called. If both are NULL, then there is no - * way to know when a transaction completes. + * completes. If the return value of this + * function isn't an error, then this function + * is guaranteed to be called when the + * transaction completes. If this parameter is + * NULL, then the generic callback registered + * through cvmx_usb_register_callback is + * called. If both are NULL, then there is no + * way to know when a transaction completes. * @param user_data User supplied data returned when the - * callback is called. This is only used if - * callback in not NULL. + * callback is called. This is only used if + * callback in not NULL. * * @return A submitted transaction handle or negative on - * failure. Negative values are error codes. + * failure. Negative values are error codes. */ int cvmx_usb_submit_bulk(cvmx_usb_state_t *state, int pipe_handle, - uint64_t buffer, int buffer_length, - cvmx_usb_callback_func_t callback, - void *user_data) + uint64_t buffer, int buffer_length, + cvmx_usb_callback_func_t callback, + void *user_data) { - int submit_handle; - cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; + int submit_handle; + cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; - /* Pipe handle checking is done later in a common place */ - if (unlikely(!buffer)) - return -EINVAL; - if (unlikely(buffer_length < 0)) - return -EINVAL; + /* Pipe handle checking is done later in a common place */ + if (unlikely(!buffer)) + return -EINVAL; + if (unlikely(buffer_length < 0)) + return -EINVAL; - submit_handle = __cvmx_usb_submit_transaction(usb, pipe_handle, - CVMX_USB_TRANSFER_BULK, - 0, /* flags */ - buffer, - buffer_length, - 0, /* control_header */ - 0, /* iso_start_frame */ - 0, /* iso_number_packets */ - NULL, /* iso_packets */ - callback, - user_data); - return submit_handle; + submit_handle = __cvmx_usb_submit_transaction(usb, pipe_handle, + CVMX_USB_TRANSFER_BULK, + 0, /* flags */ + buffer, + buffer_length, + 0, /* control_header */ + 0, /* iso_start_frame */ + 0, /* iso_number_packets */ + NULL, /* iso_packets */ + callback, + user_data); + return submit_handle; } /** * Call to submit a USB Interrupt transfer to a pipe. * - * @param state USB device state populated by - * cvmx_usb_initialize(). + * @param state USB device state populated by + * cvmx_usb_initialize(). * @param pipe_handle - * Handle to the pipe for the transfer. + * Handle to the pipe for the transfer. * @param buffer Physical address of the data buffer in - * memory. Note that this is NOT A POINTER, but - * the full 64bit physical address of the - * buffer. This may be zero if buffer_length is - * zero. + * memory. Note that this is NOT A POINTER, but + * the full 64bit physical address of the + * buffer. This may be zero if buffer_length is + * zero. * @param buffer_length - * Length of buffer in bytes. + * Length of buffer in bytes. * @param callback Function to call when this transaction - * completes. If the return value of this - * function isn't an error, then this function - * is guaranteed to be called when the - * transaction completes. If this parameter is - * NULL, then the generic callback registered - * through cvmx_usb_register_callback is - * called. If both are NULL, then there is no - * way to know when a transaction completes. + * completes. If the return value of this + * function isn't an error, then this function + * is guaranteed to be called when the + * transaction completes. If this parameter is + * NULL, then the generic callback registered + * through cvmx_usb_register_callback is + * called. If both are NULL, then there is no + * way to know when a transaction completes. * @param user_data User supplied data returned when the - * callback is called. This is only used if - * callback in not NULL. + * callback is called. This is only used if + * callback in not NULL. * * @return A submitted transaction handle or negative on - * failure. Negative values are error codes. + * failure. Negative values are error codes. */ int cvmx_usb_submit_interrupt(cvmx_usb_state_t *state, int pipe_handle, - uint64_t buffer, int buffer_length, - cvmx_usb_callback_func_t callback, - void *user_data) + uint64_t buffer, int buffer_length, + cvmx_usb_callback_func_t callback, + void *user_data) { - int submit_handle; - cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; + int submit_handle; + cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; - /* Pipe handle checking is done later in a common place */ - if (unlikely(!buffer)) - return -EINVAL; - if (unlikely(buffer_length < 0)) - return -EINVAL; + /* Pipe handle checking is done later in a common place */ + if (unlikely(!buffer)) + return -EINVAL; + if (unlikely(buffer_length < 0)) + return -EINVAL; - submit_handle = __cvmx_usb_submit_transaction(usb, pipe_handle, - CVMX_USB_TRANSFER_INTERRUPT, - 0, /* flags */ - buffer, - buffer_length, - 0, /* control_header */ - 0, /* iso_start_frame */ - 0, /* iso_number_packets */ - NULL, /* iso_packets */ - callback, - user_data); - return submit_handle; + submit_handle = __cvmx_usb_submit_transaction(usb, pipe_handle, + CVMX_USB_TRANSFER_INTERRUPT, + 0, /* flags */ + buffer, + buffer_length, + 0, /* control_header */ + 0, /* iso_start_frame */ + 0, /* iso_number_packets */ + NULL, /* iso_packets */ + callback, + user_data); + return submit_handle; } /** * Call to submit a USB Control transfer to a pipe. * - * @param state USB device state populated by - * cvmx_usb_initialize(). + * @param state USB device state populated by + * cvmx_usb_initialize(). * @param pipe_handle - * Handle to the pipe for the transfer. + * Handle to the pipe for the transfer. * @param control_header - * USB 8 byte control header physical address. - * Note that this is NOT A POINTER, but the - * full 64bit physical address of the buffer. + * USB 8 byte control header physical address. + * Note that this is NOT A POINTER, but the + * full 64bit physical address of the buffer. * @param buffer Physical address of the data buffer in - * memory. Note that this is NOT A POINTER, but - * the full 64bit physical address of the - * buffer. This may be zero if buffer_length is - * zero. + * memory. Note that this is NOT A POINTER, but + * the full 64bit physical address of the + * buffer. This may be zero if buffer_length is + * zero. * @param buffer_length - * Length of buffer in bytes. + * Length of buffer in bytes. * @param callback Function to call when this transaction - * completes. If the return value of this - * function isn't an error, then this function - * is guaranteed to be called when the - * transaction completes. If this parameter is - * NULL, then the generic callback registered - * through cvmx_usb_register_callback is - * called. If both are NULL, then there is no - * way to know when a transaction completes. + * completes. If the return value of this + * function isn't an error, then this function + * is guaranteed to be called when the + * transaction completes. If this parameter is + * NULL, then the generic callback registered + * through cvmx_usb_register_callback is + * called. If both are NULL, then there is no + * way to know when a transaction completes. * @param user_data User supplied data returned when the - * callback is called. This is only used if - * callback in not NULL. + * callback is called. This is only used if + * callback in not NULL. * * @return A submitted transaction handle or negative on - * failure. Negative values are error codes. + * failure. Negative values are error codes. */ int cvmx_usb_submit_control(cvmx_usb_state_t *state, int pipe_handle, - uint64_t control_header, - uint64_t buffer, int buffer_length, - cvmx_usb_callback_func_t callback, - void *user_data) + uint64_t control_header, + uint64_t buffer, int buffer_length, + cvmx_usb_callback_func_t callback, + void *user_data) { - int submit_handle; - cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; - cvmx_usb_control_header_t *header = cvmx_phys_to_ptr(control_header); + int submit_handle; + cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; + cvmx_usb_control_header_t *header = cvmx_phys_to_ptr(control_header); - /* Pipe handle checking is done later in a common place */ - if (unlikely(!control_header)) - return -EINVAL; - /* Some drivers send a buffer with a zero length. God only knows why */ - if (unlikely(buffer && (buffer_length < 0))) - return -EINVAL; - if (unlikely(!buffer && (buffer_length != 0))) - return -EINVAL; - if ((header->s.request_type & 0x80) == 0) - buffer_length = le16_to_cpu(header->s.length); + /* Pipe handle checking is done later in a common place */ + if (unlikely(!control_header)) + return -EINVAL; + /* Some drivers send a buffer with a zero length. God only knows why */ + if (unlikely(buffer && (buffer_length < 0))) + return -EINVAL; + if (unlikely(!buffer && (buffer_length != 0))) + return -EINVAL; + if ((header->s.request_type & 0x80) == 0) + buffer_length = le16_to_cpu(header->s.length); - submit_handle = __cvmx_usb_submit_transaction(usb, pipe_handle, - CVMX_USB_TRANSFER_CONTROL, - 0, /* flags */ - buffer, - buffer_length, - control_header, - 0, /* iso_start_frame */ - 0, /* iso_number_packets */ - NULL, /* iso_packets */ - callback, - user_data); - return submit_handle; + submit_handle = __cvmx_usb_submit_transaction(usb, pipe_handle, + CVMX_USB_TRANSFER_CONTROL, + 0, /* flags */ + buffer, + buffer_length, + control_header, + 0, /* iso_start_frame */ + 0, /* iso_number_packets */ + NULL, /* iso_packets */ + callback, + user_data); + return submit_handle; } /** * Call to submit a USB Isochronous transfer to a pipe. * - * @param state USB device state populated by - * cvmx_usb_initialize(). + * @param state USB device state populated by + * cvmx_usb_initialize(). * @param pipe_handle - * Handle to the pipe for the transfer. + * Handle to the pipe for the transfer. * @param start_frame - * Number of frames into the future to schedule - * this transaction. - * @param flags Flags to control the transfer. See - * cvmx_usb_isochronous_flags_t for the flag - * definitions. + * Number of frames into the future to schedule + * this transaction. + * @param flags Flags to control the transfer. See + * cvmx_usb_isochronous_flags_t for the flag + * definitions. * @param number_packets - * Number of sequential packets to transfer. - * "packets" is a pointer to an array of this - * many packet structures. + * Number of sequential packets to transfer. + * "packets" is a pointer to an array of this + * many packet structures. * @param packets Description of each transfer packet as - * defined by cvmx_usb_iso_packet_t. The array - * pointed to here must stay valid until the - * complete callback is called. + * defined by cvmx_usb_iso_packet_t. The array + * pointed to here must stay valid until the + * complete callback is called. * @param buffer Physical address of the data buffer in - * memory. Note that this is NOT A POINTER, but - * the full 64bit physical address of the - * buffer. This may be zero if buffer_length is - * zero. + * memory. Note that this is NOT A POINTER, but + * the full 64bit physical address of the + * buffer. This may be zero if buffer_length is + * zero. * @param buffer_length - * Length of buffer in bytes. + * Length of buffer in bytes. * @param callback Function to call when this transaction - * completes. If the return value of this - * function isn't an error, then this function - * is guaranteed to be called when the - * transaction completes. If this parameter is - * NULL, then the generic callback registered - * through cvmx_usb_register_callback is - * called. If both are NULL, then there is no - * way to know when a transaction completes. + * completes. If the return value of this + * function isn't an error, then this function + * is guaranteed to be called when the + * transaction completes. If this parameter is + * NULL, then the generic callback registered + * through cvmx_usb_register_callback is + * called. If both are NULL, then there is no + * way to know when a transaction completes. * @param user_data User supplied data returned when the - * callback is called. This is only used if - * callback in not NULL. + * callback is called. This is only used if + * callback in not NULL. * * @return A submitted transaction handle or negative on - * failure. Negative values are error codes. + * failure. Negative values are error codes. */ int cvmx_usb_submit_isochronous(cvmx_usb_state_t *state, int pipe_handle, - int start_frame, int flags, - int number_packets, - cvmx_usb_iso_packet_t packets[], - uint64_t buffer, int buffer_length, - cvmx_usb_callback_func_t callback, - void *user_data) + int start_frame, int flags, + int number_packets, + cvmx_usb_iso_packet_t packets[], + uint64_t buffer, int buffer_length, + cvmx_usb_callback_func_t callback, + void *user_data) { - int submit_handle; - cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; + int submit_handle; + cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; - /* Pipe handle checking is done later in a common place */ - if (unlikely(start_frame < 0)) - return -EINVAL; - if (unlikely(flags & ~(CVMX_USB_ISOCHRONOUS_FLAGS_ALLOW_SHORT | CVMX_USB_ISOCHRONOUS_FLAGS_ASAP))) - return -EINVAL; - if (unlikely(number_packets < 1)) - return -EINVAL; - if (unlikely(!packets)) - return -EINVAL; - if (unlikely(!buffer)) - return -EINVAL; - if (unlikely(buffer_length < 0)) - return -EINVAL; + /* Pipe handle checking is done later in a common place */ + if (unlikely(start_frame < 0)) + return -EINVAL; + if (unlikely(flags & ~(CVMX_USB_ISOCHRONOUS_FLAGS_ALLOW_SHORT | CVMX_USB_ISOCHRONOUS_FLAGS_ASAP))) + return -EINVAL; + if (unlikely(number_packets < 1)) + return -EINVAL; + if (unlikely(!packets)) + return -EINVAL; + if (unlikely(!buffer)) + return -EINVAL; + if (unlikely(buffer_length < 0)) + return -EINVAL; - submit_handle = __cvmx_usb_submit_transaction(usb, pipe_handle, - CVMX_USB_TRANSFER_ISOCHRONOUS, - flags, - buffer, - buffer_length, - 0, /* control_header */ - start_frame, - number_packets, - packets, - callback, - user_data); - return submit_handle; + submit_handle = __cvmx_usb_submit_transaction(usb, pipe_handle, + CVMX_USB_TRANSFER_ISOCHRONOUS, + flags, + buffer, + buffer_length, + 0, /* control_header */ + start_frame, + number_packets, + packets, + callback, + user_data); + return submit_handle; } @@ -2279,55 +2267,55 @@ int cvmx_usb_submit_isochronous(cvmx_usb_state_t *state, int pipe_handle, * associated callback. * * @param state USB device state populated by - * cvmx_usb_initialize(). + * cvmx_usb_initialize(). * @param pipe_handle - * Pipe handle to cancel requests in. + * Pipe handle to cancel requests in. * @param submit_handle - * Handle to transaction to cancel, returned by the submit function. + * Handle to transaction to cancel, returned by the submit function. * * @return 0 or a negative error code. */ int cvmx_usb_cancel(cvmx_usb_state_t *state, int pipe_handle, int submit_handle) { - cvmx_usb_transaction_t *transaction; - cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; - cvmx_usb_pipe_t *pipe = usb->pipe + pipe_handle; + cvmx_usb_transaction_t *transaction; + cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; + cvmx_usb_pipe_t *pipe = usb->pipe + pipe_handle; - if (unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES))) - return -EINVAL; - if (unlikely((submit_handle < 0) || (submit_handle >= MAX_TRANSACTIONS))) - return -EINVAL; + if (unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES))) + return -EINVAL; + if (unlikely((submit_handle < 0) || (submit_handle >= MAX_TRANSACTIONS))) + return -EINVAL; - /* Fail if the pipe isn't open */ - if (unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0)) - return -EINVAL; + /* Fail if the pipe isn't open */ + if (unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0)) + return -EINVAL; - transaction = usb->transaction + submit_handle; + transaction = usb->transaction + submit_handle; - /* Fail if this transaction already completed */ - if (unlikely((transaction->flags & __CVMX_USB_TRANSACTION_FLAGS_IN_USE) == 0)) - return -EINVAL; + /* Fail if this transaction already completed */ + if (unlikely((transaction->flags & __CVMX_USB_TRANSACTION_FLAGS_IN_USE) == 0)) + return -EINVAL; - /* If the transaction is the HEAD of the queue and scheduled. We need to - treat it special */ - if ((pipe->head == transaction) && - (pipe->flags & __CVMX_USB_PIPE_FLAGS_SCHEDULED)) { - cvmx_usbcx_hccharx_t usbc_hcchar; + /* If the transaction is the HEAD of the queue and scheduled. We need to + treat it special */ + if ((pipe->head == transaction) && + (pipe->flags & __CVMX_USB_PIPE_FLAGS_SCHEDULED)) { + cvmx_usbcx_hccharx_t usbc_hcchar; - usb->pipe_for_channel[pipe->channel] = NULL; - pipe->flags &= ~__CVMX_USB_PIPE_FLAGS_SCHEDULED; + usb->pipe_for_channel[pipe->channel] = NULL; + pipe->flags &= ~__CVMX_USB_PIPE_FLAGS_SCHEDULED; - CVMX_SYNCW; + CVMX_SYNCW; - usbc_hcchar.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCCHARX(pipe->channel, usb->index)); - /* If the channel isn't enabled then the transaction already completed */ - if (usbc_hcchar.s.chena) { - usbc_hcchar.s.chdis = 1; - __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCCHARX(pipe->channel, usb->index), usbc_hcchar.u32); - } - } - __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_CANCEL); - return 0; + usbc_hcchar.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCCHARX(pipe->channel, usb->index)); + /* If the channel isn't enabled then the transaction already completed */ + if (usbc_hcchar.s.chena) { + usbc_hcchar.s.chdis = 1; + __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCCHARX(pipe->channel, usb->index), usbc_hcchar.u32); + } + } + __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_CANCEL); + return 0; } @@ -2336,32 +2324,32 @@ int cvmx_usb_cancel(cvmx_usb_state_t *state, int pipe_handle, int submit_handle) * does is call cvmx_usb_cancel() in a loop. * * @param state USB device state populated by - * cvmx_usb_initialize(). + * cvmx_usb_initialize(). * @param pipe_handle - * Pipe handle to cancel requests in. + * Pipe handle to cancel requests in. * * @return 0 or a negative error code. */ int cvmx_usb_cancel_all(cvmx_usb_state_t *state, int pipe_handle) { - cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; - cvmx_usb_pipe_t *pipe = usb->pipe + pipe_handle; + cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; + cvmx_usb_pipe_t *pipe = usb->pipe + pipe_handle; - if (unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES))) - return -EINVAL; + if (unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES))) + return -EINVAL; - /* Fail if the pipe isn't open */ - if (unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0)) - return -EINVAL; + /* Fail if the pipe isn't open */ + if (unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0)) + return -EINVAL; - /* Simply loop through and attempt to cancel each transaction */ - while (pipe->head) { - int result = cvmx_usb_cancel(state, pipe_handle, - __cvmx_usb_get_submit_handle(usb, pipe->head)); - if (unlikely(result != 0)) - return result; - } - return 0; + /* Simply loop through and attempt to cancel each transaction */ + while (pipe->head) { + int result = cvmx_usb_cancel(state, pipe_handle, + __cvmx_usb_get_submit_handle(usb, pipe->head)); + if (unlikely(result != 0)) + return result; + } + return 0; } @@ -2369,42 +2357,42 @@ int cvmx_usb_cancel_all(cvmx_usb_state_t *state, int pipe_handle) * Close a pipe created with cvmx_usb_open_pipe(). * * @param state USB device state populated by - * cvmx_usb_initialize(). + * cvmx_usb_initialize(). * @param pipe_handle - * Pipe handle to close. + * Pipe handle to close. * * @return 0 or a negative error code. EBUSY is returned if the pipe has * outstanding transfers. */ int cvmx_usb_close_pipe(cvmx_usb_state_t *state, int pipe_handle) { - cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; - cvmx_usb_pipe_t *pipe = usb->pipe + pipe_handle; + cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; + cvmx_usb_pipe_t *pipe = usb->pipe + pipe_handle; - if (unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES))) - return -EINVAL; + if (unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES))) + return -EINVAL; - /* Fail if the pipe isn't open */ - if (unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0)) - return -EINVAL; + /* Fail if the pipe isn't open */ + if (unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0)) + return -EINVAL; - /* Fail if the pipe has pending transactions */ - if (unlikely(pipe->head)) - return -EBUSY; + /* Fail if the pipe has pending transactions */ + if (unlikely(pipe->head)) + return -EBUSY; - pipe->flags = 0; - __cvmx_usb_remove_pipe(&usb->idle_pipes, pipe); - __cvmx_usb_append_pipe(&usb->free_pipes, pipe); + pipe->flags = 0; + __cvmx_usb_remove_pipe(&usb->idle_pipes, pipe); + __cvmx_usb_append_pipe(&usb->free_pipes, pipe); - return 0; + return 0; } /** * Register a function to be called when various USB events occur. * - * @param state USB device state populated by - * cvmx_usb_initialize(). + * @param state USB device state populated by + * cvmx_usb_initialize(). * @param reason Which event to register for. * @param callback Function to call when the event occurs. * @param user_data User data parameter to the function. @@ -2416,17 +2404,17 @@ int cvmx_usb_register_callback(cvmx_usb_state_t *state, cvmx_usb_callback_func_t callback, void *user_data) { - cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; + cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; - if (unlikely(reason >= __CVMX_USB_CALLBACK_END)) - return -EINVAL; - if (unlikely(!callback)) - return -EINVAL; + if (unlikely(reason >= __CVMX_USB_CALLBACK_END)) + return -EINVAL; + if (unlikely(!callback)) + return -EINVAL; - usb->callback[reason] = callback; - usb->callback_data[reason] = user_data; + usb->callback[reason] = callback; + usb->callback_data[reason] = user_data; - return 0; + return 0; } @@ -2435,20 +2423,20 @@ int cvmx_usb_register_callback(cvmx_usb_state_t *state, * number is always in the range of 0-0x7ff. * * @param state USB device state populated by - * cvmx_usb_initialize(). + * cvmx_usb_initialize(). * * @return USB frame number */ int cvmx_usb_get_frame_number(cvmx_usb_state_t *state) { - int frame_number; - cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; - cvmx_usbcx_hfnum_t usbc_hfnum; + int frame_number; + cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; + cvmx_usbcx_hfnum_t usbc_hfnum; - usbc_hfnum.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HFNUM(usb->index)); - frame_number = usbc_hfnum.s.frnum; + usbc_hfnum.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HFNUM(usb->index)); + frame_number = usbc_hfnum.s.frnum; - return frame_number; + return frame_number; } @@ -2456,391 +2444,365 @@ int cvmx_usb_get_frame_number(cvmx_usb_state_t *state) * @INTERNAL * Poll a channel for status * - * @param usb USB device + * @param usb USB device * @param channel Channel to poll * * @return Zero on success */ static int __cvmx_usb_poll_channel(cvmx_usb_internal_state_t *usb, int channel) { - cvmx_usbcx_hcintx_t usbc_hcint; - cvmx_usbcx_hctsizx_t usbc_hctsiz; - cvmx_usbcx_hccharx_t usbc_hcchar; - cvmx_usb_pipe_t *pipe; - cvmx_usb_transaction_t *transaction; - int bytes_this_transfer; - int bytes_in_last_packet; - int packets_processed; - int buffer_space_left; + cvmx_usbcx_hcintx_t usbc_hcint; + cvmx_usbcx_hctsizx_t usbc_hctsiz; + cvmx_usbcx_hccharx_t usbc_hcchar; + cvmx_usb_pipe_t *pipe; + cvmx_usb_transaction_t *transaction; + int bytes_this_transfer; + int bytes_in_last_packet; + int packets_processed; + int buffer_space_left; - /* Read the interrupt status bits for the channel */ - usbc_hcint.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCINTX(channel, usb->index)); + /* Read the interrupt status bits for the channel */ + usbc_hcint.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCINTX(channel, usb->index)); - if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) { - usbc_hcchar.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index)); + if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) { + usbc_hcchar.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index)); - if (usbc_hcchar.s.chena && usbc_hcchar.s.chdis) { - /* There seems to be a bug in CN31XX which can cause interrupt - IN transfers to get stuck until we do a write of HCCHARX - without changing things */ - __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index), usbc_hcchar.u32); - return 0; - } + if (usbc_hcchar.s.chena && usbc_hcchar.s.chdis) { + /* There seems to be a bug in CN31XX which can cause interrupt + IN transfers to get stuck until we do a write of HCCHARX + without changing things */ + __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index), usbc_hcchar.u32); + return 0; + } - /* In non DMA mode the channels don't halt themselves. We need to - manually disable channels that are left running */ - if (!usbc_hcint.s.chhltd) { - if (usbc_hcchar.s.chena) { - cvmx_usbcx_hcintmskx_t hcintmsk; - /* Disable all interrupts except CHHLTD */ - hcintmsk.u32 = 0; - hcintmsk.s.chhltdmsk = 1; - __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCINTMSKX(channel, usb->index), hcintmsk.u32); - usbc_hcchar.s.chdis = 1; - __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index), usbc_hcchar.u32); - return 0; - } - else if (usbc_hcint.s.xfercompl) { - /* Successful IN/OUT with transfer complete. Channel halt isn't needed */ - } - else { - cvmx_dprintf("USB%d: Channel %d interrupt without halt\n", usb->index, channel); - return 0; - } - } - } - else { - /* There is are no interrupts that we need to process when the channel is - still running */ - if (!usbc_hcint.s.chhltd) - return 0; - } + /* In non DMA mode the channels don't halt themselves. We need to + manually disable channels that are left running */ + if (!usbc_hcint.s.chhltd) { + if (usbc_hcchar.s.chena) { + cvmx_usbcx_hcintmskx_t hcintmsk; + /* Disable all interrupts except CHHLTD */ + hcintmsk.u32 = 0; + hcintmsk.s.chhltdmsk = 1; + __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCINTMSKX(channel, usb->index), hcintmsk.u32); + usbc_hcchar.s.chdis = 1; + __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index), usbc_hcchar.u32); + return 0; + } else if (usbc_hcint.s.xfercompl) { + /* Successful IN/OUT with transfer complete. Channel halt isn't needed */ + } else { + cvmx_dprintf("USB%d: Channel %d interrupt without halt\n", usb->index, channel); + return 0; + } + } + } else { + /* There is are no interrupts that we need to process when the channel is + still running */ + if (!usbc_hcint.s.chhltd) + return 0; + } - /* Disable the channel interrupts now that it is done */ - __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCINTMSKX(channel, usb->index), 0); - usb->idle_hardware_channels |= (1<index), 0); + usb->idle_hardware_channels |= (1<pipe_for_channel[channel]; - CVMX_PREFETCH(pipe, 0); - CVMX_PREFETCH(pipe, 128); - if (!pipe) - return 0; - transaction = pipe->head; - CVMX_PREFETCH0(transaction); + /* Make sure this channel is tied to a valid pipe */ + pipe = usb->pipe_for_channel[channel]; + CVMX_PREFETCH(pipe, 0); + CVMX_PREFETCH(pipe, 128); + if (!pipe) + return 0; + transaction = pipe->head; + CVMX_PREFETCH0(transaction); - /* Disconnect this pipe from the HW channel. Later the schedule function will - figure out which pipe needs to go */ - usb->pipe_for_channel[channel] = NULL; - pipe->flags &= ~__CVMX_USB_PIPE_FLAGS_SCHEDULED; + /* Disconnect this pipe from the HW channel. Later the schedule function will + figure out which pipe needs to go */ + usb->pipe_for_channel[channel] = NULL; + pipe->flags &= ~__CVMX_USB_PIPE_FLAGS_SCHEDULED; - /* Read the channel config info so we can figure out how much data - transfered */ - usbc_hcchar.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index)); - usbc_hctsiz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index)); + /* Read the channel config info so we can figure out how much data + transfered */ + usbc_hcchar.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index)); + usbc_hctsiz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index)); - /* Calculating the number of bytes successfully transferred is dependent on - the transfer direction */ - packets_processed = transaction->pktcnt - usbc_hctsiz.s.pktcnt; - if (usbc_hcchar.s.epdir) { - /* IN transactions are easy. For every byte received the hardware - decrements xfersize. All we need to do is subtract the current - value of xfersize from its starting value and we know how many - bytes were written to the buffer */ - bytes_this_transfer = transaction->xfersize - usbc_hctsiz.s.xfersize; - } - else { - /* OUT transaction don't decrement xfersize. Instead pktcnt is - decremented on every successful packet send. The hardware does - this when it receives an ACK, or NYET. If it doesn't - receive one of these responses pktcnt doesn't change */ - bytes_this_transfer = packets_processed * usbc_hcchar.s.mps; - /* The last packet may not be a full transfer if we didn't have - enough data */ - if (bytes_this_transfer > transaction->xfersize) - bytes_this_transfer = transaction->xfersize; - } - /* Figure out how many bytes were in the last packet of the transfer */ - if (packets_processed) - bytes_in_last_packet = bytes_this_transfer - (packets_processed-1) * usbc_hcchar.s.mps; - else - bytes_in_last_packet = bytes_this_transfer; + /* Calculating the number of bytes successfully transferred is dependent on + the transfer direction */ + packets_processed = transaction->pktcnt - usbc_hctsiz.s.pktcnt; + if (usbc_hcchar.s.epdir) { + /* IN transactions are easy. For every byte received the hardware + decrements xfersize. All we need to do is subtract the current + value of xfersize from its starting value and we know how many + bytes were written to the buffer */ + bytes_this_transfer = transaction->xfersize - usbc_hctsiz.s.xfersize; + } else { + /* OUT transaction don't decrement xfersize. Instead pktcnt is + decremented on every successful packet send. The hardware does + this when it receives an ACK, or NYET. If it doesn't + receive one of these responses pktcnt doesn't change */ + bytes_this_transfer = packets_processed * usbc_hcchar.s.mps; + /* The last packet may not be a full transfer if we didn't have + enough data */ + if (bytes_this_transfer > transaction->xfersize) + bytes_this_transfer = transaction->xfersize; + } + /* Figure out how many bytes were in the last packet of the transfer */ + if (packets_processed) + bytes_in_last_packet = bytes_this_transfer - (packets_processed-1) * usbc_hcchar.s.mps; + else + bytes_in_last_packet = bytes_this_transfer; - /* As a special case, setup transactions output the setup header, not - the user's data. For this reason we don't count setup data as bytes - transferred */ - if ((transaction->stage == CVMX_USB_STAGE_SETUP) || - (transaction->stage == CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE)) - bytes_this_transfer = 0; + /* As a special case, setup transactions output the setup header, not + the user's data. For this reason we don't count setup data as bytes + transferred */ + if ((transaction->stage == CVMX_USB_STAGE_SETUP) || + (transaction->stage == CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE)) + bytes_this_transfer = 0; - /* Add the bytes transferred to the running total. It is important that - bytes_this_transfer doesn't count any data that needs to be - retransmitted */ - transaction->actual_bytes += bytes_this_transfer; - if (transaction->type == CVMX_USB_TRANSFER_ISOCHRONOUS) - buffer_space_left = transaction->iso_packets[0].length - transaction->actual_bytes; - else - buffer_space_left = transaction->buffer_length - transaction->actual_bytes; + /* Add the bytes transferred to the running total. It is important that + bytes_this_transfer doesn't count any data that needs to be + retransmitted */ + transaction->actual_bytes += bytes_this_transfer; + if (transaction->type == CVMX_USB_TRANSFER_ISOCHRONOUS) + buffer_space_left = transaction->iso_packets[0].length - transaction->actual_bytes; + else + buffer_space_left = transaction->buffer_length - transaction->actual_bytes; - /* We need to remember the PID toggle state for the next transaction. The - hardware already updated it for the next transaction */ - pipe->pid_toggle = !(usbc_hctsiz.s.pid == 0); + /* We need to remember the PID toggle state for the next transaction. The + hardware already updated it for the next transaction */ + pipe->pid_toggle = !(usbc_hctsiz.s.pid == 0); - /* For high speed bulk out, assume the next transaction will need to do a - ping before proceeding. If this isn't true the ACK processing below - will clear this flag */ - if ((pipe->device_speed == CVMX_USB_SPEED_HIGH) && - (pipe->transfer_type == CVMX_USB_TRANSFER_BULK) && - (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT)) - pipe->flags |= __CVMX_USB_PIPE_FLAGS_NEED_PING; + /* For high speed bulk out, assume the next transaction will need to do a + ping before proceeding. If this isn't true the ACK processing below + will clear this flag */ + if ((pipe->device_speed == CVMX_USB_SPEED_HIGH) && + (pipe->transfer_type == CVMX_USB_TRANSFER_BULK) && + (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT)) + pipe->flags |= __CVMX_USB_PIPE_FLAGS_NEED_PING; - if (usbc_hcint.s.stall) { - /* STALL as a response means this transaction cannot be completed - because the device can't process transactions. Tell the user. Any - data that was transferred will be counted on the actual bytes - transferred */ - pipe->pid_toggle = 0; - __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_STALL); - } - else if (usbc_hcint.s.xacterr) { - /* We know at least one packet worked if we get a ACK or NAK. Reset the retry counter */ - if (usbc_hcint.s.nak || usbc_hcint.s.ack) - transaction->retries = 0; - transaction->retries++; - if (transaction->retries > MAX_RETRIES) { - /* XactErr as a response means the device signaled something wrong with - the transfer. For example, PID toggle errors cause these */ - __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_XACTERR); - } - else { - /* If this was a split then clear our split in progress marker */ - if (usb->active_split == transaction) - usb->active_split = NULL; - /* Rewind to the beginning of the transaction by anding off the - split complete bit */ - transaction->stage &= ~1; - pipe->split_sc_frame = -1; - pipe->next_tx_frame += pipe->interval; - if (pipe->next_tx_frame < usb->frame_number) - pipe->next_tx_frame = usb->frame_number + pipe->interval - - (usb->frame_number - pipe->next_tx_frame) % pipe->interval; - } - } - else if (usbc_hcint.s.bblerr) - { - /* Babble Error (BblErr) */ - __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_BABBLEERR); - } - else if (usbc_hcint.s.datatglerr) - { - /* We'll retry the exact same transaction again */ - transaction->retries++; - } - else if (usbc_hcint.s.nyet) { - /* NYET as a response is only allowed in three cases: as a response to - a ping, as a response to a split transaction, and as a response to - a bulk out. The ping case is handled by hardware, so we only have - splits and bulk out */ - if (!__cvmx_usb_pipe_needs_split(usb, pipe)) { - transaction->retries = 0; - /* If there is more data to go then we need to try again. Otherwise - this transaction is complete */ - if ((buffer_space_left == 0) || (bytes_in_last_packet < pipe->max_packet)) - __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS); - } - else { - /* Split transactions retry the split complete 4 times then rewind - to the start split and do the entire transactions again */ - transaction->retries++; - if ((transaction->retries & 0x3) == 0) { - /* Rewind to the beginning of the transaction by anding off the - split complete bit */ - transaction->stage &= ~1; - pipe->split_sc_frame = -1; - } - } - } - else if (usbc_hcint.s.ack) { - transaction->retries = 0; - /* The ACK bit can only be checked after the other error bits. This is - because a multi packet transfer may succeed in a number of packets - and then get a different response on the last packet. In this case - both ACK and the last response bit will be set. If none of the - other response bits is set, then the last packet must have been an - ACK */ + if (usbc_hcint.s.stall) { + /* STALL as a response means this transaction cannot be completed + because the device can't process transactions. Tell the user. Any + data that was transferred will be counted on the actual bytes + transferred */ + pipe->pid_toggle = 0; + __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_STALL); + } else if (usbc_hcint.s.xacterr) { + /* We know at least one packet worked if we get a ACK or NAK. Reset the retry counter */ + if (usbc_hcint.s.nak || usbc_hcint.s.ack) + transaction->retries = 0; + transaction->retries++; + if (transaction->retries > MAX_RETRIES) { + /* XactErr as a response means the device signaled something wrong with + the transfer. For example, PID toggle errors cause these */ + __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_XACTERR); + } else { + /* If this was a split then clear our split in progress marker */ + if (usb->active_split == transaction) + usb->active_split = NULL; + /* Rewind to the beginning of the transaction by anding off the + split complete bit */ + transaction->stage &= ~1; + pipe->split_sc_frame = -1; + pipe->next_tx_frame += pipe->interval; + if (pipe->next_tx_frame < usb->frame_number) + pipe->next_tx_frame = usb->frame_number + pipe->interval - + (usb->frame_number - pipe->next_tx_frame) % pipe->interval; + } + } else if (usbc_hcint.s.bblerr) { + /* Babble Error (BblErr) */ + __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_BABBLEERR); + } else if (usbc_hcint.s.datatglerr) { + /* We'll retry the exact same transaction again */ + transaction->retries++; + } else if (usbc_hcint.s.nyet) { + /* NYET as a response is only allowed in three cases: as a response to + a ping, as a response to a split transaction, and as a response to + a bulk out. The ping case is handled by hardware, so we only have + splits and bulk out */ + if (!__cvmx_usb_pipe_needs_split(usb, pipe)) { + transaction->retries = 0; + /* If there is more data to go then we need to try again. Otherwise + this transaction is complete */ + if ((buffer_space_left == 0) || (bytes_in_last_packet < pipe->max_packet)) + __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS); + } else { + /* Split transactions retry the split complete 4 times then rewind + to the start split and do the entire transactions again */ + transaction->retries++; + if ((transaction->retries & 0x3) == 0) { + /* Rewind to the beginning of the transaction by anding off the + split complete bit */ + transaction->stage &= ~1; + pipe->split_sc_frame = -1; + } + } + } else if (usbc_hcint.s.ack) { + transaction->retries = 0; + /* The ACK bit can only be checked after the other error bits. This is + because a multi packet transfer may succeed in a number of packets + and then get a different response on the last packet. In this case + both ACK and the last response bit will be set. If none of the + other response bits is set, then the last packet must have been an + ACK */ - /* Since we got an ACK, we know we don't need to do a ping on this - pipe */ - pipe->flags &= ~__CVMX_USB_PIPE_FLAGS_NEED_PING; + /* Since we got an ACK, we know we don't need to do a ping on this + pipe */ + pipe->flags &= ~__CVMX_USB_PIPE_FLAGS_NEED_PING; - switch (transaction->type) - { - case CVMX_USB_TRANSFER_CONTROL: - switch (transaction->stage) - { - case CVMX_USB_STAGE_NON_CONTROL: - case CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE: - /* This should be impossible */ - __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_ERROR); - break; - case CVMX_USB_STAGE_SETUP: - pipe->pid_toggle = 1; - if (__cvmx_usb_pipe_needs_split(usb, pipe)) - transaction->stage = CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE; - else { - cvmx_usb_control_header_t *header = cvmx_phys_to_ptr(transaction->control_header); - if (header->s.length) - transaction->stage = CVMX_USB_STAGE_DATA; - else - transaction->stage = CVMX_USB_STAGE_STATUS; - } - break; - case CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE: - { - cvmx_usb_control_header_t *header = cvmx_phys_to_ptr(transaction->control_header); - if (header->s.length) - transaction->stage = CVMX_USB_STAGE_DATA; - else - transaction->stage = CVMX_USB_STAGE_STATUS; - } - break; - case CVMX_USB_STAGE_DATA: - if (__cvmx_usb_pipe_needs_split(usb, pipe)) { - transaction->stage = CVMX_USB_STAGE_DATA_SPLIT_COMPLETE; - /* For setup OUT data that are splits, the hardware - doesn't appear to count transferred data. Here - we manually update the data transferred */ - if (!usbc_hcchar.s.epdir) { - if (buffer_space_left < pipe->max_packet) - transaction->actual_bytes += buffer_space_left; - else - transaction->actual_bytes += pipe->max_packet; - } - } - else if ((buffer_space_left == 0) || (bytes_in_last_packet < pipe->max_packet)) { - pipe->pid_toggle = 1; - transaction->stage = CVMX_USB_STAGE_STATUS; - } - break; - case CVMX_USB_STAGE_DATA_SPLIT_COMPLETE: - if ((buffer_space_left == 0) || (bytes_in_last_packet < pipe->max_packet)) { - pipe->pid_toggle = 1; - transaction->stage = CVMX_USB_STAGE_STATUS; - } - else { - transaction->stage = CVMX_USB_STAGE_DATA; - } - break; - case CVMX_USB_STAGE_STATUS: - if (__cvmx_usb_pipe_needs_split(usb, pipe)) - transaction->stage = CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE; - else - __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS); - break; - case CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE: - __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS); - break; - } - break; - case CVMX_USB_TRANSFER_BULK: - case CVMX_USB_TRANSFER_INTERRUPT: - /* The only time a bulk transfer isn't complete when - it finishes with an ACK is during a split transaction. For - splits we need to continue the transfer if more data is - needed */ - if (__cvmx_usb_pipe_needs_split(usb, pipe)) { - if (transaction->stage == CVMX_USB_STAGE_NON_CONTROL) - transaction->stage = CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE; - else { - if (buffer_space_left && (bytes_in_last_packet == pipe->max_packet)) - transaction->stage = CVMX_USB_STAGE_NON_CONTROL; - else { - if (transaction->type == CVMX_USB_TRANSFER_INTERRUPT) - pipe->next_tx_frame += pipe->interval; - __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS); - } - } - } - else { - if ((pipe->device_speed == CVMX_USB_SPEED_HIGH) && - (pipe->transfer_type == CVMX_USB_TRANSFER_BULK) && - (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT) && - (usbc_hcint.s.nak)) - pipe->flags |= __CVMX_USB_PIPE_FLAGS_NEED_PING; - if (!buffer_space_left || (bytes_in_last_packet < pipe->max_packet)) { - if (transaction->type == CVMX_USB_TRANSFER_INTERRUPT) - pipe->next_tx_frame += pipe->interval; - __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS); - } - } - break; - case CVMX_USB_TRANSFER_ISOCHRONOUS: - if (__cvmx_usb_pipe_needs_split(usb, pipe)) { - /* ISOCHRONOUS OUT splits don't require a complete split stage. - Instead they use a sequence of begin OUT splits to transfer - the data 188 bytes at a time. Once the transfer is complete, - the pipe sleeps until the next schedule interval */ - if (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT) { - /* If no space left or this wasn't a max size packet then - this transfer is complete. Otherwise start it again - to send the next 188 bytes */ - if (!buffer_space_left || (bytes_this_transfer < 188)) { - pipe->next_tx_frame += pipe->interval; - __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS); - } - } - else { - if (transaction->stage == CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE) { - /* We are in the incoming data phase. Keep getting - data until we run out of space or get a small - packet */ - if ((buffer_space_left == 0) || (bytes_in_last_packet < pipe->max_packet)) { - pipe->next_tx_frame += pipe->interval; - __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS); - } - } - else - transaction->stage = CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE; - } - } - else { - pipe->next_tx_frame += pipe->interval; - __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS); - } - break; - } - } - else if (usbc_hcint.s.nak) { - /* If this was a split then clear our split in progress marker */ - if (usb->active_split == transaction) - usb->active_split = NULL; - /* NAK as a response means the device couldn't accept the transaction, - but it should be retried in the future. Rewind to the beginning of - the transaction by anding off the split complete bit. Retry in the - next interval */ - transaction->retries = 0; - transaction->stage &= ~1; - pipe->next_tx_frame += pipe->interval; - if (pipe->next_tx_frame < usb->frame_number) - pipe->next_tx_frame = usb->frame_number + pipe->interval - - (usb->frame_number - pipe->next_tx_frame) % pipe->interval; - } - else { - cvmx_usb_port_status_t port; - port = cvmx_usb_get_status((cvmx_usb_state_t *)usb); - if (port.port_enabled) - { - /* We'll retry the exact same transaction again */ - transaction->retries++; - } - else - { - /* We get channel halted interrupts with no result bits sets when the - cable is unplugged */ - __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_ERROR); - } - } - return 0; + switch (transaction->type) { + case CVMX_USB_TRANSFER_CONTROL: + switch (transaction->stage) { + case CVMX_USB_STAGE_NON_CONTROL: + case CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE: + /* This should be impossible */ + __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_ERROR); + break; + case CVMX_USB_STAGE_SETUP: + pipe->pid_toggle = 1; + if (__cvmx_usb_pipe_needs_split(usb, pipe)) + transaction->stage = CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE; + else { + cvmx_usb_control_header_t *header = cvmx_phys_to_ptr(transaction->control_header); + if (header->s.length) + transaction->stage = CVMX_USB_STAGE_DATA; + else + transaction->stage = CVMX_USB_STAGE_STATUS; + } + break; + case CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE: + { + cvmx_usb_control_header_t *header = cvmx_phys_to_ptr(transaction->control_header); + if (header->s.length) + transaction->stage = CVMX_USB_STAGE_DATA; + else + transaction->stage = CVMX_USB_STAGE_STATUS; + } + break; + case CVMX_USB_STAGE_DATA: + if (__cvmx_usb_pipe_needs_split(usb, pipe)) { + transaction->stage = CVMX_USB_STAGE_DATA_SPLIT_COMPLETE; + /* For setup OUT data that are splits, the hardware + doesn't appear to count transferred data. Here + we manually update the data transferred */ + if (!usbc_hcchar.s.epdir) { + if (buffer_space_left < pipe->max_packet) + transaction->actual_bytes += buffer_space_left; + else + transaction->actual_bytes += pipe->max_packet; + } + } else if ((buffer_space_left == 0) || (bytes_in_last_packet < pipe->max_packet)) { + pipe->pid_toggle = 1; + transaction->stage = CVMX_USB_STAGE_STATUS; + } + break; + case CVMX_USB_STAGE_DATA_SPLIT_COMPLETE: + if ((buffer_space_left == 0) || (bytes_in_last_packet < pipe->max_packet)) { + pipe->pid_toggle = 1; + transaction->stage = CVMX_USB_STAGE_STATUS; + } else { + transaction->stage = CVMX_USB_STAGE_DATA; + } + break; + case CVMX_USB_STAGE_STATUS: + if (__cvmx_usb_pipe_needs_split(usb, pipe)) + transaction->stage = CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE; + else + __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS); + break; + case CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE: + __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS); + break; + } + break; + case CVMX_USB_TRANSFER_BULK: + case CVMX_USB_TRANSFER_INTERRUPT: + /* The only time a bulk transfer isn't complete when + it finishes with an ACK is during a split transaction. For + splits we need to continue the transfer if more data is + needed */ + if (__cvmx_usb_pipe_needs_split(usb, pipe)) { + if (transaction->stage == CVMX_USB_STAGE_NON_CONTROL) + transaction->stage = CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE; + else { + if (buffer_space_left && (bytes_in_last_packet == pipe->max_packet)) + transaction->stage = CVMX_USB_STAGE_NON_CONTROL; + else { + if (transaction->type == CVMX_USB_TRANSFER_INTERRUPT) + pipe->next_tx_frame += pipe->interval; + __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS); + } + } + } else { + if ((pipe->device_speed == CVMX_USB_SPEED_HIGH) && + (pipe->transfer_type == CVMX_USB_TRANSFER_BULK) && + (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT) && + (usbc_hcint.s.nak)) + pipe->flags |= __CVMX_USB_PIPE_FLAGS_NEED_PING; + if (!buffer_space_left || (bytes_in_last_packet < pipe->max_packet)) { + if (transaction->type == CVMX_USB_TRANSFER_INTERRUPT) + pipe->next_tx_frame += pipe->interval; + __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS); + } + } + break; + case CVMX_USB_TRANSFER_ISOCHRONOUS: + if (__cvmx_usb_pipe_needs_split(usb, pipe)) { + /* ISOCHRONOUS OUT splits don't require a complete split stage. + Instead they use a sequence of begin OUT splits to transfer + the data 188 bytes at a time. Once the transfer is complete, + the pipe sleeps until the next schedule interval */ + if (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT) { + /* If no space left or this wasn't a max size packet then + this transfer is complete. Otherwise start it again + to send the next 188 bytes */ + if (!buffer_space_left || (bytes_this_transfer < 188)) { + pipe->next_tx_frame += pipe->interval; + __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS); + } + } else { + if (transaction->stage == CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE) { + /* We are in the incoming data phase. Keep getting + data until we run out of space or get a small + packet */ + if ((buffer_space_left == 0) || (bytes_in_last_packet < pipe->max_packet)) { + pipe->next_tx_frame += pipe->interval; + __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS); + } + } else + transaction->stage = CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE; + } + } else { + pipe->next_tx_frame += pipe->interval; + __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS); + } + break; + } + } else if (usbc_hcint.s.nak) { + /* If this was a split then clear our split in progress marker */ + if (usb->active_split == transaction) + usb->active_split = NULL; + /* NAK as a response means the device couldn't accept the transaction, + but it should be retried in the future. Rewind to the beginning of + the transaction by anding off the split complete bit. Retry in the + next interval */ + transaction->retries = 0; + transaction->stage &= ~1; + pipe->next_tx_frame += pipe->interval; + if (pipe->next_tx_frame < usb->frame_number) + pipe->next_tx_frame = usb->frame_number + pipe->interval - + (usb->frame_number - pipe->next_tx_frame) % pipe->interval; + } else { + cvmx_usb_port_status_t port; + port = cvmx_usb_get_status((cvmx_usb_state_t *)usb); + if (port.port_enabled) { + /* We'll retry the exact same transaction again */ + transaction->retries++; + } else { + /* We get channel halted interrupts with no result bits sets when the + cable is unplugged */ + __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_ERROR); + } + } + return 0; } @@ -2850,93 +2812,93 @@ static int __cvmx_usb_poll_channel(cvmx_usb_internal_state_t *usb, int channel) * handler for the USB controller. It can also be called * periodically in a loop for non-interrupt based operation. * - * @param state USB device state populated by - * cvmx_usb_initialize(). + * @param state USB device state populated by + * cvmx_usb_initialize(). * * @return 0 or a negative error code. */ int cvmx_usb_poll(cvmx_usb_state_t *state) { - cvmx_usbcx_hfnum_t usbc_hfnum; - cvmx_usbcx_gintsts_t usbc_gintsts; - cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t*)state; + cvmx_usbcx_hfnum_t usbc_hfnum; + cvmx_usbcx_gintsts_t usbc_gintsts; + cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; - CVMX_PREFETCH(usb, 0); - CVMX_PREFETCH(usb, 1*128); - CVMX_PREFETCH(usb, 2*128); - CVMX_PREFETCH(usb, 3*128); - CVMX_PREFETCH(usb, 4*128); + CVMX_PREFETCH(usb, 0); + CVMX_PREFETCH(usb, 1*128); + CVMX_PREFETCH(usb, 2*128); + CVMX_PREFETCH(usb, 3*128); + CVMX_PREFETCH(usb, 4*128); - /* Update the frame counter */ - usbc_hfnum.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HFNUM(usb->index)); - if ((usb->frame_number&0x3fff) > usbc_hfnum.s.frnum) - usb->frame_number += 0x4000; - usb->frame_number &= ~0x3fffull; - usb->frame_number |= usbc_hfnum.s.frnum; + /* Update the frame counter */ + usbc_hfnum.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HFNUM(usb->index)); + if ((usb->frame_number&0x3fff) > usbc_hfnum.s.frnum) + usb->frame_number += 0x4000; + usb->frame_number &= ~0x3fffull; + usb->frame_number |= usbc_hfnum.s.frnum; - /* Read the pending interrupts */ - usbc_gintsts.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GINTSTS(usb->index)); + /* Read the pending interrupts */ + usbc_gintsts.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GINTSTS(usb->index)); - /* Clear the interrupts now that we know about them */ - __cvmx_usb_write_csr32(usb, CVMX_USBCX_GINTSTS(usb->index), usbc_gintsts.u32); + /* Clear the interrupts now that we know about them */ + __cvmx_usb_write_csr32(usb, CVMX_USBCX_GINTSTS(usb->index), usbc_gintsts.u32); - if (usbc_gintsts.s.rxflvl) { - /* RxFIFO Non-Empty (RxFLvl) - Indicates that there is at least one packet pending to be read - from the RxFIFO. */ - /* In DMA mode this is handled by hardware */ - if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) - __cvmx_usb_poll_rx_fifo(usb); - } - if (usbc_gintsts.s.ptxfemp || usbc_gintsts.s.nptxfemp) { - /* Fill the Tx FIFOs when not in DMA mode */ - if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) - __cvmx_usb_poll_tx_fifo(usb); - } - if (usbc_gintsts.s.disconnint || usbc_gintsts.s.prtint) { - cvmx_usbcx_hprt_t usbc_hprt; - /* Disconnect Detected Interrupt (DisconnInt) - Asserted when a device disconnect is detected. */ + if (usbc_gintsts.s.rxflvl) { + /* RxFIFO Non-Empty (RxFLvl) + Indicates that there is at least one packet pending to be read + from the RxFIFO. */ + /* In DMA mode this is handled by hardware */ + if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) + __cvmx_usb_poll_rx_fifo(usb); + } + if (usbc_gintsts.s.ptxfemp || usbc_gintsts.s.nptxfemp) { + /* Fill the Tx FIFOs when not in DMA mode */ + if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) + __cvmx_usb_poll_tx_fifo(usb); + } + if (usbc_gintsts.s.disconnint || usbc_gintsts.s.prtint) { + cvmx_usbcx_hprt_t usbc_hprt; + /* Disconnect Detected Interrupt (DisconnInt) + Asserted when a device disconnect is detected. */ - /* Host Port Interrupt (PrtInt) - The core sets this bit to indicate a change in port status of one - of the O2P USB core ports in Host mode. The application must - read the Host Port Control and Status (HPRT) register to - determine the exact event that caused this interrupt. The - application must clear the appropriate status bit in the Host Port - Control and Status register to clear this bit. */ + /* Host Port Interrupt (PrtInt) + The core sets this bit to indicate a change in port status of one + of the O2P USB core ports in Host mode. The application must + read the Host Port Control and Status (HPRT) register to + determine the exact event that caused this interrupt. The + application must clear the appropriate status bit in the Host Port + Control and Status register to clear this bit. */ - /* Call the user's port callback */ - __cvmx_usb_perform_callback(usb, NULL, NULL, - CVMX_USB_CALLBACK_PORT_CHANGED, - CVMX_USB_COMPLETE_SUCCESS); - /* Clear the port change bits */ - usbc_hprt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPRT(usb->index)); - usbc_hprt.s.prtena = 0; - __cvmx_usb_write_csr32(usb, CVMX_USBCX_HPRT(usb->index), usbc_hprt.u32); - } - if (usbc_gintsts.s.hchint) { - /* Host Channels Interrupt (HChInt) - The core sets this bit to indicate that an interrupt is pending on - one of the channels of the core (in Host mode). The application - must read the Host All Channels Interrupt (HAINT) register to - determine the exact number of the channel on which the - interrupt occurred, and then read the corresponding Host - Channel-n Interrupt (HCINTn) register to determine the exact - cause of the interrupt. The application must clear the - appropriate status bit in the HCINTn register to clear this bit. */ - cvmx_usbcx_haint_t usbc_haint; - usbc_haint.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HAINT(usb->index)); - while (usbc_haint.u32) { - int channel; - CVMX_CLZ(channel, usbc_haint.u32); - channel = 31 - channel; - __cvmx_usb_poll_channel(usb, channel); - usbc_haint.u32 ^= 1<index)); + usbc_hprt.s.prtena = 0; + __cvmx_usb_write_csr32(usb, CVMX_USBCX_HPRT(usb->index), usbc_hprt.u32); + } + if (usbc_gintsts.s.hchint) { + /* Host Channels Interrupt (HChInt) + The core sets this bit to indicate that an interrupt is pending on + one of the channels of the core (in Host mode). The application + must read the Host All Channels Interrupt (HAINT) register to + determine the exact number of the channel on which the + interrupt occurred, and then read the corresponding Host + Channel-n Interrupt (HCINTn) register to determine the exact + cause of the interrupt. The application must clear the + appropriate status bit in the HCINTn register to clear this bit. */ + cvmx_usbcx_haint_t usbc_haint; + usbc_haint.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HAINT(usb->index)); + while (usbc_haint.u32) { + int channel; + CVMX_CLZ(channel, usbc_haint.u32); + channel = 31 - channel; + __cvmx_usb_poll_channel(usb, channel); + usbc_haint.u32 ^= 1< Date: Mon, 29 Jul 2013 20:07:54 +0300 Subject: [PATCH 1049/3400] staging: octeon-usb: cvmx-usb: reformat long comments Reformat long comments according to multi-line comment style. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.c | 717 +++++++++++++++++--------- 1 file changed, 462 insertions(+), 255 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.c b/drivers/staging/octeon-usb/cvmx-usb.c index e8fad48b1bb5..025671a2d5b1 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.c +++ b/drivers/staging/octeon-usb/cvmx-usb.c @@ -78,9 +78,11 @@ #define MAX_TRANSFER_BYTES ((1<<19)-1) /* The low level hardware can transfer a maximum of this number of bytes in each transfer. The field is 19 bits wide */ #define MAX_TRANSFER_PACKETS ((1<<10)-1) /* The low level hardware can transfer a maximum of this number of packets in each transfer. The field is 10 bits wide */ -/* These defines disable the normal read and write csr. This is so I can add - extra debug stuff to the usb specific version and I won't use the normal - version by mistake */ +/* + * These defines disable the normal read and write csr. This is so I can add + * extra debug stuff to the usb specific version and I won't use the normal + * version by mistake + */ #define cvmx_read_csr use_cvmx_usb_read_csr64_instead_of_cvmx_read_csr #define cvmx_write_csr use_cvmx_usb_write_csr64_instead_of_cvmx_write_csr @@ -227,8 +229,10 @@ typedef struct { } while (0); \ result; }) -/* This macro logically sets a single field in a CSR. It does the sequence - read, modify, and write */ +/* + * This macro logically sets a single field in a CSR. It does the sequence + * read, modify, and write + */ #define USB_SET_FIELD32(address, type, field, value) \ do { \ type c; \ @@ -562,23 +566,30 @@ int cvmx_usb_initialize(cvmx_usb_state_t *state, int usb_port_number, __cvmx_usb_append_pipe(&usb->free_pipes, usb->pipe + i); } - /* Power On Reset and PHY Initialization */ - - /* 1. Wait for DCOK to assert (nothing to do) */ - /* 2a. Write USBN0/1_CLK_CTL[POR] = 1 and - USBN0/1_CLK_CTL[HRST,PRST,HCLK_RST] = 0 */ + /* + * Power On Reset and PHY Initialization + * + * 1. Wait for DCOK to assert (nothing to do) + * + * 2a. Write USBN0/1_CLK_CTL[POR] = 1 and + * USBN0/1_CLK_CTL[HRST,PRST,HCLK_RST] = 0 + */ usbn_clk_ctl.u64 = __cvmx_usb_read_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index)); usbn_clk_ctl.s.por = 1; usbn_clk_ctl.s.hrst = 0; usbn_clk_ctl.s.prst = 0; usbn_clk_ctl.s.hclk_rst = 0; usbn_clk_ctl.s.enable = 0; - /* 2b. Select the USB reference clock/crystal parameters by writing - appropriate values to USBN0/1_CLK_CTL[P_C_SEL, P_RTYPE, P_COM_ON] */ + /* + * 2b. Select the USB reference clock/crystal parameters by writing + * appropriate values to USBN0/1_CLK_CTL[P_C_SEL, P_RTYPE, P_COM_ON] + */ if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND) { - /* The USB port uses 12/24/48MHz 2.5V board clock - source at USB_XO. USB_XI should be tied to GND. - Most Octeon evaluation boards require this setting */ + /* + * The USB port uses 12/24/48MHz 2.5V board clock + * source at USB_XO. USB_XI should be tied to GND. + * Most Octeon evaluation boards require this setting + */ if (OCTEON_IS_MODEL(OCTEON_CN3XXX)) { usbn_clk_ctl.cn31xx.p_rclk = 1; /* From CN31XX,CN30XX manual */ usbn_clk_ctl.cn31xx.p_xenbn = 0; @@ -599,8 +610,10 @@ int cvmx_usb_initialize(cvmx_usb_state_t *state, int usb_port_number, break; } } else { - /* The USB port uses a 12MHz crystal as clock source - at USB_XO and USB_XI */ + /* + * The USB port uses a 12MHz crystal as clock source + * at USB_XO and USB_XI + */ if (OCTEON_IS_MODEL(OCTEON_CN3XXX)) { usbn_clk_ctl.cn31xx.p_rclk = 1; /* From CN31XX,CN30XX manual */ usbn_clk_ctl.cn31xx.p_xenbn = 1; @@ -611,9 +624,11 @@ int cvmx_usb_initialize(cvmx_usb_state_t *state, int usb_port_number, usbn_clk_ctl.s.p_c_sel = 0; } - /* 2c. Select the HCLK via writing USBN0/1_CLK_CTL[DIVIDE, DIVIDE2] and - setting USBN0/1_CLK_CTL[ENABLE] = 1. Divide the core clock down such - that USB is as close as possible to 125Mhz */ + /* + * 2c. Select the HCLK via writing USBN0/1_CLK_CTL[DIVIDE, DIVIDE2] and + * setting USBN0/1_CLK_CTL[ENABLE] = 1. Divide the core clock down + * such that USB is as close as possible to 125Mhz + */ { int divisor = (octeon_get_clock_rate()+125000000-1)/125000000; if (divisor < 4) /* Lower than 4 doesn't seem to work properly */ @@ -629,41 +644,55 @@ int cvmx_usb_initialize(cvmx_usb_state_t *state, int usb_port_number, usbn_clk_ctl.u64); /* 2e. Wait 64 core-clock cycles for HCLK to stabilize */ cvmx_wait(64); - /* 3. Program the power-on reset field in the USBN clock-control register: - USBN_CLK_CTL[POR] = 0 */ + /* + * 3. Program the power-on reset field in the USBN clock-control + * register: + * USBN_CLK_CTL[POR] = 0 + */ usbn_clk_ctl.s.por = 0; __cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index), usbn_clk_ctl.u64); /* 4. Wait 1 ms for PHY clock to start */ mdelay(1); - /* 5. Program the Reset input from automatic test equipment field in the - USBP control and status register: USBN_USBP_CTL_STATUS[ATE_RESET] = 1 */ + /* + * 5. Program the Reset input from automatic test equipment field in the + * USBP control and status register: + * USBN_USBP_CTL_STATUS[ATE_RESET] = 1 + */ usbn_usbp_ctl_status.u64 = __cvmx_usb_read_csr64(usb, CVMX_USBNX_USBP_CTL_STATUS(usb->index)); usbn_usbp_ctl_status.s.ate_reset = 1; __cvmx_usb_write_csr64(usb, CVMX_USBNX_USBP_CTL_STATUS(usb->index), usbn_usbp_ctl_status.u64); /* 6. Wait 10 cycles */ cvmx_wait(10); - /* 7. Clear ATE_RESET field in the USBN clock-control register: - USBN_USBP_CTL_STATUS[ATE_RESET] = 0 */ + /* + * 7. Clear ATE_RESET field in the USBN clock-control register: + * USBN_USBP_CTL_STATUS[ATE_RESET] = 0 + */ usbn_usbp_ctl_status.s.ate_reset = 0; __cvmx_usb_write_csr64(usb, CVMX_USBNX_USBP_CTL_STATUS(usb->index), usbn_usbp_ctl_status.u64); - /* 8. Program the PHY reset field in the USBN clock-control register: - USBN_CLK_CTL[PRST] = 1 */ + /* + * 8. Program the PHY reset field in the USBN clock-control register: + * USBN_CLK_CTL[PRST] = 1 + */ usbn_clk_ctl.s.prst = 1; __cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index), usbn_clk_ctl.u64); - /* 9. Program the USBP control and status register to select host or - device mode. USBN_USBP_CTL_STATUS[HST_MODE] = 0 for host, = 1 for - device */ + /* + * 9. Program the USBP control and status register to select host or + * device mode. USBN_USBP_CTL_STATUS[HST_MODE] = 0 for host, = 1 for + * device + */ usbn_usbp_ctl_status.s.hst_mode = 0; __cvmx_usb_write_csr64(usb, CVMX_USBNX_USBP_CTL_STATUS(usb->index), usbn_usbp_ctl_status.u64); /* 10. Wait 1 us */ udelay(1); - /* 11. Program the hreset_n field in the USBN clock-control register: - USBN_CLK_CTL[HRST] = 1 */ + /* + * 11. Program the hreset_n field in the USBN clock-control register: + * USBN_CLK_CTL[HRST] = 1 + */ usbn_clk_ctl.s.hrst = 1; __cvmx_usb_write_csr64(usb, CVMX_USBNX_CLK_CTL(usb->index), usbn_clk_ctl.u64); @@ -673,20 +702,24 @@ int cvmx_usb_initialize(cvmx_usb_state_t *state, int usb_port_number, usbn_clk_ctl.u64); udelay(1); - /* USB Core Initialization */ - - /* 1. Read USBC_GHWCFG1, USBC_GHWCFG2, USBC_GHWCFG3, USBC_GHWCFG4 to - determine USB core configuration parameters. */ - /* Nothing needed */ - /* 2. Program the following fields in the global AHB configuration - register (USBC_GAHBCFG) - DMA mode, USBC_GAHBCFG[DMAEn]: 1 = DMA mode, 0 = slave mode - Burst length, USBC_GAHBCFG[HBSTLEN] = 0 - Nonperiodic TxFIFO empty level (slave mode only), - USBC_GAHBCFG[NPTXFEMPLVL] - Periodic TxFIFO empty level (slave mode only), - USBC_GAHBCFG[PTXFEMPLVL] - Global interrupt mask, USBC_GAHBCFG[GLBLINTRMSK] = 1 */ + /* + * USB Core Initialization + * + * 1. Read USBC_GHWCFG1, USBC_GHWCFG2, USBC_GHWCFG3, USBC_GHWCFG4 to + * determine USB core configuration parameters. + * + * Nothing needed + * + * 2. Program the following fields in the global AHB configuration + * register (USBC_GAHBCFG) + * DMA mode, USBC_GAHBCFG[DMAEn]: 1 = DMA mode, 0 = slave mode + * Burst length, USBC_GAHBCFG[HBSTLEN] = 0 + * Nonperiodic TxFIFO empty level (slave mode only), + * USBC_GAHBCFG[NPTXFEMPLVL] + * Periodic TxFIFO empty level (slave mode only), + * USBC_GAHBCFG[PTXFEMPLVL] + * Global interrupt mask, USBC_GAHBCFG[GLBLINTRMSK] = 1 + */ { cvmx_usbcx_gahbcfg_t usbcx_gahbcfg; /* Due to an errata, CN31XX doesn't support DMA */ @@ -707,11 +740,13 @@ int cvmx_usb_initialize(cvmx_usb_state_t *state, int usb_port_number, __cvmx_usb_write_csr32(usb, CVMX_USBCX_GAHBCFG(usb->index), usbcx_gahbcfg.u32); } - /* 3. Program the following fields in USBC_GUSBCFG register. - HS/FS timeout calibration, USBC_GUSBCFG[TOUTCAL] = 0 - ULPI DDR select, USBC_GUSBCFG[DDRSEL] = 0 - USB turnaround time, USBC_GUSBCFG[USBTRDTIM] = 0x5 - PHY low-power clock select, USBC_GUSBCFG[PHYLPWRCLKSEL] = 0 */ + /* + * 3. Program the following fields in USBC_GUSBCFG register. + * HS/FS timeout calibration, USBC_GUSBCFG[TOUTCAL] = 0 + * ULPI DDR select, USBC_GUSBCFG[DDRSEL] = 0 + * USB turnaround time, USBC_GUSBCFG[USBTRDTIM] = 0x5 + * PHY low-power clock select, USBC_GUSBCFG[PHYLPWRCLKSEL] = 0 + */ { cvmx_usbcx_gusbcfg_t usbcx_gusbcfg; usbcx_gusbcfg.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GUSBCFG(usb->index)); @@ -722,10 +757,12 @@ int cvmx_usb_initialize(cvmx_usb_state_t *state, int usb_port_number, __cvmx_usb_write_csr32(usb, CVMX_USBCX_GUSBCFG(usb->index), usbcx_gusbcfg.u32); } - /* 4. The software must unmask the following bits in the USBC_GINTMSK - register. - OTG interrupt mask, USBC_GINTMSK[OTGINTMSK] = 1 - Mode mismatch interrupt mask, USBC_GINTMSK[MODEMISMSK] = 1 */ + /* + * 4. The software must unmask the following bits in the USBC_GINTMSK + * register. + * OTG interrupt mask, USBC_GINTMSK[OTGINTMSK] = 1 + * Mode mismatch interrupt mask, USBC_GINTMSK[MODEMISMSK] = 1 + */ { cvmx_usbcx_gintmsk_t usbcx_gintmsk; int channel; @@ -747,16 +784,20 @@ int cvmx_usb_initialize(cvmx_usb_state_t *state, int usb_port_number, } { - /* Host Port Initialization */ - - /* 1. Program the host-port interrupt-mask field to unmask, - USBC_GINTMSK[PRTINT] = 1 */ + /* + * Host Port Initialization + * + * 1. Program the host-port interrupt-mask field to unmask, + * USBC_GINTMSK[PRTINT] = 1 + */ USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), cvmx_usbcx_gintmsk_t, prtintmsk, 1); USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), cvmx_usbcx_gintmsk_t, disconnintmsk, 1); - /* 2. Program the USBC_HCFG register to select full-speed host or - high-speed host. */ + /* + * 2. Program the USBC_HCFG register to select full-speed host + * or high-speed host. + */ { cvmx_usbcx_hcfg_t usbcx_hcfg; usbcx_hcfg.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCFG(usb->index)); @@ -764,11 +805,15 @@ int cvmx_usb_initialize(cvmx_usb_state_t *state, int usb_port_number, usbcx_hcfg.s.fslspclksel = 0; __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCFG(usb->index), usbcx_hcfg.u32); } - /* 3. Program the port power bit to drive VBUS on the USB, - USBC_HPRT[PRTPWR] = 1 */ + /* + * 3. Program the port power bit to drive VBUS on the USB, + * USBC_HPRT[PRTPWR] = 1 + */ USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt_t, prtpwr, 1); - /* Steps 4-15 from the manual are done later in the port enable */ + /* + * Steps 4-15 from the manual are done later in the port enable + */ } return 0; @@ -827,8 +872,10 @@ int cvmx_usb_enable(cvmx_usb_state_t *state) usb->usbcx_hprt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPRT(usb->index)); - /* If the port is already enabled the just return. We don't need to do - anything */ + /* + * If the port is already enabled the just return. We don't need to do + * anything + */ if (usb->usbcx_hprt.s.prtena) return 0; @@ -840,8 +887,10 @@ int cvmx_usb_enable(cvmx_usb_state_t *state) /* Program the port reset bit to start the reset process */ USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt_t, prtrst, 1); - /* Wait at least 50ms (high speed), or 10ms (full speed) for the reset - process to complete. */ + /* + * Wait at least 50ms (high speed), or 10ms (full speed) for the reset + * process to complete. + */ mdelay(50); /* Program the port reset bit to 0, USBC_HPRT[PRTRST] = 0 */ @@ -856,13 +905,17 @@ int cvmx_usb_enable(cvmx_usb_state_t *state) usb->usbcx_hprt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPRT(usb->index)); usbcx_ghwcfg3.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GHWCFG3(usb->index)); - /* 13. Program the USBC_GRXFSIZ register to select the size of the receive - FIFO (25%). */ + /* + * 13. Program the USBC_GRXFSIZ register to select the size of the + * receive FIFO (25%). + */ USB_SET_FIELD32(CVMX_USBCX_GRXFSIZ(usb->index), cvmx_usbcx_grxfsiz_t, rxfdep, usbcx_ghwcfg3.s.dfifodepth / 4); - /* 14. Program the USBC_GNPTXFSIZ register to select the size and the - start address of the non- periodic transmit FIFO for nonperiodic - transactions (50%). */ + /* + * 14. Program the USBC_GNPTXFSIZ register to select the size and the + * start address of the non- periodic transmit FIFO for nonperiodic + * transactions (50%). + */ { cvmx_usbcx_gnptxfsiz_t siz; siz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GNPTXFSIZ(usb->index)); @@ -870,8 +923,11 @@ int cvmx_usb_enable(cvmx_usb_state_t *state) siz.s.nptxfstaddr = usbcx_ghwcfg3.s.dfifodepth / 4; __cvmx_usb_write_csr32(usb, CVMX_USBCX_GNPTXFSIZ(usb->index), siz.u32); } - /* 15. Program the USBC_HPTXFSIZ register to select the size and start - address of the periodic transmit FIFO for periodic transactions (25%). */ + /* + * 15. Program the USBC_HPTXFSIZ register to select the size and start + * address of the periodic transmit FIFO for periodic transactions + * (25%). + */ { cvmx_usbcx_hptxfsiz_t siz; siz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPTXFSIZ(usb->index)); @@ -1112,8 +1168,10 @@ int cvmx_usb_open_pipe(cvmx_usb_state_t *state, cvmx_usb_pipe_flags_t flags, pipe->max_packet = max_packet; pipe->transfer_type = transfer_type; pipe->transfer_dir = transfer_dir; - /* All pipes use interval to rate limit NAK processing. Force an interval - if one wasn't supplied */ + /* + * All pipes use interval to rate limit NAK processing. Force an + * interval if one wasn't supplied + */ if (!interval) interval = 1; if (__cvmx_usb_pipe_needs_split(usb, pipe)) { @@ -1131,8 +1189,10 @@ int cvmx_usb_open_pipe(cvmx_usb_state_t *state, cvmx_usb_pipe_flags_t flags, pipe->split_sc_frame = -1; __cvmx_usb_append_pipe(&usb->idle_pipes, pipe); - /* We don't need to tell the hardware about this pipe yet since - it doesn't have any submitted requests */ + /* + * We don't need to tell the hardware about this pipe yet since + * it doesn't have any submitted requests + */ return __cvmx_usb_get_pipe_handle(usb, pipe); } @@ -1198,8 +1258,10 @@ static void __cvmx_usb_poll_rx_fifo(cvmx_usb_internal_state_t *usb) */ static int __cvmx_usb_fill_tx_hw(cvmx_usb_internal_state_t *usb, cvmx_usb_tx_fifo_t *fifo, int available) { - /* We're done either when there isn't anymore space or the software FIFO - is empty */ + /* + * We're done either when there isn't anymore space or the software FIFO + * is empty + */ while (available && (fifo->head != fifo->tail)) { int i = fifo->tail; const uint32_t *ptr = cvmx_phys_to_ptr(fifo->entry[i].address); @@ -1219,8 +1281,10 @@ static int __cvmx_usb_fill_tx_hw(cvmx_usb_internal_state_t *usb, cvmx_usb_tx_fif fifo->entry[i].address += words * 4; fifo->entry[i].size -= words; - /* Write the HW fifo data. The read every three writes is due - to an errata on CN3XXX chips */ + /* + * Write the HW fifo data. The read every three writes is due + * to an errata on CN3XXX chips + */ while (words > 3) { cvmx_write64_uint32(csr_address, *ptr++); cvmx_write64_uint32(csr_address, *ptr++); @@ -1351,8 +1415,10 @@ static void __cvmx_usb_start_channel_control(cvmx_usb_internal_state_t *usb, bytes_to_transfer = sizeof(*header); /* All Control operations start with a setup going OUT */ USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), cvmx_usbcx_hccharx_t, epdir, CVMX_USB_DIRECTION_OUT); - /* Setup send the control header instead of the buffer data. The - buffer data will be used in the next stage */ + /* + * Setup send the control header instead of the buffer data. The + * buffer data will be used in the next stage + */ __cvmx_usb_write_csr64(usb, CVMX_USBNX_DMA0_OUTB_CHN0(usb->index) + channel*8, transaction->control_header); break; case CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE: @@ -1406,28 +1472,36 @@ static void __cvmx_usb_start_channel_control(cvmx_usb_internal_state_t *usb, break; } - /* Make sure the transfer never exceeds the byte limit of the hardware. - Further bytes will be sent as continued transactions */ + /* + * Make sure the transfer never exceeds the byte limit of the hardware. + * Further bytes will be sent as continued transactions + */ if (bytes_to_transfer > MAX_TRANSFER_BYTES) { /* Round MAX_TRANSFER_BYTES to a multiple of out packet size */ bytes_to_transfer = MAX_TRANSFER_BYTES / pipe->max_packet; bytes_to_transfer *= pipe->max_packet; } - /* Calculate the number of packets to transfer. If the length is zero - we still need to transfer one packet */ + /* + * Calculate the number of packets to transfer. If the length is zero + * we still need to transfer one packet + */ packets_to_transfer = (bytes_to_transfer + pipe->max_packet - 1) / pipe->max_packet; if (packets_to_transfer == 0) packets_to_transfer = 1; else if ((packets_to_transfer > 1) && (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)) { - /* Limit to one packet when not using DMA. Channels must be restarted - between every packet for IN transactions, so there is no reason to - do multiple packets in a row */ + /* + * Limit to one packet when not using DMA. Channels must be + * restarted between every packet for IN transactions, so there + * is no reason to do multiple packets in a row + */ packets_to_transfer = 1; bytes_to_transfer = packets_to_transfer * pipe->max_packet; } else if (packets_to_transfer > MAX_TRANSFER_PACKETS) { - /* Limit the number of packet and data transferred to what the - hardware can handle */ + /* + * Limit the number of packet and data transferred to what the + * hardware can handle + */ packets_to_transfer = MAX_TRANSFER_PACKETS; bytes_to_transfer = packets_to_transfer * pipe->max_packet; } @@ -1517,17 +1591,24 @@ static void __cvmx_usb_start_channel(cvmx_usb_internal_state_t *usb, int packets_to_transfer; int bytes_to_transfer = transaction->buffer_length - transaction->actual_bytes; - /* ISOCHRONOUS transactions store each individual transfer size in the - packet structure, not the global buffer_length */ + /* + * ISOCHRONOUS transactions store each individual transfer size + * in the packet structure, not the global buffer_length + */ if (transaction->type == CVMX_USB_TRANSFER_ISOCHRONOUS) bytes_to_transfer = transaction->iso_packets[0].length - transaction->actual_bytes; - /* We need to do split transactions when we are talking to non high - speed devices that are behind a high speed hub */ + /* + * We need to do split transactions when we are talking to non + * high speed devices that are behind a high speed hub + */ if (__cvmx_usb_pipe_needs_split(usb, pipe)) { - /* On the start split phase (stage is even) record the frame number we - will need to send the split complete. We only store the lower two bits - since the time ahead can only be two frames */ + /* + * On the start split phase (stage is even) record the + * frame number we will need to send the split complete. + * We only store the lower two bits since the time ahead + * can only be two frames + */ if ((transaction->stage&1) == 0) { if (transaction->type == CVMX_USB_TRANSFER_BULK) pipe->split_sc_frame = (usb->frame_number + 1) & 0x7f; @@ -1541,64 +1622,94 @@ static void __cvmx_usb_start_channel(cvmx_usb_internal_state_t *usb, usbc_hcsplt.s.prtaddr = pipe->hub_port; usbc_hcsplt.s.compsplt = (transaction->stage == CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE); - /* SPLIT transactions can only ever transmit one data packet so - limit the transfer size to the max packet size */ + /* + * SPLIT transactions can only ever transmit one data + * packet so limit the transfer size to the max packet + * size + */ if (bytes_to_transfer > pipe->max_packet) bytes_to_transfer = pipe->max_packet; - /* ISOCHRONOUS OUT splits are unique in that they limit - data transfers to 188 byte chunks representing the - begin/middle/end of the data or all */ + /* + * ISOCHRONOUS OUT splits are unique in that they limit + * data transfers to 188 byte chunks representing the + * begin/middle/end of the data or all + */ if (!usbc_hcsplt.s.compsplt && (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT) && (pipe->transfer_type == CVMX_USB_TRANSFER_ISOCHRONOUS)) { - /* Clear the split complete frame number as there isn't going - to be a split complete */ + /* + * Clear the split complete frame number as + * there isn't going to be a split complete + */ pipe->split_sc_frame = -1; - /* See if we've started this transfer and sent data */ + /* + * See if we've started this transfer and sent + * data + */ if (transaction->actual_bytes == 0) { - /* Nothing sent yet, this is either a begin or the - entire payload */ + /* + * Nothing sent yet, this is either a + * begin or the entire payload + */ if (bytes_to_transfer <= 188) usbc_hcsplt.s.xactpos = 3; /* Entire payload in one go */ else usbc_hcsplt.s.xactpos = 2; /* First part of payload */ } else { - /* Continuing the previous data, we must either be - in the middle or at the end */ + /* + * Continuing the previous data, we must + * either be in the middle or at the end + */ if (bytes_to_transfer <= 188) usbc_hcsplt.s.xactpos = 1; /* End of payload */ else usbc_hcsplt.s.xactpos = 0; /* Middle of payload */ } - /* Again, the transfer size is limited to 188 bytes */ + /* + * Again, the transfer size is limited to 188 + * bytes + */ if (bytes_to_transfer > 188) bytes_to_transfer = 188; } } - /* Make sure the transfer never exceeds the byte limit of the hardware. - Further bytes will be sent as continued transactions */ + /* + * Make sure the transfer never exceeds the byte limit of the + * hardware. Further bytes will be sent as continued + * transactions + */ if (bytes_to_transfer > MAX_TRANSFER_BYTES) { - /* Round MAX_TRANSFER_BYTES to a multiple of out packet size */ + /* + * Round MAX_TRANSFER_BYTES to a multiple of out packet + * size + */ bytes_to_transfer = MAX_TRANSFER_BYTES / pipe->max_packet; bytes_to_transfer *= pipe->max_packet; } - /* Calculate the number of packets to transfer. If the length is zero - we still need to transfer one packet */ + /* + * Calculate the number of packets to transfer. If the length is + * zero we still need to transfer one packet + */ packets_to_transfer = (bytes_to_transfer + pipe->max_packet - 1) / pipe->max_packet; if (packets_to_transfer == 0) packets_to_transfer = 1; else if ((packets_to_transfer > 1) && (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA)) { - /* Limit to one packet when not using DMA. Channels must be restarted - between every packet for IN transactions, so there is no reason to - do multiple packets in a row */ + /* + * Limit to one packet when not using DMA. Channels must + * be restarted between every packet for IN + * transactions, so there is no reason to do multiple + * packets in a row + */ packets_to_transfer = 1; bytes_to_transfer = packets_to_transfer * pipe->max_packet; } else if (packets_to_transfer > MAX_TRANSFER_PACKETS) { - /* Limit the number of packet and data transferred to what the - hardware can handle */ + /* + * Limit the number of packet and data transferred to + * what the hardware can handle + */ packets_to_transfer = MAX_TRANSFER_PACKETS; bytes_to_transfer = packets_to_transfer * pipe->max_packet; } @@ -1608,7 +1719,9 @@ static void __cvmx_usb_start_channel(cvmx_usb_internal_state_t *usb, /* Update the DATA0/DATA1 toggle */ usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe); - /* High speed pipes may need a hardware ping before they start */ + /* + * High speed pipes may need a hardware ping before they start + */ if (pipe->flags & __CVMX_USB_PIPE_FLAGS_NEED_PING) usbc_hctsiz.s.dopng = 1; @@ -1620,13 +1733,18 @@ static void __cvmx_usb_start_channel(cvmx_usb_internal_state_t *usb, { cvmx_usbcx_hccharx_t usbc_hcchar = {.u32 = 0}; - /* Set the startframe odd/even properly. This is only used for periodic */ + /* + * Set the startframe odd/even properly. This is only used for + * periodic + */ usbc_hcchar.s.oddfrm = usb->frame_number&1; - /* Set the number of back to back packets allowed by this endpoint. - Split transactions interpret "ec" as the number of immediate - retries of failure. These retries happen too quickly, so we - disable these entirely for splits */ + /* + * Set the number of back to back packets allowed by this + * endpoint. Split transactions interpret "ec" as the number of + * immediate retries of failure. These retries happen too + * quickly, so we disable these entirely for splits + */ if (__cvmx_usb_pipe_needs_split(usb, pipe)) usbc_hcchar.s.ec = 1; else if (pipe->multi_count < 1) @@ -1656,8 +1774,10 @@ static void __cvmx_usb_start_channel(cvmx_usb_internal_state_t *usb, break; case CVMX_USB_TRANSFER_ISOCHRONOUS: if (!__cvmx_usb_pipe_needs_split(usb, pipe)) { - /* ISO transactions require different PIDs depending on direction - and how many packets are needed */ + /* + * ISO transactions require different PIDs depending on + * direction and how many packets are needed + */ if (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT) { if (pipe->multi_count < 2) /* Need DATA0 */ USB_SET_FIELD32(CVMX_USBCX_HCTSIZX(channel, usb->index), cvmx_usbcx_hctsizx_t, pid, 0); @@ -1745,9 +1865,11 @@ static void __cvmx_usb_schedule(cvmx_usb_internal_state_t *usb, int is_sof) /* Find a pipe needing service */ pipe = NULL; if (is_sof) { - /* Only process periodic pipes on SOF interrupts. This way we are - sure that the periodic data is sent in the beginning of the - frame */ + /* + * Only process periodic pipes on SOF interrupts. This + * way we are sure that the periodic data is sent in the + * beginning of the frame + */ pipe = __cvmx_usb_find_ready_pipe(usb, usb->active_pipes + CVMX_USB_TRANSFER_ISOCHRONOUS, usb->frame_number); if (likely(!pipe)) pipe = __cvmx_usb_find_ready_pipe(usb, usb->active_pipes + CVMX_USB_TRANSFER_INTERRUPT, usb->frame_number); @@ -1764,8 +1886,10 @@ static void __cvmx_usb_schedule(cvmx_usb_internal_state_t *usb, int is_sof) } done: - /* Only enable SOF interrupts when we have transactions pending in the - future that might need to be scheduled */ + /* + * Only enable SOF interrupts when we have transactions pending in the + * future that might need to be scheduled + */ need_sof = 0; for (ttype = CVMX_USB_TRANSFER_CONTROL; ttype <= CVMX_USB_TRANSFER_INTERRUPT; ttype++) { pipe = usb->active_pipes[ttype].head; @@ -1850,15 +1974,19 @@ static void __cvmx_usb_perform_complete(cvmx_usb_internal_state_t *usb, if (usb->active_split == transaction) usb->active_split = NULL; - /* Isochronous transactions need extra processing as they might not be done - after a single data transfer */ + /* + * Isochronous transactions need extra processing as they might not be + * done after a single data transfer + */ if (unlikely(transaction->type == CVMX_USB_TRANSFER_ISOCHRONOUS)) { /* Update the number of bytes transferred in this ISO packet */ transaction->iso_packets[0].length = transaction->actual_bytes; transaction->iso_packets[0].status = complete_code; - /* If there are more ISOs pending and we succeeded, schedule the next - one */ + /* + * If there are more ISOs pending and we succeeded, schedule the + * next one + */ if ((transaction->iso_number_packets > 1) && (complete_code == CVMX_USB_COMPLETE_SUCCESS)) { transaction->actual_bytes = 0; /* No bytes transferred for this packet as of yet */ transaction->iso_number_packets--; /* One less ISO waiting to transfer */ @@ -2296,8 +2424,10 @@ int cvmx_usb_cancel(cvmx_usb_state_t *state, int pipe_handle, int submit_handle) if (unlikely((transaction->flags & __CVMX_USB_TRANSACTION_FLAGS_IN_USE) == 0)) return -EINVAL; - /* If the transaction is the HEAD of the queue and scheduled. We need to - treat it special */ + /* + * If the transaction is the HEAD of the queue and scheduled. We need to + * treat it special + */ if ((pipe->head == transaction) && (pipe->flags & __CVMX_USB_PIPE_FLAGS_SCHEDULED)) { cvmx_usbcx_hccharx_t usbc_hcchar; @@ -2468,15 +2598,19 @@ static int __cvmx_usb_poll_channel(cvmx_usb_internal_state_t *usb, int channel) usbc_hcchar.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index)); if (usbc_hcchar.s.chena && usbc_hcchar.s.chdis) { - /* There seems to be a bug in CN31XX which can cause interrupt - IN transfers to get stuck until we do a write of HCCHARX - without changing things */ + /* + * There seems to be a bug in CN31XX which can cause + * interrupt IN transfers to get stuck until we do a + * write of HCCHARX without changing things + */ __cvmx_usb_write_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index), usbc_hcchar.u32); return 0; } - /* In non DMA mode the channels don't halt themselves. We need to - manually disable channels that are left running */ + /* + * In non DMA mode the channels don't halt themselves. We need + * to manually disable channels that are left running + */ if (!usbc_hcint.s.chhltd) { if (usbc_hcchar.s.chena) { cvmx_usbcx_hcintmskx_t hcintmsk; @@ -2495,8 +2629,10 @@ static int __cvmx_usb_poll_channel(cvmx_usb_internal_state_t *usb, int channel) } } } else { - /* There is are no interrupts that we need to process when the channel is - still running */ + /* + * There is are no interrupts that we need to process when the + * channel is still running + */ if (!usbc_hcint.s.chhltd) return 0; } @@ -2514,33 +2650,45 @@ static int __cvmx_usb_poll_channel(cvmx_usb_internal_state_t *usb, int channel) transaction = pipe->head; CVMX_PREFETCH0(transaction); - /* Disconnect this pipe from the HW channel. Later the schedule function will - figure out which pipe needs to go */ + /* + * Disconnect this pipe from the HW channel. Later the schedule + * function will figure out which pipe needs to go + */ usb->pipe_for_channel[channel] = NULL; pipe->flags &= ~__CVMX_USB_PIPE_FLAGS_SCHEDULED; - /* Read the channel config info so we can figure out how much data - transfered */ + /* + * Read the channel config info so we can figure out how much data + * transfered + */ usbc_hcchar.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index)); usbc_hctsiz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index)); - /* Calculating the number of bytes successfully transferred is dependent on - the transfer direction */ + /* + * Calculating the number of bytes successfully transferred is dependent + * on the transfer direction + */ packets_processed = transaction->pktcnt - usbc_hctsiz.s.pktcnt; if (usbc_hcchar.s.epdir) { - /* IN transactions are easy. For every byte received the hardware - decrements xfersize. All we need to do is subtract the current - value of xfersize from its starting value and we know how many - bytes were written to the buffer */ + /* + * IN transactions are easy. For every byte received the + * hardware decrements xfersize. All we need to do is subtract + * the current value of xfersize from its starting value and we + * know how many bytes were written to the buffer + */ bytes_this_transfer = transaction->xfersize - usbc_hctsiz.s.xfersize; } else { - /* OUT transaction don't decrement xfersize. Instead pktcnt is - decremented on every successful packet send. The hardware does - this when it receives an ACK, or NYET. If it doesn't - receive one of these responses pktcnt doesn't change */ + /* + * OUT transaction don't decrement xfersize. Instead pktcnt is + * decremented on every successful packet send. The hardware + * does this when it receives an ACK, or NYET. If it doesn't + * receive one of these responses pktcnt doesn't change + */ bytes_this_transfer = packets_processed * usbc_hcchar.s.mps; - /* The last packet may not be a full transfer if we didn't have - enough data */ + /* + * The last packet may not be a full transfer if we didn't have + * enough data + */ if (bytes_this_transfer > transaction->xfersize) bytes_this_transfer = transaction->xfersize; } @@ -2550,56 +2698,77 @@ static int __cvmx_usb_poll_channel(cvmx_usb_internal_state_t *usb, int channel) else bytes_in_last_packet = bytes_this_transfer; - /* As a special case, setup transactions output the setup header, not - the user's data. For this reason we don't count setup data as bytes - transferred */ + /* + * As a special case, setup transactions output the setup header, not + * the user's data. For this reason we don't count setup data as bytes + * transferred + */ if ((transaction->stage == CVMX_USB_STAGE_SETUP) || (transaction->stage == CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE)) bytes_this_transfer = 0; - /* Add the bytes transferred to the running total. It is important that - bytes_this_transfer doesn't count any data that needs to be - retransmitted */ + /* + * Add the bytes transferred to the running total. It is important that + * bytes_this_transfer doesn't count any data that needs to be + * retransmitted + */ transaction->actual_bytes += bytes_this_transfer; if (transaction->type == CVMX_USB_TRANSFER_ISOCHRONOUS) buffer_space_left = transaction->iso_packets[0].length - transaction->actual_bytes; else buffer_space_left = transaction->buffer_length - transaction->actual_bytes; - /* We need to remember the PID toggle state for the next transaction. The - hardware already updated it for the next transaction */ + /* + * We need to remember the PID toggle state for the next transaction. + * The hardware already updated it for the next transaction + */ pipe->pid_toggle = !(usbc_hctsiz.s.pid == 0); - /* For high speed bulk out, assume the next transaction will need to do a - ping before proceeding. If this isn't true the ACK processing below - will clear this flag */ + /* + * For high speed bulk out, assume the next transaction will need to do + * a ping before proceeding. If this isn't true the ACK processing below + * will clear this flag + */ if ((pipe->device_speed == CVMX_USB_SPEED_HIGH) && (pipe->transfer_type == CVMX_USB_TRANSFER_BULK) && (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT)) pipe->flags |= __CVMX_USB_PIPE_FLAGS_NEED_PING; if (usbc_hcint.s.stall) { - /* STALL as a response means this transaction cannot be completed - because the device can't process transactions. Tell the user. Any - data that was transferred will be counted on the actual bytes - transferred */ + /* + * STALL as a response means this transaction cannot be + * completed because the device can't process transactions. Tell + * the user. Any data that was transferred will be counted on + * the actual bytes transferred + */ pipe->pid_toggle = 0; __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_STALL); } else if (usbc_hcint.s.xacterr) { - /* We know at least one packet worked if we get a ACK or NAK. Reset the retry counter */ + /* + * We know at least one packet worked if we get a ACK or NAK. + * Reset the retry counter + */ if (usbc_hcint.s.nak || usbc_hcint.s.ack) transaction->retries = 0; transaction->retries++; if (transaction->retries > MAX_RETRIES) { - /* XactErr as a response means the device signaled something wrong with - the transfer. For example, PID toggle errors cause these */ + /* + * XactErr as a response means the device signaled + * something wrong with the transfer. For example, PID + * toggle errors cause these + */ __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_XACTERR); } else { - /* If this was a split then clear our split in progress marker */ + /* + * If this was a split then clear our split in progress + * marker + */ if (usb->active_split == transaction) usb->active_split = NULL; - /* Rewind to the beginning of the transaction by anding off the - split complete bit */ + /* + * Rewind to the beginning of the transaction by anding + * off the split complete bit + */ transaction->stage &= ~1; pipe->split_sc_frame = -1; pipe->next_tx_frame += pipe->interval; @@ -2614,38 +2783,49 @@ static int __cvmx_usb_poll_channel(cvmx_usb_internal_state_t *usb, int channel) /* We'll retry the exact same transaction again */ transaction->retries++; } else if (usbc_hcint.s.nyet) { - /* NYET as a response is only allowed in three cases: as a response to - a ping, as a response to a split transaction, and as a response to - a bulk out. The ping case is handled by hardware, so we only have - splits and bulk out */ + /* + * NYET as a response is only allowed in three cases: as a + * response to a ping, as a response to a split transaction, and + * as a response to a bulk out. The ping case is handled by + * hardware, so we only have splits and bulk out + */ if (!__cvmx_usb_pipe_needs_split(usb, pipe)) { transaction->retries = 0; - /* If there is more data to go then we need to try again. Otherwise - this transaction is complete */ + /* + * If there is more data to go then we need to try + * again. Otherwise this transaction is complete + */ if ((buffer_space_left == 0) || (bytes_in_last_packet < pipe->max_packet)) __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS); } else { - /* Split transactions retry the split complete 4 times then rewind - to the start split and do the entire transactions again */ + /* + * Split transactions retry the split complete 4 times + * then rewind to the start split and do the entire + * transactions again + */ transaction->retries++; if ((transaction->retries & 0x3) == 0) { - /* Rewind to the beginning of the transaction by anding off the - split complete bit */ + /* + * Rewind to the beginning of the transaction by + * anding off the split complete bit + */ transaction->stage &= ~1; pipe->split_sc_frame = -1; } } } else if (usbc_hcint.s.ack) { transaction->retries = 0; - /* The ACK bit can only be checked after the other error bits. This is - because a multi packet transfer may succeed in a number of packets - and then get a different response on the last packet. In this case - both ACK and the last response bit will be set. If none of the - other response bits is set, then the last packet must have been an - ACK */ - - /* Since we got an ACK, we know we don't need to do a ping on this - pipe */ + /* + * The ACK bit can only be checked after the other error bits. + * This is because a multi packet transfer may succeed in a + * number of packets and then get a different response on the + * last packet. In this case both ACK and the last response bit + * will be set. If none of the other response bits is set, then + * the last packet must have been an ACK + * + * Since we got an ACK, we know we don't need to do a ping on + * this pipe + */ pipe->flags &= ~__CVMX_USB_PIPE_FLAGS_NEED_PING; switch (transaction->type) { @@ -2680,9 +2860,12 @@ static int __cvmx_usb_poll_channel(cvmx_usb_internal_state_t *usb, int channel) case CVMX_USB_STAGE_DATA: if (__cvmx_usb_pipe_needs_split(usb, pipe)) { transaction->stage = CVMX_USB_STAGE_DATA_SPLIT_COMPLETE; - /* For setup OUT data that are splits, the hardware - doesn't appear to count transferred data. Here - we manually update the data transferred */ + /* + * For setup OUT data that are splits, + * the hardware doesn't appear to count + * transferred data. Here we manually + * update the data transferred + */ if (!usbc_hcchar.s.epdir) { if (buffer_space_left < pipe->max_packet) transaction->actual_bytes += buffer_space_left; @@ -2715,10 +2898,12 @@ static int __cvmx_usb_poll_channel(cvmx_usb_internal_state_t *usb, int channel) break; case CVMX_USB_TRANSFER_BULK: case CVMX_USB_TRANSFER_INTERRUPT: - /* The only time a bulk transfer isn't complete when - it finishes with an ACK is during a split transaction. For - splits we need to continue the transfer if more data is - needed */ + /* + * The only time a bulk transfer isn't complete when it + * finishes with an ACK is during a split transaction. + * For splits we need to continue the transfer if more + * data is needed + */ if (__cvmx_usb_pipe_needs_split(usb, pipe)) { if (transaction->stage == CVMX_USB_STAGE_NON_CONTROL) transaction->stage = CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE; @@ -2746,23 +2931,33 @@ static int __cvmx_usb_poll_channel(cvmx_usb_internal_state_t *usb, int channel) break; case CVMX_USB_TRANSFER_ISOCHRONOUS: if (__cvmx_usb_pipe_needs_split(usb, pipe)) { - /* ISOCHRONOUS OUT splits don't require a complete split stage. - Instead they use a sequence of begin OUT splits to transfer - the data 188 bytes at a time. Once the transfer is complete, - the pipe sleeps until the next schedule interval */ + /* + * ISOCHRONOUS OUT splits don't require a + * complete split stage. Instead they use a + * sequence of begin OUT splits to transfer the + * data 188 bytes at a time. Once the transfer + * is complete, the pipe sleeps until the next + * schedule interval + */ if (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT) { - /* If no space left or this wasn't a max size packet then - this transfer is complete. Otherwise start it again - to send the next 188 bytes */ + /* + * If no space left or this wasn't a max + * size packet then this transfer is + * complete. Otherwise start it again to + * send the next 188 bytes + */ if (!buffer_space_left || (bytes_this_transfer < 188)) { pipe->next_tx_frame += pipe->interval; __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS); } } else { if (transaction->stage == CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE) { - /* We are in the incoming data phase. Keep getting - data until we run out of space or get a small - packet */ + /* + * We are in the incoming data + * phase. Keep getting data + * until we run out of space or + * get a small packet + */ if ((buffer_space_left == 0) || (bytes_in_last_packet < pipe->max_packet)) { pipe->next_tx_frame += pipe->interval; __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_SUCCESS); @@ -2780,10 +2975,12 @@ static int __cvmx_usb_poll_channel(cvmx_usb_internal_state_t *usb, int channel) /* If this was a split then clear our split in progress marker */ if (usb->active_split == transaction) usb->active_split = NULL; - /* NAK as a response means the device couldn't accept the transaction, - but it should be retried in the future. Rewind to the beginning of - the transaction by anding off the split complete bit. Retry in the - next interval */ + /* + * NAK as a response means the device couldn't accept the + * transaction, but it should be retried in the future. Rewind + * to the beginning of the transaction by anding off the split + * complete bit. Retry in the next interval + */ transaction->retries = 0; transaction->stage &= ~1; pipe->next_tx_frame += pipe->interval; @@ -2797,8 +2994,10 @@ static int __cvmx_usb_poll_channel(cvmx_usb_internal_state_t *usb, int channel) /* We'll retry the exact same transaction again */ transaction->retries++; } else { - /* We get channel halted interrupts with no result bits sets when the - cable is unplugged */ + /* + * We get channel halted interrupts with no result bits + * sets when the cable is unplugged + */ __cvmx_usb_perform_complete(usb, pipe, transaction, CVMX_USB_COMPLETE_ERROR); } } @@ -2843,10 +3042,13 @@ int cvmx_usb_poll(cvmx_usb_state_t *state) __cvmx_usb_write_csr32(usb, CVMX_USBCX_GINTSTS(usb->index), usbc_gintsts.u32); if (usbc_gintsts.s.rxflvl) { - /* RxFIFO Non-Empty (RxFLvl) - Indicates that there is at least one packet pending to be read - from the RxFIFO. */ - /* In DMA mode this is handled by hardware */ + /* + * RxFIFO Non-Empty (RxFLvl) + * Indicates that there is at least one packet pending to be + * read from the RxFIFO. + * + * In DMA mode this is handled by hardware + */ if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) __cvmx_usb_poll_rx_fifo(usb); } @@ -2857,18 +3059,20 @@ int cvmx_usb_poll(cvmx_usb_state_t *state) } if (usbc_gintsts.s.disconnint || usbc_gintsts.s.prtint) { cvmx_usbcx_hprt_t usbc_hprt; - /* Disconnect Detected Interrupt (DisconnInt) - Asserted when a device disconnect is detected. */ - - /* Host Port Interrupt (PrtInt) - The core sets this bit to indicate a change in port status of one - of the O2P USB core ports in Host mode. The application must - read the Host Port Control and Status (HPRT) register to - determine the exact event that caused this interrupt. The - application must clear the appropriate status bit in the Host Port - Control and Status register to clear this bit. */ - - /* Call the user's port callback */ + /* + * Disconnect Detected Interrupt (DisconnInt) + * Asserted when a device disconnect is detected. + * + * Host Port Interrupt (PrtInt) + * The core sets this bit to indicate a change in port status of + * one of the O2P USB core ports in Host mode. The application + * must read the Host Port Control and Status (HPRT) register to + * determine the exact event that caused this interrupt. The + * application must clear the appropriate status bit in the Host + * Port Control and Status register to clear this bit. + * + * Call the user's port callback + */ __cvmx_usb_perform_callback(usb, NULL, NULL, CVMX_USB_CALLBACK_PORT_CHANGED, CVMX_USB_COMPLETE_SUCCESS); @@ -2878,15 +3082,18 @@ int cvmx_usb_poll(cvmx_usb_state_t *state) __cvmx_usb_write_csr32(usb, CVMX_USBCX_HPRT(usb->index), usbc_hprt.u32); } if (usbc_gintsts.s.hchint) { - /* Host Channels Interrupt (HChInt) - The core sets this bit to indicate that an interrupt is pending on - one of the channels of the core (in Host mode). The application - must read the Host All Channels Interrupt (HAINT) register to - determine the exact number of the channel on which the - interrupt occurred, and then read the corresponding Host - Channel-n Interrupt (HCINTn) register to determine the exact - cause of the interrupt. The application must clear the - appropriate status bit in the HCINTn register to clear this bit. */ + /* + * Host Channels Interrupt (HChInt) + * The core sets this bit to indicate that an interrupt is + * pending on one of the channels of the core (in Host mode). + * The application must read the Host All Channels Interrupt + * (HAINT) register to determine the exact number of the channel + * on which the interrupt occurred, and then read the + * corresponding Host Channel-n Interrupt (HCINTn) register to + * determine the exact cause of the interrupt. The application + * must clear the appropriate status bit in the HCINTn register + * to clear this bit. + */ cvmx_usbcx_haint_t usbc_haint; usbc_haint.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HAINT(usb->index)); while (usbc_haint.u32) { From 6995ae41b301ab5487fe65518c018360f6809f69 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Mon, 29 Jul 2013 20:07:55 +0300 Subject: [PATCH 1050/3400] staging: octeon-usb: cvmx-usb: delete @INTERNAL Delete "@INTERNAL" from comments. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.c | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.c b/drivers/staging/octeon-usb/cvmx-usb.c index 025671a2d5b1..d3da546f3b62 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.c +++ b/drivers/staging/octeon-usb/cvmx-usb.c @@ -258,7 +258,6 @@ static int octeon_usb_get_clock_type(void) } /** - * @INTERNAL * Read a USB 32bit CSR. It performs the necessary address swizzle * for 32bit CSRs and logs the value in a readable format if * debugging is on. @@ -277,7 +276,6 @@ static inline uint32_t __cvmx_usb_read_csr32(cvmx_usb_internal_state_t *usb, /** - * @INTERNAL * Write a USB 32bit CSR. It performs the necessary address * swizzle for 32bit CSRs and logs the value in a readable format * if debugging is on. @@ -295,7 +293,6 @@ static inline void __cvmx_usb_write_csr32(cvmx_usb_internal_state_t *usb, /** - * @INTERNAL * Read a USB 64bit CSR. It logs the value in a readable format if * debugging is on. * @@ -313,7 +310,6 @@ static inline uint64_t __cvmx_usb_read_csr64(cvmx_usb_internal_state_t *usb, /** - * @INTERNAL * Write a USB 64bit CSR. It logs the value in a readable format * if debugging is on. * @@ -328,7 +324,6 @@ static inline void __cvmx_usb_write_csr64(cvmx_usb_internal_state_t *usb, } /** - * @INTERNAL * Return non zero if this pipe connects to a non HIGH speed * device through a high speed hub. * @@ -344,7 +339,6 @@ static inline int __cvmx_usb_pipe_needs_split(cvmx_usb_internal_state_t *usb, cv /** - * @INTERNAL * Trivial utility function to return the correct PID for a pipe * * @param pipe pipe to check @@ -392,7 +386,6 @@ int cvmx_usb_get_num_ports(void) /** - * @INTERNAL * Allocate a usb transaction for use * * @param usb USB device state populated by @@ -418,7 +411,6 @@ static inline cvmx_usb_transaction_t *__cvmx_usb_alloc_transaction(cvmx_usb_inte /** - * @INTERNAL * Free a usb transaction * * @param usb USB device state populated by @@ -441,7 +433,6 @@ static inline void __cvmx_usb_free_transaction(cvmx_usb_internal_state_t *usb, /** - * @INTERNAL * Add a pipe to the tail of a list * @param list List to add pipe to * @param pipe Pipe to add @@ -459,7 +450,6 @@ static inline void __cvmx_usb_append_pipe(cvmx_usb_pipe_list_t *list, cvmx_usb_p /** - * @INTERNAL * Remove a pipe from a list * @param list List to remove pipe from * @param pipe Pipe to remove @@ -1024,7 +1014,6 @@ void cvmx_usb_set_status(cvmx_usb_state_t *state, cvmx_usb_port_status_t port_st /** - * @INTERNAL * Convert a USB transaction into a handle * * @param usb USB device state populated by @@ -1043,7 +1032,6 @@ static inline int __cvmx_usb_get_submit_handle(cvmx_usb_internal_state_t *usb, /** - * @INTERNAL * Convert a USB pipe into a handle * * @param usb USB device state populated by @@ -1199,7 +1187,6 @@ int cvmx_usb_open_pipe(cvmx_usb_state_t *state, cvmx_usb_pipe_flags_t flags, /** - * @INTERNAL * Poll the RX FIFOs and remove data as needed. This function is only used * in non DMA mode. It is very important that this function be called quickly * enough to prevent FIFO overflow. @@ -1335,7 +1322,6 @@ static void __cvmx_usb_poll_tx_fifo(cvmx_usb_internal_state_t *usb) /** - * @INTERNAL * Fill the TX FIFO with an outgoing packet * * @param usb USB device state populated by @@ -1383,7 +1369,6 @@ static void __cvmx_usb_fill_tx_fifo(cvmx_usb_internal_state_t *usb, int channel) } /** - * @INTERNAL * Perform channel specific setup for Control transactions. All * the generic stuff will already have been done in * __cvmx_usb_start_channel() @@ -1515,7 +1500,6 @@ static void __cvmx_usb_start_channel_control(cvmx_usb_internal_state_t *usb, /** - * @INTERNAL * Start a channel to perform the pipe's head transaction * * @param usb USB device state populated by @@ -1803,7 +1787,6 @@ static void __cvmx_usb_start_channel(cvmx_usb_internal_state_t *usb, /** - * @INTERNAL * Find a pipe that is ready to be scheduled to hardware. * @param usb USB device state populated by * cvmx_usb_initialize(). @@ -1832,7 +1815,6 @@ static cvmx_usb_pipe_t *__cvmx_usb_find_ready_pipe(cvmx_usb_internal_state_t *us /** - * @INTERNAL * Called whenever a pipe might need to be scheduled to the * hardware. * @@ -1907,7 +1889,6 @@ done: /** - * @INTERNAL * Call a user's callback for a specific reason. * * @param usb USB device state populated by @@ -1953,7 +1934,6 @@ static void __cvmx_usb_perform_callback(cvmx_usb_internal_state_t *usb, /** - * @INTERNAL * Signal the completion of a transaction and free it. The * transaction will be removed from the pipe transaction list. * @@ -2020,7 +2000,6 @@ done: /** - * @INTERNAL * Submit a usb transaction to a pipe. Called for all types * of transactions. * @@ -2571,7 +2550,6 @@ int cvmx_usb_get_frame_number(cvmx_usb_state_t *state) /** - * @INTERNAL * Poll a channel for status * * @param usb USB device From a6945527d34c56ca07b5f0d081f1874e3a93aa48 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Mon, 29 Jul 2013 20:07:56 +0300 Subject: [PATCH 1051/3400] staging: octeon-usb: cvmx-usb: delete duplicated documentation from .h file Delete duplicated function call documentation from the .h file. These functions are just internal anyway, and the .h file will be completely removed in the future when the driver will be made a single self-contained .c file. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.h | 363 -------------------------- 1 file changed, 363 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.h b/drivers/staging/octeon-usb/cvmx-usb.h index dc366c8e7171..30d7213ed19e 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.h +++ b/drivers/staging/octeon-usb/cvmx-usb.h @@ -409,160 +409,14 @@ typedef enum __CVMX_USB_PIPE_FLAGS_NEED_PING = 1<<18, /**< Used internally to determine if a high speed pipe is in the ping state. Do not use */ } cvmx_usb_pipe_flags_t; -/** - * Return the number of USB ports supported by this Octeon - * chip. If the chip doesn't support USB, or is not supported - * by this API, a zero will be returned. Most Octeon chips - * support one usb port, but some support two ports. - * cvmx_usb_initialize() must be called on independent - * cvmx_usb_state_t structures. - * - * @return Number of port, zero if usb isn't supported - */ extern int cvmx_usb_get_num_ports(void); - -/** - * Initialize a USB port for use. This must be called before any - * other access to the Octeon USB port is made. The port starts - * off in the disabled state. - * - * @param state Pointer to an empty cvmx_usb_state_t structure - * that will be populated by the initialize call. - * This structure is then passed to all other USB - * functions. - * @param usb_port_number - * Which Octeon USB port to initialize. - * @param flags Flags to control hardware initialization. See - * cvmx_usb_initialize_flags_t for the flag - * definitions. Some flags are mandatory. - * - * @return 0 or a negative error code. - */ extern int cvmx_usb_initialize(cvmx_usb_state_t *state, int usb_port_number, cvmx_usb_initialize_flags_t flags); - -/** - * Shutdown a USB port after a call to cvmx_usb_initialize(). - * The port should be disabled with all pipes closed when this - * function is called. - * - * @param state USB device state populated by - * cvmx_usb_initialize(). - * - * @return 0 or a negative error code. - */ extern int cvmx_usb_shutdown(cvmx_usb_state_t *state); - -/** - * Enable a USB port. After this call succeeds, the USB port is - * online and servicing requests. - * - * @param state USB device state populated by - * cvmx_usb_initialize(). - * - * @return 0 or a negative error code. - */ extern int cvmx_usb_enable(cvmx_usb_state_t *state); - -/** - * Disable a USB port. After this call the USB port will not - * generate data transfers and will not generate events. - * Transactions in process will fail and call their - * associated callbacks. - * - * @param state USB device state populated by - * cvmx_usb_initialize(). - * - * @return 0 or a negative error code. - */ extern int cvmx_usb_disable(cvmx_usb_state_t *state); - -/** - * Get the current state of the USB port. Use this call to - * determine if the usb port has anything connected, is enabled, - * or has some sort of error condition. The return value of this - * call has "changed" bits to signal of the value of some fields - * have changed between calls. These "changed" fields are based - * on the last call to cvmx_usb_set_status(). In order to clear - * them, you must update the status through cvmx_usb_set_status(). - * - * @param state USB device state populated by - * cvmx_usb_initialize(). - * - * @return Port status information - */ extern cvmx_usb_port_status_t cvmx_usb_get_status(cvmx_usb_state_t *state); - -/** - * Set the current state of the USB port. The status is used as - * a reference for the "changed" bits returned by - * cvmx_usb_get_status(). Other than serving as a reference, the - * status passed to this function is not used. No fields can be - * changed through this call. - * - * @param state USB device state populated by - * cvmx_usb_initialize(). - * @param port_status - * Port status to set, most like returned by cvmx_usb_get_status() - */ extern void cvmx_usb_set_status(cvmx_usb_state_t *state, cvmx_usb_port_status_t port_status); - -/** - * Open a virtual pipe between the host and a USB device. A pipe - * must be opened before data can be transferred between a device - * and Octeon. - * - * @param state USB device state populated by - * cvmx_usb_initialize(). - * @param flags Optional pipe flags defined in - * cvmx_usb_pipe_flags_t. - * @param device_addr - * USB device address to open the pipe to - * (0-127). - * @param endpoint_num - * USB endpoint number to open the pipe to - * (0-15). - * @param device_speed - * The speed of the device the pipe is going - * to. This must match the device's speed, - * which may be different than the port speed. - * @param max_packet The maximum packet length the device can - * transmit/receive (low speed=0-8, full - * speed=0-1023, high speed=0-1024). This value - * comes from the standard endpoint descriptor - * field wMaxPacketSize bits <10:0>. - * @param transfer_type - * The type of transfer this pipe is for. - * @param transfer_dir - * The direction the pipe is in. This is not - * used for control pipes. - * @param interval For ISOCHRONOUS and INTERRUPT transfers, - * this is how often the transfer is scheduled - * for. All other transfers should specify - * zero. The units are in frames (8000/sec at - * high speed, 1000/sec for full speed). - * @param multi_count - * For high speed devices, this is the maximum - * allowed number of packet per microframe. - * Specify zero for non high speed devices. This - * value comes from the standard endpoint descriptor - * field wMaxPacketSize bits <12:11>. - * @param hub_device_addr - * Hub device address this device is connected - * to. Devices connected directly to Octeon - * use zero. This is only used when the device - * is full/low speed behind a high speed hub. - * The address will be of the high speed hub, - * not and full speed hubs after it. - * @param hub_port Which port on the hub the device is - * connected. Use zero for devices connected - * directly to Octeon. Like hub_device_addr, - * this is only used for full/low speed - * devices behind a high speed hub. - * - * @return A non negative value is a pipe handle. Negative - * values are error codes. - */ extern int cvmx_usb_open_pipe(cvmx_usb_state_t *state, cvmx_usb_pipe_flags_t flags, int device_addr, int endpoint_num, @@ -571,111 +425,14 @@ extern int cvmx_usb_open_pipe(cvmx_usb_state_t *state, cvmx_usb_direction_t transfer_dir, int interval, int multi_count, int hub_device_addr, int hub_port); - -/** - * Call to submit a USB Bulk transfer to a pipe. - * - * @param state USB device state populated by - * cvmx_usb_initialize(). - * @param pipe_handle - * Handle to the pipe for the transfer. - * @param buffer Physical address of the data buffer in - * memory. Note that this is NOT A POINTER, but - * the full 64bit physical address of the - * buffer. This may be zero if buffer_length is - * zero. - * @param buffer_length - * Length of buffer in bytes. - * @param callback Function to call when this transaction - * completes. If the return value of this - * function isn't an error, then this function - * is guaranteed to be called when the - * transaction completes. If this parameter is - * NULL, then the generic callback registered - * through cvmx_usb_register_callback is - * called. If both are NULL, then there is no - * way to know when a transaction completes. - * @param user_data User supplied data returned when the - * callback is called. This is only used if - * callback in not NULL. - * - * @return A submitted transaction handle or negative on - * failure. Negative values are error codes. - */ extern int cvmx_usb_submit_bulk(cvmx_usb_state_t *state, int pipe_handle, uint64_t buffer, int buffer_length, cvmx_usb_callback_func_t callback, void *user_data); - -/** - * Call to submit a USB Interrupt transfer to a pipe. - * - * @param state USB device state populated by - * cvmx_usb_initialize(). - * @param pipe_handle - * Handle to the pipe for the transfer. - * @param buffer Physical address of the data buffer in - * memory. Note that this is NOT A POINTER, but - * the full 64bit physical address of the - * buffer. This may be zero if buffer_length is - * zero. - * @param buffer_length - * Length of buffer in bytes. - * @param callback Function to call when this transaction - * completes. If the return value of this - * function isn't an error, then this function - * is guaranteed to be called when the - * transaction completes. If this parameter is - * NULL, then the generic callback registered - * through cvmx_usb_register_callback is - * called. If both are NULL, then there is no - * way to know when a transaction completes. - * @param user_data User supplied data returned when the - * callback is called. This is only used if - * callback in not NULL. - * - * @return A submitted transaction handle or negative on - * failure. Negative values are error codes. - */ extern int cvmx_usb_submit_interrupt(cvmx_usb_state_t *state, int pipe_handle, uint64_t buffer, int buffer_length, cvmx_usb_callback_func_t callback, void *user_data); - -/** - * Call to submit a USB Control transfer to a pipe. - * - * @param state USB device state populated by - * cvmx_usb_initialize(). - * @param pipe_handle - * Handle to the pipe for the transfer. - * @param control_header - * USB 8 byte control header physical address. - * Note that this is NOT A POINTER, but the - * full 64bit physical address of the buffer. - * @param buffer Physical address of the data buffer in - * memory. Note that this is NOT A POINTER, but - * the full 64bit physical address of the - * buffer. This may be zero if buffer_length is - * zero. - * @param buffer_length - * Length of buffer in bytes. - * @param callback Function to call when this transaction - * completes. If the return value of this - * function isn't an error, then this function - * is guaranteed to be called when the - * transaction completes. If this parameter is - * NULL, then the generic callback registered - * through cvmx_usb_register_callback is - * called. If both are NULL, then there is no - * way to know when a transaction completes. - * @param user_data User supplied data returned when the - * callback is called. This is only used if - * callback in not NULL. - * - * @return A submitted transaction handle or negative on - * failure. Negative values are error codes. - */ extern int cvmx_usb_submit_control(cvmx_usb_state_t *state, int pipe_handle, uint64_t control_header, uint64_t buffer, int buffer_length, @@ -691,50 +448,6 @@ typedef enum CVMX_USB_ISOCHRONOUS_FLAGS_ASAP = 1<<1, /**< Schedule the transaction as soon as possible */ } cvmx_usb_isochronous_flags_t; -/** - * Call to submit a USB Isochronous transfer to a pipe. - * - * @param state USB device state populated by - * cvmx_usb_initialize(). - * @param pipe_handle - * Handle to the pipe for the transfer. - * @param start_frame - * Number of frames into the future to schedule - * this transaction. - * @param flags Flags to control the transfer. See - * cvmx_usb_isochronous_flags_t for the flag - * definitions. - * @param number_packets - * Number of sequential packets to transfer. - * "packets" is a pointer to an array of this - * many packet structures. - * @param packets Description of each transfer packet as - * defined by cvmx_usb_iso_packet_t. The array - * pointed to here must stay valid until the - * complete callback is called. - * @param buffer Physical address of the data buffer in - * memory. Note that this is NOT A POINTER, but - * the full 64bit physical address of the - * buffer. This may be zero if buffer_length is - * zero. - * @param buffer_length - * Length of buffer in bytes. - * @param callback Function to call when this transaction - * completes. If the return value of this - * function isn't an error, then this function - * is guaranteed to be called when the - * transaction completes. If this parameter is - * NULL, then the generic callback registered - * through cvmx_usb_register_callback is - * called. If both are NULL, then there is no - * way to know when a transaction completes. - * @param user_data User supplied data returned when the - * callback is called. This is only used if - * callback in not NULL. - * - * @return A submitted transaction handle or negative on - * failure. Negative values are error codes. - */ extern int cvmx_usb_submit_isochronous(cvmx_usb_state_t *state, int pipe_handle, int start_frame, int flags, int number_packets, @@ -742,91 +455,15 @@ extern int cvmx_usb_submit_isochronous(cvmx_usb_state_t *state, int pipe_handle, uint64_t buffer, int buffer_length, cvmx_usb_callback_func_t callback, void *user_data); - -/** - * Cancel one outstanding request in a pipe. Canceling a request - * can fail if the transaction has already completed before cancel - * is called. Even after a successful cancel call, it may take - * a frame or two for the cvmx_usb_poll() function to call the - * associated callback. - * - * @param state USB device state populated by - * cvmx_usb_initialize(). - * @param pipe_handle - * Pipe handle to cancel requests in. - * @param submit_handle - * Handle to transaction to cancel, returned by the submit function. - * - * @return 0 or a negative error code. - */ extern int cvmx_usb_cancel(cvmx_usb_state_t *state, int pipe_handle, int submit_handle); - - -/** - * Cancel all outstanding requests in a pipe. Logically all this - * does is call cvmx_usb_cancel() in a loop. - * - * @param state USB device state populated by - * cvmx_usb_initialize(). - * @param pipe_handle - * Pipe handle to cancel requests in. - * - * @return 0 or a negative error code. - */ extern int cvmx_usb_cancel_all(cvmx_usb_state_t *state, int pipe_handle); - -/** - * Close a pipe created with cvmx_usb_open_pipe(). - * - * @param state USB device state populated by - * cvmx_usb_initialize(). - * @param pipe_handle - * Pipe handle to close. - * - * @return 0 or a negative error code. EBUSY is returned if the pipe has - * outstanding transfers. - */ extern int cvmx_usb_close_pipe(cvmx_usb_state_t *state, int pipe_handle); - -/** - * Register a function to be called when various USB events occur. - * - * @param state USB device state populated by - * cvmx_usb_initialize(). - * @param reason Which event to register for. - * @param callback Function to call when the event occurs. - * @param user_data User data parameter to the function. - * - * @return 0 or a negative error code. - */ extern int cvmx_usb_register_callback(cvmx_usb_state_t *state, cvmx_usb_callback_t reason, cvmx_usb_callback_func_t callback, void *user_data); - -/** - * Get the current USB protocol level frame number. The frame - * number is always in the range of 0-0x7ff. - * - * @param state USB device state populated by - * cvmx_usb_initialize(). - * - * @return USB frame number - */ extern int cvmx_usb_get_frame_number(cvmx_usb_state_t *state); - -/** - * Poll the USB block for status and call all needed callback - * handlers. This function is meant to be called in the interrupt - * handler for the USB controller. It can also be called - * periodically in a loop for non-interrupt based operation. - * - * @param state USB device state populated by - * cvmx_usb_initialize(). - * - * @return 0 or a negative error code. - */ extern int cvmx_usb_poll(cvmx_usb_state_t *state); #endif /* __CVMX_USB_H__ */ From 116c163f99883be31da88c10ed38df6eb8e25b17 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Mon, 29 Jul 2013 20:07:57 +0300 Subject: [PATCH 1052/3400] staging: octeon-usb: cvmx-usb: convert @param Convert "@param name" inside comments to "@name:". Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.c | 268 +++++++++++++------------- 1 file changed, 134 insertions(+), 134 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.c b/drivers/staging/octeon-usb/cvmx-usb.c index d3da546f3b62..9a7b53ab0b21 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.c +++ b/drivers/staging/octeon-usb/cvmx-usb.c @@ -262,8 +262,8 @@ static int octeon_usb_get_clock_type(void) * for 32bit CSRs and logs the value in a readable format if * debugging is on. * - * @param usb USB block this access is for - * @param address 64bit address to read + * @usb: USB block this access is for + * @address: 64bit address to read * * @return Result of the read */ @@ -280,9 +280,9 @@ static inline uint32_t __cvmx_usb_read_csr32(cvmx_usb_internal_state_t *usb, * swizzle for 32bit CSRs and logs the value in a readable format * if debugging is on. * - * @param usb USB block this access is for - * @param address 64bit address to write - * @param value Value to write + * @usb: USB block this access is for + * @address: 64bit address to write + * @value: Value to write */ static inline void __cvmx_usb_write_csr32(cvmx_usb_internal_state_t *usb, uint64_t address, uint32_t value) @@ -296,8 +296,8 @@ static inline void __cvmx_usb_write_csr32(cvmx_usb_internal_state_t *usb, * Read a USB 64bit CSR. It logs the value in a readable format if * debugging is on. * - * @param usb USB block this access is for - * @param address 64bit address to read + * @usb: USB block this access is for + * @address: 64bit address to read * * @return Result of the read */ @@ -313,9 +313,9 @@ static inline uint64_t __cvmx_usb_read_csr64(cvmx_usb_internal_state_t *usb, * Write a USB 64bit CSR. It logs the value in a readable format * if debugging is on. * - * @param usb USB block this access is for - * @param address 64bit address to write - * @param value Value to write + * @usb: USB block this access is for + * @address: 64bit address to write + * @value: Value to write */ static inline void __cvmx_usb_write_csr64(cvmx_usb_internal_state_t *usb, uint64_t address, uint64_t value) @@ -327,8 +327,8 @@ static inline void __cvmx_usb_write_csr64(cvmx_usb_internal_state_t *usb, * Return non zero if this pipe connects to a non HIGH speed * device through a high speed hub. * - * @param usb USB block this access is for - * @param pipe Pipe to check + * @usb: USB block this access is for + * @pipe: Pipe to check * * @return Non zero if we need to do split transactions */ @@ -341,7 +341,7 @@ static inline int __cvmx_usb_pipe_needs_split(cvmx_usb_internal_state_t *usb, cv /** * Trivial utility function to return the correct PID for a pipe * - * @param pipe pipe to check + * @pipe: pipe to check * * @return PID for pipe */ @@ -388,7 +388,7 @@ int cvmx_usb_get_num_ports(void) /** * Allocate a usb transaction for use * - * @param usb USB device state populated by + * @usb: USB device state populated by * cvmx_usb_initialize(). * * @return Transaction or NULL @@ -413,9 +413,9 @@ static inline cvmx_usb_transaction_t *__cvmx_usb_alloc_transaction(cvmx_usb_inte /** * Free a usb transaction * - * @param usb USB device state populated by + * @usb: USB device state populated by * cvmx_usb_initialize(). - * @param transaction + * @transaction: * Transaction to free */ static inline void __cvmx_usb_free_transaction(cvmx_usb_internal_state_t *usb, @@ -434,8 +434,8 @@ static inline void __cvmx_usb_free_transaction(cvmx_usb_internal_state_t *usb, /** * Add a pipe to the tail of a list - * @param list List to add pipe to - * @param pipe Pipe to add + * @list: List to add pipe to + * @pipe: Pipe to add */ static inline void __cvmx_usb_append_pipe(cvmx_usb_pipe_list_t *list, cvmx_usb_pipe_t *pipe) { @@ -451,8 +451,8 @@ static inline void __cvmx_usb_append_pipe(cvmx_usb_pipe_list_t *list, cvmx_usb_p /** * Remove a pipe from a list - * @param list List to remove pipe from - * @param pipe Pipe to remove + * @list: List to remove pipe from + * @pipe: Pipe to remove */ static inline void __cvmx_usb_remove_pipe(cvmx_usb_pipe_list_t *list, cvmx_usb_pipe_t *pipe) { @@ -481,13 +481,13 @@ static inline void __cvmx_usb_remove_pipe(cvmx_usb_pipe_list_t *list, cvmx_usb_p * other access to the Octeon USB port is made. The port starts * off in the disabled state. * - * @param state Pointer to an empty cvmx_usb_state_t structure + * @state: Pointer to an empty cvmx_usb_state_t structure * that will be populated by the initialize call. * This structure is then passed to all other USB * functions. - * @param usb_port_number + * @usb_port_number: * Which Octeon USB port to initialize. - * @param flags Flags to control hardware initialization. See + * @flags: Flags to control hardware initialization. See * cvmx_usb_initialize_flags_t for the flag * definitions. Some flags are mandatory. * @@ -815,8 +815,8 @@ int cvmx_usb_initialize(cvmx_usb_state_t *state, int usb_port_number, * The port should be disabled with all pipes closed when this * function is called. * - * @param state USB device state populated by - * cvmx_usb_initialize(). + * @state: USB device state populated by + * cvmx_usb_initialize(). * * @return 0 or a negative error code. */ @@ -850,8 +850,8 @@ int cvmx_usb_shutdown(cvmx_usb_state_t *state) * Enable a USB port. After this call succeeds, the USB port is * online and servicing requests. * - * @param state USB device state populated by - * cvmx_usb_initialize(). + * @state: USB device state populated by + * cvmx_usb_initialize(). * * @return 0 or a negative error code. */ @@ -944,8 +944,8 @@ int cvmx_usb_enable(cvmx_usb_state_t *state) * Transactions in process will fail and call their * associated callbacks. * - * @param state USB device state populated by - * cvmx_usb_initialize(). + * @state: USB device state populated by + * cvmx_usb_initialize(). * * @return 0 or a negative error code. */ @@ -968,8 +968,8 @@ int cvmx_usb_disable(cvmx_usb_state_t *state) * on the last call to cvmx_usb_set_status(). In order to clear * them, you must update the status through cvmx_usb_set_status(). * - * @param state USB device state populated by - * cvmx_usb_initialize(). + * @state: USB device state populated by + * cvmx_usb_initialize(). * * @return Port status information */ @@ -1000,9 +1000,9 @@ cvmx_usb_port_status_t cvmx_usb_get_status(cvmx_usb_state_t *state) * status passed to this function is not used. No fields can be * changed through this call. * - * @param state USB device state populated by + * @state: USB device state populated by * cvmx_usb_initialize(). - * @param port_status + * @port_status: * Port status to set, most like returned by cvmx_usb_get_status() */ void cvmx_usb_set_status(cvmx_usb_state_t *state, cvmx_usb_port_status_t port_status) @@ -1016,9 +1016,9 @@ void cvmx_usb_set_status(cvmx_usb_state_t *state, cvmx_usb_port_status_t port_st /** * Convert a USB transaction into a handle * - * @param usb USB device state populated by + * @usb: USB device state populated by * cvmx_usb_initialize(). - * @param transaction + * @transaction: * Transaction to get handle for * * @return Handle @@ -1034,9 +1034,9 @@ static inline int __cvmx_usb_get_submit_handle(cvmx_usb_internal_state_t *usb, /** * Convert a USB pipe into a handle * - * @param usb USB device state populated by + * @usb: USB device state populated by * cvmx_usb_initialize(). - * @param pipe Pipe to get handle for + * @pipe: Pipe to get handle for * * @return Handle */ @@ -1052,49 +1052,49 @@ static inline int __cvmx_usb_get_pipe_handle(cvmx_usb_internal_state_t *usb, * must be opened before data can be transferred between a device * and Octeon. * - * @param state USB device state populated by + * @state: USB device state populated by * cvmx_usb_initialize(). - * @param flags Optional pipe flags defined in + * @flags: Optional pipe flags defined in * cvmx_usb_pipe_flags_t. - * @param device_addr + * @device_addr: * USB device address to open the pipe to * (0-127). - * @param endpoint_num + * @endpoint_num: * USB endpoint number to open the pipe to * (0-15). - * @param device_speed + * @device_speed: * The speed of the device the pipe is going * to. This must match the device's speed, * which may be different than the port speed. - * @param max_packet The maximum packet length the device can + * @max_packet: The maximum packet length the device can * transmit/receive (low speed=0-8, full * speed=0-1023, high speed=0-1024). This value * comes from the standard endpoint descriptor * field wMaxPacketSize bits <10:0>. - * @param transfer_type + * @transfer_type: * The type of transfer this pipe is for. - * @param transfer_dir + * @transfer_dir: * The direction the pipe is in. This is not * used for control pipes. - * @param interval For ISOCHRONOUS and INTERRUPT transfers, + * @interval: For ISOCHRONOUS and INTERRUPT transfers, * this is how often the transfer is scheduled * for. All other transfers should specify * zero. The units are in frames (8000/sec at * high speed, 1000/sec for full speed). - * @param multi_count + * @multi_count: * For high speed devices, this is the maximum * allowed number of packet per microframe. * Specify zero for non high speed devices. This * value comes from the standard endpoint descriptor * field wMaxPacketSize bits <12:11>. - * @param hub_device_addr + * @hub_device_addr: * Hub device address this device is connected * to. Devices connected directly to Octeon * use zero. This is only used when the device * is full/low speed behind a high speed hub. * The address will be of the high speed hub, * not and full speed hubs after it. - * @param hub_port Which port on the hub the device is + * @hub_port: Which port on the hub the device is * connected. Use zero for devices connected * directly to Octeon. Like hub_device_addr, * this is only used for full/low speed @@ -1191,7 +1191,7 @@ int cvmx_usb_open_pipe(cvmx_usb_state_t *state, cvmx_usb_pipe_flags_t flags, * in non DMA mode. It is very important that this function be called quickly * enough to prevent FIFO overflow. * - * @param usb USB device state populated by + * @usb: USB device state populated by * cvmx_usb_initialize(). */ static void __cvmx_usb_poll_rx_fifo(cvmx_usb_internal_state_t *usb) @@ -1235,10 +1235,10 @@ static void __cvmx_usb_poll_rx_fifo(cvmx_usb_internal_state_t *usb) * Fill the TX hardware fifo with data out of the software * fifos * - * @param usb USB device state populated by + * @usb: USB device state populated by * cvmx_usb_initialize(). - * @param fifo Software fifo to use - * @param available Amount of space in the hardware fifo + * @fifo: Software fifo to use + * @available: Amount of space in the hardware fifo * * @return Non zero if the hardware fifo was too small and needs * to be serviced again. @@ -1294,7 +1294,7 @@ static int __cvmx_usb_fill_tx_hw(cvmx_usb_internal_state_t *usb, cvmx_usb_tx_fif /** * Check the hardware FIFOs and fill them as needed * - * @param usb USB device state populated by + * @usb: USB device state populated by * cvmx_usb_initialize(). */ static void __cvmx_usb_poll_tx_fifo(cvmx_usb_internal_state_t *usb) @@ -1324,9 +1324,9 @@ static void __cvmx_usb_poll_tx_fifo(cvmx_usb_internal_state_t *usb) /** * Fill the TX FIFO with an outgoing packet * - * @param usb USB device state populated by + * @usb: USB device state populated by * cvmx_usb_initialize(). - * @param channel Channel number to get packet from + * @channel: Channel number to get packet from */ static void __cvmx_usb_fill_tx_fifo(cvmx_usb_internal_state_t *usb, int channel) { @@ -1373,10 +1373,10 @@ static void __cvmx_usb_fill_tx_fifo(cvmx_usb_internal_state_t *usb, int channel) * the generic stuff will already have been done in * __cvmx_usb_start_channel() * - * @param usb USB device state populated by + * @usb: USB device state populated by * cvmx_usb_initialize(). - * @param channel Channel to setup - * @param pipe Pipe for control transaction + * @channel: Channel to setup + * @pipe: Pipe for control transaction */ static void __cvmx_usb_start_channel_control(cvmx_usb_internal_state_t *usb, int channel, @@ -1502,10 +1502,10 @@ static void __cvmx_usb_start_channel_control(cvmx_usb_internal_state_t *usb, /** * Start a channel to perform the pipe's head transaction * - * @param usb USB device state populated by + * @usb: USB device state populated by * cvmx_usb_initialize(). - * @param channel Channel to setup - * @param pipe Pipe to start + * @channel: Channel to setup + * @pipe: Pipe to start */ static void __cvmx_usb_start_channel(cvmx_usb_internal_state_t *usb, int channel, @@ -1788,10 +1788,10 @@ static void __cvmx_usb_start_channel(cvmx_usb_internal_state_t *usb, /** * Find a pipe that is ready to be scheduled to hardware. - * @param usb USB device state populated by + * @usb: USB device state populated by * cvmx_usb_initialize(). - * @param list Pipe list to search - * @param current_frame + * @list: Pipe list to search + * @current_frame: * Frame counter to use as a time reference. * * @return Pipe or NULL if none are ready @@ -1818,9 +1818,9 @@ static cvmx_usb_pipe_t *__cvmx_usb_find_ready_pipe(cvmx_usb_internal_state_t *us * Called whenever a pipe might need to be scheduled to the * hardware. * - * @param usb USB device state populated by + * @usb: USB device state populated by * cvmx_usb_initialize(). - * @param is_sof True if this schedule was called on a SOF interrupt. + * @is_sof: True if this schedule was called on a SOF interrupt. */ static void __cvmx_usb_schedule(cvmx_usb_internal_state_t *usb, int is_sof) { @@ -1891,13 +1891,13 @@ done: /** * Call a user's callback for a specific reason. * - * @param usb USB device state populated by + * @usb: USB device state populated by * cvmx_usb_initialize(). - * @param pipe Pipe the callback is for or NULL - * @param transaction + * @pipe: Pipe the callback is for or NULL + * @transaction: * Transaction the callback is for or NULL - * @param reason Reason this callback is being called - * @param complete_code + * @reason: Reason this callback is being called + * @complete_code: * Completion code for the transaction, if any */ static void __cvmx_usb_perform_callback(cvmx_usb_internal_state_t *usb, @@ -1937,12 +1937,12 @@ static void __cvmx_usb_perform_callback(cvmx_usb_internal_state_t *usb, * Signal the completion of a transaction and free it. The * transaction will be removed from the pipe transaction list. * - * @param usb USB device state populated by + * @usb: USB device state populated by * cvmx_usb_initialize(). - * @param pipe Pipe the transaction is on - * @param transaction + * @pipe: Pipe the transaction is on + * @transaction: * Transaction that completed - * @param complete_code + * @complete_code: * Completion code */ static void __cvmx_usb_perform_complete(cvmx_usb_internal_state_t *usb, @@ -2003,24 +2003,24 @@ done: * Submit a usb transaction to a pipe. Called for all types * of transactions. * - * @param usb - * @param pipe_handle + * @usb: + * @pipe_handle: * Which pipe to submit to. Will be validated in this function. - * @param type Transaction type - * @param flags Flags for the transaction - * @param buffer User buffer for the transaction - * @param buffer_length + * @type: Transaction type + * @flags: Flags for the transaction + * @buffer: User buffer for the transaction + * @buffer_length: * User buffer's length in bytes - * @param control_header + * @control_header: * For control transactions, the 8 byte standard header - * @param iso_start_frame + * @iso_start_frame: * For ISO transactions, the start frame - * @param iso_number_packets + * @iso_number_packets: * For ISO, the number of packet in the transaction. - * @param iso_packets + * @iso_packets: * A description of each ISO packet - * @param callback User callback to call when the transaction completes - * @param user_data User's data for the callback + * @callback: User callback to call when the transaction completes + * @user_data: User's data for the callback * * @return Submit handle or negative on failure. Matches the result * in the external API. @@ -2097,18 +2097,18 @@ static int __cvmx_usb_submit_transaction(cvmx_usb_internal_state_t *usb, /** * Call to submit a USB Bulk transfer to a pipe. * - * @param state USB device state populated by + * @state: USB device state populated by * cvmx_usb_initialize(). - * @param pipe_handle + * @pipe_handle: * Handle to the pipe for the transfer. - * @param buffer Physical address of the data buffer in + * @buffer: Physical address of the data buffer in * memory. Note that this is NOT A POINTER, but * the full 64bit physical address of the * buffer. This may be zero if buffer_length is * zero. - * @param buffer_length + * @buffer_length: * Length of buffer in bytes. - * @param callback Function to call when this transaction + * @callback: Function to call when this transaction * completes. If the return value of this * function isn't an error, then this function * is guaranteed to be called when the @@ -2117,7 +2117,7 @@ static int __cvmx_usb_submit_transaction(cvmx_usb_internal_state_t *usb, * through cvmx_usb_register_callback is * called. If both are NULL, then there is no * way to know when a transaction completes. - * @param user_data User supplied data returned when the + * @user_data: User supplied data returned when the * callback is called. This is only used if * callback in not NULL. * @@ -2156,18 +2156,18 @@ int cvmx_usb_submit_bulk(cvmx_usb_state_t *state, int pipe_handle, /** * Call to submit a USB Interrupt transfer to a pipe. * - * @param state USB device state populated by + * @state: USB device state populated by * cvmx_usb_initialize(). - * @param pipe_handle + * @pipe_handle: * Handle to the pipe for the transfer. - * @param buffer Physical address of the data buffer in + * @buffer: Physical address of the data buffer in * memory. Note that this is NOT A POINTER, but * the full 64bit physical address of the * buffer. This may be zero if buffer_length is * zero. - * @param buffer_length + * @buffer_length: * Length of buffer in bytes. - * @param callback Function to call when this transaction + * @callback: Function to call when this transaction * completes. If the return value of this * function isn't an error, then this function * is guaranteed to be called when the @@ -2176,7 +2176,7 @@ int cvmx_usb_submit_bulk(cvmx_usb_state_t *state, int pipe_handle, * through cvmx_usb_register_callback is * called. If both are NULL, then there is no * way to know when a transaction completes. - * @param user_data User supplied data returned when the + * @user_data: User supplied data returned when the * callback is called. This is only used if * callback in not NULL. * @@ -2215,22 +2215,22 @@ int cvmx_usb_submit_interrupt(cvmx_usb_state_t *state, int pipe_handle, /** * Call to submit a USB Control transfer to a pipe. * - * @param state USB device state populated by + * @state: USB device state populated by * cvmx_usb_initialize(). - * @param pipe_handle + * @pipe_handle: * Handle to the pipe for the transfer. - * @param control_header + * @control_header: * USB 8 byte control header physical address. * Note that this is NOT A POINTER, but the * full 64bit physical address of the buffer. - * @param buffer Physical address of the data buffer in + * @buffer: Physical address of the data buffer in * memory. Note that this is NOT A POINTER, but * the full 64bit physical address of the * buffer. This may be zero if buffer_length is * zero. - * @param buffer_length + * @buffer_length: * Length of buffer in bytes. - * @param callback Function to call when this transaction + * @callback: Function to call when this transaction * completes. If the return value of this * function isn't an error, then this function * is guaranteed to be called when the @@ -2239,7 +2239,7 @@ int cvmx_usb_submit_interrupt(cvmx_usb_state_t *state, int pipe_handle, * through cvmx_usb_register_callback is * called. If both are NULL, then there is no * way to know when a transaction completes. - * @param user_data User supplied data returned when the + * @user_data: User supplied data returned when the * callback is called. This is only used if * callback in not NULL. * @@ -2285,32 +2285,32 @@ int cvmx_usb_submit_control(cvmx_usb_state_t *state, int pipe_handle, /** * Call to submit a USB Isochronous transfer to a pipe. * - * @param state USB device state populated by + * @state: USB device state populated by * cvmx_usb_initialize(). - * @param pipe_handle + * @pipe_handle: * Handle to the pipe for the transfer. - * @param start_frame + * @start_frame: * Number of frames into the future to schedule * this transaction. - * @param flags Flags to control the transfer. See + * @flags: Flags to control the transfer. See * cvmx_usb_isochronous_flags_t for the flag * definitions. - * @param number_packets + * @number_packets: * Number of sequential packets to transfer. * "packets" is a pointer to an array of this * many packet structures. - * @param packets Description of each transfer packet as + * @packets: Description of each transfer packet as * defined by cvmx_usb_iso_packet_t. The array * pointed to here must stay valid until the * complete callback is called. - * @param buffer Physical address of the data buffer in + * @buffer: Physical address of the data buffer in * memory. Note that this is NOT A POINTER, but * the full 64bit physical address of the * buffer. This may be zero if buffer_length is * zero. - * @param buffer_length + * @buffer_length: * Length of buffer in bytes. - * @param callback Function to call when this transaction + * @callback: Function to call when this transaction * completes. If the return value of this * function isn't an error, then this function * is guaranteed to be called when the @@ -2319,7 +2319,7 @@ int cvmx_usb_submit_control(cvmx_usb_state_t *state, int pipe_handle, * through cvmx_usb_register_callback is * called. If both are NULL, then there is no * way to know when a transaction completes. - * @param user_data User supplied data returned when the + * @user_data: User supplied data returned when the * callback is called. This is only used if * callback in not NULL. * @@ -2373,11 +2373,11 @@ int cvmx_usb_submit_isochronous(cvmx_usb_state_t *state, int pipe_handle, * a frame or two for the cvmx_usb_poll() function to call the * associated callback. * - * @param state USB device state populated by + * @state: USB device state populated by * cvmx_usb_initialize(). - * @param pipe_handle + * @pipe_handle: * Pipe handle to cancel requests in. - * @param submit_handle + * @submit_handle: * Handle to transaction to cancel, returned by the submit function. * * @return 0 or a negative error code. @@ -2432,9 +2432,9 @@ int cvmx_usb_cancel(cvmx_usb_state_t *state, int pipe_handle, int submit_handle) * Cancel all outstanding requests in a pipe. Logically all this * does is call cvmx_usb_cancel() in a loop. * - * @param state USB device state populated by + * @state: USB device state populated by * cvmx_usb_initialize(). - * @param pipe_handle + * @pipe_handle: * Pipe handle to cancel requests in. * * @return 0 or a negative error code. @@ -2465,9 +2465,9 @@ int cvmx_usb_cancel_all(cvmx_usb_state_t *state, int pipe_handle) /** * Close a pipe created with cvmx_usb_open_pipe(). * - * @param state USB device state populated by + * @state: USB device state populated by * cvmx_usb_initialize(). - * @param pipe_handle + * @pipe_handle: * Pipe handle to close. * * @return 0 or a negative error code. EBUSY is returned if the pipe has @@ -2500,11 +2500,11 @@ int cvmx_usb_close_pipe(cvmx_usb_state_t *state, int pipe_handle) /** * Register a function to be called when various USB events occur. * - * @param state USB device state populated by - * cvmx_usb_initialize(). - * @param reason Which event to register for. - * @param callback Function to call when the event occurs. - * @param user_data User data parameter to the function. + * @state: USB device state populated by + * cvmx_usb_initialize(). + * @reason: Which event to register for. + * @callback: Function to call when the event occurs. + * @user_data: User data parameter to the function. * * @return 0 or a negative error code. */ @@ -2531,8 +2531,8 @@ int cvmx_usb_register_callback(cvmx_usb_state_t *state, * Get the current USB protocol level frame number. The frame * number is always in the range of 0-0x7ff. * - * @param state USB device state populated by - * cvmx_usb_initialize(). + * @state: USB device state populated by + * cvmx_usb_initialize(). * * @return USB frame number */ @@ -2552,8 +2552,8 @@ int cvmx_usb_get_frame_number(cvmx_usb_state_t *state) /** * Poll a channel for status * - * @param usb USB device - * @param channel Channel to poll + * @usb: USB device + * @channel: Channel to poll * * @return Zero on success */ @@ -2989,7 +2989,7 @@ static int __cvmx_usb_poll_channel(cvmx_usb_internal_state_t *usb, int channel) * handler for the USB controller. It can also be called * periodically in a loop for non-interrupt based operation. * - * @param state USB device state populated by + * @state: USB device state populated by * cvmx_usb_initialize(). * * @return 0 or a negative error code. From 46e0270c25dd5b0ca2616db3b274031e7c79188e Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Mon, 29 Jul 2013 20:07:58 +0300 Subject: [PATCH 1053/3400] staging: octeon-usb: cvmx-usb: convert @return Convert "@return" to "Returns: ". Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.c | 72 +++++++++++++-------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.c b/drivers/staging/octeon-usb/cvmx-usb.c index 9a7b53ab0b21..a3ac3406ea71 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.c +++ b/drivers/staging/octeon-usb/cvmx-usb.c @@ -265,7 +265,7 @@ static int octeon_usb_get_clock_type(void) * @usb: USB block this access is for * @address: 64bit address to read * - * @return Result of the read + * Returns: Result of the read */ static inline uint32_t __cvmx_usb_read_csr32(cvmx_usb_internal_state_t *usb, uint64_t address) @@ -299,7 +299,7 @@ static inline void __cvmx_usb_write_csr32(cvmx_usb_internal_state_t *usb, * @usb: USB block this access is for * @address: 64bit address to read * - * @return Result of the read + * Returns: Result of the read */ static inline uint64_t __cvmx_usb_read_csr64(cvmx_usb_internal_state_t *usb, uint64_t address) @@ -330,7 +330,7 @@ static inline void __cvmx_usb_write_csr64(cvmx_usb_internal_state_t *usb, * @usb: USB block this access is for * @pipe: Pipe to check * - * @return Non zero if we need to do split transactions + * Returns: Non zero if we need to do split transactions */ static inline int __cvmx_usb_pipe_needs_split(cvmx_usb_internal_state_t *usb, cvmx_usb_pipe_t *pipe) { @@ -343,7 +343,7 @@ static inline int __cvmx_usb_pipe_needs_split(cvmx_usb_internal_state_t *usb, cv * * @pipe: pipe to check * - * @return PID for pipe + * Returns: PID for pipe */ static inline int __cvmx_usb_get_data_pid(cvmx_usb_pipe_t *pipe) { @@ -362,7 +362,7 @@ static inline int __cvmx_usb_get_data_pid(cvmx_usb_pipe_t *pipe) * cvmx_usb_initialize() must be called on independent * cvmx_usb_state_t structures. * - * @return Number of port, zero if usb isn't supported + * Returns: Number of port, zero if usb isn't supported */ int cvmx_usb_get_num_ports(void) { @@ -391,7 +391,7 @@ int cvmx_usb_get_num_ports(void) * @usb: USB device state populated by * cvmx_usb_initialize(). * - * @return Transaction or NULL + * Returns: Transaction or NULL */ static inline cvmx_usb_transaction_t *__cvmx_usb_alloc_transaction(cvmx_usb_internal_state_t *usb) { @@ -491,7 +491,7 @@ static inline void __cvmx_usb_remove_pipe(cvmx_usb_pipe_list_t *list, cvmx_usb_p * cvmx_usb_initialize_flags_t for the flag * definitions. Some flags are mandatory. * - * @return 0 or a negative error code. + * Returns: 0 or a negative error code. */ int cvmx_usb_initialize(cvmx_usb_state_t *state, int usb_port_number, cvmx_usb_initialize_flags_t flags) @@ -818,7 +818,7 @@ int cvmx_usb_initialize(cvmx_usb_state_t *state, int usb_port_number, * @state: USB device state populated by * cvmx_usb_initialize(). * - * @return 0 or a negative error code. + * Returns: 0 or a negative error code. */ int cvmx_usb_shutdown(cvmx_usb_state_t *state) { @@ -853,7 +853,7 @@ int cvmx_usb_shutdown(cvmx_usb_state_t *state) * @state: USB device state populated by * cvmx_usb_initialize(). * - * @return 0 or a negative error code. + * Returns: 0 or a negative error code. */ int cvmx_usb_enable(cvmx_usb_state_t *state) { @@ -947,7 +947,7 @@ int cvmx_usb_enable(cvmx_usb_state_t *state) * @state: USB device state populated by * cvmx_usb_initialize(). * - * @return 0 or a negative error code. + * Returns: 0 or a negative error code. */ int cvmx_usb_disable(cvmx_usb_state_t *state) { @@ -971,7 +971,7 @@ int cvmx_usb_disable(cvmx_usb_state_t *state) * @state: USB device state populated by * cvmx_usb_initialize(). * - * @return Port status information + * Returns: Port status information */ cvmx_usb_port_status_t cvmx_usb_get_status(cvmx_usb_state_t *state) { @@ -1021,7 +1021,7 @@ void cvmx_usb_set_status(cvmx_usb_state_t *state, cvmx_usb_port_status_t port_st * @transaction: * Transaction to get handle for * - * @return Handle + * Returns: Handle */ static inline int __cvmx_usb_get_submit_handle(cvmx_usb_internal_state_t *usb, cvmx_usb_transaction_t *transaction) @@ -1038,7 +1038,7 @@ static inline int __cvmx_usb_get_submit_handle(cvmx_usb_internal_state_t *usb, * cvmx_usb_initialize(). * @pipe: Pipe to get handle for * - * @return Handle + * Returns: Handle */ static inline int __cvmx_usb_get_pipe_handle(cvmx_usb_internal_state_t *usb, cvmx_usb_pipe_t *pipe) @@ -1100,8 +1100,8 @@ static inline int __cvmx_usb_get_pipe_handle(cvmx_usb_internal_state_t *usb, * this is only used for full/low speed * devices behind a high speed hub. * - * @return A non negative value is a pipe handle. Negative - * values are error codes. + * Returns: A non negative value is a pipe handle. Negative + * values are error codes. */ int cvmx_usb_open_pipe(cvmx_usb_state_t *state, cvmx_usb_pipe_flags_t flags, int device_addr, int endpoint_num, @@ -1240,8 +1240,8 @@ static void __cvmx_usb_poll_rx_fifo(cvmx_usb_internal_state_t *usb) * @fifo: Software fifo to use * @available: Amount of space in the hardware fifo * - * @return Non zero if the hardware fifo was too small and needs - * to be serviced again. + * Returns: Non zero if the hardware fifo was too small and needs + * to be serviced again. */ static int __cvmx_usb_fill_tx_hw(cvmx_usb_internal_state_t *usb, cvmx_usb_tx_fifo_t *fifo, int available) { @@ -1794,7 +1794,7 @@ static void __cvmx_usb_start_channel(cvmx_usb_internal_state_t *usb, * @current_frame: * Frame counter to use as a time reference. * - * @return Pipe or NULL if none are ready + * Returns: Pipe or NULL if none are ready */ static cvmx_usb_pipe_t *__cvmx_usb_find_ready_pipe(cvmx_usb_internal_state_t *usb, cvmx_usb_pipe_list_t *list, uint64_t current_frame) { @@ -2022,8 +2022,8 @@ done: * @callback: User callback to call when the transaction completes * @user_data: User's data for the callback * - * @return Submit handle or negative on failure. Matches the result - * in the external API. + * Returns: Submit handle or negative on failure. Matches the result + * in the external API. */ static int __cvmx_usb_submit_transaction(cvmx_usb_internal_state_t *usb, int pipe_handle, @@ -2121,8 +2121,8 @@ static int __cvmx_usb_submit_transaction(cvmx_usb_internal_state_t *usb, * callback is called. This is only used if * callback in not NULL. * - * @return A submitted transaction handle or negative on - * failure. Negative values are error codes. + * Returns: A submitted transaction handle or negative on + * failure. Negative values are error codes. */ int cvmx_usb_submit_bulk(cvmx_usb_state_t *state, int pipe_handle, uint64_t buffer, int buffer_length, @@ -2180,8 +2180,8 @@ int cvmx_usb_submit_bulk(cvmx_usb_state_t *state, int pipe_handle, * callback is called. This is only used if * callback in not NULL. * - * @return A submitted transaction handle or negative on - * failure. Negative values are error codes. + * Returns: A submitted transaction handle or negative on + * failure. Negative values are error codes. */ int cvmx_usb_submit_interrupt(cvmx_usb_state_t *state, int pipe_handle, uint64_t buffer, int buffer_length, @@ -2243,8 +2243,8 @@ int cvmx_usb_submit_interrupt(cvmx_usb_state_t *state, int pipe_handle, * callback is called. This is only used if * callback in not NULL. * - * @return A submitted transaction handle or negative on - * failure. Negative values are error codes. + * Returns: A submitted transaction handle or negative on + * failure. Negative values are error codes. */ int cvmx_usb_submit_control(cvmx_usb_state_t *state, int pipe_handle, uint64_t control_header, @@ -2323,8 +2323,8 @@ int cvmx_usb_submit_control(cvmx_usb_state_t *state, int pipe_handle, * callback is called. This is only used if * callback in not NULL. * - * @return A submitted transaction handle or negative on - * failure. Negative values are error codes. + * Returns: A submitted transaction handle or negative on + * failure. Negative values are error codes. */ int cvmx_usb_submit_isochronous(cvmx_usb_state_t *state, int pipe_handle, int start_frame, int flags, @@ -2380,7 +2380,7 @@ int cvmx_usb_submit_isochronous(cvmx_usb_state_t *state, int pipe_handle, * @submit_handle: * Handle to transaction to cancel, returned by the submit function. * - * @return 0 or a negative error code. + * Returns: 0 or a negative error code. */ int cvmx_usb_cancel(cvmx_usb_state_t *state, int pipe_handle, int submit_handle) { @@ -2437,7 +2437,7 @@ int cvmx_usb_cancel(cvmx_usb_state_t *state, int pipe_handle, int submit_handle) * @pipe_handle: * Pipe handle to cancel requests in. * - * @return 0 or a negative error code. + * Returns: 0 or a negative error code. */ int cvmx_usb_cancel_all(cvmx_usb_state_t *state, int pipe_handle) { @@ -2470,8 +2470,8 @@ int cvmx_usb_cancel_all(cvmx_usb_state_t *state, int pipe_handle) * @pipe_handle: * Pipe handle to close. * - * @return 0 or a negative error code. EBUSY is returned if the pipe has - * outstanding transfers. + * Returns: 0 or a negative error code. EBUSY is returned if the pipe has + * outstanding transfers. */ int cvmx_usb_close_pipe(cvmx_usb_state_t *state, int pipe_handle) { @@ -2506,7 +2506,7 @@ int cvmx_usb_close_pipe(cvmx_usb_state_t *state, int pipe_handle) * @callback: Function to call when the event occurs. * @user_data: User data parameter to the function. * - * @return 0 or a negative error code. + * Returns: 0 or a negative error code. */ int cvmx_usb_register_callback(cvmx_usb_state_t *state, cvmx_usb_callback_t reason, @@ -2534,7 +2534,7 @@ int cvmx_usb_register_callback(cvmx_usb_state_t *state, * @state: USB device state populated by * cvmx_usb_initialize(). * - * @return USB frame number + * Returns: USB frame number */ int cvmx_usb_get_frame_number(cvmx_usb_state_t *state) { @@ -2555,7 +2555,7 @@ int cvmx_usb_get_frame_number(cvmx_usb_state_t *state) * @usb: USB device * @channel: Channel to poll * - * @return Zero on success + * Returns: Zero on success */ static int __cvmx_usb_poll_channel(cvmx_usb_internal_state_t *usb, int channel) { @@ -2992,7 +2992,7 @@ static int __cvmx_usb_poll_channel(cvmx_usb_internal_state_t *usb, int channel) * @state: USB device state populated by * cvmx_usb_initialize(). * - * @return 0 or a negative error code. + * Returns: 0 or a negative error code. */ int cvmx_usb_poll(cvmx_usb_state_t *state) { From 3d1dc6adf09fa0d49625da72d39c179ab9d1e893 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Mon, 29 Jul 2013 20:07:59 +0300 Subject: [PATCH 1054/3400] staging: octeon-usb: cvmx-usb: delete CVS keyword markers Delete CVS keyword markers. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.c | 2 -- drivers/staging/octeon-usb/cvmx-usb.h | 2 -- 2 files changed, 4 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.c b/drivers/staging/octeon-usb/cvmx-usb.c index a3ac3406ea71..fa029e3f8db1 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.c +++ b/drivers/staging/octeon-usb/cvmx-usb.c @@ -46,8 +46,6 @@ * systems. These functions provide a generic API to the Octeon * USB blocks, hiding the internal hardware specific * operations. - * - *
$Revision: 32636 $
*/ #include #include diff --git a/drivers/staging/octeon-usb/cvmx-usb.h b/drivers/staging/octeon-usb/cvmx-usb.h index 30d7213ed19e..b8e9054da637 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.h +++ b/drivers/staging/octeon-usb/cvmx-usb.h @@ -234,8 +234,6 @@ * * If you aren't using interrupts, simple call cvmx_usb_poll() * in your main processing loop. - * - *
$Revision: 32636 $
*/ #ifndef __CVMX_USB_H__ From 12aede9f2f8c77f3615fabb4a32bacea5eda848a Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Mon, 29 Jul 2013 20:08:00 +0300 Subject: [PATCH 1055/3400] staging: octeon-usb: cvmx-usb: reformat documentation Reformat the high-level documentation to human readable plain text by removing HTML and other tags. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.h | 101 ++++++++++++-------------- 1 file changed, 48 insertions(+), 53 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.h b/drivers/staging/octeon-usb/cvmx-usb.h index b8e9054da637..4b425e5fa8ae 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.h +++ b/drivers/staging/octeon-usb/cvmx-usb.h @@ -39,8 +39,6 @@ /** - * @file - * * "cvmx-usb.h" defines a set of low level USB functions to help * developers create Octeon USB drivers for various operating * systems. These functions provide a generic API to the Octeon @@ -49,24 +47,24 @@ * * At a high level the device driver needs to: * - * -# Call cvmx_usb_get_num_ports() to get the number of - * supported ports. - * -# Call cvmx_usb_initialize() for each Octeon USB port. - * -# Enable the port using cvmx_usb_enable(). - * -# Either periodically, or in an interrupt handler, call - * cvmx_usb_poll() to service USB events. - * -# Manage pipes using cvmx_usb_open_pipe() and - * cvmx_usb_close_pipe(). - * -# Manage transfers using cvmx_usb_submit_*() and - * cvmx_usb_cancel*(). - * -# Shutdown USB on unload using cvmx_usb_shutdown(). + * - Call cvmx_usb_get_num_ports() to get the number of + * supported ports. + * - Call cvmx_usb_initialize() for each Octeon USB port. + * - Enable the port using cvmx_usb_enable(). + * - Either periodically, or in an interrupt handler, call + * cvmx_usb_poll() to service USB events. + * - Manage pipes using cvmx_usb_open_pipe() and + * cvmx_usb_close_pipe(). + * - Manage transfers using cvmx_usb_submit_*() and + * cvmx_usb_cancel*(). + * - Shutdown USB on unload using cvmx_usb_shutdown(). * * To monitor USB status changes, the device driver must use * cvmx_usb_register_callback() to register for events that it * is interested in. Below are a few hints on successfully * implementing a driver on top of this API. * - *

Initialization

+ * == Initialization == * * When a driver is first loaded, it is normally not necessary * to bring up the USB port completely. Most operating systems @@ -75,24 +73,24 @@ * initialize anything found, and then enable the hardware. * * In the probe phase you should: - * -# Use cvmx_usb_get_num_ports() to determine the number of - * USB port to be supported. - * -# Allocate space for a cvmx_usb_state_t structure for each - * port. - * -# Tell the operating system about each port + * - Use cvmx_usb_get_num_ports() to determine the number of + * USB port to be supported. + * - Allocate space for a cvmx_usb_state_t structure for each + * port. + * - Tell the operating system about each port * * In the initialization phase you should: - * -# Use cvmx_usb_initialize() on each port. - * -# Do not call cvmx_usb_enable(). This leaves the USB port in - * the disabled state until the operating system is ready. + * - Use cvmx_usb_initialize() on each port. + * - Do not call cvmx_usb_enable(). This leaves the USB port in + * the disabled state until the operating system is ready. * * Finally, in the enable phase you should: - * -# Call cvmx_usb_enable() on the appropriate port. - * -# Note that some operating system use a RESET instead of an - * enable call. To implement RESET, you should call - * cvmx_usb_disable() followed by cvmx_usb_enable(). + * - Call cvmx_usb_enable() on the appropriate port. + * - Note that some operating system use a RESET instead of an + * enable call. To implement RESET, you should call + * cvmx_usb_disable() followed by cvmx_usb_enable(). * - *

Locking

+ * == Locking == * * All of the functions in the cvmx-usb API assume exclusive * access to the USB hardware and internal data structures. This @@ -112,7 +110,7 @@ * take a lock to make sure that another core cannot call * cvmx-usb. * - *

Port callback

+ * == Port callback == * * The port callback prototype needs to look as follows: * @@ -123,14 +121,13 @@ * int submit_handle, * int bytes_transferred, * void *user_data); - * - @b usb is the cvmx_usb_state_t for the port. - * - @b reason will always be - * CVMX_USB_CALLBACK_PORT_CHANGED. - * - @b status will always be CVMX_USB_COMPLETE_SUCCESS. - * - @b pipe_handle will always be -1. - * - @b submit_handle will always be -1. - * - @b bytes_transferred will always be 0. - * - @b user_data is the void pointer originally passed along + * - "usb" is the cvmx_usb_state_t for the port. + * - "reason" will always be CVMX_USB_CALLBACK_PORT_CHANGED. + * - "status" will always be CVMX_USB_COMPLETE_SUCCESS. + * - "pipe_handle" will always be -1. + * - "submit_handle" will always be -1. + * - "bytes_transferred" will always be 0. + * - "user_data" is the void pointer originally passed along * with the callback. Use this for any state information you * need. * @@ -140,12 +137,12 @@ * root port. Normally all the callback needs to do is tell the * operating system to poll the root hub for status. Under * Linux, this is performed by calling usb_hcd_poll_rh_status(). - * In the Linux driver we use @b user_data. to pass around the + * In the Linux driver we use "user_data". to pass around the * Linux "hcd" structure. Once the port callback completes, * Linux automatically calls octeon_usb_hub_status_data() which * uses cvmx_usb_get_status() to determine the root port status. * - *

Complete callback

+ * == Complete callback == * * The completion callback prototype needs to look as follows: * @@ -156,29 +153,27 @@ * int submit_handle, * int bytes_transferred, * void *user_data); - * - @b usb is the cvmx_usb_state_t for the port. - * - @b reason will always be - * CVMX_USB_CALLBACK_TRANSFER_COMPLETE. - * - @b status will be one of the cvmx_usb_complete_t - * enumerations. - * - @b pipe_handle is the handle to the pipe the transaction + * - "usb" is the cvmx_usb_state_t for the port. + * - "reason" will always be CVMX_USB_CALLBACK_TRANSFER_COMPLETE. + * - "status" will be one of the cvmx_usb_complete_t enumerations. + * - "pipe_handle" is the handle to the pipe the transaction * was originally submitted on. - * - @b submit_handle is the handle returned by the original + * - "submit_handle" is the handle returned by the original * cvmx_usb_submit_* call. - * - @b bytes_transferred is the number of bytes successfully + * - "bytes_transferred" is the number of bytes successfully * transferred in the transaction. This will be zero on most * error conditions. - * - @b user_data is the void pointer originally passed along + * - "user_data" is the void pointer originally passed along * with the callback. Use this for any state information you * need. For example, the Linux "urb" is stored in here in the * Linux driver. * - * In general your callback handler should use @b status and @b - * bytes_transferred to tell the operating system the how the + * In general your callback handler should use "status" and + * "bytes_transferred" to tell the operating system the how the * transaction completed. Normally the pipe is not changed in * this callback. * - *

Canceling transactions

+ * == Canceling transactions == * * When a transaction is cancelled using cvmx_usb_cancel*(), the * actual length of time until the complete callback is called @@ -188,7 +183,7 @@ * these cases, the complete handler will receive * CVMX_USB_COMPLETE_CANCEL. * - *

Handling pipes

+ * == Handling pipes == * * USB "pipes" is a software construct created by this API to * enable the ordering of usb transactions to a device endpoint. @@ -210,7 +205,7 @@ * destroy a pipe for every transaction. A sequence of * transaction to the same endpoint must use the same pipe. * - *

Root Hub

+ * == Root Hub == * * Some operating systems view the usb root port as a normal usb * hub. These systems attempt to control the root hub with @@ -219,7 +214,7 @@ * function to decode standard usb control messages into * equivalent cvmx-usb API calls. * - *

Interrupts

+ * == Interrupts == * * If you plan on using usb interrupts, cvmx_usb_poll() must be * called on every usb interrupt. It will read the usb state, From 02073798a6b081bf74e6c10d6f7e7a693c067ecd Mon Sep 17 00:00:00 2001 From: Piotr Sarna Date: Mon, 29 Jul 2013 12:25:20 +0200 Subject: [PATCH 1056/3400] staging: zcache: fix "zcache=" kernel parameter Commit 835f2f5 ("staging: zcache: enable zcache to be built/loaded as a module") introduced an incorrect handling of "zcache=" parameter. Inside zcache_comp_init() function, zcache_comp_name variable is checked for being empty. If not empty, the above variable is tested for being compatible with Crypto API. Unfortunately, after that function ends unconditionally (by the "goto out" directive) and returns: - non-zero value if verification succeeded, wrongly indicating an error - zero value if verification failed, falsely informing that function zcache_comp_init() ended properly. A solution to this problem is as following: 1. Move the "goto out" directive inside the "if (!ret)" statement 2. In case that crypto_has_comp() returned 0, change the value of ret to non-zero before "goto out" to indicate an error. This patch replaces an earlier one from Michal Hocko (based on report from Cristian Rodriguez): http://permalink.gmane.org/gmane.linux.kernel.mm/102484 It also addressed the same issue but didn't fix the zcache_comp_init() for case when the compressor data passed to "zcache=" option was invalid or unsupported. Signed-off-by: Piotr Sarna [bzolnier: updated patch description] Acked-by: Bartlomiej Zolnierkiewicz Signed-off-by: Kyungmin Park Acked-by: Konrad Rzeszutek Wilk Acked-by: Michal Hocko Cc: stable # 3.10 Cc: Cristian Rodriguez Cc: Bob Liu Signed-off-by: Greg Kroah-Hartman --- drivers/staging/zcache/zcache-main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/staging/zcache/zcache-main.c b/drivers/staging/zcache/zcache-main.c index dcceed29d31a..81972fa47beb 100644 --- a/drivers/staging/zcache/zcache-main.c +++ b/drivers/staging/zcache/zcache-main.c @@ -1811,10 +1811,12 @@ static int zcache_comp_init(void) #else if (*zcache_comp_name != '\0') { ret = crypto_has_comp(zcache_comp_name, 0, 0); - if (!ret) + if (!ret) { pr_info("zcache: %s not supported\n", zcache_comp_name); - goto out; + ret = 1; + goto out; + } } if (!ret) strcpy(zcache_comp_name, "lzo"); From b9b9b35176316c3fc50ac50da9cf8796fbb7abd5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 29 Jul 2013 12:27:40 -0700 Subject: [PATCH 1057/3400] staging: gdm724x: depend on CONFIG_TTY The driver uses the tty layer, so explicitly say that, to prevent randomconfig build errors. Reported-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gdm724x/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/gdm724x/Kconfig b/drivers/staging/gdm724x/Kconfig index 8749e907d994..0a1f090bbf38 100644 --- a/drivers/staging/gdm724x/Kconfig +++ b/drivers/staging/gdm724x/Kconfig @@ -4,7 +4,7 @@ config LTE_GDM724X tristate "GCT GDM724x LTE support" - depends on NET && USB && m + depends on NET && USB && TTY && m help This driver supports GCT GDM724x LTE chip based USB modem devices. It exposes 4 network devices to be used per PDN and 2 tty devices to be From 89c66ee890af18500fa4598db300cc07c267f900 Mon Sep 17 00:00:00 2001 From: Christian Eggers Date: Mon, 29 Jul 2013 20:54:09 +0200 Subject: [PATCH 1058/3400] spi: spi-davinci: Fix direction in dma_map_single() Commit 048177ce3b3962852fd34a7e04938959271c7e70 (spi: spi-davinci: convert to DMA engine API) introduced a regression: dma_map_single() is called with direction DMA_FROM_DEVICE for rx and for tx. Signed-off-by: Christian Eggers Acked-by: Matt Porter Signed-off-by: Mark Brown Cc: stable@vger.kernel.org # v3.7.x+ --- drivers/spi/spi-davinci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c index 222d3e37fc28..707966bd5610 100644 --- a/drivers/spi/spi-davinci.c +++ b/drivers/spi/spi-davinci.c @@ -609,7 +609,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) else buf = (void *)t->tx_buf; t->tx_dma = dma_map_single(&spi->dev, buf, - t->len, DMA_FROM_DEVICE); + t->len, DMA_TO_DEVICE); if (!t->tx_dma) { ret = -EFAULT; goto err_tx_map; From c29782965b428d647742c5f22d9eca7a2d0f820f Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Mon, 29 Jul 2013 19:27:32 +0400 Subject: [PATCH 1059/3400] serial: max310x: Fix dev_pm_ops This patch fixes wrong dev_pm_ops which caused by commit: serial: max310x: Driver rework. CC drivers/tty/serial/max310x.o LD drivers/video/fb.o CC drivers/w1/slaves/w1_ds2433.o CC drivers/w1/slaves/w1_ds2760.o CC drivers/xen/balloon.o CC drivers/video/backlight/adp8870_bl.o drivers/tty/serial/max310x.c:1292:8: warning: initialization from incompatible pointer type [enabled by default] drivers/tty/serial/max310x.c:1292:8: warning: (near initialization for 'max310x_pm_ops.suspend') [enabled by default] drivers/tty/serial/max310x.c:1292:8: warning: initialization from incompatible pointer type [enabled by default] drivers/tty/serial/max310x.c:1292:8: warning: (near initialization for 'max310x_pm_ops.resume') [enabled by default] drivers/tty/serial/max310x.c:1292:8: warning: initialization from incompatible pointer type [enabled by default] drivers/tty/serial/max310x.c:1292:8: warning: (near initialization for 'max310x_pm_ops.freeze') [enabled by default] drivers/tty/serial/max310x.c:1292:8: warning: initialization from incompatible pointer type [enabled by default] drivers/tty/serial/max310x.c:1292:8: warning: (near initialization for 'max310x_pm_ops.thaw') [enabled by default] drivers/tty/serial/max310x.c:1292:8: warning: initialization from incompatible pointer type [enabled by default] drivers/tty/serial/max310x.c:1292:8: warning: (near initialization for 'max310x_pm_ops.poweroff') [enabled by default] drivers/tty/serial/max310x.c:1292:8: warning: initialization from incompatible pointer type [enabled by default] drivers/tty/serial/max310x.c:1292:8: warning: (near initialization for 'max310x_pm_ops.restore') [enabled by default] Reported-by: kbuild test robot Signed-off-by: Alexander Shiyan Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/max310x.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index 4ab5b272a593..b2e707aa603a 100644 --- a/drivers/tty/serial/max310x.c +++ b/drivers/tty/serial/max310x.c @@ -991,10 +991,9 @@ static const struct uart_ops max310x_ops = { .verify_port = max310x_verify_port, }; -static int __maybe_unused max310x_suspend(struct spi_device *spi, - pm_message_t state) +static int __maybe_unused max310x_suspend(struct device *dev) { - struct max310x_port *s = dev_get_drvdata(&spi->dev); + struct max310x_port *s = dev_get_drvdata(dev); int i; for (i = 0; i < s->uart.nr; i++) { @@ -1005,9 +1004,9 @@ static int __maybe_unused max310x_suspend(struct spi_device *spi, return 0; } -static int __maybe_unused max310x_resume(struct spi_device *spi) +static int __maybe_unused max310x_resume(struct device *dev) { - struct max310x_port *s = dev_get_drvdata(&spi->dev); + struct max310x_port *s = dev_get_drvdata(dev); int i; for (i = 0; i < s->uart.nr; i++) { From e06922aa836f098c4893218a1c656ce7d73a3b6a Mon Sep 17 00:00:00 2001 From: Alexandru Juncu Date: Sat, 27 Jul 2013 11:14:39 +0300 Subject: [PATCH 1060/3400] TTY: synclink: replace bitmasks add operation with OR operation. Found with coccinelle, manually fixed and verified. Signed-off-by: Alexandru Juncu Signed-off-by: Greg Kroah-Hartman --- drivers/tty/synclink.c | 130 ++++++++++++++++++++--------------------- 1 file changed, 65 insertions(+), 65 deletions(-) diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c index 8eaf1ab8addb..e1ce141bad5e 100644 --- a/drivers/tty/synclink.c +++ b/drivers/tty/synclink.c @@ -577,22 +577,22 @@ struct mgsl_struct { #define SICR_RXC_ACTIVE BIT15 #define SICR_RXC_INACTIVE BIT14 -#define SICR_RXC (BIT15+BIT14) +#define SICR_RXC (BIT15|BIT14) #define SICR_TXC_ACTIVE BIT13 #define SICR_TXC_INACTIVE BIT12 -#define SICR_TXC (BIT13+BIT12) +#define SICR_TXC (BIT13|BIT12) #define SICR_RI_ACTIVE BIT11 #define SICR_RI_INACTIVE BIT10 -#define SICR_RI (BIT11+BIT10) +#define SICR_RI (BIT11|BIT10) #define SICR_DSR_ACTIVE BIT9 #define SICR_DSR_INACTIVE BIT8 -#define SICR_DSR (BIT9+BIT8) +#define SICR_DSR (BIT9|BIT8) #define SICR_DCD_ACTIVE BIT7 #define SICR_DCD_INACTIVE BIT6 -#define SICR_DCD (BIT7+BIT6) +#define SICR_DCD (BIT7|BIT6) #define SICR_CTS_ACTIVE BIT5 #define SICR_CTS_INACTIVE BIT4 -#define SICR_CTS (BIT5+BIT4) +#define SICR_CTS (BIT5|BIT4) #define SICR_RCC_UNDERFLOW BIT3 #define SICR_DPLL_NO_SYNC BIT2 #define SICR_BRG1_ZERO BIT1 @@ -1161,7 +1161,7 @@ static void mgsl_isr_receive_status( struct mgsl_struct *info ) { u16 status = usc_InReg( info, RCSR ); - if ( debug_level >= DEBUG_LEVEL_ISR ) + if ( debug_level >= DEBUG_LEVEL_ISR ) printk("%s(%d):mgsl_isr_receive_status status=%04X\n", __FILE__,__LINE__,status); @@ -1181,7 +1181,7 @@ static void mgsl_isr_receive_status( struct mgsl_struct *info ) (usc_InReg(info, RICR) & ~RXSTATUS_ABORT_RECEIVED)); } - if (status & (RXSTATUS_EXITED_HUNT + RXSTATUS_IDLE_RECEIVED)) { + if (status & (RXSTATUS_EXITED_HUNT | RXSTATUS_IDLE_RECEIVED)) { if (status & RXSTATUS_EXITED_HUNT) info->icount.exithunt++; if (status & RXSTATUS_IDLE_RECEIVED) @@ -1463,21 +1463,21 @@ static void mgsl_isr_receive_data( struct mgsl_struct *info ) /* get the status of the received byte */ status = usc_InReg(info, RCSR); - if ( status & (RXSTATUS_FRAMING_ERROR + RXSTATUS_PARITY_ERROR + - RXSTATUS_OVERRUN + RXSTATUS_BREAK_RECEIVED) ) + if ( status & (RXSTATUS_FRAMING_ERROR | RXSTATUS_PARITY_ERROR | + RXSTATUS_OVERRUN | RXSTATUS_BREAK_RECEIVED) ) usc_UnlatchRxstatusBits(info,RXSTATUS_ALL); icount->rx++; flag = 0; - if ( status & (RXSTATUS_FRAMING_ERROR + RXSTATUS_PARITY_ERROR + - RXSTATUS_OVERRUN + RXSTATUS_BREAK_RECEIVED) ) { - printk("rxerr=%04X\n",status); + if ( status & (RXSTATUS_FRAMING_ERROR | RXSTATUS_PARITY_ERROR | + RXSTATUS_OVERRUN | RXSTATUS_BREAK_RECEIVED) ) { + printk("rxerr=%04X\n",status); /* update error statistics */ if ( status & RXSTATUS_BREAK_RECEIVED ) { - status &= ~(RXSTATUS_FRAMING_ERROR + RXSTATUS_PARITY_ERROR); + status &= ~(RXSTATUS_FRAMING_ERROR | RXSTATUS_PARITY_ERROR); icount->brk++; - } else if (status & RXSTATUS_PARITY_ERROR) + } else if (status & RXSTATUS_PARITY_ERROR) icount->parity++; else if (status & RXSTATUS_FRAMING_ERROR) icount->frame++; @@ -1488,7 +1488,7 @@ static void mgsl_isr_receive_data( struct mgsl_struct *info ) icount->overrun++; } - /* discard char if tty control flags say so */ + /* discard char if tty control flags say so */ if (status & info->ignore_status_mask) continue; @@ -1545,8 +1545,8 @@ static void mgsl_isr_misc( struct mgsl_struct *info ) usc_EnableReceiver(info,DISABLE_UNCONDITIONAL); usc_DmaCmd(info, DmaCmd_ResetRxChannel); usc_UnlatchRxstatusBits(info, RXSTATUS_ALL); - usc_ClearIrqPendingBits(info, RECEIVE_DATA + RECEIVE_STATUS); - usc_DisableInterrupts(info, RECEIVE_DATA + RECEIVE_STATUS); + usc_ClearIrqPendingBits(info, RECEIVE_DATA | RECEIVE_STATUS); + usc_DisableInterrupts(info, RECEIVE_DATA | RECEIVE_STATUS); /* schedule BH handler to restart receiver */ info->pending_bh |= BH_RECEIVE; @@ -1595,7 +1595,7 @@ static void mgsl_isr_receive_dma( struct mgsl_struct *info ) u16 status; /* clear interrupt pending and IUS bit for Rx DMA IRQ */ - usc_OutDmaReg( info, CDIR, BIT9+BIT1 ); + usc_OutDmaReg( info, CDIR, BIT9 | BIT1 ); /* Read the receive DMA status to identify interrupt type. */ /* This also clears the status bits. */ @@ -1639,7 +1639,7 @@ static void mgsl_isr_transmit_dma( struct mgsl_struct *info ) u16 status; /* clear interrupt pending and IUS bit for Tx DMA IRQ */ - usc_OutDmaReg(info, CDIR, BIT8+BIT0 ); + usc_OutDmaReg(info, CDIR, BIT8 | BIT0 ); /* Read the transmit DMA status to identify interrupt type. */ /* This also clears the status bits. */ @@ -1832,8 +1832,8 @@ static void shutdown(struct mgsl_struct * info) usc_DisableMasterIrqBit(info); usc_stop_receiver(info); usc_stop_transmitter(info); - usc_DisableInterrupts(info,RECEIVE_DATA + RECEIVE_STATUS + - TRANSMIT_DATA + TRANSMIT_STATUS + IO_PIN + MISC ); + usc_DisableInterrupts(info,RECEIVE_DATA | RECEIVE_STATUS | + TRANSMIT_DATA | TRANSMIT_STATUS | IO_PIN | MISC ); usc_DisableDmaInterrupts(info,DICR_MASTER + DICR_TRANSMIT + DICR_RECEIVE); /* Disable DMAEN (Port 7, Bit 14) */ @@ -1886,7 +1886,7 @@ static void mgsl_program_hw(struct mgsl_struct *info) info->ri_chkcount = 0; info->dsr_chkcount = 0; - usc_EnableStatusIrqs(info,SICR_CTS+SICR_DSR+SICR_DCD+SICR_RI); + usc_EnableStatusIrqs(info,SICR_CTS+SICR_DSR+SICR_DCD+SICR_RI); usc_EnableInterrupts(info, IO_PIN); usc_get_serial_signals(info); @@ -2773,7 +2773,7 @@ static int mgsl_wait_event(struct mgsl_struct * info, int __user * mask_ptr) if (!waitqueue_active(&info->event_wait_q)) { /* disable enable exit hunt mode/idle rcvd IRQs */ usc_OutReg(info, RICR, usc_InReg(info,RICR) & - ~(RXSTATUS_EXITED_HUNT + RXSTATUS_IDLE_RECEIVED)); + ~(RXSTATUS_EXITED_HUNT | RXSTATUS_IDLE_RECEIVED)); } spin_unlock_irqrestore(&info->irq_spinlock,flags); } @@ -3092,7 +3092,7 @@ static void mgsl_close(struct tty_struct *tty, struct file * filp) printk("%s(%d):mgsl_close(%s) entry, count=%d\n", __FILE__,__LINE__, info->device_name, info->port.count); - if (tty_port_close_start(&info->port, tty, filp) == 0) + if (tty_port_close_start(&info->port, tty, filp) == 0) goto cleanup; mutex_lock(&info->port.mutex); @@ -4297,7 +4297,7 @@ static struct mgsl_struct* mgsl_allocate_device(void) spin_lock_init(&info->irq_spinlock); spin_lock_init(&info->netlock); memcpy(&info->params,&default_params,sizeof(MGSL_PARAMS)); - info->idle_mode = HDLC_TXIDLE_FLAGS; + info->idle_mode = HDLC_TXIDLE_FLAGS; info->num_tx_dma_buffers = 1; info->num_tx_holding_buffers = 0; } @@ -4722,7 +4722,7 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info ) else if ( info->params.flags & HDLC_FLAG_UNDERRUN_FLAG ) RegValue |= BIT15; else if ( info->params.flags & HDLC_FLAG_UNDERRUN_CRC ) - RegValue |= BIT15 + BIT14; + RegValue |= BIT15 | BIT14; } if ( info->params.preamble != HDLC_PREAMBLE_PATTERN_NONE ) @@ -4763,11 +4763,11 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info ) switch ( info->params.encoding ) { case HDLC_ENCODING_NRZB: RegValue |= BIT13; break; case HDLC_ENCODING_NRZI_MARK: RegValue |= BIT14; break; - case HDLC_ENCODING_NRZI_SPACE: RegValue |= BIT14 + BIT13; break; + case HDLC_ENCODING_NRZI_SPACE: RegValue |= BIT14 | BIT13; break; case HDLC_ENCODING_BIPHASE_MARK: RegValue |= BIT15; break; - case HDLC_ENCODING_BIPHASE_SPACE: RegValue |= BIT15 + BIT13; break; - case HDLC_ENCODING_BIPHASE_LEVEL: RegValue |= BIT15 + BIT14; break; - case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: RegValue |= BIT15 + BIT14 + BIT13; break; + case HDLC_ENCODING_BIPHASE_SPACE: RegValue |= BIT15 | BIT13; break; + case HDLC_ENCODING_BIPHASE_LEVEL: RegValue |= BIT15 | BIT14; break; + case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: RegValue |= BIT15 | BIT14 | BIT13; break; } if ( (info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_16_CCITT ) @@ -4838,15 +4838,15 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info ) switch ( info->params.encoding ) { case HDLC_ENCODING_NRZB: RegValue |= BIT13; break; case HDLC_ENCODING_NRZI_MARK: RegValue |= BIT14; break; - case HDLC_ENCODING_NRZI_SPACE: RegValue |= BIT14 + BIT13; break; + case HDLC_ENCODING_NRZI_SPACE: RegValue |= BIT14 | BIT13; break; case HDLC_ENCODING_BIPHASE_MARK: RegValue |= BIT15; break; - case HDLC_ENCODING_BIPHASE_SPACE: RegValue |= BIT15 + BIT13; break; - case HDLC_ENCODING_BIPHASE_LEVEL: RegValue |= BIT15 + BIT14; break; - case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: RegValue |= BIT15 + BIT14 + BIT13; break; + case HDLC_ENCODING_BIPHASE_SPACE: RegValue |= BIT15 | BIT13; break; + case HDLC_ENCODING_BIPHASE_LEVEL: RegValue |= BIT15 | BIT14; break; + case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: RegValue |= BIT15 | BIT14 | BIT13; break; } if ( (info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_16_CCITT ) - RegValue |= BIT9 + BIT8; + RegValue |= BIT9 | BIT8; else if ( (info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_32_CCITT ) RegValue |= ( BIT12 | BIT10 | BIT9 | BIT8); @@ -4957,7 +4957,7 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info ) RegValue = 0x0000; - if ( info->params.flags & (HDLC_FLAG_RXC_DPLL + HDLC_FLAG_TXC_DPLL) ) { + if ( info->params.flags & (HDLC_FLAG_RXC_DPLL | HDLC_FLAG_TXC_DPLL) ) { u32 XtalSpeed; u32 DpllDivisor; u16 Tc; @@ -5019,7 +5019,7 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info ) case HDLC_ENCODING_BIPHASE_MARK: case HDLC_ENCODING_BIPHASE_SPACE: RegValue |= BIT9; break; case HDLC_ENCODING_BIPHASE_LEVEL: - case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: RegValue |= BIT9 + BIT8; break; + case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: RegValue |= BIT9 | BIT8; break; } } @@ -5056,8 +5056,8 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info ) /* enable Master Interrupt Enable bit (MIE) */ usc_EnableMasterIrqBit( info ); - usc_ClearIrqPendingBits( info, RECEIVE_STATUS + RECEIVE_DATA + - TRANSMIT_STATUS + TRANSMIT_DATA + MISC); + usc_ClearIrqPendingBits( info, RECEIVE_STATUS | RECEIVE_DATA | + TRANSMIT_STATUS | TRANSMIT_DATA | MISC); /* arm RCC underflow interrupt */ usc_OutReg(info, SICR, (u16)(usc_InReg(info,SICR) | BIT3)); @@ -5175,14 +5175,14 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info ) switch ( info->params.preamble_length ) { case HDLC_PREAMBLE_LENGTH_16BITS: RegValue |= BIT10; break; case HDLC_PREAMBLE_LENGTH_32BITS: RegValue |= BIT11; break; - case HDLC_PREAMBLE_LENGTH_64BITS: RegValue |= BIT11 + BIT10; break; + case HDLC_PREAMBLE_LENGTH_64BITS: RegValue |= BIT11 | BIT10; break; } switch ( info->params.preamble ) { - case HDLC_PREAMBLE_PATTERN_FLAGS: RegValue |= BIT8 + BIT12; break; + case HDLC_PREAMBLE_PATTERN_FLAGS: RegValue |= BIT8 | BIT12; break; case HDLC_PREAMBLE_PATTERN_ONES: RegValue |= BIT8; break; case HDLC_PREAMBLE_PATTERN_10: RegValue |= BIT9; break; - case HDLC_PREAMBLE_PATTERN_01: RegValue |= BIT9 + BIT8; break; + case HDLC_PREAMBLE_PATTERN_01: RegValue |= BIT9 | BIT8; break; } usc_OutReg( info, CCR, RegValue ); @@ -5221,7 +5221,7 @@ static void usc_enable_loopback(struct mgsl_struct *info, int enable) { if (enable) { /* blank external TXD output */ - usc_OutReg(info,IOCR,usc_InReg(info,IOCR) | (BIT7+BIT6)); + usc_OutReg(info,IOCR,usc_InReg(info,IOCR) | (BIT7 | BIT6)); /* Clock mode Control Register (CMCR) * @@ -5260,7 +5260,7 @@ static void usc_enable_loopback(struct mgsl_struct *info, int enable) outw( 0x0300, info->io_base + CCAR ); } else { /* enable external TXD output */ - usc_OutReg(info,IOCR,usc_InReg(info,IOCR) & ~(BIT7+BIT6)); + usc_OutReg(info,IOCR,usc_InReg(info,IOCR) & ~(BIT7 | BIT6)); /* clear Internal Data loopback mode */ info->loopback_bits = 0; @@ -5447,13 +5447,13 @@ static void usc_process_rxoverrun_sync( struct mgsl_struct *info ) usc_OutDmaReg( info, NRARU, (u16)(phys_addr >> 16) ); usc_UnlatchRxstatusBits( info, RXSTATUS_ALL ); - usc_ClearIrqPendingBits( info, RECEIVE_DATA + RECEIVE_STATUS ); + usc_ClearIrqPendingBits( info, RECEIVE_DATA | RECEIVE_STATUS ); usc_EnableInterrupts( info, RECEIVE_STATUS ); /* 1. Arm End of Buffer (EOB) Receive DMA Interrupt (BIT2 of RDIAR) */ /* 2. Enable Receive DMA Interrupts (BIT1 of DICR) */ - usc_OutDmaReg( info, RDIAR, BIT3 + BIT2 ); + usc_OutDmaReg( info, RDIAR, BIT3 | BIT2 ); usc_OutDmaReg( info, DICR, (u16)(usc_InDmaReg(info,DICR) | BIT1) ); usc_DmaCmd( info, DmaCmd_InitRxChannel ); if ( info->params.flags & HDLC_FLAG_AUTO_DCD ) @@ -5488,8 +5488,8 @@ static void usc_stop_receiver( struct mgsl_struct *info ) usc_DmaCmd( info, DmaCmd_ResetRxChannel ); usc_UnlatchRxstatusBits( info, RXSTATUS_ALL ); - usc_ClearIrqPendingBits( info, RECEIVE_DATA + RECEIVE_STATUS ); - usc_DisableInterrupts( info, RECEIVE_DATA + RECEIVE_STATUS ); + usc_ClearIrqPendingBits( info, RECEIVE_DATA | RECEIVE_STATUS ); + usc_DisableInterrupts( info, RECEIVE_DATA | RECEIVE_STATUS ); usc_EnableReceiver(info,DISABLE_UNCONDITIONAL); @@ -5536,13 +5536,13 @@ static void usc_start_receiver( struct mgsl_struct *info ) usc_OutDmaReg( info, NRARU, (u16)(phys_addr >> 16) ); usc_UnlatchRxstatusBits( info, RXSTATUS_ALL ); - usc_ClearIrqPendingBits( info, RECEIVE_DATA + RECEIVE_STATUS ); + usc_ClearIrqPendingBits( info, RECEIVE_DATA | RECEIVE_STATUS ); usc_EnableInterrupts( info, RECEIVE_STATUS ); /* 1. Arm End of Buffer (EOB) Receive DMA Interrupt (BIT2 of RDIAR) */ /* 2. Enable Receive DMA Interrupts (BIT1 of DICR) */ - usc_OutDmaReg( info, RDIAR, BIT3 + BIT2 ); + usc_OutDmaReg( info, RDIAR, BIT3 | BIT2 ); usc_OutDmaReg( info, DICR, (u16)(usc_InDmaReg(info,DICR) | BIT1) ); usc_DmaCmd( info, DmaCmd_InitRxChannel ); if ( info->params.flags & HDLC_FLAG_AUTO_DCD ) @@ -5551,7 +5551,7 @@ static void usc_start_receiver( struct mgsl_struct *info ) usc_EnableReceiver(info,ENABLE_UNCONDITIONAL); } else { usc_UnlatchRxstatusBits(info, RXSTATUS_ALL); - usc_ClearIrqPendingBits(info, RECEIVE_DATA + RECEIVE_STATUS); + usc_ClearIrqPendingBits(info, RECEIVE_DATA | RECEIVE_STATUS); usc_EnableInterrupts(info, RECEIVE_DATA); usc_RTCmd( info, RTCmd_PurgeRxFifo ); @@ -5925,7 +5925,7 @@ static void usc_set_async_mode( struct mgsl_struct *info ) RegValue = 0; if ( info->params.data_bits != 8 ) - RegValue |= BIT4+BIT3+BIT2; + RegValue |= BIT4 | BIT3 | BIT2; if ( info->params.parity != ASYNC_PARITY_NONE ) { RegValue |= BIT5; @@ -5982,7 +5982,7 @@ static void usc_set_async_mode( struct mgsl_struct *info ) RegValue = 0; if ( info->params.data_bits != 8 ) - RegValue |= BIT4+BIT3+BIT2; + RegValue |= BIT4 | BIT3 | BIT2; if ( info->params.parity != ASYNC_PARITY_NONE ) { RegValue |= BIT5; @@ -6129,7 +6129,7 @@ static void usc_loopback_frame( struct mgsl_struct *info ) /* WAIT FOR RECEIVE COMPLETE */ for (i=0 ; i<1000 ; i++) - if (usc_InReg( info, RCSR ) & (BIT8 + BIT4 + BIT3 + BIT1)) + if (usc_InReg( info, RCSR ) & (BIT8 | BIT4 | BIT3 | BIT1)) break; /* clear Internal Data loopback mode */ @@ -6579,8 +6579,8 @@ static bool mgsl_get_rx_frame(struct mgsl_struct *info) status = info->rx_buffer_list[EndIndex].status; - if ( status & (RXSTATUS_SHORT_FRAME + RXSTATUS_OVERRUN + - RXSTATUS_CRC_ERROR + RXSTATUS_ABORT) ) { + if ( status & (RXSTATUS_SHORT_FRAME | RXSTATUS_OVERRUN | + RXSTATUS_CRC_ERROR | RXSTATUS_ABORT) ) { if ( status & RXSTATUS_SHORT_FRAME ) info->icount.rxshort++; else if ( status & RXSTATUS_ABORT ) @@ -6762,8 +6762,8 @@ static bool mgsl_get_raw_rx_frame(struct mgsl_struct *info) status = info->rx_buffer_list[CurrentIndex].status; - if ( status & (RXSTATUS_SHORT_FRAME + RXSTATUS_OVERRUN + - RXSTATUS_CRC_ERROR + RXSTATUS_ABORT) ) { + if ( status & (RXSTATUS_SHORT_FRAME | RXSTATUS_OVERRUN | + RXSTATUS_CRC_ERROR | RXSTATUS_ABORT) ) { if ( status & RXSTATUS_SHORT_FRAME ) info->icount.rxshort++; else if ( status & RXSTATUS_ABORT ) @@ -6899,7 +6899,7 @@ static void mgsl_load_tx_dma_buffer(struct mgsl_struct *info, /* set CMR:13 to start transmit when * next GoAhead (abort) is received */ - info->cmr_value |= BIT13; + info->cmr_value |= BIT13; } /* begin loading the frame in the next available tx dma @@ -7278,7 +7278,7 @@ static bool mgsl_dma_test( struct mgsl_struct *info ) spin_unlock_irqrestore(&info->irq_spinlock,flags); - + /******************************/ /* WAIT FOR TRANSMIT COMPLETE */ /******************************/ @@ -7292,7 +7292,7 @@ static bool mgsl_dma_test( struct mgsl_struct *info ) status = usc_InReg( info, TCSR ); spin_unlock_irqrestore(&info->irq_spinlock,flags); - while ( !(status & (BIT6+BIT5+BIT4+BIT2+BIT1)) ) { + while ( !(status & (BIT6 | BIT5 | BIT4 | BIT2 | BIT1)) ) { if (time_after(jiffies, EndTime)) { rc = false; break; @@ -7307,7 +7307,7 @@ static bool mgsl_dma_test( struct mgsl_struct *info ) if ( rc ){ /* CHECK FOR TRANSMIT ERRORS */ - if ( status & (BIT5 + BIT1) ) + if ( status & (BIT5 | BIT1) ) rc = false; } @@ -7333,7 +7333,7 @@ static bool mgsl_dma_test( struct mgsl_struct *info ) /* CHECK FOR RECEIVE ERRORS */ status = info->rx_buffer_list[0].status; - if ( status & (BIT8 + BIT3 + BIT1) ) { + if ( status & (BIT8 | BIT3 | BIT1) ) { /* receive error has occurred */ rc = false; } else { @@ -7605,7 +7605,7 @@ static void usc_loopmode_send_done( struct mgsl_struct * info ) { info->loopmode_send_done_requested = false; /* clear CMR:13 to 0 to start echoing RxData to TxData */ - info->cmr_value &= ~BIT13; + info->cmr_value &= ~BIT13; usc_OutReg(info, CMR, info->cmr_value); } From 0a09ae98eade956bbc681cb905584effe4a1ed95 Mon Sep 17 00:00:00 2001 From: Darren Hart Date: Mon, 29 Jul 2013 09:58:14 -0700 Subject: [PATCH 1061/3400] serial: pch_uart: Remove __initdata annotation from dmi_table The dmi_table is best accessed from the probe function, which is not an __init function. Drop the __initdata annotation from the dmi_table to avoid the section mismatch compiler warnings: WARNING: drivers/tty/serial/pch_uart.o(.text+0x4871): Section mismatch in reference from the function pch_uart_init_port() to the variable .init.data:pch_uart_dmi_table Signed-off-by: Darren Hart Reported-by: kbuild test robot Cc: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/pch_uart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 271cc733573c..bc0aa0881d0f 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -373,7 +373,7 @@ static const struct file_operations port_regs_ops = { }; #endif /* CONFIG_DEBUG_FS */ -static struct dmi_system_id __initdata pch_uart_dmi_table[] = { +static struct dmi_system_id pch_uart_dmi_table[] = { { .ident = "CM-iTC", { From 64e22ebe49780e2454c8788c5af9f1e0e500e1a2 Mon Sep 17 00:00:00 2001 From: Elen Song Date: Mon, 22 Jul 2013 16:30:24 +0800 Subject: [PATCH 1062/3400] serial: at91: correct definition from DMA to PDC The DMA is available since at91sam9x5 socs, before that, we use PDC. Signed-off-by: Elen Song Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/atmel_serial.c | 71 ++++++++++++++++--------------- 1 file changed, 36 insertions(+), 35 deletions(-) diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 5c17f8dac91b..1d59563016fb 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -139,11 +139,11 @@ struct atmel_uart_port { u32 backup_imr; /* IMR saved during suspend */ int break_active; /* break being received */ - short use_dma_rx; /* enable PDC receiver */ + bool use_pdc_rx; /* enable PDC receiver */ short pdc_rx_idx; /* current PDC RX buffer */ struct atmel_dma_buffer pdc_rx[2]; /* PDC receier */ - short use_dma_tx; /* enable PDC transmitter */ + bool use_pdc_tx; /* enable PDC transmitter */ struct atmel_dma_buffer pdc_tx; /* PDC transmitter */ struct tasklet_struct tasklet; @@ -180,26 +180,26 @@ to_atmel_uart_port(struct uart_port *uart) } #ifdef CONFIG_SERIAL_ATMEL_PDC -static bool atmel_use_dma_rx(struct uart_port *port) +static bool atmel_use_pdc_rx(struct uart_port *port) { struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); - return atmel_port->use_dma_rx; + return atmel_port->use_pdc_rx; } -static bool atmel_use_dma_tx(struct uart_port *port) +static bool atmel_use_pdc_tx(struct uart_port *port) { struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); - return atmel_port->use_dma_tx; + return atmel_port->use_pdc_tx; } #else -static bool atmel_use_dma_rx(struct uart_port *port) +static bool atmel_use_pdc_rx(struct uart_port *port) { return false; } -static bool atmel_use_dma_tx(struct uart_port *port) +static bool atmel_use_pdc_tx(struct uart_port *port) { return false; } @@ -232,7 +232,7 @@ void atmel_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf) mode |= ATMEL_US_USMODE_RS485; } else { dev_dbg(port->dev, "Setting UART to RS232\n"); - if (atmel_use_dma_tx(port)) + if (atmel_use_pdc_tx(port)) atmel_port->tx_done_mask = ATMEL_US_ENDTX | ATMEL_US_TXBUFE; else @@ -344,7 +344,7 @@ static void atmel_stop_tx(struct uart_port *port) { struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); - if (atmel_use_dma_tx(port)) { + if (atmel_use_pdc_tx(port)) { /* disable PDC transmit */ UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS); } @@ -363,7 +363,7 @@ static void atmel_start_tx(struct uart_port *port) { struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); - if (atmel_use_dma_tx(port)) { + if (atmel_use_pdc_tx(port)) { if (UART_GET_PTSR(port) & ATMEL_PDC_TXTEN) /* The transmitter is already running. Yes, we really need this.*/ @@ -389,7 +389,7 @@ static void atmel_start_rx(struct uart_port *port) UART_PUT_CR(port, ATMEL_US_RXEN); - if (atmel_use_dma_rx(port)) { + if (atmel_use_pdc_rx(port)) { /* enable PDC controller */ UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT | port->read_status_mask); @@ -406,7 +406,7 @@ static void atmel_stop_rx(struct uart_port *port) { UART_PUT_CR(port, ATMEL_US_RXDIS); - if (atmel_use_dma_rx(port)) { + if (atmel_use_pdc_rx(port)) { /* disable PDC receive */ UART_PUT_PTCR(port, ATMEL_PDC_RXTDIS); UART_PUT_IDR(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT | @@ -571,7 +571,7 @@ atmel_handle_receive(struct uart_port *port, unsigned int pending) { struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); - if (atmel_use_dma_rx(port)) { + if (atmel_use_pdc_rx(port)) { /* * PDC receive. Just schedule the tasklet and let it * figure out the details. @@ -660,7 +660,7 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id) /* * Called from tasklet with ENDTX and TXBUFE interrupts disabled. */ -static void atmel_tx_dma(struct uart_port *port) +static void atmel_tx_pdc(struct uart_port *port) { struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); struct circ_buf *xmit = &port->state->xmit; @@ -777,7 +777,7 @@ static void atmel_rx_from_ring(struct uart_port *port) spin_lock(&port->lock); } -static void atmel_rx_from_dma(struct uart_port *port) +static void atmel_rx_from_pdc(struct uart_port *port) { struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); struct tty_port *tport = &port->state->port; @@ -867,8 +867,8 @@ static void atmel_tasklet_func(unsigned long data) /* The interrupt handler does not take the lock */ spin_lock(&port->lock); - if (atmel_use_dma_tx(port)) - atmel_tx_dma(port); + if (atmel_use_pdc_tx(port)) + atmel_tx_pdc(port); else atmel_tx_chars(port); @@ -892,8 +892,8 @@ static void atmel_tasklet_func(unsigned long data) atmel_port->irq_status_prev = status; } - if (atmel_use_dma_rx(port)) - atmel_rx_from_dma(port); + if (atmel_use_pdc_rx(port)) + atmel_rx_from_pdc(port); else atmel_rx_from_ring(port); @@ -929,7 +929,7 @@ static int atmel_startup(struct uart_port *port) /* * Initialize DMA (if necessary) */ - if (atmel_use_dma_rx(port)) { + if (atmel_use_pdc_rx(port)) { int i; for (i = 0; i < 2; i++) { @@ -963,7 +963,7 @@ static int atmel_startup(struct uart_port *port) UART_PUT_RNPR(port, atmel_port->pdc_rx[1].dma_addr); UART_PUT_RNCR(port, PDC_BUFFER_SIZE); } - if (atmel_use_dma_tx(port)) { + if (atmel_use_pdc_tx(port)) { struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx; struct circ_buf *xmit = &port->state->xmit; @@ -999,7 +999,7 @@ static int atmel_startup(struct uart_port *port) /* enable xmit & rcvr */ UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN); - if (atmel_use_dma_rx(port)) { + if (atmel_use_pdc_rx(port)) { /* set UART timeout */ UART_PUT_RTOR(port, PDC_RX_TIMEOUT); UART_PUT_CR(port, ATMEL_US_STTTO); @@ -1030,7 +1030,7 @@ static void atmel_shutdown(struct uart_port *port) /* * Shut-down the DMA. */ - if (atmel_use_dma_rx(port)) { + if (atmel_use_pdc_rx(port)) { int i; for (i = 0; i < 2; i++) { @@ -1043,7 +1043,7 @@ static void atmel_shutdown(struct uart_port *port) kfree(pdc->buf); } } - if (atmel_use_dma_tx(port)) { + if (atmel_use_pdc_tx(port)) { struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx; dma_unmap_single(port->dev, @@ -1079,7 +1079,7 @@ static void atmel_flush_buffer(struct uart_port *port) { struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); - if (atmel_use_dma_tx(port)) { + if (atmel_use_pdc_tx(port)) { UART_PUT_TCR(port, 0); atmel_port->pdc_tx.ofs = 0; } @@ -1192,7 +1192,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, if (termios->c_iflag & (BRKINT | PARMRK)) port->read_status_mask |= ATMEL_US_RXBRK; - if (atmel_use_dma_rx(port)) + if (atmel_use_pdc_rx(port)) /* need to enable error interrupts */ UART_PUT_IER(port, port->read_status_mask); @@ -1429,13 +1429,14 @@ static void atmel_of_init_port(struct atmel_uart_port *atmel_port, /* DMA/PDC usage specification */ if (of_get_property(np, "atmel,use-dma-rx", NULL)) - atmel_port->use_dma_rx = 1; + atmel_port->use_pdc_rx = true; else - atmel_port->use_dma_rx = 0; + atmel_port->use_pdc_rx = false; + if (of_get_property(np, "atmel,use-dma-tx", NULL)) - atmel_port->use_dma_tx = 1; + atmel_port->use_pdc_tx = true; else - atmel_port->use_dma_tx = 0; + atmel_port->use_pdc_tx = false; /* rs485 properties */ if (of_property_read_u32_array(np, "rs485-rts-delay", @@ -1467,8 +1468,8 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port, if (pdev->dev.of_node) { atmel_of_init_port(atmel_port, pdev->dev.of_node); } else { - atmel_port->use_dma_rx = pdata->use_dma_rx; - atmel_port->use_dma_tx = pdata->use_dma_tx; + atmel_port->use_pdc_rx = pdata->use_dma_rx; + atmel_port->use_pdc_tx = pdata->use_dma_tx; atmel_port->rs485 = pdata->rs485; } @@ -1515,7 +1516,7 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port, /* Use TXEMPTY for interrupt when rs485 else TXRDY or ENDTX|TXBUFE */ if (atmel_port->rs485.flags & SER_RS485_ENABLED) atmel_port->tx_done_mask = ATMEL_US_TXEMPTY; - else if (atmel_use_dma_tx(port)) { + else if (atmel_use_pdc_tx(port)) { port->fifosize = PDC_BUFFER_SIZE; atmel_port->tx_done_mask = ATMEL_US_ENDTX | ATMEL_US_TXBUFE; } else { @@ -1807,7 +1808,7 @@ static int atmel_serial_probe(struct platform_device *pdev) if (ret) goto err; - if (!atmel_use_dma_rx(&port->uart)) { + if (!atmel_use_pdc_rx(&port->uart)) { ret = -ENOMEM; data = kmalloc(sizeof(struct atmel_uart_char) * ATMEL_SERIAL_RINGSIZE, GFP_KERNEL); From a930e52875e96709cc01e4babcb8351687c5a58e Mon Sep 17 00:00:00 2001 From: Elen Song Date: Mon, 22 Jul 2013 16:30:25 +0800 Subject: [PATCH 1063/3400] serial: at91: use function pointer to choose pdc or pio use function pointer can avoid define atmel_use_pdc_tx/rx everywhere. (*prepare_rx/tx)() is in setup transfer stage. (*schedule_rx/tx)() is in tasklet schedule stage. (*release_rx/tx)() is used when shutdown the transfer. Signed-off-by: Elen Song Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/atmel_serial.c | 205 +++++++++++++++++++----------- 1 file changed, 131 insertions(+), 74 deletions(-) diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 1d59563016fb..b56123d3affe 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -154,6 +154,12 @@ struct atmel_uart_port { struct serial_rs485 rs485; /* rs485 settings */ unsigned int tx_done_mask; + int (*prepare_rx)(struct uart_port *port); + int (*prepare_tx)(struct uart_port *port); + void (*schedule_rx)(struct uart_port *port); + void (*schedule_tx)(struct uart_port *port); + void (*release_rx)(struct uart_port *port); + void (*release_tx)(struct uart_port *port); }; static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART]; @@ -657,6 +663,17 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id) return pass_counter ? IRQ_HANDLED : IRQ_NONE; } +static void atmel_release_tx_pdc(struct uart_port *port) +{ + struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); + struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx; + + dma_unmap_single(port->dev, + pdc->dma_addr, + pdc->dma_size, + DMA_TO_DEVICE); +} + /* * Called from tasklet with ENDTX and TXBUFE interrupts disabled. */ @@ -709,6 +726,23 @@ static void atmel_tx_pdc(struct uart_port *port) uart_write_wakeup(port); } +static int atmel_prepare_tx_pdc(struct uart_port *port) +{ + struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); + struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx; + struct circ_buf *xmit = &port->state->xmit; + + pdc->buf = xmit->buf; + pdc->dma_addr = dma_map_single(port->dev, + pdc->buf, + UART_XMIT_SIZE, + DMA_TO_DEVICE); + pdc->dma_size = UART_XMIT_SIZE; + pdc->ofs = 0; + + return 0; +} + static void atmel_rx_from_ring(struct uart_port *port) { struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); @@ -777,6 +811,22 @@ static void atmel_rx_from_ring(struct uart_port *port) spin_lock(&port->lock); } +static void atmel_release_rx_pdc(struct uart_port *port) +{ + struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); + int i; + + for (i = 0; i < 2; i++) { + struct atmel_dma_buffer *pdc = &atmel_port->pdc_rx[i]; + + dma_unmap_single(port->dev, + pdc->dma_addr, + pdc->dma_size, + DMA_FROM_DEVICE); + kfree(pdc->buf); + } +} + static void atmel_rx_from_pdc(struct uart_port *port) { struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); @@ -854,6 +904,45 @@ static void atmel_rx_from_pdc(struct uart_port *port) UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT); } +static int atmel_prepare_rx_pdc(struct uart_port *port) +{ + struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); + int i; + + for (i = 0; i < 2; i++) { + struct atmel_dma_buffer *pdc = &atmel_port->pdc_rx[i]; + + pdc->buf = kmalloc(PDC_BUFFER_SIZE, GFP_KERNEL); + if (pdc->buf == NULL) { + if (i != 0) { + dma_unmap_single(port->dev, + atmel_port->pdc_rx[0].dma_addr, + PDC_BUFFER_SIZE, + DMA_FROM_DEVICE); + kfree(atmel_port->pdc_rx[0].buf); + } + atmel_port->use_pdc_rx = 0; + return -ENOMEM; + } + pdc->dma_addr = dma_map_single(port->dev, + pdc->buf, + PDC_BUFFER_SIZE, + DMA_FROM_DEVICE); + pdc->dma_size = PDC_BUFFER_SIZE; + pdc->ofs = 0; + } + + atmel_port->pdc_rx_idx = 0; + + UART_PUT_RPR(port, atmel_port->pdc_rx[0].dma_addr); + UART_PUT_RCR(port, PDC_BUFFER_SIZE); + + UART_PUT_RNPR(port, atmel_port->pdc_rx[1].dma_addr); + UART_PUT_RNCR(port, PDC_BUFFER_SIZE); + + return 0; +} + /* * tasklet handling tty stuff outside the interrupt handler. */ @@ -867,10 +956,7 @@ static void atmel_tasklet_func(unsigned long data) /* The interrupt handler does not take the lock */ spin_lock(&port->lock); - if (atmel_use_pdc_tx(port)) - atmel_tx_pdc(port); - else - atmel_tx_chars(port); + atmel_port->schedule_tx(port); status = atmel_port->irq_status; status_change = status ^ atmel_port->irq_status_prev; @@ -892,14 +978,36 @@ static void atmel_tasklet_func(unsigned long data) atmel_port->irq_status_prev = status; } - if (atmel_use_pdc_rx(port)) - atmel_rx_from_pdc(port); - else - atmel_rx_from_ring(port); + atmel_port->schedule_rx(port); spin_unlock(&port->lock); } +static void atmel_set_ops(struct uart_port *port) +{ + struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); + + if (atmel_use_pdc_rx(port)) { + atmel_port->prepare_rx = &atmel_prepare_rx_pdc; + atmel_port->schedule_rx = &atmel_rx_from_pdc; + atmel_port->release_rx = &atmel_release_rx_pdc; + } else { + atmel_port->prepare_rx = NULL; + atmel_port->schedule_rx = &atmel_rx_from_ring; + atmel_port->release_rx = NULL; + } + + if (atmel_use_pdc_tx(port)) { + atmel_port->prepare_tx = &atmel_prepare_tx_pdc; + atmel_port->schedule_tx = &atmel_tx_pdc; + atmel_port->release_tx = &atmel_release_tx_pdc; + } else { + atmel_port->prepare_tx = NULL; + atmel_port->schedule_tx = &atmel_tx_chars; + atmel_port->release_tx = NULL; + } +} + /* * Perform initialization and enable port for reception */ @@ -929,53 +1037,17 @@ static int atmel_startup(struct uart_port *port) /* * Initialize DMA (if necessary) */ - if (atmel_use_pdc_rx(port)) { - int i; - - for (i = 0; i < 2; i++) { - struct atmel_dma_buffer *pdc = &atmel_port->pdc_rx[i]; - - pdc->buf = kmalloc(PDC_BUFFER_SIZE, GFP_KERNEL); - if (pdc->buf == NULL) { - if (i != 0) { - dma_unmap_single(port->dev, - atmel_port->pdc_rx[0].dma_addr, - PDC_BUFFER_SIZE, - DMA_FROM_DEVICE); - kfree(atmel_port->pdc_rx[0].buf); - } - free_irq(port->irq, port); - return -ENOMEM; - } - pdc->dma_addr = dma_map_single(port->dev, - pdc->buf, - PDC_BUFFER_SIZE, - DMA_FROM_DEVICE); - pdc->dma_size = PDC_BUFFER_SIZE; - pdc->ofs = 0; - } - - atmel_port->pdc_rx_idx = 0; - - UART_PUT_RPR(port, atmel_port->pdc_rx[0].dma_addr); - UART_PUT_RCR(port, PDC_BUFFER_SIZE); - - UART_PUT_RNPR(port, atmel_port->pdc_rx[1].dma_addr); - UART_PUT_RNCR(port, PDC_BUFFER_SIZE); - } - if (atmel_use_pdc_tx(port)) { - struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx; - struct circ_buf *xmit = &port->state->xmit; - - pdc->buf = xmit->buf; - pdc->dma_addr = dma_map_single(port->dev, - pdc->buf, - UART_XMIT_SIZE, - DMA_TO_DEVICE); - pdc->dma_size = UART_XMIT_SIZE; - pdc->ofs = 0; + if (atmel_port->prepare_rx) { + retval = atmel_port->prepare_rx(port); + if (retval < 0) + atmel_set_ops(port); } + if (atmel_port->prepare_tx) { + retval = atmel_port->prepare_tx(port); + if (retval < 0) + atmel_set_ops(port); + } /* * If there is a specific "open" function (to register * control line interrupts) @@ -1030,27 +1102,10 @@ static void atmel_shutdown(struct uart_port *port) /* * Shut-down the DMA. */ - if (atmel_use_pdc_rx(port)) { - int i; - - for (i = 0; i < 2; i++) { - struct atmel_dma_buffer *pdc = &atmel_port->pdc_rx[i]; - - dma_unmap_single(port->dev, - pdc->dma_addr, - pdc->dma_size, - DMA_FROM_DEVICE); - kfree(pdc->buf); - } - } - if (atmel_use_pdc_tx(port)) { - struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx; - - dma_unmap_single(port->dev, - pdc->dma_addr, - pdc->dma_size, - DMA_TO_DEVICE); - } + if (atmel_port->release_rx) + atmel_port->release_rx(port); + if (atmel_port->release_tx) + atmel_port->release_tx(port); /* * Disable all interrupts, port and break condition. @@ -1473,6 +1528,8 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port, atmel_port->rs485 = pdata->rs485; } + atmel_set_ops(port); + port->iotype = UPIO_MEM; port->flags = UPF_BOOT_AUTOCONF; port->ops = &atmel_pops; From 08f738be88bb7a0163afd810a19b9cb13c79808f Mon Sep 17 00:00:00 2001 From: Elen Song Date: Mon, 22 Jul 2013 16:30:26 +0800 Subject: [PATCH 1064/3400] serial: at91: add tx dma support Request a slave dma channel for tx dma use. Tx dma will setup a single transfer, when transfer complete, it will call atmel_complete_tx_dma to do finish stuff. Signed-off-by: Elen Song Signed-off-by: Ludovic Desroches Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/atmel_serial.c | 210 +++++++++++++++++++++++++++++- 1 file changed, 206 insertions(+), 4 deletions(-) diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index b56123d3affe..13c1d3170119 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -143,9 +143,15 @@ struct atmel_uart_port { short pdc_rx_idx; /* current PDC RX buffer */ struct atmel_dma_buffer pdc_rx[2]; /* PDC receier */ + bool use_dma_tx; /* enable DMA transmitter */ bool use_pdc_tx; /* enable PDC transmitter */ struct atmel_dma_buffer pdc_tx; /* PDC transmitter */ + spinlock_t lock_tx; /* port lock */ + struct dma_chan *chan_tx; + struct dma_async_tx_descriptor *desc_tx; + dma_cookie_t cookie_tx; + struct scatterlist sg_tx; struct tasklet_struct tasklet; unsigned int irq_status; unsigned int irq_status_prev; @@ -211,6 +217,13 @@ static bool atmel_use_pdc_tx(struct uart_port *port) } #endif +static bool atmel_use_dma_tx(struct uart_port *port) +{ + struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); + + return atmel_port->use_dma_tx; +} + /* Enable or disable the rs485 support */ void atmel_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf) { @@ -569,6 +582,182 @@ static void atmel_tx_chars(struct uart_port *port) UART_PUT_IER(port, atmel_port->tx_done_mask); } +static void atmel_complete_tx_dma(void *arg) +{ + struct atmel_uart_port *atmel_port = arg; + struct uart_port *port = &atmel_port->uart; + struct circ_buf *xmit = &port->state->xmit; + struct dma_chan *chan = atmel_port->chan_tx; + unsigned long flags; + + spin_lock_irqsave(&port->lock, flags); + + if (chan) + dmaengine_terminate_all(chan); + xmit->tail += sg_dma_len(&atmel_port->sg_tx); + xmit->tail &= UART_XMIT_SIZE - 1; + + port->icount.tx += sg_dma_len(&atmel_port->sg_tx); + + spin_lock_irq(&atmel_port->lock_tx); + async_tx_ack(atmel_port->desc_tx); + atmel_port->cookie_tx = -EINVAL; + atmel_port->desc_tx = NULL; + spin_unlock_irq(&atmel_port->lock_tx); + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(port); + + /* Do we really need this? */ + if (!uart_circ_empty(xmit)) + tasklet_schedule(&atmel_port->tasklet); + + spin_unlock_irqrestore(&port->lock, flags); +} + +static void atmel_release_tx_dma(struct uart_port *port) +{ + struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); + struct dma_chan *chan = atmel_port->chan_tx; + + if (chan) { + dmaengine_terminate_all(chan); + dma_release_channel(chan); + dma_unmap_sg(port->dev, &atmel_port->sg_tx, 1, + DMA_MEM_TO_DEV); + } + + atmel_port->desc_tx = NULL; + atmel_port->chan_tx = NULL; + atmel_port->cookie_tx = -EINVAL; +} + +/* + * Called from tasklet with TXRDY interrupt is disabled. + */ +static void atmel_tx_dma(struct uart_port *port) +{ + struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); + struct circ_buf *xmit = &port->state->xmit; + struct dma_chan *chan = atmel_port->chan_tx; + struct dma_async_tx_descriptor *desc; + struct scatterlist *sg = &atmel_port->sg_tx; + + /* Make sure we have an idle channel */ + if (atmel_port->desc_tx != NULL) + return; + + if (!uart_circ_empty(xmit) && !uart_tx_stopped(port)) { + /* + * DMA is idle now. + * Port xmit buffer is already mapped, + * and it is one page... Just adjust + * offsets and lengths. Since it is a circular buffer, + * we have to transmit till the end, and then the rest. + * Take the port lock to get a + * consistent xmit buffer state. + */ + sg->offset = xmit->tail & (UART_XMIT_SIZE - 1); + sg_dma_address(sg) = (sg_dma_address(sg) & + ~(UART_XMIT_SIZE - 1)) + + sg->offset; + sg_dma_len(sg) = CIRC_CNT_TO_END(xmit->head, + xmit->tail, + UART_XMIT_SIZE); + BUG_ON(!sg_dma_len(sg)); + + desc = dmaengine_prep_slave_sg(chan, + sg, + 1, + DMA_MEM_TO_DEV, + DMA_PREP_INTERRUPT | + DMA_CTRL_ACK); + if (!desc) { + dev_err(port->dev, "Failed to send via dma!\n"); + return; + } + + dma_sync_sg_for_device(port->dev, sg, 1, DMA_MEM_TO_DEV); + + atmel_port->desc_tx = desc; + desc->callback = atmel_complete_tx_dma; + desc->callback_param = atmel_port; + atmel_port->cookie_tx = dmaengine_submit(desc); + + } else { + if (atmel_port->rs485.flags & SER_RS485_ENABLED) { + /* DMA done, stop TX, start RX for RS485 */ + atmel_start_rx(port); + } + } + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(port); +} + +static int atmel_prepare_tx_dma(struct uart_port *port) +{ + struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); + dma_cap_mask_t mask; + struct dma_slave_config config; + int ret, nent; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + + atmel_port->chan_tx = dma_request_slave_channel(port->dev, "tx"); + if (atmel_port->chan_tx == NULL) + goto chan_err; + dev_info(port->dev, "using %s for tx DMA transfers\n", + dma_chan_name(atmel_port->chan_tx)); + + spin_lock_init(&atmel_port->lock_tx); + sg_init_table(&atmel_port->sg_tx, 1); + /* UART circular tx buffer is an aligned page. */ + BUG_ON((int)port->state->xmit.buf & ~PAGE_MASK); + sg_set_page(&atmel_port->sg_tx, + virt_to_page(port->state->xmit.buf), + UART_XMIT_SIZE, + (int)port->state->xmit.buf & ~PAGE_MASK); + nent = dma_map_sg(port->dev, + &atmel_port->sg_tx, + 1, + DMA_MEM_TO_DEV); + + if (!nent) { + dev_dbg(port->dev, "need to release resource of dma\n"); + goto chan_err; + } else { + dev_dbg(port->dev, "%s: mapped %d@%p to %x\n", __func__, + sg_dma_len(&atmel_port->sg_tx), + port->state->xmit.buf, + sg_dma_address(&atmel_port->sg_tx)); + } + + /* Configure the slave DMA */ + memset(&config, 0, sizeof(config)); + config.direction = DMA_MEM_TO_DEV; + config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; + config.dst_addr = port->mapbase + ATMEL_US_THR; + + ret = dmaengine_device_control(atmel_port->chan_tx, + DMA_SLAVE_CONFIG, + (unsigned long)&config); + if (ret) { + dev_err(port->dev, "DMA tx slave configuration failed\n"); + goto chan_err; + } + + return 0; + +chan_err: + dev_err(port->dev, "TX channel not available, switch to pio\n"); + atmel_port->use_dma_tx = 0; + if (atmel_port->chan_tx) + atmel_release_tx_dma(port); + return -EINVAL; +} + /* * receive interrupt handler. */ @@ -997,7 +1186,11 @@ static void atmel_set_ops(struct uart_port *port) atmel_port->release_rx = NULL; } - if (atmel_use_pdc_tx(port)) { + if (atmel_use_dma_tx(port)) { + atmel_port->prepare_tx = &atmel_prepare_tx_dma; + atmel_port->schedule_tx = &atmel_tx_dma; + atmel_port->release_tx = &atmel_release_tx_dma; + } else if (atmel_use_pdc_tx(port)) { atmel_port->prepare_tx = &atmel_prepare_tx_pdc; atmel_port->schedule_tx = &atmel_tx_pdc; atmel_port->release_tx = &atmel_release_tx_pdc; @@ -1488,10 +1681,18 @@ static void atmel_of_init_port(struct atmel_uart_port *atmel_port, else atmel_port->use_pdc_rx = false; - if (of_get_property(np, "atmel,use-dma-tx", NULL)) - atmel_port->use_pdc_tx = true; - else + if (of_get_property(np, "atmel,use-dma-tx", NULL)) { + if (of_get_property(np, "dmas", NULL)) { + atmel_port->use_dma_tx = true; + atmel_port->use_pdc_tx = false; + } else { + atmel_port->use_dma_tx = false; + atmel_port->use_pdc_tx = true; + } + } else { + atmel_port->use_dma_tx = false; atmel_port->use_pdc_tx = false; + } /* rs485 properties */ if (of_property_read_u32_array(np, "rs485-rts-delay", @@ -1525,6 +1726,7 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port, } else { atmel_port->use_pdc_rx = pdata->use_dma_rx; atmel_port->use_pdc_tx = pdata->use_dma_tx; + atmel_port->use_dma_tx = false; atmel_port->rs485 = pdata->rs485; } From 34df42f59a602241b416001516d53fcfe35072b2 Mon Sep 17 00:00:00 2001 From: Elen Song Date: Mon, 22 Jul 2013 16:30:27 +0800 Subject: [PATCH 1065/3400] serial: at91: add rx dma support Request a cyclic dma channel for rx dma use. Use cyclic transfer is to prevent receive data overrun. We allocate a cycle dma cookie after request channel, after that, enable uart timeout interrupt in startup stage, when data successful received, the timeout callback will check the residual bytes and insert receiving datas into the framework during the transfer interval. When current descriptor finished, the dma callback will also check the residual bytes and filp the receiving data. Signed-off-by: Elen Song Signed-off-by: Ludovic Desroches Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/atmel_serial.c | 224 +++++++++++++++++++++++++++++- 1 file changed, 220 insertions(+), 4 deletions(-) diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 13c1d3170119..eaf7dc7795b8 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -139,6 +139,7 @@ struct atmel_uart_port { u32 backup_imr; /* IMR saved during suspend */ int break_active; /* break being received */ + bool use_dma_rx; /* enable DMA receiver */ bool use_pdc_rx; /* enable PDC receiver */ short pdc_rx_idx; /* current PDC RX buffer */ struct atmel_dma_buffer pdc_rx[2]; /* PDC receier */ @@ -148,10 +149,15 @@ struct atmel_uart_port { struct atmel_dma_buffer pdc_tx; /* PDC transmitter */ spinlock_t lock_tx; /* port lock */ + spinlock_t lock_rx; /* port lock */ struct dma_chan *chan_tx; + struct dma_chan *chan_rx; struct dma_async_tx_descriptor *desc_tx; + struct dma_async_tx_descriptor *desc_rx; dma_cookie_t cookie_tx; + dma_cookie_t cookie_rx; struct scatterlist sg_tx; + struct scatterlist sg_rx; struct tasklet_struct tasklet; unsigned int irq_status; unsigned int irq_status_prev; @@ -224,6 +230,13 @@ static bool atmel_use_dma_tx(struct uart_port *port) return atmel_port->use_dma_tx; } +static bool atmel_use_dma_rx(struct uart_port *port) +{ + struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); + + return atmel_port->use_dma_rx; +} + /* Enable or disable the rs485 support */ void atmel_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf) { @@ -758,6 +771,184 @@ chan_err: return -EINVAL; } +static void atmel_flip_buffer_rx_dma(struct uart_port *port, + char *buf, size_t count) +{ + struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); + struct tty_port *tport = &port->state->port; + + dma_sync_sg_for_cpu(port->dev, + &atmel_port->sg_rx, + 1, + DMA_DEV_TO_MEM); + + tty_insert_flip_string(tport, buf, count); + + dma_sync_sg_for_device(port->dev, + &atmel_port->sg_rx, + 1, + DMA_DEV_TO_MEM); + /* + * Drop the lock here since it might end up calling + * uart_start(), which takes the lock. + */ + spin_unlock(&port->lock); + tty_flip_buffer_push(tport); + spin_lock(&port->lock); +} + +static void atmel_complete_rx_dma(void *arg) +{ + struct uart_port *port = arg; + struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); + + tasklet_schedule(&atmel_port->tasklet); +} + +static void atmel_release_rx_dma(struct uart_port *port) +{ + struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); + struct dma_chan *chan = atmel_port->chan_rx; + + if (chan) { + dmaengine_terminate_all(chan); + dma_release_channel(chan); + dma_unmap_sg(port->dev, &atmel_port->sg_rx, 1, + DMA_DEV_TO_MEM); + } + + atmel_port->desc_rx = NULL; + atmel_port->chan_rx = NULL; + atmel_port->cookie_rx = -EINVAL; +} + +static void atmel_rx_from_dma(struct uart_port *port) +{ + struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); + struct circ_buf *ring = &atmel_port->rx_ring; + struct dma_chan *chan = atmel_port->chan_rx; + struct dma_tx_state state; + enum dma_status dmastat; + size_t pending, count; + + + /* Reset the UART timeout early so that we don't miss one */ + UART_PUT_CR(port, ATMEL_US_STTTO); + dmastat = dmaengine_tx_status(chan, + atmel_port->cookie_rx, + &state); + /* Restart a new tasklet if DMA status is error */ + if (dmastat == DMA_ERROR) { + dev_dbg(port->dev, "Get residue error, restart tasklet\n"); + UART_PUT_IER(port, ATMEL_US_TIMEOUT); + tasklet_schedule(&atmel_port->tasklet); + return; + } + /* current transfer size should no larger than dma buffer */ + pending = sg_dma_len(&atmel_port->sg_rx) - state.residue; + BUG_ON(pending > sg_dma_len(&atmel_port->sg_rx)); + + /* + * This will take the chars we have so far, + * ring->head will record the transfer size, only new bytes come + * will insert into the framework. + */ + if (pending > ring->head) { + count = pending - ring->head; + + atmel_flip_buffer_rx_dma(port, ring->buf + ring->head, count); + + ring->head += count; + if (ring->head == sg_dma_len(&atmel_port->sg_rx)) + ring->head = 0; + + port->icount.rx += count; + } + + UART_PUT_IER(port, ATMEL_US_TIMEOUT); +} + +static int atmel_prepare_rx_dma(struct uart_port *port) +{ + struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); + struct dma_async_tx_descriptor *desc; + dma_cap_mask_t mask; + struct dma_slave_config config; + struct circ_buf *ring; + int ret, nent; + + ring = &atmel_port->rx_ring; + + dma_cap_zero(mask); + dma_cap_set(DMA_CYCLIC, mask); + + atmel_port->chan_rx = dma_request_slave_channel(port->dev, "rx"); + if (atmel_port->chan_rx == NULL) + goto chan_err; + dev_info(port->dev, "using %s for rx DMA transfers\n", + dma_chan_name(atmel_port->chan_rx)); + + spin_lock_init(&atmel_port->lock_rx); + sg_init_table(&atmel_port->sg_rx, 1); + /* UART circular rx buffer is an aligned page. */ + BUG_ON((int)port->state->xmit.buf & ~PAGE_MASK); + sg_set_page(&atmel_port->sg_rx, + virt_to_page(ring->buf), + ATMEL_SERIAL_RINGSIZE, + (int)ring->buf & ~PAGE_MASK); + nent = dma_map_sg(port->dev, + &atmel_port->sg_rx, + 1, + DMA_DEV_TO_MEM); + + if (!nent) { + dev_dbg(port->dev, "need to release resource of dma\n"); + goto chan_err; + } else { + dev_dbg(port->dev, "%s: mapped %d@%p to %x\n", __func__, + sg_dma_len(&atmel_port->sg_rx), + ring->buf, + sg_dma_address(&atmel_port->sg_rx)); + } + + /* Configure the slave DMA */ + memset(&config, 0, sizeof(config)); + config.direction = DMA_DEV_TO_MEM; + config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; + config.src_addr = port->mapbase + ATMEL_US_RHR; + + ret = dmaengine_device_control(atmel_port->chan_rx, + DMA_SLAVE_CONFIG, + (unsigned long)&config); + if (ret) { + dev_err(port->dev, "DMA rx slave configuration failed\n"); + goto chan_err; + } + /* + * Prepare a cyclic dma transfer, assign 2 descriptors, + * each one is half ring buffer size + */ + desc = dmaengine_prep_dma_cyclic(atmel_port->chan_rx, + sg_dma_address(&atmel_port->sg_rx), + sg_dma_len(&atmel_port->sg_rx), + sg_dma_len(&atmel_port->sg_rx)/2, + DMA_DEV_TO_MEM, + DMA_PREP_INTERRUPT); + desc->callback = atmel_complete_rx_dma; + desc->callback_param = port; + atmel_port->desc_rx = desc; + atmel_port->cookie_rx = dmaengine_submit(desc); + + return 0; + +chan_err: + dev_err(port->dev, "RX channel not available, switch to pio\n"); + atmel_port->use_dma_rx = 0; + if (atmel_port->chan_rx) + atmel_release_rx_dma(port); + return -EINVAL; +} + /* * receive interrupt handler. */ @@ -785,6 +976,13 @@ atmel_handle_receive(struct uart_port *port, unsigned int pending) atmel_pdc_rxerr(port, pending); } + if (atmel_use_dma_rx(port)) { + if (pending & ATMEL_US_TIMEOUT) { + UART_PUT_IDR(port, ATMEL_US_TIMEOUT); + tasklet_schedule(&atmel_port->tasklet); + } + } + /* Interrupt receive */ if (pending & ATMEL_US_RXRDY) atmel_rx_chars(port); @@ -1176,7 +1374,11 @@ static void atmel_set_ops(struct uart_port *port) { struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); - if (atmel_use_pdc_rx(port)) { + if (atmel_use_dma_rx(port)) { + atmel_port->prepare_rx = &atmel_prepare_rx_dma; + atmel_port->schedule_rx = &atmel_rx_from_dma; + atmel_port->release_rx = &atmel_release_rx_dma; + } else if (atmel_use_pdc_rx(port)) { atmel_port->prepare_rx = &atmel_prepare_rx_pdc; atmel_port->schedule_rx = &atmel_rx_from_pdc; atmel_port->release_rx = &atmel_release_rx_pdc; @@ -1272,6 +1474,11 @@ static int atmel_startup(struct uart_port *port) UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT); /* enable PDC controller */ UART_PUT_PTCR(port, ATMEL_PDC_RXTEN); + } else if (atmel_use_dma_rx(port)) { + UART_PUT_RTOR(port, PDC_RX_TIMEOUT); + UART_PUT_CR(port, ATMEL_US_STTTO); + + UART_PUT_IER(port, ATMEL_US_TIMEOUT); } else { /* enable receive only */ UART_PUT_IER(port, ATMEL_US_RXRDY); @@ -1676,10 +1883,18 @@ static void atmel_of_init_port(struct atmel_uart_port *atmel_port, u32 rs485_delay[2]; /* DMA/PDC usage specification */ - if (of_get_property(np, "atmel,use-dma-rx", NULL)) - atmel_port->use_pdc_rx = true; - else + if (of_get_property(np, "atmel,use-dma-rx", NULL)) { + if (of_get_property(np, "dmas", NULL)) { + atmel_port->use_dma_rx = true; + atmel_port->use_pdc_rx = false; + } else { + atmel_port->use_dma_rx = false; + atmel_port->use_pdc_rx = true; + } + } else { + atmel_port->use_dma_rx = false; atmel_port->use_pdc_rx = false; + } if (of_get_property(np, "atmel,use-dma-tx", NULL)) { if (of_get_property(np, "dmas", NULL)) { @@ -1726,6 +1941,7 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port, } else { atmel_port->use_pdc_rx = pdata->use_dma_rx; atmel_port->use_pdc_tx = pdata->use_dma_tx; + atmel_port->use_dma_rx = false; atmel_port->use_dma_tx = false; atmel_port->rs485 = pdata->rs485; } From 33d64c4ffab7da36d657a35fe2b494d5c971f615 Mon Sep 17 00:00:00 2001 From: Elen Song Date: Mon, 22 Jul 2013 16:30:28 +0800 Subject: [PATCH 1066/3400] serial: at91: support run time switch transfer mode We will switch to pio mode when request of dma or pdc fail. But soon or later, when the request is success, the transfer mode can switch to them at next open serial port action. So in startup stage, we should get original transfer mode. Signed-off-by: Elen Song Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/atmel_serial.c | 139 +++++++++++++++++------------- 1 file changed, 80 insertions(+), 59 deletions(-) diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index eaf7dc7795b8..1db68713d656 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -1370,6 +1370,80 @@ static void atmel_tasklet_func(unsigned long data) spin_unlock(&port->lock); } +static int atmel_init_property(struct atmel_uart_port *atmel_port, + struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct atmel_uart_data *pdata = pdev->dev.platform_data; + + if (np) { + /* DMA/PDC usage specification */ + if (of_get_property(np, "atmel,use-dma-rx", NULL)) { + if (of_get_property(np, "dmas", NULL)) { + atmel_port->use_dma_rx = true; + atmel_port->use_pdc_rx = false; + } else { + atmel_port->use_dma_rx = false; + atmel_port->use_pdc_rx = true; + } + } else { + atmel_port->use_dma_rx = false; + atmel_port->use_pdc_rx = false; + } + + if (of_get_property(np, "atmel,use-dma-tx", NULL)) { + if (of_get_property(np, "dmas", NULL)) { + atmel_port->use_dma_tx = true; + atmel_port->use_pdc_tx = false; + } else { + atmel_port->use_dma_tx = false; + atmel_port->use_pdc_tx = true; + } + } else { + atmel_port->use_dma_tx = false; + atmel_port->use_pdc_tx = false; + } + + } else { + atmel_port->use_pdc_rx = pdata->use_dma_rx; + atmel_port->use_pdc_tx = pdata->use_dma_tx; + atmel_port->use_dma_rx = false; + atmel_port->use_dma_tx = false; + } + + return 0; +} + +static void atmel_init_rs485(struct atmel_uart_port *atmel_port, + struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct atmel_uart_data *pdata = pdev->dev.platform_data; + + if (np) { + u32 rs485_delay[2]; + /* rs485 properties */ + if (of_property_read_u32_array(np, "rs485-rts-delay", + rs485_delay, 2) == 0) { + struct serial_rs485 *rs485conf = &atmel_port->rs485; + + rs485conf->delay_rts_before_send = rs485_delay[0]; + rs485conf->delay_rts_after_send = rs485_delay[1]; + rs485conf->flags = 0; + + if (of_get_property(np, "rs485-rx-during-tx", NULL)) + rs485conf->flags |= SER_RS485_RX_DURING_TX; + + if (of_get_property(np, "linux,rs485-enabled-at-boot-time", + NULL)) + rs485conf->flags |= SER_RS485_ENABLED; + } + } else { + atmel_port->rs485 = pdata->rs485; + } + +} + static void atmel_set_ops(struct uart_port *port) { struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); @@ -1408,6 +1482,7 @@ static void atmel_set_ops(struct uart_port *port) */ static int atmel_startup(struct uart_port *port) { + struct platform_device *pdev = to_platform_device(port->dev); struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); struct tty_struct *tty = port->state->port.tty; int retval; @@ -1432,6 +1507,8 @@ static int atmel_startup(struct uart_port *port) /* * Initialize DMA (if necessary) */ + atmel_init_property(atmel_port, pdev); + if (atmel_port->prepare_rx) { retval = atmel_port->prepare_rx(port); if (retval < 0) @@ -1877,55 +1954,6 @@ static struct uart_ops atmel_pops = { #endif }; -static void atmel_of_init_port(struct atmel_uart_port *atmel_port, - struct device_node *np) -{ - u32 rs485_delay[2]; - - /* DMA/PDC usage specification */ - if (of_get_property(np, "atmel,use-dma-rx", NULL)) { - if (of_get_property(np, "dmas", NULL)) { - atmel_port->use_dma_rx = true; - atmel_port->use_pdc_rx = false; - } else { - atmel_port->use_dma_rx = false; - atmel_port->use_pdc_rx = true; - } - } else { - atmel_port->use_dma_rx = false; - atmel_port->use_pdc_rx = false; - } - - if (of_get_property(np, "atmel,use-dma-tx", NULL)) { - if (of_get_property(np, "dmas", NULL)) { - atmel_port->use_dma_tx = true; - atmel_port->use_pdc_tx = false; - } else { - atmel_port->use_dma_tx = false; - atmel_port->use_pdc_tx = true; - } - } else { - atmel_port->use_dma_tx = false; - atmel_port->use_pdc_tx = false; - } - - /* rs485 properties */ - if (of_property_read_u32_array(np, "rs485-rts-delay", - rs485_delay, 2) == 0) { - struct serial_rs485 *rs485conf = &atmel_port->rs485; - - rs485conf->delay_rts_before_send = rs485_delay[0]; - rs485conf->delay_rts_after_send = rs485_delay[1]; - rs485conf->flags = 0; - - if (of_get_property(np, "rs485-rx-during-tx", NULL)) - rs485conf->flags |= SER_RS485_RX_DURING_TX; - - if (of_get_property(np, "linux,rs485-enabled-at-boot-time", NULL)) - rs485conf->flags |= SER_RS485_ENABLED; - } -} - /* * Configure the port from the platform device resource info. */ @@ -1936,17 +1964,10 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port, struct uart_port *port = &atmel_port->uart; struct atmel_uart_data *pdata = pdev->dev.platform_data; - if (pdev->dev.of_node) { - atmel_of_init_port(atmel_port, pdev->dev.of_node); - } else { - atmel_port->use_pdc_rx = pdata->use_dma_rx; - atmel_port->use_pdc_tx = pdata->use_dma_tx; - atmel_port->use_dma_rx = false; - atmel_port->use_dma_tx = false; - atmel_port->rs485 = pdata->rs485; - } + if (!atmel_init_property(atmel_port, pdev)) + atmel_set_ops(port); - atmel_set_ops(port); + atmel_init_rs485(atmel_port, pdev); port->iotype = UPIO_MEM; port->flags = UPF_BOOT_AUTOCONF; From 055560b04a8cd063aea916fd083b7aec02c2adb8 Mon Sep 17 00:00:00 2001 From: Elen Song Date: Mon, 22 Jul 2013 16:30:29 +0800 Subject: [PATCH 1067/3400] serial: at91: distinguish usart and uart Distinguish usart and uart by read ip name register, The usart read name is "USAR", The uart and dbgu read name is "DBGU". Signed-off-by: Elen Song Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/atmel_serial.c | 37 +++++++++++++++++++++++++++++++ include/linux/atmel_serial.h | 2 ++ 2 files changed, 39 insertions(+) diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 1db68713d656..8dbc3e67dfa4 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -97,6 +97,7 @@ static void atmel_stop_rx(struct uart_port *port); #define UART_PUT_BRGR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_BRGR) #define UART_PUT_RTOR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_RTOR) #define UART_PUT_TTGR(port, v) __raw_writel(v, (port)->membase + ATMEL_US_TTGR) +#define UART_GET_IP_NAME(port) __raw_readl((port)->membase + ATMEL_US_NAME) /* PDC registers */ #define UART_PUT_PTCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_PTCR) @@ -166,6 +167,7 @@ struct atmel_uart_port { struct serial_rs485 rs485; /* rs485 settings */ unsigned int tx_done_mask; + bool is_usart; /* usart or uart */ int (*prepare_rx)(struct uart_port *port); int (*prepare_tx)(struct uart_port *port); void (*schedule_rx)(struct uart_port *port); @@ -1477,6 +1479,34 @@ static void atmel_set_ops(struct uart_port *port) } } +/* + * Get ip name usart or uart + */ +static int atmel_get_ip_name(struct uart_port *port) +{ + struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); + int name = UART_GET_IP_NAME(port); + int usart, uart; + /* usart and uart ascii */ + usart = 0x55534152; + uart = 0x44424755; + + atmel_port->is_usart = false; + + if (name == usart) { + dev_dbg(port->dev, "This is usart\n"); + atmel_port->is_usart = true; + } else if (name == uart) { + dev_dbg(port->dev, "This is uart\n"); + atmel_port->is_usart = false; + } else { + dev_err(port->dev, "Not supported ip name, set to uart\n"); + return -EINVAL; + } + + return 0; +} + /* * Perform initialization and enable port for reception */ @@ -2336,6 +2366,13 @@ static int atmel_serial_probe(struct platform_device *pdev) UART_PUT_CR(&port->uart, ATMEL_US_RTSEN); } + /* + * Get port name of usart or uart + */ + ret = atmel_get_ip_name(&port->uart); + if (ret < 0) + goto err_add_port; + return 0; err_add_port: diff --git a/include/linux/atmel_serial.h b/include/linux/atmel_serial.h index fd6833764d72..be201ca2990c 100644 --- a/include/linux/atmel_serial.h +++ b/include/linux/atmel_serial.h @@ -124,4 +124,6 @@ #define ATMEL_US_NER 0x44 /* Number of Errors Register */ #define ATMEL_US_IF 0x4c /* IrDA Filter Register */ +#define ATMEL_US_NAME 0xf0 /* Ip Name */ + #endif From 2e68c22fde9b001e41d47185a5b7612da60d8c33 Mon Sep 17 00:00:00 2001 From: Elen Song Date: Mon, 22 Jul 2013 16:30:30 +0800 Subject: [PATCH 1068/3400] serial: at91: make UART support dma and pdc transfers Because the UART lack of receive timeout register, so we use a timer to trigger data receive. The DBGU is regarded as UART. Signed-off-by: Elen Song Signed-off-by: Ludovic Desroches Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/atmel_serial.c | 48 +++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 8dbc3e67dfa4..7e2cb31497c3 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -168,6 +169,7 @@ struct atmel_uart_port { struct serial_rs485 rs485; /* rs485 settings */ unsigned int tx_done_mask; bool is_usart; /* usart or uart */ + struct timer_list uart_timer; /* uart timer */ int (*prepare_rx)(struct uart_port *port); int (*prepare_tx)(struct uart_port *port); void (*schedule_rx)(struct uart_port *port); @@ -822,6 +824,9 @@ static void atmel_release_rx_dma(struct uart_port *port) atmel_port->desc_rx = NULL; atmel_port->chan_rx = NULL; atmel_port->cookie_rx = -EINVAL; + + if (!atmel_port->is_usart) + del_timer_sync(&atmel_port->uart_timer); } static void atmel_rx_from_dma(struct uart_port *port) @@ -951,6 +956,15 @@ chan_err: return -EINVAL; } +static void atmel_uart_timer_callback(unsigned long data) +{ + struct uart_port *port = (void *)data; + struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); + + tasklet_schedule(&atmel_port->tasklet); + mod_timer(&atmel_port->uart_timer, jiffies + uart_poll_timeout(port)); +} + /* * receive interrupt handler. */ @@ -1214,6 +1228,9 @@ static void atmel_release_rx_pdc(struct uart_port *port) DMA_FROM_DEVICE); kfree(pdc->buf); } + + if (!atmel_port->is_usart) + del_timer_sync(&atmel_port->uart_timer); } static void atmel_rx_from_pdc(struct uart_port *port) @@ -1575,17 +1592,36 @@ static int atmel_startup(struct uart_port *port) if (atmel_use_pdc_rx(port)) { /* set UART timeout */ - UART_PUT_RTOR(port, PDC_RX_TIMEOUT); - UART_PUT_CR(port, ATMEL_US_STTTO); + if (!atmel_port->is_usart) { + setup_timer(&atmel_port->uart_timer, + atmel_uart_timer_callback, + (unsigned long)port); + mod_timer(&atmel_port->uart_timer, + jiffies + uart_poll_timeout(port)); + /* set USART timeout */ + } else { + UART_PUT_RTOR(port, PDC_RX_TIMEOUT); + UART_PUT_CR(port, ATMEL_US_STTTO); - UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT); + UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT); + } /* enable PDC controller */ UART_PUT_PTCR(port, ATMEL_PDC_RXTEN); } else if (atmel_use_dma_rx(port)) { - UART_PUT_RTOR(port, PDC_RX_TIMEOUT); - UART_PUT_CR(port, ATMEL_US_STTTO); + /* set UART timeout */ + if (!atmel_port->is_usart) { + setup_timer(&atmel_port->uart_timer, + atmel_uart_timer_callback, + (unsigned long)port); + mod_timer(&atmel_port->uart_timer, + jiffies + uart_poll_timeout(port)); + /* set USART timeout */ + } else { + UART_PUT_RTOR(port, PDC_RX_TIMEOUT); + UART_PUT_CR(port, ATMEL_US_STTTO); - UART_PUT_IER(port, ATMEL_US_TIMEOUT); + UART_PUT_IER(port, ATMEL_US_TIMEOUT); + } } else { /* enable receive only */ UART_PUT_IER(port, ATMEL_US_RXRDY); From e469719344ae1cdde90a4c8c3746588f8c86f6cf Mon Sep 17 00:00:00 2001 From: Elen Song Date: Mon, 22 Jul 2013 16:30:31 +0800 Subject: [PATCH 1069/3400] serial: at91: add dma support in usart binding descriptions Signed-off-by: Elen Song Signed-off-by: Greg Kroah-Hartman --- .../bindings/tty/serial/atmel-usart.txt | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/tty/serial/atmel-usart.txt b/Documentation/devicetree/bindings/tty/serial/atmel-usart.txt index a49d9a1d4ccf..2191dcb9f1da 100644 --- a/Documentation/devicetree/bindings/tty/serial/atmel-usart.txt +++ b/Documentation/devicetree/bindings/tty/serial/atmel-usart.txt @@ -10,13 +10,18 @@ Required properties: Optional properties: - atmel,use-dma-rx: use of PDC or DMA for receiving data - atmel,use-dma-tx: use of PDC or DMA for transmitting data +- add dma bindings for dma transfer: + - dmas: DMA specifier, consisting of a phandle to DMA controller node, + memory peripheral interface and USART DMA channel ID, FIFO configuration. + Refer to dma.txt and atmel-dma.txt for details. + - dma-names: "rx" for RX channel, "tx" for TX channel. compatible description: - at91rm9200: legacy USART support - at91sam9260: generic USART implementation for SAM9 SoCs Example: - +- use PDC: usart0: serial@fff8c000 { compatible = "atmel,at91sam9260-usart"; reg = <0xfff8c000 0x4000>; @@ -25,3 +30,14 @@ Example: atmel,use-dma-tx; }; +- use DMA: + usart0: serial@f001c000 { + compatible = "atmel,at91sam9260-usart"; + reg = <0xf001c000 0x100>; + interrupts = <12 4 5>; + atmel,use-dma-rx; + atmel,use-dma-tx; + dmas = <&dma0 2 0x3>, + <&dma0 2 0x204>; + dma-names = "tx", "rx"; + }; From f21e683508ead3ad8db7ffef3d8b5802c3b43e9a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 24 Jul 2013 15:05:22 -0700 Subject: [PATCH 1070/3400] rtc: convert class code to use dev_groups The dev_attrs field of struct class is going away soon, dev_groups should be used instead. This converts the rtc class code to use the correct field. Acked-by: Alessandro Zummo Signed-off-by: Greg Kroah-Hartman --- drivers/rtc/rtc-sysfs.c | 46 ++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c index 4b26f8672b2d..babd43bf3ddc 100644 --- a/drivers/rtc/rtc-sysfs.c +++ b/drivers/rtc/rtc-sysfs.c @@ -25,15 +25,14 @@ */ static ssize_t -rtc_sysfs_show_name(struct device *dev, struct device_attribute *attr, - char *buf) +name_show(struct device *dev, struct device_attribute *attr, char *buf) { return sprintf(buf, "%s\n", to_rtc_device(dev)->name); } +static DEVICE_ATTR_RO(name); static ssize_t -rtc_sysfs_show_date(struct device *dev, struct device_attribute *attr, - char *buf) +date_show(struct device *dev, struct device_attribute *attr, char *buf) { ssize_t retval; struct rtc_time tm; @@ -46,10 +45,10 @@ rtc_sysfs_show_date(struct device *dev, struct device_attribute *attr, return retval; } +static DEVICE_ATTR_RO(date); static ssize_t -rtc_sysfs_show_time(struct device *dev, struct device_attribute *attr, - char *buf) +time_show(struct device *dev, struct device_attribute *attr, char *buf) { ssize_t retval; struct rtc_time tm; @@ -62,10 +61,10 @@ rtc_sysfs_show_time(struct device *dev, struct device_attribute *attr, return retval; } +static DEVICE_ATTR_RO(time); static ssize_t -rtc_sysfs_show_since_epoch(struct device *dev, struct device_attribute *attr, - char *buf) +since_epoch_show(struct device *dev, struct device_attribute *attr, char *buf) { ssize_t retval; struct rtc_time tm; @@ -79,16 +78,16 @@ rtc_sysfs_show_since_epoch(struct device *dev, struct device_attribute *attr, return retval; } +static DEVICE_ATTR_RO(since_epoch); static ssize_t -rtc_sysfs_show_max_user_freq(struct device *dev, struct device_attribute *attr, - char *buf) +max_user_freq_show(struct device *dev, struct device_attribute *attr, char *buf) { return sprintf(buf, "%d\n", to_rtc_device(dev)->max_user_freq); } static ssize_t -rtc_sysfs_set_max_user_freq(struct device *dev, struct device_attribute *attr, +max_user_freq_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t n) { struct rtc_device *rtc = to_rtc_device(dev); @@ -101,6 +100,7 @@ rtc_sysfs_set_max_user_freq(struct device *dev, struct device_attribute *attr, return n; } +static DEVICE_ATTR_RW(max_user_freq); /** * rtc_sysfs_show_hctosys - indicate if the given RTC set the system time @@ -109,8 +109,7 @@ rtc_sysfs_set_max_user_freq(struct device *dev, struct device_attribute *attr, * boot or resume event. */ static ssize_t -rtc_sysfs_show_hctosys(struct device *dev, struct device_attribute *attr, - char *buf) +hctosys_show(struct device *dev, struct device_attribute *attr, char *buf) { #ifdef CONFIG_RTC_HCTOSYS_DEVICE if (rtc_hctosys_ret == 0 && @@ -121,17 +120,18 @@ rtc_sysfs_show_hctosys(struct device *dev, struct device_attribute *attr, #endif return sprintf(buf, "0\n"); } +static DEVICE_ATTR_RO(hctosys); -static struct device_attribute rtc_attrs[] = { - __ATTR(name, S_IRUGO, rtc_sysfs_show_name, NULL), - __ATTR(date, S_IRUGO, rtc_sysfs_show_date, NULL), - __ATTR(time, S_IRUGO, rtc_sysfs_show_time, NULL), - __ATTR(since_epoch, S_IRUGO, rtc_sysfs_show_since_epoch, NULL), - __ATTR(max_user_freq, S_IRUGO | S_IWUSR, rtc_sysfs_show_max_user_freq, - rtc_sysfs_set_max_user_freq), - __ATTR(hctosys, S_IRUGO, rtc_sysfs_show_hctosys, NULL), - { }, +static struct attribute *rtc_attrs[] = { + &dev_attr_name.attr, + &dev_attr_date.attr, + &dev_attr_time.attr, + &dev_attr_since_epoch.attr, + &dev_attr_max_user_freq.attr, + &dev_attr_hctosys.attr, + NULL, }; +ATTRIBUTE_GROUPS(rtc); static ssize_t rtc_sysfs_show_wakealarm(struct device *dev, struct device_attribute *attr, @@ -261,5 +261,5 @@ void rtc_sysfs_del_device(struct rtc_device *rtc) void __init rtc_sysfs_init(struct class *rtc_class) { - rtc_class->dev_attrs = rtc_attrs; + rtc_class->dev_groups = rtc_groups; } From 29f1953d51faa3995192ba4ccff3b71c661940c2 Mon Sep 17 00:00:00 2001 From: Hanjun Guo Date: Sat, 27 Jul 2013 11:00:49 +0800 Subject: [PATCH 1071/3400] cpu topology: remove stale arch_provides_topology_pointers and define_siblings_show_map/list() arch_provides_topology_pointers was introduced in commit 23ca4bba3 (x86: cleanup early per cpu variables/accesses v4) to indicate pointers to the topology cpumask_t maps are valid to avoid copying data on to/off of the stack. But later in commit fbd59a8d (cpumask: Use topology_core_cpumask()/ topology_thread_cpumask()), the pointers to the topology struct cpumask maps are always valid. After that commit, the only difference is that there is a redundant "unsigned int cpu = dev->id;" if arch_provides_topology_pointers defined, but dev->id is type 'u32' which devolves to 'unsigned int' on all supported arches. So this arch_provides_topology_pointers define is pointless and only cause obfuscation now, remove it. Tested on x86 machine, topology information in sys/devices/system/cpu/ cpuX/topology/ is the same after appling this patch set. Signed-off-by: Hanjun Guo Signed-off-by: Greg Kroah-Hartman --- drivers/base/topology.c | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/drivers/base/topology.c b/drivers/base/topology.c index 2f5919ed91ab..94ffee378f10 100644 --- a/drivers/base/topology.c +++ b/drivers/base/topology.c @@ -62,25 +62,6 @@ static ssize_t show_cpumap(int type, const struct cpumask *mask, char *buf) } #endif -#ifdef arch_provides_topology_pointers -#define define_siblings_show_map(name) \ -static ssize_t show_##name(struct device *dev, \ - struct device_attribute *attr, char *buf) \ -{ \ - unsigned int cpu = dev->id; \ - return show_cpumap(0, topology_##name(cpu), buf); \ -} - -#define define_siblings_show_list(name) \ -static ssize_t show_##name##_list(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - unsigned int cpu = dev->id; \ - return show_cpumap(1, topology_##name(cpu), buf); \ -} - -#else #define define_siblings_show_map(name) \ static ssize_t show_##name(struct device *dev, \ struct device_attribute *attr, char *buf) \ @@ -95,7 +76,6 @@ static ssize_t show_##name##_list(struct device *dev, \ { \ return show_cpumap(1, topology_##name(dev->id), buf); \ } -#endif #define define_siblings_show_func(name) \ define_siblings_show_map(name); define_siblings_show_list(name) From 76f411fb3a62711de7f59e0f4c56456fe356675a Mon Sep 17 00:00:00 2001 From: Hanjun Guo Date: Sat, 27 Jul 2013 11:00:50 +0800 Subject: [PATCH 1072/3400] x86 / cpu topology: remove the stale macro arch_provides_topology_pointers Macro arch_provides_topology_pointers is pointless now, remove it. Signed-off-by: Hanjun Guo Cc: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- arch/x86/include/asm/topology.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h index 095b21507b6a..d35f24e231cd 100644 --- a/arch/x86/include/asm/topology.h +++ b/arch/x86/include/asm/topology.h @@ -124,9 +124,6 @@ extern const struct cpumask *cpu_coregroup_mask(int cpu); #define topology_core_id(cpu) (cpu_data(cpu).cpu_core_id) #define topology_core_cpumask(cpu) (per_cpu(cpu_core_map, cpu)) #define topology_thread_cpumask(cpu) (per_cpu(cpu_sibling_map, cpu)) - -/* indicates that pointers to the topology cpumask_t maps are valid */ -#define arch_provides_topology_pointers yes #endif static inline void arch_fix_phys_package_id(int num, u32 slot) From e70b0915124942204dec8064bb25756e8723b81a Mon Sep 17 00:00:00 2001 From: Hanjun Guo Date: Sat, 27 Jul 2013 11:00:51 +0800 Subject: [PATCH 1073/3400] tile / cpu topology: remove stale Macro arch_provides_topology_pointers Macro arch_provides_topology_pointers is pointless now, remove it. Signed-off-by: Hanjun Guo Cc: Chris Metcalf Signed-off-by: Greg Kroah-Hartman --- arch/tile/include/asm/topology.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/tile/include/asm/topology.h b/arch/tile/include/asm/topology.h index d5e86c9f74fd..d15c0d8d550f 100644 --- a/arch/tile/include/asm/topology.h +++ b/arch/tile/include/asm/topology.h @@ -89,9 +89,6 @@ static inline const struct cpumask *cpumask_of_node(int node) #define topology_core_id(cpu) (cpu) #define topology_core_cpumask(cpu) ((void)(cpu), cpu_online_mask) #define topology_thread_cpumask(cpu) cpumask_of(cpu) - -/* indicates that pointers to the topology struct cpumask maps are valid */ -#define arch_provides_topology_pointers yes #endif #endif /* _ASM_TILE_TOPOLOGY_H */ From e66c33d579ea566d10e8c8695a7168aae3e02992 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Fri, 12 Jul 2013 16:50:28 -0400 Subject: [PATCH 1074/3400] rcu: Add const annotation to char * for RCU tracepoints and functions All the RCU tracepoints and functions that reference char pointers do so with just 'char *' even though they do not modify the contents of the string itself. This will cause warnings if a const char * is used in one of these functions. The RCU tracepoints store the pointer to the string to refer back to them when the trace output is displayed. As this can be minutes, hours or even days later, those strings had better be constant. This change also opens the door to allow the RCU tracepoint strings and their addresses to be exported so that userspace tracing tools can translate the contents of the pointers of the RCU tracepoints. Signed-off-by: Steven Rostedt --- include/linux/rcupdate.h | 4 +- include/trace/events/rcu.h | 82 +++++++++++++++++++------------------- kernel/rcu.h | 2 +- kernel/rcupdate.c | 2 +- kernel/rcutiny.c | 2 +- kernel/rcutiny_plugin.h | 2 +- kernel/rcutorture.c | 8 ++-- kernel/rcutree.c | 4 +- kernel/rcutree.h | 2 +- 9 files changed, 54 insertions(+), 54 deletions(-) diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index 4b14bdc911d7..0c38abbe6e35 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h @@ -52,7 +52,7 @@ extern int rcutorture_runnable; /* for sysctl */ #if defined(CONFIG_TREE_RCU) || defined(CONFIG_TREE_PREEMPT_RCU) extern void rcutorture_record_test_transition(void); extern void rcutorture_record_progress(unsigned long vernum); -extern void do_trace_rcu_torture_read(char *rcutorturename, +extern void do_trace_rcu_torture_read(const char *rcutorturename, struct rcu_head *rhp, unsigned long secs, unsigned long c_old, @@ -65,7 +65,7 @@ static inline void rcutorture_record_progress(unsigned long vernum) { } #ifdef CONFIG_RCU_TRACE -extern void do_trace_rcu_torture_read(char *rcutorturename, +extern void do_trace_rcu_torture_read(const char *rcutorturename, struct rcu_head *rhp, unsigned long secs, unsigned long c_old, diff --git a/include/trace/events/rcu.h b/include/trace/events/rcu.h index 59ebcc89f148..ee2376cfaab3 100644 --- a/include/trace/events/rcu.h +++ b/include/trace/events/rcu.h @@ -19,12 +19,12 @@ */ TRACE_EVENT(rcu_utilization, - TP_PROTO(char *s), + TP_PROTO(const char *s), TP_ARGS(s), TP_STRUCT__entry( - __field(char *, s) + __field(const char *, s) ), TP_fast_assign( @@ -51,14 +51,14 @@ TRACE_EVENT(rcu_utilization, */ TRACE_EVENT(rcu_grace_period, - TP_PROTO(char *rcuname, unsigned long gpnum, char *gpevent), + TP_PROTO(const char *rcuname, unsigned long gpnum, const char *gpevent), TP_ARGS(rcuname, gpnum, gpevent), TP_STRUCT__entry( - __field(char *, rcuname) + __field(const char *, rcuname) __field(unsigned long, gpnum) - __field(char *, gpevent) + __field(const char *, gpevent) ), TP_fast_assign( @@ -89,21 +89,21 @@ TRACE_EVENT(rcu_grace_period, */ TRACE_EVENT(rcu_future_grace_period, - TP_PROTO(char *rcuname, unsigned long gpnum, unsigned long completed, + TP_PROTO(const char *rcuname, unsigned long gpnum, unsigned long completed, unsigned long c, u8 level, int grplo, int grphi, - char *gpevent), + const char *gpevent), TP_ARGS(rcuname, gpnum, completed, c, level, grplo, grphi, gpevent), TP_STRUCT__entry( - __field(char *, rcuname) + __field(const char *, rcuname) __field(unsigned long, gpnum) __field(unsigned long, completed) __field(unsigned long, c) __field(u8, level) __field(int, grplo) __field(int, grphi) - __field(char *, gpevent) + __field(const char *, gpevent) ), TP_fast_assign( @@ -132,13 +132,13 @@ TRACE_EVENT(rcu_future_grace_period, */ TRACE_EVENT(rcu_grace_period_init, - TP_PROTO(char *rcuname, unsigned long gpnum, u8 level, + TP_PROTO(const char *rcuname, unsigned long gpnum, u8 level, int grplo, int grphi, unsigned long qsmask), TP_ARGS(rcuname, gpnum, level, grplo, grphi, qsmask), TP_STRUCT__entry( - __field(char *, rcuname) + __field(const char *, rcuname) __field(unsigned long, gpnum) __field(u8, level) __field(int, grplo) @@ -168,12 +168,12 @@ TRACE_EVENT(rcu_grace_period_init, */ TRACE_EVENT(rcu_preempt_task, - TP_PROTO(char *rcuname, int pid, unsigned long gpnum), + TP_PROTO(const char *rcuname, int pid, unsigned long gpnum), TP_ARGS(rcuname, pid, gpnum), TP_STRUCT__entry( - __field(char *, rcuname) + __field(const char *, rcuname) __field(unsigned long, gpnum) __field(int, pid) ), @@ -195,12 +195,12 @@ TRACE_EVENT(rcu_preempt_task, */ TRACE_EVENT(rcu_unlock_preempted_task, - TP_PROTO(char *rcuname, unsigned long gpnum, int pid), + TP_PROTO(const char *rcuname, unsigned long gpnum, int pid), TP_ARGS(rcuname, gpnum, pid), TP_STRUCT__entry( - __field(char *, rcuname) + __field(const char *, rcuname) __field(unsigned long, gpnum) __field(int, pid) ), @@ -224,14 +224,14 @@ TRACE_EVENT(rcu_unlock_preempted_task, */ TRACE_EVENT(rcu_quiescent_state_report, - TP_PROTO(char *rcuname, unsigned long gpnum, + TP_PROTO(const char *rcuname, unsigned long gpnum, unsigned long mask, unsigned long qsmask, u8 level, int grplo, int grphi, int gp_tasks), TP_ARGS(rcuname, gpnum, mask, qsmask, level, grplo, grphi, gp_tasks), TP_STRUCT__entry( - __field(char *, rcuname) + __field(const char *, rcuname) __field(unsigned long, gpnum) __field(unsigned long, mask) __field(unsigned long, qsmask) @@ -268,15 +268,15 @@ TRACE_EVENT(rcu_quiescent_state_report, */ TRACE_EVENT(rcu_fqs, - TP_PROTO(char *rcuname, unsigned long gpnum, int cpu, char *qsevent), + TP_PROTO(const char *rcuname, unsigned long gpnum, int cpu, const char *qsevent), TP_ARGS(rcuname, gpnum, cpu, qsevent), TP_STRUCT__entry( - __field(char *, rcuname) + __field(const char *, rcuname) __field(unsigned long, gpnum) __field(int, cpu) - __field(char *, qsevent) + __field(const char *, qsevent) ), TP_fast_assign( @@ -308,12 +308,12 @@ TRACE_EVENT(rcu_fqs, */ TRACE_EVENT(rcu_dyntick, - TP_PROTO(char *polarity, long long oldnesting, long long newnesting), + TP_PROTO(const char *polarity, long long oldnesting, long long newnesting), TP_ARGS(polarity, oldnesting, newnesting), TP_STRUCT__entry( - __field(char *, polarity) + __field(const char *, polarity) __field(long long, oldnesting) __field(long long, newnesting) ), @@ -352,12 +352,12 @@ TRACE_EVENT(rcu_dyntick, */ TRACE_EVENT(rcu_prep_idle, - TP_PROTO(char *reason), + TP_PROTO(const char *reason), TP_ARGS(reason), TP_STRUCT__entry( - __field(char *, reason) + __field(const char *, reason) ), TP_fast_assign( @@ -376,13 +376,13 @@ TRACE_EVENT(rcu_prep_idle, */ TRACE_EVENT(rcu_callback, - TP_PROTO(char *rcuname, struct rcu_head *rhp, long qlen_lazy, + TP_PROTO(const char *rcuname, struct rcu_head *rhp, long qlen_lazy, long qlen), TP_ARGS(rcuname, rhp, qlen_lazy, qlen), TP_STRUCT__entry( - __field(char *, rcuname) + __field(const char *, rcuname) __field(void *, rhp) __field(void *, func) __field(long, qlen_lazy) @@ -412,13 +412,13 @@ TRACE_EVENT(rcu_callback, */ TRACE_EVENT(rcu_kfree_callback, - TP_PROTO(char *rcuname, struct rcu_head *rhp, unsigned long offset, + TP_PROTO(const char *rcuname, struct rcu_head *rhp, unsigned long offset, long qlen_lazy, long qlen), TP_ARGS(rcuname, rhp, offset, qlen_lazy, qlen), TP_STRUCT__entry( - __field(char *, rcuname) + __field(const char *, rcuname) __field(void *, rhp) __field(unsigned long, offset) __field(long, qlen_lazy) @@ -447,12 +447,12 @@ TRACE_EVENT(rcu_kfree_callback, */ TRACE_EVENT(rcu_batch_start, - TP_PROTO(char *rcuname, long qlen_lazy, long qlen, long blimit), + TP_PROTO(const char *rcuname, long qlen_lazy, long qlen, long blimit), TP_ARGS(rcuname, qlen_lazy, qlen, blimit), TP_STRUCT__entry( - __field(char *, rcuname) + __field(const char *, rcuname) __field(long, qlen_lazy) __field(long, qlen) __field(long, blimit) @@ -477,12 +477,12 @@ TRACE_EVENT(rcu_batch_start, */ TRACE_EVENT(rcu_invoke_callback, - TP_PROTO(char *rcuname, struct rcu_head *rhp), + TP_PROTO(const char *rcuname, struct rcu_head *rhp), TP_ARGS(rcuname, rhp), TP_STRUCT__entry( - __field(char *, rcuname) + __field(const char *, rcuname) __field(void *, rhp) __field(void *, func) ), @@ -506,12 +506,12 @@ TRACE_EVENT(rcu_invoke_callback, */ TRACE_EVENT(rcu_invoke_kfree_callback, - TP_PROTO(char *rcuname, struct rcu_head *rhp, unsigned long offset), + TP_PROTO(const char *rcuname, struct rcu_head *rhp, unsigned long offset), TP_ARGS(rcuname, rhp, offset), TP_STRUCT__entry( - __field(char *, rcuname) + __field(const char *, rcuname) __field(void *, rhp) __field(unsigned long, offset) ), @@ -539,13 +539,13 @@ TRACE_EVENT(rcu_invoke_kfree_callback, */ TRACE_EVENT(rcu_batch_end, - TP_PROTO(char *rcuname, int callbacks_invoked, + TP_PROTO(const char *rcuname, int callbacks_invoked, bool cb, bool nr, bool iit, bool risk), TP_ARGS(rcuname, callbacks_invoked, cb, nr, iit, risk), TP_STRUCT__entry( - __field(char *, rcuname) + __field(const char *, rcuname) __field(int, callbacks_invoked) __field(bool, cb) __field(bool, nr) @@ -577,13 +577,13 @@ TRACE_EVENT(rcu_batch_end, */ TRACE_EVENT(rcu_torture_read, - TP_PROTO(char *rcutorturename, struct rcu_head *rhp, + TP_PROTO(const char *rcutorturename, struct rcu_head *rhp, unsigned long secs, unsigned long c_old, unsigned long c), TP_ARGS(rcutorturename, rhp, secs, c_old, c), TP_STRUCT__entry( - __field(char *, rcutorturename) + __field(const char *, rcutorturename) __field(struct rcu_head *, rhp) __field(unsigned long, secs) __field(unsigned long, c_old) @@ -623,13 +623,13 @@ TRACE_EVENT(rcu_torture_read, */ TRACE_EVENT(rcu_barrier, - TP_PROTO(char *rcuname, char *s, int cpu, int cnt, unsigned long done), + TP_PROTO(const char *rcuname, const char *s, int cpu, int cnt, unsigned long done), TP_ARGS(rcuname, s, cpu, cnt, done), TP_STRUCT__entry( - __field(char *, rcuname) - __field(char *, s) + __field(const char *, rcuname) + __field(const char *, s) __field(int, cpu) __field(int, cnt) __field(unsigned long, done) diff --git a/kernel/rcu.h b/kernel/rcu.h index 7f8e7590e3e5..0a90ccc65bfb 100644 --- a/kernel/rcu.h +++ b/kernel/rcu.h @@ -94,7 +94,7 @@ static inline void debug_rcu_head_unqueue(struct rcu_head *head) extern void kfree(const void *); -static inline bool __rcu_reclaim(char *rn, struct rcu_head *head) +static inline bool __rcu_reclaim(const char *rn, struct rcu_head *head) { unsigned long offset = (unsigned long)head->func; diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c index cce6ba8bbace..14994d4e1a54 100644 --- a/kernel/rcupdate.c +++ b/kernel/rcupdate.c @@ -377,7 +377,7 @@ EXPORT_SYMBOL_GPL(rcuhead_debug_descr); #endif /* #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD */ #if defined(CONFIG_TREE_RCU) || defined(CONFIG_TREE_PREEMPT_RCU) || defined(CONFIG_RCU_TRACE) -void do_trace_rcu_torture_read(char *rcutorturename, struct rcu_head *rhp, +void do_trace_rcu_torture_read(const char *rcutorturename, struct rcu_head *rhp, unsigned long secs, unsigned long c_old, unsigned long c) { diff --git a/kernel/rcutiny.c b/kernel/rcutiny.c index aa344111de3e..9ed6075dc562 100644 --- a/kernel/rcutiny.c +++ b/kernel/rcutiny.c @@ -264,7 +264,7 @@ void rcu_check_callbacks(int cpu, int user) */ static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp) { - char *rn = NULL; + const char *rn = NULL; struct rcu_head *next, *list; unsigned long flags; RCU_TRACE(int cb_count = 0); diff --git a/kernel/rcutiny_plugin.h b/kernel/rcutiny_plugin.h index 0cd385acccfa..280d06cae352 100644 --- a/kernel/rcutiny_plugin.h +++ b/kernel/rcutiny_plugin.h @@ -36,7 +36,7 @@ struct rcu_ctrlblk { RCU_TRACE(unsigned long gp_start); /* Start time for stalls. */ RCU_TRACE(unsigned long ticks_this_gp); /* Statistic for stalls. */ RCU_TRACE(unsigned long jiffies_stall); /* Jiffies at next stall. */ - RCU_TRACE(char *name); /* Name of RCU type. */ + RCU_TRACE(const char *name); /* Name of RCU type. */ }; /* Definition for rcupdate control block. */ diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c index f4871e52c546..3d936f0fbcd8 100644 --- a/kernel/rcutorture.c +++ b/kernel/rcutorture.c @@ -267,7 +267,7 @@ rcutorture_shutdown_notify(struct notifier_block *unused1, * Absorb kthreads into a kernel function that won't return, so that * they won't ever access module text or data again. */ -static void rcutorture_shutdown_absorb(char *title) +static void rcutorture_shutdown_absorb(const char *title) { if (ACCESS_ONCE(fullstop) == FULLSTOP_SHUTDOWN) { pr_notice( @@ -337,7 +337,7 @@ rcu_random(struct rcu_random_state *rrsp) } static void -rcu_stutter_wait(char *title) +rcu_stutter_wait(const char *title) { while (stutter_pause_test || !rcutorture_runnable) { if (rcutorture_runnable) @@ -366,7 +366,7 @@ struct rcu_torture_ops { int (*stats)(char *page); int irq_capable; int can_boost; - char *name; + const char *name; }; static struct rcu_torture_ops *cur_ops; @@ -1364,7 +1364,7 @@ rcu_torture_stutter(void *arg) } static inline void -rcu_torture_print_module_parms(struct rcu_torture_ops *cur_ops, char *tag) +rcu_torture_print_module_parms(struct rcu_torture_ops *cur_ops, const char *tag) { pr_alert("%s" TORTURE_FLAG "--- %s: nreaders=%d nfakewriters=%d " diff --git a/kernel/rcutree.c b/kernel/rcutree.c index 068de3a93606..30201494560b 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -1032,7 +1032,7 @@ static unsigned long rcu_cbs_completed(struct rcu_state *rsp, * rcu_nocb_wait_gp(). */ static void trace_rcu_future_gp(struct rcu_node *rnp, struct rcu_data *rdp, - unsigned long c, char *s) + unsigned long c, const char *s) { trace_rcu_future_grace_period(rdp->rsp->name, rnp->gpnum, rnp->completed, c, rnp->level, @@ -2720,7 +2720,7 @@ static int rcu_cpu_has_callbacks(int cpu, bool *all_lazy) * Helper function for _rcu_barrier() tracing. If tracing is disabled, * the compiler is expected to optimize this away. */ -static void _rcu_barrier_trace(struct rcu_state *rsp, char *s, +static void _rcu_barrier_trace(struct rcu_state *rsp, const char *s, int cpu, unsigned long done) { trace_rcu_barrier(rsp->name, s, cpu, diff --git a/kernel/rcutree.h b/kernel/rcutree.h index b3832581043c..cbdeac6cea9e 100644 --- a/kernel/rcutree.h +++ b/kernel/rcutree.h @@ -445,7 +445,7 @@ struct rcu_state { /* for CPU stalls. */ unsigned long gp_max; /* Maximum GP duration in */ /* jiffies. */ - char *name; /* Name of structure. */ + const char *name; /* Name of structure. */ char abbr; /* Abbreviated name. */ struct list_head flavors; /* List of RCU flavors. */ struct irq_work wakeup_work; /* Postponed wakeups */ From a41bfeb2f8ed59410be7ca0f8fbc6138a758b746 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Fri, 12 Jul 2013 17:00:28 -0400 Subject: [PATCH 1075/3400] rcu: Simplify RCU_STATE_INITIALIZER() macro The RCU_STATE_INITIALIZER() macro is used only in the rcutree.c file as well as the rcutree_plugin.h file. It is passed as a rvalue to a variable of a similar name. A per_cpu variable is also created with a similar name as well. The uses of RCU_STATE_INITIALIZER() can be simplified to remove some of the duplicate code that is done. Currently the three users of this macro has this format: struct rcu_state rcu_sched_state = RCU_STATE_INITIALIZER(rcu_sched, call_rcu_sched); DEFINE_PER_CPU(struct rcu_data, rcu_sched_data); Notice that "rcu_sched" is called three times. This is the same with the other two users. This can be condensed to just: RCU_STATE_INITIALIZER(rcu_sched, call_rcu_sched); by moving the rest into the macro itself. This also opens the door to allow the RCU tracepoint strings and their addresses to be exported so that userspace tracing tools can translate the contents of the pointers of the RCU tracepoints. The change will allow for helper code to be placed in the RCU_STATE_INITIALIZER() macro to export the name that is used. Signed-off-by: Steven Rostedt --- kernel/rcutree.c | 14 ++++++-------- kernel/rcutree_plugin.h | 4 +--- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/kernel/rcutree.c b/kernel/rcutree.c index 30201494560b..97994a329d80 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -64,7 +64,8 @@ static struct lock_class_key rcu_node_class[RCU_NUM_LVLS]; static struct lock_class_key rcu_fqs_class[RCU_NUM_LVLS]; -#define RCU_STATE_INITIALIZER(sname, sabbr, cr) { \ +#define RCU_STATE_INITIALIZER(sname, sabbr, cr) \ +struct rcu_state sname##_state = { \ .level = { &sname##_state.node[0] }, \ .call = cr, \ .fqs_state = RCU_GP_IDLE, \ @@ -77,14 +78,11 @@ static struct lock_class_key rcu_fqs_class[RCU_NUM_LVLS]; .onoff_mutex = __MUTEX_INITIALIZER(sname##_state.onoff_mutex), \ .name = #sname, \ .abbr = sabbr, \ -} +}; \ +DEFINE_PER_CPU(struct rcu_data, sname##_data) -struct rcu_state rcu_sched_state = - RCU_STATE_INITIALIZER(rcu_sched, 's', call_rcu_sched); -DEFINE_PER_CPU(struct rcu_data, rcu_sched_data); - -struct rcu_state rcu_bh_state = RCU_STATE_INITIALIZER(rcu_bh, 'b', call_rcu_bh); -DEFINE_PER_CPU(struct rcu_data, rcu_bh_data); +RCU_STATE_INITIALIZER(rcu_sched, 's', call_rcu_sched); +RCU_STATE_INITIALIZER(rcu_bh, 'b', call_rcu_bh); static struct rcu_state *rcu_state; LIST_HEAD(rcu_struct_flavors); diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h index 769e12e3151b..6976a7dde874 100644 --- a/kernel/rcutree_plugin.h +++ b/kernel/rcutree_plugin.h @@ -110,9 +110,7 @@ static void __init rcu_bootup_announce_oddness(void) #ifdef CONFIG_TREE_PREEMPT_RCU -struct rcu_state rcu_preempt_state = - RCU_STATE_INITIALIZER(rcu_preempt, 'p', call_rcu); -DEFINE_PER_CPU(struct rcu_data, rcu_preempt_data); +RCU_STATE_INITIALIZER(rcu_preempt, 'p', call_rcu); static struct rcu_state *rcu_state = &rcu_preempt_state; static int rcu_preempted_readers_exp(struct rcu_node *rnp); From f7f7bac9cb1c50783f15937a11743655a5756a36 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Fri, 12 Jul 2013 17:18:47 -0400 Subject: [PATCH 1076/3400] rcu: Have the RCU tracepoints use the tracepoint_string infrastructure Currently, RCU tracepoints save only a pointer to strings in the ring buffer. When displayed via the /sys/kernel/debug/tracing/trace file they are referenced like the printf "%s" that looks at the address in the ring buffer and prints out the string it points too. This requires that the strings are constant and persistent in the kernel. The problem with this is for tools like trace-cmd and perf that read the binary data from the buffers but have no access to the kernel memory to find out what string is represented by the address in the buffer. By using the tracepoint_string infrastructure, the RCU tracepoint strings can be exported such that userspace tools can map the addresses to the strings. # cat /sys/kernel/debug/tracing/printk_formats 0xffffffff81a4a0e8 : "rcu_preempt" 0xffffffff81a4a0f4 : "rcu_bh" 0xffffffff81a4a100 : "rcu_sched" 0xffffffff818437a0 : "cpuqs" 0xffffffff818437a6 : "rcu_sched" 0xffffffff818437a0 : "cpuqs" 0xffffffff818437b0 : "rcu_bh" 0xffffffff818437b7 : "Start context switch" 0xffffffff818437cc : "End context switch" 0xffffffff818437a0 : "cpuqs" [...] Now userspaces tools can display: rcu_utilization: Start context switch rcu_dyntick: Start 1 0 rcu_utilization: End context switch rcu_batch_start: rcu_preempt CBs=0/5 bl=10 rcu_dyntick: End 0 140000000000000 rcu_invoke_callback: rcu_preempt rhp=0xffff880071c0d600 func=proc_i_callback rcu_invoke_callback: rcu_preempt rhp=0xffff880077b5b230 func=__d_free rcu_dyntick: Start 140000000000000 0 rcu_invoke_callback: rcu_preempt rhp=0xffff880077563980 func=file_free_rcu rcu_batch_end: rcu_preempt CBs-invoked=3 idle=>c<>c<>c<>c< rcu_utilization: End RCU core rcu_grace_period: rcu_preempt 9741 start rcu_dyntick: Start 1 0 rcu_dyntick: End 0 140000000000000 rcu_dyntick: Start 140000000000000 0 Instead of: rcu_utilization: ffffffff81843110 rcu_future_grace_period: ffffffff81842f1d 9939 9939 9940 0 0 3 ffffffff81842f32 rcu_batch_start: ffffffff81842f1d CBs=0/4 bl=10 rcu_future_grace_period: ffffffff81842f1d 9939 9939 9940 0 0 3 ffffffff81842f3c rcu_grace_period: ffffffff81842f1d 9939 ffffffff81842f80 rcu_invoke_callback: ffffffff81842f1d rhp=0xffff88007888aac0 func=file_free_rcu rcu_grace_period: ffffffff81842f1d 9939 ffffffff81842f95 rcu_invoke_callback: ffffffff81842f1d rhp=0xffff88006aeb4600 func=proc_i_callback rcu_future_grace_period: ffffffff81842f1d 9939 9939 9940 0 0 3 ffffffff81842f32 rcu_future_grace_period: ffffffff81842f1d 9939 9939 9940 0 0 3 ffffffff81842f3c rcu_invoke_callback: ffffffff81842f1d rhp=0xffff880071cb9fc0 func=__d_free rcu_grace_period: ffffffff81842f1d 9939 ffffffff81842f80 rcu_invoke_callback: ffffffff81842f1d rhp=0xffff88007888ae80 func=file_free_rcu rcu_batch_end: ffffffff81842f1d CBs-invoked=4 idle=>c<>c<>c<>c< rcu_utilization: ffffffff8184311f Signed-off-by: Steven Rostedt --- kernel/rcutree.c | 87 +++++++++++++++++++++++++---------------- kernel/rcutree_plugin.h | 32 +++++++-------- 2 files changed, 69 insertions(+), 50 deletions(-) diff --git a/kernel/rcutree.c b/kernel/rcutree.c index 97994a329d80..338f1d1c1c66 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -53,18 +53,36 @@ #include #include #include +#include #include "rcutree.h" #include #include "rcu.h" +/* + * Strings used in tracepoints need to be exported via the + * tracing system such that tools like perf and trace-cmd can + * translate the string address pointers to actual text. + */ +#define TPS(x) tracepoint_string(x) + /* Data structures. */ static struct lock_class_key rcu_node_class[RCU_NUM_LVLS]; static struct lock_class_key rcu_fqs_class[RCU_NUM_LVLS]; +/* + * In order to export the rcu_state name to the tracing tools, it + * needs to be added in the __tracepoint_string section. + * This requires defining a separate variable tp__varname + * that points to the string being used, and this will allow + * the tracing userspace tools to be able to decipher the string + * address to the matching string. + */ #define RCU_STATE_INITIALIZER(sname, sabbr, cr) \ +static char sname##_varname[] = #sname; \ +static const char *tp_##sname##_varname __used __tracepoint_string = sname##_varname; \ struct rcu_state sname##_state = { \ .level = { &sname##_state.node[0] }, \ .call = cr, \ @@ -76,7 +94,7 @@ struct rcu_state sname##_state = { \ .orphan_donetail = &sname##_state.orphan_donelist, \ .barrier_mutex = __MUTEX_INITIALIZER(sname##_state.barrier_mutex), \ .onoff_mutex = __MUTEX_INITIALIZER(sname##_state.onoff_mutex), \ - .name = #sname, \ + .name = sname##_varname, \ .abbr = sabbr, \ }; \ DEFINE_PER_CPU(struct rcu_data, sname##_data) @@ -176,7 +194,7 @@ void rcu_sched_qs(int cpu) struct rcu_data *rdp = &per_cpu(rcu_sched_data, cpu); if (rdp->passed_quiesce == 0) - trace_rcu_grace_period("rcu_sched", rdp->gpnum, "cpuqs"); + trace_rcu_grace_period(TPS("rcu_sched"), rdp->gpnum, TPS("cpuqs")); rdp->passed_quiesce = 1; } @@ -185,7 +203,7 @@ void rcu_bh_qs(int cpu) struct rcu_data *rdp = &per_cpu(rcu_bh_data, cpu); if (rdp->passed_quiesce == 0) - trace_rcu_grace_period("rcu_bh", rdp->gpnum, "cpuqs"); + trace_rcu_grace_period(TPS("rcu_bh"), rdp->gpnum, TPS("cpuqs")); rdp->passed_quiesce = 1; } @@ -196,10 +214,10 @@ void rcu_bh_qs(int cpu) */ void rcu_note_context_switch(int cpu) { - trace_rcu_utilization("Start context switch"); + trace_rcu_utilization(TPS("Start context switch")); rcu_sched_qs(cpu); rcu_preempt_note_context_switch(cpu); - trace_rcu_utilization("End context switch"); + trace_rcu_utilization(TPS("End context switch")); } EXPORT_SYMBOL_GPL(rcu_note_context_switch); @@ -343,11 +361,11 @@ static struct rcu_node *rcu_get_root(struct rcu_state *rsp) static void rcu_eqs_enter_common(struct rcu_dynticks *rdtp, long long oldval, bool user) { - trace_rcu_dyntick("Start", oldval, rdtp->dynticks_nesting); + trace_rcu_dyntick(TPS("Start"), oldval, rdtp->dynticks_nesting); if (!user && !is_idle_task(current)) { struct task_struct *idle = idle_task(smp_processor_id()); - trace_rcu_dyntick("Error on entry: not idle task", oldval, 0); + trace_rcu_dyntick(TPS("Error on entry: not idle task"), oldval, 0); ftrace_dump(DUMP_ORIG); WARN_ONCE(1, "Current pid: %d comm: %s / Idle pid: %d comm: %s", current->pid, current->comm, @@ -477,7 +495,7 @@ void rcu_irq_exit(void) rdtp->dynticks_nesting--; WARN_ON_ONCE(rdtp->dynticks_nesting < 0); if (rdtp->dynticks_nesting) - trace_rcu_dyntick("--=", oldval, rdtp->dynticks_nesting); + trace_rcu_dyntick(TPS("--="), oldval, rdtp->dynticks_nesting); else rcu_eqs_enter_common(rdtp, oldval, true); local_irq_restore(flags); @@ -499,11 +517,11 @@ static void rcu_eqs_exit_common(struct rcu_dynticks *rdtp, long long oldval, smp_mb__after_atomic_inc(); /* See above. */ WARN_ON_ONCE(!(atomic_read(&rdtp->dynticks) & 0x1)); rcu_cleanup_after_idle(smp_processor_id()); - trace_rcu_dyntick("End", oldval, rdtp->dynticks_nesting); + trace_rcu_dyntick(TPS("End"), oldval, rdtp->dynticks_nesting); if (!user && !is_idle_task(current)) { struct task_struct *idle = idle_task(smp_processor_id()); - trace_rcu_dyntick("Error on exit: not idle task", + trace_rcu_dyntick(TPS("Error on exit: not idle task"), oldval, rdtp->dynticks_nesting); ftrace_dump(DUMP_ORIG); WARN_ONCE(1, "Current pid: %d comm: %s / Idle pid: %d comm: %s", @@ -618,7 +636,7 @@ void rcu_irq_enter(void) rdtp->dynticks_nesting++; WARN_ON_ONCE(rdtp->dynticks_nesting == 0); if (oldval) - trace_rcu_dyntick("++=", oldval, rdtp->dynticks_nesting); + trace_rcu_dyntick(TPS("++="), oldval, rdtp->dynticks_nesting); else rcu_eqs_exit_common(rdtp, oldval, true); local_irq_restore(flags); @@ -773,7 +791,7 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp) * of the current RCU grace period. */ if ((curr & 0x1) == 0 || UINT_CMP_GE(curr, snap + 2)) { - trace_rcu_fqs(rdp->rsp->name, rdp->gpnum, rdp->cpu, "dti"); + trace_rcu_fqs(rdp->rsp->name, rdp->gpnum, rdp->cpu, TPS("dti")); rdp->dynticks_fqs++; return 1; } @@ -793,7 +811,7 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp) return 0; /* Grace period is not old enough. */ barrier(); if (cpu_is_offline(rdp->cpu)) { - trace_rcu_fqs(rdp->rsp->name, rdp->gpnum, rdp->cpu, "ofl"); + trace_rcu_fqs(rdp->rsp->name, rdp->gpnum, rdp->cpu, TPS("ofl")); rdp->offline_fqs++; return 1; } @@ -1056,9 +1074,9 @@ rcu_start_future_gp(struct rcu_node *rnp, struct rcu_data *rdp) * grace period is already marked as needed, return to the caller. */ c = rcu_cbs_completed(rdp->rsp, rnp); - trace_rcu_future_gp(rnp, rdp, c, "Startleaf"); + trace_rcu_future_gp(rnp, rdp, c, TPS("Startleaf")); if (rnp->need_future_gp[c & 0x1]) { - trace_rcu_future_gp(rnp, rdp, c, "Prestartleaf"); + trace_rcu_future_gp(rnp, rdp, c, TPS("Prestartleaf")); return c; } @@ -1072,7 +1090,7 @@ rcu_start_future_gp(struct rcu_node *rnp, struct rcu_data *rdp) if (rnp->gpnum != rnp->completed || ACCESS_ONCE(rnp->gpnum) != ACCESS_ONCE(rnp->completed)) { rnp->need_future_gp[c & 0x1]++; - trace_rcu_future_gp(rnp, rdp, c, "Startedleaf"); + trace_rcu_future_gp(rnp, rdp, c, TPS("Startedleaf")); return c; } @@ -1100,7 +1118,7 @@ rcu_start_future_gp(struct rcu_node *rnp, struct rcu_data *rdp) * recorded, trace and leave. */ if (rnp_root->need_future_gp[c & 0x1]) { - trace_rcu_future_gp(rnp, rdp, c, "Prestartedroot"); + trace_rcu_future_gp(rnp, rdp, c, TPS("Prestartedroot")); goto unlock_out; } @@ -1109,9 +1127,9 @@ rcu_start_future_gp(struct rcu_node *rnp, struct rcu_data *rdp) /* If a grace period is not already in progress, start one. */ if (rnp_root->gpnum != rnp_root->completed) { - trace_rcu_future_gp(rnp, rdp, c, "Startedleafroot"); + trace_rcu_future_gp(rnp, rdp, c, TPS("Startedleafroot")); } else { - trace_rcu_future_gp(rnp, rdp, c, "Startedroot"); + trace_rcu_future_gp(rnp, rdp, c, TPS("Startedroot")); rcu_start_gp_advanced(rdp->rsp, rnp_root, rdp); } unlock_out: @@ -1135,7 +1153,8 @@ static int rcu_future_gp_cleanup(struct rcu_state *rsp, struct rcu_node *rnp) rcu_nocb_gp_cleanup(rsp, rnp); rnp->need_future_gp[c & 0x1] = 0; needmore = rnp->need_future_gp[(c + 1) & 0x1]; - trace_rcu_future_gp(rnp, rdp, c, needmore ? "CleanupMore" : "Cleanup"); + trace_rcu_future_gp(rnp, rdp, c, + needmore ? TPS("CleanupMore") : TPS("Cleanup")); return needmore; } @@ -1203,9 +1222,9 @@ static void rcu_accelerate_cbs(struct rcu_state *rsp, struct rcu_node *rnp, /* Trace depending on how much we were able to accelerate. */ if (!*rdp->nxttail[RCU_WAIT_TAIL]) - trace_rcu_grace_period(rsp->name, rdp->gpnum, "AccWaitCB"); + trace_rcu_grace_period(rsp->name, rdp->gpnum, TPS("AccWaitCB")); else - trace_rcu_grace_period(rsp->name, rdp->gpnum, "AccReadyCB"); + trace_rcu_grace_period(rsp->name, rdp->gpnum, TPS("AccReadyCB")); } /* @@ -1271,7 +1290,7 @@ static void __note_gp_changes(struct rcu_state *rsp, struct rcu_node *rnp, struc /* Remember that we saw this grace-period completion. */ rdp->completed = rnp->completed; - trace_rcu_grace_period(rsp->name, rdp->gpnum, "cpuend"); + trace_rcu_grace_period(rsp->name, rdp->gpnum, TPS("cpuend")); } if (rdp->gpnum != rnp->gpnum) { @@ -1281,7 +1300,7 @@ static void __note_gp_changes(struct rcu_state *rsp, struct rcu_node *rnp, struc * go looking for one. */ rdp->gpnum = rnp->gpnum; - trace_rcu_grace_period(rsp->name, rdp->gpnum, "cpustart"); + trace_rcu_grace_period(rsp->name, rdp->gpnum, TPS("cpustart")); rdp->passed_quiesce = 0; rdp->qs_pending = !!(rnp->qsmask & rdp->grpmask); zero_cpu_stall_ticks(rdp); @@ -1324,7 +1343,7 @@ static int rcu_gp_init(struct rcu_state *rsp) /* Advance to a new grace period and initialize state. */ rsp->gpnum++; - trace_rcu_grace_period(rsp->name, rsp->gpnum, "start"); + trace_rcu_grace_period(rsp->name, rsp->gpnum, TPS("start")); record_gp_stall_check_time(rsp); raw_spin_unlock_irq(&rnp->lock); @@ -1446,7 +1465,7 @@ static void rcu_gp_cleanup(struct rcu_state *rsp) rcu_nocb_gp_set(rnp, nocb); rsp->completed = rsp->gpnum; /* Declare grace period done. */ - trace_rcu_grace_period(rsp->name, rsp->completed, "end"); + trace_rcu_grace_period(rsp->name, rsp->completed, TPS("end")); rsp->fqs_state = RCU_GP_IDLE; rdp = this_cpu_ptr(rsp->rda); rcu_advance_cbs(rsp, rnp, rdp); /* Reduce false positives below. */ @@ -1855,7 +1874,7 @@ static void rcu_cleanup_dying_cpu(struct rcu_state *rsp) RCU_TRACE(mask = rdp->grpmask); trace_rcu_grace_period(rsp->name, rnp->gpnum + 1 - !!(rnp->qsmask & mask), - "cpuofl"); + TPS("cpuofl")); } /* @@ -2042,7 +2061,7 @@ static void rcu_do_batch(struct rcu_state *rsp, struct rcu_data *rdp) */ void rcu_check_callbacks(int cpu, int user) { - trace_rcu_utilization("Start scheduler-tick"); + trace_rcu_utilization(TPS("Start scheduler-tick")); increment_cpu_stall_ticks(); if (user || rcu_is_cpu_rrupt_from_idle()) { @@ -2075,7 +2094,7 @@ void rcu_check_callbacks(int cpu, int user) rcu_preempt_check_callbacks(cpu); if (rcu_pending(cpu)) invoke_rcu_core(); - trace_rcu_utilization("End scheduler-tick"); + trace_rcu_utilization(TPS("End scheduler-tick")); } /* @@ -2206,10 +2225,10 @@ static void rcu_process_callbacks(struct softirq_action *unused) if (cpu_is_offline(smp_processor_id())) return; - trace_rcu_utilization("Start RCU core"); + trace_rcu_utilization(TPS("Start RCU core")); for_each_rcu_flavor(rsp) __rcu_process_callbacks(rsp); - trace_rcu_utilization("End RCU core"); + trace_rcu_utilization(TPS("End RCU core")); } /* @@ -2950,7 +2969,7 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptible) rdp->completed = rnp->completed; rdp->passed_quiesce = 0; rdp->qs_pending = 0; - trace_rcu_grace_period(rsp->name, rdp->gpnum, "cpuonl"); + trace_rcu_grace_period(rsp->name, rdp->gpnum, TPS("cpuonl")); } raw_spin_unlock(&rnp->lock); /* irqs already disabled. */ rnp = rnp->parent; @@ -2980,7 +2999,7 @@ static int rcu_cpu_notify(struct notifier_block *self, struct rcu_node *rnp = rdp->mynode; struct rcu_state *rsp; - trace_rcu_utilization("Start CPU hotplug"); + trace_rcu_utilization(TPS("Start CPU hotplug")); switch (action) { case CPU_UP_PREPARE: case CPU_UP_PREPARE_FROZEN: @@ -3009,7 +3028,7 @@ static int rcu_cpu_notify(struct notifier_block *self, default: break; } - trace_rcu_utilization("End CPU hotplug"); + trace_rcu_utilization(TPS("End CPU hotplug")); return NOTIFY_OK; } diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h index 6976a7dde874..dff86f53ee09 100644 --- a/kernel/rcutree_plugin.h +++ b/kernel/rcutree_plugin.h @@ -167,7 +167,7 @@ static void rcu_preempt_qs(int cpu) struct rcu_data *rdp = &per_cpu(rcu_preempt_data, cpu); if (rdp->passed_quiesce == 0) - trace_rcu_grace_period("rcu_preempt", rdp->gpnum, "cpuqs"); + trace_rcu_grace_period(TPS("rcu_preempt"), rdp->gpnum, TPS("cpuqs")); rdp->passed_quiesce = 1; current->rcu_read_unlock_special &= ~RCU_READ_UNLOCK_NEED_QS; } @@ -386,7 +386,7 @@ void rcu_read_unlock_special(struct task_struct *t) np = rcu_next_node_entry(t, rnp); list_del_init(&t->rcu_node_entry); t->rcu_blocked_node = NULL; - trace_rcu_unlock_preempted_task("rcu_preempt", + trace_rcu_unlock_preempted_task(TPS("rcu_preempt"), rnp->gpnum, t->pid); if (&t->rcu_node_entry == rnp->gp_tasks) rnp->gp_tasks = np; @@ -410,7 +410,7 @@ void rcu_read_unlock_special(struct task_struct *t) */ empty_exp_now = !rcu_preempted_readers_exp(rnp); if (!empty && !rcu_preempt_blocked_readers_cgp(rnp)) { - trace_rcu_quiescent_state_report("preempt_rcu", + trace_rcu_quiescent_state_report(TPS("preempt_rcu"), rnp->gpnum, 0, rnp->qsmask, rnp->level, @@ -1248,12 +1248,12 @@ static int rcu_boost_kthread(void *arg) int spincnt = 0; int more2boost; - trace_rcu_utilization("Start boost kthread@init"); + trace_rcu_utilization(TPS("Start boost kthread@init")); for (;;) { rnp->boost_kthread_status = RCU_KTHREAD_WAITING; - trace_rcu_utilization("End boost kthread@rcu_wait"); + trace_rcu_utilization(TPS("End boost kthread@rcu_wait")); rcu_wait(rnp->boost_tasks || rnp->exp_tasks); - trace_rcu_utilization("Start boost kthread@rcu_wait"); + trace_rcu_utilization(TPS("Start boost kthread@rcu_wait")); rnp->boost_kthread_status = RCU_KTHREAD_RUNNING; more2boost = rcu_boost(rnp); if (more2boost) @@ -1262,14 +1262,14 @@ static int rcu_boost_kthread(void *arg) spincnt = 0; if (spincnt > 10) { rnp->boost_kthread_status = RCU_KTHREAD_YIELDING; - trace_rcu_utilization("End boost kthread@rcu_yield"); + trace_rcu_utilization(TPS("End boost kthread@rcu_yield")); schedule_timeout_interruptible(2); - trace_rcu_utilization("Start boost kthread@rcu_yield"); + trace_rcu_utilization(TPS("Start boost kthread@rcu_yield")); spincnt = 0; } } /* NOTREACHED */ - trace_rcu_utilization("End boost kthread@notreached"); + trace_rcu_utilization(TPS("End boost kthread@notreached")); return 0; } @@ -1417,7 +1417,7 @@ static void rcu_cpu_kthread(unsigned int cpu) int spincnt; for (spincnt = 0; spincnt < 10; spincnt++) { - trace_rcu_utilization("Start CPU kthread@rcu_wait"); + trace_rcu_utilization(TPS("Start CPU kthread@rcu_wait")); local_bh_disable(); *statusp = RCU_KTHREAD_RUNNING; this_cpu_inc(rcu_cpu_kthread_loops); @@ -1429,15 +1429,15 @@ static void rcu_cpu_kthread(unsigned int cpu) rcu_kthread_do_work(); local_bh_enable(); if (*workp == 0) { - trace_rcu_utilization("End CPU kthread@rcu_wait"); + trace_rcu_utilization(TPS("End CPU kthread@rcu_wait")); *statusp = RCU_KTHREAD_WAITING; return; } } *statusp = RCU_KTHREAD_YIELDING; - trace_rcu_utilization("Start CPU kthread@rcu_yield"); + trace_rcu_utilization(TPS("Start CPU kthread@rcu_yield")); schedule_timeout_interruptible(2); - trace_rcu_utilization("End CPU kthread@rcu_yield"); + trace_rcu_utilization(TPS("End CPU kthread@rcu_yield")); *statusp = RCU_KTHREAD_WAITING; } @@ -2200,7 +2200,7 @@ static void rcu_nocb_wait_gp(struct rcu_data *rdp) * Wait for the grace period. Do so interruptibly to avoid messing * up the load average. */ - trace_rcu_future_gp(rnp, rdp, c, "StartWait"); + trace_rcu_future_gp(rnp, rdp, c, TPS("StartWait")); for (;;) { wait_event_interruptible( rnp->nocb_gp_wq[c & 0x1], @@ -2208,9 +2208,9 @@ static void rcu_nocb_wait_gp(struct rcu_data *rdp) if (likely(d)) break; flush_signals(current); - trace_rcu_future_gp(rnp, rdp, c, "ResumeWait"); + trace_rcu_future_gp(rnp, rdp, c, TPS("ResumeWait")); } - trace_rcu_future_gp(rnp, rdp, c, "EndWait"); + trace_rcu_future_gp(rnp, rdp, c, TPS("EndWait")); smp_mb(); /* Ensure that CB invocation happens after GP end. */ } From e26439ce03f0808f5d797ca33f180fdb8258335a Mon Sep 17 00:00:00 2001 From: Darren Hart Date: Mon, 29 Jul 2013 15:15:07 -0700 Subject: [PATCH 1077/3400] serial: pch_uart: Fix signed-ness and casting of uartclk related fields Storing one struct per known board would be overkill. Pre-cast the driver_data pointer to an unsigned long to avoid the pointer to int compiler warning: drivers/tty/serial/pch_uart.c:431:10: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] Unify the signed-ness of the baud and uartclk types throughout the driver. Signed-off-by: Darren Hart Reported-by: kbuild test robot Cc: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/pch_uart.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index bc0aa0881d0f..5040c517f3b8 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -232,7 +232,7 @@ struct eg20t_port { unsigned int iobase; struct pci_dev *pdev; int fifo_size; - int uartclk; + unsigned int uartclk; int start_tx; int start_rx; int tx_empty; @@ -419,7 +419,7 @@ static struct dmi_system_id pch_uart_dmi_table[] = { }; /* Return UART clock, checking for board specific clocks. */ -static int pch_uart_get_uartclk(void) +static unsigned int pch_uart_get_uartclk(void) { const struct dmi_system_id *d; @@ -428,7 +428,7 @@ static int pch_uart_get_uartclk(void) d = dmi_first_match(pch_uart_dmi_table); if (d) - return (int)d->driver_data; + return (unsigned long)d->driver_data; return DEFAULT_UARTCLK; } @@ -449,7 +449,7 @@ static void pch_uart_hal_disable_interrupt(struct eg20t_port *priv, iowrite8(ier, priv->membase + UART_IER); } -static int pch_uart_hal_set_line(struct eg20t_port *priv, int baud, +static int pch_uart_hal_set_line(struct eg20t_port *priv, unsigned int baud, unsigned int parity, unsigned int bits, unsigned int stb) { @@ -484,7 +484,7 @@ static int pch_uart_hal_set_line(struct eg20t_port *priv, int baud, lcr |= bits; lcr |= stb; - dev_dbg(priv->port.dev, "%s:baud = %d, div = %04x, lcr = %02x (%lu)\n", + dev_dbg(priv->port.dev, "%s:baud = %u, div = %04x, lcr = %02x (%lu)\n", __func__, baud, div, lcr, jiffies); iowrite8(PCH_UART_LCR_DLAB, priv->membase + UART_LCR); iowrite8(dll, priv->membase + PCH_UART_DLL); @@ -1390,9 +1390,8 @@ static void pch_uart_shutdown(struct uart_port *port) static void pch_uart_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { - int baud; int rtn; - unsigned int parity, bits, stb; + unsigned int baud, parity, bits, stb; struct eg20t_port *priv; unsigned long flags; From 1a11126bcb7c93c289bf3218fa546fd3b0c0df8b Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Fri, 26 Jul 2013 19:25:32 +0200 Subject: [PATCH 1078/3400] tracing: Turn event/id->i_private into call->event.type event_id_read() is racy, ftrace_event_call can be already freed by trace_remove_event_call() callers. Change event_create_dir() to pass "data = call->event.type", this is all event_id_read() needs. ftrace_event_id_fops no longer needs tracing_open_generic(). We add the new helper, event_file_data(), to read ->i_private, it will have more users. Note: currently ACCESS_ONCE() and "id != 0" check are not needed, but we are going to change event_remove/rmdir to clear ->i_private. Link: http://lkml.kernel.org/r/20130726172532.GA3605@redhat.com Reviewed-by: Masami Hiramatsu Signed-off-by: Oleg Nesterov Signed-off-by: Steven Rostedt --- kernel/trace/trace_events.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 898f868833f2..c2d13c528c3c 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -409,6 +409,11 @@ static void put_system(struct ftrace_subsystem_dir *dir) mutex_unlock(&event_mutex); } +static void *event_file_data(struct file *filp) +{ + return ACCESS_ONCE(file_inode(filp)->i_private); +} + /* * Open and update trace_array ref count. * Must have the current trace_array passed to it. @@ -946,14 +951,18 @@ static int trace_format_open(struct inode *inode, struct file *file) static ssize_t event_id_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) { - struct ftrace_event_call *call = filp->private_data; + int id = (long)event_file_data(filp); char buf[32]; int len; if (*ppos) return 0; - len = sprintf(buf, "%d\n", call->event.type); + if (unlikely(!id)) + return -ENODEV; + + len = sprintf(buf, "%d\n", id); + return simple_read_from_buffer(ubuf, cnt, ppos, buf, len); } @@ -1240,7 +1249,6 @@ static const struct file_operations ftrace_event_format_fops = { }; static const struct file_operations ftrace_event_id_fops = { - .open = tracing_open_generic, .read = event_id_read, .llseek = default_llseek, }; @@ -1488,8 +1496,8 @@ event_create_dir(struct dentry *parent, #ifdef CONFIG_PERF_EVENTS if (call->event.type && call->class->reg) - trace_create_file("id", 0444, file->dir, call, - id); + trace_create_file("id", 0444, file->dir, + (void *)(long)call->event.type, id); #endif /* From bc6f6b08dee5645770efb4b76186ded313f23752 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Fri, 26 Jul 2013 19:25:36 +0200 Subject: [PATCH 1079/3400] tracing: Change event_enable/disable_read() to verify i_private != NULL tracing_open_generic_file() is racy, ftrace_event_file can be already freed by rmdir or trace_remove_event_call(). Change event_enable_read() and event_disable_read() to read and verify "file = i_private" under event_mutex. This fixes nothing, but now we can change debugfs_remove("enable") callers to nullify ->i_private and fix the the problem. Link: http://lkml.kernel.org/r/20130726172536.GA3612@redhat.com Reviewed-by: Masami Hiramatsu Signed-off-by: Oleg Nesterov Signed-off-by: Steven Rostedt --- kernel/trace/trace_events.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index c2d13c528c3c..3dfa8419d0dc 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -684,15 +684,25 @@ static ssize_t event_enable_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) { - struct ftrace_event_file *file = filp->private_data; + struct ftrace_event_file *file; + unsigned long flags; char buf[4] = "0"; - if (file->flags & FTRACE_EVENT_FL_ENABLED && - !(file->flags & FTRACE_EVENT_FL_SOFT_DISABLED)) + mutex_lock(&event_mutex); + file = event_file_data(filp); + if (likely(file)) + flags = file->flags; + mutex_unlock(&event_mutex); + + if (!file) + return -ENODEV; + + if (flags & FTRACE_EVENT_FL_ENABLED && + !(flags & FTRACE_EVENT_FL_SOFT_DISABLED)) strcpy(buf, "1"); - if (file->flags & FTRACE_EVENT_FL_SOFT_DISABLED || - file->flags & FTRACE_EVENT_FL_SOFT_MODE) + if (flags & FTRACE_EVENT_FL_SOFT_DISABLED || + flags & FTRACE_EVENT_FL_SOFT_MODE) strcat(buf, "*"); strcat(buf, "\n"); @@ -704,13 +714,10 @@ static ssize_t event_enable_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) { - struct ftrace_event_file *file = filp->private_data; + struct ftrace_event_file *file; unsigned long val; int ret; - if (!file) - return -EINVAL; - ret = kstrtoul_from_user(ubuf, cnt, 10, &val); if (ret) return ret; @@ -722,8 +729,11 @@ event_enable_write(struct file *filp, const char __user *ubuf, size_t cnt, switch (val) { case 0: case 1: + ret = -ENODEV; mutex_lock(&event_mutex); - ret = ftrace_event_enable_disable(file, val); + file = event_file_data(filp); + if (likely(file)) + ret = ftrace_event_enable_disable(file, val); mutex_unlock(&event_mutex); break; From e2912b091c26b8ea95e5e00a43a7ac620f6c94a6 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Fri, 26 Jul 2013 19:25:40 +0200 Subject: [PATCH 1080/3400] tracing: Change event_filter_read/write to verify i_private != NULL event_filter_read/write() are racy, ftrace_event_call can be already freed by trace_remove_event_call() callers. 1. Shift mutex_lock(event_mutex) from print/apply_event_filter to the callers. 2. Change the callers, event_filter_read() and event_filter_write() to read i_private under this mutex and abort if it is NULL. This fixes nothing, but now we can change debugfs_remove("filter") callers to nullify ->i_private and fix the the problem. Link: http://lkml.kernel.org/r/20130726172540.GA3619@redhat.com Reviewed-by: Masami Hiramatsu Signed-off-by: Oleg Nesterov Signed-off-by: Steven Rostedt --- kernel/trace/trace_events.c | 26 +++++++++++++++++++------- kernel/trace/trace_events_filter.c | 17 ++++++----------- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 3dfa8419d0dc..1d7b6d03cd51 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -980,21 +980,28 @@ static ssize_t event_filter_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) { - struct ftrace_event_call *call = filp->private_data; + struct ftrace_event_call *call; struct trace_seq *s; - int r; + int r = -ENODEV; if (*ppos) return 0; s = kmalloc(sizeof(*s), GFP_KERNEL); + if (!s) return -ENOMEM; trace_seq_init(s); - print_event_filter(call, s); - r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->len); + mutex_lock(&event_mutex); + call = event_file_data(filp); + if (call) + print_event_filter(call, s); + mutex_unlock(&event_mutex); + + if (call) + r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->len); kfree(s); @@ -1005,9 +1012,9 @@ static ssize_t event_filter_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) { - struct ftrace_event_call *call = filp->private_data; + struct ftrace_event_call *call; char *buf; - int err; + int err = -ENODEV; if (cnt >= PAGE_SIZE) return -EINVAL; @@ -1022,7 +1029,12 @@ event_filter_write(struct file *filp, const char __user *ubuf, size_t cnt, } buf[cnt] = '\0'; - err = apply_event_filter(call, buf); + mutex_lock(&event_mutex); + call = event_file_data(filp); + if (call) + err = apply_event_filter(call, buf); + mutex_unlock(&event_mutex); + free_page((unsigned long) buf); if (err < 0) return err; diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c index 0c7b75a8acc8..97daa8cf958d 100644 --- a/kernel/trace/trace_events_filter.c +++ b/kernel/trace/trace_events_filter.c @@ -637,17 +637,15 @@ static void append_filter_err(struct filter_parse_state *ps, free_page((unsigned long) buf); } +/* caller must hold event_mutex */ void print_event_filter(struct ftrace_event_call *call, struct trace_seq *s) { - struct event_filter *filter; + struct event_filter *filter = call->filter; - mutex_lock(&event_mutex); - filter = call->filter; if (filter && filter->filter_string) trace_seq_printf(s, "%s\n", filter->filter_string); else trace_seq_puts(s, "none\n"); - mutex_unlock(&event_mutex); } void print_subsystem_event_filter(struct event_subsystem *system, @@ -1841,23 +1839,22 @@ static int create_system_filter(struct event_subsystem *system, return err; } +/* caller must hold event_mutex */ int apply_event_filter(struct ftrace_event_call *call, char *filter_string) { struct event_filter *filter; - int err = 0; - - mutex_lock(&event_mutex); + int err; if (!strcmp(strstrip(filter_string), "0")) { filter_disable(call); filter = call->filter; if (!filter) - goto out_unlock; + return 0; RCU_INIT_POINTER(call->filter, NULL); /* Make sure the filter is not being used */ synchronize_sched(); __free_filter(filter); - goto out_unlock; + return 0; } err = create_filter(call, filter_string, true, &filter); @@ -1884,8 +1881,6 @@ int apply_event_filter(struct ftrace_event_call *call, char *filter_string) __free_filter(tmp); } } -out_unlock: - mutex_unlock(&event_mutex); return err; } From c5a44a1200c6eda2202434f25325e8ad19533fca Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Fri, 26 Jul 2013 19:25:43 +0200 Subject: [PATCH 1081/3400] tracing: Change f_start() to take event_mutex and verify i_private != NULL trace_format_open() and trace_format_seq_ops are racy, nothing protects ftrace_event_call from trace_remove_event_call(). Change f_start() to take event_mutex and verify i_private != NULL, change f_stop() to drop this lock. This fixes nothing, but now we can change debugfs_remove("format") callers to nullify ->i_private and fix the the problem. Note: the usage of event_mutex is sub-optimal but simple, we can change this later. Link: http://lkml.kernel.org/r/20130726172543.GA3622@redhat.com Reviewed-by: Masami Hiramatsu Signed-off-by: Oleg Nesterov Signed-off-by: Steven Rostedt --- kernel/trace/trace_events.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 1d7b6d03cd51..50dc8b2e5435 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -840,7 +840,7 @@ enum { static void *f_next(struct seq_file *m, void *v, loff_t *pos) { - struct ftrace_event_call *call = m->private; + struct ftrace_event_call *call = event_file_data(m->private); struct list_head *common_head = &ftrace_common_fields; struct list_head *head = trace_get_fields(call); struct list_head *node = v; @@ -872,7 +872,7 @@ static void *f_next(struct seq_file *m, void *v, loff_t *pos) static int f_show(struct seq_file *m, void *v) { - struct ftrace_event_call *call = m->private; + struct ftrace_event_call *call = event_file_data(m->private); struct ftrace_event_field *field; const char *array_descriptor; @@ -925,6 +925,11 @@ static void *f_start(struct seq_file *m, loff_t *pos) void *p = (void *)FORMAT_HEADER; loff_t l = 0; + /* ->stop() is called even if ->start() fails */ + mutex_lock(&event_mutex); + if (!event_file_data(m->private)) + return ERR_PTR(-ENODEV); + while (l < *pos && p) p = f_next(m, p, &l); @@ -933,6 +938,7 @@ static void *f_start(struct seq_file *m, loff_t *pos) static void f_stop(struct seq_file *m, void *p) { + mutex_unlock(&event_mutex); } static const struct seq_operations trace_format_seq_ops = { @@ -944,7 +950,6 @@ static const struct seq_operations trace_format_seq_ops = { static int trace_format_open(struct inode *inode, struct file *file) { - struct ftrace_event_call *call = inode->i_private; struct seq_file *m; int ret; @@ -953,7 +958,7 @@ static int trace_format_open(struct inode *inode, struct file *file) return ret; m = file->private_data; - m->private = call; + m->private = file; return 0; } From f6a84bdc75b5c11621dec58db73fe102cbaf40cc Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Fri, 26 Jul 2013 19:25:47 +0200 Subject: [PATCH 1082/3400] tracing: Introduce remove_event_file_dir() Preparation for the next patch. Extract the common code from remove_event_from_tracers() and __trace_remove_event_dirs() into the new helper, remove_event_file_dir(). The patch looks more complicated than it actually is, it also moves remove_subsystem() up to avoid the forward declaration. Link: http://lkml.kernel.org/r/20130726172547.GA3629@redhat.com Reviewed-by: Masami Hiramatsu Signed-off-by: Oleg Nesterov Signed-off-by: Steven Rostedt --- kernel/trace/trace_events.c | 47 ++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 50dc8b2e5435..05d647ecd01a 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -409,11 +409,31 @@ static void put_system(struct ftrace_subsystem_dir *dir) mutex_unlock(&event_mutex); } +static void remove_subsystem(struct ftrace_subsystem_dir *dir) +{ + if (!dir) + return; + + if (!--dir->nr_events) { + debugfs_remove_recursive(dir->entry); + list_del(&dir->list); + __put_system_dir(dir); + } +} + static void *event_file_data(struct file *filp) { return ACCESS_ONCE(file_inode(filp)->i_private); } +static void remove_event_file_dir(struct ftrace_event_file *file) +{ + list_del(&file->list); + debugfs_remove_recursive(file->dir); + remove_subsystem(file->system); + kmem_cache_free(file_cachep, file); +} + /* * Open and update trace_array ref count. * Must have the current trace_array passed to it. @@ -1549,33 +1569,16 @@ event_create_dir(struct dentry *parent, return 0; } -static void remove_subsystem(struct ftrace_subsystem_dir *dir) -{ - if (!dir) - return; - - if (!--dir->nr_events) { - debugfs_remove_recursive(dir->entry); - list_del(&dir->list); - __put_system_dir(dir); - } -} - static void remove_event_from_tracers(struct ftrace_event_call *call) { struct ftrace_event_file *file; struct trace_array *tr; do_for_each_event_file_safe(tr, file) { - if (file->event_call != call) continue; - list_del(&file->list); - debugfs_remove_recursive(file->dir); - remove_subsystem(file->system); - kmem_cache_free(file_cachep, file); - + remove_event_file_dir(file); /* * The do_for_each_event_file_safe() is * a double loop. After finding the call for this @@ -2305,12 +2308,8 @@ __trace_remove_event_dirs(struct trace_array *tr) { struct ftrace_event_file *file, *next; - list_for_each_entry_safe(file, next, &tr->events, list) { - list_del(&file->list); - debugfs_remove_recursive(file->dir); - remove_subsystem(file->system); - kmem_cache_free(file_cachep, file); - } + list_for_each_entry_safe(file, next, &tr->events, list) + remove_event_file_dir(file); } static void From bf682c3159c4d298d1126a56793ed3f5e80395f7 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Sun, 28 Jul 2013 20:35:27 +0200 Subject: [PATCH 1083/3400] tracing: Change remove_event_file_dir() to clear "d_subdirs"->i_private Change remove_event_file_dir() to clear ->i_private for every file we are going to remove. We need to check file->dir != NULL because event_create_dir() can fail. debugfs_remove_recursive(NULL) is fine but the patch moves it under the same check anyway for readability. spin_lock(d_lock) and "d_inode != NULL" check are not needed afaics, but I do not understand this code enough. tracing_open_generic_file() and tracing_release_generic_file() can go away, ftrace_enable_fops and ftrace_event_filter_fops() use tracing_open_generic() but only to check tracing_disabled. This fixes all races with event_remove() or instance_delete(). f_op->read/write/whatever can never use the freed file/call, all event/* files were changed to check and use ->i_private under event_mutex. Note: this doesn't not fix other problems, event_remove() can destroy the active ftrace_event_call, we need more changes but those changes are completely orthogonal. Link: http://lkml.kernel.org/r/20130728183527.GB16723@redhat.com Reviewed-by: Masami Hiramatsu Signed-off-by: Oleg Nesterov Signed-off-by: Steven Rostedt --- kernel/trace/trace_events.c | 47 ++++++++++++------------------------- 1 file changed, 15 insertions(+), 32 deletions(-) diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 05d647ecd01a..a67c913e2f9f 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -428,41 +428,25 @@ static void *event_file_data(struct file *filp) static void remove_event_file_dir(struct ftrace_event_file *file) { + struct dentry *dir = file->dir; + struct dentry *child; + + if (dir) { + spin_lock(&dir->d_lock); /* probably unneeded */ + list_for_each_entry(child, &dir->d_subdirs, d_u.d_child) { + if (child->d_inode) /* probably unneeded */ + child->d_inode->i_private = NULL; + } + spin_unlock(&dir->d_lock); + + debugfs_remove_recursive(dir); + } + list_del(&file->list); - debugfs_remove_recursive(file->dir); remove_subsystem(file->system); kmem_cache_free(file_cachep, file); } -/* - * Open and update trace_array ref count. - * Must have the current trace_array passed to it. - */ -static int tracing_open_generic_file(struct inode *inode, struct file *filp) -{ - struct ftrace_event_file *file = inode->i_private; - struct trace_array *tr = file->tr; - int ret; - - if (trace_array_get(tr) < 0) - return -ENODEV; - - ret = tracing_open_generic(inode, filp); - if (ret < 0) - trace_array_put(tr); - return ret; -} - -static int tracing_release_generic_file(struct inode *inode, struct file *filp) -{ - struct ftrace_event_file *file = inode->i_private; - struct trace_array *tr = file->tr; - - trace_array_put(tr); - - return 0; -} - /* * __ftrace_set_clr_event(NULL, NULL, NULL, set) will set/unset all events. */ @@ -1281,10 +1265,9 @@ static const struct file_operations ftrace_set_event_fops = { }; static const struct file_operations ftrace_enable_fops = { - .open = tracing_open_generic_file, + .open = tracing_open_generic, .read = event_enable_read, .write = event_enable_write, - .release = tracing_release_generic_file, .llseek = default_llseek, }; From 1c80c43290ee576afe8d39ecc905fa3958a5858c Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Thu, 25 Jul 2013 20:22:00 -0400 Subject: [PATCH 1084/3400] ftrace: Consolidate some duplicate code for updating ftrace ops When ftrace ops modifies the functions that it will trace, the update to the function mcount callers may need to be modified. Consolidate the two places that do the checks to see if an update is required with a wrapper function for those checks. Signed-off-by: Steven Rostedt --- kernel/trace/ftrace.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 8ce9eefc5bb4..92d3334de0c3 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -3384,6 +3384,12 @@ ftrace_match_addr(struct ftrace_hash *hash, unsigned long ip, int remove) return add_hash_entry(hash, ip); } +static void ftrace_ops_update_code(struct ftrace_ops *ops) +{ + if (ops->flags & FTRACE_OPS_FL_ENABLED && ftrace_enabled) + ftrace_run_update_code(FTRACE_UPDATE_CALLS); +} + static int ftrace_set_hash(struct ftrace_ops *ops, unsigned char *buf, int len, unsigned long ip, int remove, int reset, int enable) @@ -3426,9 +3432,8 @@ ftrace_set_hash(struct ftrace_ops *ops, unsigned char *buf, int len, mutex_lock(&ftrace_lock); ret = ftrace_hash_move(ops, enable, orig_hash, hash); - if (!ret && ops->flags & FTRACE_OPS_FL_ENABLED - && ftrace_enabled) - ftrace_run_update_code(FTRACE_UPDATE_CALLS); + if (!ret) + ftrace_ops_update_code(ops); mutex_unlock(&ftrace_lock); @@ -3655,9 +3660,8 @@ int ftrace_regex_release(struct inode *inode, struct file *file) mutex_lock(&ftrace_lock); ret = ftrace_hash_move(iter->ops, filter_hash, orig_hash, iter->hash); - if (!ret && (iter->ops->flags & FTRACE_OPS_FL_ENABLED) - && ftrace_enabled) - ftrace_run_update_code(FTRACE_UPDATE_CALLS); + if (!ret) + ftrace_ops_update_code(iter->ops); mutex_unlock(&ftrace_lock); } From 35f8550c8f27968af94ba5235cc611e3b6d86981 Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Tue, 30 Jul 2013 11:32:40 +0900 Subject: [PATCH 1085/3400] ARM: SAMSUNG: fix to support for missing cpu specific map_io Since commit 7ed76e08 (ARM: EXYNOS: Fix low level debug support) map_io() is not needed for exynos5440 so need to fix to lookup cpu which using map_io(). Without this, kernel boot log complains 'CPU EXYNOS5440 support not enabled' on exynos5440 and panic(). Signed-off-by: Kukjin Kim --- arch/arm/plat-samsung/init.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm/plat-samsung/init.c b/arch/arm/plat-samsung/init.c index 3e5c4619caa5..50a3ea0037db 100644 --- a/arch/arm/plat-samsung/init.c +++ b/arch/arm/plat-samsung/init.c @@ -55,12 +55,13 @@ void __init s3c_init_cpu(unsigned long idcode, printk("CPU %s (id 0x%08lx)\n", cpu->name, idcode); - if (cpu->map_io == NULL || cpu->init == NULL) { + if (cpu->init == NULL) { printk(KERN_ERR "CPU %s support not enabled\n", cpu->name); panic("Unsupported Samsung CPU"); } - cpu->map_io(); + if (cpu->map_io) + cpu->map_io(); } /* s3c24xx_init_clocks From 9cf7b244187bba5964d4bf7438946baa2a974466 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 30 Jul 2013 09:09:15 +0300 Subject: [PATCH 1086/3400] usb: of: fix build breakage caused by recent patches commit 052a11d (usb: phy: make PHY driver selection possible by controller drivers) changed the rules on how drivers/usb/phy/of.c would be compiled and failed to update include/linux/usb/of.h accordingly. Because of that, we can fall into situations where of_usb_get_phy_mode() is redefined. In order to fix the error, we update the IS_ENABLED() check in include/linux/usb/of.h to reflect the condition where of.c is built. Reported-by: Stephen Rothwell Signed-off-by: Felipe Balbi --- include/linux/usb/of.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/usb/of.h b/include/linux/usb/of.h index 5a7cb9ebf0ef..8c38aa26b3bb 100644 --- a/include/linux/usb/of.h +++ b/include/linux/usb/of.h @@ -27,7 +27,7 @@ of_usb_get_maximum_speed(struct device_node *np) } #endif -#if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_USB_PHY) +#if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_USB_SUPPORT) enum usb_phy_interface of_usb_get_phy_mode(struct device_node *np); #else static inline enum usb_phy_interface of_usb_get_phy_mode(struct device_node *np) From 3709d323085853dc537711154004ba8704cefb9c Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Mon, 29 Jul 2013 12:03:01 -0500 Subject: [PATCH 1087/3400] ARM: dts: omap5-uevm: document regulator signals used on the actual board MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit e00c27ef3b4c23e39d0a77b7c8e5be44c28001c7 (ARM: dts: OMAP5: Add Palmas MFD node and regulator nodes) introduced regulator entries for OMAP5uEVM. However, currently we use the Palmas regulator names which is used for different purposes on uEVM. Document the same based on 750-2628-XXX boards - which is meant to be supported by this dts. Reported-by: Marc Jüttner Signed-off-by: Nishanth Menon Acked-by: J Keerthy Acked-by: Benoit Cousson Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap5-uevm.dts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/arch/arm/boot/dts/omap5-uevm.dts b/arch/arm/boot/dts/omap5-uevm.dts index 08b72678abff..b430b8f884b8 100644 --- a/arch/arm/boot/dts/omap5-uevm.dts +++ b/arch/arm/boot/dts/omap5-uevm.dts @@ -282,6 +282,7 @@ regulators { smps123_reg: smps123 { + /* VDD_OPP_MPU */ regulator-name = "smps123"; regulator-min-microvolt = < 600000>; regulator-max-microvolt = <1500000>; @@ -290,6 +291,7 @@ }; smps45_reg: smps45 { + /* VDD_OPP_MM */ regulator-name = "smps45"; regulator-min-microvolt = < 600000>; regulator-max-microvolt = <1310000>; @@ -298,6 +300,7 @@ }; smps6_reg: smps6 { + /* VDD_DDR3 - over VDD_SMPS6 */ regulator-name = "smps6"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <1200000>; @@ -306,6 +309,7 @@ }; smps7_reg: smps7 { + /* VDDS_1v8_OMAP over VDDS_1v8_MAIN */ regulator-name = "smps7"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; @@ -314,6 +318,7 @@ }; smps8_reg: smps8 { + /* VDD_OPP_CORE */ regulator-name = "smps8"; regulator-min-microvolt = < 600000>; regulator-max-microvolt = <1310000>; @@ -322,6 +327,7 @@ }; smps9_reg: smps9 { + /* VDDA_2v1_AUD over VDD_2v1 */ regulator-name = "smps9"; regulator-min-microvolt = <2100000>; regulator-max-microvolt = <2100000>; @@ -331,6 +337,7 @@ }; smps10_reg: smps10 { + /* VBUS_5V_OTG */ regulator-name = "smps10"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; @@ -339,6 +346,7 @@ }; ldo1_reg: ldo1 { + /* VDDAPHY_CAM: vdda_csiport */ regulator-name = "ldo1"; regulator-min-microvolt = <2800000>; regulator-max-microvolt = <2800000>; @@ -347,6 +355,7 @@ }; ldo2_reg: ldo2 { + /* VCC_2V8_DISP: Does not go anywhere */ regulator-name = "ldo2"; regulator-min-microvolt = <2900000>; regulator-max-microvolt = <2900000>; @@ -355,6 +364,7 @@ }; ldo3_reg: ldo3 { + /* VDDAPHY_MDM: vdda_lli */ regulator-name = "ldo3"; regulator-min-microvolt = <3000000>; regulator-max-microvolt = <3000000>; @@ -363,6 +373,7 @@ }; ldo4_reg: ldo4 { + /* VDDAPHY_DISP: vdda_dsiport/hdmi */ regulator-name = "ldo4"; regulator-min-microvolt = <2200000>; regulator-max-microvolt = <2200000>; @@ -371,6 +382,7 @@ }; ldo5_reg: ldo5 { + /* VDDA_1V8_PHY: usb/sata/hdmi.. */ regulator-name = "ldo5"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; @@ -379,6 +391,7 @@ }; ldo6_reg: ldo6 { + /* VDDS_1V2_WKUP: hsic/ldo_emu_wkup */ regulator-name = "ldo6"; regulator-min-microvolt = <1500000>; regulator-max-microvolt = <1500000>; @@ -387,6 +400,7 @@ }; ldo7_reg: ldo7 { + /* VDD_VPP: vpp1 */ regulator-name = "ldo7"; regulator-min-microvolt = <1500000>; regulator-max-microvolt = <1500000>; @@ -395,6 +409,7 @@ }; ldo8_reg: ldo8 { + /* VDD_3v0: Does not go anywhere */ regulator-name = "ldo8"; regulator-min-microvolt = <1500000>; regulator-max-microvolt = <1500000>; @@ -403,6 +418,7 @@ }; ldo9_reg: ldo9 { + /* VCC_DV_SDIO: vdds_sdcard */ regulator-name = "ldo9"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <3300000>; @@ -411,6 +427,7 @@ }; ldoln_reg: ldoln { + /* VDDA_1v8_REF: vdds_osc/mm_l4per.. */ regulator-name = "ldoln"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; @@ -419,6 +436,7 @@ }; ldousb_reg: ldousb { + /* VDDA_3V_USB: VDDA_USBHS33 */ regulator-name = "ldousb"; regulator-min-microvolt = <3250000>; regulator-max-microvolt = <3250000>; From e18235a62a7ea737d0a3f73c76eacaaec6df3dfe Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Mon, 29 Jul 2013 12:03:02 -0500 Subject: [PATCH 1088/3400] ARM: dts: omap5-uevm: fix regulator configurations mandatory for SoC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit e00c27ef3b4c23e39d0a77b7c8e5be44c28001c7 (ARM: dts: OMAP5: Add Palmas MFD node and regulator nodes) introduced regulator entries for OMAP5uEVM. However, The regulator information is based on an older temporary pre-production board variant and does not reflect production board 750-2628-XXX boards. The following fixes are hence mandatory to ensure right voltage is supplied to key OMAP5 SoC voltage rails: - LDO1 supplies VDDAPHY_CAM which is OMAP5's vdda_csiporta/b/c. This can only be supplied at 1.5V or 1.8V and we currently supply 2.8V. To prevent any potential device damage risk, use the specified 1.5V-1.8V supply. Remove 'always-on' and 'boot-on' settings here as it is a 'on need' supply to SoC IP and is not enabled by PMIC by default at boot. - LDO3 supplies Low Latency Interface(LLI) hardware module which is a special hardware to communicate with Modem. However since uEVM is not setup by default for this communication, this should be disabled by default. Further, vdda_lli is supposed to be 1.5V and not 3V. - LDO4 supplies VDDAPHY_DISP which is vdda_dsiporta/c/vdda_hdmi This can only be supplied at 1.5V or 1.8V and we currently supply 2.2V. To prevent any potential device damage risk, use the specified 1.5V-1.8V supply. Remove 'always-on' and 'boot-on' settings here as it is a 'on need' supply to SoC IP and is not enabled by PMIC by default at boot. - LDO6 supplies the board specified VDDS_1V2_WKUP supply going to ldo_emu_wkup/vdds_hsic. To stay within the SoC specification supply 1.2V instead of 1.5V. - LDO7 supplies VDD_VPP which is vpp1. This is currently configured for 1.5V which as per data manual "A pulse width of 1000 ns and an amplitude of 2V is required to program each eFuse bit. Otherwise, VPP1 must not be supplied". So, fix the voltage to 2V. and disable the supply since we have no plans of programming efuse bits - it can only be done once - in factory. Further it is not enabled by default by PMIC so, 'boot-on' must be removed, and the 'always-on' needs to be removed to achieve pulsing if efuse needs to be programmed. - LDO9 supplies the board specified vdds_sdcard supply going within SoC specification of 1.8V or 3.0V. Further the supply is controlled by switch enabled by REGEN3. So, introduce REGEN3 and map sdcard slot to be powered by LDO9. Remove 'always-on' allowing the LDO to be disabled on need basis. Reported-by: Marc Jüttner Signed-off-by: Nishanth Menon Acked-by: J Keerthy Acked-by: Benoit Cousson Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap5-uevm.dts | 43 +++++++++++++++++--------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/arch/arm/boot/dts/omap5-uevm.dts b/arch/arm/boot/dts/omap5-uevm.dts index b430b8f884b8..247c03c0d734 100644 --- a/arch/arm/boot/dts/omap5-uevm.dts +++ b/arch/arm/boot/dts/omap5-uevm.dts @@ -235,7 +235,7 @@ }; &mmc1 { - vmmc-supply = <&vmmcsd_fixed>; + vmmc-supply = <&ldo9_reg>; bus-width = <4>; }; @@ -348,10 +348,8 @@ ldo1_reg: ldo1 { /* VDDAPHY_CAM: vdda_csiport */ regulator-name = "ldo1"; - regulator-min-microvolt = <2800000>; - regulator-max-microvolt = <2800000>; - regulator-always-on; - regulator-boot-on; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1800000>; }; ldo2_reg: ldo2 { @@ -366,19 +364,18 @@ ldo3_reg: ldo3 { /* VDDAPHY_MDM: vdda_lli */ regulator-name = "ldo3"; - regulator-min-microvolt = <3000000>; - regulator-max-microvolt = <3000000>; - regulator-always-on; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; regulator-boot-on; + /* Only if Modem is used */ + status = "disabled"; }; ldo4_reg: ldo4 { /* VDDAPHY_DISP: vdda_dsiport/hdmi */ regulator-name = "ldo4"; - regulator-min-microvolt = <2200000>; - regulator-max-microvolt = <2200000>; - regulator-always-on; - regulator-boot-on; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1800000>; }; ldo5_reg: ldo5 { @@ -393,8 +390,8 @@ ldo6_reg: ldo6 { /* VDDS_1V2_WKUP: hsic/ldo_emu_wkup */ regulator-name = "ldo6"; - regulator-min-microvolt = <1500000>; - regulator-max-microvolt = <1500000>; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; regulator-always-on; regulator-boot-on; }; @@ -402,10 +399,10 @@ ldo7_reg: ldo7 { /* VDD_VPP: vpp1 */ regulator-name = "ldo7"; - regulator-min-microvolt = <1500000>; - regulator-max-microvolt = <1500000>; - regulator-always-on; - regulator-boot-on; + regulator-min-microvolt = <2000000>; + regulator-max-microvolt = <2000000>; + /* Only for efuse reprograming! */ + status = "disabled"; }; ldo8_reg: ldo8 { @@ -421,8 +418,7 @@ /* VCC_DV_SDIO: vdds_sdcard */ regulator-name = "ldo9"; regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - regulator-always-on; + regulator-max-microvolt = <3000000>; regulator-boot-on; }; @@ -443,6 +439,13 @@ regulator-always-on; regulator-boot-on; }; + + regen3_reg: regen3 { + /* REGEN3 controls LDO9 supply to card */ + regulator-name = "regen3"; + regulator-always-on; + regulator-boot-on; + }; }; }; }; From bd3c5544a1e98a25d2d24c98779092e0f84373f7 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Mon, 29 Jul 2013 12:03:03 -0500 Subject: [PATCH 1089/3400] ARM: dts: omap5-uevm: update optional/unused regulator configurations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit e00c27ef3b4c23e39d0a77b7c8e5be44c28001c7 (ARM: dts: OMAP5: Add Palmas MFD node and regulator nodes) introduced regulator entries for OMAP5uEVM. However, The regulator information is based on an older temporary pre-production board variant and does not reflect production board 750-2628-XXX boards. The following optional/unused regulators can be updated: - SMPS9 supplies TWL6040 over VDDA_2v1_AUD. This regulator needs to be enabled only when audio is active. Since it does not come active by default, it does not require "always-on" or "boot-on". - LDO2 and LDO8 do not go to any peripheral or connector on the board. Further, these unused regulators should have been 2.8V for LDO2 and 3.0V for LDO8. Mark these LDOs as disabled in the dts until needed. Reported-by: Marc Jüttner Signed-off-by: Nishanth Menon Acked-by: J Keerthy Acked-by: Benoit Cousson Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap5-uevm.dts | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/arch/arm/boot/dts/omap5-uevm.dts b/arch/arm/boot/dts/omap5-uevm.dts index 247c03c0d734..65d7b601651c 100644 --- a/arch/arm/boot/dts/omap5-uevm.dts +++ b/arch/arm/boot/dts/omap5-uevm.dts @@ -331,8 +331,6 @@ regulator-name = "smps9"; regulator-min-microvolt = <2100000>; regulator-max-microvolt = <2100000>; - regulator-always-on; - regulator-boot-on; ti,smps-range = <0x80>; }; @@ -355,10 +353,10 @@ ldo2_reg: ldo2 { /* VCC_2V8_DISP: Does not go anywhere */ regulator-name = "ldo2"; - regulator-min-microvolt = <2900000>; - regulator-max-microvolt = <2900000>; - regulator-always-on; - regulator-boot-on; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + /* Unused */ + status = "disabled"; }; ldo3_reg: ldo3 { @@ -408,10 +406,11 @@ ldo8_reg: ldo8 { /* VDD_3v0: Does not go anywhere */ regulator-name = "ldo8"; - regulator-min-microvolt = <1500000>; - regulator-max-microvolt = <1500000>; - regulator-always-on; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; regulator-boot-on; + /* Unused */ + status = "disabled"; }; ldo9_reg: ldo9 { From b27f274d358b2bf51fa052c196090f8acd1f35d6 Mon Sep 17 00:00:00 2001 From: Mikko Perttunen Date: Tue, 30 Jul 2013 09:47:57 +0300 Subject: [PATCH 1090/3400] usb: tegra: Fix typo in tegra20-usb-phy documentation The device tree binding documentation for tegra20-usb-phy used to claim that the vbus-supply property is required for host phys and optional for otg phys. This should be the other way around. Signed-off-by: Mikko Perttunen Signed-off-by: Felipe Balbi --- .../devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt b/Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt index 59c48542abb9..4c8ade8b340b 100644 --- a/Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt +++ b/Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt @@ -48,5 +48,5 @@ Optional properties: peripheral means it is device controller otg means it can operate as either ("on the go") -VBUS control (required for dr_mode == host, optional for dr_mode == otg): +VBUS control (required for dr_mode == otg, optional for dr_mode == host): - vbus-supply: regulator for VBUS From e01ee9f509a927158f670408b41127d4166db1c7 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 30 Jul 2013 17:00:51 +0900 Subject: [PATCH 1091/3400] usb: gadget: use dev_get_platdata() Use the wrapper function for retrieving the platform data instead of accessing dev->platform_data directly. Signed-off-by: Jingoo Han Signed-off-by: Felipe Balbi --- drivers/usb/gadget/at91_udc.c | 4 ++-- drivers/usb/gadget/atmel_usba_udc.c | 2 +- drivers/usb/gadget/bcm63xx_udc.c | 2 +- drivers/usb/gadget/fsl_mxc_udc.c | 4 ++-- drivers/usb/gadget/fsl_udc_core.c | 6 +++--- drivers/usb/gadget/hid.c | 2 +- drivers/usb/gadget/m66592-udc.c | 4 ++-- drivers/usb/gadget/mv_u3d_core.c | 12 ++++++------ drivers/usb/gadget/mv_udc_core.c | 4 ++-- drivers/usb/gadget/omap_udc.c | 2 +- drivers/usb/gadget/pxa25x_udc.c | 2 +- drivers/usb/gadget/pxa27x_udc.c | 2 +- drivers/usb/gadget/r8a66597-udc.c | 2 +- drivers/usb/gadget/s3c-hsotg.c | 4 ++-- drivers/usb/gadget/s3c-hsudc.c | 4 ++-- drivers/usb/gadget/s3c2410_udc.c | 2 +- 16 files changed, 29 insertions(+), 29 deletions(-) diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index d9a6add0c852..d237429dd93a 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -1697,7 +1697,7 @@ static int at91udc_probe(struct platform_device *pdev) int retval; struct resource *res; - if (!dev->platform_data && !pdev->dev.of_node) { + if (!dev_get_platdata(dev) && !pdev->dev.of_node) { /* small (so we copy it) but critical! */ DBG("missing platform_data\n"); return -ENODEV; @@ -1728,7 +1728,7 @@ static int at91udc_probe(struct platform_device *pdev) if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) at91udc_of_init(udc, pdev->dev.of_node); else - memcpy(&udc->board, dev->platform_data, + memcpy(&udc->board, dev_get_platdata(dev), sizeof(struct at91_udc_data)); udc->pdev = pdev; udc->enabled = 0; diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c index f018017e3a77..40d23384b716 100644 --- a/drivers/usb/gadget/atmel_usba_udc.c +++ b/drivers/usb/gadget/atmel_usba_udc.c @@ -1931,7 +1931,7 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev, static struct usba_ep * usba_udc_pdata(struct platform_device *pdev, struct usba_udc *udc) { - struct usba_platform_data *pdata = pdev->dev.platform_data; + struct usba_platform_data *pdata = dev_get_platdata(&pdev->dev); struct usba_ep *eps; int i; diff --git a/drivers/usb/gadget/bcm63xx_udc.c b/drivers/usb/gadget/bcm63xx_udc.c index fd24cb4540a4..c58fcf1ebe41 100644 --- a/drivers/usb/gadget/bcm63xx_udc.c +++ b/drivers/usb/gadget/bcm63xx_udc.c @@ -2313,7 +2313,7 @@ static void bcm63xx_udc_cleanup_debugfs(struct bcm63xx_udc *udc) static int bcm63xx_udc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct bcm63xx_usbd_platform_data *pd = dev->platform_data; + struct bcm63xx_usbd_platform_data *pd = dev_get_platdata(dev); struct bcm63xx_udc *udc; struct resource *res; int rc = -ENOMEM, i, irq; diff --git a/drivers/usb/gadget/fsl_mxc_udc.c b/drivers/usb/gadget/fsl_mxc_udc.c index d3bd7b095ba3..9b140fc4d3bc 100644 --- a/drivers/usb/gadget/fsl_mxc_udc.c +++ b/drivers/usb/gadget/fsl_mxc_udc.c @@ -33,7 +33,7 @@ int fsl_udc_clk_init(struct platform_device *pdev) unsigned long freq; int ret; - pdata = pdev->dev.platform_data; + pdata = dev_get_platdata(&pdev->dev); mxc_ipg_clk = devm_clk_get(&pdev->dev, "ipg"); if (IS_ERR(mxc_ipg_clk)) { @@ -80,7 +80,7 @@ eclkrate: int fsl_udc_clk_finalize(struct platform_device *pdev) { - struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; + struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev); int ret = 0; /* workaround ENGcm09152 for i.MX35 */ diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index a766a4ca1cb7..36ac7cfba91d 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -2248,7 +2248,7 @@ static int __init struct_udc_setup(struct fsl_udc *udc, struct fsl_usb2_platform_data *pdata; size_t size; - pdata = pdev->dev.platform_data; + pdata = dev_get_platdata(&pdev->dev); udc->phy_mode = pdata->phy_mode; udc->eps = kzalloc(sizeof(struct fsl_ep) * udc->max_ep, GFP_KERNEL); @@ -2343,7 +2343,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev) return -ENOMEM; } - pdata = pdev->dev.platform_data; + pdata = dev_get_platdata(&pdev->dev); udc_controller->pdata = pdata; spin_lock_init(&udc_controller->lock); udc_controller->stopped = 1; @@ -2524,7 +2524,7 @@ err_kfree: static int __exit fsl_udc_remove(struct platform_device *pdev) { struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; + struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev); DECLARE_COMPLETION(done); diff --git a/drivers/usb/gadget/hid.c b/drivers/usb/gadget/hid.c index c36260ea8bf2..778613eb37af 100644 --- a/drivers/usb/gadget/hid.c +++ b/drivers/usb/gadget/hid.c @@ -185,7 +185,7 @@ static int __exit hid_unbind(struct usb_composite_dev *cdev) static int __init hidg_plat_driver_probe(struct platform_device *pdev) { - struct hidg_func_descriptor *func = pdev->dev.platform_data; + struct hidg_func_descriptor *func = dev_get_platdata(&pdev->dev); struct hidg_func_node *entry; if (!func) { diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c index 46ba9838c3a0..d5f050d30edf 100644 --- a/drivers/usb/gadget/m66592-udc.c +++ b/drivers/usb/gadget/m66592-udc.c @@ -1584,7 +1584,7 @@ static int __init m66592_probe(struct platform_device *pdev) goto clean_up; } - if (pdev->dev.platform_data == NULL) { + if (dev_get_platdata(&pdev->dev) == NULL) { dev_err(&pdev->dev, "no platform data\n"); ret = -ENODEV; goto clean_up; @@ -1598,7 +1598,7 @@ static int __init m66592_probe(struct platform_device *pdev) goto clean_up; } - m66592->pdata = pdev->dev.platform_data; + m66592->pdata = dev_get_platdata(&pdev->dev); m66592->irq_trigger = ires->flags & IRQF_TRIGGER_MASK; spin_lock_init(&m66592->lock); diff --git a/drivers/usb/gadget/mv_u3d_core.c b/drivers/usb/gadget/mv_u3d_core.c index ec6a2d290398..bbb6e98c4384 100644 --- a/drivers/usb/gadget/mv_u3d_core.c +++ b/drivers/usb/gadget/mv_u3d_core.c @@ -1109,7 +1109,7 @@ static int mv_u3d_controller_reset(struct mv_u3d *u3d) static int mv_u3d_enable(struct mv_u3d *u3d) { - struct mv_usb_platform_data *pdata = u3d->dev->platform_data; + struct mv_usb_platform_data *pdata = dev_get_platdata(u3d->dev); int retval; if (u3d->active) @@ -1138,7 +1138,7 @@ static int mv_u3d_enable(struct mv_u3d *u3d) static void mv_u3d_disable(struct mv_u3d *u3d) { - struct mv_usb_platform_data *pdata = u3d->dev->platform_data; + struct mv_usb_platform_data *pdata = dev_get_platdata(u3d->dev); if (u3d->clock_gating && u3d->active) { dev_dbg(u3d->dev, "disable u3d\n"); if (pdata->phy_deinit) @@ -1246,7 +1246,7 @@ static int mv_u3d_start(struct usb_gadget *g, struct usb_gadget_driver *driver) { struct mv_u3d *u3d = container_of(g, struct mv_u3d, gadget); - struct mv_usb_platform_data *pdata = u3d->dev->platform_data; + struct mv_usb_platform_data *pdata = dev_get_platdata(u3d->dev); unsigned long flags; if (u3d->driver) @@ -1277,7 +1277,7 @@ static int mv_u3d_stop(struct usb_gadget *g, struct usb_gadget_driver *driver) { struct mv_u3d *u3d = container_of(g, struct mv_u3d, gadget); - struct mv_usb_platform_data *pdata = u3d->dev->platform_data; + struct mv_usb_platform_data *pdata = dev_get_platdata(u3d->dev); unsigned long flags; u3d->vbus_valid_detect = 0; @@ -1794,12 +1794,12 @@ static int mv_u3d_remove(struct platform_device *dev) static int mv_u3d_probe(struct platform_device *dev) { struct mv_u3d *u3d = NULL; - struct mv_usb_platform_data *pdata = dev->dev.platform_data; + struct mv_usb_platform_data *pdata = dev_get_platdata(&dev->dev); int retval = 0; struct resource *r; size_t size; - if (!dev->dev.platform_data) { + if (!dev_get_platdata(&dev->dev)) { dev_err(&dev->dev, "missing platform_data\n"); retval = -ENODEV; goto err_pdata; diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index c2a57023e467..104cdbea635a 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c @@ -2100,7 +2100,7 @@ static int mv_udc_remove(struct platform_device *pdev) static int mv_udc_probe(struct platform_device *pdev) { - struct mv_usb_platform_data *pdata = pdev->dev.platform_data; + struct mv_usb_platform_data *pdata = dev_get_platdata(&pdev->dev); struct mv_udc *udc; int retval = 0; struct resource *r; @@ -2118,7 +2118,7 @@ static int mv_udc_probe(struct platform_device *pdev) } udc->done = &release_done; - udc->pdata = pdev->dev.platform_data; + udc->pdata = dev_get_platdata(&pdev->dev); spin_lock_init(&udc->lock); udc->dev = pdev; diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index b8ed74a823cb..83957cc225d9 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -2734,7 +2734,7 @@ static int omap_udc_probe(struct platform_device *pdev) int hmc; struct usb_phy *xceiv = NULL; const char *type = NULL; - struct omap_usb_config *config = pdev->dev.platform_data; + struct omap_usb_config *config = dev_get_platdata(&pdev->dev); struct clk *dc_clk = NULL; struct clk *hhc_clk = NULL; diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c index 95c531d5aa4f..cc9207473dbc 100644 --- a/drivers/usb/gadget/pxa25x_udc.c +++ b/drivers/usb/gadget/pxa25x_udc.c @@ -2117,7 +2117,7 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev) /* other non-static parts of init */ dev->dev = &pdev->dev; - dev->mach = pdev->dev.platform_data; + dev->mach = dev_get_platdata(&pdev->dev); dev->transceiver = usb_get_phy(USB_PHY_TYPE_USB2); diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index 41cea9566ac8..3c97da7760da 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -2422,7 +2422,7 @@ static int pxa_udc_probe(struct platform_device *pdev) return udc->irq; udc->dev = &pdev->dev; - udc->mach = pdev->dev.platform_data; + udc->mach = dev_get_platdata(&pdev->dev); udc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2); gpio = udc->mach->gpio_pullup; diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c index c6af649f3240..68be48d33404 100644 --- a/drivers/usb/gadget/r8a66597-udc.c +++ b/drivers/usb/gadget/r8a66597-udc.c @@ -1910,7 +1910,7 @@ static int __init r8a66597_probe(struct platform_device *pdev) spin_lock_init(&r8a66597->lock); platform_set_drvdata(pdev, r8a66597); - r8a66597->pdata = pdev->dev.platform_data; + r8a66597->pdata = dev_get_platdata(&pdev->dev); r8a66597->irq_sense_low = irq_trigger == IRQF_TRIGGER_LOW; r8a66597->gadget.ops = &r8a66597_gadget_ops; diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index 616ed51f8585..d69b36a99dbc 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -3451,7 +3451,7 @@ static void s3c_hsotg_delete_debug(struct s3c_hsotg *hsotg) static int s3c_hsotg_probe(struct platform_device *pdev) { - struct s3c_hsotg_plat *plat = pdev->dev.platform_data; + struct s3c_hsotg_plat *plat = dev_get_platdata(&pdev->dev); struct usb_phy *phy; struct device *dev = &pdev->dev; struct s3c_hsotg_ep *eps; @@ -3470,7 +3470,7 @@ static int s3c_hsotg_probe(struct platform_device *pdev) phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); if (IS_ERR(phy)) { /* Fallback for pdata */ - plat = pdev->dev.platform_data; + plat = dev_get_platdata(&pdev->dev); if (!plat) { dev_err(&pdev->dev, "no platform data or transceiver defined\n"); return -EPROBE_DEFER; diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c index b1f0771fbd3d..1a1a41498db2 100644 --- a/drivers/usb/gadget/s3c-hsudc.c +++ b/drivers/usb/gadget/s3c-hsudc.c @@ -1262,7 +1262,7 @@ static int s3c_hsudc_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct resource *res; struct s3c_hsudc *hsudc; - struct s3c24xx_hsudc_platdata *pd = pdev->dev.platform_data; + struct s3c24xx_hsudc_platdata *pd = dev_get_platdata(&pdev->dev); int ret, i; hsudc = devm_kzalloc(&pdev->dev, sizeof(struct s3c_hsudc) + @@ -1275,7 +1275,7 @@ static int s3c_hsudc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, dev); hsudc->dev = dev; - hsudc->pd = pdev->dev.platform_data; + hsudc->pd = dev_get_platdata(&pdev->dev); hsudc->transceiver = usb_get_phy(USB_PHY_TYPE_USB2); diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c index 09c4f70c93c4..c72d810e6b36 100644 --- a/drivers/usb/gadget/s3c2410_udc.c +++ b/drivers/usb/gadget/s3c2410_udc.c @@ -1809,7 +1809,7 @@ static int s3c2410_udc_probe(struct platform_device *pdev) } spin_lock_init(&udc->lock); - udc_info = pdev->dev.platform_data; + udc_info = dev_get_platdata(&pdev->dev); rsrc_start = S3C2410_PA_USBDEV; rsrc_len = S3C24XX_SZ_USBDEV; From 19f9e188deb4bbcd5fc588f39dc63bdfa9103827 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 30 Jul 2013 17:02:13 +0900 Subject: [PATCH 1092/3400] usb: phy: use dev_get_platdata() Use the wrapper function for retrieving the platform data instead of accessing dev->platform_data directly. Signed-off-by: Jingoo Han Signed-off-by: Felipe Balbi --- drivers/usb/phy/phy-fsl-usb.c | 6 +++--- drivers/usb/phy/phy-gpio-vbus-usb.c | 10 +++++----- drivers/usb/phy/phy-msm-usb.c | 4 ++-- drivers/usb/phy/phy-mv-u3d-usb.c | 2 +- drivers/usb/phy/phy-mv-usb.c | 2 +- drivers/usb/phy/phy-nop.c | 3 ++- drivers/usb/phy/phy-omap-control.c | 3 ++- drivers/usb/phy/phy-rcar-usb.c | 4 ++-- drivers/usb/phy/phy-samsung-usb2.c | 2 +- drivers/usb/phy/phy-samsung-usb3.c | 2 +- drivers/usb/phy/phy-twl4030-usb.c | 2 +- drivers/usb/phy/phy-twl6030-usb.c | 2 +- 12 files changed, 22 insertions(+), 20 deletions(-) diff --git a/drivers/usb/phy/phy-fsl-usb.c b/drivers/usb/phy/phy-fsl-usb.c index e771bafb9f1d..e965cf65d696 100644 --- a/drivers/usb/phy/phy-fsl-usb.c +++ b/drivers/usb/phy/phy-fsl-usb.c @@ -834,7 +834,7 @@ int usb_otg_start(struct platform_device *pdev) int status; struct resource *res; u32 temp; - struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; + struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev); p_otg = container_of(otg_trans, struct fsl_otg, phy); fsm = &p_otg->fsm; @@ -1105,7 +1105,7 @@ static int fsl_otg_probe(struct platform_device *pdev) { int ret; - if (!pdev->dev.platform_data) + if (!dev_get_platdata(&pdev->dev)) return -ENODEV; /* configure the OTG */ @@ -1137,7 +1137,7 @@ static int fsl_otg_probe(struct platform_device *pdev) static int fsl_otg_remove(struct platform_device *pdev) { - struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; + struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev); usb_remove_phy(&fsl_otg_dev->phy); free_irq(fsl_otg_dev->irq, fsl_otg_dev); diff --git a/drivers/usb/phy/phy-gpio-vbus-usb.c b/drivers/usb/phy/phy-gpio-vbus-usb.c index 8443335c2ea0..b2f29c9aebbf 100644 --- a/drivers/usb/phy/phy-gpio-vbus-usb.c +++ b/drivers/usb/phy/phy-gpio-vbus-usb.c @@ -101,7 +101,7 @@ static void gpio_vbus_work(struct work_struct *work) { struct gpio_vbus_data *gpio_vbus = container_of(work, struct gpio_vbus_data, work.work); - struct gpio_vbus_mach_info *pdata = gpio_vbus->dev->platform_data; + struct gpio_vbus_mach_info *pdata = dev_get_platdata(gpio_vbus->dev); int gpio, status, vbus; if (!gpio_vbus->phy.otg->gadget) @@ -155,7 +155,7 @@ static void gpio_vbus_work(struct work_struct *work) 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_mach_info *pdata = dev_get_platdata(&pdev->dev); struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev); struct usb_otg *otg = gpio_vbus->phy.otg; @@ -182,7 +182,7 @@ static int gpio_vbus_set_peripheral(struct usb_otg *otg, gpio_vbus = container_of(otg->phy, struct gpio_vbus_data, phy); pdev = to_platform_device(gpio_vbus->dev); - pdata = gpio_vbus->dev->platform_data; + pdata = dev_get_platdata(gpio_vbus->dev); gpio = pdata->gpio_pullup; if (!gadget) { @@ -243,7 +243,7 @@ static int gpio_vbus_set_suspend(struct usb_phy *phy, int suspend) static int __init gpio_vbus_probe(struct platform_device *pdev) { - struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data; + struct gpio_vbus_mach_info *pdata = dev_get_platdata(&pdev->dev); struct gpio_vbus_data *gpio_vbus; struct resource *res; int err, gpio, irq; @@ -352,7 +352,7 @@ err_gpio: static int __exit gpio_vbus_remove(struct platform_device *pdev) { struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev); - struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data; + struct gpio_vbus_mach_info *pdata = dev_get_platdata(&pdev->dev); int gpio = pdata->gpio_vbus; device_init_wakeup(&pdev->dev, 0); diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c index d08f33435e96..e9d4cd960ecd 100644 --- a/drivers/usb/phy/phy-msm-usb.c +++ b/drivers/usb/phy/phy-msm-usb.c @@ -1419,7 +1419,7 @@ static int __init msm_otg_probe(struct platform_device *pdev) struct usb_phy *phy; dev_info(&pdev->dev, "msm_otg probe\n"); - if (!pdev->dev.platform_data) { + if (!dev_get_platdata(&pdev->dev)) { dev_err(&pdev->dev, "No platform data given. Bailing out\n"); return -ENODEV; } @@ -1436,7 +1436,7 @@ static int __init msm_otg_probe(struct platform_device *pdev) return -ENOMEM; } - motg->pdata = pdev->dev.platform_data; + motg->pdata = dev_get_platdata(&pdev->dev); phy = &motg->phy; phy->dev = &pdev->dev; diff --git a/drivers/usb/phy/phy-mv-u3d-usb.c b/drivers/usb/phy/phy-mv-u3d-usb.c index 1568ea63e338..6688023021d3 100644 --- a/drivers/usb/phy/phy-mv-u3d-usb.c +++ b/drivers/usb/phy/phy-mv-u3d-usb.c @@ -271,7 +271,7 @@ static int mv_u3d_phy_probe(struct platform_device *pdev) void __iomem *phy_base; int ret; - pdata = pdev->dev.platform_data; + pdata = dev_get_platdata(&pdev->dev); if (!pdata) { dev_err(&pdev->dev, "%s: no platform data defined\n", __func__); return -EINVAL; diff --git a/drivers/usb/phy/phy-mv-usb.c b/drivers/usb/phy/phy-mv-usb.c index 4a6b03c73876..03d16ff24c02 100644 --- a/drivers/usb/phy/phy-mv-usb.c +++ b/drivers/usb/phy/phy-mv-usb.c @@ -673,7 +673,7 @@ int mv_otg_remove(struct platform_device *pdev) static int mv_otg_probe(struct platform_device *pdev) { - struct mv_usb_platform_data *pdata = pdev->dev.platform_data; + struct mv_usb_platform_data *pdata = dev_get_platdata(&pdev->dev); struct mv_otg *mvotg; struct usb_otg *otg; struct resource *r; diff --git a/drivers/usb/phy/phy-nop.c b/drivers/usb/phy/phy-nop.c index 55445e5d72e5..f52b7f89eef1 100644 --- a/drivers/usb/phy/phy-nop.c +++ b/drivers/usb/phy/phy-nop.c @@ -142,7 +142,8 @@ static int nop_set_host(struct usb_otg *otg, struct usb_bus *host) static int nop_usb_xceiv_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct nop_usb_xceiv_platform_data *pdata = pdev->dev.platform_data; + struct nop_usb_xceiv_platform_data *pdata = + dev_get_platdata(&pdev->dev); struct nop_usb_xceiv *nop; enum usb_phy_type type = USB_PHY_TYPE_USB2; int err; diff --git a/drivers/usb/phy/phy-omap-control.c b/drivers/usb/phy/phy-omap-control.c index 1419ceda9759..a4dda8e12562 100644 --- a/drivers/usb/phy/phy-omap-control.c +++ b/drivers/usb/phy/phy-omap-control.c @@ -197,7 +197,8 @@ static int omap_control_usb_probe(struct platform_device *pdev) { struct resource *res; struct device_node *np = pdev->dev.of_node; - struct omap_control_usb_platform_data *pdata = pdev->dev.platform_data; + struct omap_control_usb_platform_data *pdata = + dev_get_platdata(&pdev->dev); control_usb = devm_kzalloc(&pdev->dev, sizeof(*control_usb), GFP_KERNEL); diff --git a/drivers/usb/phy/phy-rcar-usb.c b/drivers/usb/phy/phy-rcar-usb.c index deb7f97f37c7..33265a5b2cdf 100644 --- a/drivers/usb/phy/phy-rcar-usb.c +++ b/drivers/usb/phy/phy-rcar-usb.c @@ -83,7 +83,7 @@ static int rcar_usb_phy_init(struct usb_phy *phy) { struct rcar_usb_phy_priv *priv = usb_phy_to_priv(phy); struct device *dev = phy->dev; - struct rcar_phy_platform_data *pdata = dev->platform_data; + struct rcar_phy_platform_data *pdata = dev_get_platdata(dev); void __iomem *reg0 = priv->reg0; void __iomem *reg1 = priv->reg1; static const u8 ovcn_act[] = { OVC0_ACT, OVC1_ACT, OVC2_ACT }; @@ -184,7 +184,7 @@ static int rcar_usb_phy_probe(struct platform_device *pdev) void __iomem *reg0, *reg1 = NULL; int ret; - if (!pdev->dev.platform_data) { + if (!dev_get_platdata(&pdev->dev)) { dev_err(dev, "No platform data\n"); return -EINVAL; } diff --git a/drivers/usb/phy/phy-samsung-usb2.c b/drivers/usb/phy/phy-samsung-usb2.c index 758b86d0fcb3..ff70e4b19b97 100644 --- a/drivers/usb/phy/phy-samsung-usb2.c +++ b/drivers/usb/phy/phy-samsung-usb2.c @@ -359,7 +359,7 @@ static int samsung_usb2phy_probe(struct platform_device *pdev) { struct samsung_usbphy *sphy; struct usb_otg *otg; - struct samsung_usbphy_data *pdata = pdev->dev.platform_data; + struct samsung_usbphy_data *pdata = dev_get_platdata(&pdev->dev); const struct samsung_usbphy_drvdata *drv_data; struct device *dev = &pdev->dev; struct resource *phy_mem; diff --git a/drivers/usb/phy/phy-samsung-usb3.c b/drivers/usb/phy/phy-samsung-usb3.c index 300e0cf5e31f..c6eb22213de6 100644 --- a/drivers/usb/phy/phy-samsung-usb3.c +++ b/drivers/usb/phy/phy-samsung-usb3.c @@ -231,7 +231,7 @@ static void samsung_usb3phy_shutdown(struct usb_phy *phy) static int samsung_usb3phy_probe(struct platform_device *pdev) { struct samsung_usbphy *sphy; - struct samsung_usbphy_data *pdata = pdev->dev.platform_data; + struct samsung_usbphy_data *pdata = dev_get_platdata(&pdev->dev); struct device *dev = &pdev->dev; struct resource *phy_mem; void __iomem *phy_base; diff --git a/drivers/usb/phy/phy-twl4030-usb.c b/drivers/usb/phy/phy-twl4030-usb.c index 8f78d2d40722..90730c8762b8 100644 --- a/drivers/usb/phy/phy-twl4030-usb.c +++ b/drivers/usb/phy/phy-twl4030-usb.c @@ -648,7 +648,7 @@ static int twl4030_set_host(struct usb_otg *otg, struct usb_bus *host) static int twl4030_usb_probe(struct platform_device *pdev) { - struct twl4030_usb_data *pdata = pdev->dev.platform_data; + struct twl4030_usb_data *pdata = dev_get_platdata(&pdev->dev); struct twl4030_usb *twl; int status, err; struct usb_otg *otg; diff --git a/drivers/usb/phy/phy-twl6030-usb.c b/drivers/usb/phy/phy-twl6030-usb.c index 1753bd367e0a..16dbc9382678 100644 --- a/drivers/usb/phy/phy-twl6030-usb.c +++ b/drivers/usb/phy/phy-twl6030-usb.c @@ -324,7 +324,7 @@ static int twl6030_usb_probe(struct platform_device *pdev) int status, err; struct device_node *np = pdev->dev.of_node; struct device *dev = &pdev->dev; - struct twl4030_usb_data *pdata = dev->platform_data; + struct twl4030_usb_data *pdata = dev_get_platdata(dev); twl = devm_kzalloc(dev, sizeof *twl, GFP_KERNEL); if (!twl) From c1a7d67c1901347bdb3d06536cd69d018fbf2c4b Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 30 Jul 2013 17:03:12 +0900 Subject: [PATCH 1093/3400] usb: musb: use dev_get_platdata() Use the wrapper function for retrieving the platform data instead of accessing dev->platform_data directly. Signed-off-by: Jingoo Han Signed-off-by: Felipe Balbi --- drivers/usb/musb/am35x.c | 14 +++++++------- drivers/usb/musb/blackfin.c | 2 +- drivers/usb/musb/da8xx.c | 2 +- drivers/usb/musb/davinci.c | 2 +- drivers/usb/musb/musb_core.c | 2 +- drivers/usb/musb/musb_dsps.c | 2 +- drivers/usb/musb/omap2430.c | 8 ++++---- drivers/usb/musb/tusb6010.c | 2 +- drivers/usb/musb/ux500.c | 2 +- drivers/usb/musb/ux500_dma.c | 2 +- 10 files changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c index 2231850c0625..baebc39a571b 100644 --- a/drivers/usb/musb/am35x.c +++ b/drivers/usb/musb/am35x.c @@ -218,7 +218,7 @@ static irqreturn_t am35x_musb_interrupt(int irq, void *hci) struct musb *musb = hci; void __iomem *reg_base = musb->ctrl_base; struct device *dev = musb->controller; - struct musb_hdrc_platform_data *plat = dev->platform_data; + struct musb_hdrc_platform_data *plat = dev_get_platdata(dev); struct omap_musb_board_data *data = plat->board_data; struct usb_otg *otg = musb->xceiv->otg; unsigned long flags; @@ -335,7 +335,7 @@ eoi: static int am35x_musb_set_mode(struct musb *musb, u8 musb_mode) { struct device *dev = musb->controller; - struct musb_hdrc_platform_data *plat = dev->platform_data; + struct musb_hdrc_platform_data *plat = dev_get_platdata(dev); struct omap_musb_board_data *data = plat->board_data; int retval = 0; @@ -350,7 +350,7 @@ static int am35x_musb_set_mode(struct musb *musb, u8 musb_mode) static int am35x_musb_init(struct musb *musb) { struct device *dev = musb->controller; - struct musb_hdrc_platform_data *plat = dev->platform_data; + struct musb_hdrc_platform_data *plat = dev_get_platdata(dev); struct omap_musb_board_data *data = plat->board_data; void __iomem *reg_base = musb->ctrl_base; u32 rev; @@ -394,7 +394,7 @@ static int am35x_musb_init(struct musb *musb) static int am35x_musb_exit(struct musb *musb) { struct device *dev = musb->controller; - struct musb_hdrc_platform_data *plat = dev->platform_data; + struct musb_hdrc_platform_data *plat = dev_get_platdata(dev); struct omap_musb_board_data *data = plat->board_data; del_timer_sync(&otg_workaround); @@ -456,7 +456,7 @@ static u64 am35x_dmamask = DMA_BIT_MASK(32); static int am35x_probe(struct platform_device *pdev) { - struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; + struct musb_hdrc_platform_data *pdata = dev_get_platdata(&pdev->dev); struct platform_device *musb; struct am35x_glue *glue; @@ -577,7 +577,7 @@ static int am35x_remove(struct platform_device *pdev) static int am35x_suspend(struct device *dev) { struct am35x_glue *glue = dev_get_drvdata(dev); - struct musb_hdrc_platform_data *plat = dev->platform_data; + struct musb_hdrc_platform_data *plat = dev_get_platdata(dev); struct omap_musb_board_data *data = plat->board_data; /* Shutdown the on-chip PHY and its PLL. */ @@ -593,7 +593,7 @@ static int am35x_suspend(struct device *dev) static int am35x_resume(struct device *dev) { struct am35x_glue *glue = dev_get_drvdata(dev); - struct musb_hdrc_platform_data *plat = dev->platform_data; + struct musb_hdrc_platform_data *plat = dev_get_platdata(dev); struct omap_musb_board_data *data = plat->board_data; int ret; diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c index 6ba8439bd5a6..3e63379ec469 100644 --- a/drivers/usb/musb/blackfin.c +++ b/drivers/usb/musb/blackfin.c @@ -451,7 +451,7 @@ static u64 bfin_dmamask = DMA_BIT_MASK(32); static int bfin_probe(struct platform_device *pdev) { struct resource musb_resources[2]; - struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; + struct musb_hdrc_platform_data *pdata = dev_get_platdata(&pdev->dev); struct platform_device *musb; struct bfin_glue *glue; diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c index 0da6f648a9fe..7a46521c0800 100644 --- a/drivers/usb/musb/da8xx.c +++ b/drivers/usb/musb/da8xx.c @@ -477,7 +477,7 @@ static u64 da8xx_dmamask = DMA_BIT_MASK(32); static int da8xx_probe(struct platform_device *pdev) { struct resource musb_resources[2]; - struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; + struct musb_hdrc_platform_data *pdata = dev_get_platdata(&pdev->dev); struct platform_device *musb; struct da8xx_glue *glue; diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index f8aeaf2e2cd1..12ab66d26d8f 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c @@ -510,7 +510,7 @@ static u64 davinci_dmamask = DMA_BIT_MASK(32); static int davinci_probe(struct platform_device *pdev) { struct resource musb_resources[2]; - struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; + struct musb_hdrc_platform_data *pdata = dev_get_platdata(&pdev->dev); struct platform_device *musb; struct davinci_glue *glue; struct clk *clk; diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 80ffd7ee55df..b9d741614f8c 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1783,7 +1783,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) { int status; struct musb *musb; - struct musb_hdrc_platform_data *plat = dev->platform_data; + struct musb_hdrc_platform_data *plat = dev_get_platdata(dev); /* The driver might handle more features than the board; OK. * Fail when the board needs a feature that's not enabled. diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 23f511f7df6d..4816b2f972d0 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -478,7 +478,7 @@ static int dsps_create_musb_pdev(struct dsps_glue *glue, u8 id) { struct device *dev = glue->dev; struct platform_device *pdev = to_platform_device(dev); - struct musb_hdrc_platform_data *pdata = dev->platform_data; + struct musb_hdrc_platform_data *pdata = dev_get_platdata(dev); struct device_node *np = pdev->dev.of_node; struct musb_hdrc_config *config; struct platform_device *musb; diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 6708a3b78ad8..ebb46eca1791 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -255,7 +255,7 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue) { struct musb *musb = glue_to_musb(glue); struct device *dev = musb->controller; - struct musb_hdrc_platform_data *pdata = dev->platform_data; + struct musb_hdrc_platform_data *pdata = dev_get_platdata(dev); struct omap_musb_board_data *data = pdata->board_data; struct usb_otg *otg = musb->xceiv->otg; @@ -341,7 +341,7 @@ static int omap2430_musb_init(struct musb *musb) int status = 0; struct device *dev = musb->controller; struct omap2430_glue *glue = dev_get_drvdata(dev->parent); - struct musb_hdrc_platform_data *plat = dev->platform_data; + struct musb_hdrc_platform_data *plat = dev_get_platdata(dev); struct omap_musb_board_data *data = plat->board_data; /* We require some kind of external transceiver, hooked @@ -412,7 +412,7 @@ static void omap2430_musb_enable(struct musb *musb) unsigned long timeout = jiffies + msecs_to_jiffies(1000); struct device *dev = musb->controller; struct omap2430_glue *glue = dev_get_drvdata(dev->parent); - struct musb_hdrc_platform_data *pdata = dev->platform_data; + struct musb_hdrc_platform_data *pdata = dev_get_platdata(dev); struct omap_musb_board_data *data = pdata->board_data; switch (glue->status) { @@ -482,7 +482,7 @@ static u64 omap2430_dmamask = DMA_BIT_MASK(32); static int omap2430_probe(struct platform_device *pdev) { struct resource musb_resources[2]; - struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; + struct musb_hdrc_platform_data *pdata = dev_get_platdata(&pdev->dev); struct omap_musb_board_data *data; struct platform_device *musb; struct omap2430_glue *glue; diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index 2c06a8969a9f..2196ee6e79fe 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c @@ -1157,7 +1157,7 @@ static u64 tusb_dmamask = DMA_BIT_MASK(32); static int tusb_probe(struct platform_device *pdev) { struct resource musb_resources[2]; - struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; + struct musb_hdrc_platform_data *pdata = dev_get_platdata(&pdev->dev); struct platform_device *musb; struct tusb6010_glue *glue; diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c index fce71b605936..59256b12f746 100644 --- a/drivers/usb/musb/ux500.c +++ b/drivers/usb/musb/ux500.c @@ -227,7 +227,7 @@ ux500_of_probe(struct platform_device *pdev, struct device_node *np) static int ux500_probe(struct platform_device *pdev) { struct resource musb_resources[2]; - struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; + struct musb_hdrc_platform_data *pdata = dev_get_platdata(&pdev->dev); struct device_node *np = pdev->dev.of_node; struct platform_device *musb; struct ux500_glue *glue; diff --git a/drivers/usb/musb/ux500_dma.c b/drivers/usb/musb/ux500_dma.c index 1ce214e5b7ad..e51dd9b88e71 100644 --- a/drivers/usb/musb/ux500_dma.c +++ b/drivers/usb/musb/ux500_dma.c @@ -286,7 +286,7 @@ static int ux500_dma_controller_start(struct ux500_dma_controller *controller) struct ux500_dma_channel *ux500_channel = NULL; struct musb *musb = controller->private_data; struct device *dev = musb->controller; - struct musb_hdrc_platform_data *plat = dev->platform_data; + struct musb_hdrc_platform_data *plat = dev_get_platdata(dev); struct ux500_musb_board_data *data; struct dma_channel *dma_channel = NULL; char **chan_names; From f074245960e8fec9948eb8022322e43670ace4e5 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 30 Jul 2013 17:06:20 +0900 Subject: [PATCH 1094/3400] usb: renesas: use dev_get_platdata() Use the wrapper function for retrieving the platform data instead of accessing dev->platform_data directly. Signed-off-by: Jingoo Han Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c index cfd205036aba..3b39757c13bc 100644 --- a/drivers/usb/renesas_usbhs/common.c +++ b/drivers/usb/renesas_usbhs/common.c @@ -416,7 +416,7 @@ static int usbhsc_drvcllbck_notify_hotplug(struct platform_device *pdev) */ static int usbhs_probe(struct platform_device *pdev) { - struct renesas_usbhs_platform_info *info = pdev->dev.platform_data; + struct renesas_usbhs_platform_info *info = dev_get_platdata(&pdev->dev); struct renesas_usbhs_driver_callback *dfunc; struct usbhs_priv *priv; struct resource *res, *irq_res; @@ -558,7 +558,7 @@ probe_end_pipe_exit: static int usbhs_remove(struct platform_device *pdev) { struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev); - struct renesas_usbhs_platform_info *info = pdev->dev.platform_data; + struct renesas_usbhs_platform_info *info = dev_get_platdata(&pdev->dev); struct renesas_usbhs_driver_callback *dfunc = &info->driver_callback; dev_dbg(&pdev->dev, "usb remove\n"); From d9493234e20e8153495fa118b60bdff22fdfc6c8 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 30 Jul 2013 10:46:28 +0800 Subject: [PATCH 1095/3400] regulator: pfuze100: Fix n_voltages setting for SW2~SW4 with high bit set Current code adjust min_uV and uV_step but missed adjusting the n_voltages setting. When BIT6 is clear: n_voltages = (1975000 - 400000) / 25000 + 1 = 64 When BIT6 is set: n_voltages = (3300000 - 800000) / 50000 + 1 = 51 The n_voltages needs update because when BIT6 is set 0x73 ~ 0x7f are reserved. When using regulator_list_voltage_linear, the n_voltages does matter here because wrong n_voltages setting make the equation return wrong result. e.g. if selector is 63, regulator_list_voltage_linear returns 800000 + (50000 * 63) = 4000000 It should return -EINVAL if the selector is in the range of 51 ~ 63. Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/regulator/pfuze100-regulator.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c index 7b24acb66a18..e02d9b921ed3 100644 --- a/drivers/regulator/pfuze100-regulator.c +++ b/drivers/regulator/pfuze100-regulator.c @@ -388,8 +388,11 @@ static int pfuze100_regulator_probe(struct i2c_client *client, for (i = 0; i < PFUZE100_MAX_REGULATOR; i++) { struct regulator_init_data *init_data; + struct regulator_desc *desc; int val; + desc = &pfuze_chip->regulator_descs[i].desc; + if (pdata) init_data = pdata->init_data[i]; else @@ -397,13 +400,11 @@ static int pfuze100_regulator_probe(struct i2c_client *client, /* SW2~SW4 high bit check and modify the voltage value table */ if (i > PFUZE100_SW1C && i < PFUZE100_SWBST) { - regmap_read(pfuze_chip->regmap, PFUZE100_SW2VOL + - (i - PFUZE100_SW2) * 7, &val); + regmap_read(pfuze_chip->regmap, desc->vsel_reg, &val); if (val & 0x40) { - pfuze_chip->regulator_descs[i].desc.min_uV - = 800000; - pfuze_chip->regulator_descs[i].desc.uV_step - = 50000; + desc->min_uV = 800000; + desc->uV_step = 50000; + desc->n_voltages = 51; } } @@ -412,8 +413,7 @@ static int pfuze100_regulator_probe(struct i2c_client *client, config.driver_data = pfuze_chip; config.of_node = match_of_node(i); - pfuze_chip->regulators[i] = regulator_register(&pfuze_chip - ->regulator_descs[i].desc, &config); + pfuze_chip->regulators[i] = regulator_register(desc, &config); if (IS_ERR(pfuze_chip->regulators[i])) { dev_err(&client->dev, "register regulator%s failed\n", pfuze100_regulators[i].desc.name); From 7dedd346941d317b6b313de4746ad0354006e68b Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Sun, 28 Jul 2013 23:01:48 -0600 Subject: [PATCH 1096/3400] ARM: OMAP2+: hwmod: Fix a crash in _setup_reset() with DEBUG_LL With commit '82702ea11ddfe0e43382e1fa5b66d807d8114916' "ARM: OMAP2+: Fix serial init for device tree based booting" stubbing out omap_serial_early_init() for Device tree based booting, there was a crash observed on AM335x based devices when hwmod does a _setup_reset() early at boot. This was rootcaused to hwmod trying to reset console uart while earlycon was using it. The way to tell hwmod not to do this is to specify the HWMOD_INIT_NO_RESET flag, which were infact set by the omap_serial_early_init() function by parsing the cmdline to identify the console device. Parsing the cmdline to identify the uart used by earlycon itself seems broken as there is nothing preventing earlycon to use a different one. This patch, instead, attempts to populate the requiste flags for hwmod based on the CONFIG_DEBUG_OMAPxUARTy FLAGS. This gets rid of the need for cmdline parsing in the DT as well as non-DT cases to identify the uart used by earlycon. Signed-off-by: Rajendra Nayak Reported-by: Mark Jackson Reported-by: Vaibhav Bedia Tested-by: Mark Jackson Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod.h | 48 +++++++++++++++++++ .../mach-omap2/omap_hwmod_2xxx_ipblock_data.c | 6 +-- arch/arm/mach-omap2/omap_hwmod_33xx_data.c | 2 +- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 9 ++-- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 5 +- arch/arm/mach-omap2/omap_hwmod_54xx_data.c | 3 +- arch/arm/mach-omap2/serial.c | 11 ----- 7 files changed, 61 insertions(+), 23 deletions(-) diff --git a/arch/arm/mach-omap2/omap_hwmod.h b/arch/arm/mach-omap2/omap_hwmod.h index aab33fd814c0..8440a21fc60a 100644 --- a/arch/arm/mach-omap2/omap_hwmod.h +++ b/arch/arm/mach-omap2/omap_hwmod.h @@ -95,6 +95,54 @@ extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type3; #define MODULEMODE_HWCTRL 1 #define MODULEMODE_SWCTRL 2 +#define DEBUG_OMAP2UART1_FLAGS 0 +#define DEBUG_OMAP2UART2_FLAGS 0 +#define DEBUG_OMAP2UART3_FLAGS 0 +#define DEBUG_OMAP3UART3_FLAGS 0 +#define DEBUG_OMAP3UART4_FLAGS 0 +#define DEBUG_OMAP4UART3_FLAGS 0 +#define DEBUG_OMAP4UART4_FLAGS 0 +#define DEBUG_TI81XXUART1_FLAGS 0 +#define DEBUG_TI81XXUART2_FLAGS 0 +#define DEBUG_TI81XXUART3_FLAGS 0 +#define DEBUG_AM33XXUART1_FLAGS 0 + +#define DEBUG_OMAPUART_FLAGS (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET) + +#if defined(CONFIG_DEBUG_OMAP2UART1) +#undef DEBUG_OMAP2UART1_FLAGS +#define DEBUG_OMAP2UART1_FLAGS DEBUG_OMAPUART_FLAGS +#elif defined(CONFIG_DEBUG_OMAP2UART2) +#undef DEBUG_OMAP2UART2_FLAGS +#define DEBUG_OMAP2UART2_FLAGS DEBUG_OMAPUART_FLAGS +#elif defined(CONFIG_DEBUG_OMAP2UART3) +#undef DEBUG_OMAP2UART3_FLAGS +#define DEBUG_OMAP2UART3_FLAGS DEBUG_OMAPUART_FLAGS +#elif defined(CONFIG_DEBUG_OMAP3UART3) +#undef DEBUG_OMAP3UART3_FLAGS +#define DEBUG_OMAP3UART3_FLAGS DEBUG_OMAPUART_FLAGS +#elif defined(CONFIG_DEBUG_OMAP3UART4) +#undef DEBUG_OMAP3UART4_FLAGS +#define DEBUG_OMAP3UART4_FLAGS DEBUG_OMAPUART_FLAGS +#elif defined(CONFIG_DEBUG_OMAP4UART3) +#undef DEBUG_OMAP4UART3_FLAGS +#define DEBUG_OMAP4UART3_FLAGS DEBUG_OMAPUART_FLAGS +#elif defined(CONFIG_DEBUG_OMAP4UART4) +#undef DEBUG_OMAP4UART4_FLAGS +#define DEBUG_OMAP4UART4_FLAGS DEBUG_OMAPUART_FLAGS +#elif defined(CONFIG_DEBUG_TI81XXUART1) +#undef DEBUG_TI81XXUART1_FLAGS +#define DEBUG_TI81XXUART1_FLAGS DEBUG_OMAPUART_FLAGS +#elif defined(CONFIG_DEBUG_TI81XXUART2) +#undef DEBUG_TI81XXUART2_FLAGS +#define DEBUG_TI81XXUART2_FLAGS DEBUG_OMAPUART_FLAGS +#elif defined(CONFIG_DEBUG_TI81XXUART3) +#undef DEBUG_TI81XXUART3_FLAGS +#define DEBUG_TI81XXUART3_FLAGS DEBUG_OMAPUART_FLAGS +#elif defined(CONFIG_DEBUG_AM33XXUART1) +#undef DEBUG_AM33XXUART1_FLAGS +#define DEBUG_AM33XXUART1_FLAGS DEBUG_OMAPUART_FLAGS +#endif /** * struct omap_hwmod_mux_info - hwmod specific mux configuration diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c index d05fc7b54567..56cebb05509e 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c @@ -512,7 +512,7 @@ struct omap_hwmod omap2xxx_uart1_hwmod = { .mpu_irqs = omap2_uart1_mpu_irqs, .sdma_reqs = omap2_uart1_sdma_reqs, .main_clk = "uart1_fck", - .flags = HWMOD_SWSUP_SIDLE_ACT, + .flags = DEBUG_OMAP2UART1_FLAGS | HWMOD_SWSUP_SIDLE_ACT, .prcm = { .omap2 = { .module_offs = CORE_MOD, @@ -532,7 +532,7 @@ struct omap_hwmod omap2xxx_uart2_hwmod = { .mpu_irqs = omap2_uart2_mpu_irqs, .sdma_reqs = omap2_uart2_sdma_reqs, .main_clk = "uart2_fck", - .flags = HWMOD_SWSUP_SIDLE_ACT, + .flags = DEBUG_OMAP2UART2_FLAGS | HWMOD_SWSUP_SIDLE_ACT, .prcm = { .omap2 = { .module_offs = CORE_MOD, @@ -552,7 +552,7 @@ struct omap_hwmod omap2xxx_uart3_hwmod = { .mpu_irqs = omap2_uart3_mpu_irqs, .sdma_reqs = omap2_uart3_sdma_reqs, .main_clk = "uart3_fck", - .flags = HWMOD_SWSUP_SIDLE_ACT, + .flags = DEBUG_OMAP2UART3_FLAGS | HWMOD_SWSUP_SIDLE_ACT, .prcm = { .omap2 = { .module_offs = CORE_MOD, diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c index 28bbd56346a9..d4114a919df7 100644 --- a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c @@ -1512,7 +1512,7 @@ static struct omap_hwmod am33xx_uart1_hwmod = { .name = "uart1", .class = &uart_class, .clkdm_name = "l4_wkup_clkdm", - .flags = HWMOD_SWSUP_SIDLE_ACT, + .flags = DEBUG_AM33XXUART1_FLAGS | HWMOD_SWSUP_SIDLE_ACT, .main_clk = "dpll_per_m2_div4_wkupdm_ck", .prcm = { .omap4 = { diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index f7a3df2fb579..0c3a427da544 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -490,7 +490,7 @@ static struct omap_hwmod omap3xxx_uart1_hwmod = { .mpu_irqs = omap2_uart1_mpu_irqs, .sdma_reqs = omap2_uart1_sdma_reqs, .main_clk = "uart1_fck", - .flags = HWMOD_SWSUP_SIDLE_ACT, + .flags = DEBUG_TI81XXUART1_FLAGS | HWMOD_SWSUP_SIDLE_ACT, .prcm = { .omap2 = { .module_offs = CORE_MOD, @@ -509,7 +509,7 @@ static struct omap_hwmod omap3xxx_uart2_hwmod = { .mpu_irqs = omap2_uart2_mpu_irqs, .sdma_reqs = omap2_uart2_sdma_reqs, .main_clk = "uart2_fck", - .flags = HWMOD_SWSUP_SIDLE_ACT, + .flags = DEBUG_TI81XXUART2_FLAGS | HWMOD_SWSUP_SIDLE_ACT, .prcm = { .omap2 = { .module_offs = CORE_MOD, @@ -528,7 +528,8 @@ static struct omap_hwmod omap3xxx_uart3_hwmod = { .mpu_irqs = omap2_uart3_mpu_irqs, .sdma_reqs = omap2_uart3_sdma_reqs, .main_clk = "uart3_fck", - .flags = HWMOD_SWSUP_SIDLE_ACT, + .flags = DEBUG_OMAP3UART3_FLAGS | DEBUG_TI81XXUART3_FLAGS | + HWMOD_SWSUP_SIDLE_ACT, .prcm = { .omap2 = { .module_offs = OMAP3430_PER_MOD, @@ -558,7 +559,7 @@ static struct omap_hwmod omap36xx_uart4_hwmod = { .mpu_irqs = uart4_mpu_irqs, .sdma_reqs = uart4_sdma_reqs, .main_clk = "uart4_fck", - .flags = HWMOD_SWSUP_SIDLE_ACT, + .flags = DEBUG_OMAP3UART4_FLAGS | HWMOD_SWSUP_SIDLE_ACT, .prcm = { .omap2 = { .module_offs = OMAP3430_PER_MOD, diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index d04b5e60fdbe..9c3b504477d7 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -2858,8 +2858,7 @@ static struct omap_hwmod omap44xx_uart3_hwmod = { .name = "uart3", .class = &omap44xx_uart_hwmod_class, .clkdm_name = "l4_per_clkdm", - .flags = HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET | - HWMOD_SWSUP_SIDLE_ACT, + .flags = DEBUG_OMAP4UART3_FLAGS | HWMOD_SWSUP_SIDLE_ACT, .main_clk = "func_48m_fclk", .prcm = { .omap4 = { @@ -2875,7 +2874,7 @@ static struct omap_hwmod omap44xx_uart4_hwmod = { .name = "uart4", .class = &omap44xx_uart_hwmod_class, .clkdm_name = "l4_per_clkdm", - .flags = HWMOD_SWSUP_SIDLE_ACT, + .flags = DEBUG_OMAP4UART4_FLAGS | HWMOD_SWSUP_SIDLE_ACT, .main_clk = "func_48m_fclk", .prcm = { .omap4 = { diff --git a/arch/arm/mach-omap2/omap_hwmod_54xx_data.c b/arch/arm/mach-omap2/omap_hwmod_54xx_data.c index f37ae96b70a1..3c70f5c1860f 100644 --- a/arch/arm/mach-omap2/omap_hwmod_54xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_54xx_data.c @@ -1375,7 +1375,7 @@ static struct omap_hwmod omap54xx_uart3_hwmod = { .name = "uart3", .class = &omap54xx_uart_hwmod_class, .clkdm_name = "l4per_clkdm", - .flags = HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET, + .flags = DEBUG_OMAP4UART3_FLAGS, .main_clk = "func_48m_fclk", .prcm = { .omap4 = { @@ -1391,6 +1391,7 @@ static struct omap_hwmod omap54xx_uart4_hwmod = { .name = "uart4", .class = &omap54xx_uart_hwmod_class, .clkdm_name = "l4per_clkdm", + .flags = DEBUG_OMAP4UART4_FLAGS, .main_clk = "func_48m_fclk", .prcm = { .omap4 = { diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index 3a674de6cb63..a388f8c1bcb3 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c @@ -208,17 +208,6 @@ static int __init omap_serial_early_init(void) pr_info("%s used as console in debug mode: uart%d clocks will not be gated", uart_name, uart->num); } - - /* - * omap-uart can be used for earlyprintk logs - * So if omap-uart is used as console then prevent - * uart reset and idle to get logs from omap-uart - * until uart console driver is available to take - * care for console messages. - * Idling or resetting omap-uart while printing logs - * early boot logs can stall the boot-up. - */ - oh->flags |= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET; } } while (1); From f66e329d889fce165074f677509d449fc92ff7b9 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Sun, 28 Jul 2013 23:01:50 -0600 Subject: [PATCH 1097/3400] ARM: OMAP2+: Avoid idling memory controllers with no drivers Memory controllers in OMAP (like GPMC and EMIF) have the hwmods marked with HWMOD_INIT_NO_IDLE and are left in enabled state post initial setup. Even if they have drivers missing, avoid idling them as part of omap_device_late_idle() Signed-off-by: Rajendra Nayak Tested-by: Mark Jackson Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_device.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c index 5cc92874be7e..1c82cdedd358 100644 --- a/arch/arm/mach-omap2/omap_device.c +++ b/arch/arm/mach-omap2/omap_device.c @@ -842,6 +842,7 @@ static int __init omap_device_late_idle(struct device *dev, void *data) { struct platform_device *pdev = to_platform_device(dev); struct omap_device *od = to_omap_device(pdev); + int i; if (!od) return 0; @@ -850,6 +851,15 @@ static int __init omap_device_late_idle(struct device *dev, void *data) * If omap_device state is enabled, but has no driver bound, * idle it. */ + + /* + * Some devices (like memory controllers) are always kept + * enabled, and should not be idled even with no drivers. + */ + for (i = 0; i < od->hwmods_cnt; i++) + if (od->hwmods[i]->flags & HWMOD_INIT_NO_IDLE) + return 0; + if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER) { if (od->_state == OMAP_DEVICE_STATE_ENABLED) { dev_warn(dev, "%s: enabled but no driver. Idling\n", From 7268032dfb1180fca6e91a738380b7ac53684247 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Sun, 28 Jul 2013 23:01:51 -0600 Subject: [PATCH 1098/3400] ARM: OMAP2+: Sync hwmod state with the pm_runtime and omap_device state Some hwmods which are marked with HWMOD_INIT_NO_IDLE are left in enabled state post setup(). When a omap_device gets created for such hwmods make sure the omap_device and pm_runtime states are also in sync for such hwmods by doing a omap_device_enable() and pm_runtime_set_active() for the device. Signed-off-by: Rajendra Nayak Tested-by: Mark Jackson Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_device.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c index 1c82cdedd358..f99f68e1e85b 100644 --- a/arch/arm/mach-omap2/omap_device.c +++ b/arch/arm/mach-omap2/omap_device.c @@ -129,6 +129,7 @@ static int omap_device_build_from_dt(struct platform_device *pdev) struct device_node *node = pdev->dev.of_node; const char *oh_name; int oh_cnt, i, ret = 0; + bool device_active = false; oh_cnt = of_property_count_strings(node, "ti,hwmods"); if (oh_cnt <= 0) { @@ -152,6 +153,8 @@ static int omap_device_build_from_dt(struct platform_device *pdev) goto odbfd_exit1; } hwmods[i] = oh; + if (oh->flags & HWMOD_INIT_NO_IDLE) + device_active = true; } od = omap_device_alloc(pdev, hwmods, oh_cnt); @@ -172,6 +175,11 @@ static int omap_device_build_from_dt(struct platform_device *pdev) pdev->dev.pm_domain = &omap_device_pm_domain; + if (device_active) { + omap_device_enable(pdev); + pm_runtime_set_active(&pdev->dev); + } + odbfd_exit1: kfree(hwmods); odbfd_exit: From 130142d91467e8a07f3a863db369225a89e84d75 Mon Sep 17 00:00:00 2001 From: Afzal Mohammed Date: Fri, 5 Jul 2013 20:43:00 +0530 Subject: [PATCH 1099/3400] ARM: OMAP2+: hwmod: rt address space index for DT Address space is being removed from hwmod database and DT information in property is being used. Currently the 0th index of device address space is used to map for register target address. This is not always true, eg. cpgmac has it's sysconfig in second address space. Handle it by specifying index of device address space to be used for register target. As default value of this field would be zero with static initialization, existing behaviour of using first address space for register target while using DT would be kept as such. Signed-off-by: Afzal Mohammed Tested-by: Mugunthan V N [paul@pwsan.com: use u8 rather than int to save memory] Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod.c | 2 +- arch/arm/mach-omap2/omap_hwmod.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 7341eff63f56..7f4db12b1459 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -2386,7 +2386,7 @@ static void __init _init_mpu_rt_base(struct omap_hwmod *oh, void *data) np = of_dev_hwmod_lookup(of_find_node_by_name(NULL, "ocp"), oh); if (np) - va_start = of_iomap(np, 0); + va_start = of_iomap(np, oh->mpu_rt_idx); } else { va_start = ioremap(mem->pa_start, mem->pa_end - mem->pa_start); } diff --git a/arch/arm/mach-omap2/omap_hwmod.h b/arch/arm/mach-omap2/omap_hwmod.h index 8440a21fc60a..e1482a9b3bc2 100644 --- a/arch/arm/mach-omap2/omap_hwmod.h +++ b/arch/arm/mach-omap2/omap_hwmod.h @@ -616,6 +616,7 @@ struct omap_hwmod_link { * @voltdm: pointer to voltage domain (filled in at runtime) * @dev_attr: arbitrary device attributes that can be passed to the driver * @_sysc_cache: internal-use hwmod flags + * @mpu_rt_idx: index of device address space for register target (for DT boot) * @_mpu_rt_va: cached register target start address (internal use) * @_mpu_port: cached MPU register target slave (internal use) * @opt_clks_cnt: number of @opt_clks @@ -665,6 +666,7 @@ struct omap_hwmod { struct list_head node; struct omap_hwmod_ocp_if *_mpu_port; u16 flags; + u8 mpu_rt_idx; u8 response_lat; u8 rst_lines_cnt; u8 opt_clks_cnt; From 50c2a3a1518befe992f868fc1fd867bdad9776ad Mon Sep 17 00:00:00 2001 From: Afzal Mohammed Date: Fri, 5 Jul 2013 20:43:17 +0530 Subject: [PATCH 1100/3400] ARM: OMAP2+: hwmod: AM335x: fix cpgmac address space Register target address to be used for cpgmac is the second device address space. By default, hwmod picks first address space (0th index) for register target. With removal of address space from hwmod and using DT instead, cpgmac is getting wrong address space for register target. Fix it by indicating the address space to be used for register target. Signed-off-by: Afzal Mohammed Tested-by: Mugunthan V N Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/omap_hwmod_33xx_data.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c index d4114a919df7..eb2f3b93b51c 100644 --- a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c @@ -562,6 +562,7 @@ static struct omap_hwmod am33xx_cpgmac0_hwmod = { .clkdm_name = "cpsw_125mhz_clkdm", .flags = (HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY), .main_clk = "cpsw_125mhz_gclk", + .mpu_rt_idx = 1, .prcm = { .omap4 = { .clkctrl_offs = AM33XX_CM_PER_CPGMAC0_CLKCTRL_OFFSET, From e221fa40a4b6e42c226fd1e0b9d9e03ef2f5cb54 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 30 Jul 2013 11:43:57 +0100 Subject: [PATCH 1101/3400] spi/txx9: Use linux/gpio.h not asm/gpio.h Signed-off-by: Mark Brown --- drivers/spi/spi-txx9.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-txx9.c b/drivers/spi/spi-txx9.c index e9b7681ff6ac..7c6d15766c72 100644 --- a/drivers/spi/spi-txx9.c +++ b/drivers/spi/spi-txx9.c @@ -26,7 +26,7 @@ #include #include #include -#include +#include #define SPI_FIFO_SIZE 4 From dff91d0b721bf8f036c1071a8f16a7effaa87514 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 30 Jul 2013 17:20:47 +0900 Subject: [PATCH 1102/3400] regulator: use dev_get_platdata() Use the wrapper function for retrieving the platform data instead of accessing dev->platform_data directly. Signed-off-by: Jingoo Han Signed-off-by: Mark Brown --- drivers/regulator/88pm800.c | 2 +- drivers/regulator/88pm8607.c | 2 +- drivers/regulator/aat2870-regulator.c | 2 +- drivers/regulator/ab3100.c | 2 +- drivers/regulator/ad5398.c | 2 +- drivers/regulator/da903x.c | 2 +- drivers/regulator/da9052-regulator.c | 2 +- drivers/regulator/da9055-regulator.c | 2 +- drivers/regulator/fan53555.c | 2 +- drivers/regulator/fixed.c | 2 +- drivers/regulator/gpio-regulator.c | 2 +- drivers/regulator/isl6271a-regulator.c | 2 +- drivers/regulator/lp3971.c | 2 +- drivers/regulator/lp3972.c | 2 +- drivers/regulator/lp872x.c | 2 +- drivers/regulator/lp8755.c | 2 +- drivers/regulator/max1586.c | 2 +- drivers/regulator/max8649.c | 2 +- drivers/regulator/max8660.c | 2 +- drivers/regulator/max8925-regulator.c | 2 +- drivers/regulator/max8952.c | 2 +- drivers/regulator/max8973-regulator.c | 2 +- drivers/regulator/palmas-regulator.c | 2 +- drivers/regulator/pcap-regulator.c | 2 +- drivers/regulator/pcf50633-regulator.c | 2 +- drivers/regulator/tps51632-regulator.c | 2 +- drivers/regulator/tps62360-regulator.c | 2 +- drivers/regulator/tps65023-regulator.c | 2 +- drivers/regulator/tps6524x-regulator.c | 2 +- drivers/regulator/twl-regulator.c | 2 +- drivers/regulator/userspace-consumer.c | 2 +- drivers/regulator/virtual.c | 2 +- drivers/regulator/wm831x-dcdc.c | 8 ++++---- drivers/regulator/wm831x-isink.c | 2 +- drivers/regulator/wm831x-ldo.c | 6 +++--- drivers/regulator/wm8350-regulator.c | 2 +- drivers/regulator/wm8400-regulator.c | 2 +- drivers/regulator/wm8994-regulator.c | 2 +- 38 files changed, 43 insertions(+), 43 deletions(-) diff --git a/drivers/regulator/88pm800.c b/drivers/regulator/88pm800.c index b4c29b1c52a5..c72fe95e443f 100644 --- a/drivers/regulator/88pm800.c +++ b/drivers/regulator/88pm800.c @@ -283,7 +283,7 @@ static int pm800_regulator_dt_init(struct platform_device *pdev) static int pm800_regulator_probe(struct platform_device *pdev) { struct pm80x_chip *chip = dev_get_drvdata(pdev->dev.parent); - struct pm80x_platform_data *pdata = pdev->dev.parent->platform_data; + struct pm80x_platform_data *pdata = dev_get_platdata(pdev->dev.parent); struct pm800_regulators *pm800_data; struct pm800_regulator_info *info; struct regulator_config config = { }; diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c index 8a7cb1f43046..70230974468c 100644 --- a/drivers/regulator/88pm8607.c +++ b/drivers/regulator/88pm8607.c @@ -346,7 +346,7 @@ static int pm8607_regulator_probe(struct platform_device *pdev) { struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); struct pm8607_regulator_info *info = NULL; - struct regulator_init_data *pdata = pdev->dev.platform_data; + struct regulator_init_data *pdata = dev_get_platdata(&pdev->dev); struct regulator_config config = { }; struct resource *res; int i; diff --git a/drivers/regulator/aat2870-regulator.c b/drivers/regulator/aat2870-regulator.c index 8b5876356db9..881159dfcb5e 100644 --- a/drivers/regulator/aat2870-regulator.c +++ b/drivers/regulator/aat2870-regulator.c @@ -174,7 +174,7 @@ static int aat2870_regulator_probe(struct platform_device *pdev) config.dev = &pdev->dev; config.driver_data = ri; - config.init_data = pdev->dev.platform_data; + config.init_data = dev_get_platdata(&pdev->dev); rdev = regulator_register(&ri->desc, &config); if (IS_ERR(rdev)) { diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c index 3be9e46594a1..7d5eaa874b2d 100644 --- a/drivers/regulator/ab3100.c +++ b/drivers/regulator/ab3100.c @@ -660,7 +660,7 @@ ab3100_regulator_of_probe(struct platform_device *pdev, struct device_node *np) static int ab3100_regulators_probe(struct platform_device *pdev) { - struct ab3100_platform_data *plfdata = pdev->dev.platform_data; + struct ab3100_platform_data *plfdata = dev_get_platdata(&pdev->dev); struct device_node *np = pdev->dev.of_node; int err = 0; u8 data; diff --git a/drivers/regulator/ad5398.c b/drivers/regulator/ad5398.c index 6b981b5faa70..b2b203cb6b2f 100644 --- a/drivers/regulator/ad5398.c +++ b/drivers/regulator/ad5398.c @@ -214,7 +214,7 @@ MODULE_DEVICE_TABLE(i2c, ad5398_id); static int ad5398_probe(struct i2c_client *client, const struct i2c_device_id *id) { - struct regulator_init_data *init_data = client->dev.platform_data; + struct regulator_init_data *init_data = dev_get_platdata(&client->dev); struct regulator_config config = { }; struct ad5398_chip_info *chip; const struct ad5398_current_data_format *df = diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x.c index 2afa5730f324..d9799793308c 100644 --- a/drivers/regulator/da903x.c +++ b/drivers/regulator/da903x.c @@ -485,7 +485,7 @@ static int da903x_regulator_probe(struct platform_device *pdev) ri->desc.ops = &da9030_regulator_ldo1_15_ops; config.dev = &pdev->dev; - config.init_data = pdev->dev.platform_data; + config.init_data = dev_get_platdata(&pdev->dev); config.driver_data = ri; rdev = regulator_register(&ri->desc, &config); diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c index 96b569abb46c..1e4d483f6163 100644 --- a/drivers/regulator/da9052-regulator.c +++ b/drivers/regulator/da9052-regulator.c @@ -349,7 +349,7 @@ static int da9052_regulator_probe(struct platform_device *pdev) return -ENOMEM; da9052 = dev_get_drvdata(pdev->dev.parent); - pdata = da9052->dev->platform_data; + pdata = dev_get_platdata(da9052->dev); regulator->da9052 = da9052; regulator->info = find_regulator_info(regulator->da9052->chip_id, diff --git a/drivers/regulator/da9055-regulator.c b/drivers/regulator/da9055-regulator.c index 30221099d09c..77b53e5a231c 100644 --- a/drivers/regulator/da9055-regulator.c +++ b/drivers/regulator/da9055-regulator.c @@ -535,7 +535,7 @@ static int da9055_regulator_probe(struct platform_device *pdev) struct regulator_config config = { }; struct da9055_regulator *regulator; struct da9055 *da9055 = dev_get_drvdata(pdev->dev.parent); - struct da9055_pdata *pdata = da9055->dev->platform_data; + struct da9055_pdata *pdata = dev_get_platdata(da9055->dev); int ret, irq; if (pdata == NULL || pdata->regulators[pdev->id] == NULL) diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c index f0e1ae52bb05..a32b44272a05 100644 --- a/drivers/regulator/fan53555.c +++ b/drivers/regulator/fan53555.c @@ -237,7 +237,7 @@ static int fan53555_regulator_probe(struct i2c_client *client, unsigned int val; int ret; - pdata = client->dev.platform_data; + pdata = dev_get_platdata(&client->dev); if (!pdata || !pdata->regulator) { dev_err(&client->dev, "Platform data not found!\n"); return -ENODEV; diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index e5c03b534fae..7610920014d7 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -146,7 +146,7 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev) if (IS_ERR(config)) return PTR_ERR(config); } else { - config = pdev->dev.platform_data; + config = dev_get_platdata(&pdev->dev); } if (!config) diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index 9d39eb4aafa3..98a98ffa7fe0 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c @@ -219,7 +219,7 @@ static struct regulator_ops gpio_regulator_current_ops = { static int gpio_regulator_probe(struct platform_device *pdev) { - struct gpio_regulator_config *config = pdev->dev.platform_data; + struct gpio_regulator_config *config = dev_get_platdata(&pdev->dev); struct device_node *np = pdev->dev.of_node; struct gpio_regulator_data *drvdata; struct regulator_config cfg = { }; diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c index b99c49b9aff0..88c1a3acf563 100644 --- a/drivers/regulator/isl6271a-regulator.c +++ b/drivers/regulator/isl6271a-regulator.c @@ -110,7 +110,7 @@ static int isl6271a_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct regulator_config config = { }; - struct regulator_init_data *init_data = i2c->dev.platform_data; + struct regulator_init_data *init_data = dev_get_platdata(&i2c->dev); struct isl_pmic *pmic; int err, i; diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c index 3809b4381606..5a4604ee5ea5 100644 --- a/drivers/regulator/lp3971.c +++ b/drivers/regulator/lp3971.c @@ -425,7 +425,7 @@ static int lp3971_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct lp3971 *lp3971; - struct lp3971_platform_data *pdata = i2c->dev.platform_data; + struct lp3971_platform_data *pdata = dev_get_platdata(&i2c->dev); int ret; u16 val; diff --git a/drivers/regulator/lp3972.c b/drivers/regulator/lp3972.c index 573024039ca0..093e6f44ff8a 100644 --- a/drivers/regulator/lp3972.c +++ b/drivers/regulator/lp3972.c @@ -519,7 +519,7 @@ static int lp3972_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct lp3972 *lp3972; - struct lp3972_platform_data *pdata = i2c->dev.platform_data; + struct lp3972_platform_data *pdata = dev_get_platdata(&i2c->dev); int ret; u16 val; diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c index b16336bcd4d4..2b67c80fab6a 100644 --- a/drivers/regulator/lp872x.c +++ b/drivers/regulator/lp872x.c @@ -961,7 +961,7 @@ static int lp872x_probe(struct i2c_client *cl, const struct i2c_device_id *id) } lp->dev = &cl->dev; - lp->pdata = cl->dev.platform_data; + lp->pdata = dev_get_platdata(&cl->dev); lp->chipid = id->driver_data; lp->num_regulators = num_regulators; i2c_set_clientdata(cl, lp); diff --git a/drivers/regulator/lp8755.c b/drivers/regulator/lp8755.c index d9e38b4c2adc..7507db44bf26 100644 --- a/drivers/regulator/lp8755.c +++ b/drivers/regulator/lp8755.c @@ -449,7 +449,7 @@ static int lp8755_probe(struct i2c_client *client, { int ret, icnt; struct lp8755_chip *pchip; - struct lp8755_platform_data *pdata = client->dev.platform_data; + struct lp8755_platform_data *pdata = dev_get_platdata(&client->dev); if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { dev_err(&client->dev, "i2c functionality check fail.\n"); diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c index 54af61015814..3a599ee0a456 100644 --- a/drivers/regulator/max1586.c +++ b/drivers/regulator/max1586.c @@ -163,7 +163,7 @@ static int max1586_pmic_probe(struct i2c_client *client, const struct i2c_device_id *i2c_id) { struct regulator_dev **rdev; - struct max1586_platform_data *pdata = client->dev.platform_data; + struct max1586_platform_data *pdata = dev_get_platdata(&client->dev); struct regulator_config config = { }; struct max1586_data *max1586; int i, id, ret = -ENOMEM; diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c index db6c9be10f3f..19c6f08eafd5 100644 --- a/drivers/regulator/max8649.c +++ b/drivers/regulator/max8649.c @@ -152,7 +152,7 @@ static struct regmap_config max8649_regmap_config = { static int max8649_regulator_probe(struct i2c_client *client, const struct i2c_device_id *id) { - struct max8649_platform_data *pdata = client->dev.platform_data; + struct max8649_platform_data *pdata = dev_get_platdata(&client->dev); struct max8649_regulator_info *info = NULL; struct regulator_config config = { }; unsigned int val; diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c index d428ef9a626f..bfd41084c7df 100644 --- a/drivers/regulator/max8660.c +++ b/drivers/regulator/max8660.c @@ -309,7 +309,7 @@ static int max8660_probe(struct i2c_client *client, const struct i2c_device_id *i2c_id) { struct regulator_dev **rdev; - struct max8660_platform_data *pdata = client->dev.platform_data; + struct max8660_platform_data *pdata = dev_get_platdata(&client->dev); struct regulator_config config = { }; struct max8660 *max8660; int boot_on, i, id, ret = -EINVAL; diff --git a/drivers/regulator/max8925-regulator.c b/drivers/regulator/max8925-regulator.c index e6d54a546d36..d80b5fa758ae 100644 --- a/drivers/regulator/max8925-regulator.c +++ b/drivers/regulator/max8925-regulator.c @@ -277,7 +277,7 @@ static int max8925_regulator_dt_init(struct platform_device *pdev, static int max8925_regulator_probe(struct platform_device *pdev) { struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent); - struct regulator_init_data *pdata = pdev->dev.platform_data; + struct regulator_init_data *pdata = dev_get_platdata(&pdev->dev); struct regulator_config config = { }; struct max8925_regulator_info *ri; struct resource *res; diff --git a/drivers/regulator/max8952.c b/drivers/regulator/max8952.c index 5259c2fea90a..788e5ae2af1b 100644 --- a/drivers/regulator/max8952.c +++ b/drivers/regulator/max8952.c @@ -196,7 +196,7 @@ static int max8952_pmic_probe(struct i2c_client *client, const struct i2c_device_id *i2c_id) { struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); - struct max8952_platform_data *pdata = client->dev.platform_data; + struct max8952_platform_data *pdata = dev_get_platdata(&client->dev); struct regulator_config config = { }; struct max8952_data *max8952; diff --git a/drivers/regulator/max8973-regulator.c b/drivers/regulator/max8973-regulator.c index 0c5195a842e2..5b77ab7762e4 100644 --- a/drivers/regulator/max8973-regulator.c +++ b/drivers/regulator/max8973-regulator.c @@ -371,7 +371,7 @@ static int max8973_probe(struct i2c_client *client, struct max8973_chip *max; int ret; - pdata = client->dev.platform_data; + pdata = dev_get_platdata(&client->dev); if (!pdata && !client->dev.of_node) { dev_err(&client->dev, "No Platform data"); diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c index d0c87856dd25..e8877e4e5a5a 100644 --- a/drivers/regulator/palmas-regulator.c +++ b/drivers/regulator/palmas-regulator.c @@ -765,7 +765,7 @@ static void palmas_dt_to_pdata(struct device *dev, static int palmas_regulators_probe(struct platform_device *pdev) { struct palmas *palmas = dev_get_drvdata(pdev->dev.parent); - struct palmas_pmic_platform_data *pdata = pdev->dev.platform_data; + struct palmas_pmic_platform_data *pdata = dev_get_platdata(&pdev->dev); struct device_node *node = pdev->dev.of_node; struct regulator_dev *rdev; struct regulator_config config = { }; diff --git a/drivers/regulator/pcap-regulator.c b/drivers/regulator/pcap-regulator.c index 1a73a297fe73..b49eaeedea84 100644 --- a/drivers/regulator/pcap-regulator.c +++ b/drivers/regulator/pcap-regulator.c @@ -243,7 +243,7 @@ static int pcap_regulator_probe(struct platform_device *pdev) struct regulator_config config = { }; config.dev = &pdev->dev; - config.init_data = pdev->dev.platform_data; + config.init_data = dev_get_platdata(&pdev->dev); config.driver_data = pcap; rdev = regulator_register(&pcap_regulators[pdev->id], &config); diff --git a/drivers/regulator/pcf50633-regulator.c b/drivers/regulator/pcf50633-regulator.c index 54df9f7cb504..0f3576d48abf 100644 --- a/drivers/regulator/pcf50633-regulator.c +++ b/drivers/regulator/pcf50633-regulator.c @@ -86,7 +86,7 @@ static int pcf50633_regulator_probe(struct platform_device *pdev) pcf = dev_to_pcf50633(pdev->dev.parent); config.dev = &pdev->dev; - config.init_data = pdev->dev.platform_data; + config.init_data = dev_get_platdata(&pdev->dev); config.driver_data = pcf; config.regmap = pcf->regmap; diff --git a/drivers/regulator/tps51632-regulator.c b/drivers/regulator/tps51632-regulator.c index 6e67be75ea1b..9392a7ca3d2d 100644 --- a/drivers/regulator/tps51632-regulator.c +++ b/drivers/regulator/tps51632-regulator.c @@ -275,7 +275,7 @@ static int tps51632_probe(struct i2c_client *client, } } - pdata = client->dev.platform_data; + pdata = dev_get_platdata(&client->dev); if (!pdata && client->dev.of_node) pdata = of_get_tps51632_platform_data(&client->dev); if (!pdata) { diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c index a490d5b749b2..0b7ebb1ebf85 100644 --- a/drivers/regulator/tps62360-regulator.c +++ b/drivers/regulator/tps62360-regulator.c @@ -350,7 +350,7 @@ static int tps62360_probe(struct i2c_client *client, int i; int chip_id; - pdata = client->dev.platform_data; + pdata = dev_get_platdata(&client->dev); if (client->dev.of_node) { const struct of_device_id *match; diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c index 9d053e23e9eb..a15263d4bdff 100644 --- a/drivers/regulator/tps65023-regulator.c +++ b/drivers/regulator/tps65023-regulator.c @@ -218,7 +218,7 @@ static int tps_65023_probe(struct i2c_client *client, * init_data points to array of regulator_init structures * coming from the board-evm file. */ - init_data = client->dev.platform_data; + init_data = dev_get_platdata(&client->dev); if (!init_data) return -EIO; diff --git a/drivers/regulator/tps6524x-regulator.c b/drivers/regulator/tps6524x-regulator.c index 1094393155ed..62e8d28beabd 100644 --- a/drivers/regulator/tps6524x-regulator.c +++ b/drivers/regulator/tps6524x-regulator.c @@ -601,7 +601,7 @@ static int pmic_probe(struct spi_device *spi) struct regulator_config config = { }; int ret = 0, i; - init_data = dev->platform_data; + init_data = dev_get_platdata(dev); if (!init_data) { dev_err(dev, "could not find regulator platform data\n"); return -EINVAL; diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 93bc4f456da4..78aae4cbb004 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -1108,7 +1108,7 @@ static int twlreg_probe(struct platform_device *pdev) drvdata = NULL; } else { id = pdev->id; - initdata = pdev->dev.platform_data; + initdata = dev_get_platdata(&pdev->dev); for (i = 0, template = NULL; i < ARRAY_SIZE(twl_of_match); i++) { template = twl_of_match[i].data; if (template && template->desc.id == id) diff --git a/drivers/regulator/userspace-consumer.c b/drivers/regulator/userspace-consumer.c index a7c8deb5f28f..765acc11c9c8 100644 --- a/drivers/regulator/userspace-consumer.c +++ b/drivers/regulator/userspace-consumer.c @@ -111,7 +111,7 @@ static int regulator_userspace_consumer_probe(struct platform_device *pdev) struct userspace_consumer_data *drvdata; int ret; - pdata = pdev->dev.platform_data; + pdata = dev_get_platdata(&pdev->dev); if (!pdata) return -EINVAL; diff --git a/drivers/regulator/virtual.c b/drivers/regulator/virtual.c index a9d4284ea007..f53e78b9a84e 100644 --- a/drivers/regulator/virtual.c +++ b/drivers/regulator/virtual.c @@ -287,7 +287,7 @@ static const struct attribute_group regulator_virtual_attr_group = { static int regulator_virtual_probe(struct platform_device *pdev) { - char *reg_id = pdev->dev.platform_data; + char *reg_id = dev_get_platdata(&pdev->dev); struct virtual_consumer_data *drvdata; int ret; diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c index 46938cf162ad..11861cb861df 100644 --- a/drivers/regulator/wm831x-dcdc.c +++ b/drivers/regulator/wm831x-dcdc.c @@ -451,7 +451,7 @@ static void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc, static int wm831x_buckv_probe(struct platform_device *pdev) { struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); - struct wm831x_pdata *pdata = wm831x->dev->platform_data; + struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev); struct regulator_config config = { }; int id; struct wm831x_dcdc *dcdc; @@ -624,7 +624,7 @@ static struct regulator_ops wm831x_buckp_ops = { static int wm831x_buckp_probe(struct platform_device *pdev) { struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); - struct wm831x_pdata *pdata = wm831x->dev->platform_data; + struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev); struct regulator_config config = { }; int id; struct wm831x_dcdc *dcdc; @@ -770,7 +770,7 @@ static struct regulator_ops wm831x_boostp_ops = { static int wm831x_boostp_probe(struct platform_device *pdev) { struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); - struct wm831x_pdata *pdata = wm831x->dev->platform_data; + struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev); struct regulator_config config = { }; int id = pdev->id % ARRAY_SIZE(pdata->dcdc); struct wm831x_dcdc *dcdc; @@ -880,7 +880,7 @@ static struct regulator_ops wm831x_epe_ops = { static int wm831x_epe_probe(struct platform_device *pdev) { struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); - struct wm831x_pdata *pdata = wm831x->dev->platform_data; + struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev); struct regulator_config config = { }; int id = pdev->id % ARRAY_SIZE(pdata->epe); struct wm831x_dcdc *dcdc; diff --git a/drivers/regulator/wm831x-isink.c b/drivers/regulator/wm831x-isink.c index 16ebdf94d0a0..4eb373de1fac 100644 --- a/drivers/regulator/wm831x-isink.c +++ b/drivers/regulator/wm831x-isink.c @@ -151,7 +151,7 @@ static irqreturn_t wm831x_isink_irq(int irq, void *data) static int wm831x_isink_probe(struct platform_device *pdev) { struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); - struct wm831x_pdata *pdata = wm831x->dev->platform_data; + struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev); struct wm831x_isink *isink; int id = pdev->id % ARRAY_SIZE(pdata->isink); struct regulator_config config = { }; diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c index 76792c7d86f3..1432b26ef2e9 100644 --- a/drivers/regulator/wm831x-ldo.c +++ b/drivers/regulator/wm831x-ldo.c @@ -221,7 +221,7 @@ static struct regulator_ops wm831x_gp_ldo_ops = { static int wm831x_gp_ldo_probe(struct platform_device *pdev) { struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); - struct wm831x_pdata *pdata = wm831x->dev->platform_data; + struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev); struct regulator_config config = { }; int id; struct wm831x_ldo *ldo; @@ -447,7 +447,7 @@ static struct regulator_ops wm831x_aldo_ops = { static int wm831x_aldo_probe(struct platform_device *pdev) { struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); - struct wm831x_pdata *pdata = wm831x->dev->platform_data; + struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev); struct regulator_config config = { }; int id; struct wm831x_ldo *ldo; @@ -605,7 +605,7 @@ static struct regulator_ops wm831x_alive_ldo_ops = { static int wm831x_alive_ldo_probe(struct platform_device *pdev) { struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); - struct wm831x_pdata *pdata = wm831x->dev->platform_data; + struct wm831x_pdata *pdata = dev_get_platdata(wm831x->dev); struct regulator_config config = { }; int id; struct wm831x_ldo *ldo; diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c index 5453dd0105ed..835b5f0f344e 100644 --- a/drivers/regulator/wm8350-regulator.c +++ b/drivers/regulator/wm8350-regulator.c @@ -1201,7 +1201,7 @@ static int wm8350_regulator_probe(struct platform_device *pdev) } config.dev = &pdev->dev; - config.init_data = pdev->dev.platform_data; + config.init_data = dev_get_platdata(&pdev->dev); config.driver_data = dev_get_drvdata(&pdev->dev); config.regmap = wm8350->regmap; diff --git a/drivers/regulator/wm8400-regulator.c b/drivers/regulator/wm8400-regulator.c index 2ac7e1aceb05..58f51bec13f2 100644 --- a/drivers/regulator/wm8400-regulator.c +++ b/drivers/regulator/wm8400-regulator.c @@ -215,7 +215,7 @@ static int wm8400_regulator_probe(struct platform_device *pdev) struct regulator_dev *rdev; config.dev = &pdev->dev; - config.init_data = pdev->dev.platform_data; + config.init_data = dev_get_platdata(&pdev->dev); config.driver_data = wm8400; config.regmap = wm8400->regmap; diff --git a/drivers/regulator/wm8994-regulator.c b/drivers/regulator/wm8994-regulator.c index 8f2a8a7a3f99..5ee2a208457c 100644 --- a/drivers/regulator/wm8994-regulator.c +++ b/drivers/regulator/wm8994-regulator.c @@ -125,7 +125,7 @@ static const struct regulator_init_data wm8994_ldo_default[] = { static int wm8994_ldo_probe(struct platform_device *pdev) { struct wm8994 *wm8994 = dev_get_drvdata(pdev->dev.parent); - struct wm8994_pdata *pdata = wm8994->dev->platform_data; + struct wm8994_pdata *pdata = dev_get_platdata(wm8994->dev); int id = pdev->id % ARRAY_SIZE(pdata->ldo); struct regulator_config config = { }; struct wm8994_ldo *ldo; From 1207637304990374231fe4e9aeb527904f4ec1e6 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 30 Jul 2013 08:30:16 -0400 Subject: [PATCH 1103/3400] workqueue: mark WQ_NON_REENTRANT deprecated dbf2576e37 ("workqueue: make all workqueues non-reentrant") made WQ_NON_REENTRANT no-op but the following patches didn't remove the flag or update the documentation. Let's mark the flag deprecated and update the documentation accordingly. Signed-off-by: Tejun Heo --- Documentation/workqueue.txt | 18 ++++++------------ include/linux/workqueue.h | 7 ++++++- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/Documentation/workqueue.txt b/Documentation/workqueue.txt index a6ab4b62d926..67113f622880 100644 --- a/Documentation/workqueue.txt +++ b/Documentation/workqueue.txt @@ -100,8 +100,8 @@ Subsystems and drivers can create and queue work items through special workqueue API functions as they see fit. They can influence some aspects of the way the work items are executed by setting flags on the workqueue they are putting the work item on. These flags include -things like CPU locality, reentrancy, concurrency limits, priority and -more. To get a detailed overview refer to the API description of +things like CPU locality, concurrency limits, priority and more. To +get a detailed overview refer to the API description of alloc_workqueue() below. When a work item is queued to a workqueue, the target gcwq and @@ -166,16 +166,6 @@ resources, scheduled and executed. @flags: - WQ_NON_REENTRANT - - By default, a wq guarantees non-reentrance only on the same - CPU. A work item may not be executed concurrently on the same - CPU by multiple workers but is allowed to be executed - concurrently on multiple CPUs. This flag makes sure - non-reentrance is enforced across all CPUs. Work items queued - to a non-reentrant wq are guaranteed to be executed by at most - one worker system-wide at any given time. - WQ_UNBOUND Work items queued to an unbound wq are served by a special @@ -233,6 +223,10 @@ resources, scheduled and executed. This flag is meaningless for unbound wq. +Note that the flag WQ_NON_REENTRANT no longer exists as all workqueues +are now non-reentrant - any work item is guaranteed to be executed by +at most one worker system-wide at any given time. + @max_active: @max_active determines the maximum number of execution contexts per diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index a0ed78ab54d7..594521ba0d43 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h @@ -295,7 +295,12 @@ static inline unsigned int work_static(struct work_struct *work) { return 0; } * Documentation/workqueue.txt. */ enum { - WQ_NON_REENTRANT = 1 << 0, /* guarantee non-reentrance */ + /* + * All wqs are now non-reentrant making the following flag + * meaningless. Will be removed. + */ + WQ_NON_REENTRANT = 1 << 0, /* DEPRECATED */ + WQ_UNBOUND = 1 << 1, /* not bound to any cpu */ WQ_FREEZABLE = 1 << 2, /* freeze during suspend */ WQ_MEM_RECLAIM = 1 << 3, /* may be used for memory reclaim */ From 2c7d132a589077b31493b3ea82ac83b1f72c93e1 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 30 Jul 2013 14:34:00 +0200 Subject: [PATCH 1104/3400] ACPI / PM: Only set power states of devices that are power manageable Make acpi_device_set_power() check if the given device is power manageable before checking if the given power state is valid for that device. Otherwise it will print that "Device does not support" that power state into the kernel log, which may not make sense for some power states (D0 and D3cold are supported by all devices by definition). Tested-by: Yinghai Lu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/device_pm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 4ab807dc8518..63324b873636 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -159,7 +159,8 @@ int acpi_device_set_power(struct acpi_device *device, int state) int result = 0; bool cut_power = false; - if (!device || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3_COLD)) + if (!device || !device->flags.power_manageable + || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3_COLD)) return -EINVAL; /* Make sure this is a valid target state */ From b69137a74b7a9451b3da504d1ef9ead7cb393922 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 30 Jul 2013 14:34:55 +0200 Subject: [PATCH 1105/3400] ACPI / PM: Make messages in acpi_device_set_power() print device names Modify acpi_device_set_power() so that diagnostic messages printed by it to the kernel log always contain the name of the device concerned to make it possible to identify the device that triggered the message if need be. Also replace printk(KERN_WARNING ) with dev_warn() everywhere in that function. Signed-off-by: Rafael J. Wysocki Reviewed-by: Aaron Lu --- drivers/acpi/device_pm.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 63324b873636..8234e1f8c79d 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -166,20 +166,20 @@ int acpi_device_set_power(struct acpi_device *device, int state) /* Make sure this is a valid target state */ if (state == device->power.state) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at %s\n", + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] already in %s\n", + device->pnp.bus_id, acpi_power_state_string(state))); return 0; } if (!device->power.states[state].flags.valid) { - printk(KERN_WARNING PREFIX "Device does not support %s\n", - acpi_power_state_string(state)); + dev_warn(&device->dev, "Power state %s not supported\n", + acpi_power_state_string(state)); return -ENODEV; } if (device->parent && (state < device->parent->power.state)) { - printk(KERN_WARNING PREFIX - "Cannot set device to a higher-powered" - " state than parent\n"); + dev_warn(&device->dev, + "Cannot transition to a higher-powered state than parent\n"); return -ENODEV; } @@ -192,8 +192,8 @@ int acpi_device_set_power(struct acpi_device *device, int state) if (state < device->power.state && state != ACPI_STATE_D0 && device->power.state >= ACPI_STATE_D3_HOT) { - printk(KERN_WARNING PREFIX - "Cannot transition to non-D0 state from D3\n"); + dev_warn(&device->dev, + "Cannot transition to non-D0 state from D3\n"); return -ENODEV; } @@ -220,10 +220,8 @@ int acpi_device_set_power(struct acpi_device *device, int state) end: if (result) { - printk(KERN_WARNING PREFIX - "Device [%s] failed to transition to %s\n", - device->pnp.bus_id, - acpi_power_state_string(state)); + dev_warn(&device->dev, "Failed to change power state to %s\n", + acpi_power_state_string(state)); } else { device->power.state = state; ACPI_DEBUG_PRINT((ACPI_DB_INFO, From 8ad928d52e63a9b7d69f0873d7318c4561e2f8cd Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 30 Jul 2013 14:36:20 +0200 Subject: [PATCH 1106/3400] ACPI / PM: Use ACPI_STATE_D3_COLD instead of ACPI_STATE_D3 everywhere There are several places in the tree where ACPI_STATE_D3 is used instead of ACPI_STATE_D3_COLD which should be used instead for clarity. Modify them all to use ACPI_STATE_D3_COLD as appropriate. [The definition of ACPI_STATE_D3 itself cannot go away at this point as it is part of ACPICA.] Signed-off-by: Rafael J. Wysocki Reviewed-by: Aaron Lu --- drivers/acpi/fan.c | 4 ++-- drivers/acpi/power.c | 2 +- drivers/acpi/scan.c | 4 ++-- drivers/ata/libata-acpi.c | 4 ++-- drivers/ide/ide-acpi.c | 5 +++-- drivers/pnp/pnpacpi/core.c | 6 +++--- include/acpi/acpi_bus.h | 3 ++- 7 files changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index 5b02a0aa540c..41ade6570bc0 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -93,7 +93,7 @@ static int fan_get_cur_state(struct thermal_cooling_device *cdev, unsigned long if (result) return result; - *state = (acpi_state == ACPI_STATE_D3 ? 0 : + *state = (acpi_state == ACPI_STATE_D3_COLD ? 0 : (acpi_state == ACPI_STATE_D0 ? 1 : -1)); return 0; } @@ -108,7 +108,7 @@ fan_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state) return -EINVAL; result = acpi_bus_set_power(device->handle, - state ? ACPI_STATE_D0 : ACPI_STATE_D3); + state ? ACPI_STATE_D0 : ACPI_STATE_D3_COLD); return result; } diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 5c28c894c0fc..4cdcc0cf0c56 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -786,7 +786,7 @@ int acpi_power_get_inferred_state(struct acpi_device *device, int *state) } } - *state = ACPI_STATE_D3; + *state = ACPI_STATE_D3_COLD; return 0; } diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 8a46c924effd..c30df3ad2d71 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1450,8 +1450,8 @@ static void acpi_bus_get_power_flags(struct acpi_device *device) /* Set defaults for D0 and D3 states (always valid) */ device->power.states[ACPI_STATE_D0].flags.valid = 1; device->power.states[ACPI_STATE_D0].power = 100; - device->power.states[ACPI_STATE_D3].flags.valid = 1; - device->power.states[ACPI_STATE_D3].power = 0; + device->power.states[ACPI_STATE_D3_COLD].flags.valid = 1; + device->power.states[ACPI_STATE_D3_COLD].power = 0; /* Set D3cold's explicit_set flag if _PS3 exists. */ if (device->power.states[ACPI_STATE_D3_HOT].flags.explicit_set) diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index cf4e7020adac..da8170dfc90f 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c @@ -947,11 +947,11 @@ static void pata_acpi_set_state(struct ata_port *ap, pm_message_t state) continue; acpi_bus_set_power(dev_handle, state.event & PM_EVENT_RESUME ? - ACPI_STATE_D0 : ACPI_STATE_D3); + ACPI_STATE_D0 : ACPI_STATE_D3_COLD); } if (!(state.event & PM_EVENT_RESUME)) - acpi_bus_set_power(port_handle, ACPI_STATE_D3); + acpi_bus_set_power(port_handle, ACPI_STATE_D3_COLD); } /** diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c index f1a6796b165c..140c8ef50529 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c @@ -520,11 +520,12 @@ void ide_acpi_set_state(ide_hwif_t *hwif, int on) 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_COLD); } if (!on) - acpi_bus_set_power(hwif->acpidata->obj_handle, ACPI_STATE_D3); + acpi_bus_set_power(hwif->acpidata->obj_handle, + ACPI_STATE_D3_COLD); } /** diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index 55cd459a3908..34049b0b4c73 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c @@ -131,7 +131,7 @@ static int pnpacpi_disable_resources(struct pnp_dev *dev) /* acpi_unregister_gsi(pnp_irq(dev, 0)); */ ret = 0; if (acpi_bus_power_manageable(handle)) - acpi_bus_set_power(handle, ACPI_STATE_D3); + acpi_bus_set_power(handle, ACPI_STATE_D3_COLD); /* continue even if acpi_bus_set_power() fails */ if (ACPI_FAILURE(acpi_evaluate_object(handle, "_DIS", NULL, NULL))) ret = -ENODEV; @@ -174,10 +174,10 @@ static int pnpacpi_suspend(struct pnp_dev *dev, pm_message_t state) if (acpi_bus_power_manageable(handle)) { int power_state = acpi_pm_device_sleep_state(&dev->dev, NULL, - ACPI_STATE_D3); + ACPI_STATE_D3_COLD); if (power_state < 0) power_state = (state.event == PM_EVENT_ON) ? - ACPI_STATE_D0 : ACPI_STATE_D3; + ACPI_STATE_D0 : ACPI_STATE_D3_COLD; /* * acpi_bus_set_power() often fails (keyboard port can't be diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 56e6b68c8d2f..916b18933879 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -478,7 +478,8 @@ static inline int acpi_pm_device_sleep_state(struct device *d, int *p, int m) if (p) *p = ACPI_STATE_D0; - return (m >= ACPI_STATE_D0 && m <= ACPI_STATE_D3) ? m : ACPI_STATE_D0; + return (m >= ACPI_STATE_D0 && m <= ACPI_STATE_D3_COLD) ? + m : ACPI_STATE_D0; } static inline void acpi_dev_pm_add_dependent(acpi_handle handle, struct device *depdev) {} From 61b8c345aa8c50c6a99a90560a107d02124f0293 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 30 Jul 2013 17:16:05 +0900 Subject: [PATCH 1107/3400] ata: use dev_get_platdata() Use the wrapper function for retrieving the platform data instead of accessing dev->platform_data directly. Signed-off-by: Jingoo Han Signed-off-by: Tejun Heo --- drivers/ata/pata_at32.c | 2 +- drivers/ata/pata_at91.c | 2 +- drivers/ata/pata_ixp4xx_cf.c | 4 ++-- drivers/ata/pata_octeon_cf.c | 2 +- drivers/ata/pata_platform.c | 2 +- drivers/ata/pata_pxa.c | 2 +- drivers/ata/pata_samsung_cf.c | 4 ++-- drivers/ata/sata_mv.c | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/ata/pata_at32.c b/drivers/ata/pata_at32.c index 8d493b4a0961..d59d5239405f 100644 --- a/drivers/ata/pata_at32.c +++ b/drivers/ata/pata_at32.c @@ -271,7 +271,7 @@ static int __init pata_at32_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct at32_ide_info *info; - struct ide_platform_data *board = pdev->dev.platform_data; + struct ide_platform_data *board = dev_get_platdata(&pdev->dev); struct resource *res; int irq; diff --git a/drivers/ata/pata_at91.c b/drivers/ata/pata_at91.c index 5364f97b42c6..d63ee8f41a4f 100644 --- a/drivers/ata/pata_at91.c +++ b/drivers/ata/pata_at91.c @@ -315,7 +315,7 @@ static struct ata_port_operations pata_at91_port_ops = { static int pata_at91_probe(struct platform_device *pdev) { - struct at91_cf_data *board = pdev->dev.platform_data; + struct at91_cf_data *board = dev_get_platdata(&pdev->dev); struct device *dev = &pdev->dev; struct at91_ide_info *info; struct resource *mem_res; diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c index dcc6b243e525..1ec53f8ca96f 100644 --- a/drivers/ata/pata_ixp4xx_cf.c +++ b/drivers/ata/pata_ixp4xx_cf.c @@ -48,7 +48,7 @@ static unsigned int ixp4xx_mmio_data_xfer(struct ata_device *dev, u16 *buf16 = (u16 *) buf; struct ata_port *ap = dev->link->ap; void __iomem *mmio = ap->ioaddr.data_addr; - struct ixp4xx_pata_data *data = ap->host->dev->platform_data; + struct ixp4xx_pata_data *data = dev_get_platdata(ap->host->dev); /* set the expansion bus in 16bit mode and restore * 8 bit mode after the transaction. @@ -143,7 +143,7 @@ static int ixp4xx_pata_probe(struct platform_device *pdev) struct resource *cs0, *cs1; struct ata_host *host; struct ata_port *ap; - struct ixp4xx_pata_data *data = pdev->dev.platform_data; + struct ixp4xx_pata_data *data = dev_get_platdata(&pdev->dev); cs0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); cs1 = platform_get_resource(pdev, IORESOURCE_MEM, 1); diff --git a/drivers/ata/pata_octeon_cf.c b/drivers/ata/pata_octeon_cf.c index e73bef3093d2..c51bbb9ea8e8 100644 --- a/drivers/ata/pata_octeon_cf.c +++ b/drivers/ata/pata_octeon_cf.c @@ -1037,7 +1037,7 @@ static void octeon_cf_shutdown(struct device *dev) union cvmx_mio_boot_dma_cfgx dma_cfg; union cvmx_mio_boot_dma_intx dma_int; - struct octeon_cf_port *cf_port = dev->platform_data; + struct octeon_cf_port *cf_port = dev_get_platdata(dev); if (cf_port->dma_base) { /* Stop and clear the dma engine. */ diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c index 71e093767f4e..02794885de10 100644 --- a/drivers/ata/pata_platform.c +++ b/drivers/ata/pata_platform.c @@ -180,7 +180,7 @@ static int pata_platform_probe(struct platform_device *pdev) struct resource *io_res; struct resource *ctl_res; struct resource *irq_res; - struct pata_platform_info *pp_info = pdev->dev.platform_data; + struct pata_platform_info *pp_info = dev_get_platdata(&pdev->dev); /* * Simple resource validation .. diff --git a/drivers/ata/pata_pxa.c b/drivers/ata/pata_pxa.c index 942ef94b29e6..a6f05acad61e 100644 --- a/drivers/ata/pata_pxa.c +++ b/drivers/ata/pata_pxa.c @@ -238,7 +238,7 @@ static int pxa_ata_probe(struct platform_device *pdev) struct resource *ctl_res; struct resource *dma_res; struct resource *irq_res; - struct pata_pxa_pdata *pdata = pdev->dev.platform_data; + struct pata_pxa_pdata *pdata = dev_get_platdata(&pdev->dev); int ret = 0; /* diff --git a/drivers/ata/pata_samsung_cf.c b/drivers/ata/pata_samsung_cf.c index 6ef27e98c508..951aa951ffdb 100644 --- a/drivers/ata/pata_samsung_cf.c +++ b/drivers/ata/pata_samsung_cf.c @@ -475,7 +475,7 @@ static void pata_s3c_hwinit(struct s3c_ide_info *info, static int __init pata_s3c_probe(struct platform_device *pdev) { - struct s3c_ide_platdata *pdata = pdev->dev.platform_data; + struct s3c_ide_platdata *pdata = dev_get_platdata(&pdev->dev); struct device *dev = &pdev->dev; struct s3c_ide_info *info; struct resource *res; @@ -617,7 +617,7 @@ static int pata_s3c_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct ata_host *host = platform_get_drvdata(pdev); - struct s3c_ide_platdata *pdata = pdev->dev.platform_data; + struct s3c_ide_platdata *pdata = dev_get_platdata(&pdev->dev); struct s3c_ide_info *info = host->private_data; pata_s3c_hwinit(info, pdata); diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 10ea99a0192d..88e08515cf46 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -4058,7 +4058,7 @@ static int mv_platform_probe(struct platform_device *pdev) of_property_read_u32(pdev->dev.of_node, "nr-ports", &n_ports); irq = irq_of_parse_and_map(pdev->dev.of_node, 0); } else { - mv_platform_data = pdev->dev.platform_data; + mv_platform_data = dev_get_platdata(&pdev->dev); n_ports = mv_platform_data->n_ports; irq = platform_get_irq(pdev, 0); } From e0067f0b71a2b5d1c5d8df556830db253aa1b264 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Mon, 29 Jul 2013 23:46:03 -0300 Subject: [PATCH 1108/3400] sata_mv: Remove unneeded CONFIG_HAVE_CLK ifdefs If CONFIG_HAVE_CLK is not selected, then all the clk API turn out into no-ops. In other words, there's no need to have the ifdefs. The only side-effect of this patch is the extra tiny kmalloc, but that's not enough reason to have such ugly ifdefs all around the code. tj: Slightly massaged comment as per Andrew Lunn. Signed-off-by: Ezequiel Garcia Acked-by: Andrew Lunn Signed-off-by: Tejun Heo --- drivers/ata/sata_mv.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 88e08515cf46..56be31819897 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -553,10 +553,15 @@ struct mv_host_priv { u32 irq_mask_offset; u32 unmask_all_irqs; -#if defined(CONFIG_HAVE_CLK) + /* + * Needed on some devices that require their clocks to be enabled. + * These are optional: if the platform device does not have any + * clocks, they won't be used. Also, if the underlying hardware + * does not support the common clock framework (CONFIG_HAVE_CLK=n), + * all the clock operations become no-ops (see clk.h). + */ struct clk *clk; struct clk **port_clks; -#endif /* * These consistent DMA memory pools give us guaranteed * alignment for hardware-accessed data structures, @@ -4032,9 +4037,7 @@ static int mv_platform_probe(struct platform_device *pdev) struct resource *res; int n_ports = 0, irq = 0; int rc; -#if defined(CONFIG_HAVE_CLK) int port; -#endif ata_print_version_once(&pdev->dev, DRV_VERSION); @@ -4068,13 +4071,11 @@ static int mv_platform_probe(struct platform_device *pdev) if (!host || !hpriv) return -ENOMEM; -#if defined(CONFIG_HAVE_CLK) hpriv->port_clks = devm_kzalloc(&pdev->dev, sizeof(struct clk *) * n_ports, GFP_KERNEL); if (!hpriv->port_clks) return -ENOMEM; -#endif host->private_data = hpriv; hpriv->n_ports = n_ports; hpriv->board_idx = chip_soc; @@ -4084,7 +4085,6 @@ static int mv_platform_probe(struct platform_device *pdev) resource_size(res)); hpriv->base -= SATAHC0_REG_BASE; -#if defined(CONFIG_HAVE_CLK) hpriv->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(hpriv->clk)) dev_notice(&pdev->dev, "cannot get optional clkdev\n"); @@ -4098,7 +4098,6 @@ static int mv_platform_probe(struct platform_device *pdev) if (!IS_ERR(hpriv->port_clks[port])) clk_prepare_enable(hpriv->port_clks[port]); } -#endif /* * (Re-)program MBUS remapping windows if we are asked to. @@ -4124,7 +4123,6 @@ static int mv_platform_probe(struct platform_device *pdev) return 0; err: -#if defined(CONFIG_HAVE_CLK) if (!IS_ERR(hpriv->clk)) { clk_disable_unprepare(hpriv->clk); clk_put(hpriv->clk); @@ -4135,7 +4133,6 @@ err: clk_put(hpriv->port_clks[port]); } } -#endif return rc; } @@ -4151,13 +4148,10 @@ err: static int mv_platform_remove(struct platform_device *pdev) { struct ata_host *host = platform_get_drvdata(pdev); -#if defined(CONFIG_HAVE_CLK) struct mv_host_priv *hpriv = host->private_data; int port; -#endif ata_host_detach(host); -#if defined(CONFIG_HAVE_CLK) if (!IS_ERR(hpriv->clk)) { clk_disable_unprepare(hpriv->clk); clk_put(hpriv->clk); @@ -4168,7 +4162,6 @@ static int mv_platform_remove(struct platform_device *pdev) clk_put(hpriv->port_clks[port]); } } -#endif return 0; } From 0e003b709ef9f4c43f6338834526c3556ea71b19 Mon Sep 17 00:00:00 2001 From: Stefan Haberland Date: Tue, 30 Jul 2013 10:49:43 +0200 Subject: [PATCH 1109/3400] s390/dasd: fix hanging devices after path events The processing of the dasd_block tasklet may have been interrupted by a path event. Restart the dasd tasklets in sleep_on_immediately function. Signed-off-by: Stefan Haberland Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 17150a778984..451bf99582ff 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -2392,6 +2392,12 @@ int dasd_sleep_on_immediatly(struct dasd_ccw_req *cqr) rc = cqr->intrc; else rc = -EIO; + + /* kick tasklets */ + dasd_schedule_device_bh(device); + if (device->block) + dasd_schedule_block_bh(device->block); + return rc; } From 19b6984e972f2aca82d3756f826ded68e0a8fef8 Mon Sep 17 00:00:00 2001 From: Yijing Wang Date: Wed, 24 Jul 2013 17:26:12 +0800 Subject: [PATCH 1110/3400] PCI: Update NumVFs register when disabling SR-IOV Currently, we only update NumVFs register during sriov_enable(). This register should also be updated during sriov_disable() and when sriov_enable() fails. Otherwise, we will get the stale "Number of VFs" info from lspci. [bhelgaas: changelog] Signed-off-by: Yijing Wang Signed-off-by: Bjorn Helgaas --- drivers/pci/iov.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index de4034ee0efa..e73bdae447cc 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c @@ -286,7 +286,6 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn) (!(iov->cap & PCI_SRIOV_CAP_VFM) && (nr_virtfn > initial))) return -EINVAL; - pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, nr_virtfn); pci_read_config_word(dev, iov->pos + PCI_SRIOV_VF_OFFSET, &offset); pci_read_config_word(dev, iov->pos + PCI_SRIOV_VF_STRIDE, &stride); if (!offset || (nr_virtfn > 1 && !stride)) @@ -334,6 +333,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn) return rc; } + pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, nr_virtfn); iov->ctrl |= PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE; pci_cfg_access_lock(dev); pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl); @@ -368,6 +368,7 @@ failed: iov->ctrl &= ~(PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE); pci_cfg_access_lock(dev); pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl); + pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, 0); ssleep(1); pci_cfg_access_unlock(dev); @@ -401,6 +402,7 @@ static void sriov_disable(struct pci_dev *dev) sysfs_remove_link(&dev->dev.kobj, "dep_link"); iov->num_VFs = 0; + pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, 0); } static int sriov_init(struct pci_dev *dev, int pos) From bf0bd948d1682e3996adc093b43021ed391983e6 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 26 Jul 2013 23:48:42 +0200 Subject: [PATCH 1111/3400] sched: Ensure update_cfs_shares() is called for parents of continuously-running tasks We typically update a task_group's shares within the dequeue/enqueue path. However, continuously running tasks sharing a CPU are not subject to these updates as they are only put/picked. Unfortunately, when we reverted f269ae046 (in 17bc14b7), we lost the augmenting periodic update that was supposed to account for this; resulting in a potential loss of fairness. To fix this, re-introduce the explicit update in update_cfs_rq_blocked_load() [called via entity_tick()]. Reported-by: Max Hailperin Signed-off-by: Peter Zijlstra Reviewed-by: Paul Turner Link: http://lkml.kernel.org/n/tip-9545m3apw5d93ubyrotrj31y@git.kernel.org Cc: Signed-off-by: Ingo Molnar --- kernel/sched/fair.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 98d135584b4b..06db94bf47a8 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -2032,6 +2032,7 @@ entity_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr, int queued) */ update_entity_load_avg(curr, 1); update_cfs_rq_blocked_load(cfs_rq, 1); + update_cfs_shares(cfs_rq); #ifdef CONFIG_SCHED_HRTICK /* From 85f4896123d0299128f2c95cc40f3b8b01d4b0f6 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 30 Jul 2013 10:13:41 +0200 Subject: [PATCH 1112/3400] mutex: Fix w/w mutex deadlock injection The check needs to be for > 1, because ctx->acquired is already incremented. This will prevent ww_mutex_lock_slow from returning -EDEADLK and not locking the mutex. It caused a lot of false gpu lockups on radeon with CONFIG_DEBUG_WW_MUTEX_SLOWPATH=y because a function that shouldn't be able to return -EDEADLK did. Signed-off-by: Maarten Lankhorst Signed-off-by: Peter Zijlstra Cc: Alex Deucher Cc: Linus Torvalds Cc: Andrew Morton Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/51F775B5.201@canonical.com Signed-off-by: Ingo Molnar --- kernel/mutex.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/mutex.c b/kernel/mutex.c index ff05f4bd86eb..a52ee7bb830d 100644 --- a/kernel/mutex.c +++ b/kernel/mutex.c @@ -686,7 +686,7 @@ __ww_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ctx) might_sleep(); ret = __mutex_lock_common(&lock->base, TASK_UNINTERRUPTIBLE, 0, &ctx->dep_map, _RET_IP_, ctx); - if (!ret && ctx->acquired > 0) + if (!ret && ctx->acquired > 1) return ww_mutex_deadlock_injection(lock, ctx); return ret; @@ -702,7 +702,7 @@ __ww_mutex_lock_interruptible(struct ww_mutex *lock, struct ww_acquire_ctx *ctx) ret = __mutex_lock_common(&lock->base, TASK_INTERRUPTIBLE, 0, &ctx->dep_map, _RET_IP_, ctx); - if (!ret && ctx->acquired > 0) + if (!ret && ctx->acquired > 1) return ww_mutex_deadlock_injection(lock, ctx); return ret; From 46591962cb5bfd2bfb0baf42497119c816503598 Mon Sep 17 00:00:00 2001 From: Xie XiuQi Date: Tue, 30 Jul 2013 11:06:09 +0800 Subject: [PATCH 1113/3400] generic-ipi: Kill unnecessary variable - csd_flags After commit 8969a5ede0f9e17da4b943712429aef2c9bcd82b ("generic-ipi: remove kmalloc()"), wait = 0 can be guaranteed, and all callsites of generic_exec_single() do an unconditional csd_lock() now. So csd_flags is unnecessary now. Remove it. Signed-off-by: Xie XiuQi Signed-off-by: Peter Zijlstra Cc: Oleg Nesterov Cc: Linus Torvalds Cc: Nick Piggin Cc: Jens Axboe Cc: "Paul E. McKenney" Cc: Rusty Russell Link: http://lkml.kernel.org/r/51F72DA1.7010401@huawei.com Signed-off-by: Ingo Molnar --- kernel/smp.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/kernel/smp.c b/kernel/smp.c index fe9f773d7114..7332697cd184 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -186,25 +186,13 @@ void generic_smp_call_function_single_interrupt(void) while (!list_empty(&list)) { struct call_single_data *csd; - unsigned int csd_flags; csd = list_entry(list.next, struct call_single_data, list); list_del(&csd->list); - /* - * 'csd' can be invalid after this call if flags == 0 - * (when called through generic_exec_single()), - * so save them away before making the call: - */ - csd_flags = csd->flags; - csd->func(csd->info); - /* - * Unlocked CSDs are valid through generic_exec_single(): - */ - if (csd_flags & CSD_FLAG_LOCK) - csd_unlock(csd); + csd_unlock(csd); } } From 6050cb0b0b366092d1383bc23d7b16cd26db00f0 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Tue, 23 Jul 2013 02:30:59 +0200 Subject: [PATCH 1114/3400] perf: Fix branch stack refcount leak on callchain init failure On callchain buffers allocation failure, free_event() is called and all the accounting performed in perf_event_alloc() for that event is cancelled. But if the event has branch stack sampling, it is unaccounted as well from the branch stack sampling events refcounts. This is a bug because this accounting is performed after the callchain buffer allocation. As a result, the branch stack sampling events refcount can become negative. To fix this, move the branch stack event accounting before the callchain buffer allocation. Reported-by: Peter Zijlstra Signed-off-by: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Arnaldo Carvalho de Melo Cc: Stephane Eranian Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1374539466-4799-2-git-send-email-fweisbec@gmail.com Signed-off-by: Ingo Molnar --- kernel/events/core.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/kernel/events/core.c b/kernel/events/core.c index 127411400116..f35aa7e69e2d 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -6567,6 +6567,12 @@ done: atomic_inc(&nr_comm_events); if (event->attr.task) atomic_inc(&nr_task_events); + if (has_branch_stack(event)) { + static_key_slow_inc(&perf_sched_events.key); + if (!(event->attach_state & PERF_ATTACH_TASK)) + atomic_inc(&per_cpu(perf_branch_stack_events, + event->cpu)); + } if (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN) { err = get_callchain_buffers(); if (err) { @@ -6574,12 +6580,6 @@ done: return ERR_PTR(err); } } - if (has_branch_stack(event)) { - static_key_slow_inc(&perf_sched_events.key); - if (!(event->attach_state & PERF_ATTACH_TASK)) - atomic_inc(&per_cpu(perf_branch_stack_events, - event->cpu)); - } } return event; From 90983b16078ab0fdc58f0dab3e8e3da79c9579a2 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Tue, 23 Jul 2013 02:31:00 +0200 Subject: [PATCH 1115/3400] perf: Sanitize get_callchain_buffer() In case of allocation failure, get_callchain_buffer() keeps the refcount incremented for the current event. As a result, when get_callchain_buffers() returns an error, we must cleanup what it did by cancelling its last refcount with a call to put_callchain_buffers(). This is a hack in order to be able to call free_event() after that failure. The original purpose of that was to simplify the failure path. But this error handling is actually counter intuitive, ugly and not very easy to follow because one expect to see the resources used to perform a service to be cleaned by the callee if case of failure, not by the caller. So lets clean this up by cancelling the refcount from get_callchain_buffer() in case of failure. And correctly free the event accordingly in perf_event_alloc(). Signed-off-by: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Arnaldo Carvalho de Melo Cc: Stephane Eranian Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1374539466-4799-3-git-send-email-fweisbec@gmail.com Signed-off-by: Ingo Molnar --- kernel/events/callchain.c | 2 ++ kernel/events/core.c | 41 ++++++++++++++++++++------------------- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/kernel/events/callchain.c b/kernel/events/callchain.c index c77206184b8b..76a8bc5f6265 100644 --- a/kernel/events/callchain.c +++ b/kernel/events/callchain.c @@ -117,6 +117,8 @@ int get_callchain_buffers(void) err = alloc_callchain_buffers(); exit: mutex_unlock(&callchain_mutex); + if (err) + atomic_dec(&nr_callchain_events); return err; } diff --git a/kernel/events/core.c b/kernel/events/core.c index f35aa7e69e2d..3b998626b7a0 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -6457,7 +6457,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu, struct pmu *pmu; struct perf_event *event; struct hw_perf_event *hwc; - long err; + long err = -EINVAL; if ((unsigned)cpu >= nr_cpu_ids) { if (!task || cpu != -1) @@ -6540,25 +6540,23 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu, * we currently do not support PERF_FORMAT_GROUP on inherited events */ if (attr->inherit && (attr->read_format & PERF_FORMAT_GROUP)) - goto done; + goto err_ns; pmu = perf_init_event(event); - -done: - err = 0; if (!pmu) - err = -EINVAL; - else if (IS_ERR(pmu)) + goto err_ns; + else if (IS_ERR(pmu)) { err = PTR_ERR(pmu); - - if (err) { - if (event->ns) - put_pid_ns(event->ns); - kfree(event); - return ERR_PTR(err); + goto err_ns; } if (!event->parent) { + if (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN) { + err = get_callchain_buffers(); + if (err) + goto err_pmu; + } + if (event->attach_state & PERF_ATTACH_TASK) static_key_slow_inc(&perf_sched_events.key); if (event->attr.mmap || event->attr.mmap_data) @@ -6573,16 +6571,19 @@ done: atomic_inc(&per_cpu(perf_branch_stack_events, event->cpu)); } - if (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN) { - err = get_callchain_buffers(); - if (err) { - free_event(event); - return ERR_PTR(err); - } - } } return event; + +err_pmu: + if (event->destroy) + event->destroy(event); +err_ns: + if (event->ns) + put_pid_ns(event->ns); + kfree(event); + + return ERR_PTR(err); } static int perf_copy_attr(struct perf_event_attr __user *uattr, From 766d6c076928191d75ad5b0d0f58f52b1e7682d8 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Tue, 23 Jul 2013 02:31:01 +0200 Subject: [PATCH 1116/3400] perf: Factor out event accounting code to account_event()/__free_event() Gather all the event accounting code to a single place, once all the prerequisites are completed. This simplifies the refcounting. Original-patch-by: Peter Zijlstra Signed-off-by: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Arnaldo Carvalho de Melo Cc: Stephane Eranian Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1374539466-4799-4-git-send-email-fweisbec@gmail.com Signed-off-by: Ingo Molnar --- kernel/events/core.c | 79 ++++++++++++++++++++++++++------------------ 1 file changed, 47 insertions(+), 32 deletions(-) diff --git a/kernel/events/core.c b/kernel/events/core.c index 3b998626b7a0..158fd5789e58 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -3128,6 +3128,21 @@ static void free_event_rcu(struct rcu_head *head) static void ring_buffer_put(struct ring_buffer *rb); static void ring_buffer_detach(struct perf_event *event, struct ring_buffer *rb); +static void __free_event(struct perf_event *event) +{ + if (!event->parent) { + if (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN) + put_callchain_buffers(); + } + + if (event->destroy) + event->destroy(event); + + if (event->ctx) + put_ctx(event->ctx); + + call_rcu(&event->rcu_head, free_event_rcu); +} static void free_event(struct perf_event *event) { irq_work_sync(&event->pending); @@ -3141,8 +3156,6 @@ static void free_event(struct perf_event *event) atomic_dec(&nr_comm_events); if (event->attr.task) atomic_dec(&nr_task_events); - if (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN) - put_callchain_buffers(); if (is_cgroup_event(event)) { atomic_dec(&per_cpu(perf_cgroup_events, event->cpu)); static_key_slow_dec_deferred(&perf_sched_events); @@ -3180,13 +3193,8 @@ static void free_event(struct perf_event *event) if (is_cgroup_event(event)) perf_detach_cgroup(event); - if (event->destroy) - event->destroy(event); - if (event->ctx) - put_ctx(event->ctx); - - call_rcu(&event->rcu_head, free_event_rcu); + __free_event(event); } int perf_event_release_kernel(struct perf_event *event) @@ -6443,6 +6451,29 @@ unlock: return pmu; } +static void account_event(struct perf_event *event) +{ + if (event->attach_state & PERF_ATTACH_TASK) + static_key_slow_inc(&perf_sched_events.key); + if (event->attr.mmap || event->attr.mmap_data) + atomic_inc(&nr_mmap_events); + if (event->attr.comm) + atomic_inc(&nr_comm_events); + if (event->attr.task) + atomic_inc(&nr_task_events); + if (has_branch_stack(event)) { + static_key_slow_inc(&perf_sched_events.key); + if (!(event->attach_state & PERF_ATTACH_TASK)) + atomic_inc(&per_cpu(perf_branch_stack_events, + event->cpu)); + } + + if (is_cgroup_event(event)) { + atomic_inc(&per_cpu(perf_cgroup_events, event->cpu)); + static_key_slow_inc(&perf_sched_events.key); + } +} + /* * Allocate and initialize a event structure */ @@ -6556,21 +6587,6 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu, if (err) goto err_pmu; } - - if (event->attach_state & PERF_ATTACH_TASK) - static_key_slow_inc(&perf_sched_events.key); - if (event->attr.mmap || event->attr.mmap_data) - atomic_inc(&nr_mmap_events); - if (event->attr.comm) - atomic_inc(&nr_comm_events); - if (event->attr.task) - atomic_inc(&nr_task_events); - if (has_branch_stack(event)) { - static_key_slow_inc(&perf_sched_events.key); - if (!(event->attach_state & PERF_ATTACH_TASK)) - atomic_inc(&per_cpu(perf_branch_stack_events, - event->cpu)); - } } return event; @@ -6865,17 +6881,14 @@ SYSCALL_DEFINE5(perf_event_open, if (flags & PERF_FLAG_PID_CGROUP) { err = perf_cgroup_connect(pid, event, &attr, group_leader); - if (err) - goto err_alloc; - /* - * one more event: - * - that has cgroup constraint on event->cpu - * - that may need work on context switch - */ - atomic_inc(&per_cpu(perf_cgroup_events, event->cpu)); - static_key_slow_inc(&perf_sched_events.key); + if (err) { + __free_event(event); + goto err_task; + } } + account_event(event); + /* * Special case software events and allow them to be part of * any hardware group. @@ -7071,6 +7084,8 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu, goto err; } + account_event(event); + ctx = find_get_context(event->pmu, task, cpu); if (IS_ERR(ctx)) { err = PTR_ERR(ctx); From 4beb31f3657348a8b702dd014d01c520e522012f Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Tue, 23 Jul 2013 02:31:02 +0200 Subject: [PATCH 1117/3400] perf: Split the per-cpu accounting part of the event accounting code This way we can use the per-cpu handling seperately. This is going to be used by to fix the event migration code accounting. Original-patch-by: Peter Zijlstra Signed-off-by: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Arnaldo Carvalho de Melo Cc: Stephane Eranian Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1374539466-4799-5-git-send-email-fweisbec@gmail.com Signed-off-by: Ingo Molnar --- kernel/events/core.c | 87 ++++++++++++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 32 deletions(-) diff --git a/kernel/events/core.c b/kernel/events/core.c index 158fd5789e58..3a4b73aebc42 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -3128,6 +3128,40 @@ static void free_event_rcu(struct rcu_head *head) static void ring_buffer_put(struct ring_buffer *rb); static void ring_buffer_detach(struct perf_event *event, struct ring_buffer *rb); +static void unaccount_event_cpu(struct perf_event *event, int cpu) +{ + if (event->parent) + return; + + if (has_branch_stack(event)) { + if (!(event->attach_state & PERF_ATTACH_TASK)) + atomic_dec(&per_cpu(perf_branch_stack_events, cpu)); + } + if (is_cgroup_event(event)) + atomic_dec(&per_cpu(perf_cgroup_events, cpu)); +} + +static void unaccount_event(struct perf_event *event) +{ + if (event->parent) + return; + + if (event->attach_state & PERF_ATTACH_TASK) + static_key_slow_dec_deferred(&perf_sched_events); + if (event->attr.mmap || event->attr.mmap_data) + atomic_dec(&nr_mmap_events); + if (event->attr.comm) + atomic_dec(&nr_comm_events); + if (event->attr.task) + atomic_dec(&nr_task_events); + if (is_cgroup_event(event)) + static_key_slow_dec_deferred(&perf_sched_events); + if (has_branch_stack(event)) + static_key_slow_dec_deferred(&perf_sched_events); + + unaccount_event_cpu(event, event->cpu); +} + static void __free_event(struct perf_event *event) { if (!event->parent) { @@ -3147,29 +3181,7 @@ static void free_event(struct perf_event *event) { irq_work_sync(&event->pending); - if (!event->parent) { - if (event->attach_state & PERF_ATTACH_TASK) - static_key_slow_dec_deferred(&perf_sched_events); - if (event->attr.mmap || event->attr.mmap_data) - atomic_dec(&nr_mmap_events); - if (event->attr.comm) - atomic_dec(&nr_comm_events); - if (event->attr.task) - atomic_dec(&nr_task_events); - if (is_cgroup_event(event)) { - atomic_dec(&per_cpu(perf_cgroup_events, event->cpu)); - static_key_slow_dec_deferred(&perf_sched_events); - } - - if (has_branch_stack(event)) { - static_key_slow_dec_deferred(&perf_sched_events); - /* is system-wide event */ - if (!(event->attach_state & PERF_ATTACH_TASK)) { - atomic_dec(&per_cpu(perf_branch_stack_events, - event->cpu)); - } - } - } + unaccount_event(event); if (event->rb) { struct ring_buffer *rb; @@ -6451,8 +6463,24 @@ unlock: return pmu; } +static void account_event_cpu(struct perf_event *event, int cpu) +{ + if (event->parent) + return; + + if (has_branch_stack(event)) { + if (!(event->attach_state & PERF_ATTACH_TASK)) + atomic_inc(&per_cpu(perf_branch_stack_events, cpu)); + } + if (is_cgroup_event(event)) + atomic_inc(&per_cpu(perf_cgroup_events, cpu)); +} + static void account_event(struct perf_event *event) { + if (event->parent) + return; + if (event->attach_state & PERF_ATTACH_TASK) static_key_slow_inc(&perf_sched_events.key); if (event->attr.mmap || event->attr.mmap_data) @@ -6461,17 +6489,12 @@ static void account_event(struct perf_event *event) atomic_inc(&nr_comm_events); if (event->attr.task) atomic_inc(&nr_task_events); - if (has_branch_stack(event)) { + if (has_branch_stack(event)) + static_key_slow_inc(&perf_sched_events.key); + if (is_cgroup_event(event)) static_key_slow_inc(&perf_sched_events.key); - if (!(event->attach_state & PERF_ATTACH_TASK)) - atomic_inc(&per_cpu(perf_branch_stack_events, - event->cpu)); - } - if (is_cgroup_event(event)) { - atomic_inc(&per_cpu(perf_cgroup_events, event->cpu)); - static_key_slow_inc(&perf_sched_events.key); - } + account_event_cpu(event, event->cpu); } /* From 9a545de019b536771feefb76f85e5038b65c2190 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Tue, 23 Jul 2013 02:31:03 +0200 Subject: [PATCH 1118/3400] perf: Migrate per cpu event accounting When an event is migrated, move the event per-cpu accounting accordingly so that branch stack and cgroup events work correctly on the new CPU. Original-patch-by: Peter Zijlstra Signed-off-by: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Arnaldo Carvalho de Melo Cc: Stephane Eranian Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1374539466-4799-6-git-send-email-fweisbec@gmail.com Signed-off-by: Ingo Molnar --- kernel/events/core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/events/core.c b/kernel/events/core.c index 3a4b73aebc42..63bdec9fdd21 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -7145,6 +7145,7 @@ void perf_pmu_migrate_context(struct pmu *pmu, int src_cpu, int dst_cpu) list_for_each_entry_safe(event, tmp, &src_ctx->event_list, event_entry) { perf_remove_from_context(event); + unaccount_event_cpu(event, src_cpu); put_ctx(src_ctx); list_add(&event->event_entry, &events); } @@ -7157,6 +7158,7 @@ void perf_pmu_migrate_context(struct pmu *pmu, int src_cpu, int dst_cpu) list_del(&event->event_entry); if (event->state >= PERF_EVENT_STATE_OFF) event->state = PERF_EVENT_STATE_INACTIVE; + account_event_cpu(event, dst_cpu); perf_install_in_context(dst_ctx, event, dst_cpu); get_ctx(dst_ctx); } From ba8a75c16e292c0a3a87406a77508cbbc6cf4ee2 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Tue, 23 Jul 2013 02:31:04 +0200 Subject: [PATCH 1119/3400] perf: Account freq events per cpu This is going to be used by the full dynticks subsystem as a finer-grained information to know when to keep and when to stop the tick. Original-patch-by: Peter Zijlstra Signed-off-by: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Arnaldo Carvalho de Melo Cc: Stephane Eranian Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1374539466-4799-7-git-send-email-fweisbec@gmail.com Signed-off-by: Ingo Molnar --- kernel/events/core.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/kernel/events/core.c b/kernel/events/core.c index 63bdec9fdd21..3fe385aa93e6 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -141,6 +141,7 @@ enum event_type_t { struct static_key_deferred perf_sched_events __read_mostly; static DEFINE_PER_CPU(atomic_t, perf_cgroup_events); static DEFINE_PER_CPU(atomic_t, perf_branch_stack_events); +static DEFINE_PER_CPU(atomic_t, perf_freq_events); static atomic_t nr_mmap_events __read_mostly; static atomic_t nr_comm_events __read_mostly; @@ -3139,6 +3140,9 @@ static void unaccount_event_cpu(struct perf_event *event, int cpu) } if (is_cgroup_event(event)) atomic_dec(&per_cpu(perf_cgroup_events, cpu)); + + if (event->attr.freq) + atomic_dec(&per_cpu(perf_freq_events, cpu)); } static void unaccount_event(struct perf_event *event) @@ -6474,6 +6478,9 @@ static void account_event_cpu(struct perf_event *event, int cpu) } if (is_cgroup_event(event)) atomic_inc(&per_cpu(perf_cgroup_events, cpu)); + + if (event->attr.freq) + atomic_inc(&per_cpu(perf_freq_events, cpu)); } static void account_event(struct perf_event *event) From d84153d6c96f61aa06429586284639f32debf03e Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Tue, 23 Jul 2013 02:31:05 +0200 Subject: [PATCH 1120/3400] perf: Implement finer grained full dynticks kick Currently the full dynticks subsystem keep the tick alive as long as there are perf events running. This prevents the tick from being stopped as long as features such that the lockup detectors are running. As a temporary fix, the lockup detector is disabled by default when full dynticks is built but this is not a long term viable solution. To fix this, only keep the tick alive when an event configured with a frequency rather than a period is running on the CPU, or when an event throttles on the CPU. These are the only purposes of the perf tick, especially now that the rotation of flexible events is handled from a seperate hrtimer. The tick can be shutdown the rest of the time. Original-patch-by: Peter Zijlstra Signed-off-by: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Arnaldo Carvalho de Melo Cc: Stephane Eranian Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1374539466-4799-8-git-send-email-fweisbec@gmail.com Signed-off-by: Ingo Molnar --- kernel/events/core.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/kernel/events/core.c b/kernel/events/core.c index 3fe385aa93e6..916cf1f593b4 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -870,12 +870,8 @@ static void perf_pmu_rotate_start(struct pmu *pmu) WARN_ON(!irqs_disabled()); - if (list_empty(&cpuctx->rotation_list)) { - int was_empty = list_empty(head); + if (list_empty(&cpuctx->rotation_list)) list_add(&cpuctx->rotation_list, head); - if (was_empty) - tick_nohz_full_kick(); - } } static void get_ctx(struct perf_event_context *ctx) @@ -1875,6 +1871,9 @@ static int __perf_install_in_context(void *info) perf_pmu_enable(cpuctx->ctx.pmu); perf_ctx_unlock(cpuctx, task_ctx); + if (atomic_read(&__get_cpu_var(perf_freq_events))) + tick_nohz_full_kick(); + return 0; } @@ -2812,10 +2811,11 @@ done: #ifdef CONFIG_NO_HZ_FULL bool perf_event_can_stop_tick(void) { - if (list_empty(&__get_cpu_var(rotation_list))) - return true; - else + if (atomic_read(&__get_cpu_var(perf_freq_events)) || + __this_cpu_read(perf_throttled_count)) return false; + else + return true; } #endif @@ -5202,6 +5202,7 @@ static int __perf_event_overflow(struct perf_event *event, __this_cpu_inc(perf_throttled_count); hwc->interrupts = MAX_INTERRUPTS; perf_log_throttle(event, 0); + tick_nohz_full_kick(); ret = 1; } } From 93786a5f6aeb9c032c1c240246c5aabcf457b38f Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Tue, 23 Jul 2013 02:31:06 +0200 Subject: [PATCH 1121/3400] watchdog: Make it work under full dynticks A perf event can be used without forcing the tick to stay alive if it doesn't use a frequency but a sample period and if it doesn't throttle (raise storm of events). Since the lockup detector neither use a perf event frequency nor should ever throttle due to its high period, it can now run concurrently with the full dynticks feature. So remove the hack that disabled the watchdog. Signed-off-by: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Arnaldo Carvalho de Melo Cc: Stephane Eranian Cc: Don Zickus Cc: Srivatsa S. Bhat Cc: Anish Singh Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1374539466-4799-9-git-send-email-fweisbec@gmail.com Signed-off-by: Ingo Molnar --- kernel/watchdog.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/kernel/watchdog.c b/kernel/watchdog.c index 1241d8c91d5e..51c4f34d258e 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c @@ -553,14 +553,6 @@ void __init lockup_detector_init(void) { set_sample_period(); -#ifdef CONFIG_NO_HZ_FULL - if (watchdog_user_enabled) { - watchdog_user_enabled = 0; - pr_warning("Disabled lockup detectors by default for full dynticks\n"); - pr_warning("You can reactivate it with 'sysctl -w kernel.watchdog=1'\n"); - } -#endif - if (watchdog_user_enabled) watchdog_enable_all_cpus(); } From c319d50bfcf678c2857038276d9fab3c6646f3bf Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 30 Jul 2013 22:34:28 +0200 Subject: [PATCH 1122/3400] nl80211: fix another nl80211_fam.attrbuf race This is similar to the race Linus had reported, but in this case it's an older bug: nl80211_prepare_wdev_dump() uses the wiphy index in cb->args[0] as it is and thus parses the message over and over again instead of just once because 0 is the first valid wiphy index. Similar code in nl80211_testmode_dump() correctly offsets the wiphy_index by 1, do that here as well. Cc: stable@vger.kernel.org Reported-by: Ben Hutchings Signed-off-by: Johannes Berg --- net/wireless/nl80211.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 25d217d90807..3fcba69817e5 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -441,10 +441,12 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb, goto out_unlock; } *rdev = wiphy_to_dev((*wdev)->wiphy); - cb->args[0] = (*rdev)->wiphy_idx; + /* 0 is the first index - add 1 to parse only once */ + cb->args[0] = (*rdev)->wiphy_idx + 1; cb->args[1] = (*wdev)->identifier; } else { - struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0]); + /* subtract the 1 again here */ + struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1); struct wireless_dev *tmp; if (!wiphy) { From 8c4f3c3fa9681dc549cd35419b259496082fef8b Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Tue, 30 Jul 2013 00:04:32 -0400 Subject: [PATCH 1123/3400] ftrace: Check module functions being traced on reload MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's been a nasty bug that would show up and not give much info. The bug displayed the following warning: WARNING: at kernel/trace/ftrace.c:1529 __ftrace_hash_rec_update+0x1e3/0x230() Pid: 20903, comm: bash Tainted: G O 3.6.11+ #38405.trunk Call Trace: [] warn_slowpath_common+0x7f/0xc0 [] warn_slowpath_null+0x1a/0x20 [] __ftrace_hash_rec_update+0x1e3/0x230 [] ftrace_hash_move+0x28/0x1d0 [] ? kfree+0x2c/0x110 [] ftrace_regex_release+0x8e/0x150 [] __fput+0xae/0x220 [] ____fput+0xe/0x10 [] task_work_run+0x72/0x90 [] do_notify_resume+0x6c/0xc0 [] ? trace_hardirqs_on_thunk+0x3a/0x3c [] int_signal+0x12/0x17 ---[ end trace 793179526ee09b2c ]--- It was finally narrowed down to unloading a module that was being traced. It was actually more than that. When functions are being traced, there's a table of all functions that have a ref count of the number of active tracers attached to that function. When a function trace callback is registered to a function, the function's record ref count is incremented. When it is unregistered, the function's record ref count is decremented. If an inconsistency is detected (ref count goes below zero) the above warning is shown and the function tracing is permanently disabled until reboot. The ftrace callback ops holds a hash of functions that it filters on (and/or filters off). If the hash is empty, the default means to filter all functions (for the filter_hash) or to disable no functions (for the notrace_hash). When a module is unloaded, it frees the function records that represent the module functions. These records exist on their own pages, that is function records for one module will not exist on the same page as function records for other modules or even the core kernel. Now when a module unloads, the records that represents its functions are freed. When the module is loaded again, the records are recreated with a default ref count of zero (unless there's a callback that traces all functions, then they will also be traced, and the ref count will be incremented). The problem is that if an ftrace callback hash includes functions of the module being unloaded, those hash entries will not be removed. If the module is reloaded in the same location, the hash entries still point to the functions of the module but the module's ref counts do not reflect that. With the help of Steve and Joern, we found a reproducer: Using uinput module and uinput_release function. cd /sys/kernel/debug/tracing modprobe uinput echo uinput_release > set_ftrace_filter echo function > current_tracer rmmod uinput modprobe uinput # check /proc/modules to see if loaded in same addr, otherwise try again echo nop > current_tracer [BOOM] The above loads the uinput module, which creates a table of functions that can be traced within the module. We add uinput_release to the filter_hash to trace just that function. Enable function tracincg, which increments the ref count of the record associated to uinput_release. Remove uinput, which frees the records including the one that represents uinput_release. Load the uinput module again (and make sure it's at the same address). This recreates the function records all with a ref count of zero, including uinput_release. Disable function tracing, which will decrement the ref count for uinput_release which is now zero because of the module removal and reload, and we have a mismatch (below zero ref count). The solution is to check all currently tracing ftrace callbacks to see if any are tracing any of the module's functions when a module is loaded (it already does that with callbacks that trace all functions). If a callback happens to have a module function being traced, it increments that records ref count and starts tracing that function. There may be a strange side effect with this, where tracing module functions on unload and then reloading a new module may have that new module's functions being traced. This may be something that confuses the user, but it's not a big deal. Another approach is to disable all callback hashes on module unload, but this leaves some ftrace callbacks that may not be registered, but can still have hashes tracing the module's function where ftrace doesn't know about it. That situation can cause the same bug. This solution solves that case too. Another benefit of this solution, is it is possible to trace a module's function on unload and load. Link: http://lkml.kernel.org/r/20130705142629.GA325@redhat.com Reported-by: Jörn Engel Reported-by: Dave Jones Reported-by: Steve Hodgson Tested-by: Steve Hodgson Signed-off-by: Steven Rostedt --- kernel/trace/ftrace.c | 71 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 62 insertions(+), 9 deletions(-) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 92d3334de0c3..a6d098c6df3f 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -2169,12 +2169,57 @@ static cycle_t ftrace_update_time; static unsigned long ftrace_update_cnt; unsigned long ftrace_update_tot_cnt; -static int ops_traces_mod(struct ftrace_ops *ops) +static inline int ops_traces_mod(struct ftrace_ops *ops) { - struct ftrace_hash *hash; + /* + * Filter_hash being empty will default to trace module. + * But notrace hash requires a test of individual module functions. + */ + return ftrace_hash_empty(ops->filter_hash) && + ftrace_hash_empty(ops->notrace_hash); +} - hash = ops->filter_hash; - return ftrace_hash_empty(hash); +/* + * Check if the current ops references the record. + * + * If the ops traces all functions, then it was already accounted for. + * If the ops does not trace the current record function, skip it. + * If the ops ignores the function via notrace filter, skip it. + */ +static inline bool +ops_references_rec(struct ftrace_ops *ops, struct dyn_ftrace *rec) +{ + /* If ops isn't enabled, ignore it */ + if (!(ops->flags & FTRACE_OPS_FL_ENABLED)) + return 0; + + /* If ops traces all mods, we already accounted for it */ + if (ops_traces_mod(ops)) + return 0; + + /* The function must be in the filter */ + if (!ftrace_hash_empty(ops->filter_hash) && + !ftrace_lookup_ip(ops->filter_hash, rec->ip)) + return 0; + + /* If in notrace hash, we ignore it too */ + if (ftrace_lookup_ip(ops->notrace_hash, rec->ip)) + return 0; + + return 1; +} + +static int referenced_filters(struct dyn_ftrace *rec) +{ + struct ftrace_ops *ops; + int cnt = 0; + + for (ops = ftrace_ops_list; ops != &ftrace_list_end; ops = ops->next) { + if (ops_references_rec(ops, rec)) + cnt++; + } + + return cnt; } static int ftrace_update_code(struct module *mod) @@ -2183,6 +2228,7 @@ static int ftrace_update_code(struct module *mod) struct dyn_ftrace *p; cycle_t start, stop; unsigned long ref = 0; + bool test = false; int i; /* @@ -2196,9 +2242,12 @@ static int ftrace_update_code(struct module *mod) for (ops = ftrace_ops_list; ops != &ftrace_list_end; ops = ops->next) { - if (ops->flags & FTRACE_OPS_FL_ENABLED && - ops_traces_mod(ops)) - ref++; + if (ops->flags & FTRACE_OPS_FL_ENABLED) { + if (ops_traces_mod(ops)) + ref++; + else + test = true; + } } } @@ -2208,12 +2257,16 @@ static int ftrace_update_code(struct module *mod) for (pg = ftrace_new_pgs; pg; pg = pg->next) { for (i = 0; i < pg->index; i++) { + int cnt = ref; + /* If something went wrong, bail without enabling anything */ if (unlikely(ftrace_disabled)) return -1; p = &pg->records[i]; - p->flags = ref; + if (test) + cnt += referenced_filters(p); + p->flags = cnt; /* * Do the initial record conversion from mcount jump @@ -2233,7 +2286,7 @@ static int ftrace_update_code(struct module *mod) * conversion puts the module to the correct state, thus * passing the ftrace_make_call check. */ - if (ftrace_start_up && ref) { + if (ftrace_start_up && cnt) { int failed = __ftrace_replace_code(p, 1); if (failed) ftrace_bug(failed, p->ip); From 3c4d9276626c93477af0b0b9d46b4dcb37e2eed2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 23 Jul 2013 23:12:41 -0700 Subject: [PATCH 1124/3400] shdma: fixup sh_dmae_get_partial() calculation error sh_desc->hw.tcr is controlling real data size, and, register TCR is controlling data transfer count which was xmit_shifted value of hw.tcr. Current sh_dmae_get_partial() is calculating in different unit. This patch fixes it. This bug has been present since c014906a870ce70e009def0c9d170ccabeb0be63 ("dmaengine: shdma: extend .device_terminate_all() to record partial transfer"), which was added in 2.6.34-rc1. Cc: Vinod Koul Signed-off-by: Kuninori Morimoto Acked-by: Guennadi Liakhovetski Signed-off-by: Simon Horman --- drivers/dma/sh/shdma.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/dma/sh/shdma.c b/drivers/dma/sh/shdma.c index b67f45f5c271..5039fbc88254 100644 --- a/drivers/dma/sh/shdma.c +++ b/drivers/dma/sh/shdma.c @@ -400,8 +400,8 @@ static size_t sh_dmae_get_partial(struct shdma_chan *schan, shdma_chan); struct sh_dmae_desc *sh_desc = container_of(sdesc, struct sh_dmae_desc, shdma_desc); - return (sh_desc->hw.tcr - sh_dmae_readl(sh_chan, TCR)) << - sh_chan->xmit_shift; + return sh_desc->hw.tcr - + (sh_dmae_readl(sh_chan, TCR) << sh_chan->xmit_shift); } /* Called from error IRQ or NMI */ From fa3e0cee12fbdd9e0b03470b2b8cf968f537c161 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sat, 27 Jul 2013 03:46:33 +0400 Subject: [PATCH 1125/3400] ARM: shmobile: BOCK-W: fix SDHI0 PFC settings The following message is printed on the BOCK-W kernel bootup: sh-pfc pfc-r8a7778: invalid group "sdhi0" for function "sdhi0" In addition, SD card cannot be detected. The reason is apparently that commit ca7bb309485e4ec89a9addd47bea (ARM: shmobile: bockw: add SDHI0 support) matched the previous version of commit 564617d2f92473031d035deb273da5 (sh-pfc: r8a7778: add SDHI support). Add the missing pin groups according to the BOCK-W board schematics. Signed-off-by: Sergei Shtylyov Acked-by: Kuninori Morimoto Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/board-bockw.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-shmobile/board-bockw.c b/arch/arm/mach-shmobile/board-bockw.c index d5554646916c..3354a85c90f7 100644 --- a/arch/arm/mach-shmobile/board-bockw.c +++ b/arch/arm/mach-shmobile/board-bockw.c @@ -167,7 +167,13 @@ static const struct pinctrl_map bockw_pinctrl_map[] = { "usb1", "usb1"), /* SDHI0 */ PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7778", - "sdhi0", "sdhi0"), + "sdhi0_data4", "sdhi0"), + PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7778", + "sdhi0_ctrl", "sdhi0"), + PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7778", + "sdhi0_cd", "sdhi0"), + PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7778", + "sdhi0_wp", "sdhi0"), }; #define FPGA 0x18200000 From a601469386b543df2a4d97ad7d524716945278a3 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Fri, 26 Jul 2013 17:53:42 +0900 Subject: [PATCH 1126/3400] ARM: shmobile: lager: do not annotate gpio_buttons as __initdata When the gpio-keys device is registered using platform_device_register_data() the platform data argument, lager_keys_pdata is duplicated and thus should be marked as __initdata to avoid wasting memory. However, this is not true of gpio_buttons, a reference to it rather than its value is duplicated when lager_keys_pdata is duplicated. This avoids accessing freed memory if gpio-key events occur after unused kernel memory is freed late in the kernel's boot. This but was added when support for gpio-keys was added to lager in c3842e4fcbb7664276443b79187b7808c2e80a35 ("ARM: shmobile: lager: support GPIO switches") which was included in v3.11-rc1. Tested-by: Magnus Damm Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/board-lager.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-shmobile/board-lager.c b/arch/arm/mach-shmobile/board-lager.c index d73e21d3ea8a..8d6bd5c5efb9 100644 --- a/arch/arm/mach-shmobile/board-lager.c +++ b/arch/arm/mach-shmobile/board-lager.c @@ -59,7 +59,7 @@ static __initdata struct gpio_led_platform_data lager_leds_pdata = { #define GPIO_KEY(c, g, d, ...) \ { .code = c, .gpio = g, .desc = d, .active_low = 1 } -static __initdata struct gpio_keys_button gpio_buttons[] = { +static struct gpio_keys_button gpio_buttons[] = { GPIO_KEY(KEY_4, RCAR_GP_PIN(1, 28), "SW2-pin4"), GPIO_KEY(KEY_3, RCAR_GP_PIN(1, 26), "SW2-pin3"), GPIO_KEY(KEY_2, RCAR_GP_PIN(1, 24), "SW2-pin2"), From 057d6332b24a4497c55a761c83c823eed9e3f23b Mon Sep 17 00:00:00 2001 From: Chen Gang Date: Fri, 19 Jul 2013 09:01:36 +0800 Subject: [PATCH 1127/3400] cifs: extend the buffer length enought for sprintf() using For cifs_set_cifscreds() in "fs/cifs/connect.c", 'desc' buffer length is 'CIFSCREDS_DESC_SIZE' (56 is less than 256), and 'ses->domainName' length may be "255 + '\0'". The related sprintf() may cause memory overflow, so need extend related buffer enough to hold all things. It is also necessary to be sure of 'ses->domainName' must be less than 256, and define the related macro instead of hard code number '256'. Signed-off-by: Chen Gang Reviewed-by: Jeff Layton Reviewed-by: Shirish Pargaonkar Reviewed-by: Scott Lovenberg CC: Signed-off-by: Steve French --- fs/cifs/cifsencrypt.c | 2 +- fs/cifs/cifsglob.h | 1 + fs/cifs/connect.c | 7 ++++--- fs/cifs/sess.c | 6 +++--- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index 45e57cc38200..194f9cce5d83 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c @@ -421,7 +421,7 @@ find_domain_name(struct cifs_ses *ses, const struct nls_table *nls_cp) if (blobptr + attrsize > blobend) break; if (type == NTLMSSP_AV_NB_DOMAIN_NAME) { - if (!attrsize) + if (!attrsize || attrsize >= CIFS_MAX_DOMAINNAME_LEN) break; if (!ses->domainName) { ses->domainName = diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 1fdc37041057..0e68893f26f3 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -44,6 +44,7 @@ #define MAX_TREE_SIZE (2 + MAX_SERVER_SIZE + 1 + MAX_SHARE_SIZE + 1) #define MAX_SERVER_SIZE 15 #define MAX_SHARE_SIZE 80 +#define CIFS_MAX_DOMAINNAME_LEN 256 /* max domain name length */ #define MAX_USERNAME_SIZE 256 /* reasonable maximum for current servers */ #define MAX_PASSWORD_SIZE 512 /* max for windows seems to be 256 wide chars */ diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index fa68813396b5..d67c550c4980 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1675,7 +1675,8 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, if (string == NULL) goto out_nomem; - if (strnlen(string, 256) == 256) { + if (strnlen(string, CIFS_MAX_DOMAINNAME_LEN) + == CIFS_MAX_DOMAINNAME_LEN) { printk(KERN_WARNING "CIFS: domain name too" " long\n"); goto cifs_parse_mount_err; @@ -2276,8 +2277,8 @@ cifs_put_smb_ses(struct cifs_ses *ses) #ifdef CONFIG_KEYS -/* strlen("cifs:a:") + INET6_ADDRSTRLEN + 1 */ -#define CIFSCREDS_DESC_SIZE (7 + INET6_ADDRSTRLEN + 1) +/* strlen("cifs:a:") + CIFS_MAX_DOMAINNAME_LEN + 1 */ +#define CIFSCREDS_DESC_SIZE (7 + CIFS_MAX_DOMAINNAME_LEN + 1) /* Populate username and pw fields from keyring if possible */ static int diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 79358e341fd2..08dd37bb23aa 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c @@ -197,7 +197,7 @@ static void unicode_domain_string(char **pbcc_area, struct cifs_ses *ses, bytes_ret = 0; } else bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, ses->domainName, - 256, nls_cp); + CIFS_MAX_DOMAINNAME_LEN, nls_cp); bcc_ptr += 2 * bytes_ret; bcc_ptr += 2; /* account for null terminator */ @@ -255,8 +255,8 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifs_ses *ses, /* copy domain */ if (ses->domainName != NULL) { - strncpy(bcc_ptr, ses->domainName, 256); - bcc_ptr += strnlen(ses->domainName, 256); + strncpy(bcc_ptr, ses->domainName, CIFS_MAX_DOMAINNAME_LEN); + bcc_ptr += strnlen(ses->domainName, CIFS_MAX_DOMAINNAME_LEN); } /* else we will send a null domain name so the server will default to its own domain */ *bcc_ptr = 0; From 1b244081af462c223cfa6a1ae881a902af64c306 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 11 Jul 2013 19:17:40 -0500 Subject: [PATCH 1128/3400] Do not attempt to do cifs operations reading symlinks with SMB2 When use of symlinks is enabled (mounting with mfsymlinks option) to non-Samba servers, we always tried to use cifs, even when we were mounted with SMB2 or SMB3, which causes the server to drop the network connection. This patch separates out the protocol specific operations for cifs from the code which recognizes symlinks, and fixes the problem where with SMB2 mounts we attempt cifs operations to open and read symlinks. The next patch will add support for SMB2 for opening and reading symlinks. Additional followon patches will address the similar problem creating symlinks. Signed-off-by: Steve French --- fs/cifs/cifsglob.h | 3 ++ fs/cifs/cifsproto.h | 4 ++- fs/cifs/link.c | 84 ++++++++++++++++++++++++++++----------------- fs/cifs/smb1ops.c | 1 + 4 files changed, 60 insertions(+), 32 deletions(-) diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 0e68893f26f3..52ca861ed35e 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -370,6 +370,9 @@ struct smb_version_operations { void (*generate_signingkey)(struct TCP_Server_Info *server); int (*calc_signature)(struct smb_rqst *rqst, struct TCP_Server_Info *server); + int (*query_mf_symlink)(const unsigned char *path, char *pbuf, + unsigned int *pbytes_read, struct cifs_sb_info *cifs_sb, + unsigned int xid); }; struct smb_version_values { diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index f7e584d047e2..b29a012bed33 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -497,5 +497,7 @@ void cifs_writev_complete(struct work_struct *work); struct cifs_writedata *cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete); void cifs_writedata_release(struct kref *refcount); - +int open_query_close_cifs_symlink(const unsigned char *path, char *pbuf, + unsigned int *pbytes_read, struct cifs_sb_info *cifs_sb, + unsigned int xid); #endif /* _CIFSPROTO_H */ diff --git a/fs/cifs/link.c b/fs/cifs/link.c index b83c3f5646bd..562044f700e5 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -305,67 +305,89 @@ CIFSCouldBeMFSymlink(const struct cifs_fattr *fattr) } int -CIFSCheckMFSymlink(struct cifs_fattr *fattr, - const unsigned char *path, - struct cifs_sb_info *cifs_sb, unsigned int xid) +open_query_close_cifs_symlink(const unsigned char *path, char *pbuf, + unsigned int *pbytes_read, struct cifs_sb_info *cifs_sb, + unsigned int xid) { int rc; int oplock = 0; __u16 netfid = 0; struct tcon_link *tlink; - struct cifs_tcon *pTcon; + struct cifs_tcon *ptcon; struct cifs_io_parms io_parms; - u8 *buf; - char *pbuf; - unsigned int bytes_read = 0; int buf_type = CIFS_NO_BUFFER; - unsigned int link_len = 0; FILE_ALL_INFO file_info; - if (!CIFSCouldBeMFSymlink(fattr)) - /* it's not a symlink */ - return 0; - tlink = cifs_sb_tlink(cifs_sb); if (IS_ERR(tlink)) return PTR_ERR(tlink); - pTcon = tlink_tcon(tlink); + ptcon = tlink_tcon(tlink); - rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ, + rc = CIFSSMBOpen(xid, ptcon, path, FILE_OPEN, GENERIC_READ, CREATE_NOT_DIR, &netfid, &oplock, &file_info, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - if (rc != 0) - goto out; + if (rc != 0) { + cifs_put_tlink(tlink); + return rc; + } if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) { - CIFSSMBClose(xid, pTcon, netfid); + CIFSSMBClose(xid, ptcon, netfid); + cifs_put_tlink(tlink); /* it's not a symlink */ - goto out; + return rc; } + io_parms.netfid = netfid; + io_parms.pid = current->tgid; + io_parms.tcon = ptcon; + io_parms.offset = 0; + io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE; + + rc = CIFSSMBRead(xid, &io_parms, pbytes_read, &pbuf, &buf_type); + CIFSSMBClose(xid, ptcon, netfid); + cifs_put_tlink(tlink); + return rc; +} + + +int +CIFSCheckMFSymlink(struct cifs_fattr *fattr, + const unsigned char *path, + struct cifs_sb_info *cifs_sb, unsigned int xid) +{ + int rc = 0; + u8 *buf = NULL; + unsigned int link_len = 0; + unsigned int bytes_read = 0; + struct cifs_tcon *ptcon; + + if (!CIFSCouldBeMFSymlink(fattr)) + /* it's not a symlink */ + return 0; + buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL); if (!buf) { rc = -ENOMEM; goto out; } - pbuf = buf; - io_parms.netfid = netfid; - io_parms.pid = current->tgid; - io_parms.tcon = pTcon; - io_parms.offset = 0; - io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE; - rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf, &buf_type); - CIFSSMBClose(xid, pTcon, netfid); - if (rc != 0) { - kfree(buf); + ptcon = tlink_tcon(cifs_sb_tlink(cifs_sb)); + if ((ptcon->ses) && (ptcon->ses->server->ops->query_mf_symlink)) + rc = ptcon->ses->server->ops->query_mf_symlink(path, buf, + &bytes_read, cifs_sb, xid); + else + goto out; + + if (rc != 0) + goto out; + + if (bytes_read == 0) /* not a symlink */ goto out; - } rc = CIFSParseMFSymlink(buf, bytes_read, &link_len, NULL); - kfree(buf); if (rc == -EINVAL) { /* it's not a symlink */ rc = 0; @@ -381,7 +403,7 @@ CIFSCheckMFSymlink(struct cifs_fattr *fattr, fattr->cf_mode |= S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO; fattr->cf_dtype = DT_LNK; out: - cifs_put_tlink(tlink); + kfree(buf); return rc; } diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c index 6457690731a2..60943978aec3 100644 --- a/fs/cifs/smb1ops.c +++ b/fs/cifs/smb1ops.c @@ -944,6 +944,7 @@ struct smb_version_operations smb1_operations = { .mand_lock = cifs_mand_lock, .mand_unlock_range = cifs_unlock_range, .push_mand_locks = cifs_push_mandatory_locks, + .query_mf_symlink = open_query_close_cifs_symlink, }; struct smb_version_values smb1_values = { From fe090e4e44bac1d7d8c0ebd1dfa4e6007e1b2762 Mon Sep 17 00:00:00 2001 From: Andi Shyti Date: Mon, 29 Jul 2013 20:04:35 +0200 Subject: [PATCH 1129/3400] cifs: file: initialize oparms.reconnect before using it In the cifs_reopen_file function, if the following statement is asserted: (tcon->unix_ext && cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP & (tcon->fsUnixInfo.Capability))) and we succeed to open with cifs_posix_open, the function jumps to the label reopen_success and checks for oparms.reconnect which is not initialized. This issue has been reported by scan.coverity.com Signed-off-by: Andi Shyti Reviewed-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/file.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 1e57f36ea1b2..7e36ae34e947 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -647,6 +647,7 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush) oflags, &oplock, &cfile->fid.netfid, xid); if (rc == 0) { cifs_dbg(FYI, "posix reopen succeeded\n"); + oparms.reconnect = true; goto reopen_success; } /* From 9186a1fd9ed190739423db84bc344d258ef3e3d7 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Fri, 26 Jul 2013 15:29:09 +0200 Subject: [PATCH 1130/3400] iwlwifi: dvm: fix calling ieee80211_chswitch_done() with NULL If channel switch is pending and we remove interface we can crash like showed below due to passing NULL vif to mac80211: BUG: unable to handle kernel paging request at fffffffffffff8cc IP: [] strnlen+0xd/0x40 Call Trace: [] string.isra.3+0x3e/0xd0 [] vsnprintf+0x219/0x640 [] vscnprintf+0x11/0x30 [] vprintk_emit+0x115/0x4f0 [] printk+0x61/0x63 [] ieee80211_chswitch_done+0xaf/0xd0 [mac80211] [] iwl_chswitch_done+0x34/0x40 [iwldvm] [] iwlagn_commit_rxon+0x2a3/0xdc0 [iwldvm] [] ? iwlagn_set_rxon_chain+0x180/0x2c0 [iwldvm] [] iwl_set_mode+0x36/0x40 [iwldvm] [] iwlagn_mac_remove_interface+0x8d/0x1b0 [iwldvm] [] ieee80211_do_stop+0x29d/0x7f0 [mac80211] This is because we nulify ctx->vif in iwlagn_mac_remove_interface() before calling some other functions that teardown interface. To fix just check ctx->vif on iwl_chswitch_done(). We should not call ieee80211_chswitch_done() as channel switch works were already canceled by mac80211 in ieee80211_do_stop() -> ieee80211_mgd_stop(). Resolve: https://bugzilla.redhat.com/show_bug.cgi?id=979581 Cc: stable@vger.kernel.org Reported-by: Lukasz Jagiello Signed-off-by: Stanislaw Gruszka Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/dvm/mac80211.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index 822f1a00efbb..319387263e12 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c @@ -1068,7 +1068,10 @@ void iwl_chswitch_done(struct iwl_priv *priv, bool is_success) if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; - if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status)) + if (!test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status)) + return; + + if (ctx->vif) ieee80211_chswitch_done(ctx->vif, is_success); } From eabc4ac5d7606a57ee2b7308cb7323ea8f60183b Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 29 Jul 2013 23:05:18 +0300 Subject: [PATCH 1131/3400] iwlwifi: pcie: disable L1 Active after pci_enable_device As Arjan pointed out, we mustn't do anything related to PCI configuration until the device is properly enabled with pci_enable_device(). Cc: stable@vger.kernel.org Reported-by: Arjan van de Ven Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/pcie/trans.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index 96cfcdd39079..390e2f058aff 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c @@ -1502,16 +1502,16 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, spin_lock_init(&trans_pcie->reg_lock); init_waitqueue_head(&trans_pcie->ucode_write_waitq); - /* W/A - seems to solve weird behavior. We need to remove this if we - * don't want to stay in L1 all the time. This wastes a lot of power */ - pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | - PCIE_LINK_STATE_CLKPM); - if (pci_enable_device(pdev)) { err = -ENODEV; goto out_no_pci; } + /* W/A - seems to solve weird behavior. We need to remove this if we + * don't want to stay in L1 all the time. This wastes a lot of power */ + pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | + PCIE_LINK_STATE_CLKPM); + pci_set_master(pdev); err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36)); From 4bdfb2729c3a396fe7400c9332c49aee2b971bd8 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 29 Jul 2013 21:00:53 +0100 Subject: [PATCH 1132/3400] regulator: core: Add missing stub for regulator_get_exclusive() Signed-off-by: Mark Brown --- include/linux/regulator/consumer.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index 3a76389c6aaa..60da4a62c402 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h @@ -211,6 +211,13 @@ static inline struct regulator *__must_check regulator_get(struct device *dev, return NULL; } +static inline struct regulator *__must_check +regulator_get_exclusive(struct device *dev, const char *id) +{ + return NULL; +} + + static inline struct regulator *__must_check devm_regulator_get(struct device *dev, const char *id) { From de1dd9fd2156874b45803299b3b27e65d5defdd9 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 29 Jul 2013 21:42:42 +0100 Subject: [PATCH 1133/3400] regulator: core: Provide hints to the core about optional supplies While the majority of supplies on devices are mandatory and can't be physically omitted for electrical reasons some devices do have optional supplies and need to know if they are missing, MMC being the most common of these. Currently the core accurately reports all errors when regulators are requested since it does not know if the supply is one that must be provided even if by a regulator software does not know about or if it is one that may genuinely be disconnected. In order to allow this behaviour to be changed and stub regulators to be provided in the former case add a new regulator request function regulator_get_optional() which provides a hint to the core that the regulator may genuinely not be connected. Currently the implementation is identical to the current behaviour, future patches will add support in the core for returning stub regulators in the case where normal regulator_get() fails and the board has requested it. Signed-off-by: Mark Brown Acked-by: Chris Ball --- drivers/regulator/core.c | 59 ++++++++++++++++++++++++++++++ include/linux/regulator/consumer.h | 18 ++++++++- 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 288c75abc190..a27a5b6267dd 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1409,6 +1409,65 @@ struct regulator *regulator_get_exclusive(struct device *dev, const char *id) } EXPORT_SYMBOL_GPL(regulator_get_exclusive); +/** + * regulator_get_optional - obtain optional access to a regulator. + * @dev: device for regulator "consumer" + * @id: Supply name or regulator ID. + * + * Returns a struct regulator corresponding to the regulator producer, + * or IS_ERR() condition containing errno. Other consumers will be + * unable to obtain this reference is held and the use count for the + * regulator will be initialised to reflect the current state of the + * regulator. + * + * This is intended for use by consumers for devices which can have + * some supplies unconnected in normal use, such as some MMC devices. + * It can allow the regulator core to provide stub supplies for other + * supplies requested using normal regulator_get() calls without + * disrupting the operation of drivers that can handle absent + * supplies. + * + * Use of supply names configured via regulator_set_device_supply() is + * strongly encouraged. It is recommended that the supply name used + * should match the name used for the supply and/or the relevant + * device pins in the datasheet. + */ +struct regulator *regulator_get_optional(struct device *dev, const char *id) +{ + return _regulator_get(dev, id, 0); +} +EXPORT_SYMBOL_GPL(regulator_get_optional); + +/** + * devm_regulator_get_optional - Resource managed regulator_get_optional() + * @dev: device for regulator "consumer" + * @id: Supply name or regulator ID. + * + * Managed regulator_get_optional(). Regulators returned from this + * function are automatically regulator_put() on driver detach. See + * regulator_get_optional() for more information. + */ +struct regulator *devm_regulator_get_optional(struct device *dev, + const char *id) +{ + struct regulator **ptr, *regulator; + + ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return ERR_PTR(-ENOMEM); + + regulator = regulator_get_optional(dev, id); + if (!IS_ERR(regulator)) { + *ptr = regulator; + devres_add(dev, ptr); + } else { + devres_free(ptr); + } + + return regulator; +} +EXPORT_SYMBOL_GPL(devm_regulator_get_optional); + /* Locks held by regulator_put() */ static void _regulator_put(struct regulator *regulator) { diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index 60da4a62c402..e2bac6db4abc 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h @@ -137,6 +137,10 @@ struct regulator *__must_check devm_regulator_get(struct device *dev, const char *id); struct regulator *__must_check regulator_get_exclusive(struct device *dev, const char *id); +struct regulator *__must_check regulator_get_optional(struct device *dev, + const char *id); +struct regulator *__must_check devm_regulator_get_optional(struct device *dev, + const char *id); void regulator_put(struct regulator *regulator); void devm_regulator_put(struct regulator *regulator); @@ -211,15 +215,27 @@ static inline struct regulator *__must_check regulator_get(struct device *dev, return NULL; } +static inline struct regulator *__must_check +devm_regulator_get(struct device *dev, const char *id) +{ + return NULL; +} + static inline struct regulator *__must_check regulator_get_exclusive(struct device *dev, const char *id) { return NULL; } +static inline struct regulator *__must_check +regulator_get_optional(struct device *dev, const char *id) +{ + return NULL; +} + static inline struct regulator *__must_check -devm_regulator_get(struct device *dev, const char *id) +devm_regulator_get_optional(struct device *dev, const char *id) { return NULL; } From bc35d5ed5d14e63a4d6018098a129196ba4c44ae Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 29 Jul 2013 21:58:01 +0100 Subject: [PATCH 1134/3400] mmc: core: Indicate that vmmcq may be absent Use regulator_get_optional() to tell the core that requests for the vmmcq regulator can fail in a real system. Signed-off-by: Mark Brown Acked-by: Chris Ball --- drivers/mmc/core/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 49a5bca418bd..5d088551196b 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1313,7 +1313,7 @@ int mmc_regulator_get_supply(struct mmc_host *mmc) supply = devm_regulator_get(dev, "vmmc"); mmc->supply.vmmc = supply; - mmc->supply.vqmmc = devm_regulator_get(dev, "vqmmc"); + mmc->supply.vqmmc = devm_regulator_get_optional(dev, "vqmmc"); if (IS_ERR(supply)) return PTR_ERR(supply); From 462849aad50fced728d82a2ddba1b9d348e32f67 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 29 Jul 2013 21:52:55 +0100 Subject: [PATCH 1135/3400] mmc: sdhci: Indicate that regulators may be absent Use regulator_get_optional() to tell the core that requests for regulators can fail in a real system. Signed-off-by: Mark Brown Acked-by: Chris Ball --- drivers/mmc/host/sdhci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index a78bd4f3aecc..dd2c083c434d 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2966,7 +2966,7 @@ int sdhci_add_host(struct sdhci_host *host) mmc->caps |= MMC_CAP_NEEDS_POLL; /* If vqmmc regulator and no 1.8V signalling, then there's no UHS */ - host->vqmmc = regulator_get(mmc_dev(mmc), "vqmmc"); + host->vqmmc = regulator_get_optional(mmc_dev(mmc), "vqmmc"); if (IS_ERR_OR_NULL(host->vqmmc)) { if (PTR_ERR(host->vqmmc) < 0) { pr_info("%s: no vqmmc regulator found\n", @@ -3042,7 +3042,7 @@ int sdhci_add_host(struct sdhci_host *host) ocr_avail = 0; - host->vmmc = regulator_get(mmc_dev(mmc), "vmmc"); + host->vmmc = regulator_get_optional(mmc_dev(mmc), "vmmc"); if (IS_ERR_OR_NULL(host->vmmc)) { if (PTR_ERR(host->vmmc) < 0) { pr_info("%s: no vmmc regulator found\n", From a55d6ff0ed169fe2cf4bcdd81049c3c2041a7465 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 29 Jul 2013 21:55:27 +0100 Subject: [PATCH 1136/3400] mmc: dw_mmc: Indicate that regulators may be absent Use regulator_get_optional() to tell the core that requests for regulators can fail in a real system. Signed-off-by: Mark Brown Acked-by: Chris Ball Acked-by: Seungwon Jeon Acked-by: Jaehoon Chung --- drivers/mmc/host/dw_mmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index ee5f1676f14e..542407363dd2 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -2231,7 +2231,7 @@ int dw_mci_probe(struct dw_mci *host) } } - host->vmmc = devm_regulator_get(host->dev, "vmmc"); + host->vmmc = devm_regulator_get_optional(host->dev, "vmmc"); if (IS_ERR(host->vmmc)) { ret = PTR_ERR(host->vmmc); if (ret == -EPROBE_DEFER) From 6ae8717a4897d776097c5c2578a907d3c59b1e9f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 29 Jul 2013 21:55:40 +0100 Subject: [PATCH 1137/3400] mmc: pxamci: Indicate that regulators may be absent Use regulator_get_optional() to tell the core that requests for regulators can fail in a real system. Signed-off-by: Mark Brown Acked-by: Chris Ball --- drivers/mmc/host/pxamci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index 2c5a91bb8ec3..1956a3df7cf3 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c @@ -83,7 +83,7 @@ struct pxamci_host { static inline void pxamci_init_ocr(struct pxamci_host *host) { #ifdef CONFIG_REGULATOR - host->vcc = regulator_get(mmc_dev(host->mmc), "vmmc"); + host->vcc = regulator_get_optional(mmc_dev(host->mmc), "vmmc"); if (IS_ERR(host->vcc)) host->vcc = NULL; From da0a12caffad2eeadea429f83818408e7b77379a Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Wed, 31 Jul 2013 16:16:28 +0800 Subject: [PATCH 1138/3400] cgroup: fix a leak when percpu_ref_init() fails ss->css_free() is not called when perfcpu_ref_init() fails. Signed-off-by: Li Zefan Signed-off-by: Tejun Heo --- kernel/cgroup.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index afb8d53ca6c7..468e410f9e61 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -4344,8 +4344,10 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry, } err = percpu_ref_init(&css->refcnt, css_release); - if (err) + if (err) { + ss->css_free(cgrp); goto err_free_all; + } init_cgroup_css(css, ss, cgrp); From 2a4ac63333584b2791986cf2270f5ba9a4b97606 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Wed, 31 Jul 2013 16:16:40 +0800 Subject: [PATCH 1139/3400] cgroup: remove sparse tags from offline_css() This should have been removed in commit d7eeac1913ff ("cgroup: hold cgroup_mutex before calling css_offline"). While at it, update the comments. Signed-off-by: Li Zefan Signed-off-by: Tejun Heo --- kernel/cgroup.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 345fac8e4fba..41b559f51502 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -4214,7 +4214,7 @@ static void init_cgroup_css(struct cgroup_subsys_state *css, INIT_WORK(&css->dput_work, css_dput_fn); } -/* invoke ->post_create() on a new CSS and mark it online if successful */ +/* invoke ->css_online() on a new CSS and mark it online if successful */ static int online_css(struct cgroup_subsys *ss, struct cgroup *cgrp) { int ret = 0; @@ -4228,9 +4228,8 @@ static int online_css(struct cgroup_subsys *ss, struct cgroup *cgrp) return ret; } -/* if the CSS is online, invoke ->pre_destory() on it and mark it offline */ +/* if the CSS is online, invoke ->css_offline() on it and mark it offline */ static void offline_css(struct cgroup_subsys *ss, struct cgroup *cgrp) - __releases(&cgroup_mutex) __acquires(&cgroup_mutex) { struct cgroup_subsys_state *css = cgrp->subsys[ss->subsys_id]; From e0798ce27346edb8aa369b5b39af5a47fdf2b25c Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Wed, 31 Jul 2013 17:36:25 +0800 Subject: [PATCH 1140/3400] cgroup: remove struct cgroup_seqfile_state We can use struct cfent instead. v2: - remove cgroup_seqfile_release(). Signed-off-by: Li Zefan Signed-off-by: Tejun Heo --- kernel/cgroup.c | 45 +++++++++++++-------------------------------- 1 file changed, 13 insertions(+), 32 deletions(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 41b559f51502..ed2104304833 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -2397,11 +2397,6 @@ static ssize_t cgroup_file_read(struct file *file, char __user *buf, * supports string->u64 maps, but can be extended in future. */ -struct cgroup_seqfile_state { - struct cftype *cft; - struct cgroup *cgroup; -}; - static int cgroup_map_add(struct cgroup_map_cb *cb, const char *key, u64 value) { struct seq_file *sf = cb->state; @@ -2410,59 +2405,45 @@ static int cgroup_map_add(struct cgroup_map_cb *cb, const char *key, u64 value) static int cgroup_seqfile_show(struct seq_file *m, void *arg) { - struct cgroup_seqfile_state *state = m->private; - struct cftype *cft = state->cft; + struct cfent *cfe = m->private; + struct cftype *cft = cfe->type; + struct cgroup *cgrp = __d_cgrp(cfe->dentry->d_parent); + if (cft->read_map) { struct cgroup_map_cb cb = { .fill = cgroup_map_add, .state = m, }; - return cft->read_map(state->cgroup, cft, &cb); + return cft->read_map(cgrp, cft, &cb); } - return cft->read_seq_string(state->cgroup, cft, m); -} - -static int cgroup_seqfile_release(struct inode *inode, struct file *file) -{ - struct seq_file *seq = file->private_data; - kfree(seq->private); - return single_release(inode, file); + return cft->read_seq_string(cgrp, cft, m); } static const struct file_operations cgroup_seqfile_operations = { .read = seq_read, .write = cgroup_file_write, .llseek = seq_lseek, - .release = cgroup_seqfile_release, + .release = single_release, }; static int cgroup_file_open(struct inode *inode, struct file *file) { int err; + struct cfent *cfe; struct cftype *cft; err = generic_file_open(inode, file); if (err) return err; - cft = __d_cft(file->f_dentry); + cfe = __d_cfe(file->f_dentry); + cft = cfe->type; if (cft->read_map || cft->read_seq_string) { - struct cgroup_seqfile_state *state; - - state = kzalloc(sizeof(*state), GFP_USER); - if (!state) - return -ENOMEM; - - state->cft = cft; - state->cgroup = __d_cgrp(file->f_dentry->d_parent); file->f_op = &cgroup_seqfile_operations; - err = single_open(file, cgroup_seqfile_show, state); - if (err < 0) - kfree(state); - } else if (cft->open) + err = single_open(file, cgroup_seqfile_show, cfe); + } else if (cft->open) { err = cft->open(inode, file); - else - err = 0; + } return err; } From 6f4b7e632d78c2d91502211c430722cc66428492 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Wed, 31 Jul 2013 16:18:36 +0800 Subject: [PATCH 1141/3400] cgroup: more naming cleanups Constantly use @cset for css_set variables and use @cgrp as cgroup variables. Signed-off-by: Li Zefan Signed-off-by: Tejun Heo --- include/linux/cgroup.h | 6 +++--- kernel/cgroup.c | 26 +++++++++++++------------- kernel/cpuset.c | 16 ++++++++-------- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index 297462b9f41a..00a7e07a1567 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h @@ -394,8 +394,8 @@ struct cgroup_map_cb { /* cftype->flags */ enum { - CFTYPE_ONLY_ON_ROOT = (1 << 0), /* only create on root cg */ - CFTYPE_NOT_ON_ROOT = (1 << 1), /* don't create on root cg */ + CFTYPE_ONLY_ON_ROOT = (1 << 0), /* only create on root cgrp */ + CFTYPE_NOT_ON_ROOT = (1 << 1), /* don't create on root cgrp */ CFTYPE_INSANE = (1 << 2), /* don't create if sane_behavior */ }; @@ -513,7 +513,7 @@ struct cftype_set { }; struct cgroup_scanner { - struct cgroup *cg; + struct cgroup *cgrp; int (*test_task)(struct task_struct *p, struct cgroup_scanner *scan); void (*process_task)(struct task_struct *p, struct cgroup_scanner *scan); diff --git a/kernel/cgroup.c b/kernel/cgroup.c index ed2104304833..9577bebe2546 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -466,7 +466,7 @@ static inline void put_css_set_taskexit(struct css_set *cset) * @new_cgrp: cgroup that's being entered by the task * @template: desired set of css pointers in css_set (pre-calculated) * - * Returns true if "cg" matches "old_cg" except for the hierarchy + * Returns true if "cset" matches "old_cset" except for the hierarchy * which "new_cgrp" belongs to, for which it should match "new_cgrp". */ static bool compare_css_sets(struct css_set *cset, @@ -1839,7 +1839,7 @@ EXPORT_SYMBOL_GPL(task_cgroup_path_from_hierarchy); struct task_and_cgroup { struct task_struct *task; struct cgroup *cgrp; - struct css_set *cg; + struct css_set *cset; }; struct cgroup_taskset { @@ -2057,8 +2057,8 @@ static int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk, tc = flex_array_get(group, i); old_cset = task_css_set(tc->task); - tc->cg = find_css_set(old_cset, cgrp); - if (!tc->cg) { + tc->cset = find_css_set(old_cset, cgrp); + if (!tc->cset) { retval = -ENOMEM; goto out_put_css_set_refs; } @@ -2071,7 +2071,7 @@ static int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk, */ for (i = 0; i < group_size; i++) { tc = flex_array_get(group, i); - cgroup_task_migrate(tc->cgrp, tc->task, tc->cg); + cgroup_task_migrate(tc->cgrp, tc->task, tc->cset); } /* nothing is sensitive to fork() after this point. */ @@ -2091,9 +2091,9 @@ out_put_css_set_refs: if (retval) { for (i = 0; i < group_size; i++) { tc = flex_array_get(group, i); - if (!tc->cg) + if (!tc->cset) break; - put_css_set(tc->cg); + put_css_set(tc->cset); } } out_cancel_attach: @@ -2203,9 +2203,9 @@ int cgroup_attach_task_all(struct task_struct *from, struct task_struct *tsk) mutex_lock(&cgroup_mutex); for_each_active_root(root) { - struct cgroup *from_cg = task_cgroup_from_root(from, root); + struct cgroup *from_cgrp = task_cgroup_from_root(from, root); - retval = cgroup_attach_task(from_cg, tsk, false); + retval = cgroup_attach_task(from_cgrp, tsk, false); if (retval) break; } @@ -3305,8 +3305,8 @@ int cgroup_scan_tasks(struct cgroup_scanner *scan) * guarantees forward progress and that we don't miss any tasks. */ heap->size = 0; - cgroup_iter_start(scan->cg, &it); - while ((p = cgroup_iter_next(scan->cg, &it))) { + cgroup_iter_start(scan->cgrp, &it); + while ((p = cgroup_iter_next(scan->cgrp, &it))) { /* * Only affect tasks that qualify per the caller's callback, * if he provided one @@ -3339,7 +3339,7 @@ int cgroup_scan_tasks(struct cgroup_scanner *scan) * the heap and wasn't inserted */ } - cgroup_iter_end(scan->cg, &it); + cgroup_iter_end(scan->cgrp, &it); if (heap->size) { for (i = 0; i < heap->size; i++) { @@ -3385,7 +3385,7 @@ int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from) { struct cgroup_scanner scan; - scan.cg = from; + scan.cgrp = from; scan.test_task = NULL; /* select all tasks in cgroup */ scan.process_task = cgroup_transfer_one_task; scan.heap = NULL; diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 703bfd5a32a9..1b9c31549797 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -845,7 +845,7 @@ static void cpuset_change_cpumask(struct task_struct *tsk, { struct cpuset *cpus_cs; - cpus_cs = effective_cpumask_cpuset(cgroup_cs(scan->cg)); + cpus_cs = effective_cpumask_cpuset(cgroup_cs(scan->cgrp)); set_cpus_allowed_ptr(tsk, cpus_cs->cpus_allowed); } @@ -866,7 +866,7 @@ static void update_tasks_cpumask(struct cpuset *cs, struct ptr_heap *heap) { struct cgroup_scanner scan; - scan.cg = cs->css.cgroup; + scan.cgrp = cs->css.cgroup; scan.test_task = NULL; scan.process_task = cpuset_change_cpumask; scan.heap = heap; @@ -1062,7 +1062,7 @@ static void cpuset_change_task_nodemask(struct task_struct *tsk, static void cpuset_change_nodemask(struct task_struct *p, struct cgroup_scanner *scan) { - struct cpuset *cs = cgroup_cs(scan->cg); + struct cpuset *cs = cgroup_cs(scan->cgrp); struct mm_struct *mm; int migrate; nodemask_t *newmems = scan->data; @@ -1102,7 +1102,7 @@ static void update_tasks_nodemask(struct cpuset *cs, struct ptr_heap *heap) guarantee_online_mems(mems_cs, &newmems); - scan.cg = cs->css.cgroup; + scan.cgrp = cs->css.cgroup; scan.test_task = NULL; scan.process_task = cpuset_change_nodemask; scan.heap = heap; @@ -1275,7 +1275,7 @@ static int update_relax_domain_level(struct cpuset *cs, s64 val) static void cpuset_change_flag(struct task_struct *tsk, struct cgroup_scanner *scan) { - cpuset_update_task_spread_flag(cgroup_cs(scan->cg), tsk); + cpuset_update_task_spread_flag(cgroup_cs(scan->cgrp), tsk); } /* @@ -1295,7 +1295,7 @@ static void update_tasks_flags(struct cpuset *cs, struct ptr_heap *heap) { struct cgroup_scanner scan; - scan.cg = cs->css.cgroup; + scan.cgrp = cs->css.cgroup; scan.test_task = NULL; scan.process_task = cpuset_change_flag; scan.heap = heap; @@ -1971,7 +1971,7 @@ static int cpuset_css_online(struct cgroup *cgrp) struct cpuset *cs = cgroup_cs(cgrp); struct cpuset *parent = parent_cs(cs); struct cpuset *tmp_cs; - struct cgroup *pos_cg; + struct cgroup *pos_cgrp; if (!parent) return 0; @@ -2003,7 +2003,7 @@ static int cpuset_css_online(struct cgroup *cgrp) * (and likewise for mems) to the new cgroup. */ rcu_read_lock(); - cpuset_for_each_child(tmp_cs, pos_cg, parent) { + cpuset_for_each_child(tmp_cs, pos_cgrp, parent) { if (is_mem_exclusive(tmp_cs) || is_cpu_exclusive(tmp_cs)) { rcu_read_unlock(); goto out_unlock; From 4e96ee8e981b5140a2bcc5fff0d5c0eef39a62ee Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Wed, 31 Jul 2013 09:50:50 +0800 Subject: [PATCH 1142/3400] cgroup: convert cgroup_ida to cgroup_idr This enables us to lookup a cgroup by its id. v4: - add a comment for idr_remove() in cgroup_offline_fn(). v3: - on success, idr_alloc() returns the id but not 0, so fix the BUG_ON() in cgroup_init(). - pass the right value to idr_alloc() so that the id for dummy cgroup is 0. Signed-off-by: Li Zefan Reviewed-by: Michal Hocko Signed-off-by: Tejun Heo --- include/linux/cgroup.h | 4 ++-- kernel/cgroup.c | 33 +++++++++++++++++++++++++++------ 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index 00a7e07a1567..cca570e188fb 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h @@ -161,7 +161,7 @@ struct cgroup_name { struct cgroup { unsigned long flags; /* "unsigned long" so bitops work */ - int id; /* ida allocated in-hierarchy ID */ + int id; /* idr allocated in-hierarchy ID */ /* * We link our 'sibling' struct into our parent's 'children'. @@ -322,7 +322,7 @@ struct cgroupfs_root { unsigned long flags; /* IDs for cgroups in this hierarchy */ - struct ida cgroup_ida; + struct idr cgroup_idr; /* The path to use for release notifications. */ char release_agent_path[PATH_MAX]; diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 9577bebe2546..3f6593333525 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -866,8 +866,6 @@ static void cgroup_free_fn(struct work_struct *work) */ dput(cgrp->parent->dentry); - ida_simple_remove(&cgrp->root->cgroup_ida, cgrp->id); - /* * Drop the active superblock reference that we took when we * created the cgroup. This will free cgrp->root, if we are @@ -1379,6 +1377,7 @@ static void init_cgroup_root(struct cgroupfs_root *root) cgrp->root = root; RCU_INIT_POINTER(cgrp->name, &root_cgroup_name); init_cgroup_housekeeping(cgrp); + idr_init(&root->cgroup_idr); } static int cgroup_init_root_id(struct cgroupfs_root *root, int start, int end) @@ -1451,7 +1450,6 @@ static struct cgroupfs_root *cgroup_root_from_opts(struct cgroup_sb_opts *opts) */ root->subsys_mask = opts->subsys_mask; root->flags = opts->flags; - ida_init(&root->cgroup_ida); if (opts->release_agent) strcpy(root->release_agent_path, opts->release_agent); if (opts->name) @@ -1467,7 +1465,7 @@ static void cgroup_free_root(struct cgroupfs_root *root) /* hierarhcy ID shoulid already have been released */ WARN_ON_ONCE(root->hierarchy_id); - ida_destroy(&root->cgroup_ida); + idr_destroy(&root->cgroup_idr); kfree(root); } } @@ -1582,6 +1580,11 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type, mutex_lock(&cgroup_mutex); mutex_lock(&cgroup_root_mutex); + root_cgrp->id = idr_alloc(&root->cgroup_idr, root_cgrp, + 0, 1, GFP_KERNEL); + if (root_cgrp->id < 0) + goto unlock_drop; + /* Check for name clashes with existing mounts */ ret = -EBUSY; if (strlen(root->name)) @@ -4253,7 +4256,11 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry, goto err_free_cgrp; rcu_assign_pointer(cgrp->name, name); - cgrp->id = ida_simple_get(&root->cgroup_ida, 1, 0, GFP_KERNEL); + /* + * Temporarily set the pointer to NULL, so idr_find() won't return + * a half-baked cgroup. + */ + cgrp->id = idr_alloc(&root->cgroup_idr, NULL, 1, 0, GFP_KERNEL); if (cgrp->id < 0) goto err_free_name; @@ -4351,6 +4358,8 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry, } } + idr_replace(&root->cgroup_idr, cgrp, cgrp->id); + err = cgroup_addrm_files(cgrp, NULL, cgroup_base_files, true); if (err) goto err_destroy; @@ -4377,7 +4386,7 @@ err_free_all: /* Release the reference count that we took on the superblock */ deactivate_super(sb); err_free_id: - ida_simple_remove(&root->cgroup_ida, cgrp->id); + idr_remove(&root->cgroup_idr, cgrp->id); err_free_name: kfree(rcu_dereference_raw(cgrp->name)); err_free_cgrp: @@ -4570,6 +4579,14 @@ static void cgroup_offline_fn(struct work_struct *work) /* delete this cgroup from parent->children */ list_del_rcu(&cgrp->sibling); + /* + * We should remove the cgroup object from idr before its grace + * period starts, so we won't be looking up a cgroup while the + * cgroup is being freed. + */ + idr_remove(&cgrp->root->cgroup_idr, cgrp->id); + cgrp->id = -1; + dput(d); set_bit(CGRP_RELEASABLE, &parent->flags); @@ -4895,6 +4912,10 @@ int __init cgroup_init(void) BUG_ON(cgroup_init_root_id(&cgroup_dummy_root, 0, 1)); + err = idr_alloc(&cgroup_dummy_root.cgroup_idr, cgroup_dummy_top, + 0, 1, GFP_KERNEL); + BUG_ON(err < 0); + mutex_unlock(&cgroup_root_mutex); mutex_unlock(&cgroup_mutex); From b414dc09a31d41d696093a4cce9fb2853a5ecd4e Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Wed, 31 Jul 2013 09:51:06 +0800 Subject: [PATCH 1143/3400] cgroup: document how cgroup IDs are assigned As cgroup id has been used in netprio cgroup and will be used in memcg, it's important to make it clear how a cgroup id is allocated. For example, in netprio cgroup, the id is used as index of anarray. Signed-off-by: Li Zefan Reviewed-by: Michal Hocko Signed-off-by: Tejun Heo --- include/linux/cgroup.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index cca570e188fb..4dfcd0e1b73e 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h @@ -161,7 +161,13 @@ struct cgroup_name { struct cgroup { unsigned long flags; /* "unsigned long" so bitops work */ - int id; /* idr allocated in-hierarchy ID */ + /* + * idr allocated in-hierarchy ID. + * + * The ID of the root cgroup is always 0, and a new cgroup + * will be assigned with a smallest available ID. + */ + int id; /* * We link our 'sibling' struct into our parent's 'children'. From e14880f7bb7e0dc0933af304998371dd543ceb40 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Wed, 31 Jul 2013 09:51:31 +0800 Subject: [PATCH 1144/3400] cgroup: implement cgroup_from_id() This will be used as a replacement for css_lookup(). There's a difference with cgroup id and css id. cgroup id starts with 0, while css id starts with 1. v4: - also check if cggroup_mutex is held. - make it an inline function. Signed-off-by: Li Zefan Reviewed-by: Michal Hocko Signed-off-by: Tejun Heo --- include/linux/cgroup.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index 4dfcd0e1b73e..bbf4d89b56a8 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h @@ -720,6 +720,24 @@ static inline struct cgroup* task_cgroup(struct task_struct *task, return task_subsys_state(task, subsys_id)->cgroup; } +/** + * cgroup_from_id - lookup cgroup by id + * @ss: cgroup subsys to be looked into + * @id: the cgroup id + * + * Returns the cgroup if there's valid one with @id, otherwise returns NULL. + * Should be called under rcu_read_lock(). + */ +static inline struct cgroup *cgroup_from_id(struct cgroup_subsys *ss, int id) +{ +#ifdef CONFIG_PROVE_RCU + rcu_lockdep_assert(rcu_read_lock_held() || + lockdep_is_held(&cgroup_mutex), + "cgroup_from_id() needs proper protection"); +#endif + return idr_find(&ss->root->cgroup_idr, id); +} + struct cgroup *cgroup_next_sibling(struct cgroup *pos); /** From 7b4e0c4ac1809eab6fcfe6818ec8b70be79b41bc Mon Sep 17 00:00:00 2001 From: Aaron Lu Date: Wed, 31 Jul 2013 14:07:15 +0200 Subject: [PATCH 1145/3400] ACPI / PM: Remove redundant power manageable check from acpi_bus_set_power() Now that acpi_device_set_power() checks whether or not the given device is power manageable, it is not necessary to do this check in acpi_bus_set_power() any more, so remove it. Signed-off-by: Aaron Lu Signed-off-by: Rafael J. Wysocki --- drivers/acpi/device_pm.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 8234e1f8c79d..beb9625e8458 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -243,13 +243,6 @@ int acpi_bus_set_power(acpi_handle handle, int state) if (result) return result; - if (!device->flags.power_manageable) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Device [%s] is not power manageable\n", - dev_name(&device->dev))); - return -ENODEV; - } - return acpi_device_set_power(device, state); } EXPORT_SYMBOL(acpi_bus_set_power); From d6b47b122473885abc882e337ac2d321bbcfb378 Mon Sep 17 00:00:00 2001 From: Ben Guthro Date: Tue, 30 Jul 2013 08:24:52 -0400 Subject: [PATCH 1146/3400] ACPI / sleep: Introduce acpi_os_prepare_extended_sleep() for extended sleep path Like acpi_os_prepare_sleep(), register a callback for use in systems like tboot, and xen, which have system specific requirements outside of ACPICA. This mirrors the functionality in acpi_os_prepare_sleep(), called from acpi_hw_sleep() Signed-off-by: Ben Guthro Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/hwesleep.c | 9 +++++++++ drivers/acpi/osl.c | 24 ++++++++++++++++++++++++ include/linux/acpi.h | 7 +++++++ 3 files changed, 40 insertions(+) diff --git a/drivers/acpi/acpica/hwesleep.c b/drivers/acpi/acpica/hwesleep.c index 5e5f76230f5e..414076818d40 100644 --- a/drivers/acpi/acpica/hwesleep.c +++ b/drivers/acpi/acpica/hwesleep.c @@ -43,6 +43,7 @@ */ #include +#include #include "accommon.h" #define _COMPONENT ACPI_HARDWARE @@ -128,6 +129,14 @@ acpi_status acpi_hw_extended_sleep(u8 sleep_state) ACPI_FLUSH_CPU_CACHE(); + status = acpi_os_prepare_extended_sleep(sleep_state, + acpi_gbl_sleep_type_a, + acpi_gbl_sleep_type_b); + if (ACPI_SKIP(status)) + return_ACPI_STATUS(AE_OK); + if (ACPI_FAILURE(status)) + return_ACPI_STATUS(status); + /* * Set the SLP_TYP and SLP_EN bits. * diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 6ab2c3505520..a934950ff7a0 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -79,6 +79,8 @@ extern char line_buf[80]; static int (*__acpi_os_prepare_sleep)(u8 sleep_state, u32 pm1a_ctrl, u32 pm1b_ctrl); +static int (*__acpi_os_prepare_extended_sleep)(u8 sleep_state, u32 val_a, + u32 val_b); static acpi_osd_handler acpi_irq_handler; static void *acpi_irq_context; @@ -1779,6 +1781,28 @@ void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state, __acpi_os_prepare_sleep = func; } +acpi_status acpi_os_prepare_extended_sleep(u8 sleep_state, u32 val_a, + u32 val_b) +{ + int rc = 0; + if (__acpi_os_prepare_extended_sleep) + rc = __acpi_os_prepare_extended_sleep(sleep_state, + val_a, val_b); + if (rc < 0) + return AE_ERROR; + else if (rc > 0) + return AE_CTRL_SKIP; + + return AE_OK; +} + +void acpi_os_set_prepare_extended_sleep(int (*func)(u8 sleep_state, + u32 val_a, u32 val_b)) +{ + __acpi_os_prepare_extended_sleep = func; +} + + void alloc_acpi_hp_work(acpi_handle handle, u32 type, void *context, void (*func)(struct work_struct *work)) { diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 353ba256f368..a5db4aeefa36 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -481,6 +481,13 @@ void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state, acpi_status acpi_os_prepare_sleep(u8 sleep_state, u32 pm1a_control, u32 pm1b_control); + +void acpi_os_set_prepare_extended_sleep(int (*func)(u8 sleep_state, + u32 val_a, u32 val_b)); + +acpi_status acpi_os_prepare_extended_sleep(u8 sleep_state, + u32 val_a, u32 val_b); + #ifdef CONFIG_X86 void arch_reserve_mem_area(acpi_physical_address addr, size_t size); #else From be6b25d15f5e67bc49b90ed55feb1dd947f4df2c Mon Sep 17 00:00:00 2001 From: Ben Guthro Date: Tue, 30 Jul 2013 08:24:54 -0400 Subject: [PATCH 1147/3400] xen / ACPI: notify xen when reduced hardware sleep is available Use the acpi_os_prepare_extended_sleep() callback to notify xen to make use of the reduced hardware sleep functionality The xen hypervisor change underlying this is commit 62d1a69 ("ACPI: support v5 (reduced HW) sleep interface") on the master branch of git://xenbits.xen.org/xen.git. Signed-off-by: Jan Beulich Signed-off-by: Ben Guthro Acked-by: Konrad Wilk Signed-off-by: Rafael J. Wysocki --- drivers/xen/acpi.c | 41 ++++++++++++++++++++++---------- include/xen/acpi.h | 8 +++++-- include/xen/interface/platform.h | 7 +++--- 3 files changed, 38 insertions(+), 18 deletions(-) diff --git a/drivers/xen/acpi.c b/drivers/xen/acpi.c index 119d42a2bf57..90307c0b630c 100644 --- a/drivers/xen/acpi.c +++ b/drivers/xen/acpi.c @@ -35,28 +35,43 @@ #include #include -int xen_acpi_notify_hypervisor_state(u8 sleep_state, - u32 pm1a_cnt, u32 pm1b_cnt) +static int xen_acpi_notify_hypervisor_state(u8 sleep_state, + u32 val_a, u32 val_b, + bool extended) { + unsigned int bits = extended ? 8 : 16; + struct xen_platform_op op = { .cmd = XENPF_enter_acpi_sleep, .interface_version = XENPF_INTERFACE_VERSION, - .u = { - .enter_acpi_sleep = { - .pm1a_cnt_val = (u16)pm1a_cnt, - .pm1b_cnt_val = (u16)pm1b_cnt, - .sleep_state = sleep_state, - }, + .u.enter_acpi_sleep = { + .val_a = (u16)val_a, + .val_b = (u16)val_b, + .sleep_state = sleep_state, + .flags = extended ? XENPF_ACPI_SLEEP_EXTENDED : 0, }, }; - if ((pm1a_cnt & 0xffff0000) || (pm1b_cnt & 0xffff0000)) { - WARN(1, "Using more than 16bits of PM1A/B 0x%x/0x%x!" - "Email xen-devel@lists.xensource.com Thank you.\n", \ - pm1a_cnt, pm1b_cnt); + if (WARN((val_a & (~0 << bits)) || (val_b & (~0 << bits)), + "Using more than %u bits of sleep control values %#x/%#x!" + "Email xen-devel@lists.xen.org - Thank you.\n", \ + bits, val_a, val_b)) return -1; - } HYPERVISOR_dom0_op(&op); return 1; } + +int xen_acpi_notify_hypervisor_sleep(u8 sleep_state, + u32 pm1a_cnt, u32 pm1b_cnt) +{ + return xen_acpi_notify_hypervisor_state(sleep_state, pm1a_cnt, + pm1b_cnt, false); +} + +int xen_acpi_notify_hypervisor_extended_sleep(u8 sleep_state, + u32 val_a, u32 val_b) +{ + return xen_acpi_notify_hypervisor_state(sleep_state, val_a, + val_b, true); +} diff --git a/include/xen/acpi.h b/include/xen/acpi.h index 46aa3d1c1654..4ddd7dc4a61e 100644 --- a/include/xen/acpi.h +++ b/include/xen/acpi.h @@ -75,8 +75,10 @@ static inline int xen_acpi_get_pxm(acpi_handle h) return -ENXIO; } -int xen_acpi_notify_hypervisor_state(u8 sleep_state, +int xen_acpi_notify_hypervisor_sleep(u8 sleep_state, u32 pm1a_cnt, u32 pm1b_cnd); +int xen_acpi_notify_hypervisor_extended_sleep(u8 sleep_state, + u32 val_a, u32 val_b); static inline int xen_acpi_suspend_lowlevel(void) { @@ -93,7 +95,9 @@ static inline void xen_acpi_sleep_register(void) { if (xen_initial_domain()) { acpi_os_set_prepare_sleep( - &xen_acpi_notify_hypervisor_state); + &xen_acpi_notify_hypervisor_sleep); + acpi_os_set_prepare_extended_sleep( + &xen_acpi_notify_hypervisor_extended_sleep); acpi_suspend_lowlevel = xen_acpi_suspend_lowlevel; } diff --git a/include/xen/interface/platform.h b/include/xen/interface/platform.h index c57d5f67f702..f1331e3e7271 100644 --- a/include/xen/interface/platform.h +++ b/include/xen/interface/platform.h @@ -152,10 +152,11 @@ DEFINE_GUEST_HANDLE_STRUCT(xenpf_firmware_info_t); #define XENPF_enter_acpi_sleep 51 struct xenpf_enter_acpi_sleep { /* IN variables */ - uint16_t pm1a_cnt_val; /* PM1a control value. */ - uint16_t pm1b_cnt_val; /* PM1b control value. */ + uint16_t val_a; /* PM1a control / sleep type A. */ + uint16_t val_b; /* PM1b control / sleep type B. */ uint32_t sleep_state; /* Which state to enter (Sn). */ - uint32_t flags; /* Must be zero. */ +#define XENPF_ACPI_SLEEP_EXTENDED 0x00000001 + uint32_t flags; /* XENPF_ACPI_SLEEP_*. */ }; DEFINE_GUEST_HANDLE_STRUCT(xenpf_enter_acpi_sleep_t); From 01c6a6afd50f07dfd66b2891fd194c4b789fca48 Mon Sep 17 00:00:00 2001 From: Ben Guthro Date: Tue, 30 Jul 2013 09:22:37 -0400 Subject: [PATCH 1148/3400] x86 / tboot / ACPI: Fail extended mode reduced hardware sleep Register for the extended sleep callback from ACPI. As tboot currently does not support the reduced hardware sleep interface, fail this extended sleep call. Signed-off-by: Jan Beulich Signed-off-by: Ben Guthro Cc: tboot-devel@lists.sourceforge.net Cc: Gang Wei Reviewed-by: Konrad Rzeszutek Wilk Signed-off-by: Rafael J. Wysocki --- arch/x86/kernel/tboot.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/x86/kernel/tboot.c b/arch/x86/kernel/tboot.c index addf7b58f4e8..91a4496db434 100644 --- a/arch/x86/kernel/tboot.c +++ b/arch/x86/kernel/tboot.c @@ -301,6 +301,15 @@ static int tboot_sleep(u8 sleep_state, u32 pm1a_control, u32 pm1b_control) return 0; } +static int tboot_extended_sleep(u8 sleep_state, u32 val_a, u32 val_b) +{ + if (!tboot_enabled()) + return 0; + + pr_warning("tboot is not able to suspend on platforms with reduced hardware sleep (ACPIv5)"); + return -ENODEV; +} + static atomic_t ap_wfs_count; static int tboot_wait_for_aps(int num_aps) @@ -422,6 +431,7 @@ static __init int tboot_late_init(void) #endif acpi_os_set_prepare_sleep(&tboot_sleep); + acpi_os_set_prepare_extended_sleep(&tboot_extended_sleep); return 0; } From 941ea3616c747545d0278fc432fb7919b6d0d8f0 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 31 Jul 2013 09:21:25 +0300 Subject: [PATCH 1149/3400] usb: dwc3: use dev_get_platdata() Use the wrapper function for retrieving the platform_data instead of accessing dev->platform_data directly. While at that also make change 'node' initialization to use the dev pointer. Inspired-by: Jingoo Han Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index da0a4b8b33ed..3ff6f0ad01df 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -350,11 +350,11 @@ static void dwc3_core_exit(struct dwc3 *dwc) static int dwc3_probe(struct platform_device *pdev) { - struct dwc3_platform_data *pdata = pdev->dev.platform_data; - struct device_node *node = pdev->dev.of_node; + struct device *dev = &pdev->dev; + struct dwc3_platform_data *pdata = dev_get_platdata(dev); + struct device_node *node = dev->of_node; struct resource *res; struct dwc3 *dwc; - struct device *dev = &pdev->dev; int ret = -ENOMEM; From d982057f631df04f8d78321084a1a71ca51f3364 Mon Sep 17 00:00:00 2001 From: Torsten Kaiser Date: Tue, 23 Jul 2013 22:58:23 +0200 Subject: [PATCH 1150/3400] x86, amd, microcode: Fix error path in apply_microcode_amd() Return -1 (like Intels apply_microcode) when the loading fails, also do not set the active microcode level on failure. Signed-off-by: Torsten Kaiser Link: http://lkml.kernel.org/r/20130723225823.2e4e7588@googlemail.com Acked-by: Borislav Petkov Signed-off-by: H. Peter Anvin --- arch/x86/kernel/microcode_amd.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index 47ebb1dbfbcb..7a0adb7ee433 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c @@ -220,12 +220,13 @@ int apply_microcode_amd(int cpu) return 0; } - if (__apply_microcode_amd(mc_amd)) + if (__apply_microcode_amd(mc_amd)) { pr_err("CPU%d: update failed for patch_level=0x%08x\n", cpu, mc_amd->hdr.patch_id); - else - pr_info("CPU%d: new patch_level=0x%08x\n", cpu, - mc_amd->hdr.patch_id); + return -1; + } + pr_info("CPU%d: new patch_level=0x%08x\n", cpu, + mc_amd->hdr.patch_id); uci->cpu_sig.rev = mc_amd->hdr.patch_id; c->microcode = mc_amd->hdr.patch_id; From 776164c1faac4966ab14418bb0922e1820da1d19 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Fri, 26 Jul 2013 17:12:56 +0200 Subject: [PATCH 1151/3400] debugfs: debugfs_remove_recursive() must not rely on list_empty(d_subdirs) debugfs_remove_recursive() is wrong, 1. it wrongly assumes that !list_empty(d_subdirs) means that this dir should be removed. This is not that bad by itself, but: 2. if d_subdirs does not becomes empty after __debugfs_remove() it gives up and silently fails, it doesn't even try to remove other entries. However ->d_subdirs can be non-empty because it still has the already deleted !debugfs_positive() entries. 3. simple_release_fs() is called even if __debugfs_remove() fails. Suppose we have dir1/ dir2/ file2 file1 and someone opens dir1/dir2/file2. Now, debugfs_remove_recursive(dir1/dir2) succeeds, and dir1/dir2 goes away. But debugfs_remove_recursive(dir1) silently fails and doesn't remove this directory. Because it tries to delete (the already deleted) dir1/dir2/file2 again and then fails due to "Avoid infinite loop" logic. Test-case: #!/bin/sh cd /sys/kernel/debug/tracing echo 'p:probe/sigprocmask sigprocmask' >> kprobe_events sleep 1000 < events/probe/sigprocmask/id & echo -n >| kprobe_events [ -d events/probe ] && echo "ERR!! failed to rm probe" And after that it is not possible to create another probe entry. With this patch debugfs_remove_recursive() skips !debugfs_positive() files although this is not strictly needed. The most important change is that it does not try to make ->d_subdirs empty, it simply scans the whole list(s) recursively and removes as much as possible. Link: http://lkml.kernel.org/r/20130726151256.GC19472@redhat.com Acked-by: Greg Kroah-Hartman Signed-off-by: Oleg Nesterov Signed-off-by: Steven Rostedt --- fs/debugfs/inode.c | 71 +++++++++++++++------------------------------- 1 file changed, 23 insertions(+), 48 deletions(-) diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index 4888cb3fdef7..c7c83ff0f752 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -533,8 +533,7 @@ EXPORT_SYMBOL_GPL(debugfs_remove); */ void debugfs_remove_recursive(struct dentry *dentry) { - struct dentry *child; - struct dentry *parent; + struct dentry *child, *next, *parent; if (IS_ERR_OR_NULL(dentry)) return; @@ -544,61 +543,37 @@ void debugfs_remove_recursive(struct dentry *dentry) return; parent = dentry; + down: mutex_lock(&parent->d_inode->i_mutex); + list_for_each_entry_safe(child, next, &parent->d_subdirs, d_u.d_child) { + if (!debugfs_positive(child)) + continue; - while (1) { - /* - * When all dentries under "parent" has been removed, - * walk up the tree until we reach our starting point. - */ - if (list_empty(&parent->d_subdirs)) { - mutex_unlock(&parent->d_inode->i_mutex); - if (parent == dentry) - break; - parent = parent->d_parent; - mutex_lock(&parent->d_inode->i_mutex); - } - child = list_entry(parent->d_subdirs.next, struct dentry, - d_u.d_child); - next_sibling: - - /* - * If "child" isn't empty, walk down the tree and - * remove all its descendants first. - */ + /* perhaps simple_empty(child) makes more sense */ if (!list_empty(&child->d_subdirs)) { mutex_unlock(&parent->d_inode->i_mutex); parent = child; - mutex_lock(&parent->d_inode->i_mutex); - continue; + goto down; } - __debugfs_remove(child, parent); - if (parent->d_subdirs.next == &child->d_u.d_child) { - /* - * Try the next sibling. - */ - if (child->d_u.d_child.next != &parent->d_subdirs) { - child = list_entry(child->d_u.d_child.next, - struct dentry, - d_u.d_child); - goto next_sibling; - } - - /* - * Avoid infinite loop if we fail to remove - * one dentry. - */ - mutex_unlock(&parent->d_inode->i_mutex); - break; - } - simple_release_fs(&debugfs_mount, &debugfs_mount_count); + up: + if (!__debugfs_remove(child, parent)) + simple_release_fs(&debugfs_mount, &debugfs_mount_count); } - parent = dentry->d_parent; - mutex_lock(&parent->d_inode->i_mutex); - __debugfs_remove(dentry, parent); mutex_unlock(&parent->d_inode->i_mutex); - simple_release_fs(&debugfs_mount, &debugfs_mount_count); + child = parent; + parent = parent->d_parent; + mutex_lock(&parent->d_inode->i_mutex); + + if (child != dentry) { + next = list_entry(child->d_u.d_child.next, struct dentry, + d_u.d_child); + goto up; + } + + if (!__debugfs_remove(child, parent)) + simple_release_fs(&debugfs_mount, &debugfs_mount_count); + mutex_unlock(&parent->d_inode->i_mutex); } EXPORT_SYMBOL_GPL(debugfs_remove_recursive); From 481f2d4f89f87a0baa26147f323380e31cfa7c44 Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Tue, 30 Jul 2013 19:51:20 -0700 Subject: [PATCH 1152/3400] usb: core: don't try to reset_device() a port that got just disconnected The USB hub driver's event handler contains a check to catch SuperSpeed devices that transitioned into the SS.Inactive state and tries to fix them with a reset. It decides whether to do a plain hub port reset or call the usb_reset_device() function based on whether there was a device attached to the port. However, there are device/hub combinations (found with a JetFlash Transcend mass storage stick (8564:1000) on the root hub of an Intel LynxPoint PCH) which can transition to the SS.Inactive state on disconnect (and stay there long enough for the host to notice). In this case, above-mentioned reset check will call usb_reset_device() on the stale device data structure. The kernel will send pointless LPM control messages to the no longer connected device address and can even cause several 5 second khubd stalls on some (buggy?) host controllers, before finally accepting the device's fate amongst a flurry of error messages. This patch makes the choice of reset dependent on the port status that has just been read from the hub in addition to the existence of an in-kernel data structure for the device, and only proceeds with the more extensive reset if both are valid. Signed-off-by: Julius Werner Signed-off-by: Sarah Sharp --- drivers/usb/core/hub.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 4a8a1d68002c..558313de4911 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -4798,7 +4798,8 @@ static void hub_events(void) hub->ports[i - 1]->child; dev_dbg(hub_dev, "warm reset port %d\n", i); - if (!udev) { + if (!udev || !(portstatus & + USB_PORT_STAT_CONNECTION)) { status = hub_port_reset(hub, i, NULL, HUB_BH_RESET_TIME, true); @@ -4808,8 +4809,8 @@ static void hub_events(void) usb_lock_device(udev); status = usb_reset_device(udev); usb_unlock_device(udev); + connect_change = 0; } - connect_change = 0; } if (connect_change) From e56566699ca64ec44dd134ec5310a3585ffacfec Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 30 Jul 2013 22:47:44 +0800 Subject: [PATCH 1153/3400] regulator: pfuze100: Simplify pfuze100_set_ramp_delay implementation Simplify the equation to calculate ramp_delay. Below equations are equivalent: ramp_delay = 25000 / (2 * ramp_delay); ramp_delay = 50000 / (4 * ramp_delay); ramp_delay = 25000 / (2 * ramp_delay); ramp_delay = 12500 / ramp_delay; So we don't need to read BIT6 of rdev->desc->vsel_reg for applying different equations. Also use rdev->desc->vsel_reg instead of run-time calculate register address. Signed-off-by: Axel Lin Reviewed-by: Robin Gong Signed-off-by: Mark Brown --- drivers/regulator/pfuze100-regulator.c | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c index e02d9b921ed3..bda55617092b 100644 --- a/drivers/regulator/pfuze100-regulator.c +++ b/drivers/regulator/pfuze100-regulator.c @@ -93,26 +93,15 @@ static int pfuze100_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) { struct pfuze_chip *pfuze100 = rdev_get_drvdata(rdev); int id = rdev->desc->id; - unsigned int val, ramp_bits, reg; + unsigned int ramp_bits; int ret; if (id < PFUZE100_SWBST) { - if (id == PFUZE100_SW1AB) - reg = PFUZE100_SW1ABVOL; - else - reg = PFUZE100_SW1CVOL + (id - PFUZE100_SW1C) * 7; - regmap_read(pfuze100->regmap, reg, &val); - - if (id <= PFUZE100_SW1C) - ramp_delay = 25000 / (2 * ramp_delay); - else if (val & 0x40) - ramp_delay = 50000 / (4 * ramp_delay); - else - ramp_delay = 25000 / (2 * ramp_delay); - + ramp_delay = 12500 / ramp_delay; ramp_bits = (ramp_delay >> 1) - (ramp_delay >> 3); - ret = regmap_update_bits(pfuze100->regmap, reg + 4 , 0xc0, - ramp_bits << 6); + ret = regmap_update_bits(pfuze100->regmap, + rdev->desc->vsel_reg + 4, + 0xc0, ramp_bits << 6); if (ret < 0) dev_err(pfuze100->dev, "ramp failed, err %d\n", ret); } else From 2de024b766bb9e31c357f70c6344d1107f38ce1a Mon Sep 17 00:00:00 2001 From: Emil Goode Date: Tue, 30 Jul 2013 19:35:35 +0200 Subject: [PATCH 1154/3400] spi/atmel: Fix format specifier warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes the following sparse warnings. dma_addr_t can be either u32 or u64 so we should cast to the largest type and use the format specifier %llx. drivers/spi/spi-atmel.c: In function ‘atmel_spi_next_xfer_dma_submit’: drivers/spi/spi-atmel.c:631:2: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 7 has type ‘dma_addr_t’ [-Wformat] drivers/spi/spi-atmel.c:631:2: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 9 has type ‘dma_addr_t’ [-Wformat] drivers/spi/spi-atmel.c: In function ‘atmel_spi_pdc_next_xfer’: drivers/spi/spi-atmel.c:734:3: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 7 has type ‘dma_addr_t’ [-Wformat] drivers/spi/spi-atmel.c:734:3: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 9 has type ‘dma_addr_t’ [-Wformat] drivers/spi/spi-atmel.c:773:3: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 7 has type ‘dma_addr_t’ [-Wformat] drivers/spi/spi-atmel.c:773:3: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 9 has type ‘dma_addr_t’ [-Wformat] Signed-off-by: Emil Goode Signed-off-by: Mark Brown --- drivers/spi/spi-atmel.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index 4e406930fa52..fd7cc566095a 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -629,9 +629,9 @@ static int atmel_spi_next_xfer_dma_submit(struct spi_master *master, goto err_dma; dev_dbg(master->dev.parent, - " start dma xfer %p: len %u tx %p/%08x rx %p/%08x\n", - xfer, xfer->len, xfer->tx_buf, xfer->tx_dma, - xfer->rx_buf, xfer->rx_dma); + " start dma xfer %p: len %u tx %p/%08llx rx %p/%08llx\n", + xfer, xfer->len, xfer->tx_buf, (unsigned long long)xfer->tx_dma, + xfer->rx_buf, (unsigned long long)xfer->rx_dma); /* Enable relevant interrupts */ spi_writel(as, IER, SPI_BIT(OVRES)); @@ -732,9 +732,10 @@ static void atmel_spi_pdc_next_xfer(struct spi_master *master, spi_writel(as, TCR, len); dev_dbg(&msg->spi->dev, - " start xfer %p: len %u tx %p/%08x rx %p/%08x\n", - xfer, xfer->len, xfer->tx_buf, xfer->tx_dma, - xfer->rx_buf, xfer->rx_dma); + " start xfer %p: len %u tx %p/%08llx rx %p/%08llx\n", + xfer, xfer->len, xfer->tx_buf, + (unsigned long long)xfer->tx_dma, xfer->rx_buf, + (unsigned long long)xfer->rx_dma); } else { xfer = as->next_transfer; remaining = as->next_remaining_bytes; @@ -771,9 +772,10 @@ static void atmel_spi_pdc_next_xfer(struct spi_master *master, spi_writel(as, TNCR, len); dev_dbg(&msg->spi->dev, - " next xfer %p: len %u tx %p/%08x rx %p/%08x\n", - xfer, xfer->len, xfer->tx_buf, xfer->tx_dma, - xfer->rx_buf, xfer->rx_dma); + " next xfer %p: len %u tx %p/%08llx rx %p/%08llx\n", + xfer, xfer->len, xfer->tx_buf, + (unsigned long long)xfer->tx_dma, xfer->rx_buf, + (unsigned long long)xfer->rx_dma); ieval = SPI_BIT(ENDRX) | SPI_BIT(OVRES); } else { spi_writel(as, RNCR, 0); From 6a3fc31f35025a583499c0d3b1c6fc5dcf6e48ec Mon Sep 17 00:00:00 2001 From: Emil Goode Date: Tue, 30 Jul 2013 19:35:36 +0200 Subject: [PATCH 1155/3400] spi/ep93xx: Fix format specifier warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes the following sparse warning by changing the the format specifier for size_t to %zu. drivers/spi/spi-ep93xx.c:512:3: warning: format ‘%d’ expects argument of type ‘int’, but argument 3 has type ‘size_t’ [-Wformat] Signed-off-by: Emil Goode Signed-off-by: Mark Brown --- drivers/spi/spi-ep93xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index 4c9a50ce4f6c..31611f7d7be9 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -509,7 +509,7 @@ ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_transfer_direction dir) } if (WARN_ON(len)) { - dev_warn(&espi->pdev->dev, "len = %d expected 0!", len); + dev_warn(&espi->pdev->dev, "len = %zu expected 0!", len); return ERR_PTR(-EINVAL); } From 2816c551c796ec14620325b2c9ed75b9979d3125 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Mon, 29 Jul 2013 19:50:33 +0200 Subject: [PATCH 1156/3400] tracing: trace_remove_event_call() should fail if call/file is in use Change trace_remove_event_call(call) to return the error if this call is active. This is what the callers assume but can't verify outside of the tracing locks. Both trace_kprobe.c/trace_uprobe.c need the additional changes, unregister_trace_probe() should abort if trace_remove_event_call() fails. The caller is going to free this call/file so we must ensure that nobody can use them after trace_remove_event_call() succeeds. debugfs should be fine after the previous changes and event_remove() does TRACE_REG_UNREGISTER, but still there are 2 reasons why we need the additional checks: - There could be a perf_event(s) attached to this tp_event, so the patch checks ->perf_refcount. - TRACE_REG_UNREGISTER can be suppressed by FTRACE_EVENT_FL_SOFT_MODE, so we simply check FTRACE_EVENT_FL_ENABLED protected by event_mutex. Link: http://lkml.kernel.org/r/20130729175033.GB26284@redhat.com Reviewed-by: Masami Hiramatsu Signed-off-by: Oleg Nesterov Signed-off-by: Steven Rostedt --- include/linux/ftrace_event.h | 2 +- kernel/trace/trace_events.c | 37 +++++++++++++++++++++++++++++++++--- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h index 4372658c73ae..f98ab063e95e 100644 --- a/include/linux/ftrace_event.h +++ b/include/linux/ftrace_event.h @@ -332,7 +332,7 @@ extern int trace_define_field(struct ftrace_event_call *call, const char *type, const char *name, int offset, int size, int is_signed, int filter_type); extern int trace_add_event_call(struct ftrace_event_call *call); -extern void trace_remove_event_call(struct ftrace_event_call *call); +extern int trace_remove_event_call(struct ftrace_event_call *call); #define is_signed_type(type) (((type)(-1)) < (type)1) diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index a67c913e2f9f..ec04836273c0 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -1713,16 +1713,47 @@ static void __trace_remove_event_call(struct ftrace_event_call *call) destroy_preds(call); } -/* Remove an event_call */ -void trace_remove_event_call(struct ftrace_event_call *call) +static int probe_remove_event_call(struct ftrace_event_call *call) { + struct trace_array *tr; + struct ftrace_event_file *file; + +#ifdef CONFIG_PERF_EVENTS + if (call->perf_refcount) + return -EBUSY; +#endif + do_for_each_event_file(tr, file) { + if (file->event_call != call) + continue; + /* + * We can't rely on ftrace_event_enable_disable(enable => 0) + * we are going to do, FTRACE_EVENT_FL_SOFT_MODE can suppress + * TRACE_REG_UNREGISTER. + */ + if (file->flags & FTRACE_EVENT_FL_ENABLED) + return -EBUSY; + break; + } while_for_each_event_file(); + + __trace_remove_event_call(call); + + return 0; +} + +/* Remove an event_call */ +int trace_remove_event_call(struct ftrace_event_call *call) +{ + int ret; + mutex_lock(&trace_types_lock); mutex_lock(&event_mutex); down_write(&trace_event_sem); - __trace_remove_event_call(call); + ret = probe_remove_event_call(call); up_write(&trace_event_sem); mutex_unlock(&event_mutex); mutex_unlock(&trace_types_lock); + + return ret; } #define for_each_event(event, start, end) \ From 2ba64035d0ca966fd189bc3e0826343fc81bf482 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Wed, 31 Jul 2013 13:16:22 -0400 Subject: [PATCH 1157/3400] tracing: Add comment to describe special break case in probe_remove_event_call() The "break" used in the do_for_each_event_file() is used as an optimization as the loop is really a double loop. The loop searches all event files for each trace_array. There's only one matching event file per trace_array and after we find the event file for the trace_array, the break is used to jump to the next trace_array and start the search there. As this is not a standard way of using "break" in C code, it requires a comment right before the break to let people know what is going on. Signed-off-by: Steven Rostedt --- kernel/trace/trace_events.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index ec04836273c0..29a7ebcfb426 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -1732,6 +1732,12 @@ static int probe_remove_event_call(struct ftrace_event_call *call) */ if (file->flags & FTRACE_EVENT_FL_ENABLED) return -EBUSY; + /* + * The do_for_each_event_file_safe() is + * a double loop. After finding the call for this + * trace_array, we use break to jump to the next + * trace_array. + */ break; } while_for_each_event_file(); From 008eb957dafea32bac993be5cbeaf4ca0ee8b0aa Mon Sep 17 00:00:00 2001 From: James Hogan Date: Fri, 26 Jul 2013 13:34:43 +0100 Subject: [PATCH 1158/3400] usb: xhci: add missing dma-mapping.h includes A randconfig build hit the following build errors because xhci.c and xhci-mem.c use dma mapping functions but don't include . Add the missing includes to fix the build errors. drivers/usb/host/xhci.c In function 'xhci_gen_setup': drivers/usb/host/xhci.c +4872 : error: implicit declaration of function 'dma_set_mask' drivers/usb/host/xhci.c +4872 : error: implicit declaration of function 'DMA_BIT_MASK' drivers/usb/host/xhci-mem.c In function 'xhci_free_stream_ctx': drivers/usb/host/xhci-mem.c +435 : error: implicit declaration of function 'dma_free_coherent' drivers/usb/host/xhci-mem.c In function 'xhci_alloc_stream_ctx': drivers/usb/host/xhci-mem.c +463 : error: implicit declaration of function 'dma_alloc_coherent' Signed-off-by: James Hogan Cc: Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org Signed-off-by: Sarah Sharp --- drivers/usb/host/xhci-mem.c | 1 + drivers/usb/host/xhci.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index df6978abd7e6..6f8c2fd47675 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "xhci.h" diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 41eb4fc33453..9478caa2f71f 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "xhci.h" From ba48202932de455566868a065874279688c9241f Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Wed, 31 Jul 2013 13:48:00 -0400 Subject: [PATCH 1159/3400] cifs: fix bad error handling in crypto code Jarod reported an Oops like when testing with fips=1: CIFS VFS: could not allocate crypto hmacmd5 CIFS VFS: could not crypto alloc hmacmd5 rc -2 CIFS VFS: Error -2 during NTLMSSP authentication CIFS VFS: Send error in SessSetup = -2 BUG: unable to handle kernel NULL pointer dereference at 000000000000004e IP: [] crypto_destroy_tfm+0x1a/0x90 PGD 0 Oops: 0000 [#1] SMP Modules linked in: md4 nls_utf8 cifs dns_resolver fscache kvm serio_raw virtio_balloon virtio_net mperf i2c_piix4 cirrus drm_kms_helper ttm drm i2c_core virtio_blk ata_generic pata_acpi CPU: 1 PID: 639 Comm: mount.cifs Not tainted 3.11.0-0.rc3.git0.1.fc20.x86_64 #1 Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011 task: ffff88007bf496e0 ti: ffff88007b080000 task.ti: ffff88007b080000 RIP: 0010:[] [] crypto_destroy_tfm+0x1a/0x90 RSP: 0018:ffff88007b081d10 EFLAGS: 00010282 RAX: 0000000000001f1f RBX: ffff880037422000 RCX: ffff88007b081fd8 RDX: 000000000000001f RSI: 0000000000000006 RDI: fffffffffffffffe RBP: ffff88007b081d30 R08: ffff880037422000 R09: ffff88007c090100 R10: 0000000000000000 R11: 00000000fffffffe R12: fffffffffffffffe R13: ffff880037422000 R14: ffff880037422000 R15: 00000000fffffffe FS: 00007fc322f4f780(0000) GS:ffff88007fc80000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 000000000000004e CR3: 000000007bdaa000 CR4: 00000000000006e0 Stack: ffffffff81085845 ffff880037422000 ffff8800375e7400 ffff880037422000 ffff88007b081d48 ffffffffa0176022 ffff880037422000 ffff88007b081d60 ffffffffa015c07b ffff880037600600 ffff88007b081dc8 ffffffffa01610e1 Call Trace: [] ? __cancel_work_timer+0x75/0xf0 [] cifs_crypto_shash_release+0x82/0xf0 [cifs] [] cifs_put_tcp_session+0x8b/0xe0 [cifs] [] cifs_mount+0x9d1/0xad0 [cifs] [] cifs_do_mount+0xa0/0x4d0 [cifs] [] mount_fs+0x39/0x1b0 [] vfs_kern_mount+0x5f/0xf0 [] do_mount+0x23e/0xa20 [] ? copy_mount_options+0x36/0x170 [] SyS_mount+0x83/0xc0 [] system_call_fastpath+0x16/0x1b Code: eb 9e 66 66 66 66 66 66 2e 0f 1f 84 00 00 00 00 00 66 66 66 66 90 55 48 89 e5 41 55 41 54 49 89 fc 53 48 83 ec 08 48 85 ff 74 46 <48> 83 7e 48 00 48 8b 5e 50 74 4b 48 89 f7 e8 83 fc ff ff 4c 8b RIP [] crypto_destroy_tfm+0x1a/0x90 RSP CR2: 000000000000004e The cifs code allocates some crypto structures. If that fails, it returns an error, but it leaves the pointers set to their PTR_ERR values. Then later when it tries to clean up, it sees that those values are non-NULL and then passes them to the routine that frees them. Fix this by setting the pointers to NULL after collecting the error code in this situation. Cc: Sachin Prabhu Reported-by: Jarod Wilson Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/cifsencrypt.c | 12 ++++++++---- fs/cifs/smb2transport.c | 9 +++++++-- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index 194f9cce5d83..fc6f4f3a1a9d 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c @@ -43,17 +43,18 @@ cifs_crypto_shash_md5_allocate(struct TCP_Server_Info *server) server->secmech.md5 = crypto_alloc_shash("md5", 0, 0); if (IS_ERR(server->secmech.md5)) { cifs_dbg(VFS, "could not allocate crypto md5\n"); - return PTR_ERR(server->secmech.md5); + rc = PTR_ERR(server->secmech.md5); + server->secmech.md5 = NULL; + return rc; } size = sizeof(struct shash_desc) + crypto_shash_descsize(server->secmech.md5); server->secmech.sdescmd5 = kmalloc(size, GFP_KERNEL); if (!server->secmech.sdescmd5) { - rc = -ENOMEM; crypto_free_shash(server->secmech.md5); server->secmech.md5 = NULL; - return rc; + return -ENOMEM; } server->secmech.sdescmd5->shash.tfm = server->secmech.md5; server->secmech.sdescmd5->shash.flags = 0x0; @@ -591,6 +592,7 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash) static int crypto_hmacmd5_alloc(struct TCP_Server_Info *server) { + int rc; unsigned int size; /* check if already allocated */ @@ -600,7 +602,9 @@ static int crypto_hmacmd5_alloc(struct TCP_Server_Info *server) server->secmech.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0); if (IS_ERR(server->secmech.hmacmd5)) { cifs_dbg(VFS, "could not allocate crypto hmacmd5\n"); - return PTR_ERR(server->secmech.hmacmd5); + rc = PTR_ERR(server->secmech.hmacmd5); + server->secmech.hmacmd5 = NULL; + return rc; } size = sizeof(struct shash_desc) + diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c index 301b191270b9..4f2300d020c7 100644 --- a/fs/cifs/smb2transport.c +++ b/fs/cifs/smb2transport.c @@ -42,6 +42,7 @@ static int smb2_crypto_shash_allocate(struct TCP_Server_Info *server) { + int rc; unsigned int size; if (server->secmech.sdeschmacsha256 != NULL) @@ -50,7 +51,9 @@ smb2_crypto_shash_allocate(struct TCP_Server_Info *server) server->secmech.hmacsha256 = crypto_alloc_shash("hmac(sha256)", 0, 0); if (IS_ERR(server->secmech.hmacsha256)) { cifs_dbg(VFS, "could not allocate crypto hmacsha256\n"); - return PTR_ERR(server->secmech.hmacsha256); + rc = PTR_ERR(server->secmech.hmacsha256); + server->secmech.hmacsha256 = NULL; + return rc; } size = sizeof(struct shash_desc) + @@ -87,7 +90,9 @@ smb3_crypto_shash_allocate(struct TCP_Server_Info *server) server->secmech.sdeschmacsha256 = NULL; crypto_free_shash(server->secmech.hmacsha256); server->secmech.hmacsha256 = NULL; - return PTR_ERR(server->secmech.cmacaes); + rc = PTR_ERR(server->secmech.cmacaes); + server->secmech.cmacaes = NULL; + return rc; } size = sizeof(struct shash_desc) + From 66ffd113f5d81e951b0379acfd0a1df0771d8828 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Tue, 30 Jul 2013 11:38:44 -0400 Subject: [PATCH 1160/3400] cifs: set sb->s_d_op before calling d_make_root() Currently, the s_root dentry doesn't get its d_op pointer set to anything. This breaks lookups in the root of case-insensitive mounts since that relies on having d_hash and d_compare routines that know to treat the filename as case-insensitive. cifs.ko has been broken this way for a long time, but commit 1c929cfe6 ("switch cifs"), added a cryptic comment which is removed in the patch below, which makes me wonder if this was done deliberately for some reason. It's not clear to me why we'd want the s_root not to have d_op set properly. It may have something to do with d_automount or d_revalidate on the root, but my suspicion in looking over the code is that Al was just trying to preserve the existing behavior when changing this code over to use s_d_op. This patch changes it so that we set s_d_op before calling d_make_root and removes the comment. I tested mounting, accessing and unmounting several types of shares (including DFS referrals) and everything still seemed to work OK afterward. I could be missing something however, so please do let me know if I am. Reported-by: Jan-Marek Glogowski Cc: Al Viro Cc: Ian Kent Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/cifsfs.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 4bdd547dbf6f..85ea98d139fc 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -147,18 +147,17 @@ cifs_read_super(struct super_block *sb) goto out_no_root; } + if (cifs_sb_master_tcon(cifs_sb)->nocase) + sb->s_d_op = &cifs_ci_dentry_ops; + else + sb->s_d_op = &cifs_dentry_ops; + sb->s_root = d_make_root(inode); if (!sb->s_root) { rc = -ENOMEM; goto out_no_root; } - /* do that *after* d_make_root() - we want NULL ->d_op for root here */ - if (cifs_sb_master_tcon(cifs_sb)->nocase) - sb->s_d_op = &cifs_ci_dentry_ops; - else - sb->s_d_op = &cifs_dentry_ops; - #ifdef CONFIG_CIFS_NFSD_EXPORT if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { cifs_dbg(FYI, "export ops supported\n"); From b56e4b857c5210e848bfb80e074e5756a36cd523 Mon Sep 17 00:00:00 2001 From: Chris Wright Date: Wed, 31 Jul 2013 12:12:24 -0700 Subject: [PATCH 1161/3400] mac80211: fix infinite loop in ieee80211_determine_chantype Commit "3d9646d mac80211: fix channel selection bug" introduced a possible infinite loop by moving the out target above the chandef_downgrade while loop. When we downgrade to NL80211_CHAN_WIDTH_20_NOHT, we jump back up to re-run the while loop...indefinitely. Replace goto with break and carry on. This may not be sufficient to connect to the AP, but will at least keep the cpu from livelocking. Thanks to Derek Atkins as an extra pair of debugging eyes. Cc: stable@kernel.org Signed-off-by: Chris Wright Signed-off-by: Johannes Berg --- 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 ae31968d42d3..e3e7d2be9e41 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -338,7 +338,7 @@ out: if (WARN_ON(chandef->width == NL80211_CHAN_WIDTH_20_NOHT)) { ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; - goto out; + break; } ret |= chandef_downgrade(chandef); From cb236d2d713cff83d024a82b836757d9e2b50715 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 29 Jul 2013 23:07:43 +0200 Subject: [PATCH 1162/3400] mac80211: don't wait for TX status forever TX status notification can get lost, or the frames could get stuck on the queue, so don't wait for the callback from the driver forever and instead time out after half a second. Cc: stable@vger.kernel.org Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index e3e7d2be9e41..e5c3cf405060 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -31,10 +31,12 @@ #include "led.h" #define IEEE80211_AUTH_TIMEOUT (HZ / 5) +#define IEEE80211_AUTH_TIMEOUT_LONG (HZ / 2) #define IEEE80211_AUTH_TIMEOUT_SHORT (HZ / 10) #define IEEE80211_AUTH_MAX_TRIES 3 #define IEEE80211_AUTH_WAIT_ASSOC (HZ * 5) #define IEEE80211_ASSOC_TIMEOUT (HZ / 5) +#define IEEE80211_ASSOC_TIMEOUT_LONG (HZ / 2) #define IEEE80211_ASSOC_TIMEOUT_SHORT (HZ / 10) #define IEEE80211_ASSOC_MAX_TRIES 3 @@ -3394,10 +3396,13 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) if (tx_flags == 0) { auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; - ifmgd->auth_data->timeout_started = true; + auth_data->timeout_started = true; run_again(sdata, auth_data->timeout); } else { - auth_data->timeout_started = false; + auth_data->timeout = + round_jiffies_up(jiffies + IEEE80211_AUTH_TIMEOUT_LONG); + auth_data->timeout_started = true; + run_again(sdata, auth_data->timeout); } return 0; @@ -3434,7 +3439,11 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata) assoc_data->timeout_started = true; run_again(sdata, assoc_data->timeout); } else { - assoc_data->timeout_started = false; + assoc_data->timeout = + round_jiffies_up(jiffies + + IEEE80211_ASSOC_TIMEOUT_LONG); + assoc_data->timeout_started = true; + run_again(sdata, assoc_data->timeout); } return 0; From 5cdaed1e878d723d56d04ae0be1738124acf9f46 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 31 Jul 2013 11:23:06 +0200 Subject: [PATCH 1163/3400] mac80211: ignore HT primary channel while connected While we're connected, the AP shouldn't change the primary channel in the HT information. We checked this, and dropped the connection if it did change it. Unfortunately, this is causing problems on some APs, e.g. on the Netgear WRT610NL: the beacons seem to always contain a bad channel and if we made a connection using a probe response (correct data) we drop the connection immediately and can basically not connect properly at all. Work around this by ignoring the HT primary channel information in beacons if we're already connected. Also print out more verbose messages in the other situations to help diagnose similar bugs quicker in the future. Cc: stable@vger.kernel.org [3.10] Acked-by: Andy Isaacson Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index e5c3cf405060..077a95360830 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -211,8 +211,9 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, struct ieee80211_channel *channel, const struct ieee80211_ht_operation *ht_oper, const struct ieee80211_vht_operation *vht_oper, - struct cfg80211_chan_def *chandef, bool verbose) + struct cfg80211_chan_def *chandef, bool tracking) { + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct cfg80211_chan_def vht_chandef; u32 ht_cfreq, ret; @@ -231,7 +232,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, ht_cfreq = ieee80211_channel_to_frequency(ht_oper->primary_chan, channel->band); /* check that channel matches the right operating channel */ - if (channel->center_freq != ht_cfreq) { + if (!tracking && channel->center_freq != ht_cfreq) { /* * It's possible that some APs are confused here; * Netgear WNDR3700 sometimes reports 4 higher than @@ -239,11 +240,10 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, * since we look at probe response/beacon data here * it should be OK. */ - if (verbose) - sdata_info(sdata, - "Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n", - channel->center_freq, ht_cfreq, - ht_oper->primary_chan, channel->band); + sdata_info(sdata, + "Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n", + channel->center_freq, ht_cfreq, + ht_oper->primary_chan, channel->band); ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; goto out; } @@ -297,7 +297,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, channel->band); break; default: - if (verbose) + if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) sdata_info(sdata, "AP VHT operation IE has invalid channel width (%d), disable VHT\n", vht_oper->chan_width); @@ -306,7 +306,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, } if (!cfg80211_chandef_valid(&vht_chandef)) { - if (verbose) + if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) sdata_info(sdata, "AP VHT information is invalid, disable VHT\n"); ret = IEEE80211_STA_DISABLE_VHT; @@ -319,7 +319,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, } if (!cfg80211_chandef_compatible(chandef, &vht_chandef)) { - if (verbose) + if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) sdata_info(sdata, "AP VHT information doesn't match HT, disable VHT\n"); ret = IEEE80211_STA_DISABLE_VHT; @@ -346,7 +346,7 @@ out: ret |= chandef_downgrade(chandef); } - if (chandef->width != vht_chandef.width && verbose) + if (chandef->width != vht_chandef.width && !tracking) sdata_info(sdata, "capabilities/regulatory prevented using AP HT/VHT configuration, downgraded\n"); @@ -386,7 +386,7 @@ static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata, /* calculate new channel (type) based on HT/VHT operation IEs */ flags = ieee80211_determine_chantype(sdata, sband, chan, ht_oper, - vht_oper, &chandef, false); + vht_oper, &chandef, true); /* * Downgrade the new channel if we associated with restricted @@ -3838,7 +3838,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, ifmgd->flags |= ieee80211_determine_chantype(sdata, sband, cbss->channel, ht_oper, vht_oper, - &chandef, true); + &chandef, false); sdata->needed_rx_chains = min(ieee80211_ht_vht_rx_chains(sdata, cbss), local->rx_chains); From 74418edec915d0f446debebde08d170c7b8ba0ee Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 30 Jul 2013 10:11:25 +0200 Subject: [PATCH 1164/3400] cfg80211: fix P2P GO interface teardown When a P2P GO interface goes down, cfg80211 doesn't properly tear it down, leading to warnings later. Add the GO interface type to the enumeration to tear it down like AP interfaces. Otherwise, we leave it pending and mac80211's state can get very confused, leading to warnings later. Cc: stable@vger.kernel.org Reported-by: Ilan Peer Tested-by: Ilan Peer Reviewed-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- net/wireless/core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/wireless/core.c b/net/wireless/core.c index 4f9f216665e9..a8c29fa4f1b3 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -765,6 +765,7 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev, cfg80211_leave_mesh(rdev, dev); break; case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_P2P_GO: cfg80211_stop_ap(rdev, dev); break; default: From ddfe49b42d8ad4bfdf92d63d4a74f162660d878d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 31 Jul 2013 20:52:03 +0200 Subject: [PATCH 1165/3400] mac80211: continue using disabled channels while connected In case the AP has different regulatory information than we do, it can happen that we connect to an AP based on e.g. the world roaming regulatory data, and then update our database with the AP's country information disables the channel the AP is using. If this happens on an HT AP, the bandwidth tracking code will hit the WARN_ON() and disconnect. Since that's not very useful, ignore the channel-disable flag in bandwidth tracking. Cc: stable@vger.kernel.org Reported-by: Chris Wright Tested-by: Chris Wright Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 077a95360830..cc9e02d79b55 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -335,8 +335,17 @@ out: if (ret & IEEE80211_STA_DISABLE_VHT) vht_chandef = *chandef; + /* + * Ignore the DISABLED flag when we're already connected and only + * tracking the APs beacon for bandwidth changes - otherwise we + * might get disconnected here if we connect to an AP, update our + * regulatory information based on the AP's country IE and the + * information we have is wrong/outdated and disables the channel + * that we're actually using for the connection to the AP. + */ while (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef, - IEEE80211_CHAN_DISABLED)) { + tracking ? 0 : + IEEE80211_CHAN_DISABLED)) { if (WARN_ON(chandef->width == NL80211_CHAN_WIDTH_20_NOHT)) { ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; From d010e5769a5ab2ae8d2bcb36e77b98172c24d80c Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Tue, 30 Jul 2013 10:32:30 +0800 Subject: [PATCH 1166/3400] PCI / ACPI: Use dev_dbg() instead of dev_info() in acpi_pci_set_power_state() acpi_pci_set_power_state() uses dev_info() to print diagnostic messages regarding ACPI power state changes of devices, but that results in too much not really interesting output into the kernel log in some cases. For this reason, change it to use dev_dbg() instead and prevent kernel log from being spammed. [rjw: Changelog] References: https://bugzilla.kernel.org/show_bug.cgi?id=60636 Suggested-by: Alan Stern Signed-off-by: Lan Tianyu Acked-by: Bjorn Helgaas Signed-off-by: Rafael J. Wysocki --- drivers/pci/pci-acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index c78cc432edab..fb3522957f01 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -210,7 +210,7 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state) } if (!error) - dev_info(&dev->dev, "power state changed by ACPI to %s\n", + dev_dbg(&dev->dev, "power state changed by ACPI to %s\n", acpi_power_state_string(state_conv[state])); return error; From 652d1100453a14bcc2b4514af79c701360836085 Mon Sep 17 00:00:00 2001 From: Stefan Assmann Date: Wed, 31 Jul 2013 16:47:56 -0600 Subject: [PATCH 1167/3400] PCI: Return -ENOSYS for SR-IOV operations on non-SR-IOV devices Change the return value to -ENOSYS if a device is not an SR-IOV PF. Previously we returned either -ENODEV or -EINVAL. Also have pci_sriov_get_totalvfs() return 0 in the error case to make the behaviour consistent whether CONFIG_PCI_IOV is enabled or not. Signed-off-by: Stefan Assmann Signed-off-by: Bjorn Helgaas --- drivers/pci/iov.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index e73bdae447cc..21a7182dccd4 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c @@ -323,7 +323,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn) if (!pdev->is_physfn) { pci_dev_put(pdev); - return -ENODEV; + return -ENOSYS; } rc = sysfs_create_link(&dev->dev.kobj, @@ -664,7 +664,7 @@ int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn) might_sleep(); if (!dev->is_physfn) - return -ENODEV; + return -ENOSYS; return sriov_enable(dev, nr_virtfn); } @@ -724,7 +724,7 @@ EXPORT_SYMBOL_GPL(pci_num_vf); * @dev: the PCI device * * Returns number of VFs belonging to this device that are assigned to a guest. - * If device is not a physical function returns -ENODEV. + * If device is not a physical function returns 0. */ int pci_vfs_assigned(struct pci_dev *dev) { @@ -769,12 +769,15 @@ EXPORT_SYMBOL_GPL(pci_vfs_assigned); * device's mutex held. * * Returns 0 if PF is an SRIOV-capable device and - * value of numvfs valid. If not a PF with VFS, return -EINVAL; + * value of numvfs valid. If not a PF return -ENOSYS; + * if numvfs is invalid return -EINVAL; * if VFs already enabled, return -EBUSY. */ int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs) { - if (!dev->is_physfn || (numvfs > dev->sriov->total_VFs)) + if (!dev->is_physfn) + return -ENOSYS; + if (numvfs > dev->sriov->total_VFs) return -EINVAL; /* Shouldn't change if VFs already enabled */ @@ -793,12 +796,12 @@ EXPORT_SYMBOL_GPL(pci_sriov_set_totalvfs); * * For a PCIe device with SRIOV support, return the PCIe * SRIOV capability value of TotalVFs or the value of driver_max_VFs - * if the driver reduced it. Otherwise, -EINVAL. + * if the driver reduced it. Otherwise 0. */ int pci_sriov_get_totalvfs(struct pci_dev *dev) { if (!dev->is_physfn) - return -EINVAL; + return 0; if (dev->sriov->driver_max_VFs) return dev->sriov->driver_max_VFs; From b662a8662436cd4815e1738d5f491a12dc289177 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Fri, 19 Jul 2013 13:12:59 +0200 Subject: [PATCH 1168/3400] ARM: clocksource: moxart: documentation: Fix device tree bindings document Fix device tree bindings document with the correct clock name. Signed-off-by: Jonas Jensen Signed-off-by: Daniel Lezcano --- Documentation/devicetree/bindings/timer/moxa,moxart-timer.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/timer/moxa,moxart-timer.txt b/Documentation/devicetree/bindings/timer/moxa,moxart-timer.txt index 77c4cfa198ee..ad0bf7f1a7e7 100644 --- a/Documentation/devicetree/bindings/timer/moxa,moxart-timer.txt +++ b/Documentation/devicetree/bindings/timer/moxa,moxart-timer.txt @@ -5,7 +5,7 @@ Required properties: - compatible : Should be "moxa,moxart-timer" - reg : Should contain registers location and length - interrupts : Should contain the timer interrupt number -- clocks : Should contain phandle for APB clock "clkapb" +- clocks : Should contain phandle for the MOXA ART core clock "coreclk" Example: @@ -13,5 +13,5 @@ Example: compatible = "moxa,moxart-timer"; reg = <0x98400000 0x42>; interrupts = <19 1>; - clocks = <&clkapb>; + clocks = <&coreclk>; }; From adf157ebf6097aa2abc7f05120e7dda6ed238252 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Fri, 26 Jul 2013 16:03:38 +0200 Subject: [PATCH 1169/3400] ARM: clocksource: moxart: Add bitops.h include bitops.h included implicitly, add #include Signed-off-by: Jonas Jensen Signed-off-by: Daniel Lezcano --- drivers/clocksource/moxart_timer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clocksource/moxart_timer.c b/drivers/clocksource/moxart_timer.c index 08a5943b3e42..5eb2c35932b1 100644 --- a/drivers/clocksource/moxart_timer.c +++ b/drivers/clocksource/moxart_timer.c @@ -20,6 +20,7 @@ #include #include #include +#include #define TIMER1_BASE 0x00 #define TIMER2_BASE 0x10 From 766acb88a773dcbc98f2ae8d7ef8c147e2dccd99 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Fri, 26 Jul 2013 16:17:15 +0200 Subject: [PATCH 1170/3400] ARM: clocksource: moxart: documentation: Update device tree bindings document 1. describe compatible variable "Must be" instead of "Should be". 2. change description so it's from the point of view of the device Signed-off-by: Jonas Jensen Signed-off-by: Daniel Lezcano --- Documentation/devicetree/bindings/timer/moxa,moxart-timer.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/timer/moxa,moxart-timer.txt b/Documentation/devicetree/bindings/timer/moxa,moxart-timer.txt index ad0bf7f1a7e7..da2d510cae47 100644 --- a/Documentation/devicetree/bindings/timer/moxa,moxart-timer.txt +++ b/Documentation/devicetree/bindings/timer/moxa,moxart-timer.txt @@ -2,10 +2,10 @@ MOXA ART timer Required properties: -- compatible : Should be "moxa,moxart-timer" +- compatible : Must be "moxa,moxart-timer" - reg : Should contain registers location and length - interrupts : Should contain the timer interrupt number -- clocks : Should contain phandle for the MOXA ART core clock "coreclk" +- clocks : Should contain phandle for the clock that drives the counter Example: From e09f3cc0184d6b5c3816f921b7ffb67623e5e834 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 18 Jul 2013 16:59:28 -0700 Subject: [PATCH 1171/3400] clocksource: arch_timer: Make register accessors less error-prone Using an enum for the register we wish to access allows newer compilers to determine if we've forgotten a case in our switch statement. This allows us to remove the BUILD_BUG() instances in the arm64 port, avoiding problems where optimizations may not happen. To try and force better code generation we're currently marking the accessor functions as inline, but newer compilers can ignore the inline keyword unless it's marked __always_inline. Luckily on arm and arm64 inline is __always_inline, but let's make everything __always_inline to be explicit. Suggested-by: Thomas Gleixner Cc: Thomas Gleixner Cc: Mark Rutland Cc: Marc Zyngier Signed-off-by: Stephen Boyd Signed-off-by: Daniel Lezcano Acked-by: Mark Rutland --- arch/arm/include/asm/arch_timer.h | 14 ++++++-------- arch/arm64/include/asm/arch_timer.h | 23 +++++++++-------------- drivers/clocksource/arm_arch_timer.c | 6 +++--- include/clocksource/arm_arch_timer.h | 6 ++++-- 4 files changed, 22 insertions(+), 27 deletions(-) diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h index accefe099182..aeb93f38e9c9 100644 --- a/arch/arm/include/asm/arch_timer.h +++ b/arch/arm/include/asm/arch_timer.h @@ -17,7 +17,8 @@ int arch_timer_arch_init(void); * nicely work out which register we want, and chuck away the rest of * the code. At least it does so with a recent GCC (4.6.3). */ -static inline void arch_timer_reg_write(const int access, const int reg, u32 val) +static __always_inline +void arch_timer_reg_write(int access, enum arch_timer_reg reg, u32 val) { if (access == ARCH_TIMER_PHYS_ACCESS) { switch (reg) { @@ -28,9 +29,7 @@ static inline void arch_timer_reg_write(const int access, const int reg, u32 val asm volatile("mcr p15, 0, %0, c14, c2, 0" : : "r" (val)); break; } - } - - if (access == ARCH_TIMER_VIRT_ACCESS) { + } else if (access == ARCH_TIMER_VIRT_ACCESS) { switch (reg) { case ARCH_TIMER_REG_CTRL: asm volatile("mcr p15, 0, %0, c14, c3, 1" : : "r" (val)); @@ -44,7 +43,8 @@ static inline void arch_timer_reg_write(const int access, const int reg, u32 val isb(); } -static inline u32 arch_timer_reg_read(const int access, const int reg) +static __always_inline +u32 arch_timer_reg_read(int access, enum arch_timer_reg reg) { u32 val = 0; @@ -57,9 +57,7 @@ static inline u32 arch_timer_reg_read(const int access, const int reg) asm volatile("mrc p15, 0, %0, c14, c2, 0" : "=r" (val)); break; } - } - - if (access == ARCH_TIMER_VIRT_ACCESS) { + } else if (access == ARCH_TIMER_VIRT_ACCESS) { switch (reg) { case ARCH_TIMER_REG_CTRL: asm volatile("mrc p15, 0, %0, c14, c3, 1" : "=r" (val)); diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h index d56ed11ba9a3..dbca77168e81 100644 --- a/arch/arm64/include/asm/arch_timer.h +++ b/arch/arm64/include/asm/arch_timer.h @@ -26,7 +26,13 @@ #include -static inline void arch_timer_reg_write(int access, int reg, u32 val) +/* + * These register accessors are marked inline so the compiler can + * nicely work out which register we want, and chuck away the rest of + * the code. + */ +static __always_inline +void arch_timer_reg_write(int access, enum arch_timer_reg reg, u32 val) { if (access == ARCH_TIMER_PHYS_ACCESS) { switch (reg) { @@ -36,8 +42,6 @@ static inline void arch_timer_reg_write(int access, int reg, u32 val) case ARCH_TIMER_REG_TVAL: asm volatile("msr cntp_tval_el0, %0" : : "r" (val)); break; - default: - BUILD_BUG(); } } else if (access == ARCH_TIMER_VIRT_ACCESS) { switch (reg) { @@ -47,17 +51,14 @@ static inline void arch_timer_reg_write(int access, int reg, u32 val) case ARCH_TIMER_REG_TVAL: asm volatile("msr cntv_tval_el0, %0" : : "r" (val)); break; - default: - BUILD_BUG(); } - } else { - BUILD_BUG(); } isb(); } -static inline u32 arch_timer_reg_read(int access, int reg) +static __always_inline +u32 arch_timer_reg_read(int access, enum arch_timer_reg reg) { u32 val; @@ -69,8 +70,6 @@ static inline u32 arch_timer_reg_read(int access, int reg) case ARCH_TIMER_REG_TVAL: asm volatile("mrs %0, cntp_tval_el0" : "=r" (val)); break; - default: - BUILD_BUG(); } } else if (access == ARCH_TIMER_VIRT_ACCESS) { switch (reg) { @@ -80,11 +79,7 @@ static inline u32 arch_timer_reg_read(int access, int reg) case ARCH_TIMER_REG_TVAL: asm volatile("mrs %0, cntv_tval_el0" : "=r" (val)); break; - default: - BUILD_BUG(); } - } else { - BUILD_BUG(); } return val; diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 053d846ab5b1..aa0703847e5d 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -43,7 +43,7 @@ static bool arch_timer_use_virtual = true; * Architected system timer support. */ -static inline irqreturn_t timer_handler(const int access, +static __always_inline irqreturn_t timer_handler(const int access, struct clock_event_device *evt) { unsigned long ctrl; @@ -72,7 +72,7 @@ static irqreturn_t arch_timer_handler_phys(int irq, void *dev_id) return timer_handler(ARCH_TIMER_PHYS_ACCESS, evt); } -static inline void timer_set_mode(const int access, int mode) +static __always_inline void timer_set_mode(const int access, int mode) { unsigned long ctrl; switch (mode) { @@ -99,7 +99,7 @@ static void arch_timer_set_mode_phys(enum clock_event_mode mode, timer_set_mode(ARCH_TIMER_PHYS_ACCESS, mode); } -static inline void set_next_event(const int access, unsigned long evt) +static __always_inline void set_next_event(const int access, unsigned long evt) { unsigned long ctrl; ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL); diff --git a/include/clocksource/arm_arch_timer.h b/include/clocksource/arm_arch_timer.h index c463ce990c48..f3da817b9b8e 100644 --- a/include/clocksource/arm_arch_timer.h +++ b/include/clocksource/arm_arch_timer.h @@ -23,8 +23,10 @@ #define ARCH_TIMER_CTRL_IT_MASK (1 << 1) #define ARCH_TIMER_CTRL_IT_STAT (1 << 2) -#define ARCH_TIMER_REG_CTRL 0 -#define ARCH_TIMER_REG_TVAL 1 +enum arch_timer_reg { + ARCH_TIMER_REG_CTRL, + ARCH_TIMER_REG_TVAL, +}; #define ARCH_TIMER_PHYS_ACCESS 0 #define ARCH_TIMER_VIRT_ACCESS 1 From 1ff99ea65687d921cb71f330491ec4205c00eb9f Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 18 Jul 2013 16:59:30 -0700 Subject: [PATCH 1172/3400] clocksource: arch_timer: Pass clock event to set_mode callback There isn't any reason why we don't pass the event here and we'll need it in the near future for memory mapped arch timers anyway. Cc: Mark Rutland Cc: Marc Zyngier Signed-off-by: Stephen Boyd Signed-off-by: Daniel Lezcano Acked-by: Mark Rutland --- drivers/clocksource/arm_arch_timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index aa0703847e5d..7624ba574144 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -140,7 +140,7 @@ static int __cpuinit arch_timer_setup(struct clock_event_device *clk) clk->cpumask = cpumask_of(smp_processor_id()); - clk->set_mode(CLOCK_EVT_MODE_SHUTDOWN, NULL); + clk->set_mode(CLOCK_EVT_MODE_SHUTDOWN, clk); clockevents_config_and_register(clk, arch_timer_rate, 0xf, 0x7fffffff); From d53ef114cf40a043e3cc3fa70dbcdfb268a7e4dc Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 18 Jul 2013 16:59:29 -0700 Subject: [PATCH 1173/3400] Documentation: Add memory mapped ARM architected timer binding Add a binding for the arm architected timer hardware's memory mapped interface. The mmio timer hardware is made up of one base frame and a collection of up to 8 timer frames, where each of the 8 timer frames can have either one or two views. A frame typically maps to a privilege level (user/kernel, hypervisor, secure). The first view has full access to the registers within a frame, while the second view can be restricted to particular registers within a frame. Each frame must support a physical timer. It's optional for a frame to support a virtual timer. Cc: devicetree-discuss@lists.ozlabs.org Cc: Marc Zyngier Cc: Mark Rutland Cc: Rob Herring Signed-off-by: Stephen Boyd Signed-off-by: Daniel Lezcano Acked-by: Mark Rutland --- .../devicetree/bindings/arm/arch_timer.txt | 59 ++++++++++++++++++- 1 file changed, 56 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/arm/arch_timer.txt b/Documentation/devicetree/bindings/arm/arch_timer.txt index 20746e5abe6f..06fc7602593a 100644 --- a/Documentation/devicetree/bindings/arm/arch_timer.txt +++ b/Documentation/devicetree/bindings/arm/arch_timer.txt @@ -1,10 +1,14 @@ * ARM architected timer -ARM cores may have a per-core architected timer, which provides per-cpu timers. +ARM cores may have a per-core architected timer, which provides per-cpu timers, +or a memory mapped architected timer, which provides up to 8 frames with a +physical and optional virtual timer per frame. -The timer is attached to a GIC to deliver its per-processor interrupts. +The per-core architected timer is attached to a GIC to deliver its +per-processor interrupts via PPIs. The memory mapped timer is attached to a GIC +to deliver its interrupts via SPIs. -** Timer node properties: +** CP15 Timer node properties: - compatible : Should at least contain one of "arm,armv7-timer" @@ -26,3 +30,52 @@ Example: <1 10 0xf08>; clock-frequency = <100000000>; }; + +** Memory mapped timer node properties: + +- compatible : Should at least contain "arm,armv7-timer-mem". + +- clock-frequency : The frequency of the main counter, in Hz. Optional. + +- reg : The control frame base address. + +Note that #address-cells, #size-cells, and ranges shall be present to ensure +the CPU can address a frame's registers. + +A timer node has up to 8 frame sub-nodes, each with the following properties: + +- frame-number: 0 to 7. + +- interrupts : Interrupt list for physical and virtual timers in that order. + The virtual timer interrupt is optional. + +- reg : The first and second view base addresses in that order. The second view + base address is optional. + +- status : "disabled" indicates the frame is not available for use. Optional. + +Example: + + timer@f0000000 { + compatible = "arm,armv7-timer-mem"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + reg = <0xf0000000 0x1000>; + clock-frequency = <50000000>; + + frame@f0001000 { + frame-number = <0> + interrupts = <0 13 0x8>, + <0 14 0x8>; + reg = <0xf0001000 0x1000>, + <0xf0002000 0x1000>; + }; + + frame@f0003000 { + frame-number = <1> + interrupts = <0 15 0x8>; + reg = <0xf0003000 0x1000>; + status = "disabled"; + }; + }; From 60faddf6eb3aba16068032bdcf35e18ace4bfb21 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 18 Jul 2013 16:59:31 -0700 Subject: [PATCH 1174/3400] clocksource: arch_timer: Push the read/write wrappers deeper We're going to introduce support to read and write the memory mapped timer registers in the next patch, so push the cp15 read/write functions one level deeper. This simplifies the next patch and makes it clearer what's going on. Cc: Mark Rutland Cc: Marc Zyngier Signed-off-by: Stephen Boyd Signed-off-by: Daniel Lezcano Acked-by: Mark Rutland --- arch/arm/include/asm/arch_timer.h | 4 +-- arch/arm64/include/asm/arch_timer.h | 4 +-- drivers/clocksource/arm_arch_timer.c | 46 +++++++++++++++++++--------- 3 files changed, 35 insertions(+), 19 deletions(-) diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h index aeb93f38e9c9..556094689724 100644 --- a/arch/arm/include/asm/arch_timer.h +++ b/arch/arm/include/asm/arch_timer.h @@ -18,7 +18,7 @@ int arch_timer_arch_init(void); * the code. At least it does so with a recent GCC (4.6.3). */ static __always_inline -void arch_timer_reg_write(int access, enum arch_timer_reg reg, u32 val) +void arch_timer_reg_write_cp15(int access, enum arch_timer_reg reg, u32 val) { if (access == ARCH_TIMER_PHYS_ACCESS) { switch (reg) { @@ -44,7 +44,7 @@ void arch_timer_reg_write(int access, enum arch_timer_reg reg, u32 val) } static __always_inline -u32 arch_timer_reg_read(int access, enum arch_timer_reg reg) +u32 arch_timer_reg_read_cp15(int access, enum arch_timer_reg reg) { u32 val = 0; diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h index dbca77168e81..7181e777c2c5 100644 --- a/arch/arm64/include/asm/arch_timer.h +++ b/arch/arm64/include/asm/arch_timer.h @@ -32,7 +32,7 @@ * the code. */ static __always_inline -void arch_timer_reg_write(int access, enum arch_timer_reg reg, u32 val) +void arch_timer_reg_write_cp15(int access, enum arch_timer_reg reg, u32 val) { if (access == ARCH_TIMER_PHYS_ACCESS) { switch (reg) { @@ -58,7 +58,7 @@ void arch_timer_reg_write(int access, enum arch_timer_reg reg, u32 val) } static __always_inline -u32 arch_timer_reg_read(int access, enum arch_timer_reg reg) +u32 arch_timer_reg_read_cp15(int access, enum arch_timer_reg reg) { u32 val; diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 7624ba574144..a9ca28447b49 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -43,14 +43,28 @@ static bool arch_timer_use_virtual = true; * Architected system timer support. */ +static __always_inline +void arch_timer_reg_write(int access, enum arch_timer_reg reg, u32 val, + struct clock_event_device *clk) +{ + arch_timer_reg_write_cp15(access, reg, val); +} + +static __always_inline +u32 arch_timer_reg_read(int access, enum arch_timer_reg reg, + struct clock_event_device *clk) +{ + return arch_timer_reg_read_cp15(access, reg); +} + static __always_inline irqreturn_t timer_handler(const int access, struct clock_event_device *evt) { unsigned long ctrl; - ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL); + ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, evt); if (ctrl & ARCH_TIMER_CTRL_IT_STAT) { ctrl |= ARCH_TIMER_CTRL_IT_MASK; - arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl); + arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, evt); evt->event_handler(evt); return IRQ_HANDLED; } @@ -72,15 +86,16 @@ static irqreturn_t arch_timer_handler_phys(int irq, void *dev_id) return timer_handler(ARCH_TIMER_PHYS_ACCESS, evt); } -static __always_inline void timer_set_mode(const int access, int mode) +static __always_inline void timer_set_mode(const int access, int mode, + struct clock_event_device *clk) { unsigned long ctrl; switch (mode) { case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_SHUTDOWN: - ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL); + ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, clk); ctrl &= ~ARCH_TIMER_CTRL_ENABLE; - arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl); + arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk); break; default: break; @@ -90,36 +105,37 @@ static __always_inline void timer_set_mode(const int access, int mode) static void arch_timer_set_mode_virt(enum clock_event_mode mode, struct clock_event_device *clk) { - timer_set_mode(ARCH_TIMER_VIRT_ACCESS, mode); + timer_set_mode(ARCH_TIMER_VIRT_ACCESS, mode, clk); } static void arch_timer_set_mode_phys(enum clock_event_mode mode, struct clock_event_device *clk) { - timer_set_mode(ARCH_TIMER_PHYS_ACCESS, mode); + timer_set_mode(ARCH_TIMER_PHYS_ACCESS, mode, clk); } -static __always_inline void set_next_event(const int access, unsigned long evt) +static __always_inline void set_next_event(const int access, unsigned long evt, + struct clock_event_device *clk) { unsigned long ctrl; - ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL); + ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL, clk); ctrl |= ARCH_TIMER_CTRL_ENABLE; ctrl &= ~ARCH_TIMER_CTRL_IT_MASK; - arch_timer_reg_write(access, ARCH_TIMER_REG_TVAL, evt); - arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl); + arch_timer_reg_write(access, ARCH_TIMER_REG_TVAL, evt, clk); + arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl, clk); } static int arch_timer_set_next_event_virt(unsigned long evt, - struct clock_event_device *unused) + struct clock_event_device *clk) { - set_next_event(ARCH_TIMER_VIRT_ACCESS, evt); + set_next_event(ARCH_TIMER_VIRT_ACCESS, evt, clk); return 0; } static int arch_timer_set_next_event_phys(unsigned long evt, - struct clock_event_device *unused) + struct clock_event_device *clk) { - set_next_event(ARCH_TIMER_PHYS_ACCESS, evt); + set_next_event(ARCH_TIMER_PHYS_ACCESS, evt, clk); return 0; } From 220069945b298d3998c6598b081c466dca259929 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 18 Jul 2013 16:59:32 -0700 Subject: [PATCH 1175/3400] clocksource: arch_timer: Add support for memory mapped timers Add support for the memory mapped timers by filling in the read/write functions and adding some parsing code. Note that we only register one clocksource, preferring the cp15 based clocksource over the mmio one. To keep things simple we register one global clockevent. This covers the case of UP and SMP systems with only mmio hardware and systems where the memory mapped timers are used as the broadcast timer in low power modes. The DT binding allows for per-CPU memory mapped timers in case we want to support that in the future, but the code isn't added here. We also don't do much for hypervisor support, although it should be possible to support it by searching for at least two frames where one frame has the virtual capability and then updating KVM timers to support it. Cc: Mark Rutland Cc: Marc Zyngier Cc: Rob Herring Signed-off-by: Stephen Boyd Signed-off-by: Daniel Lezcano Acked-by: Mark Rutland --- drivers/clocksource/arm_arch_timer.c | 404 +++++++++++++++++++++++---- include/clocksource/arm_arch_timer.h | 4 +- 2 files changed, 351 insertions(+), 57 deletions(-) diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index a9ca28447b49..b3df46d9918b 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -16,13 +16,39 @@ #include #include #include +#include #include +#include #include #include #include +#define CNTTIDR 0x08 +#define CNTTIDR_VIRT(n) (BIT(1) << ((n) * 4)) + +#define CNTVCT_LO 0x08 +#define CNTVCT_HI 0x0c +#define CNTFRQ 0x10 +#define CNTP_TVAL 0x28 +#define CNTP_CTL 0x2c +#define CNTV_TVAL 0x38 +#define CNTV_CTL 0x3c + +#define ARCH_CP15_TIMER BIT(0) +#define ARCH_MEM_TIMER BIT(1) +static unsigned arch_timers_present __initdata; + +static void __iomem *arch_counter_base; + +struct arch_timer { + void __iomem *base; + struct clock_event_device evt; +}; + +#define to_arch_timer(e) container_of(e, struct arch_timer, evt) + static u32 arch_timer_rate; enum ppi_nr { @@ -38,6 +64,7 @@ static int arch_timer_ppi[MAX_TIMER_PPI]; static struct clock_event_device __percpu *arch_timer_evt; static bool arch_timer_use_virtual = true; +static bool arch_timer_mem_use_virtual; /* * Architected system timer support. @@ -47,14 +74,62 @@ static __always_inline void arch_timer_reg_write(int access, enum arch_timer_reg reg, u32 val, struct clock_event_device *clk) { - arch_timer_reg_write_cp15(access, reg, val); + if (access == ARCH_TIMER_MEM_PHYS_ACCESS) { + struct arch_timer *timer = to_arch_timer(clk); + switch (reg) { + case ARCH_TIMER_REG_CTRL: + writel_relaxed(val, timer->base + CNTP_CTL); + break; + case ARCH_TIMER_REG_TVAL: + writel_relaxed(val, timer->base + CNTP_TVAL); + break; + } + } else if (access == ARCH_TIMER_MEM_VIRT_ACCESS) { + struct arch_timer *timer = to_arch_timer(clk); + switch (reg) { + case ARCH_TIMER_REG_CTRL: + writel_relaxed(val, timer->base + CNTV_CTL); + break; + case ARCH_TIMER_REG_TVAL: + writel_relaxed(val, timer->base + CNTV_TVAL); + break; + } + } else { + arch_timer_reg_write_cp15(access, reg, val); + } } static __always_inline u32 arch_timer_reg_read(int access, enum arch_timer_reg reg, struct clock_event_device *clk) { - return arch_timer_reg_read_cp15(access, reg); + u32 val; + + if (access == ARCH_TIMER_MEM_PHYS_ACCESS) { + struct arch_timer *timer = to_arch_timer(clk); + switch (reg) { + case ARCH_TIMER_REG_CTRL: + val = readl_relaxed(timer->base + CNTP_CTL); + break; + case ARCH_TIMER_REG_TVAL: + val = readl_relaxed(timer->base + CNTP_TVAL); + break; + } + } else if (access == ARCH_TIMER_MEM_VIRT_ACCESS) { + struct arch_timer *timer = to_arch_timer(clk); + switch (reg) { + case ARCH_TIMER_REG_CTRL: + val = readl_relaxed(timer->base + CNTV_CTL); + break; + case ARCH_TIMER_REG_TVAL: + val = readl_relaxed(timer->base + CNTV_TVAL); + break; + } + } else { + val = arch_timer_reg_read_cp15(access, reg); + } + + return val; } static __always_inline irqreturn_t timer_handler(const int access, @@ -86,6 +161,20 @@ static irqreturn_t arch_timer_handler_phys(int irq, void *dev_id) return timer_handler(ARCH_TIMER_PHYS_ACCESS, evt); } +static irqreturn_t arch_timer_handler_phys_mem(int irq, void *dev_id) +{ + struct clock_event_device *evt = dev_id; + + return timer_handler(ARCH_TIMER_MEM_PHYS_ACCESS, evt); +} + +static irqreturn_t arch_timer_handler_virt_mem(int irq, void *dev_id) +{ + struct clock_event_device *evt = dev_id; + + return timer_handler(ARCH_TIMER_MEM_VIRT_ACCESS, evt); +} + static __always_inline void timer_set_mode(const int access, int mode, struct clock_event_device *clk) { @@ -114,6 +203,18 @@ static void arch_timer_set_mode_phys(enum clock_event_mode mode, timer_set_mode(ARCH_TIMER_PHYS_ACCESS, mode, clk); } +static void arch_timer_set_mode_virt_mem(enum clock_event_mode mode, + struct clock_event_device *clk) +{ + timer_set_mode(ARCH_TIMER_MEM_VIRT_ACCESS, mode, clk); +} + +static void arch_timer_set_mode_phys_mem(enum clock_event_mode mode, + struct clock_event_device *clk) +{ + timer_set_mode(ARCH_TIMER_MEM_PHYS_ACCESS, mode, clk); +} + static __always_inline void set_next_event(const int access, unsigned long evt, struct clock_event_device *clk) { @@ -139,27 +240,62 @@ static int arch_timer_set_next_event_phys(unsigned long evt, return 0; } -static int __cpuinit arch_timer_setup(struct clock_event_device *clk) +static int arch_timer_set_next_event_virt_mem(unsigned long evt, + struct clock_event_device *clk) { - clk->features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_C3STOP; - clk->name = "arch_sys_timer"; - clk->rating = 450; - if (arch_timer_use_virtual) { - clk->irq = arch_timer_ppi[VIRT_PPI]; - clk->set_mode = arch_timer_set_mode_virt; - clk->set_next_event = arch_timer_set_next_event_virt; - } else { - clk->irq = arch_timer_ppi[PHYS_SECURE_PPI]; - clk->set_mode = arch_timer_set_mode_phys; - clk->set_next_event = arch_timer_set_next_event_phys; - } + set_next_event(ARCH_TIMER_MEM_VIRT_ACCESS, evt, clk); + return 0; +} - clk->cpumask = cpumask_of(smp_processor_id()); +static int arch_timer_set_next_event_phys_mem(unsigned long evt, + struct clock_event_device *clk) +{ + set_next_event(ARCH_TIMER_MEM_PHYS_ACCESS, evt, clk); + return 0; +} + +static void __cpuinit __arch_timer_setup(unsigned type, + struct clock_event_device *clk) +{ + clk->features = CLOCK_EVT_FEAT_ONESHOT; + + if (type == ARCH_CP15_TIMER) { + clk->features |= CLOCK_EVT_FEAT_C3STOP; + clk->name = "arch_sys_timer"; + clk->rating = 450; + clk->cpumask = cpumask_of(smp_processor_id()); + if (arch_timer_use_virtual) { + clk->irq = arch_timer_ppi[VIRT_PPI]; + clk->set_mode = arch_timer_set_mode_virt; + clk->set_next_event = arch_timer_set_next_event_virt; + } else { + clk->irq = arch_timer_ppi[PHYS_SECURE_PPI]; + clk->set_mode = arch_timer_set_mode_phys; + clk->set_next_event = arch_timer_set_next_event_phys; + } + } else { + clk->name = "arch_mem_timer"; + clk->rating = 400; + clk->cpumask = cpu_all_mask; + if (arch_timer_mem_use_virtual) { + clk->set_mode = arch_timer_set_mode_virt_mem; + clk->set_next_event = + arch_timer_set_next_event_virt_mem; + } else { + clk->set_mode = arch_timer_set_mode_phys_mem; + clk->set_next_event = + arch_timer_set_next_event_phys_mem; + } + } clk->set_mode(CLOCK_EVT_MODE_SHUTDOWN, clk); - clockevents_config_and_register(clk, arch_timer_rate, - 0xf, 0x7fffffff); + clockevents_config_and_register(clk, arch_timer_rate, 0xf, 0x7fffffff); +} + +static int __cpuinit arch_timer_setup(struct clock_event_device *clk) +{ + __arch_timer_setup(ARCH_CP15_TIMER, clk); if (arch_timer_use_virtual) enable_percpu_irq(arch_timer_ppi[VIRT_PPI], 0); @@ -174,27 +310,41 @@ static int __cpuinit arch_timer_setup(struct clock_event_device *clk) return 0; } -static int arch_timer_available(void) +static void +arch_timer_detect_rate(void __iomem *cntbase, struct device_node *np) { - u32 freq; + /* Who has more than one independent system counter? */ + if (arch_timer_rate) + return; - if (arch_timer_rate == 0) { - freq = arch_timer_get_cntfrq(); - - /* Check the timer frequency. */ - if (freq == 0) { - pr_warn("Architected timer frequency not available\n"); - return -EINVAL; - } - - arch_timer_rate = freq; + /* Try to determine the frequency from the device tree or CNTFRQ */ + if (of_property_read_u32(np, "clock-frequency", &arch_timer_rate)) { + if (cntbase) + arch_timer_rate = readl_relaxed(cntbase + CNTFRQ); + else + arch_timer_rate = arch_timer_get_cntfrq(); } - pr_info_once("Architected local timer running at %lu.%02luMHz (%s).\n", + /* Check the timer frequency. */ + if (arch_timer_rate == 0) + pr_warn("Architected timer frequency not available\n"); +} + +static void arch_timer_banner(unsigned type) +{ + pr_info("Architected %s%s%s timer(s) running at %lu.%02luMHz (%s%s%s).\n", + type & ARCH_CP15_TIMER ? "cp15" : "", + type == (ARCH_CP15_TIMER | ARCH_MEM_TIMER) ? " and " : "", + type & ARCH_MEM_TIMER ? "mmio" : "", (unsigned long)arch_timer_rate / 1000000, (unsigned long)(arch_timer_rate / 10000) % 100, - arch_timer_use_virtual ? "virt" : "phys"); - return 0; + type & ARCH_CP15_TIMER ? + arch_timer_use_virtual ? "virt" : "phys" : + "", + type == (ARCH_CP15_TIMER | ARCH_MEM_TIMER) ? "/" : "", + type & ARCH_MEM_TIMER ? + arch_timer_mem_use_virtual ? "virt" : "phys" : + ""); } u32 arch_timer_get_rate(void) @@ -202,19 +352,35 @@ u32 arch_timer_get_rate(void) return arch_timer_rate; } -u64 arch_timer_read_counter(void) +static u64 arch_counter_get_cntvct_mem(void) { - return arch_counter_get_cntvct(); + u32 vct_lo, vct_hi, tmp_hi; + + do { + vct_hi = readl_relaxed(arch_counter_base + CNTVCT_HI); + vct_lo = readl_relaxed(arch_counter_base + CNTVCT_LO); + tmp_hi = readl_relaxed(arch_counter_base + CNTVCT_HI); + } while (vct_hi != tmp_hi); + + return ((u64) vct_hi << 32) | vct_lo; } +/* + * Default to cp15 based access because arm64 uses this function for + * sched_clock() before DT is probed and the cp15 method is guaranteed + * to exist on arm64. arm doesn't use this before DT is probed so even + * if we don't have the cp15 accessors we won't have a problem. + */ +u64 (*arch_timer_read_counter)(void) = arch_counter_get_cntvct; + static cycle_t arch_counter_read(struct clocksource *cs) { - return arch_counter_get_cntvct(); + return arch_timer_read_counter(); } static cycle_t arch_counter_read_cc(const struct cyclecounter *cc) { - return arch_counter_get_cntvct(); + return arch_timer_read_counter(); } static struct clocksource clocksource_counter = { @@ -237,6 +403,23 @@ struct timecounter *arch_timer_get_timecounter(void) return &timecounter; } +static void __init arch_counter_register(unsigned type) +{ + u64 start_count; + + /* Register the CP15 based counter if we have one */ + if (type & ARCH_CP15_TIMER) + arch_timer_read_counter = arch_counter_get_cntvct; + else + arch_timer_read_counter = arch_counter_get_cntvct_mem; + + start_count = arch_timer_read_counter(); + clocksource_register_hz(&clocksource_counter, arch_timer_rate); + cyclecounter.mult = clocksource_counter.mult; + cyclecounter.shift = clocksource_counter.shift; + timecounter_init(&timecounter, &cyclecounter, start_count); +} + static void __cpuinit arch_timer_stop(struct clock_event_device *clk) { pr_debug("arch_timer_teardown disable IRQ%d cpu #%d\n", @@ -281,22 +464,12 @@ static int __init arch_timer_register(void) int err; int ppi; - err = arch_timer_available(); - if (err) - goto out; - arch_timer_evt = alloc_percpu(struct clock_event_device); if (!arch_timer_evt) { err = -ENOMEM; goto out; } - clocksource_register_hz(&clocksource_counter, arch_timer_rate); - cyclecounter.mult = clocksource_counter.mult; - cyclecounter.shift = clocksource_counter.shift; - timecounter_init(&timecounter, &cyclecounter, - arch_counter_get_cntvct()); - if (arch_timer_use_virtual) { ppi = arch_timer_ppi[VIRT_PPI]; err = request_percpu_irq(ppi, arch_timer_handler_virt, @@ -347,24 +520,77 @@ out: return err; } +static int __init arch_timer_mem_register(void __iomem *base, unsigned int irq) +{ + int ret; + irq_handler_t func; + struct arch_timer *t; + + t = kzalloc(sizeof(*t), GFP_KERNEL); + if (!t) + return -ENOMEM; + + t->base = base; + t->evt.irq = irq; + __arch_timer_setup(ARCH_MEM_TIMER, &t->evt); + + if (arch_timer_mem_use_virtual) + func = arch_timer_handler_virt_mem; + else + func = arch_timer_handler_phys_mem; + + ret = request_irq(irq, func, IRQF_TIMER, "arch_mem_timer", &t->evt); + if (ret) { + pr_err("arch_timer: Failed to request mem timer irq\n"); + kfree(t); + } + + return ret; +} + +static const struct of_device_id arch_timer_of_match[] __initconst = { + { .compatible = "arm,armv7-timer", }, + { .compatible = "arm,armv8-timer", }, + {}, +}; + +static const struct of_device_id arch_timer_mem_of_match[] __initconst = { + { .compatible = "arm,armv7-timer-mem", }, + {}, +}; + +static void __init arch_timer_common_init(void) +{ + unsigned mask = ARCH_CP15_TIMER | ARCH_MEM_TIMER; + + /* Wait until both nodes are probed if we have two timers */ + if ((arch_timers_present & mask) != mask) { + if (of_find_matching_node(NULL, arch_timer_mem_of_match) && + !(arch_timers_present & ARCH_MEM_TIMER)) + return; + if (of_find_matching_node(NULL, arch_timer_of_match) && + !(arch_timers_present & ARCH_CP15_TIMER)) + return; + } + + arch_timer_banner(arch_timers_present); + arch_counter_register(arch_timers_present); + arch_timer_arch_init(); +} + static void __init arch_timer_init(struct device_node *np) { - u32 freq; int i; - if (arch_timer_get_rate()) { + if (arch_timers_present & ARCH_CP15_TIMER) { pr_warn("arch_timer: multiple nodes in dt, skipping\n"); return; } - /* Try to determine the frequency from the device tree or CNTFRQ */ - if (!of_property_read_u32(np, "clock-frequency", &freq)) - arch_timer_rate = freq; - + arch_timers_present |= ARCH_CP15_TIMER; for (i = PHYS_SECURE_PPI; i < MAX_TIMER_PPI; i++) arch_timer_ppi[i] = irq_of_parse_and_map(np, i); - - of_node_put(np); + arch_timer_detect_rate(NULL, np); /* * If HYP mode is available, we know that the physical timer @@ -385,7 +611,73 @@ static void __init arch_timer_init(struct device_node *np) } arch_timer_register(); - arch_timer_arch_init(); + arch_timer_common_init(); } CLOCKSOURCE_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", arch_timer_init); CLOCKSOURCE_OF_DECLARE(armv8_arch_timer, "arm,armv8-timer", arch_timer_init); + +static void __init arch_timer_mem_init(struct device_node *np) +{ + struct device_node *frame, *best_frame = NULL; + void __iomem *cntctlbase, *base; + unsigned int irq; + u32 cnttidr; + + arch_timers_present |= ARCH_MEM_TIMER; + cntctlbase = of_iomap(np, 0); + if (!cntctlbase) { + pr_err("arch_timer: Can't find CNTCTLBase\n"); + return; + } + + cnttidr = readl_relaxed(cntctlbase + CNTTIDR); + iounmap(cntctlbase); + + /* + * Try to find a virtual capable frame. Otherwise fall back to a + * physical capable frame. + */ + for_each_available_child_of_node(np, frame) { + int n; + + if (of_property_read_u32(frame, "frame-number", &n)) { + pr_err("arch_timer: Missing frame-number\n"); + of_node_put(best_frame); + of_node_put(frame); + return; + } + + if (cnttidr & CNTTIDR_VIRT(n)) { + of_node_put(best_frame); + best_frame = frame; + arch_timer_mem_use_virtual = true; + break; + } + of_node_put(best_frame); + best_frame = of_node_get(frame); + } + + base = arch_counter_base = of_iomap(best_frame, 0); + if (!base) { + pr_err("arch_timer: Can't map frame's registers\n"); + of_node_put(best_frame); + return; + } + + if (arch_timer_mem_use_virtual) + irq = irq_of_parse_and_map(best_frame, 1); + else + irq = irq_of_parse_and_map(best_frame, 0); + of_node_put(best_frame); + if (!irq) { + pr_err("arch_timer: Frame missing %s irq", + arch_timer_mem_use_virtual ? "virt" : "phys"); + return; + } + + arch_timer_detect_rate(base, np); + arch_timer_mem_register(base, irq); + arch_timer_common_init(); +} +CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem", + arch_timer_mem_init); diff --git a/include/clocksource/arm_arch_timer.h b/include/clocksource/arm_arch_timer.h index f3da817b9b8e..93b7f96f9c59 100644 --- a/include/clocksource/arm_arch_timer.h +++ b/include/clocksource/arm_arch_timer.h @@ -30,11 +30,13 @@ enum arch_timer_reg { #define ARCH_TIMER_PHYS_ACCESS 0 #define ARCH_TIMER_VIRT_ACCESS 1 +#define ARCH_TIMER_MEM_PHYS_ACCESS 2 +#define ARCH_TIMER_MEM_VIRT_ACCESS 3 #ifdef CONFIG_ARM_ARCH_TIMER extern u32 arch_timer_get_rate(void); -extern u64 arch_timer_read_counter(void); +extern u64 (*arch_timer_read_counter)(void); extern struct timecounter *arch_timer_get_timecounter(void); #else From f3e94aa15dc3d9155f8fc4a3295866d7a207b4e5 Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Tue, 30 Jul 2013 19:51:20 -0700 Subject: [PATCH 1176/3400] usb: core: don't try to reset_device() a port that got just disconnected The USB hub driver's event handler contains a check to catch SuperSpeed devices that transitioned into the SS.Inactive state and tries to fix them with a reset. It decides whether to do a plain hub port reset or call the usb_reset_device() function based on whether there was a device attached to the port. However, there are device/hub combinations (found with a JetFlash Transcend mass storage stick (8564:1000) on the root hub of an Intel LynxPoint PCH) which can transition to the SS.Inactive state on disconnect (and stay there long enough for the host to notice). In this case, above-mentioned reset check will call usb_reset_device() on the stale device data structure. The kernel will send pointless LPM control messages to the no longer connected device address and can even cause several 5 second khubd stalls on some (buggy?) host controllers, before finally accepting the device's fate amongst a flurry of error messages. This patch makes the choice of reset dependent on the port status that has just been read from the hub in addition to the existence of an in-kernel data structure for the device, and only proceeds with the more extensive reset if both are valid. Signed-off-by: Julius Werner Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 91a0e84a68cd..c881830af55f 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -4796,7 +4796,8 @@ static void hub_events(void) hub->ports[i - 1]->child; dev_dbg(hub_dev, "warm reset port %d\n", i); - if (!udev) { + if (!udev || !(portstatus & + USB_PORT_STAT_CONNECTION)) { status = hub_port_reset(hub, i, NULL, HUB_BH_RESET_TIME, true); @@ -4806,8 +4807,8 @@ static void hub_events(void) usb_lock_device(udev); status = usb_reset_device(udev); usb_unlock_device(udev); + connect_change = 0; } - connect_change = 0; } if (connect_change) From 1fa0b42e7154d3563c21a5db2d18393f6022b3a6 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 30 Jul 2013 08:17:59 -0700 Subject: [PATCH 1177/3400] MAINTAINERS: USB, remove F: drivers/net/usb/ pattern On Tue, 2013-07-30 at 06:58 -0700, Greg KH wrote: > In the future, you do not need to send drivers/net/usb/ patches to me, > netdev and the linux-usb mailing lists should be sufficient. Signed-off-by: Joe Perches Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 1 - 1 file changed, 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index a26b10e52aea..23d3d4f90702 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8785,7 +8785,6 @@ W: http://www.linux-usb.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git S: Supported F: Documentation/usb/ -F: drivers/net/usb/ F: drivers/usb/ F: include/linux/usb.h F: include/linux/usb/ From 720ce6e4b1ba83aa1ed526a47d36852ac6a25d7e Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 30 Jul 2013 17:25:19 +0900 Subject: [PATCH 1178/3400] USB: c67x00: use dev_get_platdata() Use the wrapper function for retrieving the platform data instead of accessing dev->platform_data directly. Signed-off-by: Jingoo Han Signed-off-by: Greg Kroah-Hartman --- drivers/usb/c67x00/c67x00-drv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/c67x00/c67x00-drv.c b/drivers/usb/c67x00/c67x00-drv.c index fe815ecd557e..8db3380c3329 100644 --- a/drivers/usb/c67x00/c67x00-drv.c +++ b/drivers/usb/c67x00/c67x00-drv.c @@ -131,7 +131,7 @@ static int c67x00_drv_probe(struct platform_device *pdev) if (!res2) return -ENODEV; - pdata = pdev->dev.platform_data; + pdata = dev_get_platdata(&pdev->dev); if (!pdata) return -ENODEV; @@ -154,7 +154,7 @@ static int c67x00_drv_probe(struct platform_device *pdev) spin_lock_init(&c67x00->hpi.lock); c67x00->hpi.regstep = pdata->hpi_regstep; - c67x00->pdata = pdev->dev.platform_data; + c67x00->pdata = dev_get_platdata(&pdev->dev); c67x00->pdev = pdev; c67x00_ll_init(c67x00); From ace0a5f9471ef51349dba59ff57beee2c3748a34 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 30 Jul 2013 17:06:20 +0900 Subject: [PATCH 1179/3400] usb: renesas: use dev_get_platdata() Use the wrapper function for retrieving the platform data instead of accessing dev->platform_data directly. Signed-off-by: Jingoo Han Signed-off-by: Greg Kroah-Hartman --- drivers/usb/renesas_usbhs/common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c index cfd205036aba..3b39757c13bc 100644 --- a/drivers/usb/renesas_usbhs/common.c +++ b/drivers/usb/renesas_usbhs/common.c @@ -416,7 +416,7 @@ static int usbhsc_drvcllbck_notify_hotplug(struct platform_device *pdev) */ static int usbhs_probe(struct platform_device *pdev) { - struct renesas_usbhs_platform_info *info = pdev->dev.platform_data; + struct renesas_usbhs_platform_info *info = dev_get_platdata(&pdev->dev); struct renesas_usbhs_driver_callback *dfunc; struct usbhs_priv *priv; struct resource *res, *irq_res; @@ -558,7 +558,7 @@ probe_end_pipe_exit: static int usbhs_remove(struct platform_device *pdev) { struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev); - struct renesas_usbhs_platform_info *info = pdev->dev.platform_data; + struct renesas_usbhs_platform_info *info = dev_get_platdata(&pdev->dev); struct renesas_usbhs_driver_callback *dfunc = &info->driver_callback; dev_dbg(&pdev->dev, "usb remove\n"); From b977a3068a284b2ad4612cdb8ca326cbd2a7ffc9 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 30 Jul 2013 17:05:28 +0900 Subject: [PATCH 1180/3400] usb: misc: usb3503: use dev_get_platdata() Use the wrapper function for retrieving the platform data instead of accessing dev->platform_data directly. Signed-off-by: Jingoo Han Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/usb3503.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c index c3578393ddef..cbb6b7841653 100644 --- a/drivers/usb/misc/usb3503.c +++ b/drivers/usb/misc/usb3503.c @@ -179,7 +179,7 @@ err_hubmode: static int usb3503_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { - struct usb3503_platform_data *pdata = i2c->dev.platform_data; + struct usb3503_platform_data *pdata = dev_get_platdata(&i2c->dev); struct device_node *np = i2c->dev.of_node; struct usb3503 *hub; int err = -ENOMEM; From 15b7336e02d998720c5ace47036f7e539365bb05 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 30 Jul 2013 15:35:40 -0400 Subject: [PATCH 1181/3400] USB: simplify the interface of usb_get_status() This patch simplifies the interface presented by usb_get_status(). Instead of forcing callers to check for the proper data length and convert the status value to host byte order, the function will now do these things itself. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 10 ++-------- drivers/usb/core/message.c | 13 +++++++++---- drivers/usb/misc/usbtest.c | 9 ++++----- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index c881830af55f..11a92198bfc7 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1464,11 +1464,10 @@ static int hub_configure(struct usb_hub *hub, * and battery-powered root hubs (may provide just 8 mA). */ ret = usb_get_status(hdev, USB_RECIP_DEVICE, 0, &hubstatus); - if (ret < 2) { + if (ret) { message = "can't get hub status"; goto fail; } - le16_to_cpus(&hubstatus); hcd = bus_to_hcd(hdev->bus); if (hdev == hdev->bus->root_hub) { if (hcd->power_budget > 0) @@ -3101,8 +3100,6 @@ static int finish_port_resume(struct usb_device *udev) if (status == 0) { devstatus = 0; status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus); - if (status >= 0) - status = (status > 0 ? 0 : -ENODEV); /* If a normal resume failed, try doing a reset-resume */ if (status && !udev->reset_resume && udev->persist_enabled) { @@ -3123,7 +3120,6 @@ static int finish_port_resume(struct usb_device *udev) */ } else if (udev->actconfig && !udev->reset_resume) { if (!hub_is_superspeed(udev->parent)) { - le16_to_cpus(&devstatus); if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), @@ -3135,7 +3131,6 @@ static int finish_port_resume(struct usb_device *udev) } else { status = usb_get_status(udev, USB_RECIP_INTERFACE, 0, &devstatus); - le16_to_cpus(&devstatus); if (!status && devstatus & (USB_INTRF_STAT_FUNC_RW_CAP | USB_INTRF_STAT_FUNC_RW)) status = @@ -4481,11 +4476,10 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstat); - if (status < 2) { + if (status) { dev_dbg(&udev->dev, "get status %d ?\n", status); goto loop_disable; } - le16_to_cpus(&devstat); if ((devstat & (1 << USB_DEVICE_SELF_POWERED)) == 0) { dev_err(&udev->dev, "can't connect bus-powered hub " diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index e7ee1e451660..6549a975b0c5 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -934,13 +934,13 @@ int usb_get_device_descriptor(struct usb_device *dev, unsigned int size) * * This call is synchronous, and may not be used in an interrupt context. * - * Returns the number of bytes received on success, or else the status code - * returned by the underlying usb_control_msg() call. + * Returns 0 and the status value in *@data (in host byte order) on success, + * or else the status code from the underlying usb_control_msg() call. */ int usb_get_status(struct usb_device *dev, int type, int target, void *data) { int ret; - u16 *status = kmalloc(sizeof(*status), GFP_KERNEL); + __le16 *status = kmalloc(sizeof(*status), GFP_KERNEL); if (!status) return -ENOMEM; @@ -949,7 +949,12 @@ int usb_get_status(struct usb_device *dev, int type, int target, void *data) USB_REQ_GET_STATUS, USB_DIR_IN | type, 0, target, status, sizeof(*status), USB_CTRL_GET_TIMEOUT); - *(u16 *)data = *status; + if (ret == 2) { + *(u16 *) data = le16_to_cpu(*status); + ret = 0; + } else if (ret >= 0) { + ret = -EIO; + } kfree(status); return ret; } diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 8b4ca1cb450a..aa28ac8c7607 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -747,9 +747,9 @@ static int ch9_postconfig(struct usbtest_dev *dev) /* [9.4.5] get_status always works */ retval = usb_get_status(udev, USB_RECIP_DEVICE, 0, dev->buf); - if (retval != 2) { + if (retval) { dev_err(&iface->dev, "get dev status --> %d\n", retval); - return (retval < 0) ? retval : -EDOM; + return retval; } /* FIXME configuration.bmAttributes says if we could try to set/clear @@ -758,9 +758,9 @@ static int ch9_postconfig(struct usbtest_dev *dev) retval = usb_get_status(udev, USB_RECIP_INTERFACE, iface->altsetting[0].desc.bInterfaceNumber, dev->buf); - if (retval != 2) { + if (retval) { dev_err(&iface->dev, "get interface status --> %d\n", retval); - return (retval < 0) ? retval : -EDOM; + return retval; } /* FIXME get status for each endpoint in the interface */ @@ -1351,7 +1351,6 @@ static int verify_halted(struct usbtest_dev *tdev, int ep, struct urb *urb) ep, retval); return retval; } - le16_to_cpus(&status); if (status != 1) { ERROR(tdev, "ep %02x bogus status: %04x != 1\n", ep, status); return -EINVAL; From 28e861658e23ca94692f98e245d254c75c8088a7 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 30 Jul 2013 15:37:33 -0400 Subject: [PATCH 1182/3400] USB: refactor code for enabling/disabling remote wakeup The hub driver is inconsistent in its organization of code for enabling and disabling remote wakeup. There is a special routine to disable wakeup for SuperSpeed devices but not for slower devices, and there is no special routine to enable wakeup. This patch refactors the code. It renames and changes the existing function to make it handle both SuperSpeed and non-SuperSpeed devices, and it adds a corresponding routine to enable remote wakeup. It also changes the speed determination to look at the device's speed rather than the speed of the parent hub -- this shouldn't make any difference because a SuperSpeed device always has to be attached to a SuperSpeed hub and conversely. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 98 ++++++++++++++++++++---------------------- 1 file changed, 46 insertions(+), 52 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 11a92198bfc7..c376c8bad40c 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2838,18 +2838,50 @@ void usb_enable_ltm(struct usb_device *udev) EXPORT_SYMBOL_GPL(usb_enable_ltm); /* - * usb_disable_function_remotewakeup - disable usb3.0 - * device's function remote wakeup + * usb_enable_remote_wakeup - enable remote wakeup for a device * @udev: target device * - * Assume there's only one function on the USB 3.0 - * device and disable remote wake for the first - * interface. FIXME if the interface association - * descriptor shows there's more than one function. + * For USB-2 devices: Set the device's remote wakeup feature. + * + * For USB-3 devices: Assume there's only one function on the device and + * enable remote wake for the first interface. FIXME if the interface + * association descriptor shows there's more than one function. */ -static int usb_disable_function_remotewakeup(struct usb_device *udev) +static int usb_enable_remote_wakeup(struct usb_device *udev) { - return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + if (udev->speed < USB_SPEED_SUPER) + return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_SET_FEATURE, USB_RECIP_DEVICE, + USB_DEVICE_REMOTE_WAKEUP, 0, NULL, 0, + USB_CTRL_SET_TIMEOUT); + else + return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_SET_FEATURE, USB_RECIP_INTERFACE, + USB_INTRF_FUNC_SUSPEND, + USB_INTRF_FUNC_SUSPEND_RW | + USB_INTRF_FUNC_SUSPEND_LP, + NULL, 0, USB_CTRL_SET_TIMEOUT); +} + +/* + * usb_disable_remote_wakeup - disable remote wakeup for a device + * @udev: target device + * + * For USB-2 devices: Clear the device's remote wakeup feature. + * + * For USB-3 devices: Assume there's only one function on the device and + * disable remote wake for the first interface. FIXME if the interface + * association descriptor shows there's more than one function. + */ +static int usb_disable_remote_wakeup(struct usb_device *udev) +{ + if (udev->speed < USB_SPEED_SUPER) + return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, + USB_DEVICE_REMOTE_WAKEUP, 0, NULL, 0, + USB_CTRL_SET_TIMEOUT); + else + return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), USB_REQ_CLEAR_FEATURE, USB_RECIP_INTERFACE, USB_INTRF_FUNC_SUSPEND, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); @@ -2928,27 +2960,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) * we don't explicitly enable it here. */ if (udev->do_remote_wakeup) { - if (!hub_is_superspeed(hub->hdev)) { - status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - USB_REQ_SET_FEATURE, USB_RECIP_DEVICE, - USB_DEVICE_REMOTE_WAKEUP, 0, - NULL, 0, - USB_CTRL_SET_TIMEOUT); - } else { - /* Assume there's only one function on the USB 3.0 - * device and enable remote wake for the first - * interface. FIXME if the interface association - * descriptor shows there's more than one function. - */ - status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - USB_REQ_SET_FEATURE, - USB_RECIP_INTERFACE, - USB_INTRF_FUNC_SUSPEND, - USB_INTRF_FUNC_SUSPEND_RW | - USB_INTRF_FUNC_SUSPEND_LP, - NULL, 0, - USB_CTRL_SET_TIMEOUT); - } + status = usb_enable_remote_wakeup(udev); if (status) { dev_dbg(&udev->dev, "won't remote wakeup, status %d\n", status); @@ -2999,19 +3011,8 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n", port1, status); /* paranoia: "should not happen" */ - if (udev->do_remote_wakeup) { - if (!hub_is_superspeed(hub->hdev)) { - (void) usb_control_msg(udev, - usb_sndctrlpipe(udev, 0), - USB_REQ_CLEAR_FEATURE, - USB_RECIP_DEVICE, - USB_DEVICE_REMOTE_WAKEUP, 0, - NULL, 0, - USB_CTRL_SET_TIMEOUT); - } else - (void) usb_disable_function_remotewakeup(udev); - - } + if (udev->do_remote_wakeup) + (void) usb_disable_remote_wakeup(udev); /* Try to enable USB2 hardware LPM again */ if (udev->usb2_hw_lpm_capable == 1) @@ -3119,22 +3120,15 @@ static int finish_port_resume(struct usb_device *udev) * udev->reset_resume */ } else if (udev->actconfig && !udev->reset_resume) { - if (!hub_is_superspeed(udev->parent)) { + if (udev->speed < USB_SPEED_SUPER) { if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) - status = usb_control_msg(udev, - usb_sndctrlpipe(udev, 0), - USB_REQ_CLEAR_FEATURE, - USB_RECIP_DEVICE, - USB_DEVICE_REMOTE_WAKEUP, 0, - NULL, 0, - USB_CTRL_SET_TIMEOUT); + status = usb_disable_remote_wakeup(udev); } else { status = usb_get_status(udev, USB_RECIP_INTERFACE, 0, &devstatus); if (!status && devstatus & (USB_INTRF_STAT_FUNC_RW_CAP | USB_INTRF_STAT_FUNC_RW)) - status = - usb_disable_function_remotewakeup(udev); + status = usb_disable_remote_wakeup(udev); } if (status) From 4fae6f0fa86f92e6bc7429371b1e177ad0aaac66 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 30 Jul 2013 15:39:02 -0400 Subject: [PATCH 1183/3400] USB: handle LPM errors during device suspend correctly The hub driver's usb_port_suspend() routine doesn't handle errors related to Link Power Management properly. It always returns failure, it doesn't try to clean up the wakeup setting, (in the case of system sleep) it doesn't try to go ahead with the port suspend regardless, and it doesn't try to apply the new power-off mechanism. This patch fixes these problems. Signed-off-by: Alan Stern Acked-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 48 +++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index c376c8bad40c..0416f835cfee 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2948,7 +2948,6 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) { struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent); struct usb_port *port_dev = hub->ports[udev->portnum - 1]; - enum pm_qos_flags_status pm_qos_stat; int port1 = udev->portnum; int status; bool really_suspend = true; @@ -2966,7 +2965,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) status); /* bail if autosuspend is requested */ if (PMSG_IS_AUTO(msg)) - return status; + goto err_wakeup; } } @@ -2975,14 +2974,16 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) usb_set_usb2_hardware_lpm(udev, 0); if (usb_disable_ltm(udev)) { - dev_err(&udev->dev, "%s Failed to disable LTM before suspend\n.", - __func__); - return -ENOMEM; + dev_err(&udev->dev, "Failed to disable LTM before suspend\n."); + status = -ENOMEM; + if (PMSG_IS_AUTO(msg)) + goto err_ltm; } if (usb_unlocked_disable_lpm(udev)) { - dev_err(&udev->dev, "%s Failed to disable LPM before suspend\n.", - __func__); - return -ENOMEM; + dev_err(&udev->dev, "Failed to disable LPM before suspend\n."); + status = -ENOMEM; + if (PMSG_IS_AUTO(msg)) + goto err_lpm3; } /* see 7.1.7.6 */ @@ -3010,17 +3011,19 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) if (status) { dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n", port1, status); - /* paranoia: "should not happen" */ - if (udev->do_remote_wakeup) - (void) usb_disable_remote_wakeup(udev); + /* Try to enable USB3 LPM and LTM again */ + usb_unlocked_enable_lpm(udev); + err_lpm3: + usb_enable_ltm(udev); + err_ltm: /* Try to enable USB2 hardware LPM again */ if (udev->usb2_hw_lpm_capable == 1) usb_set_usb2_hardware_lpm(udev, 1); - /* Try to enable USB3 LTM and LPM again */ - usb_enable_ltm(udev); - usb_unlocked_enable_lpm(udev); + if (udev->do_remote_wakeup) + (void) usb_disable_remote_wakeup(udev); + err_wakeup: /* System sleep transitions should never fail */ if (!PMSG_IS_AUTO(msg)) @@ -3042,14 +3045,15 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) * Check whether current status meets the requirement of * usb port power off mechanism */ - pm_qos_stat = dev_pm_qos_flags(&port_dev->dev, - PM_QOS_FLAG_NO_POWER_OFF); - if (!udev->do_remote_wakeup - && pm_qos_stat != PM_QOS_FLAGS_ALL - && udev->persist_enabled - && !status) { - pm_runtime_put_sync(&port_dev->dev); - port_dev->did_runtime_put = true; + if (status == 0 && !udev->do_remote_wakeup && udev->persist_enabled) { + enum pm_qos_flags_status pm_qos_stat; + + pm_qos_stat = dev_pm_qos_flags(&port_dev->dev, + PM_QOS_FLAG_NO_POWER_OFF); + if (pm_qos_stat != PM_QOS_FLAGS_ALL) { + pm_runtime_put_sync(&port_dev->dev); + port_dev->did_runtime_put = true; + } } usb_mark_last_busy(hub->hdev); From 1c9962b434e347c4e9875b8eaf41f87665bc0162 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Wed, 31 Jul 2013 14:29:27 +0800 Subject: [PATCH 1184/3400] Staging: rtl8192e: add missing single_release() The debug file is opened with single_open(), but there's no single_release(). Signed-off-by: Li Zefan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib_module.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/rtl8192e/rtllib_module.c b/drivers/staging/rtl8192e/rtllib_module.c index 84ea721d5d8e..51d46e04d3f5 100644 --- a/drivers/staging/rtl8192e/rtllib_module.c +++ b/drivers/staging/rtl8192e/rtllib_module.c @@ -233,7 +233,8 @@ static const struct file_operations fops = { .open = open_debug_level, .read = seq_read, .llseek = seq_lseek, - .write = write_debug_level + .write = write_debug_level, + .release = single_release, }; int __init rtllib_init(void) From e8e6fda00b834a5c048214d58ca7eb00ddad734c Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Wed, 31 Jul 2013 14:30:13 +0800 Subject: [PATCH 1185/3400] Staging: rtl8192u/ieee80211: add missing single_release() The debug file is opened with single_open(), but there's no single_release(). Signed-off-by: Li Zefan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/ieee80211/ieee80211_module.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c index e0870c05a5e0..434c43127183 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c @@ -268,7 +268,8 @@ static const struct file_operations fops = { .open = open_debug_level, .read = seq_read, .llseek = seq_lseek, - .write = write_debug_level + .write = write_debug_level, + .release = single_release, }; int __init ieee80211_debug_init(void) From 7df68962899e667479632217862dd69ea9815238 Mon Sep 17 00:00:00 2001 From: Jens Frederich Date: Tue, 30 Jul 2013 20:11:34 +0200 Subject: [PATCH 1186/3400] staging: olpc_dcon: provide detailed FB_OLPC_DCON help section The FB_OLPC_DCON help section is to short according to checkpatch.pl. We want more information about the controller type, its task, its video pipeline position and so on. There are no style issues, remove checkpatch.pl TODO entry. Signed-off-by: Jens Frederich Acked-by: Andres Salomon Signed-off-by: Greg Kroah-Hartman --- drivers/staging/olpc_dcon/Kconfig | 11 ++++++++--- drivers/staging/olpc_dcon/TODO | 1 - 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/staging/olpc_dcon/Kconfig b/drivers/staging/olpc_dcon/Kconfig index fe40e0b6f675..2ff015d84509 100644 --- a/drivers/staging/olpc_dcon/Kconfig +++ b/drivers/staging/olpc_dcon/Kconfig @@ -4,9 +4,14 @@ config FB_OLPC_DCON select I2C select BACKLIGHT_CLASS_DEVICE ---help--- - Add support for the OLPC XO DCON controller. This controller is - only available on OLPC platforms. Unless you have one of these - platforms, you will want to say 'N'. + In order to support very low power operation, the XO laptop uses a + secondary Display CONtroller, or DCON. This secondary controller + is present in the video pipeline between the primary display + controller (integrate into the processor or chipset) and the LCD + panel. It allows the main processor/display controller to be + completely powered off while still retaining an image on the display. + This controller is only available on OLPC platforms. Unless you have + one of these platforms, you will want to say 'N'. config FB_OLPC_DCON_1 bool "OLPC XO-1 DCON support" diff --git a/drivers/staging/olpc_dcon/TODO b/drivers/staging/olpc_dcon/TODO index 35f9cda7be11..f378e848b51a 100644 --- a/drivers/staging/olpc_dcon/TODO +++ b/drivers/staging/olpc_dcon/TODO @@ -1,5 +1,4 @@ TODO: - - checkpatch.pl cleanups - see if vx855 gpio API can be made similar enough to cs5535 so we can share more code - allow simultaneous XO-1 and XO-1.5 support From 23cdad3360a39b1b81e1068b1027db25c9e16d97 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 13:48:01 -0700 Subject: [PATCH 1187/3400] staging: comedi: das16: "timer_mode" is always used for DMA As noted in the driver, a timer is always used by this driver to handle the DMA due to buggy DMA controllers and the lack of a hardware fifo in some of the supported boards. Remove all the non-timer mode specific code. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 95 +++----------------------- 1 file changed, 9 insertions(+), 86 deletions(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 593ec3866146..2dd03da22a2e 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -387,7 +387,6 @@ struct das16_private_struct { struct timer_list timer; /* for timed interrupt */ volatile short timer_running; - volatile short timer_mode; /* true if using timer mode */ unsigned long extra_iobase; }; @@ -516,49 +515,6 @@ static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s, return 0; } -/* utility function that suggests a dma transfer size in bytes */ -static unsigned int das16_suggest_transfer_size(struct comedi_device *dev, - const struct comedi_cmd *cmd) -{ - struct das16_private_struct *devpriv = dev->private; - unsigned int size; - unsigned int freq; - - /* if we are using timer interrupt, we don't care how long it - * will take to complete transfer since it will be interrupted - * by timer interrupt */ - if (devpriv->timer_mode) - return DAS16_DMA_SIZE; - - /* otherwise, we are relying on dma terminal count interrupt, - * so pick a reasonable size */ - if (cmd->convert_src == TRIG_TIMER) - freq = 1000000000 / cmd->convert_arg; - else if (cmd->scan_begin_src == TRIG_TIMER) - freq = (1000000000 / cmd->scan_begin_arg) * cmd->chanlist_len; - /* return some default value */ - else - freq = 0xffffffff; - - if (cmd->flags & TRIG_WAKE_EOS) { - size = sample_size * cmd->chanlist_len; - } else { - /* make buffer fill in no more than 1/3 second */ - size = (freq / 3) * sample_size; - } - - /* set a minimum and maximum size allowed */ - if (size > DAS16_DMA_SIZE) - size = DAS16_DMA_SIZE - DAS16_DMA_SIZE % sample_size; - else if (size < sample_size) - size = sample_size; - - if (cmd->stop_src == TRIG_COUNT && size > devpriv->adc_byte_count) - size = devpriv->adc_byte_count; - - return size; -} - static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns, int rounding_flags) { @@ -585,13 +541,6 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) unsigned long flags; int range; - if (devpriv->dma_chan == 0 || (dev->irq == 0 - && devpriv->timer_mode == 0)) { - comedi_error(dev, - "irq (or use of 'timer mode') dma required to " - "execute comedi_cmd"); - return -1; - } if (cmd->flags & TRIG_RT) { comedi_error(dev, "isa dma transfers cannot be performed with " "TRIG_RT, aborting"); @@ -648,24 +597,16 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->current_buffer = 0; set_dma_addr(devpriv->dma_chan, devpriv->dma_buffer_addr[devpriv->current_buffer]); - /* set appropriate size of transfer */ - devpriv->dma_transfer_size = das16_suggest_transfer_size(dev, cmd); + devpriv->dma_transfer_size = DAS16_DMA_SIZE; set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size); enable_dma(devpriv->dma_chan); release_dma_lock(flags); /* set up interrupt */ - if (devpriv->timer_mode) { - devpriv->timer_running = 1; - devpriv->timer.expires = jiffies + timer_period(); - add_timer(&devpriv->timer); - devpriv->control_state &= ~DAS16_INTE; - } else { - /* clear interrupt bit */ - outb(0x00, dev->iobase + DAS16_STATUS); - /* enable interrupts */ - devpriv->control_state |= DAS16_INTE; - } + devpriv->timer_running = 1; + devpriv->timer.expires = jiffies + timer_period(); + add_timer(&devpriv->timer); + devpriv->control_state &= ~DAS16_INTE; devpriv->control_state |= DMA_ENABLE; devpriv->control_state &= ~PACING_MASK; if (cmd->convert_src == TRIG_EXT) @@ -696,7 +637,7 @@ static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s) disable_dma(devpriv->dma_chan); /* disable SW timer */ - if (devpriv->timer_mode && devpriv->timer_running) { + if (devpriv->timer_running) { devpriv->timer_running = 0; del_timer(&devpriv->timer); } @@ -864,7 +805,6 @@ static int disable_dma_on_even(struct comedi_device *dev) static void das16_interrupt(struct comedi_device *dev) { - const struct das16_board *board = comedi_board(dev); struct das16_private_struct *devpriv = dev->private; unsigned long dma_flags, spin_flags; struct comedi_subdevice *s = dev->read_subdev; @@ -915,21 +855,12 @@ static void das16_interrupt(struct comedi_device *dev) devpriv->current_buffer = (devpriv->current_buffer + 1) % 2; devpriv->adc_byte_count -= num_bytes; - /* figure out how many bytes for next transfer */ - if (cmd->stop_src == TRIG_COUNT && devpriv->timer_mode == 0 && - devpriv->dma_transfer_size > devpriv->adc_byte_count) - devpriv->dma_transfer_size = devpriv->adc_byte_count; - /* re-enable dma */ if ((async->events & COMEDI_CB_EOA) == 0) { set_dma_addr(devpriv->dma_chan, devpriv->dma_buffer_addr[devpriv->current_buffer]); set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size); enable_dma(devpriv->dma_chan); - /* reenable conversions for das1600 mode, (stupid hardware) */ - if (board->size > 0x400 && devpriv->timer_mode == 0) - outb(0x00, dev->iobase + DAS1600_CONV); - } release_dma_lock(dma_flags); @@ -1077,20 +1008,15 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) int ret; unsigned int irq; unsigned int dma_chan; - int timer_mode; unsigned long flags; struct comedi_krange *user_ai_range, *user_ao_range; #if 0 irq = it->options[1]; - timer_mode = it->options[8]; #endif /* always use time_mode since using irq can drop samples while * waiting for dma done interrupt (due to hardware limitations) */ irq = 0; - timer_mode = 1; - if (timer_mode) - irq = 0; /* check that clock setting is valid */ if (it->options[3]) { @@ -1214,12 +1140,9 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) user_ao_range->flags = UNIT_volt; } - if (timer_mode) { - init_timer(&(devpriv->timer)); - devpriv->timer.function = das16_timer_interrupt; - devpriv->timer.data = (unsigned long)dev; - } - devpriv->timer_mode = timer_mode ? 1 : 0; + init_timer(&(devpriv->timer)); + devpriv->timer.function = das16_timer_interrupt; + devpriv->timer.data = (unsigned long)dev; ret = comedi_alloc_subdevices(dev, 5); if (ret) From 5589c7cc9f37e929754e0a14b85db7c23a28129f Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 13:48:19 -0700 Subject: [PATCH 1188/3400] staging: comedi: das16: remove DMA irq support As noted in the driver, a timer is always used by this driver to handle the DMA because samples could be dropped while waiting for the DMA done interrupt. Remove the irq setup code as well as the interrupt handler. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 42 -------------------------- 1 file changed, 42 deletions(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 2dd03da22a2e..52f98a71c80f 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -872,24 +872,6 @@ static void das16_interrupt(struct comedi_device *dev) cfc_handle_events(dev, s); } -static irqreturn_t das16_dma_interrupt(int irq, void *d) -{ - int status; - struct comedi_device *dev = d; - - status = inb(dev->iobase + DAS16_STATUS); - - if ((status & DAS16_INT) == 0) { - DEBUG_PRINT("spurious interrupt\n"); - return IRQ_NONE; - } - - /* clear interrupt */ - outb(0x00, dev->iobase + DAS16_STATUS); - das16_interrupt(dev); - return IRQ_HANDLED; -} - static void das16_timer_interrupt(unsigned long arg) { struct comedi_device *dev = (struct comedi_device *)arg; @@ -1006,18 +988,10 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct das16_private_struct *devpriv; struct comedi_subdevice *s; int ret; - unsigned int irq; unsigned int dma_chan; unsigned long flags; struct comedi_krange *user_ai_range, *user_ao_range; -#if 0 - irq = it->options[1]; -#endif - /* always use time_mode since using irq can drop samples while - * waiting for dma done interrupt (due to hardware limitations) */ - irq = 0; - /* check that clock setting is valid */ if (it->options[3]) { if (it->options[3] != 0 && @@ -1065,22 +1039,6 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) das1600_mode_detect(dev); } - /* now for the irq */ - if (irq > 1 && irq < 8) { - ret = request_irq(irq, das16_dma_interrupt, 0, - dev->board_name, dev); - - if (ret < 0) - return ret; - dev->irq = irq; - printk(KERN_INFO " ( irq = %u )", irq); - } else if (irq == 0) { - printk(" ( no irq )"); - } else { - printk(" invalid irq\n"); - return -EINVAL; - } - /* initialize dma */ dma_chan = it->options[2]; if (dma_chan == 1 || dma_chan == 3) { From b0926a7afabe49021f4fbed9baac0419ad3aa56a Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 13:48:38 -0700 Subject: [PATCH 1189/3400] staging: comedi: das16: fix DMA init during board attach DMA support is optional in this driver. To enable it, the user passes the desired DMA channel during the board attach. A timer is then used by the driver to periodically get the analog input data from the DMA. Since the DMA support is optional, modify the init code so that it only fails if the DMA channel is unavailable or the DMA buffers can not be allocated. Don't fail just because the user passed an invalid DMA channel (only DMA channels 1 and 3 are valid). Remove the printk() noise about the DMA. Change the printk() when the request_dma() fails into a dev_err(). Move the timer initialization so it's only setup if DMA is available. It's not needed otherwise. Also, only hook up the subdevice command support functions if DMA is available. This allows removing a couple sanity checks in the command support. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 72 ++++++++++++-------------- 1 file changed, 34 insertions(+), 38 deletions(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 52f98a71c80f..f35aabd960f9 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -633,8 +633,7 @@ static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s) /* disable interrupts, dma and pacer clocked conversions */ devpriv->control_state &= ~DAS16_INTE & ~PACING_MASK & ~DMA_ENABLE; outb(devpriv->control_state, dev->iobase + DAS16_CONTROL); - if (devpriv->dma_chan) - disable_dma(devpriv->dma_chan); + disable_dma(devpriv->dma_chan); /* disable SW timer */ if (devpriv->timer_running) { @@ -821,11 +820,6 @@ static void das16_interrupt(struct comedi_device *dev) async = s->async; cmd = &async->cmd; - if (devpriv->dma_chan == 0) { - comedi_error(dev, "interrupt with no dma channel?"); - return; - } - spin_lock_irqsave(&dev->spinlock, spin_flags); if ((devpriv->control_state & DMA_ENABLE) == 0) { spin_unlock_irqrestore(&dev->spinlock, spin_flags); @@ -987,10 +981,10 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) const struct das16_board *board = comedi_board(dev); struct das16_private_struct *devpriv; struct comedi_subdevice *s; + struct comedi_krange *user_ai_range; + struct comedi_krange *user_ao_range; + unsigned int dma_chan = it->options[2]; int ret; - unsigned int dma_chan; - unsigned long flags; - struct comedi_krange *user_ai_range, *user_ao_range; /* check that clock setting is valid */ if (it->options[3]) { @@ -1039,35 +1033,38 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) das1600_mode_detect(dev); } - /* initialize dma */ - dma_chan = it->options[2]; + /* initialize dma */ if (dma_chan == 1 || dma_chan == 3) { - /* allocate dma buffers */ + unsigned long flags; int i; - for (i = 0; i < 2; i++) { - devpriv->dma_buffer[i] = pci_alloc_consistent( - NULL, DAS16_DMA_SIZE, - &devpriv->dma_buffer_addr[i]); - if (devpriv->dma_buffer[i] == NULL) - return -ENOMEM; - } if (request_dma(dma_chan, dev->board_name)) { - printk(KERN_ERR " failed to allocate dma channel %i\n", - dma_chan); + dev_err(dev->class_dev, + "failed to request dma channel %i\n", + dma_chan); return -EINVAL; } devpriv->dma_chan = dma_chan; + + /* allocate dma buffers */ + for (i = 0; i < 2; i++) { + void *p; + + p = pci_alloc_consistent(NULL, DAS16_DMA_SIZE, + &devpriv->dma_buffer_addr[i]); + if (!p) + return -ENOMEM; + devpriv->dma_buffer[i] = p; + } + flags = claim_dma_lock(); disable_dma(devpriv->dma_chan); set_dma_mode(devpriv->dma_chan, DMA_MODE_READ); release_dma_lock(flags); - printk(KERN_INFO " ( dma = %u)\n", dma_chan); - } else if (dma_chan == 0) { - printk(KERN_INFO " ( no dma )\n"); - } else { - printk(KERN_ERR " invalid dma channel\n"); - return -EINVAL; + + init_timer(&(devpriv->timer)); + devpriv->timer.function = das16_timer_interrupt; + devpriv->timer.data = (unsigned long)dev; } /* get any user-defined input range */ @@ -1098,20 +1095,15 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) user_ao_range->flags = UNIT_volt; } - init_timer(&(devpriv->timer)); - devpriv->timer.function = das16_timer_interrupt; - devpriv->timer.data = (unsigned long)dev; - ret = comedi_alloc_subdevices(dev, 5); if (ret) return ret; s = &dev->subdevices[0]; - dev->read_subdev = s; /* ai */ if (board->ai) { s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_CMD_READ; + s->subdev_flags = SDF_READABLE; if (devpriv->ai_singleended) { s->n_chan = 16; s->len_chanlist = 16; @@ -1130,10 +1122,14 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->range_table = das16_ai_bip_lranges[board->ai_pg]; } s->insn_read = board->ai; - s->do_cmdtest = das16_cmd_test; - s->do_cmd = das16_cmd_exec; - s->cancel = das16_cancel; - s->munge = das16_ai_munge; + if (devpriv->dma_chan) { + dev->read_subdev = s; + s->subdev_flags |= SDF_CMD_READ; + s->do_cmdtest = das16_cmd_test; + s->do_cmd = das16_cmd_exec; + s->cancel = das16_cancel; + s->munge = das16_ai_munge; + } } else { s->type = COMEDI_SUBD_UNUSED; } From 465e25b5e143a7de07f243d50ee0f265cc132aad Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 13:49:01 -0700 Subject: [PATCH 1190/3400] staging: comedi: das16: all supported board have analog inputs All the boards supported by this driver have analog inputs and all of then use the same function to handle the (*insn_read) for the subdevice. Remove the 'ai' member from the boardinfo and always initalize the analog input subdevice during the board attach. Tidy up the subdevice init a bit. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 86 +++++++++----------------- 1 file changed, 30 insertions(+), 56 deletions(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index f35aabd960f9..0b76af68f957 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -338,7 +338,6 @@ struct munge_info { struct das16_board { const char *name; - void *ai; unsigned int ai_nbits; unsigned int ai_speed; /* max conversion speed in nanosec */ unsigned int ai_pg; @@ -659,8 +658,10 @@ static void das16_reset(struct comedi_device *dev) outb(0, dev->iobase + DAS16_CNTR_CONTROL); } -static int das16_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int das16_ai_insn_read(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { const struct das16_board *board = comedi_board(dev); struct das16_private_struct *devpriv = dev->private; @@ -1099,39 +1100,34 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; + /* Analog Input subdevice */ s = &dev->subdevices[0]; - /* ai */ - if (board->ai) { - s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE; - if (devpriv->ai_singleended) { - s->n_chan = 16; - s->len_chanlist = 16; - s->subdev_flags |= SDF_GROUND; - } else { - s->n_chan = 8; - s->len_chanlist = 8; - s->subdev_flags |= SDF_DIFF; - } - s->maxdata = (1 << board->ai_nbits) - 1; - if (devpriv->user_ai_range_table) { /* user defined ai range */ - s->range_table = devpriv->user_ai_range_table; - } else if (devpriv->ai_unipolar) { - s->range_table = das16_ai_uni_lranges[board->ai_pg]; - } else { - s->range_table = das16_ai_bip_lranges[board->ai_pg]; - } - s->insn_read = board->ai; - if (devpriv->dma_chan) { - dev->read_subdev = s; - s->subdev_flags |= SDF_CMD_READ; - s->do_cmdtest = das16_cmd_test; - s->do_cmd = das16_cmd_exec; - s->cancel = das16_cancel; - s->munge = das16_ai_munge; - } + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE; + if (devpriv->ai_singleended) { + s->subdev_flags |= SDF_GROUND; + s->n_chan = 16; } else { - s->type = COMEDI_SUBD_UNUSED; + s->subdev_flags |= SDF_DIFF; + s->n_chan = 8; + } + s->len_chanlist = s->n_chan; + s->maxdata = (1 << board->ai_nbits) - 1; + if (devpriv->user_ai_range_table) { /* user defined ai range */ + s->range_table = devpriv->user_ai_range_table; + } else if (devpriv->ai_unipolar) { + s->range_table = das16_ai_uni_lranges[board->ai_pg]; + } else { + s->range_table = das16_ai_bip_lranges[board->ai_pg]; + } + s->insn_read = das16_ai_insn_read; + if (devpriv->dma_chan) { + dev->read_subdev = s; + s->subdev_flags |= SDF_CMD_READ; + s->do_cmdtest = das16_cmd_test; + s->do_cmd = das16_cmd_exec; + s->cancel = das16_cancel; + s->munge = das16_ai_munge; } s = &dev->subdevices[1]; @@ -1232,7 +1228,6 @@ static void das16_detach(struct comedi_device *dev) static const struct das16_board das16_boards[] = { { .name = "das-16", - .ai = das16_ai_rinsn, .ai_nbits = 12, .ai_speed = 15000, .ai_pg = das16_pg_none, @@ -1246,7 +1241,6 @@ static const struct das16_board das16_boards[] = { .id = 0x00, }, { .name = "das-16g", - .ai = das16_ai_rinsn, .ai_nbits = 12, .ai_speed = 15000, .ai_pg = das16_pg_none, @@ -1260,7 +1254,6 @@ static const struct das16_board das16_boards[] = { .id = 0x00, }, { .name = "das-16f", - .ai = das16_ai_rinsn, .ai_nbits = 12, .ai_speed = 8500, .ai_pg = das16_pg_none, @@ -1274,7 +1267,6 @@ static const struct das16_board das16_boards[] = { .id = 0x00, }, { .name = "cio-das16", - .ai = das16_ai_rinsn, .ai_nbits = 12, .ai_speed = 20000, .ai_pg = das16_pg_none, @@ -1288,7 +1280,6 @@ static const struct das16_board das16_boards[] = { .id = 0x80, }, { .name = "cio-das16/f", - .ai = das16_ai_rinsn, .ai_nbits = 12, .ai_speed = 10000, .ai_pg = das16_pg_none, @@ -1302,7 +1293,6 @@ static const struct das16_board das16_boards[] = { .id = 0x80, }, { .name = "cio-das16/jr", - .ai = das16_ai_rinsn, .ai_nbits = 12, .ai_speed = 7692, .ai_pg = das16_pg_16jr, @@ -1315,7 +1305,6 @@ static const struct das16_board das16_boards[] = { .id = 0x00, }, { .name = "pc104-das16jr", - .ai = das16_ai_rinsn, .ai_nbits = 12, .ai_speed = 3300, .ai_pg = das16_pg_16jr, @@ -1328,7 +1317,6 @@ static const struct das16_board das16_boards[] = { .id = 0x00, }, { .name = "cio-das16jr/16", - .ai = das16_ai_rinsn, .ai_nbits = 16, .ai_speed = 10000, .ai_pg = das16_pg_16jr_16, @@ -1341,7 +1329,6 @@ static const struct das16_board das16_boards[] = { .id = 0x00, }, { .name = "pc104-das16jr/16", - .ai = das16_ai_rinsn, .ai_nbits = 16, .ai_speed = 10000, .ai_pg = das16_pg_16jr_16, @@ -1354,7 +1341,6 @@ static const struct das16_board das16_boards[] = { .id = 0x00, }, { .name = "das-1201", - .ai = das16_ai_rinsn, .ai_nbits = 12, .ai_speed = 20000, .ai_pg = das16_pg_none, @@ -1367,7 +1353,6 @@ static const struct das16_board das16_boards[] = { .id = 0x20, }, { .name = "das-1202", - .ai = das16_ai_rinsn, .ai_nbits = 12, .ai_speed = 10000, .ai_pg = das16_pg_none, @@ -1380,7 +1365,6 @@ static const struct das16_board das16_boards[] = { .id = 0x20, }, { .name = "das-1401", - .ai = das16_ai_rinsn, .ai_nbits = 12, .ai_speed = 10000, .ai_pg = das16_pg_1601, @@ -1393,7 +1377,6 @@ static const struct das16_board das16_boards[] = { .id = 0xc0, }, { .name = "das-1402", - .ai = das16_ai_rinsn, .ai_nbits = 12, .ai_speed = 10000, .ai_pg = das16_pg_1602, @@ -1406,7 +1389,6 @@ static const struct das16_board das16_boards[] = { .id = 0xc0, }, { .name = "das-1601", - .ai = das16_ai_rinsn, .ai_nbits = 12, .ai_speed = 10000, .ai_pg = das16_pg_1601, @@ -1420,7 +1402,6 @@ static const struct das16_board das16_boards[] = { .id = 0xc0, }, { .name = "das-1602", - .ai = das16_ai_rinsn, .ai_nbits = 12, .ai_speed = 10000, .ai_pg = das16_pg_1602, @@ -1434,7 +1415,6 @@ static const struct das16_board das16_boards[] = { .id = 0xc0, }, { .name = "cio-das1401/12", - .ai = das16_ai_rinsn, .ai_nbits = 12, .ai_speed = 6250, .ai_pg = das16_pg_1601, @@ -1447,7 +1427,6 @@ static const struct das16_board das16_boards[] = { .id = 0xc0, }, { .name = "cio-das1402/12", - .ai = das16_ai_rinsn, .ai_nbits = 12, .ai_speed = 6250, .ai_pg = das16_pg_1602, @@ -1460,7 +1439,6 @@ static const struct das16_board das16_boards[] = { .id = 0xc0, }, { .name = "cio-das1402/16", - .ai = das16_ai_rinsn, .ai_nbits = 16, .ai_speed = 10000, .ai_pg = das16_pg_1602, @@ -1473,7 +1451,6 @@ static const struct das16_board das16_boards[] = { .id = 0xc0, }, { .name = "cio-das1601/12", - .ai = das16_ai_rinsn, .ai_nbits = 12, .ai_speed = 6250, .ai_pg = das16_pg_1601, @@ -1487,7 +1464,6 @@ static const struct das16_board das16_boards[] = { .id = 0xc0, }, { .name = "cio-das1602/12", - .ai = das16_ai_rinsn, .ai_nbits = 12, .ai_speed = 10000, .ai_pg = das16_pg_1602, @@ -1501,7 +1477,6 @@ static const struct das16_board das16_boards[] = { .id = 0xc0, }, { .name = "cio-das1602/16", - .ai = das16_ai_rinsn, .ai_nbits = 16, .ai_speed = 10000, .ai_pg = das16_pg_1602, @@ -1515,7 +1490,6 @@ static const struct das16_board das16_boards[] = { .id = 0xc0, }, { .name = "cio-das16/330", - .ai = das16_ai_rinsn, .ai_nbits = 12, .ai_speed = 3030, .ai_pg = das16_pg_16jr, From 0dc7c5db134dcd216003ea1be2b7b93a5169ea26 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 13:49:21 -0700 Subject: [PATCH 1191/3400] staging: comedi: das16: change boardinfo 'ai_nbits' to 'ai_maxdata' The subdevice functions that used this boardinfo can use the subdevice 's->maxdata' value instead. Tidy up those functions. Change the boardinfo so that the calculation is not needed during the attach. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 71 +++++++++++++------------- 1 file changed, 36 insertions(+), 35 deletions(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 0b76af68f957..11e5787dd27e 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -338,7 +338,7 @@ struct munge_info { struct das16_board { const char *name; - unsigned int ai_nbits; + unsigned int ai_maxdata; unsigned int ai_speed; /* max conversion speed in nanosec */ unsigned int ai_pg; void *ao; @@ -668,7 +668,6 @@ static int das16_ai_insn_read(struct comedi_device *dev, int i, n; int range; int chan; - int msb, lsb; /* disable interrupts and pacing */ devpriv->control_state &= ~DAS16_INTE & ~DMA_ENABLE & ~PACING_MASK; @@ -687,6 +686,8 @@ static int das16_ai_insn_read(struct comedi_device *dev, } for (n = 0; n < insn->n; n++) { + unsigned int val; + /* trigger conversion */ outb_p(0, dev->iobase + DAS16_TRIG); @@ -698,13 +699,14 @@ static int das16_ai_insn_read(struct comedi_device *dev, printk("das16: timeout\n"); return -ETIME; } - msb = inb(dev->iobase + DAS16_AI_MSB); - lsb = inb(dev->iobase + DAS16_AI_LSB); - if (board->ai_nbits == 12) - data[n] = ((lsb >> 4) & 0xf) | (msb << 4); - else - data[n] = lsb | (msb << 8); + val = inb(dev->iobase + DAS16_AI_MSB) << 8; + val |= inb(dev->iobase + DAS16_AI_LSB); + if (s->maxdata == 0x0fff) + data[n] >>= 4; + val &= s->maxdata; + + data[n] = val; } return n; @@ -957,15 +959,14 @@ static void das16_ai_munge(struct comedi_device *dev, unsigned int num_bytes, unsigned int start_chan_index) { - const struct das16_board *board = comedi_board(dev); unsigned int i, num_samples = num_bytes / sizeof(short); short *data = array; for (i = 0; i < num_samples; i++) { data[i] = le16_to_cpu(data[i]); - if (board->ai_nbits == 12) - data[i] = (data[i] >> 4) & 0xfff; - + if (s->maxdata == 0x0fff) + data[i] >>= 4; + data[i] &= s->maxdata; } } @@ -1112,7 +1113,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->n_chan = 8; } s->len_chanlist = s->n_chan; - s->maxdata = (1 << board->ai_nbits) - 1; + s->maxdata = board->ai_maxdata; if (devpriv->user_ai_range_table) { /* user defined ai range */ s->range_table = devpriv->user_ai_range_table; } else if (devpriv->ai_unipolar) { @@ -1228,7 +1229,7 @@ static void das16_detach(struct comedi_device *dev) static const struct das16_board das16_boards[] = { { .name = "das-16", - .ai_nbits = 12, + .ai_maxdata = 0x0fff, .ai_speed = 15000, .ai_pg = das16_pg_none, .ao = das16_ao_winsn, @@ -1241,7 +1242,7 @@ static const struct das16_board das16_boards[] = { .id = 0x00, }, { .name = "das-16g", - .ai_nbits = 12, + .ai_maxdata = 0x0fff, .ai_speed = 15000, .ai_pg = das16_pg_none, .ao = das16_ao_winsn, @@ -1254,7 +1255,7 @@ static const struct das16_board das16_boards[] = { .id = 0x00, }, { .name = "das-16f", - .ai_nbits = 12, + .ai_maxdata = 0x0fff, .ai_speed = 8500, .ai_pg = das16_pg_none, .ao = das16_ao_winsn, @@ -1267,7 +1268,7 @@ static const struct das16_board das16_boards[] = { .id = 0x00, }, { .name = "cio-das16", - .ai_nbits = 12, + .ai_maxdata = 0x0fff, .ai_speed = 20000, .ai_pg = das16_pg_none, .ao = das16_ao_winsn, @@ -1280,7 +1281,7 @@ static const struct das16_board das16_boards[] = { .id = 0x80, }, { .name = "cio-das16/f", - .ai_nbits = 12, + .ai_maxdata = 0x0fff, .ai_speed = 10000, .ai_pg = das16_pg_none, .ao = das16_ao_winsn, @@ -1293,7 +1294,7 @@ static const struct das16_board das16_boards[] = { .id = 0x80, }, { .name = "cio-das16/jr", - .ai_nbits = 12, + .ai_maxdata = 0x0fff, .ai_speed = 7692, .ai_pg = das16_pg_16jr, .ao = NULL, @@ -1305,7 +1306,7 @@ static const struct das16_board das16_boards[] = { .id = 0x00, }, { .name = "pc104-das16jr", - .ai_nbits = 12, + .ai_maxdata = 0x0fff, .ai_speed = 3300, .ai_pg = das16_pg_16jr, .ao = NULL, @@ -1317,7 +1318,7 @@ static const struct das16_board das16_boards[] = { .id = 0x00, }, { .name = "cio-das16jr/16", - .ai_nbits = 16, + .ai_maxdata = 0xffff, .ai_speed = 10000, .ai_pg = das16_pg_16jr_16, .ao = NULL, @@ -1329,7 +1330,7 @@ static const struct das16_board das16_boards[] = { .id = 0x00, }, { .name = "pc104-das16jr/16", - .ai_nbits = 16, + .ai_maxdata = 0xffff, .ai_speed = 10000, .ai_pg = das16_pg_16jr_16, .ao = NULL, @@ -1341,7 +1342,7 @@ static const struct das16_board das16_boards[] = { .id = 0x00, }, { .name = "das-1201", - .ai_nbits = 12, + .ai_maxdata = 0x0fff, .ai_speed = 20000, .ai_pg = das16_pg_none, .ao = NULL, @@ -1353,7 +1354,7 @@ static const struct das16_board das16_boards[] = { .id = 0x20, }, { .name = "das-1202", - .ai_nbits = 12, + .ai_maxdata = 0x0fff, .ai_speed = 10000, .ai_pg = das16_pg_none, .ao = NULL, @@ -1365,7 +1366,7 @@ static const struct das16_board das16_boards[] = { .id = 0x20, }, { .name = "das-1401", - .ai_nbits = 12, + .ai_maxdata = 0x0fff, .ai_speed = 10000, .ai_pg = das16_pg_1601, .ao = NULL, @@ -1377,7 +1378,7 @@ static const struct das16_board das16_boards[] = { .id = 0xc0, }, { .name = "das-1402", - .ai_nbits = 12, + .ai_maxdata = 0x0fff, .ai_speed = 10000, .ai_pg = das16_pg_1602, .ao = NULL, @@ -1389,7 +1390,7 @@ static const struct das16_board das16_boards[] = { .id = 0xc0, }, { .name = "das-1601", - .ai_nbits = 12, + .ai_maxdata = 0x0fff, .ai_speed = 10000, .ai_pg = das16_pg_1601, .ao = das16_ao_winsn, @@ -1402,7 +1403,7 @@ static const struct das16_board das16_boards[] = { .id = 0xc0, }, { .name = "das-1602", - .ai_nbits = 12, + .ai_maxdata = 0x0fff, .ai_speed = 10000, .ai_pg = das16_pg_1602, .ao = das16_ao_winsn, @@ -1415,7 +1416,7 @@ static const struct das16_board das16_boards[] = { .id = 0xc0, }, { .name = "cio-das1401/12", - .ai_nbits = 12, + .ai_maxdata = 0x0fff, .ai_speed = 6250, .ai_pg = das16_pg_1601, .ao = NULL, @@ -1427,7 +1428,7 @@ static const struct das16_board das16_boards[] = { .id = 0xc0, }, { .name = "cio-das1402/12", - .ai_nbits = 12, + .ai_maxdata = 0x0fff, .ai_speed = 6250, .ai_pg = das16_pg_1602, .ao = NULL, @@ -1439,7 +1440,7 @@ static const struct das16_board das16_boards[] = { .id = 0xc0, }, { .name = "cio-das1402/16", - .ai_nbits = 16, + .ai_maxdata = 0xffff, .ai_speed = 10000, .ai_pg = das16_pg_1602, .ao = NULL, @@ -1451,7 +1452,7 @@ static const struct das16_board das16_boards[] = { .id = 0xc0, }, { .name = "cio-das1601/12", - .ai_nbits = 12, + .ai_maxdata = 0x0fff, .ai_speed = 6250, .ai_pg = das16_pg_1601, .ao = das16_ao_winsn, @@ -1464,7 +1465,7 @@ static const struct das16_board das16_boards[] = { .id = 0xc0, }, { .name = "cio-das1602/12", - .ai_nbits = 12, + .ai_maxdata = 0x0fff, .ai_speed = 10000, .ai_pg = das16_pg_1602, .ao = das16_ao_winsn, @@ -1477,7 +1478,7 @@ static const struct das16_board das16_boards[] = { .id = 0xc0, }, { .name = "cio-das1602/16", - .ai_nbits = 16, + .ai_maxdata = 0xffff, .ai_speed = 10000, .ai_pg = das16_pg_1602, .ao = das16_ao_winsn, @@ -1490,7 +1491,7 @@ static const struct das16_board das16_boards[] = { .id = 0xc0, }, { .name = "cio-das16/330", - .ai_nbits = 12, + .ai_maxdata = 0x0fff, .ai_speed = 3030, .ai_pg = das16_pg_16jr, .ao = NULL, From fb1864ba9535353530f43ae60386f00bc629a5bb Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 13:54:09 -0700 Subject: [PATCH 1192/3400] staging: comedi: das16: all supported board have digital inputs All the boards supported by this driver have digital inputs and all of then use the same function to handle the (*insn_bits) for the subdevice. Remove the 'di' member from the boardinfo and always initialize the digital input subdevice during the board attach. Tidy up the subdevice init a bit as well as the (*insn_bits) function. The (*insn_bits) function does not need to clear data[0]. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 53 ++++++-------------------- 1 file changed, 12 insertions(+), 41 deletions(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 11e5787dd27e..3528c8257a5c 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -343,7 +343,6 @@ struct das16_board { unsigned int ai_pg; void *ao; unsigned int ao_nbits; - void *di; void *do_; unsigned int i8255_offset; @@ -712,14 +711,12 @@ static int das16_ai_insn_read(struct comedi_device *dev, return n; } -static int das16_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int das16_di_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { - unsigned int bits; - - bits = inb(dev->iobase + DAS16_DIO) & 0xf; - data[1] = bits; - data[0] = 0; + data[1] = inb(dev->iobase + DAS16_DIO) & 0xf; return insn->n; } @@ -1149,18 +1146,14 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->type = COMEDI_SUBD_UNUSED; } + /* Digital Input subdevice */ s = &dev->subdevices[2]; - /* di */ - if (board->di) { - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE; - s->n_chan = 4; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = board->di; - } else { - s->type = COMEDI_SUBD_UNUSED; - } + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 4; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = das16_di_insn_bits; s = &dev->subdevices[3]; /* do */ @@ -1234,7 +1227,6 @@ static const struct das16_board das16_boards[] = { .ai_pg = das16_pg_none, .ao = das16_ao_winsn, .ao_nbits = 12, - .di = das16_di_rbits, .do_ = das16_do_wbits, .i8255_offset = 0x10, .i8254_offset = 0x0c, @@ -1247,7 +1239,6 @@ static const struct das16_board das16_boards[] = { .ai_pg = das16_pg_none, .ao = das16_ao_winsn, .ao_nbits = 12, - .di = das16_di_rbits, .do_ = das16_do_wbits, .i8255_offset = 0x10, .i8254_offset = 0x0c, @@ -1260,7 +1251,6 @@ static const struct das16_board das16_boards[] = { .ai_pg = das16_pg_none, .ao = das16_ao_winsn, .ao_nbits = 12, - .di = das16_di_rbits, .do_ = das16_do_wbits, .i8255_offset = 0x10, .i8254_offset = 0x0c, @@ -1273,7 +1263,6 @@ static const struct das16_board das16_boards[] = { .ai_pg = das16_pg_none, .ao = das16_ao_winsn, .ao_nbits = 12, - .di = das16_di_rbits, .do_ = das16_do_wbits, .i8255_offset = 0x10, .i8254_offset = 0x0c, @@ -1286,7 +1275,6 @@ static const struct das16_board das16_boards[] = { .ai_pg = das16_pg_none, .ao = das16_ao_winsn, .ao_nbits = 12, - .di = das16_di_rbits, .do_ = das16_do_wbits, .i8255_offset = 0x10, .i8254_offset = 0x0c, @@ -1298,7 +1286,6 @@ static const struct das16_board das16_boards[] = { .ai_speed = 7692, .ai_pg = das16_pg_16jr, .ao = NULL, - .di = das16_di_rbits, .do_ = das16_do_wbits, .i8255_offset = 0, .i8254_offset = 0x0c, @@ -1310,7 +1297,6 @@ static const struct das16_board das16_boards[] = { .ai_speed = 3300, .ai_pg = das16_pg_16jr, .ao = NULL, - .di = das16_di_rbits, .do_ = das16_do_wbits, .i8255_offset = 0, .i8254_offset = 0x0c, @@ -1322,7 +1308,6 @@ static const struct das16_board das16_boards[] = { .ai_speed = 10000, .ai_pg = das16_pg_16jr_16, .ao = NULL, - .di = das16_di_rbits, .do_ = das16_do_wbits, .i8255_offset = 0, .i8254_offset = 0x0c, @@ -1334,7 +1319,6 @@ static const struct das16_board das16_boards[] = { .ai_speed = 10000, .ai_pg = das16_pg_16jr_16, .ao = NULL, - .di = das16_di_rbits, .do_ = das16_do_wbits, .i8255_offset = 0, .i8254_offset = 0x0c, @@ -1346,7 +1330,6 @@ static const struct das16_board das16_boards[] = { .ai_speed = 20000, .ai_pg = das16_pg_none, .ao = NULL, - .di = das16_di_rbits, .do_ = das16_do_wbits, .i8255_offset = 0x400, .i8254_offset = 0x0c, @@ -1358,7 +1341,6 @@ static const struct das16_board das16_boards[] = { .ai_speed = 10000, .ai_pg = das16_pg_none, .ao = NULL, - .di = das16_di_rbits, .do_ = das16_do_wbits, .i8255_offset = 0x400, .i8254_offset = 0x0c, @@ -1370,7 +1352,6 @@ static const struct das16_board das16_boards[] = { .ai_speed = 10000, .ai_pg = das16_pg_1601, .ao = NULL, - .di = das16_di_rbits, .do_ = das16_do_wbits, .i8255_offset = 0x0, .i8254_offset = 0x0c, @@ -1382,7 +1363,6 @@ static const struct das16_board das16_boards[] = { .ai_speed = 10000, .ai_pg = das16_pg_1602, .ao = NULL, - .di = das16_di_rbits, .do_ = das16_do_wbits, .i8255_offset = 0x0, .i8254_offset = 0x0c, @@ -1395,7 +1375,6 @@ static const struct das16_board das16_boards[] = { .ai_pg = das16_pg_1601, .ao = das16_ao_winsn, .ao_nbits = 12, - .di = das16_di_rbits, .do_ = das16_do_wbits, .i8255_offset = 0x400, .i8254_offset = 0x0c, @@ -1408,7 +1387,6 @@ static const struct das16_board das16_boards[] = { .ai_pg = das16_pg_1602, .ao = das16_ao_winsn, .ao_nbits = 12, - .di = das16_di_rbits, .do_ = das16_do_wbits, .i8255_offset = 0x400, .i8254_offset = 0x0c, @@ -1420,7 +1398,6 @@ static const struct das16_board das16_boards[] = { .ai_speed = 6250, .ai_pg = das16_pg_1601, .ao = NULL, - .di = das16_di_rbits, .do_ = das16_do_wbits, .i8255_offset = 0, .i8254_offset = 0x0c, @@ -1432,7 +1409,6 @@ static const struct das16_board das16_boards[] = { .ai_speed = 6250, .ai_pg = das16_pg_1602, .ao = NULL, - .di = das16_di_rbits, .do_ = das16_do_wbits, .i8255_offset = 0, .i8254_offset = 0x0c, @@ -1444,7 +1420,6 @@ static const struct das16_board das16_boards[] = { .ai_speed = 10000, .ai_pg = das16_pg_1602, .ao = NULL, - .di = das16_di_rbits, .do_ = das16_do_wbits, .i8255_offset = 0, .i8254_offset = 0x0c, @@ -1457,7 +1432,6 @@ static const struct das16_board das16_boards[] = { .ai_pg = das16_pg_1601, .ao = das16_ao_winsn, .ao_nbits = 12, - .di = das16_di_rbits, .do_ = das16_do_wbits, .i8255_offset = 0x400, .i8254_offset = 0x0c, @@ -1470,7 +1444,6 @@ static const struct das16_board das16_boards[] = { .ai_pg = das16_pg_1602, .ao = das16_ao_winsn, .ao_nbits = 12, - .di = das16_di_rbits, .do_ = das16_do_wbits, .i8255_offset = 0x400, .i8254_offset = 0x0c, @@ -1483,7 +1456,6 @@ static const struct das16_board das16_boards[] = { .ai_pg = das16_pg_1602, .ao = das16_ao_winsn, .ao_nbits = 12, - .di = das16_di_rbits, .do_ = das16_do_wbits, .i8255_offset = 0x400, .i8254_offset = 0x0c, @@ -1495,7 +1467,6 @@ static const struct das16_board das16_boards[] = { .ai_speed = 3030, .ai_pg = das16_pg_16jr, .ao = NULL, - .di = das16_di_rbits, .do_ = das16_do_wbits, .i8255_offset = 0, .i8254_offset = 0x0c, From 6050cc918dd4c002ddebf76861c6d9f240c1a4dc Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 13:54:39 -0700 Subject: [PATCH 1193/3400] staging: comedi: das16: all supported board have digital outputs All the boards supported by this driver have digital outputs and all of then use the same function to handle the (*insn_bits) for the subdevice. Remove the 'do_' member from the boardinfo and always initialize the digital output subdevice during the board attach. Tidy up the subdevice init a bit as well as the (*insn_bits) function. Remove SDF_READABLE from the subdev_flags. This is a pure digital output subdevice and the outputs are not readable. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 72 ++++++++------------------ 1 file changed, 23 insertions(+), 49 deletions(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 3528c8257a5c..22d2bf423d66 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -343,7 +343,6 @@ struct das16_board { unsigned int ai_pg; void *ao; unsigned int ao_nbits; - void *do_; unsigned int i8255_offset; unsigned int i8254_offset; @@ -721,22 +720,22 @@ static int das16_di_insn_bits(struct comedi_device *dev, return insn->n; } -static int das16_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int das16_do_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { - unsigned int wbits; + unsigned int mask = data[0]; + unsigned int bits = data[1]; - /* only set bits that have been masked */ - data[0] &= 0xf; - wbits = s->state; - /* zero bits that have been masked */ - wbits &= ~data[0]; - /* set masked bits */ - wbits |= data[0] & data[1]; - s->state = wbits; - data[1] = wbits; + if (mask) { + s->state &= ~mask; + s->state |= (bits & mask); - outb(s->state, dev->iobase + DAS16_DIO); + outb(s->state, dev->iobase + DAS16_DIO); + } + + data[1] = s->state; return insn->n; } @@ -1155,20 +1154,17 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->range_table = &range_digital; s->insn_bits = das16_di_insn_bits; + /* Digital Output subdevice */ s = &dev->subdevices[3]; - /* do */ - if (board->do_) { - s->type = COMEDI_SUBD_DO; - s->subdev_flags = SDF_WRITABLE | SDF_READABLE; - s->n_chan = 4; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = board->do_; - /* initialize digital output lines */ - outb(s->state, dev->iobase + DAS16_DIO); - } else { - s->type = COMEDI_SUBD_UNUSED; - } + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 4; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = das16_do_insn_bits; + + /* initialize digital output lines */ + outb(s->state, dev->iobase + DAS16_DIO); s = &dev->subdevices[4]; /* 8255 */ @@ -1227,7 +1223,6 @@ static const struct das16_board das16_boards[] = { .ai_pg = das16_pg_none, .ao = das16_ao_winsn, .ao_nbits = 12, - .do_ = das16_do_wbits, .i8255_offset = 0x10, .i8254_offset = 0x0c, .size = 0x14, @@ -1239,7 +1234,6 @@ static const struct das16_board das16_boards[] = { .ai_pg = das16_pg_none, .ao = das16_ao_winsn, .ao_nbits = 12, - .do_ = das16_do_wbits, .i8255_offset = 0x10, .i8254_offset = 0x0c, .size = 0x14, @@ -1251,7 +1245,6 @@ static const struct das16_board das16_boards[] = { .ai_pg = das16_pg_none, .ao = das16_ao_winsn, .ao_nbits = 12, - .do_ = das16_do_wbits, .i8255_offset = 0x10, .i8254_offset = 0x0c, .size = 0x14, @@ -1263,7 +1256,6 @@ static const struct das16_board das16_boards[] = { .ai_pg = das16_pg_none, .ao = das16_ao_winsn, .ao_nbits = 12, - .do_ = das16_do_wbits, .i8255_offset = 0x10, .i8254_offset = 0x0c, .size = 0x14, @@ -1275,7 +1267,6 @@ static const struct das16_board das16_boards[] = { .ai_pg = das16_pg_none, .ao = das16_ao_winsn, .ao_nbits = 12, - .do_ = das16_do_wbits, .i8255_offset = 0x10, .i8254_offset = 0x0c, .size = 0x14, @@ -1286,7 +1277,6 @@ static const struct das16_board das16_boards[] = { .ai_speed = 7692, .ai_pg = das16_pg_16jr, .ao = NULL, - .do_ = das16_do_wbits, .i8255_offset = 0, .i8254_offset = 0x0c, .size = 0x10, @@ -1297,7 +1287,6 @@ static const struct das16_board das16_boards[] = { .ai_speed = 3300, .ai_pg = das16_pg_16jr, .ao = NULL, - .do_ = das16_do_wbits, .i8255_offset = 0, .i8254_offset = 0x0c, .size = 0x10, @@ -1308,7 +1297,6 @@ static const struct das16_board das16_boards[] = { .ai_speed = 10000, .ai_pg = das16_pg_16jr_16, .ao = NULL, - .do_ = das16_do_wbits, .i8255_offset = 0, .i8254_offset = 0x0c, .size = 0x10, @@ -1319,7 +1307,6 @@ static const struct das16_board das16_boards[] = { .ai_speed = 10000, .ai_pg = das16_pg_16jr_16, .ao = NULL, - .do_ = das16_do_wbits, .i8255_offset = 0, .i8254_offset = 0x0c, .size = 0x10, @@ -1330,7 +1317,6 @@ static const struct das16_board das16_boards[] = { .ai_speed = 20000, .ai_pg = das16_pg_none, .ao = NULL, - .do_ = das16_do_wbits, .i8255_offset = 0x400, .i8254_offset = 0x0c, .size = 0x408, @@ -1341,7 +1327,6 @@ static const struct das16_board das16_boards[] = { .ai_speed = 10000, .ai_pg = das16_pg_none, .ao = NULL, - .do_ = das16_do_wbits, .i8255_offset = 0x400, .i8254_offset = 0x0c, .size = 0x408, @@ -1352,7 +1337,6 @@ static const struct das16_board das16_boards[] = { .ai_speed = 10000, .ai_pg = das16_pg_1601, .ao = NULL, - .do_ = das16_do_wbits, .i8255_offset = 0x0, .i8254_offset = 0x0c, .size = 0x408, @@ -1363,7 +1347,6 @@ static const struct das16_board das16_boards[] = { .ai_speed = 10000, .ai_pg = das16_pg_1602, .ao = NULL, - .do_ = das16_do_wbits, .i8255_offset = 0x0, .i8254_offset = 0x0c, .size = 0x408, @@ -1375,7 +1358,6 @@ static const struct das16_board das16_boards[] = { .ai_pg = das16_pg_1601, .ao = das16_ao_winsn, .ao_nbits = 12, - .do_ = das16_do_wbits, .i8255_offset = 0x400, .i8254_offset = 0x0c, .size = 0x408, @@ -1387,7 +1369,6 @@ static const struct das16_board das16_boards[] = { .ai_pg = das16_pg_1602, .ao = das16_ao_winsn, .ao_nbits = 12, - .do_ = das16_do_wbits, .i8255_offset = 0x400, .i8254_offset = 0x0c, .size = 0x408, @@ -1398,7 +1379,6 @@ static const struct das16_board das16_boards[] = { .ai_speed = 6250, .ai_pg = das16_pg_1601, .ao = NULL, - .do_ = das16_do_wbits, .i8255_offset = 0, .i8254_offset = 0x0c, .size = 0x408, @@ -1409,7 +1389,6 @@ static const struct das16_board das16_boards[] = { .ai_speed = 6250, .ai_pg = das16_pg_1602, .ao = NULL, - .do_ = das16_do_wbits, .i8255_offset = 0, .i8254_offset = 0x0c, .size = 0x408, @@ -1420,7 +1399,6 @@ static const struct das16_board das16_boards[] = { .ai_speed = 10000, .ai_pg = das16_pg_1602, .ao = NULL, - .do_ = das16_do_wbits, .i8255_offset = 0, .i8254_offset = 0x0c, .size = 0x408, @@ -1432,7 +1410,6 @@ static const struct das16_board das16_boards[] = { .ai_pg = das16_pg_1601, .ao = das16_ao_winsn, .ao_nbits = 12, - .do_ = das16_do_wbits, .i8255_offset = 0x400, .i8254_offset = 0x0c, .size = 0x408, @@ -1444,7 +1421,6 @@ static const struct das16_board das16_boards[] = { .ai_pg = das16_pg_1602, .ao = das16_ao_winsn, .ao_nbits = 12, - .do_ = das16_do_wbits, .i8255_offset = 0x400, .i8254_offset = 0x0c, .size = 0x408, @@ -1456,7 +1432,6 @@ static const struct das16_board das16_boards[] = { .ai_pg = das16_pg_1602, .ao = das16_ao_winsn, .ao_nbits = 12, - .do_ = das16_do_wbits, .i8255_offset = 0x400, .i8254_offset = 0x0c, .size = 0x408, @@ -1467,7 +1442,6 @@ static const struct das16_board das16_boards[] = { .ai_speed = 3030, .ai_pg = das16_pg_16jr, .ao = NULL, - .do_ = das16_do_wbits, .i8255_offset = 0, .i8254_offset = 0x0c, .size = 0x14, From 6d063851933584ab812f59bb0cdfb16d584ac5b0 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 13:55:00 -0700 Subject: [PATCH 1194/3400] staging: comedi: das16: cleanup analog output subdevice All the boards supported by this driver that have analog outputs use the same function to handle the (*insn_write) for the subdevice. They all also have 12-bit resolution (maxdata = 0x0fff). Remove the 'ao' and 'ao_nbits' members from the boardinfo and replace them with a simple bit-field flag 'has_ao'. Tidy up the subdevice init a bit as well as the (*insn_write) function. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 95 +++++++++----------------- 1 file changed, 33 insertions(+), 62 deletions(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 22d2bf423d66..bad39d79b2c3 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -341,8 +341,7 @@ struct das16_board { unsigned int ai_maxdata; unsigned int ai_speed; /* max conversion speed in nanosec */ unsigned int ai_pg; - void *ao; - unsigned int ao_nbits; + unsigned int has_ao:1; unsigned int i8255_offset; unsigned int i8254_offset; @@ -740,29 +739,24 @@ static int das16_do_insn_bits(struct comedi_device *dev, return insn->n; } -static int das16_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int das16_ao_insn_write(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { - const struct das16_board *board = comedi_board(dev); + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int val; int i; - int lsb, msb; - int chan; - - chan = CR_CHAN(insn->chanspec); for (i = 0; i < insn->n; i++) { - if (board->ao_nbits == 12) { - lsb = (data[i] << 4) & 0xff; - msb = (data[i] >> 4) & 0xff; - } else { - lsb = data[i] & 0xff; - msb = (data[i] >> 8) & 0xff; - } - outb(lsb, dev->iobase + DAS16_AO_LSB(chan)); - outb(msb, dev->iobase + DAS16_AO_MSB(chan)); + val = data[i]; + val <<= 4; + + outb(val & 0xff, dev->iobase + DAS16_AO_LSB(chan)); + outb((val >> 8) & 0xff, dev->iobase + DAS16_AO_MSB(chan)); } - return i; + return insn->n; } /* the pc104-das16jr (at least) has problems if the dma @@ -1127,22 +1121,21 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->munge = das16_ai_munge; } + /* Analog Output subdevice */ s = &dev->subdevices[1]; - /* ao */ - if (board->ao) { - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = 2; - s->maxdata = (1 << board->ao_nbits) - 1; - /* user defined ao range */ + if (board->has_ao) { + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 2; + s->maxdata = 0x0fff; if (devpriv->user_ao_range_table) - s->range_table = devpriv->user_ao_range_table; + s->range_table = devpriv->user_ao_range_table; else - s->range_table = &range_unknown; + s->range_table = &range_unknown; - s->insn_write = board->ao; + s->insn_write = das16_ao_insn_write; } else { - s->type = COMEDI_SUBD_UNUSED; + s->type = COMEDI_SUBD_UNUSED; } /* Digital Input subdevice */ @@ -1221,8 +1214,7 @@ static const struct das16_board das16_boards[] = { .ai_maxdata = 0x0fff, .ai_speed = 15000, .ai_pg = das16_pg_none, - .ao = das16_ao_winsn, - .ao_nbits = 12, + .has_ao = 1, .i8255_offset = 0x10, .i8254_offset = 0x0c, .size = 0x14, @@ -1232,8 +1224,7 @@ static const struct das16_board das16_boards[] = { .ai_maxdata = 0x0fff, .ai_speed = 15000, .ai_pg = das16_pg_none, - .ao = das16_ao_winsn, - .ao_nbits = 12, + .has_ao = 1, .i8255_offset = 0x10, .i8254_offset = 0x0c, .size = 0x14, @@ -1243,8 +1234,7 @@ static const struct das16_board das16_boards[] = { .ai_maxdata = 0x0fff, .ai_speed = 8500, .ai_pg = das16_pg_none, - .ao = das16_ao_winsn, - .ao_nbits = 12, + .has_ao = 1, .i8255_offset = 0x10, .i8254_offset = 0x0c, .size = 0x14, @@ -1254,8 +1244,7 @@ static const struct das16_board das16_boards[] = { .ai_maxdata = 0x0fff, .ai_speed = 20000, .ai_pg = das16_pg_none, - .ao = das16_ao_winsn, - .ao_nbits = 12, + .has_ao = 1, .i8255_offset = 0x10, .i8254_offset = 0x0c, .size = 0x14, @@ -1265,8 +1254,7 @@ static const struct das16_board das16_boards[] = { .ai_maxdata = 0x0fff, .ai_speed = 10000, .ai_pg = das16_pg_none, - .ao = das16_ao_winsn, - .ao_nbits = 12, + .has_ao = 1, .i8255_offset = 0x10, .i8254_offset = 0x0c, .size = 0x14, @@ -1276,7 +1264,6 @@ static const struct das16_board das16_boards[] = { .ai_maxdata = 0x0fff, .ai_speed = 7692, .ai_pg = das16_pg_16jr, - .ao = NULL, .i8255_offset = 0, .i8254_offset = 0x0c, .size = 0x10, @@ -1286,7 +1273,6 @@ static const struct das16_board das16_boards[] = { .ai_maxdata = 0x0fff, .ai_speed = 3300, .ai_pg = das16_pg_16jr, - .ao = NULL, .i8255_offset = 0, .i8254_offset = 0x0c, .size = 0x10, @@ -1296,7 +1282,6 @@ static const struct das16_board das16_boards[] = { .ai_maxdata = 0xffff, .ai_speed = 10000, .ai_pg = das16_pg_16jr_16, - .ao = NULL, .i8255_offset = 0, .i8254_offset = 0x0c, .size = 0x10, @@ -1306,7 +1291,6 @@ static const struct das16_board das16_boards[] = { .ai_maxdata = 0xffff, .ai_speed = 10000, .ai_pg = das16_pg_16jr_16, - .ao = NULL, .i8255_offset = 0, .i8254_offset = 0x0c, .size = 0x10, @@ -1316,7 +1300,6 @@ static const struct das16_board das16_boards[] = { .ai_maxdata = 0x0fff, .ai_speed = 20000, .ai_pg = das16_pg_none, - .ao = NULL, .i8255_offset = 0x400, .i8254_offset = 0x0c, .size = 0x408, @@ -1326,7 +1309,6 @@ static const struct das16_board das16_boards[] = { .ai_maxdata = 0x0fff, .ai_speed = 10000, .ai_pg = das16_pg_none, - .ao = NULL, .i8255_offset = 0x400, .i8254_offset = 0x0c, .size = 0x408, @@ -1336,7 +1318,6 @@ static const struct das16_board das16_boards[] = { .ai_maxdata = 0x0fff, .ai_speed = 10000, .ai_pg = das16_pg_1601, - .ao = NULL, .i8255_offset = 0x0, .i8254_offset = 0x0c, .size = 0x408, @@ -1346,7 +1327,6 @@ static const struct das16_board das16_boards[] = { .ai_maxdata = 0x0fff, .ai_speed = 10000, .ai_pg = das16_pg_1602, - .ao = NULL, .i8255_offset = 0x0, .i8254_offset = 0x0c, .size = 0x408, @@ -1356,8 +1336,7 @@ static const struct das16_board das16_boards[] = { .ai_maxdata = 0x0fff, .ai_speed = 10000, .ai_pg = das16_pg_1601, - .ao = das16_ao_winsn, - .ao_nbits = 12, + .has_ao = 1, .i8255_offset = 0x400, .i8254_offset = 0x0c, .size = 0x408, @@ -1367,8 +1346,7 @@ static const struct das16_board das16_boards[] = { .ai_maxdata = 0x0fff, .ai_speed = 10000, .ai_pg = das16_pg_1602, - .ao = das16_ao_winsn, - .ao_nbits = 12, + .has_ao = 1, .i8255_offset = 0x400, .i8254_offset = 0x0c, .size = 0x408, @@ -1378,7 +1356,6 @@ static const struct das16_board das16_boards[] = { .ai_maxdata = 0x0fff, .ai_speed = 6250, .ai_pg = das16_pg_1601, - .ao = NULL, .i8255_offset = 0, .i8254_offset = 0x0c, .size = 0x408, @@ -1388,7 +1365,6 @@ static const struct das16_board das16_boards[] = { .ai_maxdata = 0x0fff, .ai_speed = 6250, .ai_pg = das16_pg_1602, - .ao = NULL, .i8255_offset = 0, .i8254_offset = 0x0c, .size = 0x408, @@ -1398,7 +1374,6 @@ static const struct das16_board das16_boards[] = { .ai_maxdata = 0xffff, .ai_speed = 10000, .ai_pg = das16_pg_1602, - .ao = NULL, .i8255_offset = 0, .i8254_offset = 0x0c, .size = 0x408, @@ -1408,8 +1383,7 @@ static const struct das16_board das16_boards[] = { .ai_maxdata = 0x0fff, .ai_speed = 6250, .ai_pg = das16_pg_1601, - .ao = das16_ao_winsn, - .ao_nbits = 12, + .has_ao = 1, .i8255_offset = 0x400, .i8254_offset = 0x0c, .size = 0x408, @@ -1419,8 +1393,7 @@ static const struct das16_board das16_boards[] = { .ai_maxdata = 0x0fff, .ai_speed = 10000, .ai_pg = das16_pg_1602, - .ao = das16_ao_winsn, - .ao_nbits = 12, + .has_ao = 1, .i8255_offset = 0x400, .i8254_offset = 0x0c, .size = 0x408, @@ -1430,8 +1403,7 @@ static const struct das16_board das16_boards[] = { .ai_maxdata = 0xffff, .ai_speed = 10000, .ai_pg = das16_pg_1602, - .ao = das16_ao_winsn, - .ao_nbits = 12, + .has_ao = 1, .i8255_offset = 0x400, .i8254_offset = 0x0c, .size = 0x408, @@ -1441,7 +1413,6 @@ static const struct das16_board das16_boards[] = { .ai_maxdata = 0x0fff, .ai_speed = 3030, .ai_pg = das16_pg_16jr, - .ao = NULL, .i8255_offset = 0, .i8254_offset = 0x0c, .size = 0x14, From 6d33b860cdfe5ab3c4dca57104abb8f0d4c9cb8b Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 13:55:20 -0700 Subject: [PATCH 1195/3400] staging: comedi: das16: tidy up the comedi_lrange tables Cleanup the whitespace in the tables. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 97 ++++++++++++++------------ 1 file changed, 51 insertions(+), 46 deletions(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index bad39d79b2c3..93c3a8866bef 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -238,62 +238,67 @@ static const int sample_size = 2; #define DAS1600_WS 0x02 #define DAS1600_CLK_10MHZ 0x01 -static const struct comedi_lrange range_das1x01_bip = { 4, { - BIP_RANGE(10), - BIP_RANGE(1), - BIP_RANGE(0.1), - BIP_RANGE(0.01), - } +static const struct comedi_lrange range_das1x01_bip = { + 4, { + BIP_RANGE(10), + BIP_RANGE(1), + BIP_RANGE(0.1), + BIP_RANGE(0.01) + } }; -static const struct comedi_lrange range_das1x01_unip = { 4, { - UNI_RANGE(10), - UNI_RANGE(1), - UNI_RANGE(0.1), - UNI_RANGE(0.01), - } +static const struct comedi_lrange range_das1x01_unip = { + 4, { + UNI_RANGE(10), + UNI_RANGE(1), + UNI_RANGE(0.1), + UNI_RANGE(0.01) + } }; -static const struct comedi_lrange range_das1x02_bip = { 4, { - BIP_RANGE(10), - BIP_RANGE(5), - BIP_RANGE(2.5), - BIP_RANGE(1.25), - } +static const struct comedi_lrange range_das1x02_bip = { + 4, { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25) + } }; -static const struct comedi_lrange range_das1x02_unip = { 4, { - UNI_RANGE(10), - UNI_RANGE(5), - UNI_RANGE(2.5), - UNI_RANGE(1.25), - } +static const struct comedi_lrange range_das1x02_unip = { + 4, { + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2.5), + UNI_RANGE(1.25) + } }; -static const struct comedi_lrange range_das16jr = { 9, { - /* also used by 16/330 */ - BIP_RANGE(10), - BIP_RANGE(5), - BIP_RANGE(2.5), - BIP_RANGE(1.25), - BIP_RANGE(0.625), - UNI_RANGE(10), - UNI_RANGE(5), - UNI_RANGE(2.5), - UNI_RANGE(1.25), - } +static const struct comedi_lrange range_das16jr = { + 9, { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25), + BIP_RANGE(0.625), + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2.5), + UNI_RANGE(1.25) + } }; -static const struct comedi_lrange range_das16jr_16 = { 8, { - BIP_RANGE(10), - BIP_RANGE(5), - BIP_RANGE(2.5), - BIP_RANGE(1.25), - UNI_RANGE(10), - UNI_RANGE(5), - UNI_RANGE(2.5), - UNI_RANGE(1.25), - } +static const struct comedi_lrange range_das16jr_16 = { + 8, { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25), + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2.5), + UNI_RANGE(1.25) + } }; static const int das16jr_gainlist[] = { 8, 0, 1, 2, 3, 4, 5, 6, 7 }; From 0837e209b3519517dd252d31af02d42368ddfcc6 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 13:55:38 -0700 Subject: [PATCH 1196/3400] staging: comedi: das16: remove unused struct definition This struct is not used by the driver. Remove it. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 93c3a8866bef..14d2aa057b88 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -336,11 +336,6 @@ static const struct comedi_lrange *const das16_ai_bip_lranges[] = { &range_das1x02_bip, }; -struct munge_info { - uint8_t byte; - unsigned have_byte:1; -}; - struct das16_board { const char *name; unsigned int ai_maxdata; From 1aa4694fb6bd5c0cdadb6d7ba0723186f5198c1b Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 13:56:02 -0700 Subject: [PATCH 1197/3400] staging: comedi: das16: remove 'ai_unipolar' and 'ai_singleended' These members in the private data are only used during the board attach. Move the reading of the status register to the board attach and just check the value where needed when initializing the analog input subdevice. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 28 +++++--------------------- 1 file changed, 5 insertions(+), 23 deletions(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 14d2aa057b88..ccb0acde6334 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -360,8 +360,6 @@ static inline int timer_period(void) } struct das16_private_struct { - unsigned int ai_unipolar; /* unipolar flag */ - unsigned int ai_singleended; /* single ended flag */ unsigned int clockbase; /* master clock speed in ns */ volatile unsigned int control_state; /* dma, interrupt and trigger control bits */ volatile unsigned long adc_byte_count; /* number of bytes remaining */ @@ -891,28 +889,9 @@ static void reg_dump(struct comedi_device *dev) static int das16_probe(struct comedi_device *dev, struct comedi_devconfig *it) { const struct das16_board *board = comedi_board(dev); - struct das16_private_struct *devpriv = dev->private; - int status; int diobits; - /* status is available on all boards */ - - status = inb(dev->iobase + DAS16_STATUS); - - if ((status & UNIPOLAR)) - devpriv->ai_unipolar = 1; - else - devpriv->ai_unipolar = 0; - - - if ((status & DAS16_MUXBIT)) - devpriv->ai_singleended = 1; - else - devpriv->ai_singleended = 0; - - /* diobits indicates boards */ - diobits = inb(dev->iobase + DAS16_DIO) & 0xf0; printk(KERN_INFO " id bits are 0x%02x\n", diobits); @@ -976,6 +955,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) struct comedi_krange *user_ai_range; struct comedi_krange *user_ao_range; unsigned int dma_chan = it->options[2]; + unsigned int status; int ret; /* check that clock setting is valid */ @@ -1091,11 +1071,13 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; + status = inb(dev->iobase + DAS16_STATUS); + /* Analog Input subdevice */ s = &dev->subdevices[0]; s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE; - if (devpriv->ai_singleended) { + if (status & DAS16_MUXBIT) { s->subdev_flags |= SDF_GROUND; s->n_chan = 16; } else { @@ -1106,7 +1088,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->maxdata = board->ai_maxdata; if (devpriv->user_ai_range_table) { /* user defined ai range */ s->range_table = devpriv->user_ai_range_table; - } else if (devpriv->ai_unipolar) { + } else if (status & UNIPOLAR) { s->range_table = das16_ai_uni_lranges[board->ai_pg]; } else { s->range_table = das16_ai_bip_lranges[board->ai_pg]; From 9960ad37cf501336450048137c61be21cb0c5672 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 13:56:21 -0700 Subject: [PATCH 1198/3400] staging: comedi: das16: remove reg_dump() This function just prints some development debug information. There is no reason to leave this in the final driver. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index ccb0acde6334..ae3a3eaef3d9 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -868,24 +868,6 @@ static void das16_timer_interrupt(unsigned long arg) mod_timer(&devpriv->timer, jiffies + timer_period()); } -static void reg_dump(struct comedi_device *dev) -{ - DEBUG_PRINT("********DAS1600 REGISTER DUMP********\n"); - DEBUG_PRINT("DAS16_MUX: %x\n", inb(dev->iobase + DAS16_MUX)); - DEBUG_PRINT("DAS16_DIO: %x\n", inb(dev->iobase + DAS16_DIO)); - DEBUG_PRINT("DAS16_STATUS: %x\n", inb(dev->iobase + DAS16_STATUS)); - DEBUG_PRINT("DAS16_CONTROL: %x\n", inb(dev->iobase + DAS16_CONTROL)); - DEBUG_PRINT("DAS16_PACER: %x\n", inb(dev->iobase + DAS16_PACER)); - DEBUG_PRINT("DAS16_GAIN: %x\n", inb(dev->iobase + DAS16_GAIN)); - DEBUG_PRINT("DAS16_CNTR_CONTROL: %x\n", - inb(dev->iobase + DAS16_CNTR_CONTROL)); - DEBUG_PRINT("DAS1600_CONV: %x\n", inb(dev->iobase + DAS1600_CONV)); - DEBUG_PRINT("DAS1600_BURST: %x\n", inb(dev->iobase + DAS1600_BURST)); - DEBUG_PRINT("DAS1600_ENABLE: %x\n", inb(dev->iobase + DAS1600_ENABLE)); - DEBUG_PRINT("DAS1600_STATUS_B: %x\n", - inb(dev->iobase + DAS1600_STATUS_B)); -} - static int das16_probe(struct comedi_device *dev, struct comedi_devconfig *it) { const struct das16_board *board = comedi_board(dev); @@ -918,8 +900,6 @@ static int das1600_mode_detect(struct comedi_device *dev) printk(KERN_INFO " 1MHz pacer clock\n"); } - reg_dump(dev); - return 0; } From 66eca8575525a725a105aec5ca3a5cfa57ecd524 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 13:56:38 -0700 Subject: [PATCH 1199/3400] staging: comedi: das16: remove DEBUG_PRINT macro This macro outputs some printk() debug info that is just added noise. Remove it as well as the DEBUG stuff. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index ae3a3eaef3d9..d86ed2cce7c0 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -86,16 +86,6 @@ www.measurementcomputing.com #include "8255.h" #include "comedi_fc.h" -#undef DEBUG -/* #define DEBUG */ - -#ifdef DEBUG -#define DEBUG_PRINT(format, args...) \ - printk(KERN_DEBUG "das16: " format, ## args) -#else -#define DEBUG_PRINT(format, args...) -#endif - #define DAS16_SIZE 20 /* number of ioports */ #define DAS16_DMA_SIZE 0xff00 /* size in bytes of allocated dma buffer */ @@ -566,7 +556,6 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) cmd->convert_arg = das16_set_pacer(dev, cmd->convert_arg, cmd->flags & TRIG_ROUND_MASK); - DEBUG_PRINT("pacer period: %d ns\n", cmd->convert_arg); /* enable counters */ byte = 0; @@ -814,7 +803,6 @@ static void das16_interrupt(struct comedi_device *dev) spin_lock_irqsave(&dev->spinlock, spin_flags); if ((devpriv->control_state & DMA_ENABLE) == 0) { spin_unlock_irqrestore(&dev->spinlock, spin_flags); - DEBUG_PRINT("interrupt while dma disabled?\n"); return; } From 6f63840447030b32662d8d425b36e8fabd7799cf Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 13:56:59 -0700 Subject: [PATCH 1200/3400] staging: comedi: das16: remove 'volatile' on private data variables As indicated by checkpatch.pl, "WARNING: Use of volatile is usually wrong: ...". The variables in the private data that are marked volatile don't need to be. Remove the volatile. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index d86ed2cce7c0..95261a617623 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -351,8 +351,8 @@ static inline int timer_period(void) struct das16_private_struct { unsigned int clockbase; /* master clock speed in ns */ - volatile unsigned int control_state; /* dma, interrupt and trigger control bits */ - volatile unsigned long adc_byte_count; /* number of bytes remaining */ + unsigned int control_state; /* dma, interrupt and trigger control bits */ + unsigned long adc_byte_count; /* number of bytes remaining */ /* divisor dividing master clock to get conversion frequency */ unsigned int divisor1; /* divisor dividing master clock to get conversion frequency */ @@ -361,7 +361,7 @@ struct das16_private_struct { uint16_t *dma_buffer[2]; dma_addr_t dma_buffer_addr[2]; unsigned int current_buffer; - volatile unsigned int dma_transfer_size; /* target number of bytes to transfer per dma shot */ + unsigned int dma_transfer_size; /* target number of bytes to transfer per dma shot */ /** * user-defined analog input and output ranges * defined from config options @@ -370,7 +370,7 @@ struct das16_private_struct { struct comedi_lrange *user_ao_range_table; struct timer_list timer; /* for timed interrupt */ - volatile short timer_running; + short timer_running; unsigned long extra_iobase; }; From 96334bfebf5697dce1dba23c0abdf1683a733c52 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 13:57:18 -0700 Subject: [PATCH 1201/3400] staging: comedi: das16: add a 'can_burst' flag to the private data If the boardinfo 'size' is > 0x400 it indicates that the board has additional registers that allow bursting of analog input data. To better indicate this add a flag to the private data. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 31 ++++++++++---------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 95261a617623..009c074b664b 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -373,6 +373,7 @@ struct das16_private_struct { short timer_running; unsigned long extra_iobase; + unsigned int can_burst:1; }; static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s, @@ -389,15 +390,13 @@ static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s, err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); mask = TRIG_FOLLOW; - /* if board supports burst mode */ - if (board->size > 0x400) + if (devpriv->can_burst) mask |= TRIG_TIMER | TRIG_EXT; err |= cfc_check_trigger_src(&cmd->scan_begin_src, mask); tmp = cmd->convert_src; mask = TRIG_TIMER | TRIG_EXT; - /* if board supports burst mode */ - if (board->size > 0x400) + if (devpriv->can_burst) mask |= TRIG_NOW; err |= cfc_check_trigger_src(&cmd->convert_src, mask); @@ -534,8 +533,7 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->adc_byte_count = cmd->stop_arg * cmd->chanlist_len * sizeof(uint16_t); - /* disable conversions for das1600 mode */ - if (board->size > 0x400) + if (devpriv->can_burst) outb(DAS1600_CONV_DISABLE, dev->iobase + DAS1600_CONV); /* set scan limits */ @@ -559,8 +557,7 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) /* enable counters */ byte = 0; - /* Enable burst mode if appropriate. */ - if (board->size > 0x400) { + if (devpriv->can_burst) { if (cmd->convert_src == TRIG_NOW) { outb(DAS1600_BURST_VAL, dev->iobase + DAS1600_BURST); /* set burst length */ @@ -598,8 +595,7 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->control_state |= INT_PACER; outb(devpriv->control_state, dev->iobase + DAS16_CONTROL); - /* Enable conversions if using das1600 mode */ - if (board->size > 0x400) + if (devpriv->can_burst) outb(0, dev->iobase + DAS1600_CONV); @@ -608,7 +604,6 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { - const struct das16_board *board = comedi_board(dev); struct das16_private_struct *devpriv = dev->private; unsigned long flags; @@ -624,11 +619,9 @@ static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s) del_timer(&devpriv->timer); } - /* disable burst mode */ - if (board->size > 0x400) + if (devpriv->can_burst) outb(0, dev->iobase + DAS1600_BURST); - spin_unlock_irqrestore(&dev->spinlock, flags); return 0; @@ -955,6 +948,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; devpriv->extra_iobase = dev->iobase + 0x400; + devpriv->can_burst = 1; } /* probe id bits to make sure they are consistent */ @@ -964,13 +958,13 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) } /* get master clock speed */ - if (board->size < 0x400) { + if (devpriv->can_burst) { + das1600_mode_detect(dev); + } else { if (it->options[3]) devpriv->clockbase = 1000 / it->options[3]; else devpriv->clockbase = 1000; /* 1 MHz default */ - } else { - das1600_mode_detect(dev); } /* initialize dma */ @@ -1123,8 +1117,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->control_state = DAS16_IRQ(dev->irq); outb(devpriv->control_state, dev->iobase + DAS16_CONTROL); - /* turn on das1600 mode if available */ - if (board->size > 0x400) { + if (devpriv->can_burst) { outb(DAS1600_ENABLE_VAL, dev->iobase + DAS1600_ENABLE); outb(0, dev->iobase + DAS1600_CONV); outb(0, dev->iobase + DAS1600_BURST); From 3f7890eb24f4e8ce4f70c39595a34bdd31293033 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 13:57:38 -0700 Subject: [PATCH 1202/3400] staging: comedi: das16: remove unused DAS16_SIZE This define is not used in the driver. Remove it. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 009c074b664b..577e2a842845 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -86,7 +86,6 @@ www.measurementcomputing.com #include "8255.h" #include "comedi_fc.h" -#define DAS16_SIZE 20 /* number of ioports */ #define DAS16_DMA_SIZE 0xff00 /* size in bytes of allocated dma buffer */ /* From 6f8f6b2d4f5255eb91d0cc2643daf3f7d48a14f1 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 13:57:58 -0700 Subject: [PATCH 1203/3400] staging: comedi: das16: remove unused static const variable This variable is not used in the driver. Remove it. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 577e2a842845..96c081b48d07 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -174,9 +174,6 @@ www.measurementcomputing.com */ -/* size in bytes of a sample from board */ -static const int sample_size = 2; - #define DAS16_TRIG 0 #define DAS16_AI_LSB 0 #define DAS16_AI_MSB 1 From 9336140c49465a16e0fdd8385753020e275ec7d4 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 13:58:17 -0700 Subject: [PATCH 1204/3400] staging: comedi: das16: remove the register map comments This is just extra cruft. Remove it. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 87 +------------------------- 1 file changed, 2 insertions(+), 85 deletions(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 96c081b48d07..bd5f516f361c 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -89,91 +89,8 @@ www.measurementcomputing.com #define DAS16_DMA_SIZE 0xff00 /* size in bytes of allocated dma buffer */ /* - cio-das16.pdf - - "das16" - "das16/f" - - 0 a/d bits 0-3 start 12 bit - 1 a/d bits 4-11 unused - 2 mux read mux set - 3 di 4 bit do 4 bit - 4 unused ao0_lsb - 5 unused ao0_msb - 6 unused ao1_lsb - 7 unused ao1_msb - 8 status eoc uni/bip interrupt reset - 9 dma, int, trig ctrl set dma, int - a pacer control unused - b reserved reserved - cdef 8254 - 0123 8255 - -*/ - -/* - cio-das16jr.pdf - - "das16jr" - - 0 a/d bits 0-3 start 12 bit - 1 a/d bits 4-11 unused - 2 mux read mux set - 3 di 4 bit do 4 bit - 4567 unused unused - 8 status eoc uni/bip interrupt reset - 9 dma, int, trig ctrl set dma, int - a pacer control unused - b gain status gain control - cdef 8254 - -*/ - -/* - cio-das16jr_16.pdf - - "das16jr_16" - - 0 a/d bits 0-7 start 16 bit - 1 a/d bits 8-15 unused - 2 mux read mux set - 3 di 4 bit do 4 bit - 4567 unused unused - 8 status eoc uni/bip interrupt reset - 9 dma, int, trig ctrl set dma, int - a pacer control unused - b gain status gain control - cdef 8254 - -*/ -/* - cio-das160x-1x.pdf - - "das1601/12" - "das1602/12" - "das1602/16" - - 0 a/d bits 0-3 start 12 bit - 1 a/d bits 4-11 unused - 2 mux read mux set - 3 di 4 bit do 4 bit - 4 unused ao0_lsb - 5 unused ao0_msb - 6 unused ao1_lsb - 7 unused ao1_msb - 8 status eoc uni/bip interrupt reset - 9 dma, int, trig ctrl set dma, int - a pacer control unused - b gain status gain control - cdef 8254 - 400 8255 - 404 unused conversion enable - 405 unused burst enable - 406 unused das1600 enable - 407 status - -*/ - + * Register I/O map + */ #define DAS16_TRIG 0 #define DAS16_AI_LSB 0 #define DAS16_AI_MSB 1 From b53ceaf71af836bfc209b68f5d6c7c93895c7329 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 13:58:36 -0700 Subject: [PATCH 1205/3400] staging: comedi: das16: introduce das16_ai_{en, dis}able() helpers Introduce a couple helper functions to enable and disable the analog input interrupt/dma conversions. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 53 ++++++++++++++++---------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index bd5f516f361c..f6d0f7e868b2 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -264,7 +264,7 @@ static inline int timer_period(void) struct das16_private_struct { unsigned int clockbase; /* master clock speed in ns */ - unsigned int control_state; /* dma, interrupt and trigger control bits */ + unsigned int ctrl_reg; unsigned long adc_byte_count; /* number of bytes remaining */ /* divisor dividing master clock to get conversion frequency */ unsigned int divisor1; @@ -289,6 +289,30 @@ struct das16_private_struct { unsigned int can_burst:1; }; +static void das16_ai_enable(struct comedi_device *dev, + unsigned int mode, unsigned int src) +{ + struct das16_private_struct *devpriv = dev->private; + + devpriv->ctrl_reg &= ~(DAS16_INTE | DMA_ENABLE | PACING_MASK); + devpriv->ctrl_reg |= mode; + + if (src == TRIG_EXT) + devpriv->ctrl_reg |= EXT_PACER; + else + devpriv->ctrl_reg |= INT_PACER; + outb(devpriv->ctrl_reg, dev->iobase + DAS16_CONTROL); +} + +static void das16_ai_disable(struct comedi_device *dev) +{ + struct das16_private_struct *devpriv = dev->private; + + /* disable interrupts, dma and pacer clocked conversions */ + devpriv->ctrl_reg &= ~(DAS16_INTE | DMA_ENABLE | PACING_MASK); + outb(devpriv->ctrl_reg, dev->iobase + DAS16_CONTROL); +} + static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { @@ -499,19 +523,12 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->timer_running = 1; devpriv->timer.expires = jiffies + timer_period(); add_timer(&devpriv->timer); - devpriv->control_state &= ~DAS16_INTE; - devpriv->control_state |= DMA_ENABLE; - devpriv->control_state &= ~PACING_MASK; - if (cmd->convert_src == TRIG_EXT) - devpriv->control_state |= EXT_PACER; - else - devpriv->control_state |= INT_PACER; - outb(devpriv->control_state, dev->iobase + DAS16_CONTROL); + + das16_ai_enable(dev, DMA_ENABLE, cmd->convert_src); if (devpriv->can_burst) outb(0, dev->iobase + DAS1600_CONV); - return 0; } @@ -521,9 +538,8 @@ static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s) unsigned long flags; spin_lock_irqsave(&dev->spinlock, flags); - /* disable interrupts, dma and pacer clocked conversions */ - devpriv->control_state &= ~DAS16_INTE & ~PACING_MASK & ~DMA_ENABLE; - outb(devpriv->control_state, dev->iobase + DAS16_CONTROL); + + das16_ai_disable(dev); disable_dma(devpriv->dma_chan); /* disable SW timer */ @@ -554,14 +570,11 @@ static int das16_ai_insn_read(struct comedi_device *dev, unsigned int *data) { const struct das16_board *board = comedi_board(dev); - struct das16_private_struct *devpriv = dev->private; int i, n; int range; int chan; - /* disable interrupts and pacing */ - devpriv->control_state &= ~DAS16_INTE & ~DMA_ENABLE & ~PACING_MASK; - outb(devpriv->control_state, dev->iobase + DAS16_CONTROL); + das16_ai_disable(dev); /* set multiplexer */ chan = CR_CHAN(insn->chanspec); @@ -707,7 +720,7 @@ static void das16_interrupt(struct comedi_device *dev) cmd = &async->cmd; spin_lock_irqsave(&dev->spinlock, spin_flags); - if ((devpriv->control_state & DMA_ENABLE) == 0) { + if ((devpriv->ctrl_reg & DMA_ENABLE) == 0) { spin_unlock_irqrestore(&dev->spinlock, spin_flags); return; } @@ -1027,8 +1040,8 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) das16_reset(dev); /* set the interrupt level */ - devpriv->control_state = DAS16_IRQ(dev->irq); - outb(devpriv->control_state, dev->iobase + DAS16_CONTROL); + devpriv->ctrl_reg = DAS16_IRQ(dev->irq); + outb(devpriv->ctrl_reg, dev->iobase + DAS16_CONTROL); if (devpriv->can_burst) { outb(DAS1600_ENABLE_VAL, dev->iobase + DAS1600_ENABLE); From 73ef2b5387ff95ac24487934250e9749e8aaa217 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 14:02:22 -0700 Subject: [PATCH 1206/3400] staging: comedi: das16: tidy up das16_ai_insn_read() Factor out the loop that waits for the ai conversion to complete. Tidy up the function a bit. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 50 ++++++++++++++------------ 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index f6d0f7e868b2..a482bd524e9b 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -253,8 +253,6 @@ struct das16_board { unsigned int id; }; -#define DAS16_TIMEOUT 1000 - /* Period for timer interrupt in jiffies. It's a function * to deal with possibility of dynamic HZ patches */ static inline int timer_period(void) @@ -564,55 +562,61 @@ static void das16_reset(struct comedi_device *dev) outb(0, dev->iobase + DAS16_CNTR_CONTROL); } +static int das16_ai_wait_for_conv(struct comedi_device *dev, + unsigned int timeout) +{ + unsigned int status; + int i; + + for (i = 0; i < timeout; i++) { + status = inb(dev->iobase + DAS16_STATUS); + if (!(status & BUSY)) + return 0; + } + return -ETIME; +} + static int das16_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { const struct das16_board *board = comedi_board(dev); - int i, n; - int range; - int chan; + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int range = CR_RANGE(insn->chanspec); + unsigned int val; + int ret; + int i; das16_ai_disable(dev); /* set multiplexer */ - chan = CR_CHAN(insn->chanspec); - chan |= CR_CHAN(insn->chanspec) << 4; - outb(chan, dev->iobase + DAS16_MUX); + outb(chan | (chan << 4), dev->iobase + DAS16_MUX); /* set gain */ if (board->ai_pg != das16_pg_none) { - range = CR_RANGE(insn->chanspec); outb((das16_gainlists[board->ai_pg])[range], dev->iobase + DAS16_GAIN); } - for (n = 0; n < insn->n; n++) { - unsigned int val; - + for (i = 0; i < insn->n; i++) { /* trigger conversion */ outb_p(0, dev->iobase + DAS16_TRIG); - for (i = 0; i < DAS16_TIMEOUT; i++) { - if (!(inb(dev->iobase + DAS16_STATUS) & BUSY)) - break; - } - if (i == DAS16_TIMEOUT) { - printk("das16: timeout\n"); - return -ETIME; - } + ret = das16_ai_wait_for_conv(dev, 1000); + if (ret) + return ret; val = inb(dev->iobase + DAS16_AI_MSB) << 8; val |= inb(dev->iobase + DAS16_AI_LSB); if (s->maxdata == 0x0fff) - data[n] >>= 4; + val >>= 4; val &= s->maxdata; - data[n] = val; + data[i] = val; } - return n; + return insn->n; } static int das16_di_insn_bits(struct comedi_device *dev, From 372f3bb949482c6f0a53c03942d6def634fc2804 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 14:02:48 -0700 Subject: [PATCH 1207/3400] staging: comedi: das16: move some functions to improve readability For aesthetics, move some of the functions to make the code easier to follow. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 304 ++++++++++++------------- 1 file changed, 148 insertions(+), 156 deletions(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index a482bd524e9b..cd2fa4cafc44 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -311,6 +311,116 @@ static void das16_ai_disable(struct comedi_device *dev) outb(devpriv->ctrl_reg, dev->iobase + DAS16_CONTROL); } +/* the pc104-das16jr (at least) has problems if the dma + transfer is interrupted in the middle of transferring + a 16 bit sample, so this function takes care to get + an even transfer count after disabling dma + channel. +*/ +static int disable_dma_on_even(struct comedi_device *dev) +{ + struct das16_private_struct *devpriv = dev->private; + int residue; + int i; + static const int disable_limit = 100; + static const int enable_timeout = 100; + + disable_dma(devpriv->dma_chan); + residue = get_dma_residue(devpriv->dma_chan); + for (i = 0; i < disable_limit && (residue % 2); ++i) { + int j; + enable_dma(devpriv->dma_chan); + for (j = 0; j < enable_timeout; ++j) { + int new_residue; + udelay(2); + new_residue = get_dma_residue(devpriv->dma_chan); + if (new_residue != residue) + break; + } + disable_dma(devpriv->dma_chan); + residue = get_dma_residue(devpriv->dma_chan); + } + if (i == disable_limit) { + comedi_error(dev, "failed to get an even dma transfer, " + "could be trouble."); + } + return residue; +} + +static void das16_interrupt(struct comedi_device *dev) +{ + struct das16_private_struct *devpriv = dev->private; + unsigned long dma_flags, spin_flags; + struct comedi_subdevice *s = dev->read_subdev; + struct comedi_async *async; + struct comedi_cmd *cmd; + int num_bytes, residue; + int buffer_index; + + if (!dev->attached) { + comedi_error(dev, "premature interrupt"); + return; + } + /* initialize async here to make sure it is not NULL */ + async = s->async; + cmd = &async->cmd; + + spin_lock_irqsave(&dev->spinlock, spin_flags); + if ((devpriv->ctrl_reg & DMA_ENABLE) == 0) { + spin_unlock_irqrestore(&dev->spinlock, spin_flags); + return; + } + + dma_flags = claim_dma_lock(); + clear_dma_ff(devpriv->dma_chan); + residue = disable_dma_on_even(dev); + + /* figure out how many points to read */ + if (residue > devpriv->dma_transfer_size) { + comedi_error(dev, "residue > transfer size!\n"); + async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; + num_bytes = 0; + } else + num_bytes = devpriv->dma_transfer_size - residue; + + if (cmd->stop_src == TRIG_COUNT && + num_bytes >= devpriv->adc_byte_count) { + num_bytes = devpriv->adc_byte_count; + async->events |= COMEDI_CB_EOA; + } + + buffer_index = devpriv->current_buffer; + devpriv->current_buffer = (devpriv->current_buffer + 1) % 2; + devpriv->adc_byte_count -= num_bytes; + + /* re-enable dma */ + if ((async->events & COMEDI_CB_EOA) == 0) { + set_dma_addr(devpriv->dma_chan, + devpriv->dma_buffer_addr[devpriv->current_buffer]); + set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size); + enable_dma(devpriv->dma_chan); + } + release_dma_lock(dma_flags); + + spin_unlock_irqrestore(&dev->spinlock, spin_flags); + + cfc_write_array_to_buffer(s, + devpriv->dma_buffer[buffer_index], num_bytes); + + cfc_handle_events(dev, s); +} + +static void das16_timer_interrupt(unsigned long arg) +{ + struct comedi_device *dev = (struct comedi_device *)arg; + struct das16_private_struct *devpriv = dev->private; + + das16_interrupt(dev); + + if (devpriv->timer_running) + mod_timer(&devpriv->timer, jiffies + timer_period()); +} + static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { @@ -554,12 +664,20 @@ static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s) return 0; } -static void das16_reset(struct comedi_device *dev) +static void das16_ai_munge(struct comedi_device *dev, + struct comedi_subdevice *s, void *array, + unsigned int num_bytes, + unsigned int start_chan_index) { - outb(0, dev->iobase + DAS16_STATUS); - outb(0, dev->iobase + DAS16_CONTROL); - outb(0, dev->iobase + DAS16_PACER); - outb(0, dev->iobase + DAS16_CNTR_CONTROL); + unsigned int i, num_samples = num_bytes / sizeof(short); + short *data = array; + + for (i = 0; i < num_samples; i++) { + data[i] = le16_to_cpu(data[i]); + if (s->maxdata == 0x0fff) + data[i] >>= 4; + data[i] &= s->maxdata; + } } static int das16_ai_wait_for_conv(struct comedi_device *dev, @@ -619,6 +737,26 @@ static int das16_ai_insn_read(struct comedi_device *dev, return insn->n; } +static int das16_ao_insn_write(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int val; + int i; + + for (i = 0; i < insn->n; i++) { + val = data[i]; + val <<= 4; + + outb(val & 0xff, dev->iobase + DAS16_AO_LSB(chan)); + outb((val >> 8) & 0xff, dev->iobase + DAS16_AO_MSB(chan)); + } + + return insn->n; +} + static int das16_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, @@ -649,136 +787,6 @@ static int das16_do_insn_bits(struct comedi_device *dev, return insn->n; } -static int das16_ao_insn_write(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - unsigned int chan = CR_CHAN(insn->chanspec); - unsigned int val; - int i; - - for (i = 0; i < insn->n; i++) { - val = data[i]; - val <<= 4; - - outb(val & 0xff, dev->iobase + DAS16_AO_LSB(chan)); - outb((val >> 8) & 0xff, dev->iobase + DAS16_AO_MSB(chan)); - } - - return insn->n; -} - -/* the pc104-das16jr (at least) has problems if the dma - transfer is interrupted in the middle of transferring - a 16 bit sample, so this function takes care to get - an even transfer count after disabling dma - channel. -*/ -static int disable_dma_on_even(struct comedi_device *dev) -{ - struct das16_private_struct *devpriv = dev->private; - int residue; - int i; - static const int disable_limit = 100; - static const int enable_timeout = 100; - - disable_dma(devpriv->dma_chan); - residue = get_dma_residue(devpriv->dma_chan); - for (i = 0; i < disable_limit && (residue % 2); ++i) { - int j; - enable_dma(devpriv->dma_chan); - for (j = 0; j < enable_timeout; ++j) { - int new_residue; - udelay(2); - new_residue = get_dma_residue(devpriv->dma_chan); - if (new_residue != residue) - break; - } - disable_dma(devpriv->dma_chan); - residue = get_dma_residue(devpriv->dma_chan); - } - if (i == disable_limit) { - comedi_error(dev, "failed to get an even dma transfer, " - "could be trouble."); - } - return residue; -} - -static void das16_interrupt(struct comedi_device *dev) -{ - struct das16_private_struct *devpriv = dev->private; - unsigned long dma_flags, spin_flags; - struct comedi_subdevice *s = dev->read_subdev; - struct comedi_async *async; - struct comedi_cmd *cmd; - int num_bytes, residue; - int buffer_index; - - if (!dev->attached) { - comedi_error(dev, "premature interrupt"); - return; - } - /* initialize async here to make sure it is not NULL */ - async = s->async; - cmd = &async->cmd; - - spin_lock_irqsave(&dev->spinlock, spin_flags); - if ((devpriv->ctrl_reg & DMA_ENABLE) == 0) { - spin_unlock_irqrestore(&dev->spinlock, spin_flags); - return; - } - - dma_flags = claim_dma_lock(); - clear_dma_ff(devpriv->dma_chan); - residue = disable_dma_on_even(dev); - - /* figure out how many points to read */ - if (residue > devpriv->dma_transfer_size) { - comedi_error(dev, "residue > transfer size!\n"); - async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; - num_bytes = 0; - } else - num_bytes = devpriv->dma_transfer_size - residue; - - if (cmd->stop_src == TRIG_COUNT && - num_bytes >= devpriv->adc_byte_count) { - num_bytes = devpriv->adc_byte_count; - async->events |= COMEDI_CB_EOA; - } - - buffer_index = devpriv->current_buffer; - devpriv->current_buffer = (devpriv->current_buffer + 1) % 2; - devpriv->adc_byte_count -= num_bytes; - - /* re-enable dma */ - if ((async->events & COMEDI_CB_EOA) == 0) { - set_dma_addr(devpriv->dma_chan, - devpriv->dma_buffer_addr[devpriv->current_buffer]); - set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size); - enable_dma(devpriv->dma_chan); - } - release_dma_lock(dma_flags); - - spin_unlock_irqrestore(&dev->spinlock, spin_flags); - - cfc_write_array_to_buffer(s, - devpriv->dma_buffer[buffer_index], num_bytes); - - cfc_handle_events(dev, s); -} - -static void das16_timer_interrupt(unsigned long arg) -{ - struct comedi_device *dev = (struct comedi_device *)arg; - struct das16_private_struct *devpriv = dev->private; - - das16_interrupt(dev); - - if (devpriv->timer_running) - mod_timer(&devpriv->timer, jiffies + timer_period()); -} - static int das16_probe(struct comedi_device *dev, struct comedi_devconfig *it) { const struct das16_board *board = comedi_board(dev); @@ -814,30 +822,14 @@ static int das1600_mode_detect(struct comedi_device *dev) return 0; } -static void das16_ai_munge(struct comedi_device *dev, - struct comedi_subdevice *s, void *array, - unsigned int num_bytes, - unsigned int start_chan_index) +static void das16_reset(struct comedi_device *dev) { - unsigned int i, num_samples = num_bytes / sizeof(short); - short *data = array; - - for (i = 0; i < num_samples; i++) { - data[i] = le16_to_cpu(data[i]); - if (s->maxdata == 0x0fff) - data[i] >>= 4; - data[i] &= s->maxdata; - } + outb(0, dev->iobase + DAS16_STATUS); + outb(0, dev->iobase + DAS16_CONTROL); + outb(0, dev->iobase + DAS16_PACER); + outb(0, dev->iobase + DAS16_CNTR_CONTROL); } -/* - * - * Options list: - * 0 I/O base - * 1 IRQ - * 2 DMA - * 3 Clock speed (in MHz) - */ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) { const struct das16_board *board = comedi_board(dev); From b65daeef1d2401a18ecdcc73fa8f263cb64cdd5d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 14:03:11 -0700 Subject: [PATCH 1208/3400] staging: comedi: das16: remove unnecessary test in das16_interrupt() The timer is only started by the ai subdevice in das16_cmd_exec() and this function can only be called if the device is attached. Remove the unnecessary sanity check. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index cd2fa4cafc44..df7bf1e26c5e 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -350,21 +350,14 @@ static int disable_dma_on_even(struct comedi_device *dev) static void das16_interrupt(struct comedi_device *dev) { struct das16_private_struct *devpriv = dev->private; - unsigned long dma_flags, spin_flags; struct comedi_subdevice *s = dev->read_subdev; - struct comedi_async *async; - struct comedi_cmd *cmd; + struct comedi_async *async = s->async; + struct comedi_cmd *cmd = &async->cmd; + unsigned long spin_flags; + unsigned long dma_flags; int num_bytes, residue; int buffer_index; - if (!dev->attached) { - comedi_error(dev, "premature interrupt"); - return; - } - /* initialize async here to make sure it is not NULL */ - async = s->async; - cmd = &async->cmd; - spin_lock_irqsave(&dev->spinlock, spin_flags); if ((devpriv->ctrl_reg & DMA_ENABLE) == 0) { spin_unlock_irqrestore(&dev->spinlock, spin_flags); From 46399a84b730d9c27e9e967eabe45d280ee79163 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 14:03:28 -0700 Subject: [PATCH 1209/3400] staging: comedi: das16: move boardinfo declaration Now that the boardinfo does not require any forward declarations, move it near the definition of the struct. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 424 ++++++++++++------------- 1 file changed, 212 insertions(+), 212 deletions(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index df7bf1e26c5e..b04b3ae6bf03 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -253,6 +253,218 @@ struct das16_board { unsigned int id; }; +static const struct das16_board das16_boards[] = { + { + .name = "das-16", + .ai_maxdata = 0x0fff, + .ai_speed = 15000, + .ai_pg = das16_pg_none, + .has_ao = 1, + .i8255_offset = 0x10, + .i8254_offset = 0x0c, + .size = 0x14, + .id = 0x00, + }, { + .name = "das-16g", + .ai_maxdata = 0x0fff, + .ai_speed = 15000, + .ai_pg = das16_pg_none, + .has_ao = 1, + .i8255_offset = 0x10, + .i8254_offset = 0x0c, + .size = 0x14, + .id = 0x00, + }, { + .name = "das-16f", + .ai_maxdata = 0x0fff, + .ai_speed = 8500, + .ai_pg = das16_pg_none, + .has_ao = 1, + .i8255_offset = 0x10, + .i8254_offset = 0x0c, + .size = 0x14, + .id = 0x00, + }, { + .name = "cio-das16", + .ai_maxdata = 0x0fff, + .ai_speed = 20000, + .ai_pg = das16_pg_none, + .has_ao = 1, + .i8255_offset = 0x10, + .i8254_offset = 0x0c, + .size = 0x14, + .id = 0x80, + }, { + .name = "cio-das16/f", + .ai_maxdata = 0x0fff, + .ai_speed = 10000, + .ai_pg = das16_pg_none, + .has_ao = 1, + .i8255_offset = 0x10, + .i8254_offset = 0x0c, + .size = 0x14, + .id = 0x80, + }, { + .name = "cio-das16/jr", + .ai_maxdata = 0x0fff, + .ai_speed = 7692, + .ai_pg = das16_pg_16jr, + .i8255_offset = 0, + .i8254_offset = 0x0c, + .size = 0x10, + .id = 0x00, + }, { + .name = "pc104-das16jr", + .ai_maxdata = 0x0fff, + .ai_speed = 3300, + .ai_pg = das16_pg_16jr, + .i8255_offset = 0, + .i8254_offset = 0x0c, + .size = 0x10, + .id = 0x00, + }, { + .name = "cio-das16jr/16", + .ai_maxdata = 0xffff, + .ai_speed = 10000, + .ai_pg = das16_pg_16jr_16, + .i8255_offset = 0, + .i8254_offset = 0x0c, + .size = 0x10, + .id = 0x00, + }, { + .name = "pc104-das16jr/16", + .ai_maxdata = 0xffff, + .ai_speed = 10000, + .ai_pg = das16_pg_16jr_16, + .i8255_offset = 0, + .i8254_offset = 0x0c, + .size = 0x10, + .id = 0x00, + }, { + .name = "das-1201", + .ai_maxdata = 0x0fff, + .ai_speed = 20000, + .ai_pg = das16_pg_none, + .i8255_offset = 0x400, + .i8254_offset = 0x0c, + .size = 0x408, + .id = 0x20, + }, { + .name = "das-1202", + .ai_maxdata = 0x0fff, + .ai_speed = 10000, + .ai_pg = das16_pg_none, + .i8255_offset = 0x400, + .i8254_offset = 0x0c, + .size = 0x408, + .id = 0x20, + }, { + .name = "das-1401", + .ai_maxdata = 0x0fff, + .ai_speed = 10000, + .ai_pg = das16_pg_1601, + .i8255_offset = 0x0, + .i8254_offset = 0x0c, + .size = 0x408, + .id = 0xc0, + }, { + .name = "das-1402", + .ai_maxdata = 0x0fff, + .ai_speed = 10000, + .ai_pg = das16_pg_1602, + .i8255_offset = 0x0, + .i8254_offset = 0x0c, + .size = 0x408, + .id = 0xc0, + }, { + .name = "das-1601", + .ai_maxdata = 0x0fff, + .ai_speed = 10000, + .ai_pg = das16_pg_1601, + .has_ao = 1, + .i8255_offset = 0x400, + .i8254_offset = 0x0c, + .size = 0x408, + .id = 0xc0, + }, { + .name = "das-1602", + .ai_maxdata = 0x0fff, + .ai_speed = 10000, + .ai_pg = das16_pg_1602, + .has_ao = 1, + .i8255_offset = 0x400, + .i8254_offset = 0x0c, + .size = 0x408, + .id = 0xc0, + }, { + .name = "cio-das1401/12", + .ai_maxdata = 0x0fff, + .ai_speed = 6250, + .ai_pg = das16_pg_1601, + .i8255_offset = 0, + .i8254_offset = 0x0c, + .size = 0x408, + .id = 0xc0, + }, { + .name = "cio-das1402/12", + .ai_maxdata = 0x0fff, + .ai_speed = 6250, + .ai_pg = das16_pg_1602, + .i8255_offset = 0, + .i8254_offset = 0x0c, + .size = 0x408, + .id = 0xc0, + }, { + .name = "cio-das1402/16", + .ai_maxdata = 0xffff, + .ai_speed = 10000, + .ai_pg = das16_pg_1602, + .i8255_offset = 0, + .i8254_offset = 0x0c, + .size = 0x408, + .id = 0xc0, + }, { + .name = "cio-das1601/12", + .ai_maxdata = 0x0fff, + .ai_speed = 6250, + .ai_pg = das16_pg_1601, + .has_ao = 1, + .i8255_offset = 0x400, + .i8254_offset = 0x0c, + .size = 0x408, + .id = 0xc0, + }, { + .name = "cio-das1602/12", + .ai_maxdata = 0x0fff, + .ai_speed = 10000, + .ai_pg = das16_pg_1602, + .has_ao = 1, + .i8255_offset = 0x400, + .i8254_offset = 0x0c, + .size = 0x408, + .id = 0xc0, + }, { + .name = "cio-das1602/16", + .ai_maxdata = 0xffff, + .ai_speed = 10000, + .ai_pg = das16_pg_1602, + .has_ao = 1, + .i8255_offset = 0x400, + .i8254_offset = 0x0c, + .size = 0x408, + .id = 0xc0, + }, { + .name = "cio-das16/330", + .ai_maxdata = 0x0fff, + .ai_speed = 3030, + .ai_pg = das16_pg_16jr, + .i8255_offset = 0, + .i8254_offset = 0x0c, + .size = 0x14, + .id = 0xf0, + }, +}; + /* Period for timer interrupt in jiffies. It's a function * to deal with possibility of dynamic HZ patches */ static inline int timer_period(void) @@ -1066,218 +1278,6 @@ static void das16_detach(struct comedi_device *dev) comedi_legacy_detach(dev); } -static const struct das16_board das16_boards[] = { - { - .name = "das-16", - .ai_maxdata = 0x0fff, - .ai_speed = 15000, - .ai_pg = das16_pg_none, - .has_ao = 1, - .i8255_offset = 0x10, - .i8254_offset = 0x0c, - .size = 0x14, - .id = 0x00, - }, { - .name = "das-16g", - .ai_maxdata = 0x0fff, - .ai_speed = 15000, - .ai_pg = das16_pg_none, - .has_ao = 1, - .i8255_offset = 0x10, - .i8254_offset = 0x0c, - .size = 0x14, - .id = 0x00, - }, { - .name = "das-16f", - .ai_maxdata = 0x0fff, - .ai_speed = 8500, - .ai_pg = das16_pg_none, - .has_ao = 1, - .i8255_offset = 0x10, - .i8254_offset = 0x0c, - .size = 0x14, - .id = 0x00, - }, { - .name = "cio-das16", - .ai_maxdata = 0x0fff, - .ai_speed = 20000, - .ai_pg = das16_pg_none, - .has_ao = 1, - .i8255_offset = 0x10, - .i8254_offset = 0x0c, - .size = 0x14, - .id = 0x80, - }, { - .name = "cio-das16/f", - .ai_maxdata = 0x0fff, - .ai_speed = 10000, - .ai_pg = das16_pg_none, - .has_ao = 1, - .i8255_offset = 0x10, - .i8254_offset = 0x0c, - .size = 0x14, - .id = 0x80, - }, { - .name = "cio-das16/jr", - .ai_maxdata = 0x0fff, - .ai_speed = 7692, - .ai_pg = das16_pg_16jr, - .i8255_offset = 0, - .i8254_offset = 0x0c, - .size = 0x10, - .id = 0x00, - }, { - .name = "pc104-das16jr", - .ai_maxdata = 0x0fff, - .ai_speed = 3300, - .ai_pg = das16_pg_16jr, - .i8255_offset = 0, - .i8254_offset = 0x0c, - .size = 0x10, - .id = 0x00, - }, { - .name = "cio-das16jr/16", - .ai_maxdata = 0xffff, - .ai_speed = 10000, - .ai_pg = das16_pg_16jr_16, - .i8255_offset = 0, - .i8254_offset = 0x0c, - .size = 0x10, - .id = 0x00, - }, { - .name = "pc104-das16jr/16", - .ai_maxdata = 0xffff, - .ai_speed = 10000, - .ai_pg = das16_pg_16jr_16, - .i8255_offset = 0, - .i8254_offset = 0x0c, - .size = 0x10, - .id = 0x00, - }, { - .name = "das-1201", - .ai_maxdata = 0x0fff, - .ai_speed = 20000, - .ai_pg = das16_pg_none, - .i8255_offset = 0x400, - .i8254_offset = 0x0c, - .size = 0x408, - .id = 0x20, - }, { - .name = "das-1202", - .ai_maxdata = 0x0fff, - .ai_speed = 10000, - .ai_pg = das16_pg_none, - .i8255_offset = 0x400, - .i8254_offset = 0x0c, - .size = 0x408, - .id = 0x20, - }, { - .name = "das-1401", - .ai_maxdata = 0x0fff, - .ai_speed = 10000, - .ai_pg = das16_pg_1601, - .i8255_offset = 0x0, - .i8254_offset = 0x0c, - .size = 0x408, - .id = 0xc0, - }, { - .name = "das-1402", - .ai_maxdata = 0x0fff, - .ai_speed = 10000, - .ai_pg = das16_pg_1602, - .i8255_offset = 0x0, - .i8254_offset = 0x0c, - .size = 0x408, - .id = 0xc0, - }, { - .name = "das-1601", - .ai_maxdata = 0x0fff, - .ai_speed = 10000, - .ai_pg = das16_pg_1601, - .has_ao = 1, - .i8255_offset = 0x400, - .i8254_offset = 0x0c, - .size = 0x408, - .id = 0xc0, - }, { - .name = "das-1602", - .ai_maxdata = 0x0fff, - .ai_speed = 10000, - .ai_pg = das16_pg_1602, - .has_ao = 1, - .i8255_offset = 0x400, - .i8254_offset = 0x0c, - .size = 0x408, - .id = 0xc0, - }, { - .name = "cio-das1401/12", - .ai_maxdata = 0x0fff, - .ai_speed = 6250, - .ai_pg = das16_pg_1601, - .i8255_offset = 0, - .i8254_offset = 0x0c, - .size = 0x408, - .id = 0xc0, - }, { - .name = "cio-das1402/12", - .ai_maxdata = 0x0fff, - .ai_speed = 6250, - .ai_pg = das16_pg_1602, - .i8255_offset = 0, - .i8254_offset = 0x0c, - .size = 0x408, - .id = 0xc0, - }, { - .name = "cio-das1402/16", - .ai_maxdata = 0xffff, - .ai_speed = 10000, - .ai_pg = das16_pg_1602, - .i8255_offset = 0, - .i8254_offset = 0x0c, - .size = 0x408, - .id = 0xc0, - }, { - .name = "cio-das1601/12", - .ai_maxdata = 0x0fff, - .ai_speed = 6250, - .ai_pg = das16_pg_1601, - .has_ao = 1, - .i8255_offset = 0x400, - .i8254_offset = 0x0c, - .size = 0x408, - .id = 0xc0, - }, { - .name = "cio-das1602/12", - .ai_maxdata = 0x0fff, - .ai_speed = 10000, - .ai_pg = das16_pg_1602, - .has_ao = 1, - .i8255_offset = 0x400, - .i8254_offset = 0x0c, - .size = 0x408, - .id = 0xc0, - }, { - .name = "cio-das1602/16", - .ai_maxdata = 0xffff, - .ai_speed = 10000, - .ai_pg = das16_pg_1602, - .has_ao = 1, - .i8255_offset = 0x400, - .i8254_offset = 0x0c, - .size = 0x408, - .id = 0xc0, - }, { - .name = "cio-das16/330", - .ai_maxdata = 0x0fff, - .ai_speed = 3030, - .ai_pg = das16_pg_16jr, - .i8255_offset = 0, - .i8254_offset = 0x0c, - .size = 0x14, - .id = 0xf0, - }, -}; - static struct comedi_driver das16_driver = { .driver_name = "das16", .module = THIS_MODULE, From 22cfc772f5e55341708ac31881df69e233787b8a Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 14:03:46 -0700 Subject: [PATCH 1210/3400] staging: comedi: das16: remove 'i8254_offset' from boardinfo All the boards supported by this driver have an 8254 timer at offset 0x0c. Remove this unused information from the boardinfo. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index b04b3ae6bf03..c7b664ae5c79 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -247,7 +247,6 @@ struct das16_board { unsigned int has_ao:1; unsigned int i8255_offset; - unsigned int i8254_offset; unsigned int size; unsigned int id; @@ -261,7 +260,6 @@ static const struct das16_board das16_boards[] = { .ai_pg = das16_pg_none, .has_ao = 1, .i8255_offset = 0x10, - .i8254_offset = 0x0c, .size = 0x14, .id = 0x00, }, { @@ -271,7 +269,6 @@ static const struct das16_board das16_boards[] = { .ai_pg = das16_pg_none, .has_ao = 1, .i8255_offset = 0x10, - .i8254_offset = 0x0c, .size = 0x14, .id = 0x00, }, { @@ -281,7 +278,6 @@ static const struct das16_board das16_boards[] = { .ai_pg = das16_pg_none, .has_ao = 1, .i8255_offset = 0x10, - .i8254_offset = 0x0c, .size = 0x14, .id = 0x00, }, { @@ -291,7 +287,6 @@ static const struct das16_board das16_boards[] = { .ai_pg = das16_pg_none, .has_ao = 1, .i8255_offset = 0x10, - .i8254_offset = 0x0c, .size = 0x14, .id = 0x80, }, { @@ -301,7 +296,6 @@ static const struct das16_board das16_boards[] = { .ai_pg = das16_pg_none, .has_ao = 1, .i8255_offset = 0x10, - .i8254_offset = 0x0c, .size = 0x14, .id = 0x80, }, { @@ -310,7 +304,6 @@ static const struct das16_board das16_boards[] = { .ai_speed = 7692, .ai_pg = das16_pg_16jr, .i8255_offset = 0, - .i8254_offset = 0x0c, .size = 0x10, .id = 0x00, }, { @@ -319,7 +312,6 @@ static const struct das16_board das16_boards[] = { .ai_speed = 3300, .ai_pg = das16_pg_16jr, .i8255_offset = 0, - .i8254_offset = 0x0c, .size = 0x10, .id = 0x00, }, { @@ -328,7 +320,6 @@ static const struct das16_board das16_boards[] = { .ai_speed = 10000, .ai_pg = das16_pg_16jr_16, .i8255_offset = 0, - .i8254_offset = 0x0c, .size = 0x10, .id = 0x00, }, { @@ -337,7 +328,6 @@ static const struct das16_board das16_boards[] = { .ai_speed = 10000, .ai_pg = das16_pg_16jr_16, .i8255_offset = 0, - .i8254_offset = 0x0c, .size = 0x10, .id = 0x00, }, { @@ -346,7 +336,6 @@ static const struct das16_board das16_boards[] = { .ai_speed = 20000, .ai_pg = das16_pg_none, .i8255_offset = 0x400, - .i8254_offset = 0x0c, .size = 0x408, .id = 0x20, }, { @@ -355,7 +344,6 @@ static const struct das16_board das16_boards[] = { .ai_speed = 10000, .ai_pg = das16_pg_none, .i8255_offset = 0x400, - .i8254_offset = 0x0c, .size = 0x408, .id = 0x20, }, { @@ -364,7 +352,6 @@ static const struct das16_board das16_boards[] = { .ai_speed = 10000, .ai_pg = das16_pg_1601, .i8255_offset = 0x0, - .i8254_offset = 0x0c, .size = 0x408, .id = 0xc0, }, { @@ -373,7 +360,6 @@ static const struct das16_board das16_boards[] = { .ai_speed = 10000, .ai_pg = das16_pg_1602, .i8255_offset = 0x0, - .i8254_offset = 0x0c, .size = 0x408, .id = 0xc0, }, { @@ -383,7 +369,6 @@ static const struct das16_board das16_boards[] = { .ai_pg = das16_pg_1601, .has_ao = 1, .i8255_offset = 0x400, - .i8254_offset = 0x0c, .size = 0x408, .id = 0xc0, }, { @@ -393,7 +378,6 @@ static const struct das16_board das16_boards[] = { .ai_pg = das16_pg_1602, .has_ao = 1, .i8255_offset = 0x400, - .i8254_offset = 0x0c, .size = 0x408, .id = 0xc0, }, { @@ -402,7 +386,6 @@ static const struct das16_board das16_boards[] = { .ai_speed = 6250, .ai_pg = das16_pg_1601, .i8255_offset = 0, - .i8254_offset = 0x0c, .size = 0x408, .id = 0xc0, }, { @@ -411,7 +394,6 @@ static const struct das16_board das16_boards[] = { .ai_speed = 6250, .ai_pg = das16_pg_1602, .i8255_offset = 0, - .i8254_offset = 0x0c, .size = 0x408, .id = 0xc0, }, { @@ -420,7 +402,6 @@ static const struct das16_board das16_boards[] = { .ai_speed = 10000, .ai_pg = das16_pg_1602, .i8255_offset = 0, - .i8254_offset = 0x0c, .size = 0x408, .id = 0xc0, }, { @@ -430,7 +411,6 @@ static const struct das16_board das16_boards[] = { .ai_pg = das16_pg_1601, .has_ao = 1, .i8255_offset = 0x400, - .i8254_offset = 0x0c, .size = 0x408, .id = 0xc0, }, { @@ -440,7 +420,6 @@ static const struct das16_board das16_boards[] = { .ai_pg = das16_pg_1602, .has_ao = 1, .i8255_offset = 0x400, - .i8254_offset = 0x0c, .size = 0x408, .id = 0xc0, }, { @@ -450,7 +429,6 @@ static const struct das16_board das16_boards[] = { .ai_pg = das16_pg_1602, .has_ao = 1, .i8255_offset = 0x400, - .i8254_offset = 0x0c, .size = 0x408, .id = 0xc0, }, { @@ -459,7 +437,6 @@ static const struct das16_board das16_boards[] = { .ai_speed = 3030, .ai_pg = das16_pg_16jr, .i8255_offset = 0, - .i8254_offset = 0x0c, .size = 0x14, .id = 0xf0, }, From 21b8f248976f7270595f27e878f0026baf99e6e3 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 14:04:13 -0700 Subject: [PATCH 1211/3400] staging: comedi: das16: tidy up 8255 digital i/o subdevice The 8255 digital i/o subdevice is only available on some of the boards supported by this driver. Currently the 'i8255_offset' member of the boardinfo is used to indicate that it is available. To clarify this support, add a 'has_8255' bit-field flag to the boardinfo. We can then use this flag to conditionally allocate the space for the subdevice only when it is needed. Also, make sure to check that subdev_8255_init() is successful and propagate any errors. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 39 ++++++++++++++------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index c7b664ae5c79..8da7ee34d57d 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -245,6 +245,7 @@ struct das16_board { unsigned int ai_speed; /* max conversion speed in nanosec */ unsigned int ai_pg; unsigned int has_ao:1; + unsigned int has_8255:1; unsigned int i8255_offset; @@ -259,6 +260,7 @@ static const struct das16_board das16_boards[] = { .ai_speed = 15000, .ai_pg = das16_pg_none, .has_ao = 1, + .has_8255 = 1, .i8255_offset = 0x10, .size = 0x14, .id = 0x00, @@ -268,6 +270,7 @@ static const struct das16_board das16_boards[] = { .ai_speed = 15000, .ai_pg = das16_pg_none, .has_ao = 1, + .has_8255 = 1, .i8255_offset = 0x10, .size = 0x14, .id = 0x00, @@ -277,6 +280,7 @@ static const struct das16_board das16_boards[] = { .ai_speed = 8500, .ai_pg = das16_pg_none, .has_ao = 1, + .has_8255 = 1, .i8255_offset = 0x10, .size = 0x14, .id = 0x00, @@ -286,6 +290,7 @@ static const struct das16_board das16_boards[] = { .ai_speed = 20000, .ai_pg = das16_pg_none, .has_ao = 1, + .has_8255 = 1, .i8255_offset = 0x10, .size = 0x14, .id = 0x80, @@ -295,6 +300,7 @@ static const struct das16_board das16_boards[] = { .ai_speed = 10000, .ai_pg = das16_pg_none, .has_ao = 1, + .has_8255 = 1, .i8255_offset = 0x10, .size = 0x14, .id = 0x80, @@ -303,7 +309,6 @@ static const struct das16_board das16_boards[] = { .ai_maxdata = 0x0fff, .ai_speed = 7692, .ai_pg = das16_pg_16jr, - .i8255_offset = 0, .size = 0x10, .id = 0x00, }, { @@ -311,7 +316,6 @@ static const struct das16_board das16_boards[] = { .ai_maxdata = 0x0fff, .ai_speed = 3300, .ai_pg = das16_pg_16jr, - .i8255_offset = 0, .size = 0x10, .id = 0x00, }, { @@ -319,7 +323,6 @@ static const struct das16_board das16_boards[] = { .ai_maxdata = 0xffff, .ai_speed = 10000, .ai_pg = das16_pg_16jr_16, - .i8255_offset = 0, .size = 0x10, .id = 0x00, }, { @@ -327,7 +330,6 @@ static const struct das16_board das16_boards[] = { .ai_maxdata = 0xffff, .ai_speed = 10000, .ai_pg = das16_pg_16jr_16, - .i8255_offset = 0, .size = 0x10, .id = 0x00, }, { @@ -335,6 +337,7 @@ static const struct das16_board das16_boards[] = { .ai_maxdata = 0x0fff, .ai_speed = 20000, .ai_pg = das16_pg_none, + .has_8255 = 1, .i8255_offset = 0x400, .size = 0x408, .id = 0x20, @@ -343,6 +346,7 @@ static const struct das16_board das16_boards[] = { .ai_maxdata = 0x0fff, .ai_speed = 10000, .ai_pg = das16_pg_none, + .has_8255 = 1, .i8255_offset = 0x400, .size = 0x408, .id = 0x20, @@ -351,7 +355,6 @@ static const struct das16_board das16_boards[] = { .ai_maxdata = 0x0fff, .ai_speed = 10000, .ai_pg = das16_pg_1601, - .i8255_offset = 0x0, .size = 0x408, .id = 0xc0, }, { @@ -359,7 +362,6 @@ static const struct das16_board das16_boards[] = { .ai_maxdata = 0x0fff, .ai_speed = 10000, .ai_pg = das16_pg_1602, - .i8255_offset = 0x0, .size = 0x408, .id = 0xc0, }, { @@ -368,6 +370,7 @@ static const struct das16_board das16_boards[] = { .ai_speed = 10000, .ai_pg = das16_pg_1601, .has_ao = 1, + .has_8255 = 1, .i8255_offset = 0x400, .size = 0x408, .id = 0xc0, @@ -377,6 +380,7 @@ static const struct das16_board das16_boards[] = { .ai_speed = 10000, .ai_pg = das16_pg_1602, .has_ao = 1, + .has_8255 = 1, .i8255_offset = 0x400, .size = 0x408, .id = 0xc0, @@ -385,7 +389,6 @@ static const struct das16_board das16_boards[] = { .ai_maxdata = 0x0fff, .ai_speed = 6250, .ai_pg = das16_pg_1601, - .i8255_offset = 0, .size = 0x408, .id = 0xc0, }, { @@ -393,7 +396,6 @@ static const struct das16_board das16_boards[] = { .ai_maxdata = 0x0fff, .ai_speed = 6250, .ai_pg = das16_pg_1602, - .i8255_offset = 0, .size = 0x408, .id = 0xc0, }, { @@ -401,7 +403,6 @@ static const struct das16_board das16_boards[] = { .ai_maxdata = 0xffff, .ai_speed = 10000, .ai_pg = das16_pg_1602, - .i8255_offset = 0, .size = 0x408, .id = 0xc0, }, { @@ -410,6 +411,7 @@ static const struct das16_board das16_boards[] = { .ai_speed = 6250, .ai_pg = das16_pg_1601, .has_ao = 1, + .has_8255 = 1, .i8255_offset = 0x400, .size = 0x408, .id = 0xc0, @@ -419,6 +421,7 @@ static const struct das16_board das16_boards[] = { .ai_speed = 10000, .ai_pg = das16_pg_1602, .has_ao = 1, + .has_8255 = 1, .i8255_offset = 0x400, .size = 0x408, .id = 0xc0, @@ -428,6 +431,7 @@ static const struct das16_board das16_boards[] = { .ai_speed = 10000, .ai_pg = das16_pg_1602, .has_ao = 1, + .has_8255 = 1, .i8255_offset = 0x400, .size = 0x408, .id = 0xc0, @@ -436,7 +440,6 @@ static const struct das16_board das16_boards[] = { .ai_maxdata = 0x0fff, .ai_speed = 3030, .ai_pg = das16_pg_16jr, - .i8255_offset = 0, .size = 0x14, .id = 0xf0, }, @@ -1133,7 +1136,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) user_ao_range->flags = UNIT_volt; } - ret = comedi_alloc_subdevices(dev, 5); + ret = comedi_alloc_subdevices(dev, 4 + board->has_8255); if (ret) return ret; @@ -1207,13 +1210,13 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* initialize digital output lines */ outb(s->state, dev->iobase + DAS16_DIO); - s = &dev->subdevices[4]; - /* 8255 */ - if (board->i8255_offset != 0) { - subdev_8255_init(dev, s, NULL, (dev->iobase + - board->i8255_offset)); - } else { - s->type = COMEDI_SUBD_UNUSED; + /* 8255 Digital I/O subdevice */ + if (board->has_8255) { + s = &dev->subdevices[4]; + ret = subdev_8255_init(dev, s, NULL, + dev->iobase + board->i8255_offset); + if (ret) + return ret; } das16_reset(dev); From 0f13a8d02741f3fd301c5c0184e2c2d734f31a85 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 14:04:41 -0700 Subject: [PATCH 1212/3400] staging: comedi: das16: tidy up the register map defines Add the suffix _REG to all the register defines to better indicate what they are. Add a prefix to all the register bit defines to avoid namespace clashes and to better indicate what they are. Tidy up the whitesapce. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 183 ++++++++++++------------- 1 file changed, 89 insertions(+), 94 deletions(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 8da7ee34d57d..97ba2bd88485 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -91,55 +91,45 @@ www.measurementcomputing.com /* * Register I/O map */ -#define DAS16_TRIG 0 -#define DAS16_AI_LSB 0 -#define DAS16_AI_MSB 1 -#define DAS16_MUX 2 -#define DAS16_DIO 3 -#define DAS16_AO_LSB(x) ((x) ? 6 : 4) -#define DAS16_AO_MSB(x) ((x) ? 7 : 5) -#define DAS16_STATUS 8 -#define BUSY (1<<7) -#define UNIPOLAR (1<<6) -#define DAS16_MUXBIT (1<<5) -#define DAS16_INT (1<<4) -#define DAS16_CONTROL 9 -#define DAS16_INTE (1<<7) -#define DAS16_IRQ(x) (((x) & 0x7) << 4) -#define DMA_ENABLE (1<<2) -#define PACING_MASK 0x3 -#define INT_PACER 0x03 -#define EXT_PACER 0x02 -#define DAS16_SOFT 0x00 -#define DAS16_PACER 0x0A -#define DAS16_CTR0 (1<<1) -#define DAS16_TRIG0 (1<<0) -#define BURST_LEN_BITS(x) (((x) & 0xf) << 4) -#define DAS16_GAIN 0x0B -#define DAS16_CNTR0_DATA 0x0C -#define DAS16_CNTR1_DATA 0x0D -#define DAS16_CNTR2_DATA 0x0E -#define DAS16_CNTR_CONTROL 0x0F -#define DAS16_TERM_CNT 0x00 -#define DAS16_ONE_SHOT 0x02 -#define DAS16_RATE_GEN 0x04 -#define DAS16_CNTR_LSB_MSB 0x30 -#define DAS16_CNTR0 0x00 -#define DAS16_CNTR1 0x40 -#define DAS16_CNTR2 0x80 +#define DAS16_TRIG_REG 0x00 +#define DAS16_AI_LSB_REG 0x00 +#define DAS16_AI_MSB_REG 0x01 +#define DAS16_MUX_REG 0x02 +#define DAS16_DIO_REG 0x03 +#define DAS16_AO_LSB_REG(x) ((x) ? 0x06 : 0x04) +#define DAS16_AO_MSB_REG(x) ((x) ? 0x07 : 0x05) +#define DAS16_STATUS_REG 0x08 +#define DAS16_STATUS_BUSY (1 << 7) +#define DAS16_STATUS_UNIPOLAR (1 << 6) +#define DAS16_STATUS_MUXBIT (1 << 5) +#define DAS16_STATUS_INT (1 << 4) +#define DAS16_CTRL_REG 0x09 +#define DAS16_CTRL_INTE (1 << 7) +#define DAS16_CTRL_IRQ(x) (((x) & 0x7) << 4) +#define DAS16_CTRL_DMAE (1 << 2) +#define DAS16_CTRL_PACING_MASK (3 << 0) +#define DAS16_CTRL_INT_PACER (3 << 0) +#define DAS16_CTRL_EXT_PACER (2 << 0) +#define DAS16_CTRL_SOFT_PACER (0 << 0) +#define DAS16_PACER_REG 0x0a +#define DAS16_PACER_BURST_LEN(x) (((x) & 0xf) << 4) +#define DAS16_PACER_CTR0 (1 << 1) +#define DAS16_PACER_TRIG0 (1 << 0) +#define DAS16_GAIN_REG 0x0b +#define DAS16_TIMER_BASE_REG 0x0c /* to 0x0f */ -#define DAS1600_CONV 0x404 -#define DAS1600_CONV_DISABLE 0x40 -#define DAS1600_BURST 0x405 -#define DAS1600_BURST_VAL 0x40 -#define DAS1600_ENABLE 0x406 -#define DAS1600_ENABLE_VAL 0x40 -#define DAS1600_STATUS_B 0x407 -#define DAS1600_BME 0x40 -#define DAS1600_ME 0x20 -#define DAS1600_CD 0x10 -#define DAS1600_WS 0x02 -#define DAS1600_CLK_10MHZ 0x01 +#define DAS1600_CONV_REG 0x404 +#define DAS1600_CONV_DISABLE (1 << 6) +#define DAS1600_BURST_REG 0x405 +#define DAS1600_BURST_VAL (1 << 6) +#define DAS1600_ENABLE_REG 0x406 +#define DAS1600_ENABLE_VAL (1 << 6) +#define DAS1600_STATUS_REG 0x407 +#define DAS1600_STATUS_BME (1 << 6) +#define DAS1600_STATUS_ME (1 << 5) +#define DAS1600_STATUS_CD (1 << 4) +#define DAS1600_STATUS_WS (1 << 1) +#define DAS1600_STATUS_CLK_10MHZ (1 << 0) static const struct comedi_lrange range_das1x01_bip = { 4, { @@ -484,14 +474,16 @@ static void das16_ai_enable(struct comedi_device *dev, { struct das16_private_struct *devpriv = dev->private; - devpriv->ctrl_reg &= ~(DAS16_INTE | DMA_ENABLE | PACING_MASK); + devpriv->ctrl_reg &= ~(DAS16_CTRL_INTE | + DAS16_CTRL_DMAE | + DAS16_CTRL_PACING_MASK); devpriv->ctrl_reg |= mode; if (src == TRIG_EXT) - devpriv->ctrl_reg |= EXT_PACER; + devpriv->ctrl_reg |= DAS16_CTRL_EXT_PACER; else - devpriv->ctrl_reg |= INT_PACER; - outb(devpriv->ctrl_reg, dev->iobase + DAS16_CONTROL); + devpriv->ctrl_reg |= DAS16_CTRL_INT_PACER; + outb(devpriv->ctrl_reg, dev->iobase + DAS16_CTRL_REG); } static void das16_ai_disable(struct comedi_device *dev) @@ -499,8 +491,10 @@ static void das16_ai_disable(struct comedi_device *dev) struct das16_private_struct *devpriv = dev->private; /* disable interrupts, dma and pacer clocked conversions */ - devpriv->ctrl_reg &= ~(DAS16_INTE | DMA_ENABLE | PACING_MASK); - outb(devpriv->ctrl_reg, dev->iobase + DAS16_CONTROL); + devpriv->ctrl_reg &= ~(DAS16_CTRL_INTE | + DAS16_CTRL_DMAE | + DAS16_CTRL_PACING_MASK); + outb(devpriv->ctrl_reg, dev->iobase + DAS16_CTRL_REG); } /* the pc104-das16jr (at least) has problems if the dma @@ -551,7 +545,7 @@ static void das16_interrupt(struct comedi_device *dev) int buffer_index; spin_lock_irqsave(&dev->spinlock, spin_flags); - if ((devpriv->ctrl_reg & DMA_ENABLE) == 0) { + if (!(devpriv->ctrl_reg & DAS16_CTRL_DMAE)) { spin_unlock_irqrestore(&dev->spinlock, spin_flags); return; } @@ -732,14 +726,15 @@ static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns, int rounding_flags) { struct das16_private_struct *devpriv = dev->private; + unsigned long timer_base = dev->iobase + DAS16_TIMER_BASE_REG; i8253_cascade_ns_to_timer_2div(devpriv->clockbase, &(devpriv->divisor1), &(devpriv->divisor2), &ns, rounding_flags & TRIG_ROUND_MASK); /* Write the values of ctr1 and ctr2 into counters 1 and 2 */ - i8254_load(dev->iobase + DAS16_CNTR0_DATA, 0, 1, devpriv->divisor1, 2); - i8254_load(dev->iobase + DAS16_CNTR0_DATA, 0, 2, devpriv->divisor2, 2); + i8254_load(timer_base, 0, 1, devpriv->divisor1, 2); + i8254_load(timer_base, 0, 2, devpriv->divisor2, 2); return ns; } @@ -764,12 +759,12 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) cmd->stop_arg * cmd->chanlist_len * sizeof(uint16_t); if (devpriv->can_burst) - outb(DAS1600_CONV_DISABLE, dev->iobase + DAS1600_CONV); + outb(DAS1600_CONV_DISABLE, dev->iobase + DAS1600_CONV_REG); /* set scan limits */ byte = CR_CHAN(cmd->chanlist[0]); byte |= CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]) << 4; - outb(byte, dev->iobase + DAS16_MUX); + outb(byte, dev->iobase + DAS16_MUX_REG); /* set gain (this is also burst rate register but according to * computer boards manual, burst rate does nothing, even on @@ -777,7 +772,7 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) if (board->ai_pg != das16_pg_none) { range = CR_RANGE(cmd->chanlist[0]); outb((das16_gainlists[board->ai_pg])[range], - dev->iobase + DAS16_GAIN); + dev->iobase + DAS16_GAIN_REG); } /* set counter mode and counts */ @@ -789,14 +784,14 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) byte = 0; if (devpriv->can_burst) { if (cmd->convert_src == TRIG_NOW) { - outb(DAS1600_BURST_VAL, dev->iobase + DAS1600_BURST); + outb(DAS1600_BURST_VAL, dev->iobase + DAS1600_BURST_REG); /* set burst length */ - byte |= BURST_LEN_BITS(cmd->chanlist_len - 1); + byte |= DAS16_PACER_BURST_LEN(cmd->chanlist_len - 1); } else { - outb(0, dev->iobase + DAS1600_BURST); + outb(0, dev->iobase + DAS1600_BURST_REG); } } - outb(byte, dev->iobase + DAS16_PACER); + outb(byte, dev->iobase + DAS16_PACER_REG); /* set up dma transfer */ flags = claim_dma_lock(); @@ -817,10 +812,10 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->timer.expires = jiffies + timer_period(); add_timer(&devpriv->timer); - das16_ai_enable(dev, DMA_ENABLE, cmd->convert_src); + das16_ai_enable(dev, DAS16_CTRL_DMAE, cmd->convert_src); if (devpriv->can_burst) - outb(0, dev->iobase + DAS1600_CONV); + outb(0, dev->iobase + DAS1600_CONV_REG); return 0; } @@ -842,7 +837,7 @@ static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s) } if (devpriv->can_burst) - outb(0, dev->iobase + DAS1600_BURST); + outb(0, dev->iobase + DAS1600_BURST_REG); spin_unlock_irqrestore(&dev->spinlock, flags); @@ -872,8 +867,8 @@ static int das16_ai_wait_for_conv(struct comedi_device *dev, int i; for (i = 0; i < timeout; i++) { - status = inb(dev->iobase + DAS16_STATUS); - if (!(status & BUSY)) + status = inb(dev->iobase + DAS16_STATUS_REG); + if (!(status & DAS16_STATUS_BUSY)) return 0; } return -ETIME; @@ -894,24 +889,24 @@ static int das16_ai_insn_read(struct comedi_device *dev, das16_ai_disable(dev); /* set multiplexer */ - outb(chan | (chan << 4), dev->iobase + DAS16_MUX); + outb(chan | (chan << 4), dev->iobase + DAS16_MUX_REG); /* set gain */ if (board->ai_pg != das16_pg_none) { outb((das16_gainlists[board->ai_pg])[range], - dev->iobase + DAS16_GAIN); + dev->iobase + DAS16_GAIN_REG); } for (i = 0; i < insn->n; i++) { /* trigger conversion */ - outb_p(0, dev->iobase + DAS16_TRIG); + outb_p(0, dev->iobase + DAS16_TRIG_REG); ret = das16_ai_wait_for_conv(dev, 1000); if (ret) return ret; - val = inb(dev->iobase + DAS16_AI_MSB) << 8; - val |= inb(dev->iobase + DAS16_AI_LSB); + val = inb(dev->iobase + DAS16_AI_MSB_REG) << 8; + val |= inb(dev->iobase + DAS16_AI_LSB_REG); if (s->maxdata == 0x0fff) val >>= 4; val &= s->maxdata; @@ -935,8 +930,8 @@ static int das16_ao_insn_write(struct comedi_device *dev, val = data[i]; val <<= 4; - outb(val & 0xff, dev->iobase + DAS16_AO_LSB(chan)); - outb((val >> 8) & 0xff, dev->iobase + DAS16_AO_MSB(chan)); + outb(val & 0xff, dev->iobase + DAS16_AO_LSB_REG(chan)); + outb((val >> 8) & 0xff, dev->iobase + DAS16_AO_MSB_REG(chan)); } return insn->n; @@ -947,7 +942,7 @@ static int das16_di_insn_bits(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - data[1] = inb(dev->iobase + DAS16_DIO) & 0xf; + data[1] = inb(dev->iobase + DAS16_DIO_REG) & 0xf; return insn->n; } @@ -964,7 +959,7 @@ static int das16_do_insn_bits(struct comedi_device *dev, s->state &= ~mask; s->state |= (bits & mask); - outb(s->state, dev->iobase + DAS16_DIO); + outb(s->state, dev->iobase + DAS16_DIO_REG); } data[1] = s->state; @@ -978,7 +973,7 @@ static int das16_probe(struct comedi_device *dev, struct comedi_devconfig *it) int diobits; /* diobits indicates boards */ - diobits = inb(dev->iobase + DAS16_DIO) & 0xf0; + diobits = inb(dev->iobase + DAS16_DIO_REG) & 0xf0; printk(KERN_INFO " id bits are 0x%02x\n", diobits); if (board->id != diobits) { @@ -994,9 +989,9 @@ static int das1600_mode_detect(struct comedi_device *dev) struct das16_private_struct *devpriv = dev->private; int status = 0; - status = inb(dev->iobase + DAS1600_STATUS_B); + status = inb(dev->iobase + DAS1600_STATUS_REG); - if (status & DAS1600_CLK_10MHZ) { + if (status & DAS1600_STATUS_CLK_10MHZ) { devpriv->clockbase = 100; printk(KERN_INFO " 10MHz pacer clock\n"); } else { @@ -1009,10 +1004,10 @@ static int das1600_mode_detect(struct comedi_device *dev) static void das16_reset(struct comedi_device *dev) { - outb(0, dev->iobase + DAS16_STATUS); - outb(0, dev->iobase + DAS16_CONTROL); - outb(0, dev->iobase + DAS16_PACER); - outb(0, dev->iobase + DAS16_CNTR_CONTROL); + outb(0, dev->iobase + DAS16_STATUS_REG); + outb(0, dev->iobase + DAS16_CTRL_REG); + outb(0, dev->iobase + DAS16_PACER_REG); + outb(0, dev->iobase + DAS16_TIMER_BASE_REG + i8254_control_reg); } static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) @@ -1140,13 +1135,13 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (ret) return ret; - status = inb(dev->iobase + DAS16_STATUS); + status = inb(dev->iobase + DAS16_STATUS_REG); /* Analog Input subdevice */ s = &dev->subdevices[0]; s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE; - if (status & DAS16_MUXBIT) { + if (status & DAS16_STATUS_MUXBIT) { s->subdev_flags |= SDF_GROUND; s->n_chan = 16; } else { @@ -1157,7 +1152,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->maxdata = board->ai_maxdata; if (devpriv->user_ai_range_table) { /* user defined ai range */ s->range_table = devpriv->user_ai_range_table; - } else if (status & UNIPOLAR) { + } else if (status & DAS16_STATUS_UNIPOLAR) { s->range_table = das16_ai_uni_lranges[board->ai_pg]; } else { s->range_table = das16_ai_bip_lranges[board->ai_pg]; @@ -1208,7 +1203,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->insn_bits = das16_do_insn_bits; /* initialize digital output lines */ - outb(s->state, dev->iobase + DAS16_DIO); + outb(s->state, dev->iobase + DAS16_DIO_REG); /* 8255 Digital I/O subdevice */ if (board->has_8255) { @@ -1221,13 +1216,13 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) das16_reset(dev); /* set the interrupt level */ - devpriv->ctrl_reg = DAS16_IRQ(dev->irq); - outb(devpriv->ctrl_reg, dev->iobase + DAS16_CONTROL); + devpriv->ctrl_reg = DAS16_CTRL_IRQ(dev->irq); + outb(devpriv->ctrl_reg, dev->iobase + DAS16_CTRL_REG); if (devpriv->can_burst) { - outb(DAS1600_ENABLE_VAL, dev->iobase + DAS1600_ENABLE); - outb(0, dev->iobase + DAS1600_CONV); - outb(0, dev->iobase + DAS1600_BURST); + outb(DAS1600_ENABLE_VAL, dev->iobase + DAS1600_ENABLE_REG); + outb(0, dev->iobase + DAS1600_CONV_REG); + outb(0, dev->iobase + DAS1600_BURST_REG); } return 0; From b08c4015e6042113625d92f9e3e32bdaa652bf76 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 14:05:00 -0700 Subject: [PATCH 1213/3400] staging: comedi: das16: fail attach if board id is incorrect This driver probes the board id during the attach to ensure that the user is attempting to attach to the correct board type. Currently an error message is output if the ids are not consistent but the attach continues anyway. Make the attach fail if the id bits do not match. Also, cleanup the printk messages and use a dev_err() only if the probe fails. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 97ba2bd88485..8f4b3dd3170f 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -974,11 +974,11 @@ static int das16_probe(struct comedi_device *dev, struct comedi_devconfig *it) /* diobits indicates boards */ diobits = inb(dev->iobase + DAS16_DIO_REG) & 0xf0; - - printk(KERN_INFO " id bits are 0x%02x\n", diobits); if (board->id != diobits) { - printk(KERN_INFO " requested board's id bits are 0x%x (ignore)\n", - board->id); + dev_err(dev->class_dev, + "requested board's id bits are incorrect (0x%x != 0x%x)\n", + board->id, diobits); + return -EINVAL; } return 0; @@ -1054,10 +1054,8 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) } /* probe id bits to make sure they are consistent */ - if (das16_probe(dev, it)) { - printk(KERN_ERR " id bits do not match selected board, aborting\n"); + if (das16_probe(dev, it)) return -EINVAL; - } /* get master clock speed */ if (devpriv->can_burst) { From ccb26aa72c9a5e7bf95ec148c734ca0821331922 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 14:05:20 -0700 Subject: [PATCH 1214/3400] staging: comedi: das16: cleanup printk message in board attach Convert this printk message into a dev_err(). Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 8f4b3dd3170f..2169cd728655 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -1025,9 +1025,8 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (it->options[3]) { if (it->options[3] != 0 && it->options[3] != 1 && it->options[3] != 10) { - printk - ("\n Invalid option. Master clock must be set " - "to 1 or 10 (MHz)\n"); + dev_err(dev->class_dev, + "Invalid option. Master clock must be set to 1 or 10 (MHz)\n"); return -EINVAL; } } From f2e92ee1af58128b554203fafbbd2ae37f694fec Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 14:05:37 -0700 Subject: [PATCH 1215/3400] staging: comedi: das16: absorb das1600_mode_detect() into caller This function is only called during the board attach to determine the pacer clock speed for the boards capable of bursting. Absorb it into the caller and remove the attach noise. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 2169cd728655..7dae83e1f96a 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -984,24 +984,6 @@ static int das16_probe(struct comedi_device *dev, struct comedi_devconfig *it) return 0; } -static int das1600_mode_detect(struct comedi_device *dev) -{ - struct das16_private_struct *devpriv = dev->private; - int status = 0; - - status = inb(dev->iobase + DAS1600_STATUS_REG); - - if (status & DAS1600_STATUS_CLK_10MHZ) { - devpriv->clockbase = 100; - printk(KERN_INFO " 10MHz pacer clock\n"); - } else { - devpriv->clockbase = 1000; - printk(KERN_INFO " 1MHz pacer clock\n"); - } - - return 0; -} - static void das16_reset(struct comedi_device *dev) { outb(0, dev->iobase + DAS16_STATUS_REG); @@ -1058,7 +1040,12 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) /* get master clock speed */ if (devpriv->can_burst) { - das1600_mode_detect(dev); + status = inb(dev->iobase + DAS1600_STATUS_REG); + + if (status & DAS1600_STATUS_CLK_10MHZ) + devpriv->clockbase = 100; + else + devpriv->clockbase = 1000; } else { if (it->options[3]) devpriv->clockbase = 1000 / it->options[3]; From 0541144e80e95265325160385bd267ecf9216ed2 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 14:05:59 -0700 Subject: [PATCH 1216/3400] staging: comedi: das16: fix a > 80 char line issue Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 7dae83e1f96a..c4f0853c7247 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -784,7 +784,8 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) byte = 0; if (devpriv->can_burst) { if (cmd->convert_src == TRIG_NOW) { - outb(DAS1600_BURST_VAL, dev->iobase + DAS1600_BURST_REG); + outb(DAS1600_BURST_VAL, + dev->iobase + DAS1600_BURST_REG); /* set burst length */ byte |= DAS16_PACER_BURST_LEN(cmd->chanlist_len - 1); } else { From c04fc1a5898bb2ea7ba884bf747e17f548897afb Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 14:06:16 -0700 Subject: [PATCH 1217/3400] staging: comedi: das16: cleanup comedi_error() messages Some of these messages are missing the terminating '\n' and most of them have the quoted string split across lines. Change all of them to dev_err() messages and fix the issues. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index c4f0853c7247..fb3e0e07551d 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -527,8 +527,8 @@ static int disable_dma_on_even(struct comedi_device *dev) residue = get_dma_residue(devpriv->dma_chan); } if (i == disable_limit) { - comedi_error(dev, "failed to get an even dma transfer, " - "could be trouble."); + dev_err(dev->class_dev, + "failed to get an even dma transfer, could be trouble\n"); } return residue; } @@ -556,7 +556,7 @@ static void das16_interrupt(struct comedi_device *dev) /* figure out how many points to read */ if (residue > devpriv->dma_transfer_size) { - comedi_error(dev, "residue > transfer size!\n"); + dev_err(dev->class_dev, "residue > transfer size!\n"); async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; num_bytes = 0; } else @@ -702,16 +702,13 @@ static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s, for (i = 1; i < cmd->chanlist_len; i++) { if (CR_CHAN(cmd->chanlist[i]) != (start_chan + i) % s->n_chan) { - comedi_error(dev, - "entries in chanlist must be " - "consecutive channels, " - "counting upwards\n"); + dev_err(dev->class_dev, + "entries in chanlist must be consecutive channels, counting upwards\n"); err++; } if (CR_RANGE(cmd->chanlist[i]) != gain) { - comedi_error(dev, - "entries in chanlist must all " - "have the same gain\n"); + dev_err(dev->class_dev, + "entries in chanlist must all have the same gain\n"); err++; } } @@ -750,8 +747,8 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) int range; if (cmd->flags & TRIG_RT) { - comedi_error(dev, "isa dma transfers cannot be performed with " - "TRIG_RT, aborting"); + dev_err(dev->class_dev, + "isa dma transfers cannot be performed with TRIG_RT, aborting\n"); return -1; } From 10206ef6328609cbb07b8c5b09cedfaa339c4d42 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 14:06:34 -0700 Subject: [PATCH 1218/3400] staging: comedi: das16: tidy up private data definition Remove the comments and add some whitespace to help readability. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 40 +++++++++++--------------- 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index fb3e0e07551d..e7b7bcd9220c 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -443,30 +443,22 @@ static inline int timer_period(void) } struct das16_private_struct { - unsigned int clockbase; /* master clock speed in ns */ - unsigned int ctrl_reg; - unsigned long adc_byte_count; /* number of bytes remaining */ - /* divisor dividing master clock to get conversion frequency */ - unsigned int divisor1; - /* divisor dividing master clock to get conversion frequency */ - unsigned int divisor2; - unsigned int dma_chan; /* dma channel */ - uint16_t *dma_buffer[2]; - dma_addr_t dma_buffer_addr[2]; - unsigned int current_buffer; - unsigned int dma_transfer_size; /* target number of bytes to transfer per dma shot */ - /** - * user-defined analog input and output ranges - * defined from config options - */ - struct comedi_lrange *user_ai_range_table; - struct comedi_lrange *user_ao_range_table; - - struct timer_list timer; /* for timed interrupt */ - short timer_running; - - unsigned long extra_iobase; - unsigned int can_burst:1; + unsigned int clockbase; + unsigned int ctrl_reg; + unsigned long adc_byte_count; + unsigned int divisor1; + unsigned int divisor2; + unsigned int dma_chan; + uint16_t *dma_buffer[2]; + dma_addr_t dma_buffer_addr[2]; + unsigned int current_buffer; + unsigned int dma_transfer_size; + struct comedi_lrange *user_ai_range_table; + struct comedi_lrange *user_ao_range_table; + struct timer_list timer; + short timer_running; + unsigned long extra_iobase; + unsigned int can_burst:1; }; static void das16_ai_enable(struct comedi_device *dev, From efb623168225ee2f49b607d5aaca15caed20e8e4 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 14:06:52 -0700 Subject: [PATCH 1219/3400] staging: comedi: das16: change MODULE_DESCRIPTION Change the MODULE_DESCRIPTION to something useful instead of the generic "Comedi low-level driver". Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index e7b7bcd9220c..60895e658c43 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -1239,5 +1239,5 @@ static struct comedi_driver das16_driver = { module_comedi_driver(das16_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_DESCRIPTION("Comedi driver for DAS16 compatible boards"); MODULE_LICENSE("GPL"); From cb09d912e29605bc5a7bc6a204dda8c8f01cf10d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 14:07:10 -0700 Subject: [PATCH 1220/3400] staging: comedi: das16: fix das16_detach() The function das16_reset() needs a valid dev->iobase. Since the iobase is requested after the devpriv has been allocated in the attach, move the das16_reset() call into the if (devpriv) and add a if (dev->iobase). Also, move the release of the extra iobase into the if (devpriv) to prevent an invalid memory access. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 60895e658c43..9944f715b5da 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -1206,10 +1206,12 @@ static void das16_detach(struct comedi_device *dev) { const struct das16_board *board = comedi_board(dev); struct das16_private_struct *devpriv = dev->private; + int i; - das16_reset(dev); if (devpriv) { - int i; + if (dev->iobase) + das16_reset(dev); + for (i = 0; i < 2; i++) { if (devpriv->dma_buffer[i]) pci_free_consistent(NULL, DAS16_DMA_SIZE, @@ -1221,9 +1223,12 @@ static void das16_detach(struct comedi_device *dev) free_dma(devpriv->dma_chan); kfree(devpriv->user_ai_range_table); kfree(devpriv->user_ao_range_table); + + if (devpriv->extra_iobase) + release_region(devpriv->extra_iobase, + board->size & 0x3ff); } - if (devpriv->extra_iobase) - release_region(devpriv->extra_iobase, board->size & 0x3ff); + comedi_legacy_detach(dev); } From 3ffb03e62a12d82f7ce1b1aaa471f780e2e42743 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 14:07:30 -0700 Subject: [PATCH 1221/3400] staging: comedi: das16: remove an unnecessary check in the attach If the user does not specify the analog output range the private data 'user_ao_range_table' will not be allocated. The comedi core will detect the NULL s->range_table and automatically set it to &range_unknown. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 9944f715b5da..00ecb3c010d7 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -1148,11 +1148,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) s->subdev_flags = SDF_WRITABLE; s->n_chan = 2; s->maxdata = 0x0fff; - if (devpriv->user_ao_range_table) - s->range_table = devpriv->user_ao_range_table; - else - s->range_table = &range_unknown; - + s->range_table = devpriv->user_ao_range_table; s->insn_write = das16_ao_insn_write; } else { s->type = COMEDI_SUBD_UNUSED; From 05591eaf71a9c2ad57e2d59a398ade423a9bda00 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 14:07:53 -0700 Subject: [PATCH 1222/3400] staging: comedi: das16: tidy up user ai/ao range initialization The allocation of the user range tables could fail. Make sure to check for it. Change the kmalloc()'s to kzalloc()'s to make sure the allocated range tables are initialized to a known state. Change the local variables so they can be used for both the ai and ao range initialization and use shorter names to keep the lines < 80 chars. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 53 ++++++++++++++------------ 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 00ecb3c010d7..da640803d825 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -987,8 +987,8 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) const struct das16_board *board = comedi_board(dev); struct das16_private_struct *devpriv; struct comedi_subdevice *s; - struct comedi_krange *user_ai_range; - struct comedi_krange *user_ao_range; + struct comedi_lrange *lrange; + struct comedi_krange *krange; unsigned int dma_chan = it->options[2]; unsigned int status; int ret; @@ -1077,32 +1077,37 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) devpriv->timer.data = (unsigned long)dev; } - /* get any user-defined input range */ + /* get any user-defined input range */ if (board->ai_pg == das16_pg_none && (it->options[4] || it->options[5])) { - /* allocate single-range range table */ - devpriv->user_ai_range_table = - kmalloc(sizeof(struct comedi_lrange) + - sizeof(struct comedi_krange), GFP_KERNEL); - /* initialize ai range */ - devpriv->user_ai_range_table->length = 1; - user_ai_range = devpriv->user_ai_range_table->range; - user_ai_range->min = it->options[4]; - user_ai_range->max = it->options[5]; - user_ai_range->flags = UNIT_volt; + /* allocate single-range range table */ + lrange = kzalloc(sizeof(*lrange) + sizeof(*krange), GFP_KERNEL); + if (!lrange) + return -ENOMEM; + + /* initialize ai range */ + devpriv->user_ai_range_table = lrange; + lrange->length = 1; + krange = devpriv->user_ai_range_table->range; + krange->min = it->options[4]; + krange->max = it->options[5]; + krange->flags = UNIT_volt; } - /* get any user-defined output range */ + + /* get any user-defined output range */ if (it->options[6] || it->options[7]) { - /* allocate single-range range table */ - devpriv->user_ao_range_table = - kmalloc(sizeof(struct comedi_lrange) + - sizeof(struct comedi_krange), GFP_KERNEL); - /* initialize ao range */ - devpriv->user_ao_range_table->length = 1; - user_ao_range = devpriv->user_ao_range_table->range; - user_ao_range->min = it->options[6]; - user_ao_range->max = it->options[7]; - user_ao_range->flags = UNIT_volt; + /* allocate single-range range table */ + lrange = kzalloc(sizeof(*lrange) + sizeof(*krange), GFP_KERNEL); + if (!lrange) + return -ENOMEM; + + /* initialize ao range */ + devpriv->user_ao_range_table = lrange; + lrange->length = 1; + krange = devpriv->user_ao_range_table->range; + krange->min = it->options[6]; + krange->max = it->options[7]; + krange->flags = UNIT_volt; } ret = comedi_alloc_subdevices(dev, 4 + board->has_8255); From 27b579be13a4edbb71eeec2d16748a28e788888a Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 14:08:13 -0700 Subject: [PATCH 1223/3400] staging: comedi: das16: remove some unnecessary parentheses These parentheses are not necessary. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index da640803d825..599be27d1570 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -668,9 +668,9 @@ static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int tmp = cmd->scan_begin_arg; /* set divisors, correct timing arguments */ i8253_cascade_ns_to_timer_2div(devpriv->clockbase, - &(devpriv->divisor1), - &(devpriv->divisor2), - &(cmd->scan_begin_arg), + &devpriv->divisor1, + &devpriv->divisor2, + &cmd->scan_begin_arg, cmd->flags & TRIG_ROUND_MASK); err += (tmp != cmd->scan_begin_arg); } @@ -678,9 +678,9 @@ static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int tmp = cmd->convert_arg; /* set divisors, correct timing arguments */ i8253_cascade_ns_to_timer_2div(devpriv->clockbase, - &(devpriv->divisor1), - &(devpriv->divisor2), - &(cmd->convert_arg), + &devpriv->divisor1, + &devpriv->divisor2, + &cmd->convert_arg, cmd->flags & TRIG_ROUND_MASK); err += (tmp != cmd->convert_arg); } @@ -717,8 +717,10 @@ static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns, struct das16_private_struct *devpriv = dev->private; unsigned long timer_base = dev->iobase + DAS16_TIMER_BASE_REG; - i8253_cascade_ns_to_timer_2div(devpriv->clockbase, &(devpriv->divisor1), - &(devpriv->divisor2), &ns, + i8253_cascade_ns_to_timer_2div(devpriv->clockbase, + &devpriv->divisor1, + &devpriv->divisor2, + &ns, rounding_flags & TRIG_ROUND_MASK); /* Write the values of ctr1 and ctr2 into counters 1 and 2 */ @@ -1072,7 +1074,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) set_dma_mode(devpriv->dma_chan, DMA_MODE_READ); release_dma_lock(flags); - init_timer(&(devpriv->timer)); + init_timer(&devpriv->timer); devpriv->timer.function = das16_timer_interrupt; devpriv->timer.data = (unsigned long)dev; } From 71c9e43b88576683685e8e763eb223bf9e8193c4 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 14:08:31 -0700 Subject: [PATCH 1224/3400] staging: comedi: das16: tidy up multi-line comments Tidy up the multi-line comments to follow the CodingStyle. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/das16.c | 145 +++++++++++++------------ 1 file changed, 76 insertions(+), 69 deletions(-) diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 599be27d1570..93a8f09173aa 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -1,77 +1,84 @@ /* - comedi/drivers/das16.c - DAS16 driver + * das16.c + * DAS16 driver + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 2000 David A. Schleef + * Copyright (C) 2000 Chris R. Baugher + * Copyright (C) 2001,2002 Frank Mori Hess + * + * 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. + */ - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 2000 David A. Schleef - Copyright (C) 2000 Chris R. Baugher - Copyright (C) 2001,2002 Frank Mori Hess - - 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. -*/ /* -Driver: das16 -Description: DAS16 compatible boards -Author: Sam Moore, Warren Jasper, ds, Chris Baugher, Frank Hess, Roman Fietze -Devices: [Keithley Metrabyte] DAS-16 (das-16), DAS-16G (das-16g), - DAS-16F (das-16f), DAS-1201 (das-1201), DAS-1202 (das-1202), - DAS-1401 (das-1401), DAS-1402 (das-1402), DAS-1601 (das-1601), - DAS-1602 (das-1602), - [ComputerBoards] PC104-DAS16/JR (pc104-das16jr), - PC104-DAS16JR/16 (pc104-das16jr/16), - CIO-DAS16JR/16 (cio-das16jr/16), - CIO-DAS16/JR (cio-das16/jr), CIO-DAS1401/12 (cio-das1401/12), - CIO-DAS1402/12 (cio-das1402/12), CIO-DAS1402/16 (cio-das1402/16), - CIO-DAS1601/12 (cio-das1601/12), CIO-DAS1602/12 (cio-das1602/12), - CIO-DAS1602/16 (cio-das1602/16), CIO-DAS16/330 (cio-das16/330) -Status: works -Updated: 2003-10-12 + * Driver: das16 + * Description: DAS16 compatible boards + * Author: Sam Moore, Warren Jasper, ds, Chris Baugher, Frank Hess, Roman Fietze + * Devices: (Keithley Metrabyte) DAS-16 [das-16] + * (Keithley Metrabyte) DAS-16G [das-16g] + * (Keithley Metrabyte) DAS-16F [das-16f] + * (Keithley Metrabyte) DAS-1201 [das-1201] + * (Keithley Metrabyte) DAS-1202 [das-1202] + * (Keithley Metrabyte) DAS-1401 [das-1401] + * (Keithley Metrabyte) DAS-1402 [das-1402] + * (Keithley Metrabyte) DAS-1601 [das-1601] + * (Keithley Metrabyte) DAS-1602 [das-1602] + * (ComputerBoards) PC104-DAS16/JR [pc104-das16jr] + * (ComputerBoards) PC104-DAS16JR/16 [pc104-das16jr/16] + * (ComputerBoards) CIO-DAS16 [cio-das16] + * (ComputerBoards) CIO-DAS16F [cio-das16/f] + * (ComputerBoards) CIO-DAS16/JR [cio-das16/jr] + * (ComputerBoards) CIO-DAS16JR/16 [cio-das16jr/16] + * (ComputerBoards) CIO-DAS1401/12 [cio-das1401/12] + * (ComputerBoards) CIO-DAS1402/12 [cio-das1402/12] + * (ComputerBoards) CIO-DAS1402/16 [cio-das1402/16] + * (ComputerBoards) CIO-DAS1601/12 [cio-das1601/12] + * (ComputerBoards) CIO-DAS1602/12 [cio-das1602/12] + * (ComputerBoards) CIO-DAS1602/16 [cio-das1602/16] + * (ComputerBoards) CIO-DAS16/330 [cio-das16/330] + * Status: works + * Updated: 2003-10-12 + * + * A rewrite of the das16 and das1600 drivers. + * + * Options: + * [0] - base io address + * [1] - irq (does nothing, irq is not used anymore) + * [2] - dma channel (optional, required for comedi_command support) + * [3] - master clock speed in MHz (optional, 1 or 10, ignored if + * board can probe clock, defaults to 1) + * [4] - analog input range lowest voltage in microvolts (optional, + * only useful if your board does not have software + * programmable gain) + * [5] - analog input range highest voltage in microvolts (optional, + * only useful if board does not have software programmable + * gain) + * [6] - analog output range lowest voltage in microvolts (optional) + * [7] - analog output range highest voltage in microvolts (optional) + * + * Passing a zero for an option is the same as leaving it unspecified. + */ -A rewrite of the das16 and das1600 drivers. -Options: - [0] - base io address - [1] - irq (does nothing, irq is not used anymore) - [2] - dma (optional, required for comedi_command support) - [3] - master clock speed in MHz (optional, 1 or 10, ignored if - board can probe clock, defaults to 1) - [4] - analog input range lowest voltage in microvolts (optional, - only useful if your board does not have software - programmable gain) - [5] - analog input range highest voltage in microvolts (optional, - only useful if board does not have software programmable - gain) - [6] - analog output range lowest voltage in microvolts (optional) - [7] - analog output range highest voltage in microvolts (optional) - [8] - use timer mode for DMA. Timer mode is needed e.g. for - buggy DMA controllers in NS CS5530A (Geode Companion), and for - 'jr' cards that lack a hardware fifo. This option is no - longer needed, since timer mode is _always_ used. - -Passing a zero for an option is the same as leaving it unspecified. - -*/ /* - -Testing and debugging help provided by Daniel Koch. - -Keithley Manuals: - 2309.PDF (das16) - 4919.PDF (das1400, 1600) - 4922.PDF (das-1400) - 4923.PDF (das1200, 1400, 1600) - -Computer boards manuals also available from their website -www.measurementcomputing.com - -*/ + * Testing and debugging help provided by Daniel Koch. + * + * Keithley Manuals: + * 2309.PDF (das16) + * 4919.PDF (das1400, 1600) + * 4922.PDF (das-1400) + * 4923.PDF (das1200, 1400, 1600) + * + * Computer boards manuals also available from their website + * www.measurementcomputing.com + */ #include #include From 853a57f2d3f1f1126c3bd6a04a1efdee851fe546 Mon Sep 17 00:00:00 2001 From: Eli Billauer Date: Wed, 31 Jul 2013 11:22:42 +0300 Subject: [PATCH 1225/3400] staging: xillybus: Removed dependency on OF_DEVICE in Kconfig This variable was removed from the kernel a while ago. Signed-off-by: Eli Billauer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xillybus/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/xillybus/Kconfig b/drivers/staging/xillybus/Kconfig index 459d050065f7..8a4181f846a1 100644 --- a/drivers/staging/xillybus/Kconfig +++ b/drivers/staging/xillybus/Kconfig @@ -4,7 +4,7 @@ config XILLYBUS tristate "Xillybus generic FPGA interface" - depends on PCI || (OF_ADDRESS && OF_DEVICE && OF_IRQ) && m + depends on PCI || (OF_ADDRESS && OF_IRQ) && m help Xillybus is a generic interface for peripherals designed on programmable logic (FPGA). The driver probes the hardware for @@ -23,7 +23,7 @@ config XILLYBUS_PCIE config XILLYBUS_OF tristate "Xillybus over Device Tree" - depends on XILLYBUS && OF_ADDRESS && OF_DEVICE && OF_IRQ + depends on XILLYBUS && OF_ADDRESS && OF_IRQ help Set to M if you want Xillybus to find its resources from the Open Firmware Flattened Device Tree. If the target is an embedded From 7ee9ded220199f3be0b5d587ff9e2a1fdf7b6e2c Mon Sep 17 00:00:00 2001 From: Eli Billauer Date: Wed, 31 Jul 2013 11:22:43 +0300 Subject: [PATCH 1226/3400] staging: xillybus: Fixed sparse errors Changes: * xillybus.h: __iomem added to struct xilly_endpoint -> registers to suppress "different address spaces" errors. * xillybus_core.c: __user added as required for the same reason. * The two member names of struct xilly_endpoint_hardware of the form sync_single_for_{cpu,device} were changed to something that won't look like the well-known functions. * All *.c files: Variables and functions made static as required. Reported-by: Greg Kroah-Hartman Signed-off-by: Eli Billauer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xillybus/xillybus.h | 6 ++--- drivers/staging/xillybus/xillybus_core.c | 28 ++++++++++++------------ drivers/staging/xillybus/xillybus_of.c | 6 ++--- drivers/staging/xillybus/xillybus_pcie.c | 6 ++--- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/drivers/staging/xillybus/xillybus.h b/drivers/staging/xillybus/xillybus.h index b62faeb31c53..d3fc8aa896de 100644 --- a/drivers/staging/xillybus/xillybus.h +++ b/drivers/staging/xillybus/xillybus.h @@ -122,7 +122,7 @@ struct xilly_endpoint { struct list_head ep_list; int dma_using_dac; /* =1 if 64-bit DMA is used, =0 otherwise. */ - u32 *registers; + __iomem u32 *registers; int fatal_error; struct mutex register_mutex; @@ -150,11 +150,11 @@ struct xilly_endpoint { struct xilly_endpoint_hardware { struct module *owner; - void (*sync_single_for_cpu)(struct xilly_endpoint *, + void (*hw_sync_sgl_for_cpu)(struct xilly_endpoint *, dma_addr_t, size_t, int); - void (*sync_single_for_device)(struct xilly_endpoint *, + void (*hw_sync_sgl_for_device)(struct xilly_endpoint *, dma_addr_t, size_t, int); diff --git a/drivers/staging/xillybus/xillybus_core.c b/drivers/staging/xillybus/xillybus_core.c index 9ccd6aa7e8c5..3d7471a72077 100644 --- a/drivers/staging/xillybus/xillybus_core.c +++ b/drivers/staging/xillybus/xillybus_core.c @@ -71,7 +71,7 @@ static struct class *xillybus_class; static LIST_HEAD(list_of_endpoints); static struct mutex ep_list_lock; -struct workqueue_struct *xillybus_wq; +static struct workqueue_struct *xillybus_wq; /* * Locking scheme: Mutexes protect invocations of character device methods. @@ -145,7 +145,7 @@ irqreturn_t xillybus_isr(int irq, void *data) buf_size = ep->msg_buf_size/sizeof(u32); - ep->ephw->sync_single_for_cpu(ep, + ep->ephw->hw_sync_sgl_for_cpu(ep, ep->msgbuf_dma_addr, ep->msg_buf_size, DMA_FROM_DEVICE); @@ -163,7 +163,7 @@ irqreturn_t xillybus_isr(int irq, void *data) pr_err("xillybus: Lost sync with " "interrupt messages. Stopping.\n"); else { - ep->ephw->sync_single_for_device( + ep->ephw->hw_sync_sgl_for_device( ep, ep->msgbuf_dma_addr, ep->msg_buf_size, @@ -297,7 +297,7 @@ irqreturn_t xillybus_isr(int irq, void *data) } } - ep->ephw->sync_single_for_device(ep, + ep->ephw->hw_sync_sgl_for_device(ep, ep->msgbuf_dma_addr, ep->msg_buf_size, DMA_FROM_DEVICE); @@ -796,7 +796,7 @@ static int xilly_obtain_idt(struct xilly_endpoint *endpoint) return rc; } - endpoint->ephw->sync_single_for_cpu( + endpoint->ephw->hw_sync_sgl_for_cpu( channel->endpoint, channel->wr_buffers[0]->dma_addr, channel->wr_buf_size, @@ -832,8 +832,8 @@ static int xilly_obtain_idt(struct xilly_endpoint *endpoint) return 0; /* Success */ } -static ssize_t xillybus_read(struct file *filp, char *userbuf, size_t count, - loff_t *f_pos) +static ssize_t xillybus_read(struct file *filp, char __user *userbuf, + size_t count, loff_t *f_pos) { ssize_t rc; unsigned long flags; @@ -917,7 +917,7 @@ static ssize_t xillybus_read(struct file *filp, char *userbuf, size_t count, if (!empty) { /* Go on, now without the spinlock */ if (bufpos == 0) /* Position zero means it's virgin */ - channel->endpoint->ephw->sync_single_for_cpu( + channel->endpoint->ephw->hw_sync_sgl_for_cpu( channel->endpoint, channel->wr_buffers[bufidx]->dma_addr, channel->wr_buf_size, @@ -934,7 +934,7 @@ static ssize_t xillybus_read(struct file *filp, char *userbuf, size_t count, if (bufferdone) { channel->endpoint->ephw-> - sync_single_for_device + hw_sync_sgl_for_device ( channel->endpoint, channel->wr_buffers[bufidx]-> @@ -1243,7 +1243,7 @@ static int xillybus_myflush(struct xilly_channel *channel, long timeout) else channel->rd_host_buf_idx++; - channel->endpoint->ephw->sync_single_for_device( + channel->endpoint->ephw->hw_sync_sgl_for_device( channel->endpoint, channel->rd_buffers[bufidx]->dma_addr, channel->rd_buf_size, @@ -1362,7 +1362,7 @@ static void xillybus_autoflush(struct work_struct *work) } -static ssize_t xillybus_write(struct file *filp, const char *userbuf, +static ssize_t xillybus_write(struct file *filp, const char __user *userbuf, size_t count, loff_t *f_pos) { ssize_t rc; @@ -1471,7 +1471,7 @@ static ssize_t xillybus_write(struct file *filp, const char *userbuf, if ((bufpos == 0) || /* Zero means it's virgin */ (channel->rd_leftovers[3] != 0)) { - channel->endpoint->ephw->sync_single_for_cpu( + channel->endpoint->ephw->hw_sync_sgl_for_cpu( channel->endpoint, channel->rd_buffers[bufidx]->dma_addr, channel->rd_buf_size, @@ -1494,7 +1494,7 @@ static ssize_t xillybus_write(struct file *filp, const char *userbuf, if (bufferdone) { channel->endpoint->ephw-> - sync_single_for_device( + hw_sync_sgl_for_device( channel->endpoint, channel->rd_buffers[bufidx]-> dma_addr, @@ -1867,7 +1867,7 @@ static int xillybus_release(struct inode *inode, struct file *filp) return 0; } -loff_t xillybus_llseek(struct file *filp, loff_t offset, int whence) +static loff_t xillybus_llseek(struct file *filp, loff_t offset, int whence) { struct xilly_channel *channel = filp->private_data; loff_t pos = filp->f_pos; diff --git a/drivers/staging/xillybus/xillybus_of.c b/drivers/staging/xillybus/xillybus_of.c index 122d9ba1b28b..92c2931f4348 100644 --- a/drivers/staging/xillybus/xillybus_of.c +++ b/drivers/staging/xillybus/xillybus_of.c @@ -85,7 +85,7 @@ static dma_addr_t xilly_map_single_of(struct xilly_cleanup *mem, return addr; } -void xilly_unmap_single_of(struct xilly_dma *entry) +static void xilly_unmap_single_of(struct xilly_dma *entry) { dma_unmap_single(entry->dev, entry->dma_addr, @@ -95,8 +95,8 @@ void xilly_unmap_single_of(struct xilly_dma *entry) static struct xilly_endpoint_hardware of_hw = { .owner = THIS_MODULE, - .sync_single_for_cpu = xilly_dma_sync_single_for_cpu_of, - .sync_single_for_device = xilly_dma_sync_single_for_device_of, + .hw_sync_sgl_for_cpu = xilly_dma_sync_single_for_cpu_of, + .hw_sync_sgl_for_device = xilly_dma_sync_single_for_device_of, .map_single = xilly_map_single_of, .unmap_single = xilly_unmap_single_of }; diff --git a/drivers/staging/xillybus/xillybus_pcie.c b/drivers/staging/xillybus/xillybus_pcie.c index ad45bdb2a715..67013652358b 100644 --- a/drivers/staging/xillybus/xillybus_pcie.c +++ b/drivers/staging/xillybus/xillybus_pcie.c @@ -112,7 +112,7 @@ static dma_addr_t xilly_map_single_pci(struct xilly_cleanup *mem, return addr; } -void xilly_unmap_single_pci(struct xilly_dma *entry) +static void xilly_unmap_single_pci(struct xilly_dma *entry) { pci_unmap_single(entry->pdev, entry->dma_addr, @@ -122,8 +122,8 @@ void xilly_unmap_single_pci(struct xilly_dma *entry) static struct xilly_endpoint_hardware pci_hw = { .owner = THIS_MODULE, - .sync_single_for_cpu = xilly_dma_sync_single_for_cpu_pci, - .sync_single_for_device = xilly_dma_sync_single_for_device_pci, + .hw_sync_sgl_for_cpu = xilly_dma_sync_single_for_cpu_pci, + .hw_sync_sgl_for_device = xilly_dma_sync_single_for_device_pci, .map_single = xilly_map_single_pci, .unmap_single = xilly_unmap_single_pci }; From 2cf8ed6031522ee62a09c539f275f05c3b64d95a Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Tue, 30 Jul 2013 21:03:13 +0100 Subject: [PATCH 1227/3400] staging: vt6656: dead code wCTSDuration. Always set to zero, so remove. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/device.h | 1 - drivers/staging/vt6656/main_usb.c | 1 - drivers/staging/vt6656/rxtx.c | 4 ---- 3 files changed, 6 deletions(-) diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h index f07ba242811b..5324c2414baa 100644 --- a/drivers/staging/vt6656/device.h +++ b/drivers/staging/vt6656/device.h @@ -591,7 +591,6 @@ struct vnt_private { u8 abyBSSID[ETH_ALEN]; u8 abyDesireBSSID[ETH_ALEN]; - u16 wCTSDuration; /* update while speed change */ u16 wACKDuration; u16 wRTSTransmitLen; u8 byRTSServiceField; diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index 0c9e60fd57f7..3bc5834a13cc 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -267,7 +267,6 @@ device_set_options(struct vnt_private *pDevice) { pDevice->bUpdateBBVGA = true; pDevice->byFOETuning = 0; pDevice->byAutoPwrTunning = 0; - pDevice->wCTSDuration = 0; pDevice->byPreambleType = 0; pDevice->bExistSWNetAddr = false; /* pDevice->bDiversityRegCtlON = true; */ diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index 00e0c7118776..be0c9ce5af06 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -1005,15 +1005,12 @@ static void s_vFillCTSHead(struct vnt_private *pDevice, u32 uDMAIdx, ); pBuf->wTransmitLength_b = cpu_to_le16(wLen); pBuf->wDuration_ba = (u16)s_uGetRTSCTSDuration(pDevice, CTSDUR_BA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption); //3:CTSDuration_ba, 1:2.4G, 2,3:2.4G OFDM Data - pBuf->wDuration_ba += pDevice->wCTSDuration; pBuf->wDuration_ba = cpu_to_le16(pBuf->wDuration_ba); //Get CTSDuration_ba_f0 pBuf->wCTSDuration_ba_f0 = (u16)s_uGetRTSCTSDuration(pDevice, CTSDUR_BA_F0, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption); //8:CTSDuration_ba_f0, 1:2.4G, 2,3:2.4G OFDM Data - pBuf->wCTSDuration_ba_f0 += pDevice->wCTSDuration; pBuf->wCTSDuration_ba_f0 = cpu_to_le16(pBuf->wCTSDuration_ba_f0); //Get CTSDuration_ba_f1 pBuf->wCTSDuration_ba_f1 = (u16)s_uGetRTSCTSDuration(pDevice, CTSDUR_BA_F1, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption); //9:CTSDuration_ba_f1, 1:2.4G, 2,3:2.4G OFDM Data - pBuf->wCTSDuration_ba_f1 += pDevice->wCTSDuration; pBuf->wCTSDuration_ba_f1 = cpu_to_le16(pBuf->wCTSDuration_ba_f1); //Get CTS Frame body pBuf->Data.wDurationID = pBuf->wDuration_ba; @@ -1031,7 +1028,6 @@ static void s_vFillCTSHead(struct vnt_private *pDevice, u32 uDMAIdx, pBuf->wTransmitLength_b = cpu_to_le16(wLen); //Get CTSDuration_ba pBuf->wDuration_ba = cpu_to_le16((u16)s_uGetRTSCTSDuration(pDevice, CTSDUR_BA, cbFrameLength, byPktType, wCurrentRate, bNeedAck, byFBOption)); //3:CTSDuration_ba, 1:2.4G, 2,3:2.4G OFDM Data - pBuf->wDuration_ba += pDevice->wCTSDuration; pBuf->wDuration_ba = cpu_to_le16(pBuf->wDuration_ba); //Get CTS Frame body From 0260fe9380b6b457cf03df3735e7049e33b06953 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Tue, 30 Jul 2013 21:08:54 +0100 Subject: [PATCH 1228/3400] staging: vt6656: device.h unused variables wACKDuration wRTSTransmitLen byRTSServiceField byRTSSignalField Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/device.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h index 5324c2414baa..49869108e7e0 100644 --- a/drivers/staging/vt6656/device.h +++ b/drivers/staging/vt6656/device.h @@ -591,11 +591,6 @@ struct vnt_private { u8 abyBSSID[ETH_ALEN]; u8 abyDesireBSSID[ETH_ALEN]; - u16 wACKDuration; - u16 wRTSTransmitLen; - u8 byRTSServiceField; - u8 byRTSSignalField; - u32 dwMaxReceiveLifetime; /* dot11MaxReceiveLifetime */ int bCCK; From d0b31b8b92fc246bdd2b85bba38a28a8343f4909 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 17:43:16 -0700 Subject: [PATCH 1229/3400] staging: comedi: usbdux: generalize the usb_submit_urb functions Generalize a helper function to replace usbduxsub_submit_{in,out}urbs(). Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 47 ++++++++----------------- 1 file changed, 15 insertions(+), 32 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 7ff731fd804a..bf6c9ffa93ee 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -531,7 +531,9 @@ static void usbduxsub_ao_isoc_irq(struct urb *urb) } } -static int usbduxsub_submit_inurbs(struct comedi_device *dev) +static int usbdux_submit_urbs(struct comedi_device *dev, + struct urb **urbs, int num_urbs, + int input_urb) { struct usb_device *usb = comedi_to_usb_dev(dev); struct usbdux_private *devpriv = dev->private; @@ -540,35 +542,12 @@ static int usbduxsub_submit_inurbs(struct comedi_device *dev) int i; /* Submit all URBs and start the transfer on the bus */ - for (i = 0; i < devpriv->n_ai_urbs; i++) { - urb = devpriv->ai_urbs[i]; - - /* in case of a resubmission after an unlink... */ - urb->interval = devpriv->ai_interval; - urb->context = dev; - urb->dev = usb; - urb->status = 0; - urb->transfer_flags = URB_ISO_ASAP; - - ret = usb_submit_urb(urb, GFP_ATOMIC); - if (ret) - return ret; - } - return 0; -} - -static int usbduxsub_submit_outurbs(struct comedi_device *dev) -{ - struct usb_device *usb = comedi_to_usb_dev(dev); - struct usbdux_private *devpriv = dev->private; - struct urb *urb; - int ret; - int i; - - for (i = 0; i < devpriv->n_ao_urbs; i++) { - urb = devpriv->ao_urbs[i]; + for (i = 0; i < num_urbs; i++) { + urb = urbs[i]; /* in case of a resubmission after an unlink... */ + if (input_urb) + urb->interval = devpriv->ai_interval; urb->context = dev; urb->dev = usb; urb->status = 0; @@ -725,7 +704,8 @@ static int usbdux_ai_inttrig(struct comedi_device *dev, if (!devpriv->ai_cmd_running) { devpriv->ai_cmd_running = 1; - ret = usbduxsub_submit_inurbs(dev); + ret = usbdux_submit_urbs(dev, devpriv->ai_urbs, + devpriv->n_ai_urbs, 1); if (ret < 0) { devpriv->ai_cmd_running = 0; goto ai_trig_exit; @@ -807,7 +787,8 @@ static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) if (cmd->start_src == TRIG_NOW) { /* enable this acquisition operation */ devpriv->ai_cmd_running = 1; - ret = usbduxsub_submit_inurbs(dev); + ret = usbdux_submit_urbs(dev, devpriv->ai_urbs, + devpriv->n_ai_urbs, 1); if (ret < 0) { devpriv->ai_cmd_running = 0; /* fixme: unlink here?? */ @@ -944,7 +925,8 @@ static int usbdux_ao_inttrig(struct comedi_device *dev, if (!devpriv->ao_cmd_running) { devpriv->ao_cmd_running = 1; - ret = usbduxsub_submit_outurbs(dev); + ret = usbdux_submit_urbs(dev, devpriv->ao_urbs, + devpriv->n_ao_urbs, 0); if (ret < 0) { devpriv->ao_cmd_running = 0; goto ao_trig_exit; @@ -1105,7 +1087,8 @@ static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) if (cmd->start_src == TRIG_NOW) { /* enable this acquisition operation */ devpriv->ao_cmd_running = 1; - ret = usbduxsub_submit_outurbs(dev); + ret = usbdux_submit_urbs(dev, devpriv->ao_urbs, + devpriv->n_ao_urbs, 0); if (ret < 0) { devpriv->ao_cmd_running = 0; /* fixme: unlink here?? */ From e0bc079c669a9b6f438f8801da5fc04947323b45 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 17:43:36 -0700 Subject: [PATCH 1230/3400] staging: comedi: usbduxsigma: generalize the ai/ao usb_kill_urb() Generalize a helper function to replace for() loops in usbduxsigma_{ai,ao}_stop() that call usb_kill_urb() to unlink all the urbs. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbduxsigma.c | 28 +++++++++----------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index 1af235407eb4..b31e400faf45 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -195,18 +195,20 @@ struct usbduxsigma_private { struct semaphore sem; }; +static void usbduxsigma_unlink_urbs(struct urb **urbs, int num_urbs) +{ + int i; + + for (i = 0; i < num_urbs; i++) + usb_kill_urb(urbs[i]); +} + static void usbduxsigma_ai_stop(struct comedi_device *dev, int do_unlink) { struct usbduxsigma_private *devpriv = dev->private; - if (do_unlink) { - int i; - - for (i = 0; i < devpriv->n_ai_urbs; i++) { - if (devpriv->ai_urbs[i]) - usb_kill_urb(devpriv->ai_urbs[i]); - } - } + if (do_unlink && devpriv->ai_urbs) + usbduxsigma_unlink_urbs(devpriv->ai_urbs, devpriv->n_ai_urbs); devpriv->ai_cmd_running = 0; } @@ -342,14 +344,8 @@ static void usbduxsigma_ao_stop(struct comedi_device *dev, int do_unlink) { struct usbduxsigma_private *devpriv = dev->private; - if (do_unlink) { - int i; - - for (i = 0; i < devpriv->n_ao_urbs; i++) { - if (devpriv->ao_urbs[i]) - usb_kill_urb(devpriv->ao_urbs[i]); - } - } + if (do_unlink && devpriv->ao_urbs) + usbduxsigma_unlink_urbs(devpriv->ao_urbs, devpriv->n_ao_urbs); devpriv->ao_cmd_running = 0; } From b509a76aff183e5b12858da6feaf4f896cf2af09 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 17:43:55 -0700 Subject: [PATCH 1231/3400] staging: comedi: usbduxsigma: remove the usb endpoint defines The endpoint defines are each only used in one place and don't help clarify the code. Remove the defines and just open code the values. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbduxsigma.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index b31e400faf45..ca6d9528f8cb 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -66,13 +66,6 @@ /* internal addresses of the 8051 processor */ #define USBDUXSUB_CPUCS 0xE600 -/* USB endpoints */ -#define USBDUXSIGMA_CMD_OUT_EP 1 /* command output */ -#define USBDUXSIGMA_ISO_OUT_EP 2 /* analog output ISO/IRQ */ -#define USBDUXSIGMA_PWM_OUT_EP 4 /* pwm output */ -#define USBDUXSIGMA_ISO_IN_EP 6 /* analog input ISO/IRQ */ -#define USBDUXSIGMA_CMD_IN_EP 8 /* command input */ - /* 300Hz max frequ under PWM */ #define MIN_PWM_PERIOD ((long)(1E9/300)) @@ -639,7 +632,7 @@ static int usbbuxsigma_send_cmd(struct comedi_device *dev, int cmd_type) devpriv->dux_commands[0] = cmd_type; - return usb_bulk_msg(usb, usb_sndbulkpipe(usb, USBDUXSIGMA_CMD_OUT_EP), + return usb_bulk_msg(usb, usb_sndbulkpipe(usb, 1), devpriv->dux_commands, SIZEOFDUXBUFFER, &nsent, BULK_TIMEOUT); } @@ -653,8 +646,7 @@ static int usbduxsigma_receive_cmd(struct comedi_device *dev, int command) int i; for (i = 0; i < RETRIES; i++) { - ret = usb_bulk_msg(usb, - usb_rcvbulkpipe(usb, USBDUXSIGMA_CMD_IN_EP), + ret = usb_bulk_msg(usb, usb_rcvbulkpipe(usb, 8), devpriv->insn_buf, SIZEINSNBUF, &nrec, BULK_TIMEOUT); if (ret < 0) @@ -1194,8 +1186,7 @@ static int usbduxsigma_submit_pwm_urb(struct comedi_device *dev) struct urb *urb = devpriv->pwm_urb; /* in case of a resubmission after an unlink... */ - usb_fill_bulk_urb(urb, - usb, usb_sndbulkpipe(usb, USBDUXSIGMA_PWM_OUT_EP), + usb_fill_bulk_urb(urb, usb, usb_sndbulkpipe(usb, 4), urb->transfer_buffer, devpriv->pwm_buf_sz, usbduxsigma_pwm_urb_complete, dev); @@ -1573,7 +1564,7 @@ static int usbduxsigma_alloc_usb_buffers(struct comedi_device *dev) /* will be filled later with a pointer to the comedi-device */ /* and ONLY then the urb should be submitted */ urb->context = NULL; - urb->pipe = usb_rcvisocpipe(usb, USBDUXSIGMA_ISO_IN_EP); + urb->pipe = usb_rcvisocpipe(usb, 6); urb->transfer_flags = URB_ISO_ASAP; urb->transfer_buffer = kzalloc(SIZEINBUF, GFP_KERNEL); if (!urb->transfer_buffer) @@ -1595,7 +1586,7 @@ static int usbduxsigma_alloc_usb_buffers(struct comedi_device *dev) /* will be filled later with a pointer to the comedi-device */ /* and ONLY then the urb should be submitted */ urb->context = NULL; - urb->pipe = usb_sndisocpipe(usb, USBDUXSIGMA_ISO_OUT_EP); + urb->pipe = usb_sndisocpipe(usb, 2); urb->transfer_flags = URB_ISO_ASAP; urb->transfer_buffer = kzalloc(SIZEOUTBUF, GFP_KERNEL); if (!urb->transfer_buffer) From 9fe4df4db1350a5075b617bfda40b423f161bb6f Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 17:44:14 -0700 Subject: [PATCH 1232/3400] staging: comedi: usbdux: tidy up usbdux_pwm_period() Rename the local variable used for the private data pointer to 'devpriv'. Fix the fx2delay calculation so it does not use floating point values. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index bf6c9ffa93ee..0683c8e644bb 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -1347,20 +1347,21 @@ static int usbduxsub_submit_pwm_urbs(struct comedi_device *dev) } static int usbdux_pwm_period(struct comedi_device *dev, - struct comedi_subdevice *s, unsigned int period) + struct comedi_subdevice *s, + unsigned int period) { - struct usbdux_private *this_usbduxsub = dev->private; + struct usbdux_private *devpriv = dev->private; int fx2delay = 255; if (period < MIN_PWM_PERIOD) { return -EAGAIN; } else { - fx2delay = period / ((int)(6 * 512 * (1.0 / 0.033))) - 6; + fx2delay = (period / (6 * 512 * 1000 / 33)) - 6; if (fx2delay > 255) return -EAGAIN; } - this_usbduxsub->pwm_delay = fx2delay; - this_usbduxsub->pwm_period = period; + devpriv->pwm_delay = fx2delay; + devpriv->pwm_period = period; return 0; } From 3b2dc08b72a80009887a0e0b80d63fdaa1f2a8a9 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 17:44:32 -0700 Subject: [PATCH 1233/3400] staging: comedi: usbdux: tidy up usbdux_pwm_pattern() Rename the local variable used for the private data pointer to 'devpriv'. Remove the sanity check of the private data. This function can only be called if the private data was successfully allocated in the attach. Tidy up the function to make it more concise. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 53 +++++++++---------------- 1 file changed, 19 insertions(+), 34 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 0683c8e644bb..72094d9abba7 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -1396,45 +1396,30 @@ pwm_start_exit: return ret; } -/* generates the bit pattern for PWM with the optional sign bit */ static int usbdux_pwm_pattern(struct comedi_device *dev, - struct comedi_subdevice *s, int channel, - unsigned int value, unsigned int sign) + struct comedi_subdevice *s, + unsigned int chan, + unsigned int value, + unsigned int sign) { - struct usbdux_private *this_usbduxsub = dev->private; - int i, szbuf; - char *p_buf; - char pwm_mask; - char sgn_mask; - char c; + struct usbdux_private *devpriv = dev->private; + char pwm_mask = (1 << chan); /* DIO bit for the PWM data */ + char sgn_mask = (16 << chan); /* DIO bit for the sign */ + char *buf = (char *)(devpriv->pwm_urb->transfer_buffer); + int szbuf = devpriv->pwm_buf_sz; + int i; - if (!this_usbduxsub) - return -EFAULT; - - /* this is the DIO bit which carries the PWM data */ - pwm_mask = (1 << channel); - /* this is the DIO bit which carries the optional direction bit */ - sgn_mask = (16 << channel); - /* this is the buffer which will be filled with the with bit */ - /* pattern for one period */ - szbuf = this_usbduxsub->pwm_buf_sz; - p_buf = (char *)(this_usbduxsub->pwm_urb->transfer_buffer); for (i = 0; i < szbuf; i++) { - c = *p_buf; - /* reset bits */ - c = c & (~pwm_mask); - /* set the bit as long as the index is lower than the value */ + char c = *buf; + + c &= ~pwm_mask; if (i < value) - c = c | pwm_mask; - /* set the optional sign bit for a relay */ - if (!sign) { - /* positive value */ - c = c & (~sgn_mask); - } else { - /* negative value */ - c = c | sgn_mask; - } - *(p_buf++) = c; + c |= pwm_mask; + if (!sign) + c &= ~sgn_mask; + else + c |= sgn_mask; + *buf++ = c; } return 1; } From 5c63f094a75820b85f7aecf6ee84439d610017c0 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 17:44:50 -0700 Subject: [PATCH 1234/3400] staging: comedi: usbdux: tidy up usbdux_pwm_write() Remove the sanity check of the private data. This function can only be called if the private data was successfully allocated in the attach. Tidy up the function a bit. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 30 +++++++++++-------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 72094d9abba7..214a49f23ec5 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -1426,27 +1426,23 @@ static int usbdux_pwm_pattern(struct comedi_device *dev, static int usbdux_pwm_write(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - struct usbdux_private *this_usbduxsub = dev->private; - - if (!this_usbduxsub) - return -EFAULT; - - if ((insn->n) != 1) { - /* - * doesn't make sense to have more than one value here because - * it would just overwrite the PWM buffer a couple of times - */ - return -EINVAL; - } + unsigned int chan = CR_CHAN(insn->chanspec); /* - * the sign is set via a special INSN only, this gives us 8 bits for - * normal operation - * relay sign 0 by default + * It doesn't make sense to support more than one value here + * because it would just overwrite the PWM buffer. */ - return usbdux_pwm_pattern(dev, s, CR_CHAN(insn->chanspec), data[0], 0); + if (insn->n != 1) + return -EINVAL; + + /* + * The sign is set via a special INSN only, this gives us 8 bits + * for normal operation, sign is 0 by default. + */ + return usbdux_pwm_pattern(dev, s, chan, data[0], 0); } static int usbdux_pwm_read(struct comedi_device *x1, From 64ffc665d7172ce9f13b6ad5fca107e8847d68d1 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 17:45:09 -0700 Subject: [PATCH 1235/3400] staging: comedi: usbdux: remove usbdux_pwm_read() The pwm subdevice is not readable so this callback function is not needed. Remove it. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 214a49f23ec5..9f97e3e1f1c6 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -1445,14 +1445,6 @@ static int usbdux_pwm_write(struct comedi_device *dev, return usbdux_pwm_pattern(dev, s, chan, data[0], 0); } -static int usbdux_pwm_read(struct comedi_device *x1, - struct comedi_subdevice *x2, struct comedi_insn *x3, - unsigned int *x4) -{ - /* not needed */ - return -EINVAL; -}; - /* switches on/off PWM */ static int usbdux_pwm_config(struct comedi_device *dev, struct comedi_subdevice *s, @@ -1819,7 +1811,6 @@ static int usbdux_auto_attach(struct comedi_device *dev, s->n_chan = 8; s->maxdata = devpriv->pwm_buf_sz; s->insn_write = usbdux_pwm_write; - s->insn_read = usbdux_pwm_read; s->insn_config = usbdux_pwm_config; usbdux_pwm_period(dev, s, PWM_DEFAULT_PERIOD); From 893a27785c93ac76514cceb812eb41d059cd8f55 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 17:45:28 -0700 Subject: [PATCH 1236/3400] staging: comedi: usbdux: tidy up usbdux_pwm_config() Rename the local variable used for the private data pointer to 'devpriv'. Tidy up the function a bit. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 32 ++++++++++--------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 9f97e3e1f1c6..b1fe32934e38 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -1445,15 +1445,16 @@ static int usbdux_pwm_write(struct comedi_device *dev, return usbdux_pwm_pattern(dev, s, chan, data[0], 0); } -/* switches on/off PWM */ static int usbdux_pwm_config(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - struct usbdux_private *this_usbduxsub = dev->private; + struct usbdux_private *devpriv = dev->private; + unsigned int chan = CR_CHAN(insn->chanspec); + switch (data[0]) { case INSN_CONFIG_ARM: - /* switch it on */ /* * if not zero the PWM is limited to a certain time which is * not supported here @@ -1464,27 +1465,20 @@ static int usbdux_pwm_config(struct comedi_device *dev, case INSN_CONFIG_DISARM: return usbdux_pwm_cancel(dev, s); case INSN_CONFIG_GET_PWM_STATUS: - /* - * to check if the USB transmission has failed or in case PWM - * was limited to n cycles to check if it has terminated - */ - data[1] = this_usbduxsub->pwm_cmd_running; + data[1] = devpriv->pwm_cmd_running; return 0; case INSN_CONFIG_PWM_SET_PERIOD: return usbdux_pwm_period(dev, s, data[1]); case INSN_CONFIG_PWM_GET_PERIOD: - data[1] = this_usbduxsub->pwm_period; + data[1] = devpriv->pwm_period; return 0; case INSN_CONFIG_PWM_SET_H_BRIDGE: - /* value in the first byte and the sign in the second for a - relay */ - return usbdux_pwm_pattern(dev, s, - /* the channel number */ - CR_CHAN(insn->chanspec), - /* actual PWM data */ - data[1], - /* just a sign */ - (data[2] != 0)); + /* + * data[1] = value + * data[2] = sign (for a relay) + */ + return usbdux_pwm_pattern(dev, s, chan, + data[1], (data[2] != 0)); case INSN_CONFIG_PWM_GET_H_BRIDGE: /* values are not kept in this driver, nothing to return here */ return -EINVAL; From 89878614e24329209bf0d4efbb09fb5e431e7eb0 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 17:45:47 -0700 Subject: [PATCH 1237/3400] staging: comedi: usbdux: return void from usbdux_pwm_pattern() This function never fails and currently returns '1' so that the usbdux_pwm_write() function returns to proper value (insn->n). It's also called by usbdux_pwm_config() which also returns the '1' value. The proper return code for this function should be '0' to indicate success. Change the return type of the function to void and just have the callers return the proper values. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index b1fe32934e38..9dcb2978922f 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -1396,11 +1396,11 @@ pwm_start_exit: return ret; } -static int usbdux_pwm_pattern(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned int chan, - unsigned int value, - unsigned int sign) +static void usbdux_pwm_pattern(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int chan, + unsigned int value, + unsigned int sign) { struct usbdux_private *devpriv = dev->private; char pwm_mask = (1 << chan); /* DIO bit for the PWM data */ @@ -1421,7 +1421,6 @@ static int usbdux_pwm_pattern(struct comedi_device *dev, c |= sgn_mask; *buf++ = c; } - return 1; } static int usbdux_pwm_write(struct comedi_device *dev, @@ -1442,7 +1441,9 @@ static int usbdux_pwm_write(struct comedi_device *dev, * The sign is set via a special INSN only, this gives us 8 bits * for normal operation, sign is 0 by default. */ - return usbdux_pwm_pattern(dev, s, chan, data[0], 0); + usbdux_pwm_pattern(dev, s, chan, data[0], 0); + + return insn->n; } static int usbdux_pwm_config(struct comedi_device *dev, @@ -1477,8 +1478,8 @@ static int usbdux_pwm_config(struct comedi_device *dev, * data[1] = value * data[2] = sign (for a relay) */ - return usbdux_pwm_pattern(dev, s, chan, - data[1], (data[2] != 0)); + usbdux_pwm_pattern(dev, s, chan, data[1], (data[2] != 0)); + return 0; case INSN_CONFIG_PWM_GET_H_BRIDGE: /* values are not kept in this driver, nothing to return here */ return -EINVAL; From aa25b91304bbca0c79c6b1d736236cd2f817ca03 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 17:46:07 -0700 Subject: [PATCH 1238/3400] staging: comedi: usbduxsigma: return void from usbduxsigma_pwm_pattern() This function never fails and currently returns '1' so that the usbduxsigma_pwm_write() function returns to proper value (insn->n). It's also called by usbduxsigma_pwm_config() which also returns the '1' value. The proper return code for this function should be '0' to indicate success. Change the return type of the function to void and just have the callers return the proper values. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbduxsigma.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index ca6d9528f8cb..660eec28540f 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -1238,11 +1238,11 @@ static int usbduxsigma_pwm_start(struct comedi_device *dev, return 0; } -static int usbduxsigma_pwm_pattern(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned int chan, - unsigned int value, - unsigned int sign) +static void usbduxsigma_pwm_pattern(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned int chan, + unsigned int value, + unsigned int sign) { struct usbduxsigma_private *devpriv = dev->private; char pwm_mask = (1 << chan); /* DIO bit for the PWM data */ @@ -1263,7 +1263,6 @@ static int usbduxsigma_pwm_pattern(struct comedi_device *dev, c |= sgn_mask; *buf++ = c; } - return 1; } static int usbduxsigma_pwm_write(struct comedi_device *dev, @@ -1284,7 +1283,9 @@ static int usbduxsigma_pwm_write(struct comedi_device *dev, * The sign is set via a special INSN only, this gives us 8 bits * for normal operation, sign is 0 by default. */ - return usbduxsigma_pwm_pattern(dev, s, chan, data[0], 0); + usbduxsigma_pwm_pattern(dev, s, chan, data[0], 0); + + return insn->n; } static int usbduxsigma_pwm_config(struct comedi_device *dev, @@ -1319,8 +1320,8 @@ static int usbduxsigma_pwm_config(struct comedi_device *dev, * data[1] = value * data[2] = sign (for a relay) */ - return usbduxsigma_pwm_pattern(dev, s, chan, - data[1], (data[2] != 0)); + usbduxsigma_pwm_pattern(dev, s, chan, data[1], (data[2] != 0)); + return 0; case INSN_CONFIG_PWM_GET_H_BRIDGE: /* values are not kept in this driver, nothing to return */ return -EINVAL; From ef1e3c4a3b383c6da3979670fcb5c6e9c7de4741 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 17:46:27 -0700 Subject: [PATCH 1239/3400] staging: comedi: usbdux: tidy up usbdux_alloc_usb_buffers() Tidy up the error path by doing all the basic allocations then checking for failures. We have the comedi device now so fill in the urb->context. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 32 +++++-------------------- 1 file changed, 6 insertions(+), 26 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 9dcb2978922f..75b2de33ffd5 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -1566,25 +1566,15 @@ static int usbdux_alloc_usb_buffers(struct comedi_device *dev) struct urb *urb; int i; - /* create space for the commands going to the usb device */ devpriv->dux_commands = kzalloc(SIZEOFDUXBUFFER, GFP_KERNEL); - if (!devpriv->dux_commands) - return -ENOMEM; - - /* create space for the in buffer and set it to zero */ devpriv->in_buf = kzalloc(SIZEINBUF, GFP_KERNEL); - if (!devpriv->in_buf) - return -ENOMEM; - - /* create space of the instruction buffer */ devpriv->insn_buf = kzalloc(SIZEINSNBUF, GFP_KERNEL); - if (!devpriv->insn_buf) - return -ENOMEM; - - /* in urbs */ devpriv->ai_urbs = kcalloc(devpriv->n_ai_urbs, sizeof(*urb), GFP_KERNEL); - if (!devpriv->ai_urbs) + devpriv->ao_urbs = kcalloc(devpriv->n_ao_urbs, sizeof(*urb), + GFP_KERNEL); + if (!devpriv->dux_commands || !devpriv->in_buf || !devpriv->insn_buf || + !devpriv->ai_urbs || !devpriv->ao_urbs) return -ENOMEM; for (i = 0; i < devpriv->n_ai_urbs; i++) { @@ -1595,9 +1585,7 @@ static int usbdux_alloc_usb_buffers(struct comedi_device *dev) devpriv->ai_urbs[i] = urb; urb->dev = usb; - /* will be filled later with a pointer to the comedi-device */ - /* and ONLY then the urb should be submitted */ - urb->context = NULL; + urb->context = dev; urb->pipe = usb_rcvisocpipe(usb, 6); urb->transfer_flags = URB_ISO_ASAP; urb->transfer_buffer = kzalloc(SIZEINBUF, GFP_KERNEL); @@ -1611,12 +1599,6 @@ static int usbdux_alloc_usb_buffers(struct comedi_device *dev) urb->iso_frame_desc[0].length = SIZEINBUF; } - /* out urbs */ - devpriv->ao_urbs = kcalloc(devpriv->n_ao_urbs, sizeof(*urb), - GFP_KERNEL); - if (!devpriv->ao_urbs) - return -ENOMEM; - for (i = 0; i < devpriv->n_ao_urbs; i++) { /* one frame: 1ms */ urb = usb_alloc_urb(1, GFP_KERNEL); @@ -1625,9 +1607,7 @@ static int usbdux_alloc_usb_buffers(struct comedi_device *dev) devpriv->ao_urbs[i] = urb; urb->dev = usb; - /* will be filled later with a pointer to the comedi-device */ - /* and ONLY then the urb should be submitted */ - urb->context = NULL; + urb->context = dev; urb->pipe = usb_sndisocpipe(usb, 2); urb->transfer_flags = URB_ISO_ASAP; urb->transfer_buffer = kzalloc(SIZEOUTBUF, GFP_KERNEL); From 315a276da9952f481edc2396deab455173dbaea8 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 17:46:46 -0700 Subject: [PATCH 1240/3400] staging: comedi: usbduxsigma: 'dac_commands' does not need to be kzalloc()'d The 'dac_commands' buffer is used to pass the ao channel list from usbduxsigma_ao_cmd() to the urb callback, usbduxsigma_ao_urb_complete(). This buffer does not need to be allocated. Change it into a simple array of the correct size. Rename the variable to 'ao_chanlist' to clarify what it actually is. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbduxsigma.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index 660eec28540f..df563953fc26 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -161,6 +161,7 @@ struct usbduxsigma_private { /* input buffer for single insn */ int8_t *insn_buf; + int8_t ao_chanlist[USBDUXSIGMA_NUM_AO_CHAN]; unsigned int ao_readback[USBDUXSIGMA_NUM_AO_CHAN]; unsigned high_speed:1; @@ -181,8 +182,6 @@ struct usbduxsigma_private { unsigned int ao_counter; /* interval in frames/uframes */ unsigned int ai_interval; - /* D/A commands */ - uint8_t *dac_commands; /* commands */ uint8_t *dux_commands; struct semaphore sem; @@ -421,7 +420,7 @@ static void usbduxsigma_ao_urb_complete(struct urb *urb) len = s->async->cmd.chanlist_len; *datap++ = len; for (i = 0; i < len; i++) { - unsigned int chan = devpriv->dac_commands[i]; + unsigned int chan = devpriv->ao_chanlist[i]; short val; ret = comedi_buf_get(s->async, &val); @@ -1011,7 +1010,7 @@ static int usbduxsigma_ao_cmd(struct comedi_device *dev, /* set current channel of the running acquisition to zero */ s->async->cur_chan = 0; for (i = 0; i < cmd->chanlist_len; ++i) - devpriv->dac_commands[i] = CR_CHAN(cmd->chanlist[i]); + devpriv->ao_chanlist[i] = CR_CHAN(cmd->chanlist[i]); devpriv->ao_counter = devpriv->ao_timer; @@ -1542,7 +1541,6 @@ static int usbduxsigma_alloc_usb_buffers(struct comedi_device *dev) struct urb *urb; int i; - devpriv->dac_commands = kzalloc(NUMOUTCHANNELS, GFP_KERNEL); devpriv->dux_commands = kzalloc(SIZEOFDUXBUFFER, GFP_KERNEL); devpriv->in_buf = kzalloc(SIZEINBUF, GFP_KERNEL); devpriv->insn_buf = kzalloc(SIZEINSNBUF, GFP_KERNEL); @@ -1550,8 +1548,7 @@ static int usbduxsigma_alloc_usb_buffers(struct comedi_device *dev) GFP_KERNEL); devpriv->ao_urbs = kcalloc(devpriv->n_ao_urbs, sizeof(*urb), GFP_KERNEL); - if (!devpriv->dac_commands || !devpriv->dux_commands || - !devpriv->in_buf || !devpriv->insn_buf || + if (!devpriv->dux_commands || !devpriv->in_buf || !devpriv->insn_buf || !devpriv->ai_urbs || !devpriv->ao_urbs) return -ENOMEM; @@ -1660,7 +1657,6 @@ static void usbduxsigma_free_usb_buffers(struct comedi_device *dev) kfree(devpriv->insn_buf); kfree(devpriv->in_buf); kfree(devpriv->dux_commands); - kfree(devpriv->dac_commands); } static int usbduxsigma_auto_attach(struct comedi_device *dev, From 1c379e94b38d5e575643212e6890de6a3380e6fe Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 17:47:06 -0700 Subject: [PATCH 1241/3400] staging: comedi: usbduxsigma: init 'pwm_buf_sz' in usbduxsigma_auto_attach() Initialize this variable with then_ai_urbs and n_ao_urbs in the attach. Then usbduxsigma_alloc_usb_buffers() can just check the variable to determine if the urb needs to be allocated. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbduxsigma.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index df563953fc26..68a3cd2bb173 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -1600,19 +1600,16 @@ static int usbduxsigma_alloc_usb_buffers(struct comedi_device *dev) urb->interval = 1; /* frames */ } - if (devpriv->high_speed) { - /* max bulk ep size in high speed */ - devpriv->pwm_buf_sz = 512; + if (devpriv->pwm_buf_sz) { urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) return -ENOMEM; devpriv->pwm_urb = urb; - urb->transfer_buffer = kzalloc(devpriv->pwm_buf_sz, GFP_KERNEL); + + urb->transfer_buffer = kzalloc(devpriv->pwm_buf_sz, + GFP_KERNEL); if (!urb->transfer_buffer) return -ENOMEM; - } else { - devpriv->pwm_urb = NULL; - devpriv->pwm_buf_sz = 0; } return 0; @@ -1687,9 +1684,11 @@ static int usbduxsigma_auto_attach(struct comedi_device *dev, if (devpriv->high_speed) { devpriv->n_ai_urbs = NUMOFINBUFFERSHIGH; devpriv->n_ao_urbs = NUMOFOUTBUFFERSHIGH; + devpriv->pwm_buf_sz = 512; } else { devpriv->n_ai_urbs = NUMOFINBUFFERSFULL; devpriv->n_ao_urbs = NUMOFOUTBUFFERSFULL; + devpriv->pwm_buf_sz = 0; } ret = usbduxsigma_alloc_usb_buffers(dev); From 71d7e1ee2c5505ffd2055eb36ab983e9cb52d5b7 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 17:47:26 -0700 Subject: [PATCH 1242/3400] staging: comedi: usbduxsigma: move urb unlink into usbduxsigma_detach() For aesthetics, move the final force unlink of the urbs from usbduxsigma_free_usb_buffers() to usbduxsigma_detach(). Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbduxsigma.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index 68a3cd2bb173..636209458a66 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -1621,11 +1621,6 @@ static void usbduxsigma_free_usb_buffers(struct comedi_device *dev) struct urb *urb; int i; - /* force unlink all urbs */ - usbduxsigma_ai_stop(dev, 1); - usbduxsigma_ao_stop(dev, 1); - usbduxsigma_pwm_stop(dev, 1); - urb = devpriv->pwm_urb; if (urb) { kfree(urb->transfer_buffer); @@ -1714,7 +1709,14 @@ static void usbduxsigma_detach(struct comedi_device *dev) usb_set_intfdata(intf, NULL); down(&devpriv->sem); + + /* force unlink all urbs */ + usbduxsigma_ai_stop(dev, 1); + usbduxsigma_ao_stop(dev, 1); + usbduxsigma_pwm_stop(dev, 1); + usbduxsigma_free_usb_buffers(dev); + up(&devpriv->sem); } From 1da439008e972ad3dfceca8a9ff4950db20f3528 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 17:47:44 -0700 Subject: [PATCH 1243/3400] staging: comedi: usbduxsigma: always clear the usb intfdata in (*detach) Make sure the usb intfdata is always cleared when the device is detached. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbduxsigma.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index 636209458a66..60815a3ec540 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -1703,11 +1703,11 @@ static void usbduxsigma_detach(struct comedi_device *dev) struct usb_interface *intf = comedi_to_usb_interface(dev); struct usbduxsigma_private *devpriv = dev->private; + usb_set_intfdata(intf, NULL); + if (!devpriv) return; - usb_set_intfdata(intf, NULL); - down(&devpriv->sem); /* force unlink all urbs */ From 4d9861b554bc08e72045098dbc03d8221d904490 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 17:48:04 -0700 Subject: [PATCH 1244/3400] staging: comedi: usbdux: tidy up usbdux_detach() Make sure the usb intfdata is always cleared when the device is detached. Refactor the code to remove an indent level. Always unlink the urbs when the device is detached. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 75b2de33ffd5..991c425bb837 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -1799,20 +1799,21 @@ static void usbdux_detach(struct comedi_device *dev) struct usb_interface *intf = comedi_to_usb_interface(dev); struct usbdux_private *devpriv = dev->private; - if (devpriv) { - down(&devpriv->sem); + usb_set_intfdata(intf, NULL); - usb_set_intfdata(intf, NULL); + if (!devpriv) + return; - /* stop and unlink any submitted urbs */ - usbdux_pwm_stop(dev, devpriv->pwm_cmd_running); - usbdux_ao_stop(dev, devpriv->ao_cmd_running); - usbdux_ai_stop(dev, devpriv->ai_cmd_running); + down(&devpriv->sem); - usbdux_free_usb_buffers(devpriv); + /* force unlink all urbs */ + usbdux_pwm_stop(dev, 1); + usbdux_ao_stop(dev, 1); + usbdux_ai_stop(dev, 1); - up(&devpriv->sem); - } + usbdux_free_usb_buffers(devpriv); + + up(&devpriv->sem); } static struct comedi_driver usbdux_driver = { From 71500b272064410a3417ab764aec20572564d68d Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 17:48:25 -0700 Subject: [PATCH 1245/3400] staging: comedi: usbdux: tidy up usbdux_free_usb_buffers() For aesthetics, pass the comedi_device pointer to this function instead of the private data pointer. The usb_kill_urb() calls are not needed. All the urbs were unlinked before this function was called. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 991c425bb837..689b45276e8d 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -1642,15 +1642,15 @@ static int usbdux_alloc_usb_buffers(struct comedi_device *dev) return 0; } -static void usbdux_free_usb_buffers(struct usbdux_private *devpriv) +static void usbdux_free_usb_buffers(struct comedi_device *dev) { + struct usbdux_private *devpriv = dev->private; struct urb *urb; int i; urb = devpriv->pwm_urb; if (urb) { kfree(urb->transfer_buffer); - usb_kill_urb(urb); usb_free_urb(urb); } if (devpriv->ao_urbs) { @@ -1658,7 +1658,6 @@ static void usbdux_free_usb_buffers(struct usbdux_private *devpriv) urb = devpriv->ao_urbs[i]; if (urb) { kfree(urb->transfer_buffer); - usb_kill_urb(urb); usb_free_urb(urb); } } @@ -1669,7 +1668,6 @@ static void usbdux_free_usb_buffers(struct usbdux_private *devpriv) urb = devpriv->ai_urbs[i]; if (urb) { kfree(urb->transfer_buffer); - usb_kill_urb(urb); usb_free_urb(urb); } } @@ -1811,7 +1809,7 @@ static void usbdux_detach(struct comedi_device *dev) usbdux_ao_stop(dev, 1); usbdux_ai_stop(dev, 1); - usbdux_free_usb_buffers(devpriv); + usbdux_free_usb_buffers(dev); up(&devpriv->sem); } From 259ed07b6c391b10fd8ed8d3afe38c5b04bb7904 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 29 Jul 2013 17:48:50 -0700 Subject: [PATCH 1246/3400] staging: comedi: usbduxsigma: absorb usbduxsigma_attach_common() into caller This function is only called by usbduxsigma_auto_attach(). Absorb it and refactor the code a bit to match the usbdux driver. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbduxsigma.c | 171 +++++++++---------- 1 file changed, 76 insertions(+), 95 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index 60815a3ec540..fca89c367a68 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -1379,90 +1379,6 @@ static int usbduxsigma_getstatusinfo(struct comedi_device *dev, int chan) return (int)val; } -static int usbduxsigma_attach_common(struct comedi_device *dev) -{ - struct usbduxsigma_private *devpriv = dev->private; - struct comedi_subdevice *s; - int n_subdevs; - int offset; - int ret; - - down(&devpriv->sem); - - if (devpriv->high_speed) - n_subdevs = 4; /* with pwm */ - else - n_subdevs = 3; /* without pwm */ - ret = comedi_alloc_subdevices(dev, n_subdevs); - if (ret) { - up(&devpriv->sem); - return ret; - } - - /* Analog Input subdevice */ - s = &dev->subdevices[0]; - dev->read_subdev = s; - s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ | SDF_LSAMPL; - s->n_chan = NUMCHANNELS; - s->len_chanlist = NUMCHANNELS; - s->maxdata = 0x00ffffff; - s->range_table = &usbduxsigma_ai_range; - s->insn_read = usbduxsigma_ai_insn_read; - s->do_cmdtest = usbduxsigma_ai_cmdtest; - s->do_cmd = usbduxsigma_ai_cmd; - s->cancel = usbduxsigma_ai_cancel; - - /* Analog Output subdevice */ - s = &dev->subdevices[1]; - dev->write_subdev = s; - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE; - s->n_chan = USBDUXSIGMA_NUM_AO_CHAN; - s->len_chanlist = s->n_chan; - s->maxdata = 0x00ff; - s->range_table = &range_unipolar2_5; - s->insn_write = usbduxsigma_ao_insn_write; - s->insn_read = usbduxsigma_ao_insn_read; - s->do_cmdtest = usbduxsigma_ao_cmdtest; - s->do_cmd = usbduxsigma_ao_cmd; - s->cancel = usbduxsigma_ao_cancel; - - /* Digital I/O subdevice */ - s = &dev->subdevices[2]; - s->type = COMEDI_SUBD_DIO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = 24; - s->maxdata = 1; - s->range_table = &range_digital; - s->insn_bits = usbduxsigma_dio_insn_bits; - s->insn_config = usbduxsigma_dio_insn_config; - - if (devpriv->high_speed) { - /* Timer / pwm subdevice */ - s = &dev->subdevices[3]; - s->type = COMEDI_SUBD_PWM; - s->subdev_flags = SDF_WRITABLE | SDF_PWM_HBRIDGE; - s->n_chan = 8; - s->maxdata = devpriv->pwm_buf_sz; - s->insn_write = usbduxsigma_pwm_write; - s->insn_config = usbduxsigma_pwm_config; - - usbduxsigma_pwm_period(dev, s, PWM_DEFAULT_PERIOD); - } - - up(&devpriv->sem); - - offset = usbduxsigma_getstatusinfo(dev, 0); - if (offset < 0) - dev_err(dev->class_dev, - "Communication to USBDUXSIGMA failed! Check firmware and cabling\n"); - - dev_info(dev->class_dev, "attached, ADC_zero = %x\n", offset); - - return 0; -} - static int usbduxsigma_firmware_upload(struct comedi_device *dev, const u8 *data, size_t size, unsigned long context) @@ -1657,6 +1573,8 @@ static int usbduxsigma_auto_attach(struct comedi_device *dev, struct usb_interface *intf = comedi_to_usb_interface(dev); struct usb_device *usb = comedi_to_usb_dev(dev); struct usbduxsigma_private *devpriv; + struct comedi_subdevice *s; + int offset; int ret; devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); @@ -1664,17 +1582,9 @@ static int usbduxsigma_auto_attach(struct comedi_device *dev, return -ENOMEM; sema_init(&devpriv->sem, 1); + usb_set_intfdata(intf, devpriv); - ret = usb_set_interface(usb, - intf->altsetting->desc.bInterfaceNumber, 3); - if (ret < 0) { - dev_err(dev->class_dev, - "could not set alternate setting 3 in high speed\n"); - return -ENODEV; - } - - /* test if it is high speed (USB 2.0) */ devpriv->high_speed = (usb->speed == USB_SPEED_HIGH); if (devpriv->high_speed) { devpriv->n_ai_urbs = NUMOFINBUFFERSHIGH; @@ -1683,19 +1593,90 @@ static int usbduxsigma_auto_attach(struct comedi_device *dev, } else { devpriv->n_ai_urbs = NUMOFINBUFFERSFULL; devpriv->n_ao_urbs = NUMOFOUTBUFFERSFULL; - devpriv->pwm_buf_sz = 0; } ret = usbduxsigma_alloc_usb_buffers(dev); if (ret) return ret; + /* setting to alternate setting 3: enabling iso ep and bulk ep. */ + ret = usb_set_interface(usb, intf->altsetting->desc.bInterfaceNumber, + 3); + if (ret < 0) { + dev_err(dev->class_dev, + "could not set alternate setting 3 in high speed\n"); + return ret; + } + ret = comedi_load_firmware(dev, &usb->dev, FIRMWARE, usbduxsigma_firmware_upload, 0); if (ret) return ret; - return usbduxsigma_attach_common(dev); + ret = comedi_alloc_subdevices(dev, (devpriv->high_speed) ? 4 : 3); + if (ret) + return ret; + + /* Analog Input subdevice */ + s = &dev->subdevices[0]; + dev->read_subdev = s; + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ | SDF_LSAMPL; + s->n_chan = NUMCHANNELS; + s->len_chanlist = NUMCHANNELS; + s->maxdata = 0x00ffffff; + s->range_table = &usbduxsigma_ai_range; + s->insn_read = usbduxsigma_ai_insn_read; + s->do_cmdtest = usbduxsigma_ai_cmdtest; + s->do_cmd = usbduxsigma_ai_cmd; + s->cancel = usbduxsigma_ai_cancel; + + /* Analog Output subdevice */ + s = &dev->subdevices[1]; + dev->write_subdev = s; + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE; + s->n_chan = USBDUXSIGMA_NUM_AO_CHAN; + s->len_chanlist = s->n_chan; + s->maxdata = 0x00ff; + s->range_table = &range_unipolar2_5; + s->insn_write = usbduxsigma_ao_insn_write; + s->insn_read = usbduxsigma_ao_insn_read; + s->do_cmdtest = usbduxsigma_ao_cmdtest; + s->do_cmd = usbduxsigma_ao_cmd; + s->cancel = usbduxsigma_ao_cancel; + + /* Digital I/O subdevice */ + s = &dev->subdevices[2]; + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; + s->n_chan = 24; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = usbduxsigma_dio_insn_bits; + s->insn_config = usbduxsigma_dio_insn_config; + + if (devpriv->high_speed) { + /* Timer / pwm subdevice */ + s = &dev->subdevices[3]; + s->type = COMEDI_SUBD_PWM; + s->subdev_flags = SDF_WRITABLE | SDF_PWM_HBRIDGE; + s->n_chan = 8; + s->maxdata = devpriv->pwm_buf_sz; + s->insn_write = usbduxsigma_pwm_write; + s->insn_config = usbduxsigma_pwm_config; + + usbduxsigma_pwm_period(dev, s, PWM_DEFAULT_PERIOD); + } + + offset = usbduxsigma_getstatusinfo(dev, 0); + if (offset < 0) + dev_err(dev->class_dev, + "Communication to USBDUXSIGMA failed! Check firmware and cabling\n"); + + dev_info(dev->class_dev, "attached, ADC_zero = %x\n", offset); + + return 0; } static void usbduxsigma_detach(struct comedi_device *dev) From 62bf50cdfe596c373e877e5809193e4df600ac0b Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Tue, 30 Jul 2013 09:39:49 -0700 Subject: [PATCH 1247/3400] staging: comedi: allow ISA and PC/104 drivers on non-ISA systems Embedded systems with a PC/104 bus might have a configuration that does not have ISA enabled. This creates a problem in Comedi where the PC/104 drivers cannot be enabled. Remove the 'depends on ISA' for the "Comedi ISA and PC/104 drivers" menu to allow the user to select these drivers on non-ISA systems. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index 57362fee7593..a84aab47a113 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -100,7 +100,6 @@ endif # COMEDI_MISC_DRIVERS menuconfig COMEDI_ISA_DRIVERS bool "Comedi ISA and PC/104 drivers" - depends on ISA ---help--- Enable comedi ISA and PC/104 drivers to be built From 70bcbc06b7c0c7ecb900a81250862440e80205f7 Mon Sep 17 00:00:00 2001 From: Shaun Laing Date: Tue, 30 Jul 2013 11:29:43 -0600 Subject: [PATCH 1248/3400] staging: comedi: dt9812: Resolve different base types warnings. Resolves warnings from the "sparse" checker of the form "warning: incorrect type in assignment (different base types)". Signed-off-by: Shaun Laing Reviewed-by: Ian Abbott Reviewed-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt9812.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c index 7d78c78a4a27..b5e6f33dc217 100644 --- a/drivers/staging/comedi/drivers/dt9812.c +++ b/drivers/staging/comedi/drivers/dt9812.c @@ -187,8 +187,8 @@ enum { }; struct dt9812_flash_data { - u16 numbytes; - u16 address; + __le16 numbytes; + __le16 address; }; #define DT9812_MAX_NUM_MULTI_BYTE_RDS \ @@ -229,7 +229,7 @@ struct dt9812_rmw_multi { }; struct dt9812_usb_cmd { - u32 cmd; + __le32 cmd; union { struct dt9812_flash_data flash_data_info; struct dt9812_read_multi read_multi_info; From 8fd070077410b26847ef6f5856850df417e7b83e Mon Sep 17 00:00:00 2001 From: Rupesh Gujare Date: Tue, 30 Jul 2013 13:31:50 +0100 Subject: [PATCH 1249/3400] staging: ozwpan: High resolution timers Current implementation assumes HZ = 1000 for calculating all internal timer intervals, which creates problem on platforms where HZ != 1000. As well we need resolution of less than 10 mSec for heartbeat calculation, this creates problem on some platforms where HZ is configured as HZ = 100, or around, which restricts us to timer interval of 10 mSec. This is particularly found on embedded devices. This patch moves on to use high resolution timers to calculate all timer intervals as it allows us to have very small resolution of timer interval, removing dependency on HZ. Signed-off-by: Rupesh Gujare Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ozwpan/ozhcd.c | 91 +++---- drivers/staging/ozwpan/ozpd.c | 31 ++- drivers/staging/ozwpan/ozpd.h | 18 +- drivers/staging/ozwpan/ozproto.c | 357 +++++++------------------ drivers/staging/ozwpan/ozproto.h | 24 +- drivers/staging/ozwpan/ozurbparanoia.c | 5 +- drivers/staging/ozwpan/ozusbsvc.c | 14 +- 7 files changed, 202 insertions(+), 338 deletions(-) diff --git a/drivers/staging/ozwpan/ozhcd.c b/drivers/staging/ozwpan/ozhcd.c index 6b16bfc4cdd8..f81a0c53b39b 100644 --- a/drivers/staging/ozwpan/ozhcd.c +++ b/drivers/staging/ozwpan/ozhcd.c @@ -26,7 +26,6 @@ */ #include #include -#include #include #include #include "linux/usb/hcd.h" @@ -49,6 +48,9 @@ /* Get endpoint object from the containing link. */ #define ep_from_link(__e) container_of((__e), struct oz_endpoint, link) +/*EP0 timeout before ep0 request is again added to TX queue. (13*8 = 98mSec) + */ +#define EP0_TIMEOUT_COUNTER 13 /*------------------------------------------------------------------------------ * Used to link urbs together and also store some status information for each * urb. @@ -60,7 +62,7 @@ struct oz_urb_link { struct oz_port *port; u8 req_id; u8 ep_num; - unsigned long submit_jiffies; + unsigned submit_counter; }; /* Holds state information about a USB endpoint. @@ -69,7 +71,7 @@ struct oz_endpoint { struct list_head urb_list; /* List of oz_urb_link items. */ struct list_head link; /* For isoc ep, links in to isoc lists of oz_port. */ - unsigned long last_jiffies; + struct timespec timestamp; int credit; int credit_ceiling; u8 ep_num; @@ -187,6 +189,7 @@ static DEFINE_SPINLOCK(g_tasklet_lock); static struct tasklet_struct g_urb_process_tasklet; static struct tasklet_struct g_urb_cancel_tasklet; static atomic_t g_pending_urbs = ATOMIC_INIT(0); +static atomic_t g_usb_frame_number = ATOMIC_INIT(0); static const struct hc_driver g_oz_hc_drv = { .description = g_hcd_name, .product_desc = "Ozmo Devices WPAN", @@ -344,7 +347,7 @@ static struct oz_urb_link *oz_uncancel_urb(struct oz_hcd *ozhcd, struct urb *urb * Context: softirq or process */ static void oz_complete_urb(struct usb_hcd *hcd, struct urb *urb, - int status, unsigned long submit_jiffies) + int status) { struct oz_hcd *ozhcd = oz_hcd_private(hcd); unsigned long irq_state; @@ -372,12 +375,7 @@ static void oz_complete_urb(struct usb_hcd *hcd, struct urb *urb, if (oz_forget_urb(urb)) { oz_dbg(ON, "ERROR Unknown URB %p\n", urb); } else { - static unsigned long last_time; atomic_dec(&g_pending_urbs); - oz_dbg(URB, "%lu: giveback_urb(%p,%x) %lu %lu pending:%d\n", - jiffies, urb, status, jiffies-submit_jiffies, - jiffies-last_time, atomic_read(&g_pending_urbs)); - last_time = jiffies; usb_hcd_giveback_urb(hcd, urb, status); } spin_lock(&g_tasklet_lock); @@ -445,7 +443,7 @@ static void oz_complete_buffered_urb(struct oz_port *port, ep->buffered_units--; oz_dbg(ON, "Trying to give back buffered frame of size=%d\n", available_space); - oz_complete_urb(port->ozhcd->hcd, urb, 0, 0); + oz_complete_urb(port->ozhcd->hcd, urb, 0); } /*------------------------------------------------------------------------------ @@ -464,7 +462,7 @@ static int oz_enqueue_ep_urb(struct oz_port *port, u8 ep_addr, int in_dir, urbl = oz_alloc_urb_link(); if (!urbl) return -ENOMEM; - urbl->submit_jiffies = jiffies; + urbl->submit_counter = 0; urbl->urb = urb; urbl->req_id = req_id; urbl->ep_num = ep_addr; @@ -478,7 +476,7 @@ static int oz_enqueue_ep_urb(struct oz_port *port, u8 ep_addr, int in_dir, if (urb->unlinked) { spin_unlock_bh(&port->ozhcd->hcd_lock); oz_dbg(ON, "urb %p unlinked so complete immediately\n", urb); - oz_complete_urb(port->ozhcd->hcd, urb, 0, 0); + oz_complete_urb(port->ozhcd->hcd, urb, 0); oz_free_urb_link(urbl); return 0; } @@ -501,7 +499,7 @@ static int oz_enqueue_ep_urb(struct oz_port *port, u8 ep_addr, int in_dir, if (ep && port->hpd) { list_add_tail(&urbl->link, &ep->urb_list); if (!in_dir && ep_addr && (ep->credit < 0)) { - ep->last_jiffies = jiffies; + getrawmonotonic(&ep->timestamp); ep->credit = 0; } } else { @@ -790,7 +788,7 @@ void oz_hcd_get_desc_cnf(void *hport, u8 req_id, int status, const u8 *desc, } } urb->actual_length = total_size; - oz_complete_urb(port->ozhcd->hcd, urb, 0, 0); + oz_complete_urb(port->ozhcd->hcd, urb, 0); } /*------------------------------------------------------------------------------ * Context: softirq @@ -852,7 +850,7 @@ static void oz_hcd_complete_set_config(struct oz_port *port, struct urb *urb, } else { rc = -ENOMEM; } - oz_complete_urb(hcd, urb, rc, 0); + oz_complete_urb(hcd, urb, rc); } /*------------------------------------------------------------------------------ * Context: softirq @@ -877,7 +875,7 @@ static void oz_hcd_complete_set_interface(struct oz_port *port, struct urb *urb, } else { rc = -ENOMEM; } - oz_complete_urb(hcd, urb, rc, 0); + oz_complete_urb(hcd, urb, rc); } /*------------------------------------------------------------------------------ * Context: softirq @@ -914,7 +912,7 @@ void oz_hcd_control_cnf(void *hport, u8 req_id, u8 rcode, const u8 *data, (u8)windex, (u8)wvalue); break; default: - oz_complete_urb(hcd, urb, 0, 0); + oz_complete_urb(hcd, urb, 0); } } else { @@ -928,7 +926,7 @@ void oz_hcd_control_cnf(void *hport, u8 req_id, u8 rcode, const u8 *data, memcpy(urb->transfer_buffer, data, copy_len); urb->actual_length = copy_len; } - oz_complete_urb(hcd, urb, 0, 0); + oz_complete_urb(hcd, urb, 0); } } /*------------------------------------------------------------------------------ @@ -998,7 +996,7 @@ void oz_hcd_data_ind(void *hport, u8 endpoint, const u8 *data, int data_len) copy_len = urb->transfer_buffer_length; memcpy(urb->transfer_buffer, data, copy_len); urb->actual_length = copy_len; - oz_complete_urb(port->ozhcd->hcd, urb, 0, 0); + oz_complete_urb(port->ozhcd->hcd, urb, 0); return; } else { oz_dbg(ON, "buffering frame as URB is not available\n"); @@ -1017,7 +1015,7 @@ done: */ static inline int oz_usb_get_frame_number(void) { - return jiffies_to_msecs(get_jiffies_64()); + return atomic_inc_return(&g_usb_frame_number); } /*------------------------------------------------------------------------------ * Context: softirq @@ -1033,7 +1031,8 @@ int oz_hcd_heartbeat(void *hport) struct list_head *n; struct urb *urb; struct oz_endpoint *ep; - unsigned long now = jiffies; + struct timespec ts, delta; + getrawmonotonic(&ts); INIT_LIST_HEAD(&xfr_list); /* Check the OUT isoc endpoints to see if any URB data can be sent. */ @@ -1042,10 +1041,11 @@ int oz_hcd_heartbeat(void *hport) ep = ep_from_link(e); if (ep->credit < 0) continue; - ep->credit += jiffies_to_msecs(now - ep->last_jiffies); + delta = timespec_sub(ts, ep->timestamp); + ep->credit += timespec_to_ns(&delta) / NSEC_PER_MSEC; if (ep->credit > ep->credit_ceiling) ep->credit = ep->credit_ceiling; - ep->last_jiffies = now; + ep->timestamp = ts; while (ep->credit && !list_empty(&ep->urb_list)) { urbl = list_first_entry(&ep->urb_list, struct oz_urb_link, link); @@ -1053,6 +1053,8 @@ int oz_hcd_heartbeat(void *hport) if ((ep->credit + 1) < urb->number_of_packets) break; ep->credit -= urb->number_of_packets; + if (ep->credit < 0) + ep->credit = 0; list_move_tail(&urbl->link, &xfr_list); } } @@ -1060,16 +1062,14 @@ int oz_hcd_heartbeat(void *hport) /* Send to PD and complete URBs. */ list_for_each_safe(e, n, &xfr_list) { - unsigned long t; urbl = container_of(e, struct oz_urb_link, link); urb = urbl->urb; - t = urbl->submit_jiffies; list_del_init(e); urb->error_count = 0; urb->start_frame = oz_usb_get_frame_number(); oz_usb_send_isoc(port->hpd, urbl->ep_num, urb); oz_free_urb_link(urbl); - oz_complete_urb(port->ozhcd->hcd, urb, 0, t); + oz_complete_urb(port->ozhcd->hcd, urb, 0); } /* Check the IN isoc endpoints to see if any URBs can be completed. */ @@ -1080,13 +1080,14 @@ int oz_hcd_heartbeat(void *hport) if (ep->buffered_units >= OZ_IN_BUFFERING_UNITS) { ep->flags &= ~OZ_F_EP_BUFFERING; ep->credit = 0; - ep->last_jiffies = now; + ep->timestamp = ts; ep->start_frame = 0; } continue; } - ep->credit += jiffies_to_msecs(now - ep->last_jiffies); - ep->last_jiffies = now; + delta = timespec_sub(ts, ep->timestamp); + ep->credit += timespec_to_ns(&delta) / NSEC_PER_MSEC; + ep->timestamp = ts; while (!list_empty(&ep->urb_list)) { struct oz_urb_link *urbl = list_first_entry(&ep->urb_list, @@ -1095,7 +1096,7 @@ int oz_hcd_heartbeat(void *hport) int len = 0; int copy_len; int i; - if ((ep->credit + 1) < urb->number_of_packets) + if (ep->credit < urb->number_of_packets) break; if (ep->buffered_units < urb->number_of_packets) break; @@ -1141,7 +1142,7 @@ int oz_hcd_heartbeat(void *hport) urb = urbl->urb; list_del_init(e); oz_free_urb_link(urbl); - oz_complete_urb(port->ozhcd->hcd, urb, 0, 0); + oz_complete_urb(port->ozhcd->hcd, urb, 0); } /* Check if there are any ep0 requests that have timed out. * If so resent to PD. @@ -1153,11 +1154,12 @@ int oz_hcd_heartbeat(void *hport) spin_lock_bh(&ozhcd->hcd_lock); list_for_each_safe(e, n, &ep->urb_list) { urbl = container_of(e, struct oz_urb_link, link); - if (time_after(now, urbl->submit_jiffies+HZ/2)) { - oz_dbg(ON, "%ld: Request 0x%p timeout\n", - now, urbl->urb); - urbl->submit_jiffies = now; + if (urbl->submit_counter > EP0_TIMEOUT_COUNTER) { + oz_dbg(ON, "Request 0x%p timeout\n", urbl->urb); list_move_tail(e, &xfr_list); + urbl->submit_counter = 0; + } else { + urbl->submit_counter++; } } if (!list_empty(&ep->urb_list)) @@ -1382,7 +1384,7 @@ static void oz_process_ep0_urb(struct oz_hcd *ozhcd, struct urb *urb, int port_ix = -1; struct oz_port *port = NULL; - oz_dbg(URB, "%lu: %s: (%p)\n", jiffies, __func__, urb); + oz_dbg(URB, "[%s]:(%p)\n", __func__, urb); port_ix = oz_get_port_from_addr(ozhcd, urb->dev->devnum); if (port_ix < 0) { rc = -EPIPE; @@ -1505,7 +1507,7 @@ static void oz_process_ep0_urb(struct oz_hcd *ozhcd, struct urb *urb, out: if (rc || complete) { oz_dbg(ON, "Completing request locally\n"); - oz_complete_urb(ozhcd->hcd, urb, rc, 0); + oz_complete_urb(ozhcd->hcd, urb, rc); } else { oz_usb_request_heartbeat(port->hpd); } @@ -1569,7 +1571,7 @@ static void oz_urb_process_tasklet(unsigned long unused) oz_free_urb_link(urbl); rc = oz_urb_process(ozhcd, urb); if (rc) - oz_complete_urb(ozhcd->hcd, urb, rc, 0); + oz_complete_urb(ozhcd->hcd, urb, rc); spin_lock_irqsave(&g_tasklet_lock, irq_state); } spin_unlock_irqrestore(&g_tasklet_lock, irq_state); @@ -1638,7 +1640,7 @@ out2: if (urbl) { urb->actual_length = 0; oz_free_urb_link(urbl); - oz_complete_urb(ozhcd->hcd, urb, -EPIPE, 0); + oz_complete_urb(ozhcd->hcd, urb, -EPIPE); } } /*------------------------------------------------------------------------------ @@ -1678,7 +1680,7 @@ static void oz_hcd_clear_orphanage(struct oz_hcd *ozhcd, int status) urbl = list_first_entry(&ozhcd->orphanage, struct oz_urb_link, link); list_del(&urbl->link); - oz_complete_urb(ozhcd->hcd, urbl->urb, status, 0); + oz_complete_urb(ozhcd->hcd, urbl->urb, status); oz_free_urb_link(urbl); } } @@ -1720,14 +1722,13 @@ static int oz_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, struct oz_port *port; unsigned long irq_state; struct oz_urb_link *urbl; - oz_dbg(URB, "%lu: %s: (%p)\n", jiffies, __func__, urb); + oz_dbg(URB, "%s: (%p)\n", __func__, urb); if (unlikely(ozhcd == NULL)) { - oz_dbg(URB, "%lu: Refused urb(%p) not ozhcd\n", jiffies, urb); + oz_dbg(URB, "Refused urb(%p) not ozhcd\n", urb); return -EPIPE; } if (unlikely(hcd->state != HC_STATE_RUNNING)) { - oz_dbg(URB, "%lu: Refused urb(%p) not running\n", - jiffies, urb); + oz_dbg(URB, "Refused urb(%p) not running\n", urb); return -EPIPE; } port_ix = oz_get_port_from_addr(ozhcd, urb->dev->devnum); @@ -1795,7 +1796,7 @@ static int oz_hcd_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) struct oz_urb_link *urbl = NULL; int rc; unsigned long irq_state; - oz_dbg(URB, "%lu: %s: (%p)\n", jiffies, __func__, urb); + oz_dbg(URB, "%s: (%p)\n", __func__, urb); urbl = oz_alloc_urb_link(); if (unlikely(urbl == NULL)) return -ENOMEM; diff --git a/drivers/staging/ozwpan/ozpd.c b/drivers/staging/ozwpan/ozpd.c index 8a253ac07c26..86876bda29a5 100644 --- a/drivers/staging/ozwpan/ozpd.c +++ b/drivers/staging/ozwpan/ozpd.c @@ -176,6 +176,14 @@ struct oz_pd *oz_pd_alloc(const u8 *mac_addr) pd->last_sent_frame = &pd->tx_queue; spin_lock_init(&pd->stream_lock); INIT_LIST_HEAD(&pd->stream_list); + tasklet_init(&pd->heartbeat_tasklet, oz_pd_heartbeat_handler, + (unsigned long)pd); + tasklet_init(&pd->timeout_tasklet, oz_pd_timeout_handler, + (unsigned long)pd); + hrtimer_init(&pd->heartbeat, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + hrtimer_init(&pd->timeout, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + pd->heartbeat.function = oz_pd_heartbeat_event; + pd->timeout.function = oz_pd_timeout_event; } return pd; } @@ -189,6 +197,13 @@ void oz_pd_destroy(struct oz_pd *pd) struct oz_isoc_stream *st; struct oz_farewell *fwell; oz_pd_dbg(pd, ON, "Destroying PD\n"); + if (hrtimer_active(&pd->timeout)) + hrtimer_cancel(&pd->timeout); + if (hrtimer_active(&pd->heartbeat)) + hrtimer_cancel(&pd->heartbeat); + /*Disable timer tasklets*/ + tasklet_kill(&pd->heartbeat_tasklet); + tasklet_kill(&pd->timeout_tasklet); /* Delete any streams. */ e = pd->stream_list.next; @@ -287,8 +302,8 @@ void oz_pd_heartbeat(struct oz_pd *pd, u16 apps) more = 1; } } - if (more) - oz_pd_request_heartbeat(pd); + if ((!more) && (hrtimer_active(&pd->heartbeat))) + hrtimer_cancel(&pd->heartbeat); if (pd->mode & OZ_F_ISOC_ANYTIME) { int count = 8; while (count-- && (oz_send_isoc_frame(pd) >= 0)) @@ -315,7 +330,6 @@ void oz_pd_stop(struct oz_pd *pd) list_del(&pd->link); oz_polling_unlock_bh(); oz_dbg(ON, "pd ref count = %d\n", atomic_read(&pd->ref_count)); - oz_timer_delete(pd, 0); oz_pd_put(pd); } /*------------------------------------------------------------------------------ @@ -330,21 +344,18 @@ int oz_pd_sleep(struct oz_pd *pd) oz_polling_unlock_bh(); return 0; } - if (pd->keep_alive_j && pd->session_id) { + if (pd->keep_alive && pd->session_id) oz_pd_set_state(pd, OZ_PD_S_SLEEP); - pd->pulse_time_j = jiffies + pd->keep_alive_j; - oz_dbg(ON, "Sleep Now %lu until %lu\n", - jiffies, pd->pulse_time_j); - } else { + else do_stop = 1; - } + stop_apps = pd->total_apps; oz_polling_unlock_bh(); if (do_stop) { oz_pd_stop(pd); } else { oz_services_stop(pd, stop_apps, 1); - oz_timer_add(pd, OZ_TIMER_STOP, jiffies + pd->keep_alive_j, 1); + oz_timer_add(pd, OZ_TIMER_STOP, pd->keep_alive); } return do_stop; } diff --git a/drivers/staging/ozwpan/ozpd.h b/drivers/staging/ozwpan/ozpd.h index fbf47cbab8a9..a281753774e6 100644 --- a/drivers/staging/ozwpan/ozpd.h +++ b/drivers/staging/ozwpan/ozpd.h @@ -6,6 +6,7 @@ #ifndef _OZPD_H_ #define _OZPD_H_ +#include #include "ozeltbuf.h" /* PD state @@ -68,18 +69,16 @@ struct oz_pd { u8 isoc_sent; u32 last_rx_pkt_num; u32 last_tx_pkt_num; + struct timespec last_rx_timestamp; u32 trigger_pkt_num; - unsigned long pulse_time_j; - unsigned long timeout_time_j; - unsigned long pulse_period_j; - unsigned long presleep_j; - unsigned long keep_alive_j; - unsigned long last_rx_time_j; + unsigned long pulse_time; + unsigned long pulse_period; + unsigned long presleep; + unsigned long keep_alive; struct oz_elt_buf elt_buff; void *app_ctx[OZ_APPID_MAX]; spinlock_t app_lock[OZ_APPID_MAX]; int max_tx_size; - u8 heartbeat_requested; u8 mode; u8 ms_per_isoc; unsigned isoc_latency; @@ -95,6 +94,11 @@ struct oz_pd { spinlock_t stream_lock; struct list_head stream_list; struct net_device *net_dev; + struct hrtimer heartbeat; + struct hrtimer timeout; + u8 timeout_type; + struct tasklet_struct heartbeat_tasklet; + struct tasklet_struct timeout_tasklet; }; #define OZ_MAX_QUEUED_FRAMES 4 diff --git a/drivers/staging/ozwpan/ozproto.c b/drivers/staging/ozwpan/ozproto.c index 760761df3845..ed22729ea90d 100644 --- a/drivers/staging/ozwpan/ozproto.c +++ b/drivers/staging/ozwpan/ozproto.c @@ -30,12 +30,6 @@ #define OZ_DO_STOP 1 #define OZ_DO_SLEEP 2 -/* States of the timer. - */ -#define OZ_TIMER_IDLE 0 -#define OZ_TIMER_SET 1 -#define OZ_TIMER_IN_HANDLER 2 - #define OZ_MAX_TIMER_POOL_SIZE 16 /*------------------------------------------------------------------------------ @@ -46,12 +40,6 @@ struct oz_binding { struct oz_binding *next; }; -struct oz_timer { - struct list_head link; - struct oz_pd *pd; - unsigned long due_time; - int type; -}; /*------------------------------------------------------------------------------ * Static external variables. */ @@ -63,15 +51,6 @@ static struct sk_buff_head g_rx_queue; static u8 g_session_id; static u16 g_apps = 0x1; static int g_processing_rx; -static struct timer_list g_timer; -static struct oz_timer *g_cur_timer; -static struct list_head *g_timer_pool; -static int g_timer_pool_count; -static int g_timer_state = OZ_TIMER_IDLE; -static LIST_HEAD(g_timer_list); -/*------------------------------------------------------------------------------ - */ -static void oz_protocol_timer_start(void); /*------------------------------------------------------------------------------ * Context: softirq-serialized */ @@ -138,33 +117,37 @@ static void pd_set_keepalive(struct oz_pd *pd, u8 kalive) switch (kalive & OZ_KALIVE_TYPE_MASK) { case OZ_KALIVE_SPECIAL: - pd->keep_alive_j = - oz_ms_to_jiffies(keep_alive * 1000*60*60*24*20); + pd->keep_alive = keep_alive * 1000*60*60*24*20; break; case OZ_KALIVE_SECS: - pd->keep_alive_j = oz_ms_to_jiffies(keep_alive*1000); + pd->keep_alive = keep_alive*1000; break; case OZ_KALIVE_MINS: - pd->keep_alive_j = oz_ms_to_jiffies(keep_alive*1000*60); + pd->keep_alive = keep_alive*1000*60; break; case OZ_KALIVE_HOURS: - pd->keep_alive_j = oz_ms_to_jiffies(keep_alive*1000*60*60); + pd->keep_alive = keep_alive*1000*60*60; break; default: - pd->keep_alive_j = 0; + pd->keep_alive = 0; } - oz_dbg(ON, "Keepalive = %lu jiffies\n", pd->keep_alive_j); + oz_dbg(ON, "Keepalive = %lu mSec\n", pd->keep_alive); } /*------------------------------------------------------------------------------ * Context: softirq-serialized */ -static void pd_set_presleep(struct oz_pd *pd, u8 presleep) +static void pd_set_presleep(struct oz_pd *pd, u8 presleep, u8 start_timer) { if (presleep) - pd->presleep_j = oz_ms_to_jiffies(presleep*100); + pd->presleep = presleep*100; else - pd->presleep_j = OZ_PRESLEEP_TOUT_J; - oz_dbg(ON, "Presleep time = %lu jiffies\n", pd->presleep_j); + pd->presleep = OZ_PRESLEEP_TOUT; + if (start_timer) { + spin_unlock(&g_polling_lock); + oz_timer_add(pd, OZ_TIMER_TOUT, pd->presleep); + spin_lock(&g_polling_lock); + } + oz_dbg(ON, "Presleep time = %lu mSec\n", pd->presleep); } /*------------------------------------------------------------------------------ * Context: softirq-serialized @@ -189,7 +172,7 @@ static struct oz_pd *oz_connect_req(struct oz_pd *cur_pd, struct oz_elt *elt, pd = oz_pd_alloc(pd_addr); if (pd == NULL) return NULL; - pd->last_rx_time_j = jiffies; + getnstimeofday(&pd->last_rx_timestamp); spin_lock_bh(&g_polling_lock); list_for_each(e, &g_pd_list) { pd2 = container_of(e, struct oz_pd, link); @@ -238,9 +221,8 @@ static struct oz_pd *oz_connect_req(struct oz_pd *cur_pd, struct oz_elt *elt, oz_dbg(ON, "Max frame:%u Ms per isoc:%u\n", pd->max_tx_size, pd->ms_per_isoc); pd->max_stream_buffering = 3*1024; - pd->timeout_time_j = jiffies + OZ_CONNECTION_TOUT_J; - pd->pulse_period_j = OZ_QUANTUM_J; - pd_set_presleep(pd, body->presleep); + pd->pulse_period = OZ_QUANTUM; + pd_set_presleep(pd, body->presleep, 0); pd_set_keepalive(pd, body->keep_alive); new_apps &= le16_to_cpu(get_unaligned(&body->apps)); @@ -272,7 +254,6 @@ done: u16 resume_apps = new_apps & pd->paused_apps & ~0x1; spin_unlock_bh(&g_polling_lock); oz_pd_set_state(pd, OZ_PD_S_CONNECTED); - oz_timer_delete(pd, OZ_TIMER_STOP); oz_dbg(ON, "new_apps=0x%x total_apps=0x%x paused_apps=0x%x\n", new_apps, pd->total_apps, pd->paused_apps); if (start_apps) { @@ -341,6 +322,7 @@ static void oz_rx_frame(struct sk_buff *skb) int length; struct oz_pd *pd = NULL; struct oz_hdr *oz_hdr = (struct oz_hdr *)skb_network_header(skb); + struct timespec current_time; int dup = 0; u32 pkt_num; @@ -361,9 +343,14 @@ static void oz_rx_frame(struct sk_buff *skb) pd = oz_pd_find(src_addr); if (pd) { - pd->last_rx_time_j = jiffies; - oz_timer_add(pd, OZ_TIMER_TOUT, - pd->last_rx_time_j + pd->presleep_j, 1); + if (!(pd->state & OZ_PD_S_CONNECTED)) + oz_pd_set_state(pd, OZ_PD_S_CONNECTED); + getnstimeofday(¤t_time); + if ((current_time.tv_sec != pd->last_rx_timestamp.tv_sec) || + (pd->presleep < MSEC_PER_SEC)) { + oz_timer_add(pd, OZ_TIMER_TOUT, pd->presleep); + pd->last_rx_timestamp = current_time; + } if (pkt_num != pd->last_rx_pkt_num) { pd->last_rx_pkt_num = pkt_num; } else { @@ -412,7 +399,7 @@ static void oz_rx_frame(struct sk_buff *skb) if (pd && (pd->state & OZ_PD_S_CONNECTED)) { spin_lock(&g_polling_lock); pd_set_keepalive(pd, body->keepalive); - pd_set_presleep(pd, body->presleep); + pd_set_presleep(pd, body->presleep, 1); spin_unlock(&g_polling_lock); } } @@ -450,8 +437,6 @@ done: */ void oz_protocol_term(void) { - struct list_head *chain; - del_timer_sync(&g_timer); /* Walk the list of bindings and remove each one. */ spin_lock_bh(&g_binding_lock); @@ -480,21 +465,35 @@ void oz_protocol_term(void) oz_pd_put(pd); spin_lock_bh(&g_polling_lock); } - chain = g_timer_pool; - g_timer_pool = NULL; spin_unlock_bh(&g_polling_lock); - while (chain) { - struct oz_timer *t = container_of(chain, struct oz_timer, link); - chain = chain->next; - kfree(t); - } oz_dbg(ON, "Protocol stopped\n"); } /*------------------------------------------------------------------------------ * Context: softirq */ -static void oz_pd_handle_timer(struct oz_pd *pd, int type) +void oz_pd_heartbeat_handler(unsigned long data) { + struct oz_pd *pd = (struct oz_pd *)data; + u16 apps = 0; + spin_lock_bh(&g_polling_lock); + if (pd->state & OZ_PD_S_CONNECTED) + apps = pd->total_apps; + spin_unlock_bh(&g_polling_lock); + if (apps) + oz_pd_heartbeat(pd, apps); + +} +/*------------------------------------------------------------------------------ + * Context: softirq + */ +void oz_pd_timeout_handler(unsigned long data) +{ + int type; + struct oz_pd *pd = (struct oz_pd *)data; + + spin_lock_bh(&g_polling_lock); + type = pd->timeout_type; + spin_unlock_bh(&g_polling_lock); switch (type) { case OZ_TIMER_TOUT: oz_pd_sleep(pd); @@ -502,218 +501,69 @@ static void oz_pd_handle_timer(struct oz_pd *pd, int type) case OZ_TIMER_STOP: oz_pd_stop(pd); break; - case OZ_TIMER_HEARTBEAT: { - u16 apps = 0; - spin_lock_bh(&g_polling_lock); - pd->heartbeat_requested = 0; - if (pd->state & OZ_PD_S_CONNECTED) - apps = pd->total_apps; - spin_unlock_bh(&g_polling_lock); - if (apps) - oz_pd_heartbeat(pd, apps); + } +} +/*------------------------------------------------------------------------------ + * Context: Interrupt + */ +enum hrtimer_restart oz_pd_heartbeat_event(struct hrtimer *timer) +{ + struct oz_pd *pd; + + pd = container_of(timer, struct oz_pd, heartbeat); + hrtimer_forward_now(timer, ktime_set(pd->pulse_period / + MSEC_PER_SEC, (pd->pulse_period % MSEC_PER_SEC) * NSEC_PER_MSEC)); + tasklet_schedule(&pd->heartbeat_tasklet); + return HRTIMER_RESTART; +} +/*------------------------------------------------------------------------------ + * Context: Interrupt + */ +enum hrtimer_restart oz_pd_timeout_event(struct hrtimer *timer) +{ + struct oz_pd *pd; + + pd = container_of(timer, struct oz_pd, timeout); + tasklet_schedule(&pd->timeout_tasklet); + return HRTIMER_NORESTART; +} +/*------------------------------------------------------------------------------ + * Context: softirq or process + */ +void oz_timer_add(struct oz_pd *pd, int type, unsigned long due_time) +{ + spin_lock_bh(&g_polling_lock); + switch (type) { + case OZ_TIMER_TOUT: + case OZ_TIMER_STOP: + if (hrtimer_active(&pd->timeout)) { + hrtimer_set_expires(&pd->timeout, ktime_set(due_time / + MSEC_PER_SEC, (due_time % MSEC_PER_SEC) * + NSEC_PER_MSEC)); + hrtimer_start_expires(&pd->timeout, HRTIMER_MODE_REL); + } else { + hrtimer_start(&pd->timeout, ktime_set(due_time / + MSEC_PER_SEC, (due_time % MSEC_PER_SEC) * + NSEC_PER_MSEC), HRTIMER_MODE_REL); } + pd->timeout_type = type; + break; + case OZ_TIMER_HEARTBEAT: + if (!hrtimer_active(&pd->heartbeat)) + hrtimer_start(&pd->heartbeat, ktime_set(due_time / + MSEC_PER_SEC, (due_time % MSEC_PER_SEC) * + NSEC_PER_MSEC), HRTIMER_MODE_REL); break; } -} -/*------------------------------------------------------------------------------ - * Context: softirq - */ -static void oz_protocol_timer(unsigned long arg) -{ - struct oz_timer *t; - struct oz_timer *t2; - struct oz_pd *pd; - spin_lock_bh(&g_polling_lock); - if (!g_cur_timer) { - /* This happens if we remove the current timer but can't stop - * the timer from firing. In this case just get out. - */ - spin_unlock_bh(&g_polling_lock); - return; - } - g_timer_state = OZ_TIMER_IN_HANDLER; - t = g_cur_timer; - g_cur_timer = NULL; - list_del(&t->link); spin_unlock_bh(&g_polling_lock); - do { - pd = t->pd; - oz_pd_handle_timer(pd, t->type); - spin_lock_bh(&g_polling_lock); - if (g_timer_pool_count < OZ_MAX_TIMER_POOL_SIZE) { - t->link.next = g_timer_pool; - g_timer_pool = &t->link; - g_timer_pool_count++; - t = NULL; - } - if (!list_empty(&g_timer_list)) { - t2 = container_of(g_timer_list.next, - struct oz_timer, link); - if (time_before_eq(t2->due_time, jiffies)) - list_del(&t2->link); - else - t2 = NULL; - } else { - t2 = NULL; - } - spin_unlock_bh(&g_polling_lock); - oz_pd_put(pd); - kfree(t); - t = t2; - } while (t); - g_timer_state = OZ_TIMER_IDLE; - oz_protocol_timer_start(); -} -/*------------------------------------------------------------------------------ - * Context: softirq - */ -static void oz_protocol_timer_start(void) -{ - spin_lock_bh(&g_polling_lock); - if (!list_empty(&g_timer_list)) { - g_cur_timer = - container_of(g_timer_list.next, struct oz_timer, link); - if (g_timer_state == OZ_TIMER_SET) { - mod_timer(&g_timer, g_cur_timer->due_time); - } else { - g_timer.expires = g_cur_timer->due_time; - g_timer.function = oz_protocol_timer; - g_timer.data = 0; - add_timer(&g_timer); - } - g_timer_state = OZ_TIMER_SET; - } else { - oz_dbg(ON, "No queued timers\n"); - } - spin_unlock_bh(&g_polling_lock); -} -/*------------------------------------------------------------------------------ - * Context: softirq or process - */ -void oz_timer_add(struct oz_pd *pd, int type, unsigned long due_time, - int remove) -{ - struct list_head *e; - struct oz_timer *t = NULL; - int restart_needed = 0; - spin_lock(&g_polling_lock); - if (remove) { - list_for_each(e, &g_timer_list) { - t = container_of(e, struct oz_timer, link); - if ((t->pd == pd) && (t->type == type)) { - if (g_cur_timer == t) { - restart_needed = 1; - g_cur_timer = NULL; - } - list_del(e); - break; - } - t = NULL; - } - } - if (!t) { - if (g_timer_pool) { - t = container_of(g_timer_pool, struct oz_timer, link); - g_timer_pool = g_timer_pool->next; - g_timer_pool_count--; - } else { - t = kmalloc(sizeof(struct oz_timer), GFP_ATOMIC); - } - if (t) { - t->pd = pd; - t->type = type; - oz_pd_get(pd); - } - } - if (t) { - struct oz_timer *t2; - t->due_time = due_time; - list_for_each(e, &g_timer_list) { - t2 = container_of(e, struct oz_timer, link); - if (time_before(due_time, t2->due_time)) { - if (t2 == g_cur_timer) { - g_cur_timer = NULL; - restart_needed = 1; - } - break; - } - } - list_add_tail(&t->link, e); - } - if (g_timer_state == OZ_TIMER_IDLE) - restart_needed = 1; - else if (g_timer_state == OZ_TIMER_IN_HANDLER) - restart_needed = 0; - spin_unlock(&g_polling_lock); - if (restart_needed) - oz_protocol_timer_start(); -} -/*------------------------------------------------------------------------------ - * Context: softirq or process - */ -void oz_timer_delete(struct oz_pd *pd, int type) -{ - struct list_head *chain = NULL; - struct oz_timer *t; - struct oz_timer *n; - int restart_needed = 0; - int release = 0; - spin_lock(&g_polling_lock); - list_for_each_entry_safe(t, n, &g_timer_list, link) { - if ((t->pd == pd) && ((type == 0) || (t->type == type))) { - if (g_cur_timer == t) { - restart_needed = 1; - g_cur_timer = NULL; - del_timer(&g_timer); - } - list_del(&t->link); - release++; - if (g_timer_pool_count < OZ_MAX_TIMER_POOL_SIZE) { - t->link.next = g_timer_pool; - g_timer_pool = &t->link; - g_timer_pool_count++; - } else { - t->link.next = chain; - chain = &t->link; - } - if (type) - break; - } - } - if (g_timer_state == OZ_TIMER_IN_HANDLER) - restart_needed = 0; - else if (restart_needed) - g_timer_state = OZ_TIMER_IDLE; - spin_unlock(&g_polling_lock); - if (restart_needed) - oz_protocol_timer_start(); - while (release--) - oz_pd_put(pd); - while (chain) { - t = container_of(chain, struct oz_timer, link); - chain = chain->next; - kfree(t); - } } /*------------------------------------------------------------------------------ * Context: softirq or process */ void oz_pd_request_heartbeat(struct oz_pd *pd) { - unsigned long now = jiffies; - unsigned long t; - spin_lock(&g_polling_lock); - if (pd->heartbeat_requested) { - spin_unlock(&g_polling_lock); - return; - } - if (pd->pulse_period_j) - t = ((now / pd->pulse_period_j) + 1) * pd->pulse_period_j; - else - t = now + 1; - pd->heartbeat_requested = 1; - spin_unlock(&g_polling_lock); - oz_timer_add(pd, OZ_TIMER_HEARTBEAT, t, 0); + oz_timer_add(pd, OZ_TIMER_HEARTBEAT, pd->pulse_period > 0 ? + pd->pulse_period : OZ_QUANTUM); } /*------------------------------------------------------------------------------ * Context: softirq or process @@ -915,7 +765,6 @@ int oz_protocol_init(char *devs) oz_binding_add(d); } } - init_timer(&g_timer); return 0; } /*------------------------------------------------------------------------------ diff --git a/drivers/staging/ozwpan/ozproto.h b/drivers/staging/ozwpan/ozproto.h index 9bb0a6abfc88..305c5321022d 100644 --- a/drivers/staging/ozwpan/ozproto.h +++ b/drivers/staging/ozwpan/ozproto.h @@ -12,20 +12,11 @@ #define OZ_ALLOCATED_SPACE(__x) (LL_RESERVED_SPACE(__x)+(__x)->needed_tailroom) -/* Converts millisecs to jiffies. - */ -#define oz_ms_to_jiffies(__x) msecs_to_jiffies(__x) - -/* Quantum milliseconds. - */ -#define OZ_QUANTUM_MS 8 -/* Quantum jiffies - */ -#define OZ_QUANTUM_J (oz_ms_to_jiffies(OZ_QUANTUM_MS)) +/* Quantum in MS */ +#define OZ_QUANTUM 8 /* Default timeouts. */ -#define OZ_CONNECTION_TOUT_J (2*HZ) -#define OZ_PRESLEEP_TOUT_J (11*HZ) +#define OZ_PRESLEEP_TOUT 11 /* Maximun sizes of tx frames. */ #define OZ_MAX_TX_SIZE 1514 @@ -65,11 +56,16 @@ void oz_app_enable(int app_id, int enable); struct oz_pd *oz_pd_find(const u8 *mac_addr); void oz_binding_add(char *net_dev); void oz_binding_remove(char *net_dev); -void oz_timer_add(struct oz_pd *pd, int type, unsigned long due_time, - int remove); +void oz_timer_add(struct oz_pd *pd, int type, unsigned long due_time); void oz_timer_delete(struct oz_pd *pd, int type); void oz_pd_request_heartbeat(struct oz_pd *pd); void oz_polling_lock_bh(void); void oz_polling_unlock_bh(void); +void oz_pd_heartbeat_handler(unsigned long data); +void oz_pd_timeout_handler(unsigned long data); +enum hrtimer_restart oz_pd_heartbeat_event(struct hrtimer *timer); +enum hrtimer_restart oz_pd_timeout_event(struct hrtimer *timer); +int oz_get_pd_status_list(char *pd_list, int max_count); +int oz_get_binding_list(char *buf, int max_if); #endif /* _OZPROTO_H */ diff --git a/drivers/staging/ozwpan/ozurbparanoia.c b/drivers/staging/ozwpan/ozurbparanoia.c index 366584b75767..d69e8ab9db9a 100644 --- a/drivers/staging/ozwpan/ozurbparanoia.c +++ b/drivers/staging/ozwpan/ozurbparanoia.c @@ -24,7 +24,7 @@ void oz_remember_urb(struct urb *urb) spin_lock_irqsave(&g_urb_mem_lock, irq_state); if (g_nb_urbs < OZ_MAX_URBS) { g_urb_memory[g_nb_urbs++] = urb; - oz_dbg(ON, "%lu: urb up = %d %p\n", jiffies, g_nb_urbs, urb); + oz_dbg(ON, "urb up = %d %p\n", g_nb_urbs, urb); } else { oz_dbg(ON, "ERROR urb buffer full\n"); } @@ -44,8 +44,7 @@ int oz_forget_urb(struct urb *urb) if (--g_nb_urbs > i) memcpy(&g_urb_memory[i], &g_urb_memory[i+1], (g_nb_urbs - i) * sizeof(struct urb *)); - oz_dbg(ON, "%lu: urb down = %d %p\n", - jiffies, g_nb_urbs, urb); + oz_dbg(ON, "urb down = %d %p\n", g_nb_urbs, urb); } } spin_unlock_irqrestore(&g_urb_mem_lock, irq_state); diff --git a/drivers/staging/ozwpan/ozusbsvc.c b/drivers/staging/ozwpan/ozusbsvc.c index 816cac980586..732face55e8c 100644 --- a/drivers/staging/ozwpan/ozusbsvc.c +++ b/drivers/staging/ozwpan/ozusbsvc.c @@ -123,7 +123,8 @@ void oz_usb_stop(struct oz_pd *pd, int pause) pd->app_ctx[OZ_APPID_USB-1] = NULL; spin_unlock_bh(&pd->app_lock[OZ_APPID_USB-1]); if (usb_ctx) { - unsigned long tout = jiffies + HZ; + struct timespec ts, now; + getnstimeofday(&ts); oz_dbg(ON, "USB service stopping...\n"); usb_ctx->stopped = 1; /* At this point the reference count on the usb context should @@ -132,9 +133,12 @@ void oz_usb_stop(struct oz_pd *pd, int pause) * should get in but someone may already be in. So wait * until they leave but timeout after 1 second. */ - while ((atomic_read(&usb_ctx->ref_count) > 2) && - time_before(jiffies, tout)) - ; + while ((atomic_read(&usb_ctx->ref_count) > 2)) { + getnstimeofday(&now); + /*Approx 1 Sec. this is not perfect calculation*/ + if (now.tv_sec != ts.tv_sec) + break; + } oz_dbg(ON, "USB service stopped\n"); oz_hcd_pd_departed(usb_ctx->hport); /* Release the reference taken in oz_usb_start. @@ -155,7 +159,7 @@ void oz_usb_get(void *hpd) /*------------------------------------------------------------------------------ * This decrements the reference count of the context area for a specific PD * and destroys the context area if the reference count becomes zero. - * Context: softirq or process + * Context: irq or process */ void oz_usb_put(void *hpd) { From 4918072eb0fa3d430613c11b4cb287e6c3bf1879 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 30 Jul 2013 23:42:53 +0300 Subject: [PATCH 1250/3400] staging: octeon-usb: cvmx_usb_speed_t -> enum cvmx_usb_speed Replace cvmx_usb_speed_t with enum cvmx_usb_speed. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.c | 4 ++-- drivers/staging/octeon-usb/cvmx-usb.h | 21 ++++++++++++--------- drivers/staging/octeon-usb/octeon-hcd.c | 2 +- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.c b/drivers/staging/octeon-usb/cvmx-usb.c index fa029e3f8db1..44f4db0cfd9a 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.c +++ b/drivers/staging/octeon-usb/cvmx-usb.c @@ -151,7 +151,7 @@ typedef struct cvmx_usb_pipe { uint64_t interval; /**< For periodic pipes, the interval between packets in frames */ uint64_t next_tx_frame; /**< The next frame this pipe is allowed to transmit on */ cvmx_usb_pipe_flags_t flags; /**< State flags for this pipe */ - cvmx_usb_speed_t device_speed; /**< Speed of device connected to this pipe */ + enum cvmx_usb_speed device_speed; /**< Speed of device connected to this pipe */ cvmx_usb_transfer_t transfer_type; /**< Type of transaction supported by this pipe */ cvmx_usb_direction_t transfer_dir; /**< IN or OUT. Ignored for Control */ int multi_count; /**< Max packet in a row for the device */ @@ -1103,7 +1103,7 @@ static inline int __cvmx_usb_get_pipe_handle(cvmx_usb_internal_state_t *usb, */ int cvmx_usb_open_pipe(cvmx_usb_state_t *state, cvmx_usb_pipe_flags_t flags, int device_addr, int endpoint_num, - cvmx_usb_speed_t device_speed, int max_packet, + enum cvmx_usb_speed device_speed, int max_packet, cvmx_usb_transfer_t transfer_type, cvmx_usb_direction_t transfer_dir, int interval, int multi_count, int hub_device_addr, int hub_port) diff --git a/drivers/staging/octeon-usb/cvmx-usb.h b/drivers/staging/octeon-usb/cvmx-usb.h index 4b425e5fa8ae..c5ccda34b530 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.h +++ b/drivers/staging/octeon-usb/cvmx-usb.h @@ -235,14 +235,17 @@ #define __CVMX_USB_H__ /** - * Enumerations representing the possible USB device speeds + * enum cvmx_usb_speed - the possible USB device speeds + * + * @CVMX_USB_SPEED_HIGH: Device is operation at 480Mbps + * @CVMX_USB_SPEED_FULL: Device is operation at 12Mbps + * @CVMX_USB_SPEED_LOW: Device is operation at 1.5Mbps */ -typedef enum -{ - CVMX_USB_SPEED_HIGH = 0, /**< Device is operation at 480Mbps */ - CVMX_USB_SPEED_FULL = 1, /**< Device is operation at 12Mbps */ - CVMX_USB_SPEED_LOW = 2, /**< Device is operation at 1.5Mbps */ -} cvmx_usb_speed_t; +enum cvmx_usb_speed { + CVMX_USB_SPEED_HIGH = 0, + CVMX_USB_SPEED_FULL = 1, + CVMX_USB_SPEED_LOW = 2, +}; /** * Enumeration representing the possible USB transfer types. @@ -290,7 +293,7 @@ typedef struct uint32_t port_enabled : 1; /**< 1 = Usb port is enabled, 0 = disabled */ uint32_t port_over_current : 1; /**< 1 = Over current detected, 0 = Over current not detected. Octeon doesn't support over current detection */ uint32_t port_powered : 1; /**< 1 = Port power is being supplied to the device, 0 = power is off. Octeon doesn't support turning port power off */ - cvmx_usb_speed_t port_speed : 2; /**< Current port speed */ + enum cvmx_usb_speed port_speed : 2; /**< Current port speed */ uint32_t connected : 1; /**< 1 = A device is connected to the port, 0 = No device is connected */ uint32_t connect_change : 1; /**< 1 = Device connected state changed since the last set status call */ } cvmx_usb_port_status_t; @@ -413,7 +416,7 @@ extern void cvmx_usb_set_status(cvmx_usb_state_t *state, cvmx_usb_port_status_t extern int cvmx_usb_open_pipe(cvmx_usb_state_t *state, cvmx_usb_pipe_flags_t flags, int device_addr, int endpoint_num, - cvmx_usb_speed_t device_speed, int max_packet, + enum cvmx_usb_speed device_speed, int max_packet, cvmx_usb_transfer_t transfer_type, cvmx_usb_direction_t transfer_dir, int interval, int multi_count, int hub_device_addr, diff --git a/drivers/staging/octeon-usb/octeon-hcd.c b/drivers/staging/octeon-usb/octeon-hcd.c index d156b603ae65..f32d8fc60200 100644 --- a/drivers/staging/octeon-usb/octeon-hcd.c +++ b/drivers/staging/octeon-usb/octeon-hcd.c @@ -217,7 +217,7 @@ static int octeon_usb_urb_enqueue(struct usb_hcd *hcd, if (!ep->hcpriv) { cvmx_usb_transfer_t transfer_type; - cvmx_usb_speed_t speed; + enum cvmx_usb_speed speed; int split_device = 0; int split_port = 0; switch (usb_pipetype(urb->pipe)) { From 394d4e080f31cd59ccfd1ab8983dcf79c8f7e774 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 30 Jul 2013 23:42:54 +0300 Subject: [PATCH 1251/3400] staging: octeon-usb: cvmx_usb_transfer_t -> enum cvmx_usb_transfer Replace cvmx_usb_transfer_t with enum cvmx_usb_transfer. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.c | 10 +++++----- drivers/staging/octeon-usb/cvmx-usb.h | 26 ++++++++++++++++--------- drivers/staging/octeon-usb/octeon-hcd.c | 2 +- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.c b/drivers/staging/octeon-usb/cvmx-usb.c index 44f4db0cfd9a..ff5d1706c423 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.c +++ b/drivers/staging/octeon-usb/cvmx-usb.c @@ -122,7 +122,7 @@ typedef enum { typedef struct cvmx_usb_transaction { struct cvmx_usb_transaction *prev; /**< Transaction before this one in the pipe */ struct cvmx_usb_transaction *next; /**< Transaction after this one in the pipe */ - cvmx_usb_transfer_t type; /**< Type of transaction, duplicated of the pipe */ + enum cvmx_usb_transfer type; /**< Type of transaction, duplicated of the pipe */ cvmx_usb_transaction_flags_t flags; /**< State flags for this transaction */ uint64_t buffer; /**< User's physical buffer address to read/write */ int buffer_length; /**< Size of the user's buffer in bytes */ @@ -152,7 +152,7 @@ typedef struct cvmx_usb_pipe { uint64_t next_tx_frame; /**< The next frame this pipe is allowed to transmit on */ cvmx_usb_pipe_flags_t flags; /**< State flags for this pipe */ enum cvmx_usb_speed device_speed; /**< Speed of device connected to this pipe */ - cvmx_usb_transfer_t transfer_type; /**< Type of transaction supported by this pipe */ + enum cvmx_usb_transfer transfer_type; /**< Type of transaction supported by this pipe */ cvmx_usb_direction_t transfer_dir; /**< IN or OUT. Ignored for Control */ int multi_count; /**< Max packet in a row for the device */ uint16_t max_packet; /**< The device's maximum packet size in bytes */ @@ -1104,7 +1104,7 @@ static inline int __cvmx_usb_get_pipe_handle(cvmx_usb_internal_state_t *usb, int cvmx_usb_open_pipe(cvmx_usb_state_t *state, cvmx_usb_pipe_flags_t flags, int device_addr, int endpoint_num, enum cvmx_usb_speed device_speed, int max_packet, - cvmx_usb_transfer_t transfer_type, + enum cvmx_usb_transfer transfer_type, cvmx_usb_direction_t transfer_dir, int interval, int multi_count, int hub_device_addr, int hub_port) { @@ -1825,7 +1825,7 @@ static void __cvmx_usb_schedule(cvmx_usb_internal_state_t *usb, int is_sof) int channel; cvmx_usb_pipe_t *pipe; int need_sof; - cvmx_usb_transfer_t ttype; + enum cvmx_usb_transfer ttype; if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) { /* Without DMA we need to be careful to not schedule something at the end of a frame and cause an overrun */ @@ -2025,7 +2025,7 @@ done: */ static int __cvmx_usb_submit_transaction(cvmx_usb_internal_state_t *usb, int pipe_handle, - cvmx_usb_transfer_t type, + enum cvmx_usb_transfer type, int flags, uint64_t buffer, int buffer_length, diff --git a/drivers/staging/octeon-usb/cvmx-usb.h b/drivers/staging/octeon-usb/cvmx-usb.h index c5ccda34b530..0cb13ee21950 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.h +++ b/drivers/staging/octeon-usb/cvmx-usb.h @@ -248,15 +248,23 @@ enum cvmx_usb_speed { }; /** - * Enumeration representing the possible USB transfer types. + * enum cvmx_usb_transfer - the possible USB transfer types + * + * @CVMX_USB_TRANSFER_CONTROL: USB transfer type control for hub and status + * transfers + * @CVMX_USB_TRANSFER_ISOCHRONOUS: USB transfer type isochronous for low + * priority periodic transfers + * @CVMX_USB_TRANSFER_BULK: USB transfer type bulk for large low priority + * transfers + * @CVMX_USB_TRANSFER_INTERRUPT: USB transfer type interrupt for high priority + * periodic transfers */ -typedef enum -{ - CVMX_USB_TRANSFER_CONTROL = 0, /**< USB transfer type control for hub and status transfers */ - CVMX_USB_TRANSFER_ISOCHRONOUS = 1, /**< USB transfer type isochronous for low priority periodic transfers */ - CVMX_USB_TRANSFER_BULK = 2, /**< USB transfer type bulk for large low priority transfers */ - CVMX_USB_TRANSFER_INTERRUPT = 3, /**< USB transfer type interrupt for high priority periodic transfers */ -} cvmx_usb_transfer_t; +enum cvmx_usb_transfer { + CVMX_USB_TRANSFER_CONTROL = 0, + CVMX_USB_TRANSFER_ISOCHRONOUS = 1, + CVMX_USB_TRANSFER_BULK = 2, + CVMX_USB_TRANSFER_INTERRUPT = 3, +}; /** * Enumeration of the transfer directions @@ -417,7 +425,7 @@ extern int cvmx_usb_open_pipe(cvmx_usb_state_t *state, cvmx_usb_pipe_flags_t flags, int device_addr, int endpoint_num, enum cvmx_usb_speed device_speed, int max_packet, - cvmx_usb_transfer_t transfer_type, + enum cvmx_usb_transfer transfer_type, cvmx_usb_direction_t transfer_dir, int interval, int multi_count, int hub_device_addr, int hub_port); diff --git a/drivers/staging/octeon-usb/octeon-hcd.c b/drivers/staging/octeon-usb/octeon-hcd.c index f32d8fc60200..6ab78ed57e80 100644 --- a/drivers/staging/octeon-usb/octeon-hcd.c +++ b/drivers/staging/octeon-usb/octeon-hcd.c @@ -216,7 +216,7 @@ static int octeon_usb_urb_enqueue(struct usb_hcd *hcd, spin_lock_irqsave(&priv->lock, flags); if (!ep->hcpriv) { - cvmx_usb_transfer_t transfer_type; + enum cvmx_usb_transfer transfer_type; enum cvmx_usb_speed speed; int split_device = 0; int split_port = 0; From f1e1c1f69e0d38ddbff9610faa6572f04d3eff20 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 30 Jul 2013 23:42:55 +0300 Subject: [PATCH 1252/3400] staging: octeon-usb: cvmx_usb_direction_t -> enum cvmx_usb_direction Replace cvmx_usb_direction_t with enum cvmx_usb_direction. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.c | 4 ++-- drivers/staging/octeon-usb/cvmx-usb.h | 16 +++++++++------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.c b/drivers/staging/octeon-usb/cvmx-usb.c index ff5d1706c423..533ad5f38826 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.c +++ b/drivers/staging/octeon-usb/cvmx-usb.c @@ -153,7 +153,7 @@ typedef struct cvmx_usb_pipe { cvmx_usb_pipe_flags_t flags; /**< State flags for this pipe */ enum cvmx_usb_speed device_speed; /**< Speed of device connected to this pipe */ enum cvmx_usb_transfer transfer_type; /**< Type of transaction supported by this pipe */ - cvmx_usb_direction_t transfer_dir; /**< IN or OUT. Ignored for Control */ + enum cvmx_usb_direction transfer_dir; /**< IN or OUT. Ignored for Control */ int multi_count; /**< Max packet in a row for the device */ uint16_t max_packet; /**< The device's maximum packet size in bytes */ uint8_t device_addr; /**< USB device address at other end of pipe */ @@ -1105,7 +1105,7 @@ int cvmx_usb_open_pipe(cvmx_usb_state_t *state, cvmx_usb_pipe_flags_t flags, int device_addr, int endpoint_num, enum cvmx_usb_speed device_speed, int max_packet, enum cvmx_usb_transfer transfer_type, - cvmx_usb_direction_t transfer_dir, int interval, + enum cvmx_usb_direction transfer_dir, int interval, int multi_count, int hub_device_addr, int hub_port) { cvmx_usb_pipe_t *pipe; diff --git a/drivers/staging/octeon-usb/cvmx-usb.h b/drivers/staging/octeon-usb/cvmx-usb.h index 0cb13ee21950..7c313ff9c3e6 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.h +++ b/drivers/staging/octeon-usb/cvmx-usb.h @@ -267,13 +267,15 @@ enum cvmx_usb_transfer { }; /** - * Enumeration of the transfer directions + * enum cvmx_usb_direction - the transfer directions + * + * @CVMX_USB_DIRECTION_OUT: Data is transferring from Octeon to the device/host + * @CVMX_USB_DIRECTION_IN: Data is transferring from the device/host to Octeon */ -typedef enum -{ - CVMX_USB_DIRECTION_OUT, /**< Data is transferring from Octeon to the device/host */ - CVMX_USB_DIRECTION_IN, /**< Data is transferring from the device/host to Octeon */ -} cvmx_usb_direction_t; +enum cvmx_usb_direction { + CVMX_USB_DIRECTION_OUT, + CVMX_USB_DIRECTION_IN, +}; /** * Enumeration of all possible status codes passed to callback @@ -426,7 +428,7 @@ extern int cvmx_usb_open_pipe(cvmx_usb_state_t *state, int device_addr, int endpoint_num, enum cvmx_usb_speed device_speed, int max_packet, enum cvmx_usb_transfer transfer_type, - cvmx_usb_direction_t transfer_dir, int interval, + enum cvmx_usb_direction transfer_dir, int interval, int multi_count, int hub_device_addr, int hub_port); extern int cvmx_usb_submit_bulk(cvmx_usb_state_t *state, int pipe_handle, From 1c1bdf2764c7e5d983b20548a2913c0e4df07a3c Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 30 Jul 2013 23:42:56 +0300 Subject: [PATCH 1253/3400] staging: octeon-usb: cvmx_usb_complete_t -> enum cvmx_usb_complete Replace cvmx_usb_complete_t with enum cvmx_usb_complete. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.c | 4 +- drivers/staging/octeon-usb/cvmx-usb.h | 55 ++++++++++++++++--------- drivers/staging/octeon-usb/octeon-hcd.c | 4 +- 3 files changed, 39 insertions(+), 24 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.c b/drivers/staging/octeon-usb/cvmx-usb.c index 533ad5f38826..d8035bb810b8 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.c +++ b/drivers/staging/octeon-usb/cvmx-usb.c @@ -1902,7 +1902,7 @@ static void __cvmx_usb_perform_callback(cvmx_usb_internal_state_t *usb, cvmx_usb_pipe_t *pipe, cvmx_usb_transaction_t *transaction, cvmx_usb_callback_t reason, - cvmx_usb_complete_t complete_code) + enum cvmx_usb_complete complete_code) { cvmx_usb_callback_func_t callback = usb->callback[reason]; void *user_data = usb->callback_data[reason]; @@ -1946,7 +1946,7 @@ static void __cvmx_usb_perform_callback(cvmx_usb_internal_state_t *usb, static void __cvmx_usb_perform_complete(cvmx_usb_internal_state_t *usb, cvmx_usb_pipe_t *pipe, cvmx_usb_transaction_t *transaction, - cvmx_usb_complete_t complete_code) + enum cvmx_usb_complete complete_code) { /* If this was a split then clear our split in progress marker */ if (usb->active_split == transaction) diff --git a/drivers/staging/octeon-usb/cvmx-usb.h b/drivers/staging/octeon-usb/cvmx-usb.h index 7c313ff9c3e6..ea1f2eefc241 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.h +++ b/drivers/staging/octeon-usb/cvmx-usb.h @@ -116,7 +116,7 @@ * * void port_callback(cvmx_usb_state_t *usb, * cvmx_usb_callback_t reason, - * cvmx_usb_complete_t status, + * enum cvmx_usb_complete status, * int pipe_handle, * int submit_handle, * int bytes_transferred, @@ -148,14 +148,14 @@ * * void complete_callback(cvmx_usb_state_t *usb, * cvmx_usb_callback_t reason, - * cvmx_usb_complete_t status, + * enum cvmx_usb_complete status, * int pipe_handle, * int submit_handle, * int bytes_transferred, * void *user_data); * - "usb" is the cvmx_usb_state_t for the port. * - "reason" will always be CVMX_USB_CALLBACK_TRANSFER_COMPLETE. - * - "status" will be one of the cvmx_usb_complete_t enumerations. + * - "status" will be one of the cvmx_usb_complete enumerations. * - "pipe_handle" is the handle to the pipe the transaction * was originally submitted on. * - "submit_handle" is the handle returned by the original @@ -278,21 +278,36 @@ enum cvmx_usb_direction { }; /** - * Enumeration of all possible status codes passed to callback - * functions. + * enum cvmx_usb_complete - possible callback function status codes + * + * @CVMX_USB_COMPLETE_SUCCESS: The transaction / operation finished without + * any errors + * @CVMX_USB_COMPLETE_SHORT: FIXME: This is currently not implemented + * @CVMX_USB_COMPLETE_CANCEL: The transaction was canceled while in flight by + * a user call to cvmx_usb_cancel + * @CVMX_USB_COMPLETE_ERROR: The transaction aborted with an unexpected + * error status + * @CVMX_USB_COMPLETE_STALL: The transaction received a USB STALL response + * from the device + * @CVMX_USB_COMPLETE_XACTERR: The transaction failed with an error from the + * device even after a number of retries + * @CVMX_USB_COMPLETE_DATATGLERR: The transaction failed with a data toggle + * error even after a number of retries + * @CVMX_USB_COMPLETE_BABBLEERR: The transaction failed with a babble error + * @CVMX_USB_COMPLETE_FRAMEERR: The transaction failed with a frame error + * even after a number of retries */ -typedef enum -{ - CVMX_USB_COMPLETE_SUCCESS, /**< The transaction / operation finished without any errors */ - CVMX_USB_COMPLETE_SHORT, /**< FIXME: This is currently not implemented */ - CVMX_USB_COMPLETE_CANCEL, /**< The transaction was canceled while in flight by a user call to cvmx_usb_cancel* */ - CVMX_USB_COMPLETE_ERROR, /**< The transaction aborted with an unexpected error status */ - CVMX_USB_COMPLETE_STALL, /**< The transaction received a USB STALL response from the device */ - CVMX_USB_COMPLETE_XACTERR, /**< The transaction failed with an error from the device even after a number of retries */ - CVMX_USB_COMPLETE_DATATGLERR, /**< The transaction failed with a data toggle error even after a number of retries */ - CVMX_USB_COMPLETE_BABBLEERR, /**< The transaction failed with a babble error */ - CVMX_USB_COMPLETE_FRAMEERR, /**< The transaction failed with a frame error even after a number of retries */ -} cvmx_usb_complete_t; +enum cvmx_usb_complete { + CVMX_USB_COMPLETE_SUCCESS, + CVMX_USB_COMPLETE_SHORT, + CVMX_USB_COMPLETE_CANCEL, + CVMX_USB_COMPLETE_ERROR, + CVMX_USB_COMPLETE_STALL, + CVMX_USB_COMPLETE_XACTERR, + CVMX_USB_COMPLETE_DATATGLERR, + CVMX_USB_COMPLETE_BABBLEERR, + CVMX_USB_COMPLETE_FRAMEERR, +}; /** * Structure returned containing the USB port status information. @@ -331,7 +346,7 @@ typedef struct { int offset; /**< This is the offset in bytes into the main buffer where this data is stored */ int length; /**< This is the length in bytes of the data */ - cvmx_usb_complete_t status; /**< This is the status of this individual packet transfer */ + enum cvmx_usb_complete status; /**< This is the status of this individual packet transfer */ } cvmx_usb_iso_packet_t; /** @@ -368,7 +383,7 @@ typedef struct * cvmx_usb_initialize(). * - reason = The cvmx_usb_callback_t used to register * the callback. - * - status = The cvmx_usb_complete_t representing the + * - status = The enum cvmx_usb_complete representing the * status code of a transaction. * - pipe_handle = The Pipe that caused this callback, or * -1 if this callback wasn't associated with a pipe. @@ -381,7 +396,7 @@ typedef struct * cvmx_usb_register_callback() */ typedef void (*cvmx_usb_callback_func_t)(cvmx_usb_state_t *state, cvmx_usb_callback_t reason, - cvmx_usb_complete_t status, + enum cvmx_usb_complete status, int pipe_handle, int submit_handle, int bytes_transferred, void *user_data); diff --git a/drivers/staging/octeon-usb/octeon-hcd.c b/drivers/staging/octeon-usb/octeon-hcd.c index 6ab78ed57e80..b3c287394e07 100644 --- a/drivers/staging/octeon-usb/octeon-hcd.c +++ b/drivers/staging/octeon-usb/octeon-hcd.c @@ -60,7 +60,7 @@ static irqreturn_t octeon_usb_irq(struct usb_hcd *hcd) static void octeon_usb_port_callback(cvmx_usb_state_t *usb, cvmx_usb_callback_t reason, - cvmx_usb_complete_t status, + enum cvmx_usb_complete status, int pipe_handle, int submit_handle, int bytes_transferred, @@ -107,7 +107,7 @@ static int octeon_usb_get_frame_number(struct usb_hcd *hcd) static void octeon_usb_urb_complete_callback(cvmx_usb_state_t *usb, cvmx_usb_callback_t reason, - cvmx_usb_complete_t status, + enum cvmx_usb_complete status, int pipe_handle, int submit_handle, int bytes_transferred, From e53b624ae56919b6b5c3e65543667293f3dedf99 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 30 Jul 2013 23:42:57 +0300 Subject: [PATCH 1254/3400] staging: octeon-usb: cvmx_usb_callback_t -> enum cvmx_usb_callback Replace cvmx_usb_callback_t with enum cvmx_usb_callback. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.c | 4 +-- drivers/staging/octeon-usb/cvmx-usb.h | 45 ++++++++++++++----------- drivers/staging/octeon-usb/octeon-hcd.c | 4 +-- 3 files changed, 30 insertions(+), 23 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.c b/drivers/staging/octeon-usb/cvmx-usb.c index d8035bb810b8..9e4bf7194ac7 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.c +++ b/drivers/staging/octeon-usb/cvmx-usb.c @@ -1901,7 +1901,7 @@ done: static void __cvmx_usb_perform_callback(cvmx_usb_internal_state_t *usb, cvmx_usb_pipe_t *pipe, cvmx_usb_transaction_t *transaction, - cvmx_usb_callback_t reason, + enum cvmx_usb_callback reason, enum cvmx_usb_complete complete_code) { cvmx_usb_callback_func_t callback = usb->callback[reason]; @@ -2507,7 +2507,7 @@ int cvmx_usb_close_pipe(cvmx_usb_state_t *state, int pipe_handle) * Returns: 0 or a negative error code. */ int cvmx_usb_register_callback(cvmx_usb_state_t *state, - cvmx_usb_callback_t reason, + enum cvmx_usb_callback reason, cvmx_usb_callback_func_t callback, void *user_data) { diff --git a/drivers/staging/octeon-usb/cvmx-usb.h b/drivers/staging/octeon-usb/cvmx-usb.h index ea1f2eefc241..7e1e2986d953 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.h +++ b/drivers/staging/octeon-usb/cvmx-usb.h @@ -115,7 +115,7 @@ * The port callback prototype needs to look as follows: * * void port_callback(cvmx_usb_state_t *usb, - * cvmx_usb_callback_t reason, + * enum cvmx_usb_callback reason, * enum cvmx_usb_complete status, * int pipe_handle, * int submit_handle, @@ -147,7 +147,7 @@ * The completion callback prototype needs to look as follows: * * void complete_callback(cvmx_usb_state_t *usb, - * cvmx_usb_callback_t reason, + * enum cvmx_usb_callback reason, * enum cvmx_usb_complete status, * int pipe_handle, * int submit_handle, @@ -350,21 +350,28 @@ typedef struct } cvmx_usb_iso_packet_t; /** - * Possible callback reasons for the USB API. + * enum cvmx_usb_callback - possible callback reasons for the USB API + * + * @CVMX_USB_CALLBACK_TRANSFER_COMPLETE: A callback of this type is called when + * a submitted transfer completes. The + * completion callback will be called even + * if the transfer fails or is canceled. + * The status parameter will contain + * details of why he callback was called. + * @CVMX_USB_CALLBACK_PORT_CHANGED: The status of the port changed. For + * example, someone may have plugged a + * device in. The status parameter + * contains CVMX_USB_COMPLETE_SUCCESS. Use + * cvmx_usb_get_status() to get the new + * port status. + * @__CVMX_USB_CALLBACK_END: Do not use. Used internally for array + * bounds. */ -typedef enum -{ - CVMX_USB_CALLBACK_TRANSFER_COMPLETE, - /**< A callback of this type is called when a submitted transfer - completes. The completion callback will be called even if the - transfer fails or is canceled. The status parameter will - contain details of why he callback was called. */ - CVMX_USB_CALLBACK_PORT_CHANGED, /**< The status of the port changed. For example, someone may have - plugged a device in. The status parameter contains - CVMX_USB_COMPLETE_SUCCESS. Use cvmx_usb_get_status() to get - the new port status. */ - __CVMX_USB_CALLBACK_END /**< Do not use. Used internally for array bounds */ -} cvmx_usb_callback_t; +enum cvmx_usb_callback { + CVMX_USB_CALLBACK_TRANSFER_COMPLETE, + CVMX_USB_CALLBACK_PORT_CHANGED, + __CVMX_USB_CALLBACK_END +}; /** * USB state internal data. The contents of this structure @@ -381,7 +388,7 @@ typedef struct * The parameters are as follows: * - state = USB device state populated by * cvmx_usb_initialize(). - * - reason = The cvmx_usb_callback_t used to register + * - reason = The enum cvmx_usb_callback used to register * the callback. * - status = The enum cvmx_usb_complete representing the * status code of a transaction. @@ -395,7 +402,7 @@ typedef struct * function cvmx_usb_submit() or * cvmx_usb_register_callback() */ typedef void (*cvmx_usb_callback_func_t)(cvmx_usb_state_t *state, - cvmx_usb_callback_t reason, + enum cvmx_usb_callback reason, enum cvmx_usb_complete status, int pipe_handle, int submit_handle, int bytes_transferred, void *user_data); @@ -481,7 +488,7 @@ extern int cvmx_usb_cancel(cvmx_usb_state_t *state, int pipe_handle, extern int cvmx_usb_cancel_all(cvmx_usb_state_t *state, int pipe_handle); extern int cvmx_usb_close_pipe(cvmx_usb_state_t *state, int pipe_handle); extern int cvmx_usb_register_callback(cvmx_usb_state_t *state, - cvmx_usb_callback_t reason, + enum cvmx_usb_callback reason, cvmx_usb_callback_func_t callback, void *user_data); extern int cvmx_usb_get_frame_number(cvmx_usb_state_t *state); diff --git a/drivers/staging/octeon-usb/octeon-hcd.c b/drivers/staging/octeon-usb/octeon-hcd.c index b3c287394e07..5137da74c2b2 100644 --- a/drivers/staging/octeon-usb/octeon-hcd.c +++ b/drivers/staging/octeon-usb/octeon-hcd.c @@ -59,7 +59,7 @@ static irqreturn_t octeon_usb_irq(struct usb_hcd *hcd) } static void octeon_usb_port_callback(cvmx_usb_state_t *usb, - cvmx_usb_callback_t reason, + enum cvmx_usb_callback reason, enum cvmx_usb_complete status, int pipe_handle, int submit_handle, @@ -106,7 +106,7 @@ static int octeon_usb_get_frame_number(struct usb_hcd *hcd) } static void octeon_usb_urb_complete_callback(cvmx_usb_state_t *usb, - cvmx_usb_callback_t reason, + enum cvmx_usb_callback reason, enum cvmx_usb_complete status, int pipe_handle, int submit_handle, From 1c25754815e6ff06048afb1104754b016acc4202 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 30 Jul 2013 23:42:58 +0300 Subject: [PATCH 1255/3400] staging: octeon-usb: cvmx_usb_initialize_flags_t -> enum cvmx_usb_initialize_flags Replace cvmx_usb_initialize_flags_t with enum cvmx_usb_initialize_flags. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.c | 4 +-- drivers/staging/octeon-usb/cvmx-usb.h | 47 +++++++++++++++++---------- 2 files changed, 32 insertions(+), 19 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.c b/drivers/staging/octeon-usb/cvmx-usb.c index 9e4bf7194ac7..3993e3c4b8cc 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.c +++ b/drivers/staging/octeon-usb/cvmx-usb.c @@ -486,13 +486,13 @@ static inline void __cvmx_usb_remove_pipe(cvmx_usb_pipe_list_t *list, cvmx_usb_p * @usb_port_number: * Which Octeon USB port to initialize. * @flags: Flags to control hardware initialization. See - * cvmx_usb_initialize_flags_t for the flag + * enum cvmx_usb_initialize_flags for the flag * definitions. Some flags are mandatory. * * Returns: 0 or a negative error code. */ int cvmx_usb_initialize(cvmx_usb_state_t *state, int usb_port_number, - cvmx_usb_initialize_flags_t flags) + enum cvmx_usb_initialize_flags flags) { cvmx_usbnx_clk_ctl_t usbn_clk_ctl; cvmx_usbnx_usbp_ctl_status_t usbn_usbp_ctl_status; diff --git a/drivers/staging/octeon-usb/cvmx-usb.h b/drivers/staging/octeon-usb/cvmx-usb.h index 7e1e2986d953..8c46ebd15bfd 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.h +++ b/drivers/staging/octeon-usb/cvmx-usb.h @@ -408,23 +408,36 @@ typedef void (*cvmx_usb_callback_func_t)(cvmx_usb_state_t *state, int bytes_transferred, void *user_data); /** - * Flags to pass the initialization function. + * enum cvmx_usb_initialize_flags - flags to pass the initialization function + * + * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI: The USB port uses a 12MHz crystal + * as clock source at USB_XO and + * USB_XI. + * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND: The USB port uses 12/24/48MHz 2.5V + * board clock source at USB_XO. + * USB_XI should be tied to GND. + * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_AUTO: Automatically determine clock type + * based on function in + * cvmx-helper-board.c. + * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_MHZ_MASK: Mask for clock speed field + * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ: Speed of reference clock or + * crystal + * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ: Speed of reference clock + * @CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ: Speed of reference clock + * @CVMX_USB_INITIALIZE_FLAGS_NO_DMA: Disable DMA and used polled IO for + * data transfer use for the USB */ -typedef enum -{ - CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI = 1<<0, /**< The USB port uses a 12MHz crystal as clock source - at USB_XO and USB_XI. */ - CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND = 1<<1, /**< The USB port uses 12/24/48MHz 2.5V board clock - source at USB_XO. USB_XI should be tied to GND.*/ - CVMX_USB_INITIALIZE_FLAGS_CLOCK_AUTO = 0, /**< Automatically determine clock type based on function - in cvmx-helper-board.c. */ - CVMX_USB_INITIALIZE_FLAGS_CLOCK_MHZ_MASK = 3<<3, /**< Mask for clock speed field */ - CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ = 1<<3, /**< Speed of reference clock or crystal */ - CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ = 2<<3, /**< Speed of reference clock */ - CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ = 3<<3, /**< Speed of reference clock */ - /* Bits 3-4 used to encode the clock frequency */ - CVMX_USB_INITIALIZE_FLAGS_NO_DMA = 1<<5, /**< Disable DMA and used polled IO for data transfer use for the USB */ -} cvmx_usb_initialize_flags_t; +enum cvmx_usb_initialize_flags { + CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_XI = 1 << 0, + CVMX_USB_INITIALIZE_FLAGS_CLOCK_XO_GND = 1 << 1, + CVMX_USB_INITIALIZE_FLAGS_CLOCK_AUTO = 0, + CVMX_USB_INITIALIZE_FLAGS_CLOCK_MHZ_MASK = 3 << 3, + CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ = 1 << 3, + CVMX_USB_INITIALIZE_FLAGS_CLOCK_24MHZ = 2 << 3, + CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ = 3 << 3, + /* Bits 3-4 used to encode the clock frequency */ + CVMX_USB_INITIALIZE_FLAGS_NO_DMA = 1 << 5, +}; /** * Flags for passing when a pipe is created. Currently no flags @@ -439,7 +452,7 @@ typedef enum extern int cvmx_usb_get_num_ports(void); extern int cvmx_usb_initialize(cvmx_usb_state_t *state, int usb_port_number, - cvmx_usb_initialize_flags_t flags); + enum cvmx_usb_initialize_flags flags); extern int cvmx_usb_shutdown(cvmx_usb_state_t *state); extern int cvmx_usb_enable(cvmx_usb_state_t *state); extern int cvmx_usb_disable(cvmx_usb_state_t *state); From 3f937c51b4115c4943d76255591806d86f04a6c9 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 30 Jul 2013 23:42:59 +0300 Subject: [PATCH 1256/3400] staging: octeon-usb: cvmx_usb_pipe_flags_t -> enum cvmx_usb_pipe_flags Replace cvmx_usb_pipe_flags_t with enum cvmx_usb_pipe_flags. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.c | 6 +++--- drivers/staging/octeon-usb/cvmx-usb.h | 25 ++++++++++++++++--------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.c b/drivers/staging/octeon-usb/cvmx-usb.c index 3993e3c4b8cc..a77d9308b987 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.c +++ b/drivers/staging/octeon-usb/cvmx-usb.c @@ -150,7 +150,7 @@ typedef struct cvmx_usb_pipe { cvmx_usb_transaction_t *tail; /**< The last pending transaction */ uint64_t interval; /**< For periodic pipes, the interval between packets in frames */ uint64_t next_tx_frame; /**< The next frame this pipe is allowed to transmit on */ - cvmx_usb_pipe_flags_t flags; /**< State flags for this pipe */ + enum cvmx_usb_pipe_flags flags; /**< State flags for this pipe */ enum cvmx_usb_speed device_speed; /**< Speed of device connected to this pipe */ enum cvmx_usb_transfer transfer_type; /**< Type of transaction supported by this pipe */ enum cvmx_usb_direction transfer_dir; /**< IN or OUT. Ignored for Control */ @@ -1053,7 +1053,7 @@ static inline int __cvmx_usb_get_pipe_handle(cvmx_usb_internal_state_t *usb, * @state: USB device state populated by * cvmx_usb_initialize(). * @flags: Optional pipe flags defined in - * cvmx_usb_pipe_flags_t. + * enum cvmx_usb_pipe_flags. * @device_addr: * USB device address to open the pipe to * (0-127). @@ -1101,7 +1101,7 @@ static inline int __cvmx_usb_get_pipe_handle(cvmx_usb_internal_state_t *usb, * Returns: A non negative value is a pipe handle. Negative * values are error codes. */ -int cvmx_usb_open_pipe(cvmx_usb_state_t *state, cvmx_usb_pipe_flags_t flags, +int cvmx_usb_open_pipe(cvmx_usb_state_t *state, enum cvmx_usb_pipe_flags flags, int device_addr, int endpoint_num, enum cvmx_usb_speed device_speed, int max_packet, enum cvmx_usb_transfer transfer_type, diff --git a/drivers/staging/octeon-usb/cvmx-usb.h b/drivers/staging/octeon-usb/cvmx-usb.h index 8c46ebd15bfd..6c404b0882d7 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.h +++ b/drivers/staging/octeon-usb/cvmx-usb.h @@ -440,15 +440,22 @@ enum cvmx_usb_initialize_flags { }; /** - * Flags for passing when a pipe is created. Currently no flags - * need to be passed. + * enum cvmx_usb_pipe_flags - flags for passing when a pipe is created. + * Currently no flags need to be passed. + * + * @__CVMX_USB_PIPE_FLAGS_OPEN: Used internally to determine if a pipe is + * open. Do not use. + * @__CVMX_USB_PIPE_FLAGS_SCHEDULED: Used internally to determine if a pipe is + * actively using hardware. Do not use. + * @__CVMX_USB_PIPE_FLAGS_NEED_PING: Used internally to determine if a high + * speed pipe is in the ping state. Do not + * use. */ -typedef enum -{ - __CVMX_USB_PIPE_FLAGS_OPEN = 1<<16, /**< Used internally to determine if a pipe is open. Do not use */ - __CVMX_USB_PIPE_FLAGS_SCHEDULED = 1<<17, /**< Used internally to determine if a pipe is actively using hardware. Do not use */ - __CVMX_USB_PIPE_FLAGS_NEED_PING = 1<<18, /**< Used internally to determine if a high speed pipe is in the ping state. Do not use */ -} cvmx_usb_pipe_flags_t; +enum cvmx_usb_pipe_flags { + __CVMX_USB_PIPE_FLAGS_OPEN = 1 << 16, + __CVMX_USB_PIPE_FLAGS_SCHEDULED = 1 << 17, + __CVMX_USB_PIPE_FLAGS_NEED_PING = 1 << 18, +}; extern int cvmx_usb_get_num_ports(void); extern int cvmx_usb_initialize(cvmx_usb_state_t *state, int usb_port_number, @@ -459,7 +466,7 @@ extern int cvmx_usb_disable(cvmx_usb_state_t *state); extern cvmx_usb_port_status_t cvmx_usb_get_status(cvmx_usb_state_t *state); extern void cvmx_usb_set_status(cvmx_usb_state_t *state, cvmx_usb_port_status_t port_status); extern int cvmx_usb_open_pipe(cvmx_usb_state_t *state, - cvmx_usb_pipe_flags_t flags, + enum cvmx_usb_pipe_flags flags, int device_addr, int endpoint_num, enum cvmx_usb_speed device_speed, int max_packet, enum cvmx_usb_transfer transfer_type, From ff9a3e3982535c73d91209b0d26fff76852b784f Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 30 Jul 2013 23:43:00 +0300 Subject: [PATCH 1257/3400] staging: octeon-usb: cvmx_usb_isochronous_flags_t -> enum cvmx_usb_isochronous_flags Replace cvmx_usb_isochronous_flags_t with enum cvmx_usb_isochronous_flags. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.c | 2 +- drivers/staging/octeon-usb/cvmx-usb.h | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.c b/drivers/staging/octeon-usb/cvmx-usb.c index a77d9308b987..2d9474aab979 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.c +++ b/drivers/staging/octeon-usb/cvmx-usb.c @@ -2291,7 +2291,7 @@ int cvmx_usb_submit_control(cvmx_usb_state_t *state, int pipe_handle, * Number of frames into the future to schedule * this transaction. * @flags: Flags to control the transfer. See - * cvmx_usb_isochronous_flags_t for the flag + * enum cvmx_usb_isochronous_flags for the flag * definitions. * @number_packets: * Number of sequential packets to transfer. diff --git a/drivers/staging/octeon-usb/cvmx-usb.h b/drivers/staging/octeon-usb/cvmx-usb.h index 6c404b0882d7..cf49b13a806b 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.h +++ b/drivers/staging/octeon-usb/cvmx-usb.h @@ -488,13 +488,19 @@ extern int cvmx_usb_submit_control(cvmx_usb_state_t *state, int pipe_handle, void *user_data); /** - * Flags to pass the cvmx_usb_submit_isochronous() function. + * enum cvmx_usb_isochronous_flags - flags to pass the + * cvmx_usb_submit_isochronous() function. + * + * @CVMX_USB_ISOCHRONOUS_FLAGS_ALLOW_SHORT: Do not return an error if a transfer + * is less than the maximum packet size + * of the device. + * @CVMX_USB_ISOCHRONOUS_FLAGS_ASAP: Schedule the transaction as soon as + * possible. */ -typedef enum -{ - CVMX_USB_ISOCHRONOUS_FLAGS_ALLOW_SHORT = 1<<0, /**< Do not return an error if a transfer is less than the maximum packet size of the device */ - CVMX_USB_ISOCHRONOUS_FLAGS_ASAP = 1<<1, /**< Schedule the transaction as soon as possible */ -} cvmx_usb_isochronous_flags_t; +enum cvmx_usb_isochronous_flags { + CVMX_USB_ISOCHRONOUS_FLAGS_ALLOW_SHORT = 1 << 0, + CVMX_USB_ISOCHRONOUS_FLAGS_ASAP = 1 << 1, +}; extern int cvmx_usb_submit_isochronous(cvmx_usb_state_t *state, int pipe_handle, int start_frame, int flags, From 4f1d6ba901151b5c56babbb544546ebb7a9e0308 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 30 Jul 2013 23:43:01 +0300 Subject: [PATCH 1258/3400] staging: octeon-usb: cvmx_usb_transaction_flags_t -> enum cvmx_usb_transaction_flags Replace cvmx_usb_transaction_flags_t with enum cvmx_usb_transaction_flags. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.c b/drivers/staging/octeon-usb/cvmx-usb.c index 2d9474aab979..b8af45da1c45 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.c +++ b/drivers/staging/octeon-usb/cvmx-usb.c @@ -84,9 +84,9 @@ #define cvmx_read_csr use_cvmx_usb_read_csr64_instead_of_cvmx_read_csr #define cvmx_write_csr use_cvmx_usb_write_csr64_instead_of_cvmx_write_csr -typedef enum { +enum cvmx_usb_transaction_flags { __CVMX_USB_TRANSACTION_FLAGS_IN_USE = 1<<16, -} cvmx_usb_transaction_flags_t; +}; enum { USB_CLOCK_TYPE_REF_12, @@ -123,7 +123,7 @@ typedef struct cvmx_usb_transaction { struct cvmx_usb_transaction *prev; /**< Transaction before this one in the pipe */ struct cvmx_usb_transaction *next; /**< Transaction after this one in the pipe */ enum cvmx_usb_transfer type; /**< Type of transaction, duplicated of the pipe */ - cvmx_usb_transaction_flags_t flags; /**< State flags for this transaction */ + enum cvmx_usb_transaction_flags flags; /**< State flags for this transaction */ uint64_t buffer; /**< User's physical buffer address to read/write */ int buffer_length; /**< Size of the user's buffer in bytes */ uint64_t control_header; /**< For control transactions, physical address of the 8 byte standard header */ From 03f9adf44cef7423fa9493b3abc2f2d764157481 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 30 Jul 2013 23:43:02 +0300 Subject: [PATCH 1259/3400] staging: octeon-usb: cvmx_usb_stage_t -> enum cvmx_usb_stage Replace cvmx_usb_stage_t with enum cvmx_usb_stage. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.c b/drivers/staging/octeon-usb/cvmx-usb.c index b8af45da1c45..f5918979abd1 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.c +++ b/drivers/staging/octeon-usb/cvmx-usb.c @@ -103,7 +103,7 @@ enum { * the NAK handler can backup to the previous low level * transaction with a simple clearing of bit 0. */ -typedef enum { +enum cvmx_usb_stage { CVMX_USB_STAGE_NON_CONTROL, CVMX_USB_STAGE_NON_CONTROL_SPLIT_COMPLETE, CVMX_USB_STAGE_SETUP, @@ -112,7 +112,7 @@ typedef enum { CVMX_USB_STAGE_DATA_SPLIT_COMPLETE, CVMX_USB_STAGE_STATUS, CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE, -} cvmx_usb_stage_t; +}; /** * This structure describes each pending USB transaction @@ -134,7 +134,7 @@ typedef struct cvmx_usb_transaction { int pktcnt; int retries; int actual_bytes; /**< Actual bytes transfer for this transaction */ - cvmx_usb_stage_t stage; /**< For control transactions, the current stage */ + enum cvmx_usb_stage stage; /**< For control transactions, the current stage */ cvmx_usb_callback_func_t callback; /**< User's callback function when complete */ void *callback_data; /**< User's data */ } cvmx_usb_transaction_t; From 51a19621ccb10191915220de8d2ec69bcb9862ac Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 30 Jul 2013 23:43:03 +0300 Subject: [PATCH 1260/3400] staging: octeon-usb: cvmx_usb_port_status_t -> struct cvmx_usb_port_status Replace cvmx_usb_port_status_t with struct cvmx_usb_port_status. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.c | 10 +++---- drivers/staging/octeon-usb/cvmx-usb.h | 37 ++++++++++++++++--------- drivers/staging/octeon-usb/octeon-hcd.c | 4 +-- 3 files changed, 31 insertions(+), 20 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.c b/drivers/staging/octeon-usb/cvmx-usb.c index f5918979abd1..c92b15f30fea 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.c +++ b/drivers/staging/octeon-usb/cvmx-usb.c @@ -196,7 +196,7 @@ typedef struct { cvmx_usb_callback_func_t callback[__CVMX_USB_CALLBACK_END]; /**< User global callbacks */ void *callback_data[__CVMX_USB_CALLBACK_END]; /**< User data for each callback */ int indent; /**< Used by debug output to indent functions */ - cvmx_usb_port_status_t port_status; /**< Last port status used for change notification */ + struct cvmx_usb_port_status port_status; /**< Last port status used for change notification */ cvmx_usb_pipe_list_t free_pipes; /**< List of all pipes that are currently closed */ cvmx_usb_pipe_list_t idle_pipes; /**< List of open pipes that have no transactions */ cvmx_usb_pipe_list_t active_pipes[4]; /**< Active pipes indexed by transfer type */ @@ -971,10 +971,10 @@ int cvmx_usb_disable(cvmx_usb_state_t *state) * * Returns: Port status information */ -cvmx_usb_port_status_t cvmx_usb_get_status(cvmx_usb_state_t *state) +struct cvmx_usb_port_status cvmx_usb_get_status(cvmx_usb_state_t *state) { cvmx_usbcx_hprt_t usbc_hprt; - cvmx_usb_port_status_t result; + struct cvmx_usb_port_status result; cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; memset(&result, 0, sizeof(result)); @@ -1003,7 +1003,7 @@ cvmx_usb_port_status_t cvmx_usb_get_status(cvmx_usb_state_t *state) * @port_status: * Port status to set, most like returned by cvmx_usb_get_status() */ -void cvmx_usb_set_status(cvmx_usb_state_t *state, cvmx_usb_port_status_t port_status) +void cvmx_usb_set_status(cvmx_usb_state_t *state, struct cvmx_usb_port_status port_status) { cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; usb->port_status = port_status; @@ -2964,7 +2964,7 @@ static int __cvmx_usb_poll_channel(cvmx_usb_internal_state_t *usb, int channel) pipe->next_tx_frame = usb->frame_number + pipe->interval - (usb->frame_number - pipe->next_tx_frame) % pipe->interval; } else { - cvmx_usb_port_status_t port; + struct cvmx_usb_port_status port; port = cvmx_usb_get_status((cvmx_usb_state_t *)usb); if (port.port_enabled) { /* We'll retry the exact same transaction again */ diff --git a/drivers/staging/octeon-usb/cvmx-usb.h b/drivers/staging/octeon-usb/cvmx-usb.h index cf49b13a806b..9c7ff4a6c52e 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.h +++ b/drivers/staging/octeon-usb/cvmx-usb.h @@ -310,18 +310,29 @@ enum cvmx_usb_complete { }; /** - * Structure returned containing the USB port status information. + * struct cvmx_usb_port_status - the USB port status information + * + * @port_enabled: 1 = Usb port is enabled, 0 = disabled + * @port_over_current: 1 = Over current detected, 0 = Over current not + * detected. Octeon doesn't support over current detection. + * @port_powered: 1 = Port power is being supplied to the device, 0 = + * power is off. Octeon doesn't support turning port power + * off. + * @port_speed: Current port speed. + * @connected: 1 = A device is connected to the port, 0 = No device is + * connected. + * @connect_change: 1 = Device connected state changed since the last set + * status call. */ -typedef struct -{ - uint32_t reserved : 25; - uint32_t port_enabled : 1; /**< 1 = Usb port is enabled, 0 = disabled */ - uint32_t port_over_current : 1; /**< 1 = Over current detected, 0 = Over current not detected. Octeon doesn't support over current detection */ - uint32_t port_powered : 1; /**< 1 = Port power is being supplied to the device, 0 = power is off. Octeon doesn't support turning port power off */ - enum cvmx_usb_speed port_speed : 2; /**< Current port speed */ - uint32_t connected : 1; /**< 1 = A device is connected to the port, 0 = No device is connected */ - uint32_t connect_change : 1; /**< 1 = Device connected state changed since the last set status call */ -} cvmx_usb_port_status_t; +struct cvmx_usb_port_status { + uint32_t reserved : 25; + uint32_t port_enabled : 1; + uint32_t port_over_current : 1; + uint32_t port_powered : 1; + enum cvmx_usb_speed port_speed : 2; + uint32_t connected : 1; + uint32_t connect_change : 1; +}; /** * This is the structure of a Control packet header @@ -463,8 +474,8 @@ extern int cvmx_usb_initialize(cvmx_usb_state_t *state, int usb_port_number, extern int cvmx_usb_shutdown(cvmx_usb_state_t *state); extern int cvmx_usb_enable(cvmx_usb_state_t *state); extern int cvmx_usb_disable(cvmx_usb_state_t *state); -extern cvmx_usb_port_status_t cvmx_usb_get_status(cvmx_usb_state_t *state); -extern void cvmx_usb_set_status(cvmx_usb_state_t *state, cvmx_usb_port_status_t port_status); +extern struct cvmx_usb_port_status cvmx_usb_get_status(cvmx_usb_state_t *state); +extern void cvmx_usb_set_status(cvmx_usb_state_t *state, struct cvmx_usb_port_status port_status); extern int cvmx_usb_open_pipe(cvmx_usb_state_t *state, enum cvmx_usb_pipe_flags flags, int device_addr, int endpoint_num, diff --git a/drivers/staging/octeon-usb/octeon-hcd.c b/drivers/staging/octeon-usb/octeon-hcd.c index 5137da74c2b2..8a41d092b08b 100644 --- a/drivers/staging/octeon-usb/octeon-hcd.c +++ b/drivers/staging/octeon-usb/octeon-hcd.c @@ -440,7 +440,7 @@ static void octeon_usb_endpoint_disable(struct usb_hcd *hcd, struct usb_host_end static int octeon_usb_hub_status_data(struct usb_hcd *hcd, char *buf) { struct octeon_hcd *priv = hcd_to_octeon(hcd); - cvmx_usb_port_status_t port_status; + struct cvmx_usb_port_status port_status; unsigned long flags; spin_lock_irqsave(&priv->lock, flags); @@ -456,7 +456,7 @@ static int octeon_usb_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, { struct octeon_hcd *priv = hcd_to_octeon(hcd); struct device *dev = hcd->self.controller; - cvmx_usb_port_status_t usb_port_status; + struct cvmx_usb_port_status usb_port_status; int port_status; struct usb_hub_descriptor *desc; unsigned long flags; From 6e0e1b006993e0a4e2d39421d7adbe1ad92b7cbf Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 30 Jul 2013 23:43:04 +0300 Subject: [PATCH 1261/3400] staging: octeon-usb: cvmx_usb_iso_packet_t -> struct cvmx_usb_iso_packet Replace cvmx_usb_iso_packet_t with struct cvmx_usb_iso_packet. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.c | 8 ++++---- drivers/staging/octeon-usb/cvmx-usb.h | 20 ++++++++++++-------- drivers/staging/octeon-usb/octeon-hcd.c | 9 ++++++--- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.c b/drivers/staging/octeon-usb/cvmx-usb.c index c92b15f30fea..6c79cc15b516 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.c +++ b/drivers/staging/octeon-usb/cvmx-usb.c @@ -129,7 +129,7 @@ typedef struct cvmx_usb_transaction { uint64_t control_header; /**< For control transactions, physical address of the 8 byte standard header */ int iso_start_frame; /**< For ISO transactions, the starting frame number */ int iso_number_packets; /**< For ISO transactions, the number of packets in the request */ - cvmx_usb_iso_packet_t *iso_packets; /**< For ISO transactions, the sub packets in the request */ + struct cvmx_usb_iso_packet *iso_packets;/**< For ISO transactions, the sub packets in the request */ int xfersize; int pktcnt; int retries; @@ -2032,7 +2032,7 @@ static int __cvmx_usb_submit_transaction(cvmx_usb_internal_state_t *usb, uint64_t control_header, int iso_start_frame, int iso_number_packets, - cvmx_usb_iso_packet_t *iso_packets, + struct cvmx_usb_iso_packet *iso_packets, cvmx_usb_callback_func_t callback, void *user_data) { @@ -2298,7 +2298,7 @@ int cvmx_usb_submit_control(cvmx_usb_state_t *state, int pipe_handle, * "packets" is a pointer to an array of this * many packet structures. * @packets: Description of each transfer packet as - * defined by cvmx_usb_iso_packet_t. The array + * defined by struct cvmx_usb_iso_packet. The array * pointed to here must stay valid until the * complete callback is called. * @buffer: Physical address of the data buffer in @@ -2327,7 +2327,7 @@ int cvmx_usb_submit_control(cvmx_usb_state_t *state, int pipe_handle, int cvmx_usb_submit_isochronous(cvmx_usb_state_t *state, int pipe_handle, int start_frame, int flags, int number_packets, - cvmx_usb_iso_packet_t packets[], + struct cvmx_usb_iso_packet packets[], uint64_t buffer, int buffer_length, cvmx_usb_callback_func_t callback, void *user_data) diff --git a/drivers/staging/octeon-usb/cvmx-usb.h b/drivers/staging/octeon-usb/cvmx-usb.h index 9c7ff4a6c52e..b0d0f6aab5d1 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.h +++ b/drivers/staging/octeon-usb/cvmx-usb.h @@ -351,14 +351,18 @@ typedef union } cvmx_usb_control_header_t; /** - * Descriptor for Isochronous packets + * struct cvmx_usb_iso_packet - descriptor for Isochronous packets + * + * @offset: This is the offset in bytes into the main buffer where this data + * is stored. + * @length: This is the length in bytes of the data. + * @status: This is the status of this individual packet transfer. */ -typedef struct -{ - int offset; /**< This is the offset in bytes into the main buffer where this data is stored */ - int length; /**< This is the length in bytes of the data */ - enum cvmx_usb_complete status; /**< This is the status of this individual packet transfer */ -} cvmx_usb_iso_packet_t; +struct cvmx_usb_iso_packet { + int offset; + int length; + enum cvmx_usb_complete status; +}; /** * enum cvmx_usb_callback - possible callback reasons for the USB API @@ -516,7 +520,7 @@ enum cvmx_usb_isochronous_flags { extern int cvmx_usb_submit_isochronous(cvmx_usb_state_t *state, int pipe_handle, int start_frame, int flags, int number_packets, - cvmx_usb_iso_packet_t packets[], + struct cvmx_usb_iso_packet packets[], uint64_t buffer, int buffer_length, cvmx_usb_callback_func_t callback, void *user_data); diff --git a/drivers/staging/octeon-usb/octeon-hcd.c b/drivers/staging/octeon-usb/octeon-hcd.c index 8a41d092b08b..319f2e15662a 100644 --- a/drivers/staging/octeon-usb/octeon-hcd.c +++ b/drivers/staging/octeon-usb/octeon-hcd.c @@ -141,7 +141,8 @@ static void octeon_usb_urb_complete_callback(cvmx_usb_state_t *usb, * The pointer to the private list is stored in the setup_packet * field. */ - cvmx_usb_iso_packet_t *iso_packet = (cvmx_usb_iso_packet_t *) urb->setup_packet; + struct cvmx_usb_iso_packet *iso_packet = + (struct cvmx_usb_iso_packet *) urb->setup_packet; /* Recalculate the transfer size by adding up each packet */ urb->actual_length = 0; for (i = 0; i < urb->number_of_packets; i++) { @@ -208,7 +209,7 @@ static int octeon_usb_urb_enqueue(struct usb_hcd *hcd, int submit_handle = -1; int pipe_handle; unsigned long flags; - cvmx_usb_iso_packet_t *iso_packet; + struct cvmx_usb_iso_packet *iso_packet; struct usb_host_endpoint *ep = urb->ep; urb->status = 0; @@ -305,7 +306,9 @@ static int octeon_usb_urb_enqueue(struct usb_hcd *hcd, * Allocate a structure to use for our private list of * isochronous packets. */ - iso_packet = kmalloc(urb->number_of_packets * sizeof(cvmx_usb_iso_packet_t), GFP_ATOMIC); + iso_packet = kmalloc(urb->number_of_packets * + sizeof(struct cvmx_usb_iso_packet), + GFP_ATOMIC); if (iso_packet) { int i; /* Fill the list with the data from the URB */ From a24ed35a19bd97e2803ad4fcc39732734d62fd93 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 30 Jul 2013 23:43:05 +0300 Subject: [PATCH 1262/3400] staging: octeon-usb: cvmx_usb_state_t -> struct cvmx_usb_state Replace cvmx_usb_state_t with struct cvmx_usb_state. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.c | 42 ++++++++++---------- drivers/staging/octeon-usb/cvmx-usb.h | 53 ++++++++++++------------- drivers/staging/octeon-usb/octeon-hcd.c | 8 ++-- 3 files changed, 51 insertions(+), 52 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.c b/drivers/staging/octeon-usb/cvmx-usb.c index 6c79cc15b516..c7f7566048cf 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.c +++ b/drivers/staging/octeon-usb/cvmx-usb.c @@ -358,7 +358,7 @@ static inline int __cvmx_usb_get_data_pid(cvmx_usb_pipe_t *pipe) * by this API, a zero will be returned. Most Octeon chips * support one usb port, but some support two ports. * cvmx_usb_initialize() must be called on independent - * cvmx_usb_state_t structures. + * struct cvmx_usb_state. * * Returns: Number of port, zero if usb isn't supported */ @@ -479,7 +479,7 @@ static inline void __cvmx_usb_remove_pipe(cvmx_usb_pipe_list_t *list, cvmx_usb_p * other access to the Octeon USB port is made. The port starts * off in the disabled state. * - * @state: Pointer to an empty cvmx_usb_state_t structure + * @state: Pointer to an empty struct cvmx_usb_state * that will be populated by the initialize call. * This structure is then passed to all other USB * functions. @@ -491,7 +491,7 @@ static inline void __cvmx_usb_remove_pipe(cvmx_usb_pipe_list_t *list, cvmx_usb_p * * Returns: 0 or a negative error code. */ -int cvmx_usb_initialize(cvmx_usb_state_t *state, int usb_port_number, +int cvmx_usb_initialize(struct cvmx_usb_state *state, int usb_port_number, enum cvmx_usb_initialize_flags flags) { cvmx_usbnx_clk_ctl_t usbn_clk_ctl; @@ -818,7 +818,7 @@ int cvmx_usb_initialize(cvmx_usb_state_t *state, int usb_port_number, * * Returns: 0 or a negative error code. */ -int cvmx_usb_shutdown(cvmx_usb_state_t *state) +int cvmx_usb_shutdown(struct cvmx_usb_state *state) { cvmx_usbnx_clk_ctl_t usbn_clk_ctl; cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; @@ -853,7 +853,7 @@ int cvmx_usb_shutdown(cvmx_usb_state_t *state) * * Returns: 0 or a negative error code. */ -int cvmx_usb_enable(cvmx_usb_state_t *state) +int cvmx_usb_enable(struct cvmx_usb_state *state) { cvmx_usbcx_ghwcfg3_t usbcx_ghwcfg3; cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; @@ -947,7 +947,7 @@ int cvmx_usb_enable(cvmx_usb_state_t *state) * * Returns: 0 or a negative error code. */ -int cvmx_usb_disable(cvmx_usb_state_t *state) +int cvmx_usb_disable(struct cvmx_usb_state *state) { cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; @@ -971,7 +971,7 @@ int cvmx_usb_disable(cvmx_usb_state_t *state) * * Returns: Port status information */ -struct cvmx_usb_port_status cvmx_usb_get_status(cvmx_usb_state_t *state) +struct cvmx_usb_port_status cvmx_usb_get_status(struct cvmx_usb_state *state) { cvmx_usbcx_hprt_t usbc_hprt; struct cvmx_usb_port_status result; @@ -1003,7 +1003,7 @@ struct cvmx_usb_port_status cvmx_usb_get_status(cvmx_usb_state_t *state) * @port_status: * Port status to set, most like returned by cvmx_usb_get_status() */ -void cvmx_usb_set_status(cvmx_usb_state_t *state, struct cvmx_usb_port_status port_status) +void cvmx_usb_set_status(struct cvmx_usb_state *state, struct cvmx_usb_port_status port_status) { cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; usb->port_status = port_status; @@ -1101,7 +1101,7 @@ static inline int __cvmx_usb_get_pipe_handle(cvmx_usb_internal_state_t *usb, * Returns: A non negative value is a pipe handle. Negative * values are error codes. */ -int cvmx_usb_open_pipe(cvmx_usb_state_t *state, enum cvmx_usb_pipe_flags flags, +int cvmx_usb_open_pipe(struct cvmx_usb_state *state, enum cvmx_usb_pipe_flags flags, int device_addr, int endpoint_num, enum cvmx_usb_speed device_speed, int max_packet, enum cvmx_usb_transfer transfer_type, @@ -1926,7 +1926,7 @@ static void __cvmx_usb_perform_callback(cvmx_usb_internal_state_t *usb, if (!callback) return; - callback((cvmx_usb_state_t *)usb, reason, complete_code, pipe_handle, submit_handle, + callback((struct cvmx_usb_state *)usb, reason, complete_code, pipe_handle, submit_handle, bytes_transferred, user_data); } @@ -2122,7 +2122,7 @@ static int __cvmx_usb_submit_transaction(cvmx_usb_internal_state_t *usb, * Returns: A submitted transaction handle or negative on * failure. Negative values are error codes. */ -int cvmx_usb_submit_bulk(cvmx_usb_state_t *state, int pipe_handle, +int cvmx_usb_submit_bulk(struct cvmx_usb_state *state, int pipe_handle, uint64_t buffer, int buffer_length, cvmx_usb_callback_func_t callback, void *user_data) @@ -2181,7 +2181,7 @@ int cvmx_usb_submit_bulk(cvmx_usb_state_t *state, int pipe_handle, * Returns: A submitted transaction handle or negative on * failure. Negative values are error codes. */ -int cvmx_usb_submit_interrupt(cvmx_usb_state_t *state, int pipe_handle, +int cvmx_usb_submit_interrupt(struct cvmx_usb_state *state, int pipe_handle, uint64_t buffer, int buffer_length, cvmx_usb_callback_func_t callback, void *user_data) @@ -2244,7 +2244,7 @@ int cvmx_usb_submit_interrupt(cvmx_usb_state_t *state, int pipe_handle, * Returns: A submitted transaction handle or negative on * failure. Negative values are error codes. */ -int cvmx_usb_submit_control(cvmx_usb_state_t *state, int pipe_handle, +int cvmx_usb_submit_control(struct cvmx_usb_state *state, int pipe_handle, uint64_t control_header, uint64_t buffer, int buffer_length, cvmx_usb_callback_func_t callback, @@ -2324,7 +2324,7 @@ int cvmx_usb_submit_control(cvmx_usb_state_t *state, int pipe_handle, * Returns: A submitted transaction handle or negative on * failure. Negative values are error codes. */ -int cvmx_usb_submit_isochronous(cvmx_usb_state_t *state, int pipe_handle, +int cvmx_usb_submit_isochronous(struct cvmx_usb_state *state, int pipe_handle, int start_frame, int flags, int number_packets, struct cvmx_usb_iso_packet packets[], @@ -2380,7 +2380,7 @@ int cvmx_usb_submit_isochronous(cvmx_usb_state_t *state, int pipe_handle, * * Returns: 0 or a negative error code. */ -int cvmx_usb_cancel(cvmx_usb_state_t *state, int pipe_handle, int submit_handle) +int cvmx_usb_cancel(struct cvmx_usb_state *state, int pipe_handle, int submit_handle) { cvmx_usb_transaction_t *transaction; cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; @@ -2437,7 +2437,7 @@ int cvmx_usb_cancel(cvmx_usb_state_t *state, int pipe_handle, int submit_handle) * * Returns: 0 or a negative error code. */ -int cvmx_usb_cancel_all(cvmx_usb_state_t *state, int pipe_handle) +int cvmx_usb_cancel_all(struct cvmx_usb_state *state, int pipe_handle) { cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; cvmx_usb_pipe_t *pipe = usb->pipe + pipe_handle; @@ -2471,7 +2471,7 @@ int cvmx_usb_cancel_all(cvmx_usb_state_t *state, int pipe_handle) * Returns: 0 or a negative error code. EBUSY is returned if the pipe has * outstanding transfers. */ -int cvmx_usb_close_pipe(cvmx_usb_state_t *state, int pipe_handle) +int cvmx_usb_close_pipe(struct cvmx_usb_state *state, int pipe_handle) { cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; cvmx_usb_pipe_t *pipe = usb->pipe + pipe_handle; @@ -2506,7 +2506,7 @@ int cvmx_usb_close_pipe(cvmx_usb_state_t *state, int pipe_handle) * * Returns: 0 or a negative error code. */ -int cvmx_usb_register_callback(cvmx_usb_state_t *state, +int cvmx_usb_register_callback(struct cvmx_usb_state *state, enum cvmx_usb_callback reason, cvmx_usb_callback_func_t callback, void *user_data) @@ -2534,7 +2534,7 @@ int cvmx_usb_register_callback(cvmx_usb_state_t *state, * * Returns: USB frame number */ -int cvmx_usb_get_frame_number(cvmx_usb_state_t *state) +int cvmx_usb_get_frame_number(struct cvmx_usb_state *state) { int frame_number; cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; @@ -2965,7 +2965,7 @@ static int __cvmx_usb_poll_channel(cvmx_usb_internal_state_t *usb, int channel) (usb->frame_number - pipe->next_tx_frame) % pipe->interval; } else { struct cvmx_usb_port_status port; - port = cvmx_usb_get_status((cvmx_usb_state_t *)usb); + port = cvmx_usb_get_status((struct cvmx_usb_state *)usb); if (port.port_enabled) { /* We'll retry the exact same transaction again */ transaction->retries++; @@ -2992,7 +2992,7 @@ static int __cvmx_usb_poll_channel(cvmx_usb_internal_state_t *usb, int channel) * * Returns: 0 or a negative error code. */ -int cvmx_usb_poll(cvmx_usb_state_t *state) +int cvmx_usb_poll(struct cvmx_usb_state *state) { cvmx_usbcx_hfnum_t usbc_hfnum; cvmx_usbcx_gintsts_t usbc_gintsts; diff --git a/drivers/staging/octeon-usb/cvmx-usb.h b/drivers/staging/octeon-usb/cvmx-usb.h index b0d0f6aab5d1..bd6a2fb07489 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.h +++ b/drivers/staging/octeon-usb/cvmx-usb.h @@ -75,7 +75,7 @@ * In the probe phase you should: * - Use cvmx_usb_get_num_ports() to determine the number of * USB port to be supported. - * - Allocate space for a cvmx_usb_state_t structure for each + * - Allocate space for a struct cvmx_usb_state for each * port. * - Tell the operating system about each port * @@ -114,14 +114,14 @@ * * The port callback prototype needs to look as follows: * - * void port_callback(cvmx_usb_state_t *usb, + * void port_callback(struct cvmx_usb_state *usb, * enum cvmx_usb_callback reason, * enum cvmx_usb_complete status, * int pipe_handle, * int submit_handle, * int bytes_transferred, * void *user_data); - * - "usb" is the cvmx_usb_state_t for the port. + * - "usb" is the struct cvmx_usb_state for the port. * - "reason" will always be CVMX_USB_CALLBACK_PORT_CHANGED. * - "status" will always be CVMX_USB_COMPLETE_SUCCESS. * - "pipe_handle" will always be -1. @@ -146,14 +146,14 @@ * * The completion callback prototype needs to look as follows: * - * void complete_callback(cvmx_usb_state_t *usb, + * void complete_callback(struct cvmx_usb_state *usb, * enum cvmx_usb_callback reason, * enum cvmx_usb_complete status, * int pipe_handle, * int submit_handle, * int bytes_transferred, * void *user_data); - * - "usb" is the cvmx_usb_state_t for the port. + * - "usb" is the struct cvmx_usb_state for the port. * - "reason" will always be CVMX_USB_CALLBACK_TRANSFER_COMPLETE. * - "status" will be one of the cvmx_usb_complete enumerations. * - "pipe_handle" is the handle to the pipe the transaction @@ -393,10 +393,9 @@ enum cvmx_usb_callback { * may change in future SDKs. No data in it should be referenced * by user's of this API. */ -typedef struct -{ - char data[65536]; -} cvmx_usb_state_t; +struct cvmx_usb_state { + char data[65536]; +}; /** * USB callback functions are always of the following type. @@ -416,7 +415,7 @@ typedef struct * - user_data = The user pointer supplied to the * function cvmx_usb_submit() or * cvmx_usb_register_callback() */ -typedef void (*cvmx_usb_callback_func_t)(cvmx_usb_state_t *state, +typedef void (*cvmx_usb_callback_func_t)(struct cvmx_usb_state *state, enum cvmx_usb_callback reason, enum cvmx_usb_complete status, int pipe_handle, int submit_handle, @@ -473,14 +472,14 @@ enum cvmx_usb_pipe_flags { }; extern int cvmx_usb_get_num_ports(void); -extern int cvmx_usb_initialize(cvmx_usb_state_t *state, int usb_port_number, +extern int cvmx_usb_initialize(struct cvmx_usb_state *state, int usb_port_number, enum cvmx_usb_initialize_flags flags); -extern int cvmx_usb_shutdown(cvmx_usb_state_t *state); -extern int cvmx_usb_enable(cvmx_usb_state_t *state); -extern int cvmx_usb_disable(cvmx_usb_state_t *state); -extern struct cvmx_usb_port_status cvmx_usb_get_status(cvmx_usb_state_t *state); -extern void cvmx_usb_set_status(cvmx_usb_state_t *state, struct cvmx_usb_port_status port_status); -extern int cvmx_usb_open_pipe(cvmx_usb_state_t *state, +extern int cvmx_usb_shutdown(struct cvmx_usb_state *state); +extern int cvmx_usb_enable(struct cvmx_usb_state *state); +extern int cvmx_usb_disable(struct cvmx_usb_state *state); +extern struct cvmx_usb_port_status cvmx_usb_get_status(struct cvmx_usb_state *state); +extern void cvmx_usb_set_status(struct cvmx_usb_state *state, struct cvmx_usb_port_status port_status); +extern int cvmx_usb_open_pipe(struct cvmx_usb_state *state, enum cvmx_usb_pipe_flags flags, int device_addr, int endpoint_num, enum cvmx_usb_speed device_speed, int max_packet, @@ -488,15 +487,15 @@ extern int cvmx_usb_open_pipe(cvmx_usb_state_t *state, enum cvmx_usb_direction transfer_dir, int interval, int multi_count, int hub_device_addr, int hub_port); -extern int cvmx_usb_submit_bulk(cvmx_usb_state_t *state, int pipe_handle, +extern int cvmx_usb_submit_bulk(struct cvmx_usb_state *state, int pipe_handle, uint64_t buffer, int buffer_length, cvmx_usb_callback_func_t callback, void *user_data); -extern int cvmx_usb_submit_interrupt(cvmx_usb_state_t *state, int pipe_handle, +extern int cvmx_usb_submit_interrupt(struct cvmx_usb_state *state, int pipe_handle, uint64_t buffer, int buffer_length, cvmx_usb_callback_func_t callback, void *user_data); -extern int cvmx_usb_submit_control(cvmx_usb_state_t *state, int pipe_handle, +extern int cvmx_usb_submit_control(struct cvmx_usb_state *state, int pipe_handle, uint64_t control_header, uint64_t buffer, int buffer_length, cvmx_usb_callback_func_t callback, @@ -517,22 +516,22 @@ enum cvmx_usb_isochronous_flags { CVMX_USB_ISOCHRONOUS_FLAGS_ASAP = 1 << 1, }; -extern int cvmx_usb_submit_isochronous(cvmx_usb_state_t *state, int pipe_handle, +extern int cvmx_usb_submit_isochronous(struct cvmx_usb_state *state, int pipe_handle, int start_frame, int flags, int number_packets, struct cvmx_usb_iso_packet packets[], uint64_t buffer, int buffer_length, cvmx_usb_callback_func_t callback, void *user_data); -extern int cvmx_usb_cancel(cvmx_usb_state_t *state, int pipe_handle, +extern int cvmx_usb_cancel(struct cvmx_usb_state *state, int pipe_handle, int submit_handle); -extern int cvmx_usb_cancel_all(cvmx_usb_state_t *state, int pipe_handle); -extern int cvmx_usb_close_pipe(cvmx_usb_state_t *state, int pipe_handle); -extern int cvmx_usb_register_callback(cvmx_usb_state_t *state, +extern int cvmx_usb_cancel_all(struct cvmx_usb_state *state, int pipe_handle); +extern int cvmx_usb_close_pipe(struct cvmx_usb_state *state, int pipe_handle); +extern int cvmx_usb_register_callback(struct cvmx_usb_state *state, enum cvmx_usb_callback reason, cvmx_usb_callback_func_t callback, void *user_data); -extern int cvmx_usb_get_frame_number(cvmx_usb_state_t *state); -extern int cvmx_usb_poll(cvmx_usb_state_t *state); +extern int cvmx_usb_get_frame_number(struct cvmx_usb_state *state); +extern int cvmx_usb_poll(struct cvmx_usb_state *state); #endif /* __CVMX_USB_H__ */ diff --git a/drivers/staging/octeon-usb/octeon-hcd.c b/drivers/staging/octeon-usb/octeon-hcd.c index 319f2e15662a..5dbbd14ec615 100644 --- a/drivers/staging/octeon-usb/octeon-hcd.c +++ b/drivers/staging/octeon-usb/octeon-hcd.c @@ -26,7 +26,7 @@ struct octeon_hcd { spinlock_t lock; - cvmx_usb_state_t usb; + struct cvmx_usb_state usb; struct tasklet_struct dequeue_tasklet; struct list_head dequeue_list; }; @@ -42,7 +42,7 @@ static inline struct usb_hcd *octeon_to_hcd(struct octeon_hcd *p) return container_of((void *)p, struct usb_hcd, hcd_priv); } -static inline struct octeon_hcd *cvmx_usb_to_octeon(cvmx_usb_state_t *p) +static inline struct octeon_hcd *cvmx_usb_to_octeon(struct cvmx_usb_state *p) { return container_of(p, struct octeon_hcd, usb); } @@ -58,7 +58,7 @@ static irqreturn_t octeon_usb_irq(struct usb_hcd *hcd) return IRQ_HANDLED; } -static void octeon_usb_port_callback(cvmx_usb_state_t *usb, +static void octeon_usb_port_callback(struct cvmx_usb_state *usb, enum cvmx_usb_callback reason, enum cvmx_usb_complete status, int pipe_handle, @@ -105,7 +105,7 @@ static int octeon_usb_get_frame_number(struct usb_hcd *hcd) return cvmx_usb_get_frame_number(&priv->usb); } -static void octeon_usb_urb_complete_callback(cvmx_usb_state_t *usb, +static void octeon_usb_urb_complete_callback(struct cvmx_usb_state *usb, enum cvmx_usb_callback reason, enum cvmx_usb_complete status, int pipe_handle, From 48f61f832d6b369bf2d6d790ad7073cc19507045 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 30 Jul 2013 23:43:06 +0300 Subject: [PATCH 1263/3400] staging: octeon-usb: cvmx_usb_transaction_t -> struct cvmx_usb_transaction Replace cvmx_usb_transaction_t with struct cvmx_usb_transaction. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.c | 89 ++++++++++++++++----------- 1 file changed, 53 insertions(+), 36 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.c b/drivers/staging/octeon-usb/cvmx-usb.c index c7f7566048cf..beb3963dd5e6 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.c +++ b/drivers/staging/octeon-usb/cvmx-usb.c @@ -115,29 +115,46 @@ enum cvmx_usb_stage { }; /** - * This structure describes each pending USB transaction - * regardless of type. These are linked together to form a list - * of pending requests for a pipe. + * struct cvmx_usb_transaction - describes each pending USB transaction + * regardless of type. These are linked together + * to form a list of pending requests for a pipe. + * + * @prev: Transaction before this one in the pipe. + * @next: Transaction after this one in the pipe. + * @type: Type of transaction, duplicated of the pipe. + * @flags: State flags for this transaction. + * @buffer: User's physical buffer address to read/write. + * @buffer_length: Size of the user's buffer in bytes. + * @control_header: For control transactions, physical address of the 8 + * byte standard header. + * @iso_start_frame: For ISO transactions, the starting frame number. + * @iso_number_packets: For ISO transactions, the number of packets in the + * request. + * @iso_packets: For ISO transactions, the sub packets in the request. + * @actual_bytes: Actual bytes transfer for this transaction. + * @stage: For control transactions, the current stage. + * @callback: User's callback function when complete. + * @callback_data: User's data. */ -typedef struct cvmx_usb_transaction { - struct cvmx_usb_transaction *prev; /**< Transaction before this one in the pipe */ - struct cvmx_usb_transaction *next; /**< Transaction after this one in the pipe */ - enum cvmx_usb_transfer type; /**< Type of transaction, duplicated of the pipe */ - enum cvmx_usb_transaction_flags flags; /**< State flags for this transaction */ - uint64_t buffer; /**< User's physical buffer address to read/write */ - int buffer_length; /**< Size of the user's buffer in bytes */ - uint64_t control_header; /**< For control transactions, physical address of the 8 byte standard header */ - int iso_start_frame; /**< For ISO transactions, the starting frame number */ - int iso_number_packets; /**< For ISO transactions, the number of packets in the request */ - struct cvmx_usb_iso_packet *iso_packets;/**< For ISO transactions, the sub packets in the request */ +struct cvmx_usb_transaction { + struct cvmx_usb_transaction *prev; + struct cvmx_usb_transaction *next; + enum cvmx_usb_transfer type; + enum cvmx_usb_transaction_flags flags; + uint64_t buffer; + int buffer_length; + uint64_t control_header; + int iso_start_frame; + int iso_number_packets; + struct cvmx_usb_iso_packet *iso_packets; int xfersize; int pktcnt; int retries; - int actual_bytes; /**< Actual bytes transfer for this transaction */ - enum cvmx_usb_stage stage; /**< For control transactions, the current stage */ - cvmx_usb_callback_func_t callback; /**< User's callback function when complete */ - void *callback_data; /**< User's data */ -} cvmx_usb_transaction_t; + int actual_bytes; + enum cvmx_usb_stage stage; + cvmx_usb_callback_func_t callback; + void *callback_data; +}; /** * A pipe represents a virtual connection between Octeon and some @@ -146,8 +163,8 @@ typedef struct cvmx_usb_transaction { typedef struct cvmx_usb_pipe { struct cvmx_usb_pipe *prev; /**< Pipe before this one in the list */ struct cvmx_usb_pipe *next; /**< Pipe after this one in the list */ - cvmx_usb_transaction_t *head; /**< The first pending transaction */ - cvmx_usb_transaction_t *tail; /**< The last pending transaction */ + struct cvmx_usb_transaction *head; /**< The first pending transaction */ + struct cvmx_usb_transaction *tail; /**< The last pending transaction */ uint64_t interval; /**< For periodic pipes, the interval between packets in frames */ uint64_t next_tx_frame; /**< The next frame this pipe is allowed to transmit on */ enum cvmx_usb_pipe_flags flags; /**< State flags for this pipe */ @@ -189,10 +206,10 @@ typedef struct { int idle_hardware_channels; /**< Bit set for every idle hardware channel */ cvmx_usbcx_hprt_t usbcx_hprt; /**< Stored port status so we don't need to read a CSR to determine splits */ cvmx_usb_pipe_t *pipe_for_channel[MAX_CHANNELS]; /**< Map channels to pipes */ - cvmx_usb_transaction_t *free_transaction_head; /**< List of free transactions head */ - cvmx_usb_transaction_t *free_transaction_tail; /**< List of free transactions tail */ + struct cvmx_usb_transaction *free_transaction_head; /**< List of free transactions head */ + struct cvmx_usb_transaction *free_transaction_tail; /**< List of free transactions tail */ cvmx_usb_pipe_t pipe[MAX_PIPES]; /**< Storage for pipes */ - cvmx_usb_transaction_t transaction[MAX_TRANSACTIONS]; /**< Storage for transactions */ + struct cvmx_usb_transaction transaction[MAX_TRANSACTIONS]; /**< Storage for transactions */ cvmx_usb_callback_func_t callback[__CVMX_USB_CALLBACK_END]; /**< User global callbacks */ void *callback_data[__CVMX_USB_CALLBACK_END]; /**< User data for each callback */ int indent; /**< Used by debug output to indent functions */ @@ -201,7 +218,7 @@ typedef struct { cvmx_usb_pipe_list_t idle_pipes; /**< List of open pipes that have no transactions */ cvmx_usb_pipe_list_t active_pipes[4]; /**< Active pipes indexed by transfer type */ uint64_t frame_number; /**< Increments every SOF interrupt for time keeping */ - cvmx_usb_transaction_t *active_split; /**< Points to the current active split, or NULL */ + struct cvmx_usb_transaction *active_split; /**< Points to the current active split, or NULL */ cvmx_usb_tx_fifo_t periodic; cvmx_usb_tx_fifo_t nonperiodic; } cvmx_usb_internal_state_t; @@ -391,9 +408,9 @@ int cvmx_usb_get_num_ports(void) * * Returns: Transaction or NULL */ -static inline cvmx_usb_transaction_t *__cvmx_usb_alloc_transaction(cvmx_usb_internal_state_t *usb) +static inline struct cvmx_usb_transaction *__cvmx_usb_alloc_transaction(cvmx_usb_internal_state_t *usb) { - cvmx_usb_transaction_t *t; + struct cvmx_usb_transaction *t; t = usb->free_transaction_head; if (t) { usb->free_transaction_head = t->next; @@ -417,7 +434,7 @@ static inline cvmx_usb_transaction_t *__cvmx_usb_alloc_transaction(cvmx_usb_inte * Transaction to free */ static inline void __cvmx_usb_free_transaction(cvmx_usb_internal_state_t *usb, - cvmx_usb_transaction_t *transaction) + struct cvmx_usb_transaction *transaction) { transaction->flags = 0; transaction->prev = NULL; @@ -1022,7 +1039,7 @@ void cvmx_usb_set_status(struct cvmx_usb_state *state, struct cvmx_usb_port_stat * Returns: Handle */ static inline int __cvmx_usb_get_submit_handle(cvmx_usb_internal_state_t *usb, - cvmx_usb_transaction_t *transaction) + struct cvmx_usb_transaction *transaction) { return ((unsigned long)transaction - (unsigned long)usb->transaction) / sizeof(*transaction); @@ -1380,7 +1397,7 @@ static void __cvmx_usb_start_channel_control(cvmx_usb_internal_state_t *usb, int channel, cvmx_usb_pipe_t *pipe) { - cvmx_usb_transaction_t *transaction = pipe->head; + struct cvmx_usb_transaction *transaction = pipe->head; cvmx_usb_control_header_t *header = cvmx_phys_to_ptr(transaction->control_header); int bytes_to_transfer = transaction->buffer_length - transaction->actual_bytes; int packets_to_transfer; @@ -1509,7 +1526,7 @@ static void __cvmx_usb_start_channel(cvmx_usb_internal_state_t *usb, int channel, cvmx_usb_pipe_t *pipe) { - cvmx_usb_transaction_t *transaction = pipe->head; + struct cvmx_usb_transaction *transaction = pipe->head; /* Make sure all writes to the DMA region get flushed */ CVMX_SYNCW; @@ -1900,7 +1917,7 @@ done: */ static void __cvmx_usb_perform_callback(cvmx_usb_internal_state_t *usb, cvmx_usb_pipe_t *pipe, - cvmx_usb_transaction_t *transaction, + struct cvmx_usb_transaction *transaction, enum cvmx_usb_callback reason, enum cvmx_usb_complete complete_code) { @@ -1945,7 +1962,7 @@ static void __cvmx_usb_perform_callback(cvmx_usb_internal_state_t *usb, */ static void __cvmx_usb_perform_complete(cvmx_usb_internal_state_t *usb, cvmx_usb_pipe_t *pipe, - cvmx_usb_transaction_t *transaction, + struct cvmx_usb_transaction *transaction, enum cvmx_usb_complete complete_code) { /* If this was a split then clear our split in progress marker */ @@ -2037,7 +2054,7 @@ static int __cvmx_usb_submit_transaction(cvmx_usb_internal_state_t *usb, void *user_data) { int submit_handle; - cvmx_usb_transaction_t *transaction; + struct cvmx_usb_transaction *transaction; cvmx_usb_pipe_t *pipe = usb->pipe + pipe_handle; if (unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES))) @@ -2382,7 +2399,7 @@ int cvmx_usb_submit_isochronous(struct cvmx_usb_state *state, int pipe_handle, */ int cvmx_usb_cancel(struct cvmx_usb_state *state, int pipe_handle, int submit_handle) { - cvmx_usb_transaction_t *transaction; + struct cvmx_usb_transaction *transaction; cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; cvmx_usb_pipe_t *pipe = usb->pipe + pipe_handle; @@ -2561,7 +2578,7 @@ static int __cvmx_usb_poll_channel(cvmx_usb_internal_state_t *usb, int channel) cvmx_usbcx_hctsizx_t usbc_hctsiz; cvmx_usbcx_hccharx_t usbc_hcchar; cvmx_usb_pipe_t *pipe; - cvmx_usb_transaction_t *transaction; + struct cvmx_usb_transaction *transaction; int bytes_this_transfer; int bytes_in_last_packet; int packets_processed; From 4ec3ae8412d0da9118cc441a807cce77fc0416bd Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 30 Jul 2013 23:43:07 +0300 Subject: [PATCH 1264/3400] staging: octeon-usb: cvmx_usb_pipe_t -> struct cvmx_usb_pipe Replace cvmx_usb_pipe_t with struct cvmx_usb_pipe. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.c | 114 ++++++++++++++++---------- 1 file changed, 69 insertions(+), 45 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.c b/drivers/staging/octeon-usb/cvmx-usb.c index beb3963dd5e6..93ce1176dbca 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.c +++ b/drivers/staging/octeon-usb/cvmx-usb.c @@ -157,34 +157,58 @@ struct cvmx_usb_transaction { }; /** - * A pipe represents a virtual connection between Octeon and some - * USB device. It contains a list of pending request to the device. + * struct cvmx_usb_pipe - a pipe represents a virtual connection between Octeon + * and some USB device. It contains a list of pending + * request to the device. + * + * @prev: Pipe before this one in the list + * @next: Pipe after this one in the list + * @head: The first pending transaction + * @tail: The last pending transaction + * @interval: For periodic pipes, the interval between packets in + * frames + * @next_tx_frame: The next frame this pipe is allowed to transmit on + * @flags: State flags for this pipe + * @device_speed: Speed of device connected to this pipe + * @transfer_type: Type of transaction supported by this pipe + * @transfer_dir: IN or OUT. Ignored for Control + * @multi_count: Max packet in a row for the device + * @max_packet: The device's maximum packet size in bytes + * @device_addr: USB device address at other end of pipe + * @endpoint_num: USB endpoint number at other end of pipe + * @hub_device_addr: Hub address this device is connected to + * @hub_port: Hub port this device is connected to + * @pid_toggle: This toggles between 0/1 on every packet send to track + * the data pid needed + * @channel: Hardware DMA channel for this pipe + * @split_sc_frame: The low order bits of the frame number the split + * complete should be sent on */ -typedef struct cvmx_usb_pipe { - struct cvmx_usb_pipe *prev; /**< Pipe before this one in the list */ - struct cvmx_usb_pipe *next; /**< Pipe after this one in the list */ - struct cvmx_usb_transaction *head; /**< The first pending transaction */ - struct cvmx_usb_transaction *tail; /**< The last pending transaction */ - uint64_t interval; /**< For periodic pipes, the interval between packets in frames */ - uint64_t next_tx_frame; /**< The next frame this pipe is allowed to transmit on */ - enum cvmx_usb_pipe_flags flags; /**< State flags for this pipe */ - enum cvmx_usb_speed device_speed; /**< Speed of device connected to this pipe */ - enum cvmx_usb_transfer transfer_type; /**< Type of transaction supported by this pipe */ - enum cvmx_usb_direction transfer_dir; /**< IN or OUT. Ignored for Control */ - int multi_count; /**< Max packet in a row for the device */ - uint16_t max_packet; /**< The device's maximum packet size in bytes */ - uint8_t device_addr; /**< USB device address at other end of pipe */ - uint8_t endpoint_num; /**< USB endpoint number at other end of pipe */ - uint8_t hub_device_addr; /**< Hub address this device is connected to */ - uint8_t hub_port; /**< Hub port this device is connected to */ - uint8_t pid_toggle; /**< This toggles between 0/1 on every packet send to track the data pid needed */ - uint8_t channel; /**< Hardware DMA channel for this pipe */ - int8_t split_sc_frame; /**< The low order bits of the frame number the split complete should be sent on */ -} cvmx_usb_pipe_t; +struct cvmx_usb_pipe { + struct cvmx_usb_pipe *prev; + struct cvmx_usb_pipe *next; + struct cvmx_usb_transaction *head; + struct cvmx_usb_transaction *tail; + uint64_t interval; + uint64_t next_tx_frame; + enum cvmx_usb_pipe_flags flags; + enum cvmx_usb_speed device_speed; + enum cvmx_usb_transfer transfer_type; + enum cvmx_usb_direction transfer_dir; + int multi_count; + uint16_t max_packet; + uint8_t device_addr; + uint8_t endpoint_num; + uint8_t hub_device_addr; + uint8_t hub_port; + uint8_t pid_toggle; + uint8_t channel; + int8_t split_sc_frame; +}; typedef struct { - cvmx_usb_pipe_t *head; /**< Head of the list, or NULL if empty */ - cvmx_usb_pipe_t *tail; /**< Tail if the list, or NULL if empty */ + struct cvmx_usb_pipe *head; /**< Head of the list, or NULL if empty */ + struct cvmx_usb_pipe *tail; /**< Tail if the list, or NULL if empty */ } cvmx_usb_pipe_list_t; typedef struct { @@ -205,10 +229,10 @@ typedef struct { int index; /**< Which USB block this is for */ int idle_hardware_channels; /**< Bit set for every idle hardware channel */ cvmx_usbcx_hprt_t usbcx_hprt; /**< Stored port status so we don't need to read a CSR to determine splits */ - cvmx_usb_pipe_t *pipe_for_channel[MAX_CHANNELS]; /**< Map channels to pipes */ + struct cvmx_usb_pipe *pipe_for_channel[MAX_CHANNELS]; /**< Map channels to pipes */ struct cvmx_usb_transaction *free_transaction_head; /**< List of free transactions head */ struct cvmx_usb_transaction *free_transaction_tail; /**< List of free transactions tail */ - cvmx_usb_pipe_t pipe[MAX_PIPES]; /**< Storage for pipes */ + struct cvmx_usb_pipe pipe[MAX_PIPES]; /**< Storage for pipes */ struct cvmx_usb_transaction transaction[MAX_TRANSACTIONS]; /**< Storage for transactions */ cvmx_usb_callback_func_t callback[__CVMX_USB_CALLBACK_END]; /**< User global callbacks */ void *callback_data[__CVMX_USB_CALLBACK_END]; /**< User data for each callback */ @@ -347,7 +371,7 @@ static inline void __cvmx_usb_write_csr64(cvmx_usb_internal_state_t *usb, * * Returns: Non zero if we need to do split transactions */ -static inline int __cvmx_usb_pipe_needs_split(cvmx_usb_internal_state_t *usb, cvmx_usb_pipe_t *pipe) +static inline int __cvmx_usb_pipe_needs_split(cvmx_usb_internal_state_t *usb, struct cvmx_usb_pipe *pipe) { return ((pipe->device_speed != CVMX_USB_SPEED_HIGH) && (usb->usbcx_hprt.s.prtspd == CVMX_USB_SPEED_HIGH)); } @@ -360,7 +384,7 @@ static inline int __cvmx_usb_pipe_needs_split(cvmx_usb_internal_state_t *usb, cv * * Returns: PID for pipe */ -static inline int __cvmx_usb_get_data_pid(cvmx_usb_pipe_t *pipe) +static inline int __cvmx_usb_get_data_pid(struct cvmx_usb_pipe *pipe) { if (pipe->pid_toggle) return 2; /* Data1 */ @@ -452,7 +476,7 @@ static inline void __cvmx_usb_free_transaction(cvmx_usb_internal_state_t *usb, * @list: List to add pipe to * @pipe: Pipe to add */ -static inline void __cvmx_usb_append_pipe(cvmx_usb_pipe_list_t *list, cvmx_usb_pipe_t *pipe) +static inline void __cvmx_usb_append_pipe(cvmx_usb_pipe_list_t *list, struct cvmx_usb_pipe *pipe) { pipe->next = NULL; pipe->prev = list->tail; @@ -469,7 +493,7 @@ static inline void __cvmx_usb_append_pipe(cvmx_usb_pipe_list_t *list, cvmx_usb_p * @list: List to remove pipe from * @pipe: Pipe to remove */ -static inline void __cvmx_usb_remove_pipe(cvmx_usb_pipe_list_t *list, cvmx_usb_pipe_t *pipe) +static inline void __cvmx_usb_remove_pipe(cvmx_usb_pipe_list_t *list, struct cvmx_usb_pipe *pipe) { if (list->head == pipe) { list->head = pipe->next; @@ -1056,7 +1080,7 @@ static inline int __cvmx_usb_get_submit_handle(cvmx_usb_internal_state_t *usb, * Returns: Handle */ static inline int __cvmx_usb_get_pipe_handle(cvmx_usb_internal_state_t *usb, - cvmx_usb_pipe_t *pipe) + struct cvmx_usb_pipe *pipe) { return ((unsigned long)pipe - (unsigned long)usb->pipe) / sizeof(*pipe); } @@ -1125,7 +1149,7 @@ int cvmx_usb_open_pipe(struct cvmx_usb_state *state, enum cvmx_usb_pipe_flags fl enum cvmx_usb_direction transfer_dir, int interval, int multi_count, int hub_device_addr, int hub_port) { - cvmx_usb_pipe_t *pipe; + struct cvmx_usb_pipe *pipe; cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; if (unlikely((device_addr < 0) || (device_addr > MAX_USB_ADDRESS))) @@ -1395,7 +1419,7 @@ static void __cvmx_usb_fill_tx_fifo(cvmx_usb_internal_state_t *usb, int channel) */ static void __cvmx_usb_start_channel_control(cvmx_usb_internal_state_t *usb, int channel, - cvmx_usb_pipe_t *pipe) + struct cvmx_usb_pipe *pipe) { struct cvmx_usb_transaction *transaction = pipe->head; cvmx_usb_control_header_t *header = cvmx_phys_to_ptr(transaction->control_header); @@ -1524,7 +1548,7 @@ static void __cvmx_usb_start_channel_control(cvmx_usb_internal_state_t *usb, */ static void __cvmx_usb_start_channel(cvmx_usb_internal_state_t *usb, int channel, - cvmx_usb_pipe_t *pipe) + struct cvmx_usb_pipe *pipe) { struct cvmx_usb_transaction *transaction = pipe->head; @@ -1811,9 +1835,9 @@ static void __cvmx_usb_start_channel(cvmx_usb_internal_state_t *usb, * * Returns: Pipe or NULL if none are ready */ -static cvmx_usb_pipe_t *__cvmx_usb_find_ready_pipe(cvmx_usb_internal_state_t *usb, cvmx_usb_pipe_list_t *list, uint64_t current_frame) +static struct cvmx_usb_pipe *__cvmx_usb_find_ready_pipe(cvmx_usb_internal_state_t *usb, cvmx_usb_pipe_list_t *list, uint64_t current_frame) { - cvmx_usb_pipe_t *pipe = list->head; + struct cvmx_usb_pipe *pipe = list->head; while (pipe) { if (!(pipe->flags & __CVMX_USB_PIPE_FLAGS_SCHEDULED) && pipe->head && (pipe->next_tx_frame <= current_frame) && @@ -1840,7 +1864,7 @@ static cvmx_usb_pipe_t *__cvmx_usb_find_ready_pipe(cvmx_usb_internal_state_t *us static void __cvmx_usb_schedule(cvmx_usb_internal_state_t *usb, int is_sof) { int channel; - cvmx_usb_pipe_t *pipe; + struct cvmx_usb_pipe *pipe; int need_sof; enum cvmx_usb_transfer ttype; @@ -1916,7 +1940,7 @@ done: * Completion code for the transaction, if any */ static void __cvmx_usb_perform_callback(cvmx_usb_internal_state_t *usb, - cvmx_usb_pipe_t *pipe, + struct cvmx_usb_pipe *pipe, struct cvmx_usb_transaction *transaction, enum cvmx_usb_callback reason, enum cvmx_usb_complete complete_code) @@ -1961,7 +1985,7 @@ static void __cvmx_usb_perform_callback(cvmx_usb_internal_state_t *usb, * Completion code */ static void __cvmx_usb_perform_complete(cvmx_usb_internal_state_t *usb, - cvmx_usb_pipe_t *pipe, + struct cvmx_usb_pipe *pipe, struct cvmx_usb_transaction *transaction, enum cvmx_usb_complete complete_code) { @@ -2055,7 +2079,7 @@ static int __cvmx_usb_submit_transaction(cvmx_usb_internal_state_t *usb, { int submit_handle; struct cvmx_usb_transaction *transaction; - cvmx_usb_pipe_t *pipe = usb->pipe + pipe_handle; + struct cvmx_usb_pipe *pipe = usb->pipe + pipe_handle; if (unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES))) return -EINVAL; @@ -2401,7 +2425,7 @@ int cvmx_usb_cancel(struct cvmx_usb_state *state, int pipe_handle, int submit_ha { struct cvmx_usb_transaction *transaction; cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; - cvmx_usb_pipe_t *pipe = usb->pipe + pipe_handle; + struct cvmx_usb_pipe *pipe = usb->pipe + pipe_handle; if (unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES))) return -EINVAL; @@ -2457,7 +2481,7 @@ int cvmx_usb_cancel(struct cvmx_usb_state *state, int pipe_handle, int submit_ha int cvmx_usb_cancel_all(struct cvmx_usb_state *state, int pipe_handle) { cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; - cvmx_usb_pipe_t *pipe = usb->pipe + pipe_handle; + struct cvmx_usb_pipe *pipe = usb->pipe + pipe_handle; if (unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES))) return -EINVAL; @@ -2491,7 +2515,7 @@ int cvmx_usb_cancel_all(struct cvmx_usb_state *state, int pipe_handle) int cvmx_usb_close_pipe(struct cvmx_usb_state *state, int pipe_handle) { cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; - cvmx_usb_pipe_t *pipe = usb->pipe + pipe_handle; + struct cvmx_usb_pipe *pipe = usb->pipe + pipe_handle; if (unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES))) return -EINVAL; @@ -2577,7 +2601,7 @@ static int __cvmx_usb_poll_channel(cvmx_usb_internal_state_t *usb, int channel) cvmx_usbcx_hcintx_t usbc_hcint; cvmx_usbcx_hctsizx_t usbc_hctsiz; cvmx_usbcx_hccharx_t usbc_hcchar; - cvmx_usb_pipe_t *pipe; + struct cvmx_usb_pipe *pipe; struct cvmx_usb_transaction *transaction; int bytes_this_transfer; int bytes_in_last_packet; From bb06528d6eb9be3f857a2f1275c4c55ce1584a20 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 30 Jul 2013 23:43:08 +0300 Subject: [PATCH 1265/3400] staging: octeon-usb: cvmx_usb_pipe_list_t -> struct cvmx_usb_pipe_list Replace cvmx_usb_pipe_list_t with struct cvmx_usb_pipe_list. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.c b/drivers/staging/octeon-usb/cvmx-usb.c index 93ce1176dbca..c5bf5d1db1f9 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.c +++ b/drivers/staging/octeon-usb/cvmx-usb.c @@ -206,10 +206,16 @@ struct cvmx_usb_pipe { int8_t split_sc_frame; }; -typedef struct { - struct cvmx_usb_pipe *head; /**< Head of the list, or NULL if empty */ - struct cvmx_usb_pipe *tail; /**< Tail if the list, or NULL if empty */ -} cvmx_usb_pipe_list_t; +/** + * struct cvmx_usb_pipe_list + * + * @head: Head of the list, or NULL if empty. + * @tail: Tail if the list, or NULL if empty. + */ +struct cvmx_usb_pipe_list { + struct cvmx_usb_pipe *head; + struct cvmx_usb_pipe *tail; +}; typedef struct { struct { @@ -238,9 +244,9 @@ typedef struct { void *callback_data[__CVMX_USB_CALLBACK_END]; /**< User data for each callback */ int indent; /**< Used by debug output to indent functions */ struct cvmx_usb_port_status port_status; /**< Last port status used for change notification */ - cvmx_usb_pipe_list_t free_pipes; /**< List of all pipes that are currently closed */ - cvmx_usb_pipe_list_t idle_pipes; /**< List of open pipes that have no transactions */ - cvmx_usb_pipe_list_t active_pipes[4]; /**< Active pipes indexed by transfer type */ + struct cvmx_usb_pipe_list free_pipes; /**< List of all pipes that are currently closed */ + struct cvmx_usb_pipe_list idle_pipes; /**< List of open pipes that have no transactions */ + struct cvmx_usb_pipe_list active_pipes[4]; /**< Active pipes indexed by transfer type */ uint64_t frame_number; /**< Increments every SOF interrupt for time keeping */ struct cvmx_usb_transaction *active_split; /**< Points to the current active split, or NULL */ cvmx_usb_tx_fifo_t periodic; @@ -476,7 +482,7 @@ static inline void __cvmx_usb_free_transaction(cvmx_usb_internal_state_t *usb, * @list: List to add pipe to * @pipe: Pipe to add */ -static inline void __cvmx_usb_append_pipe(cvmx_usb_pipe_list_t *list, struct cvmx_usb_pipe *pipe) +static inline void __cvmx_usb_append_pipe(struct cvmx_usb_pipe_list *list, struct cvmx_usb_pipe *pipe) { pipe->next = NULL; pipe->prev = list->tail; @@ -493,7 +499,7 @@ static inline void __cvmx_usb_append_pipe(cvmx_usb_pipe_list_t *list, struct cvm * @list: List to remove pipe from * @pipe: Pipe to remove */ -static inline void __cvmx_usb_remove_pipe(cvmx_usb_pipe_list_t *list, struct cvmx_usb_pipe *pipe) +static inline void __cvmx_usb_remove_pipe(struct cvmx_usb_pipe_list *list, struct cvmx_usb_pipe *pipe) { if (list->head == pipe) { list->head = pipe->next; @@ -1835,7 +1841,7 @@ static void __cvmx_usb_start_channel(cvmx_usb_internal_state_t *usb, * * Returns: Pipe or NULL if none are ready */ -static struct cvmx_usb_pipe *__cvmx_usb_find_ready_pipe(cvmx_usb_internal_state_t *usb, cvmx_usb_pipe_list_t *list, uint64_t current_frame) +static struct cvmx_usb_pipe *__cvmx_usb_find_ready_pipe(cvmx_usb_internal_state_t *usb, struct cvmx_usb_pipe_list *list, uint64_t current_frame) { struct cvmx_usb_pipe *pipe = list->head; while (pipe) { From 0ff6ac84f9648260f0d4e5994f13cbb6538d9285 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 30 Jul 2013 23:43:09 +0300 Subject: [PATCH 1266/3400] staging: octeon-usb: cvmx_usb_tx_fifo_t -> struct cvmx_usb_tx_fifo Replace cvmx_usb_tx_fifo_t with struct cvmx_usb_tx_fifo_t. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.c b/drivers/staging/octeon-usb/cvmx-usb.c index c5bf5d1db1f9..468cdff3cccb 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.c +++ b/drivers/staging/octeon-usb/cvmx-usb.c @@ -217,7 +217,7 @@ struct cvmx_usb_pipe_list { struct cvmx_usb_pipe *tail; }; -typedef struct { +struct cvmx_usb_tx_fifo { struct { int channel; int size; @@ -225,7 +225,7 @@ typedef struct { } entry[MAX_CHANNELS+1]; int head; int tail; -} cvmx_usb_tx_fifo_t; +}; /** * The state of the USB block is stored in this structure @@ -249,8 +249,8 @@ typedef struct { struct cvmx_usb_pipe_list active_pipes[4]; /**< Active pipes indexed by transfer type */ uint64_t frame_number; /**< Increments every SOF interrupt for time keeping */ struct cvmx_usb_transaction *active_split; /**< Points to the current active split, or NULL */ - cvmx_usb_tx_fifo_t periodic; - cvmx_usb_tx_fifo_t nonperiodic; + struct cvmx_usb_tx_fifo periodic; + struct cvmx_usb_tx_fifo nonperiodic; } cvmx_usb_internal_state_t; /* This macro spins on a field waiting for it to reach a value */ @@ -1288,7 +1288,7 @@ static void __cvmx_usb_poll_rx_fifo(cvmx_usb_internal_state_t *usb) * Returns: Non zero if the hardware fifo was too small and needs * to be serviced again. */ -static int __cvmx_usb_fill_tx_hw(cvmx_usb_internal_state_t *usb, cvmx_usb_tx_fifo_t *fifo, int available) +static int __cvmx_usb_fill_tx_hw(cvmx_usb_internal_state_t *usb, struct cvmx_usb_tx_fifo *fifo, int available) { /* * We're done either when there isn't anymore space or the software FIFO @@ -1378,7 +1378,7 @@ static void __cvmx_usb_fill_tx_fifo(cvmx_usb_internal_state_t *usb, int channel) cvmx_usbcx_hccharx_t hcchar; cvmx_usbcx_hcspltx_t usbc_hcsplt; cvmx_usbcx_hctsizx_t usbc_hctsiz; - cvmx_usb_tx_fifo_t *fifo; + struct cvmx_usb_tx_fifo *fifo; /* We only need to fill data on outbound channels */ hcchar.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCCHARX(channel, usb->index)); From 2bf249e482f42145890d39d8c575e502642b3307 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 30 Jul 2013 23:43:10 +0300 Subject: [PATCH 1267/3400] staging: octeon-usb: cvmx_usb_internal_state_t -> struct cvmx_usb_internal_state Replace cvmx_usb_internal_state_t with struct cvmx_usb_internal_state. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.c | 138 +++++++++++++++----------- 1 file changed, 79 insertions(+), 59 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.c b/drivers/staging/octeon-usb/cvmx-usb.c index 468cdff3cccb..3cc315ded3f9 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.c +++ b/drivers/staging/octeon-usb/cvmx-usb.c @@ -228,30 +228,50 @@ struct cvmx_usb_tx_fifo { }; /** - * The state of the USB block is stored in this structure + * struct cvmx_usb_internal_state - the state of the USB block + * + * init_flags: Flags passed to initialize. + * index: Which USB block this is for. + * idle_hardware_channels: Bit set for every idle hardware channel. + * usbcx_hprt: Stored port status so we don't need to read a CSR to + * determine splits. + * pipe_for_channel: Map channels to pipes. + * free_transaction_head: List of free transactions head. + * free_transaction_tail: List of free transactions tail. + * pipe: Storage for pipes. + * transaction: Storage for transactions. + * callback: User global callbacks. + * callback_data: User data for each callback. + * indent: Used by debug output to indent functions. + * port_status: Last port status used for change notification. + * free_pipes: List of all pipes that are currently closed. + * idle_pipes: List of open pipes that have no transactions. + * active_pipes: Active pipes indexed by transfer type. + * frame_number: Increments every SOF interrupt for time keeping. + * active_split: Points to the current active split, or NULL. */ -typedef struct { - int init_flags; /**< Flags passed to initialize */ - int index; /**< Which USB block this is for */ - int idle_hardware_channels; /**< Bit set for every idle hardware channel */ - cvmx_usbcx_hprt_t usbcx_hprt; /**< Stored port status so we don't need to read a CSR to determine splits */ - struct cvmx_usb_pipe *pipe_for_channel[MAX_CHANNELS]; /**< Map channels to pipes */ - struct cvmx_usb_transaction *free_transaction_head; /**< List of free transactions head */ - struct cvmx_usb_transaction *free_transaction_tail; /**< List of free transactions tail */ - struct cvmx_usb_pipe pipe[MAX_PIPES]; /**< Storage for pipes */ - struct cvmx_usb_transaction transaction[MAX_TRANSACTIONS]; /**< Storage for transactions */ - cvmx_usb_callback_func_t callback[__CVMX_USB_CALLBACK_END]; /**< User global callbacks */ - void *callback_data[__CVMX_USB_CALLBACK_END]; /**< User data for each callback */ - int indent; /**< Used by debug output to indent functions */ - struct cvmx_usb_port_status port_status; /**< Last port status used for change notification */ - struct cvmx_usb_pipe_list free_pipes; /**< List of all pipes that are currently closed */ - struct cvmx_usb_pipe_list idle_pipes; /**< List of open pipes that have no transactions */ - struct cvmx_usb_pipe_list active_pipes[4]; /**< Active pipes indexed by transfer type */ - uint64_t frame_number; /**< Increments every SOF interrupt for time keeping */ - struct cvmx_usb_transaction *active_split; /**< Points to the current active split, or NULL */ +struct cvmx_usb_internal_state { + int init_flags; + int index; + int idle_hardware_channels; + cvmx_usbcx_hprt_t usbcx_hprt; + struct cvmx_usb_pipe *pipe_for_channel[MAX_CHANNELS]; + struct cvmx_usb_transaction *free_transaction_head; + struct cvmx_usb_transaction *free_transaction_tail; + struct cvmx_usb_pipe pipe[MAX_PIPES]; + struct cvmx_usb_transaction transaction[MAX_TRANSACTIONS]; + cvmx_usb_callback_func_t callback[__CVMX_USB_CALLBACK_END]; + void *callback_data[__CVMX_USB_CALLBACK_END]; + int indent; + struct cvmx_usb_port_status port_status; + struct cvmx_usb_pipe_list free_pipes; + struct cvmx_usb_pipe_list idle_pipes; + struct cvmx_usb_pipe_list active_pipes[4]; + uint64_t frame_number; + struct cvmx_usb_transaction *active_split; struct cvmx_usb_tx_fifo periodic; struct cvmx_usb_tx_fifo nonperiodic; -} cvmx_usb_internal_state_t; +}; /* This macro spins on a field waiting for it to reach a value */ #define CVMX_WAIT_FOR_FIELD32(address, type, field, op, value, timeout_usec)\ @@ -312,7 +332,7 @@ static int octeon_usb_get_clock_type(void) * * Returns: Result of the read */ -static inline uint32_t __cvmx_usb_read_csr32(cvmx_usb_internal_state_t *usb, +static inline uint32_t __cvmx_usb_read_csr32(struct cvmx_usb_internal_state *usb, uint64_t address) { uint32_t result = cvmx_read64_uint32(address ^ 4); @@ -329,7 +349,7 @@ static inline uint32_t __cvmx_usb_read_csr32(cvmx_usb_internal_state_t *usb, * @address: 64bit address to write * @value: Value to write */ -static inline void __cvmx_usb_write_csr32(cvmx_usb_internal_state_t *usb, +static inline void __cvmx_usb_write_csr32(struct cvmx_usb_internal_state *usb, uint64_t address, uint32_t value) { cvmx_write64_uint32(address ^ 4, value); @@ -346,7 +366,7 @@ static inline void __cvmx_usb_write_csr32(cvmx_usb_internal_state_t *usb, * * Returns: Result of the read */ -static inline uint64_t __cvmx_usb_read_csr64(cvmx_usb_internal_state_t *usb, +static inline uint64_t __cvmx_usb_read_csr64(struct cvmx_usb_internal_state *usb, uint64_t address) { uint64_t result = cvmx_read64_uint64(address); @@ -362,7 +382,7 @@ static inline uint64_t __cvmx_usb_read_csr64(cvmx_usb_internal_state_t *usb, * @address: 64bit address to write * @value: Value to write */ -static inline void __cvmx_usb_write_csr64(cvmx_usb_internal_state_t *usb, +static inline void __cvmx_usb_write_csr64(struct cvmx_usb_internal_state *usb, uint64_t address, uint64_t value) { cvmx_write64_uint64(address, value); @@ -377,7 +397,7 @@ static inline void __cvmx_usb_write_csr64(cvmx_usb_internal_state_t *usb, * * Returns: Non zero if we need to do split transactions */ -static inline int __cvmx_usb_pipe_needs_split(cvmx_usb_internal_state_t *usb, struct cvmx_usb_pipe *pipe) +static inline int __cvmx_usb_pipe_needs_split(struct cvmx_usb_internal_state *usb, struct cvmx_usb_pipe *pipe) { return ((pipe->device_speed != CVMX_USB_SPEED_HIGH) && (usb->usbcx_hprt.s.prtspd == CVMX_USB_SPEED_HIGH)); } @@ -438,7 +458,7 @@ int cvmx_usb_get_num_ports(void) * * Returns: Transaction or NULL */ -static inline struct cvmx_usb_transaction *__cvmx_usb_alloc_transaction(cvmx_usb_internal_state_t *usb) +static inline struct cvmx_usb_transaction *__cvmx_usb_alloc_transaction(struct cvmx_usb_internal_state *usb) { struct cvmx_usb_transaction *t; t = usb->free_transaction_head; @@ -463,7 +483,7 @@ static inline struct cvmx_usb_transaction *__cvmx_usb_alloc_transaction(cvmx_usb * @transaction: * Transaction to free */ -static inline void __cvmx_usb_free_transaction(cvmx_usb_internal_state_t *usb, +static inline void __cvmx_usb_free_transaction(struct cvmx_usb_internal_state *usb, struct cvmx_usb_transaction *transaction) { transaction->flags = 0; @@ -543,7 +563,7 @@ int cvmx_usb_initialize(struct cvmx_usb_state *state, int usb_port_number, { cvmx_usbnx_clk_ctl_t usbn_clk_ctl; cvmx_usbnx_usbp_ctl_status_t usbn_usbp_ctl_status; - cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; + struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state; usb->init_flags = flags; @@ -868,7 +888,7 @@ int cvmx_usb_initialize(struct cvmx_usb_state *state, int usb_port_number, int cvmx_usb_shutdown(struct cvmx_usb_state *state) { cvmx_usbnx_clk_ctl_t usbn_clk_ctl; - cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; + struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state; /* Make sure all pipes are closed */ if (usb->idle_pipes.head || @@ -903,7 +923,7 @@ int cvmx_usb_shutdown(struct cvmx_usb_state *state) int cvmx_usb_enable(struct cvmx_usb_state *state) { cvmx_usbcx_ghwcfg3_t usbcx_ghwcfg3; - cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; + struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state; usb->usbcx_hprt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPRT(usb->index)); @@ -996,7 +1016,7 @@ int cvmx_usb_enable(struct cvmx_usb_state *state) */ int cvmx_usb_disable(struct cvmx_usb_state *state) { - cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; + struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state; /* Disable the port */ USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt_t, prtena, 1); @@ -1022,7 +1042,7 @@ struct cvmx_usb_port_status cvmx_usb_get_status(struct cvmx_usb_state *state) { cvmx_usbcx_hprt_t usbc_hprt; struct cvmx_usb_port_status result; - cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; + struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state; memset(&result, 0, sizeof(result)); @@ -1052,7 +1072,7 @@ struct cvmx_usb_port_status cvmx_usb_get_status(struct cvmx_usb_state *state) */ void cvmx_usb_set_status(struct cvmx_usb_state *state, struct cvmx_usb_port_status port_status) { - cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; + struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state; usb->port_status = port_status; return; } @@ -1068,7 +1088,7 @@ void cvmx_usb_set_status(struct cvmx_usb_state *state, struct cvmx_usb_port_stat * * Returns: Handle */ -static inline int __cvmx_usb_get_submit_handle(cvmx_usb_internal_state_t *usb, +static inline int __cvmx_usb_get_submit_handle(struct cvmx_usb_internal_state *usb, struct cvmx_usb_transaction *transaction) { return ((unsigned long)transaction - (unsigned long)usb->transaction) / @@ -1085,7 +1105,7 @@ static inline int __cvmx_usb_get_submit_handle(cvmx_usb_internal_state_t *usb, * * Returns: Handle */ -static inline int __cvmx_usb_get_pipe_handle(cvmx_usb_internal_state_t *usb, +static inline int __cvmx_usb_get_pipe_handle(struct cvmx_usb_internal_state *usb, struct cvmx_usb_pipe *pipe) { return ((unsigned long)pipe - (unsigned long)usb->pipe) / sizeof(*pipe); @@ -1156,7 +1176,7 @@ int cvmx_usb_open_pipe(struct cvmx_usb_state *state, enum cvmx_usb_pipe_flags fl int multi_count, int hub_device_addr, int hub_port) { struct cvmx_usb_pipe *pipe; - cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; + struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state; if (unlikely((device_addr < 0) || (device_addr > MAX_USB_ADDRESS))) return -EINVAL; @@ -1239,7 +1259,7 @@ int cvmx_usb_open_pipe(struct cvmx_usb_state *state, enum cvmx_usb_pipe_flags fl * @usb: USB device state populated by * cvmx_usb_initialize(). */ -static void __cvmx_usb_poll_rx_fifo(cvmx_usb_internal_state_t *usb) +static void __cvmx_usb_poll_rx_fifo(struct cvmx_usb_internal_state *usb) { cvmx_usbcx_grxstsph_t rx_status; int channel; @@ -1288,7 +1308,7 @@ static void __cvmx_usb_poll_rx_fifo(cvmx_usb_internal_state_t *usb) * Returns: Non zero if the hardware fifo was too small and needs * to be serviced again. */ -static int __cvmx_usb_fill_tx_hw(cvmx_usb_internal_state_t *usb, struct cvmx_usb_tx_fifo *fifo, int available) +static int __cvmx_usb_fill_tx_hw(struct cvmx_usb_internal_state *usb, struct cvmx_usb_tx_fifo *fifo, int available) { /* * We're done either when there isn't anymore space or the software FIFO @@ -1342,7 +1362,7 @@ static int __cvmx_usb_fill_tx_hw(cvmx_usb_internal_state_t *usb, struct cvmx_usb * @usb: USB device state populated by * cvmx_usb_initialize(). */ -static void __cvmx_usb_poll_tx_fifo(cvmx_usb_internal_state_t *usb) +static void __cvmx_usb_poll_tx_fifo(struct cvmx_usb_internal_state *usb) { if (usb->periodic.head != usb->periodic.tail) { cvmx_usbcx_hptxsts_t tx_status; @@ -1373,7 +1393,7 @@ static void __cvmx_usb_poll_tx_fifo(cvmx_usb_internal_state_t *usb) * cvmx_usb_initialize(). * @channel: Channel number to get packet from */ -static void __cvmx_usb_fill_tx_fifo(cvmx_usb_internal_state_t *usb, int channel) +static void __cvmx_usb_fill_tx_fifo(struct cvmx_usb_internal_state *usb, int channel) { cvmx_usbcx_hccharx_t hcchar; cvmx_usbcx_hcspltx_t usbc_hcsplt; @@ -1423,7 +1443,7 @@ static void __cvmx_usb_fill_tx_fifo(cvmx_usb_internal_state_t *usb, int channel) * @channel: Channel to setup * @pipe: Pipe for control transaction */ -static void __cvmx_usb_start_channel_control(cvmx_usb_internal_state_t *usb, +static void __cvmx_usb_start_channel_control(struct cvmx_usb_internal_state *usb, int channel, struct cvmx_usb_pipe *pipe) { @@ -1552,7 +1572,7 @@ static void __cvmx_usb_start_channel_control(cvmx_usb_internal_state_t *usb, * @channel: Channel to setup * @pipe: Pipe to start */ -static void __cvmx_usb_start_channel(cvmx_usb_internal_state_t *usb, +static void __cvmx_usb_start_channel(struct cvmx_usb_internal_state *usb, int channel, struct cvmx_usb_pipe *pipe) { @@ -1841,7 +1861,7 @@ static void __cvmx_usb_start_channel(cvmx_usb_internal_state_t *usb, * * Returns: Pipe or NULL if none are ready */ -static struct cvmx_usb_pipe *__cvmx_usb_find_ready_pipe(cvmx_usb_internal_state_t *usb, struct cvmx_usb_pipe_list *list, uint64_t current_frame) +static struct cvmx_usb_pipe *__cvmx_usb_find_ready_pipe(struct cvmx_usb_internal_state *usb, struct cvmx_usb_pipe_list *list, uint64_t current_frame) { struct cvmx_usb_pipe *pipe = list->head; while (pipe) { @@ -1867,7 +1887,7 @@ static struct cvmx_usb_pipe *__cvmx_usb_find_ready_pipe(cvmx_usb_internal_state_ * cvmx_usb_initialize(). * @is_sof: True if this schedule was called on a SOF interrupt. */ -static void __cvmx_usb_schedule(cvmx_usb_internal_state_t *usb, int is_sof) +static void __cvmx_usb_schedule(struct cvmx_usb_internal_state *usb, int is_sof) { int channel; struct cvmx_usb_pipe *pipe; @@ -1945,7 +1965,7 @@ done: * @complete_code: * Completion code for the transaction, if any */ -static void __cvmx_usb_perform_callback(cvmx_usb_internal_state_t *usb, +static void __cvmx_usb_perform_callback(struct cvmx_usb_internal_state *usb, struct cvmx_usb_pipe *pipe, struct cvmx_usb_transaction *transaction, enum cvmx_usb_callback reason, @@ -1990,7 +2010,7 @@ static void __cvmx_usb_perform_callback(cvmx_usb_internal_state_t *usb, * @complete_code: * Completion code */ -static void __cvmx_usb_perform_complete(cvmx_usb_internal_state_t *usb, +static void __cvmx_usb_perform_complete(struct cvmx_usb_internal_state *usb, struct cvmx_usb_pipe *pipe, struct cvmx_usb_transaction *transaction, enum cvmx_usb_complete complete_code) @@ -2070,7 +2090,7 @@ done: * Returns: Submit handle or negative on failure. Matches the result * in the external API. */ -static int __cvmx_usb_submit_transaction(cvmx_usb_internal_state_t *usb, +static int __cvmx_usb_submit_transaction(struct cvmx_usb_internal_state *usb, int pipe_handle, enum cvmx_usb_transfer type, int flags, @@ -2175,7 +2195,7 @@ int cvmx_usb_submit_bulk(struct cvmx_usb_state *state, int pipe_handle, void *user_data) { int submit_handle; - cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; + struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state; /* Pipe handle checking is done later in a common place */ if (unlikely(!buffer)) @@ -2234,7 +2254,7 @@ int cvmx_usb_submit_interrupt(struct cvmx_usb_state *state, int pipe_handle, void *user_data) { int submit_handle; - cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; + struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state; /* Pipe handle checking is done later in a common place */ if (unlikely(!buffer)) @@ -2298,7 +2318,7 @@ int cvmx_usb_submit_control(struct cvmx_usb_state *state, int pipe_handle, void *user_data) { int submit_handle; - cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; + struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state; cvmx_usb_control_header_t *header = cvmx_phys_to_ptr(control_header); /* Pipe handle checking is done later in a common place */ @@ -2380,7 +2400,7 @@ int cvmx_usb_submit_isochronous(struct cvmx_usb_state *state, int pipe_handle, void *user_data) { int submit_handle; - cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; + struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state; /* Pipe handle checking is done later in a common place */ if (unlikely(start_frame < 0)) @@ -2430,7 +2450,7 @@ int cvmx_usb_submit_isochronous(struct cvmx_usb_state *state, int pipe_handle, int cvmx_usb_cancel(struct cvmx_usb_state *state, int pipe_handle, int submit_handle) { struct cvmx_usb_transaction *transaction; - cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; + struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state; struct cvmx_usb_pipe *pipe = usb->pipe + pipe_handle; if (unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES))) @@ -2486,7 +2506,7 @@ int cvmx_usb_cancel(struct cvmx_usb_state *state, int pipe_handle, int submit_ha */ int cvmx_usb_cancel_all(struct cvmx_usb_state *state, int pipe_handle) { - cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; + struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state; struct cvmx_usb_pipe *pipe = usb->pipe + pipe_handle; if (unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES))) @@ -2520,7 +2540,7 @@ int cvmx_usb_cancel_all(struct cvmx_usb_state *state, int pipe_handle) */ int cvmx_usb_close_pipe(struct cvmx_usb_state *state, int pipe_handle) { - cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; + struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state; struct cvmx_usb_pipe *pipe = usb->pipe + pipe_handle; if (unlikely((pipe_handle < 0) || (pipe_handle >= MAX_PIPES))) @@ -2558,7 +2578,7 @@ int cvmx_usb_register_callback(struct cvmx_usb_state *state, cvmx_usb_callback_func_t callback, void *user_data) { - cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; + struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state; if (unlikely(reason >= __CVMX_USB_CALLBACK_END)) return -EINVAL; @@ -2584,7 +2604,7 @@ int cvmx_usb_register_callback(struct cvmx_usb_state *state, int cvmx_usb_get_frame_number(struct cvmx_usb_state *state) { int frame_number; - cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; + struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state; cvmx_usbcx_hfnum_t usbc_hfnum; usbc_hfnum.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HFNUM(usb->index)); @@ -2602,7 +2622,7 @@ int cvmx_usb_get_frame_number(struct cvmx_usb_state *state) * * Returns: Zero on success */ -static int __cvmx_usb_poll_channel(cvmx_usb_internal_state_t *usb, int channel) +static int __cvmx_usb_poll_channel(struct cvmx_usb_internal_state *usb, int channel) { cvmx_usbcx_hcintx_t usbc_hcint; cvmx_usbcx_hctsizx_t usbc_hctsiz; @@ -3043,7 +3063,7 @@ int cvmx_usb_poll(struct cvmx_usb_state *state) { cvmx_usbcx_hfnum_t usbc_hfnum; cvmx_usbcx_gintsts_t usbc_gintsts; - cvmx_usb_internal_state_t *usb = (cvmx_usb_internal_state_t *)state; + struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state; CVMX_PREFETCH(usb, 0); CVMX_PREFETCH(usb, 1*128); From 47509e4a9c17e71a5ab61b5a05aeacb4310aacae Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 30 Jul 2013 23:43:11 +0300 Subject: [PATCH 1268/3400] staging: octeon-usb: cvmx_usb_control_header_t -> union cvmx_usb_control_header Replace cvmx_usb_control_header_t with union cvmx_usb_control_header. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.c | 12 +++++++---- drivers/staging/octeon-usb/cvmx-usb.h | 31 ++++++++++++++++----------- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.c b/drivers/staging/octeon-usb/cvmx-usb.c index 3cc315ded3f9..8a9d94b80ea0 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.c +++ b/drivers/staging/octeon-usb/cvmx-usb.c @@ -1448,7 +1448,8 @@ static void __cvmx_usb_start_channel_control(struct cvmx_usb_internal_state *usb struct cvmx_usb_pipe *pipe) { struct cvmx_usb_transaction *transaction = pipe->head; - cvmx_usb_control_header_t *header = cvmx_phys_to_ptr(transaction->control_header); + union cvmx_usb_control_header *header = + cvmx_phys_to_ptr(transaction->control_header); int bytes_to_transfer = transaction->buffer_length - transaction->actual_bytes; int packets_to_transfer; cvmx_usbcx_hctsizx_t usbc_hctsiz; @@ -2319,7 +2320,8 @@ int cvmx_usb_submit_control(struct cvmx_usb_state *state, int pipe_handle, { int submit_handle; struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state; - cvmx_usb_control_header_t *header = cvmx_phys_to_ptr(control_header); + union cvmx_usb_control_header *header = + cvmx_phys_to_ptr(control_header); /* Pipe handle checking is done later in a common place */ if (unlikely(!control_header)) @@ -2884,7 +2886,8 @@ static int __cvmx_usb_poll_channel(struct cvmx_usb_internal_state *usb, int chan if (__cvmx_usb_pipe_needs_split(usb, pipe)) transaction->stage = CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE; else { - cvmx_usb_control_header_t *header = cvmx_phys_to_ptr(transaction->control_header); + union cvmx_usb_control_header *header = + cvmx_phys_to_ptr(transaction->control_header); if (header->s.length) transaction->stage = CVMX_USB_STAGE_DATA; else @@ -2893,7 +2896,8 @@ static int __cvmx_usb_poll_channel(struct cvmx_usb_internal_state *usb, int chan break; case CVMX_USB_STAGE_SETUP_SPLIT_COMPLETE: { - cvmx_usb_control_header_t *header = cvmx_phys_to_ptr(transaction->control_header); + union cvmx_usb_control_header *header = + cvmx_phys_to_ptr(transaction->control_header); if (header->s.length) transaction->stage = CVMX_USB_STAGE_DATA; else diff --git a/drivers/staging/octeon-usb/cvmx-usb.h b/drivers/staging/octeon-usb/cvmx-usb.h index bd6a2fb07489..8bf36966ef15 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.h +++ b/drivers/staging/octeon-usb/cvmx-usb.h @@ -335,20 +335,25 @@ struct cvmx_usb_port_status { }; /** - * This is the structure of a Control packet header + * union cvmx_usb_control_header - the structure of a Control packet header + * + * @s.request_type: Bit 7 tells the direction: 1=IN, 0=OUT + * @s.request The standard usb request to make + * @s.value Value parameter for the request in little endian format + * @s.index Index for the request in little endian format + * @s.length Length of the data associated with this request in + * little endian format */ -typedef union -{ - uint64_t u64; - struct - { - uint64_t request_type : 8; /**< Bit 7 tells the direction: 1=IN, 0=OUT */ - uint64_t request : 8; /**< The standard usb request to make */ - uint64_t value : 16; /**< Value parameter for the request in little endian format */ - uint64_t index : 16; /**< Index for the request in little endian format */ - uint64_t length : 16; /**< Length of the data associated with this request in little endian format */ - } s; -} cvmx_usb_control_header_t; +union cvmx_usb_control_header { + uint64_t u64; + struct { + uint64_t request_type : 8; + uint64_t request : 8; + uint64_t value : 16; + uint64_t index : 16; + uint64_t length : 16; + } s; +}; /** * struct cvmx_usb_iso_packet - descriptor for Isochronous packets From b9cc16c03dab5c43ad962b064f0b76a79a4bb5cb Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 30 Jul 2013 23:43:12 +0300 Subject: [PATCH 1269/3400] staging: octeon-usb: eliminate remaining typedef unions Remaining typedef unions can be trivially eliminated with the pattern: foo_t -> union foo Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/cvmx-usb.c | 136 +++++++++---------- drivers/staging/octeon-usb/cvmx-usbcx-defs.h | 23 ---- drivers/staging/octeon-usb/cvmx-usbnx-defs.h | 2 - 3 files changed, 68 insertions(+), 93 deletions(-) diff --git a/drivers/staging/octeon-usb/cvmx-usb.c b/drivers/staging/octeon-usb/cvmx-usb.c index 8a9d94b80ea0..d7b3c82b5ead 100644 --- a/drivers/staging/octeon-usb/cvmx-usb.c +++ b/drivers/staging/octeon-usb/cvmx-usb.c @@ -254,7 +254,7 @@ struct cvmx_usb_internal_state { int init_flags; int index; int idle_hardware_channels; - cvmx_usbcx_hprt_t usbcx_hprt; + union cvmx_usbcx_hprt usbcx_hprt; struct cvmx_usb_pipe *pipe_for_channel[MAX_CHANNELS]; struct cvmx_usb_transaction *free_transaction_head; struct cvmx_usb_transaction *free_transaction_tail; @@ -561,8 +561,8 @@ static inline void __cvmx_usb_remove_pipe(struct cvmx_usb_pipe_list *list, struc int cvmx_usb_initialize(struct cvmx_usb_state *state, int usb_port_number, enum cvmx_usb_initialize_flags flags) { - cvmx_usbnx_clk_ctl_t usbn_clk_ctl; - cvmx_usbnx_usbp_ctl_status_t usbn_usbp_ctl_status; + union cvmx_usbnx_clk_ctl usbn_clk_ctl; + union cvmx_usbnx_usbp_ctl_status usbn_usbp_ctl_status; struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state; usb->init_flags = flags; @@ -776,7 +776,7 @@ int cvmx_usb_initialize(struct cvmx_usb_state *state, int usb_port_number, * Global interrupt mask, USBC_GAHBCFG[GLBLINTRMSK] = 1 */ { - cvmx_usbcx_gahbcfg_t usbcx_gahbcfg; + union cvmx_usbcx_gahbcfg usbcx_gahbcfg; /* Due to an errata, CN31XX doesn't support DMA */ if (OCTEON_IS_MODEL(OCTEON_CN31XX)) usb->init_flags |= CVMX_USB_INITIALIZE_FLAGS_NO_DMA; @@ -803,7 +803,7 @@ int cvmx_usb_initialize(struct cvmx_usb_state *state, int usb_port_number, * PHY low-power clock select, USBC_GUSBCFG[PHYLPWRCLKSEL] = 0 */ { - cvmx_usbcx_gusbcfg_t usbcx_gusbcfg; + union cvmx_usbcx_gusbcfg usbcx_gusbcfg; usbcx_gusbcfg.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GUSBCFG(usb->index)); usbcx_gusbcfg.s.toutcal = 0; usbcx_gusbcfg.s.ddrsel = 0; @@ -819,7 +819,7 @@ int cvmx_usb_initialize(struct cvmx_usb_state *state, int usb_port_number, * Mode mismatch interrupt mask, USBC_GINTMSK[MODEMISMSK] = 1 */ { - cvmx_usbcx_gintmsk_t usbcx_gintmsk; + union cvmx_usbcx_gintmsk usbcx_gintmsk; int channel; usbcx_gintmsk.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GINTMSK(usb->index)); @@ -845,16 +845,16 @@ int cvmx_usb_initialize(struct cvmx_usb_state *state, int usb_port_number, * 1. Program the host-port interrupt-mask field to unmask, * USBC_GINTMSK[PRTINT] = 1 */ - USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), cvmx_usbcx_gintmsk_t, + USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), union cvmx_usbcx_gintmsk, prtintmsk, 1); - USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), cvmx_usbcx_gintmsk_t, + USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), union cvmx_usbcx_gintmsk, disconnintmsk, 1); /* * 2. Program the USBC_HCFG register to select full-speed host * or high-speed host. */ { - cvmx_usbcx_hcfg_t usbcx_hcfg; + union cvmx_usbcx_hcfg usbcx_hcfg; usbcx_hcfg.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCFG(usb->index)); usbcx_hcfg.s.fslssupp = 0; usbcx_hcfg.s.fslspclksel = 0; @@ -864,7 +864,7 @@ int cvmx_usb_initialize(struct cvmx_usb_state *state, int usb_port_number, * 3. Program the port power bit to drive VBUS on the USB, * USBC_HPRT[PRTPWR] = 1 */ - USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt_t, prtpwr, 1); + USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), union cvmx_usbcx_hprt, prtpwr, 1); /* * Steps 4-15 from the manual are done later in the port enable @@ -887,7 +887,7 @@ int cvmx_usb_initialize(struct cvmx_usb_state *state, int usb_port_number, */ int cvmx_usb_shutdown(struct cvmx_usb_state *state) { - cvmx_usbnx_clk_ctl_t usbn_clk_ctl; + union cvmx_usbnx_clk_ctl usbn_clk_ctl; struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state; /* Make sure all pipes are closed */ @@ -922,7 +922,7 @@ int cvmx_usb_shutdown(struct cvmx_usb_state *state) */ int cvmx_usb_enable(struct cvmx_usb_state *state) { - cvmx_usbcx_ghwcfg3_t usbcx_ghwcfg3; + union cvmx_usbcx_ghwcfg3 usbcx_ghwcfg3; struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state; usb->usbcx_hprt.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPRT(usb->index)); @@ -940,7 +940,7 @@ int cvmx_usb_enable(struct cvmx_usb_state *state) } /* Program the port reset bit to start the reset process */ - USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt_t, prtrst, 1); + USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), union cvmx_usbcx_hprt, prtrst, 1); /* * Wait at least 50ms (high speed), or 10ms (full speed) for the reset @@ -949,10 +949,10 @@ int cvmx_usb_enable(struct cvmx_usb_state *state) mdelay(50); /* Program the port reset bit to 0, USBC_HPRT[PRTRST] = 0 */ - USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt_t, prtrst, 0); + USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), union cvmx_usbcx_hprt, prtrst, 0); /* Wait for the USBC_HPRT[PRTENA]. */ - if (CVMX_WAIT_FOR_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt_t, + if (CVMX_WAIT_FOR_FIELD32(CVMX_USBCX_HPRT(usb->index), union cvmx_usbcx_hprt, prtena, ==, 1, 100000)) return -ETIMEDOUT; @@ -964,7 +964,7 @@ int cvmx_usb_enable(struct cvmx_usb_state *state) * 13. Program the USBC_GRXFSIZ register to select the size of the * receive FIFO (25%). */ - USB_SET_FIELD32(CVMX_USBCX_GRXFSIZ(usb->index), cvmx_usbcx_grxfsiz_t, + USB_SET_FIELD32(CVMX_USBCX_GRXFSIZ(usb->index), union cvmx_usbcx_grxfsiz, rxfdep, usbcx_ghwcfg3.s.dfifodepth / 4); /* * 14. Program the USBC_GNPTXFSIZ register to select the size and the @@ -972,7 +972,7 @@ int cvmx_usb_enable(struct cvmx_usb_state *state) * transactions (50%). */ { - cvmx_usbcx_gnptxfsiz_t siz; + union cvmx_usbcx_gnptxfsiz siz; siz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GNPTXFSIZ(usb->index)); siz.s.nptxfdep = usbcx_ghwcfg3.s.dfifodepth / 2; siz.s.nptxfstaddr = usbcx_ghwcfg3.s.dfifodepth / 4; @@ -984,19 +984,19 @@ int cvmx_usb_enable(struct cvmx_usb_state *state) * (25%). */ { - cvmx_usbcx_hptxfsiz_t siz; + union cvmx_usbcx_hptxfsiz siz; siz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPTXFSIZ(usb->index)); siz.s.ptxfsize = usbcx_ghwcfg3.s.dfifodepth / 4; siz.s.ptxfstaddr = 3 * usbcx_ghwcfg3.s.dfifodepth / 4; __cvmx_usb_write_csr32(usb, CVMX_USBCX_HPTXFSIZ(usb->index), siz.u32); } /* Flush all FIFOs */ - USB_SET_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), cvmx_usbcx_grstctl_t, txfnum, 0x10); - USB_SET_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), cvmx_usbcx_grstctl_t, txfflsh, 1); - CVMX_WAIT_FOR_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), cvmx_usbcx_grstctl_t, + USB_SET_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), union cvmx_usbcx_grstctl, txfnum, 0x10); + USB_SET_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), union cvmx_usbcx_grstctl, txfflsh, 1); + CVMX_WAIT_FOR_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), union cvmx_usbcx_grstctl, txfflsh, ==, 0, 100); - USB_SET_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), cvmx_usbcx_grstctl_t, rxfflsh, 1); - CVMX_WAIT_FOR_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), cvmx_usbcx_grstctl_t, + USB_SET_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), union cvmx_usbcx_grstctl, rxfflsh, 1); + CVMX_WAIT_FOR_FIELD32(CVMX_USBCX_GRSTCTL(usb->index), union cvmx_usbcx_grstctl, rxfflsh, ==, 0, 100); return 0; @@ -1019,7 +1019,7 @@ int cvmx_usb_disable(struct cvmx_usb_state *state) struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state; /* Disable the port */ - USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), cvmx_usbcx_hprt_t, prtena, 1); + USB_SET_FIELD32(CVMX_USBCX_HPRT(usb->index), union cvmx_usbcx_hprt, prtena, 1); return 0; } @@ -1040,7 +1040,7 @@ int cvmx_usb_disable(struct cvmx_usb_state *state) */ struct cvmx_usb_port_status cvmx_usb_get_status(struct cvmx_usb_state *state) { - cvmx_usbcx_hprt_t usbc_hprt; + union cvmx_usbcx_hprt usbc_hprt; struct cvmx_usb_port_status result; struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state; @@ -1261,7 +1261,7 @@ int cvmx_usb_open_pipe(struct cvmx_usb_state *state, enum cvmx_usb_pipe_flags fl */ static void __cvmx_usb_poll_rx_fifo(struct cvmx_usb_internal_state *usb) { - cvmx_usbcx_grxstsph_t rx_status; + union cvmx_usbcx_grxstsph rx_status; int channel; int bytes; uint64_t address; @@ -1365,21 +1365,21 @@ static int __cvmx_usb_fill_tx_hw(struct cvmx_usb_internal_state *usb, struct cvm static void __cvmx_usb_poll_tx_fifo(struct cvmx_usb_internal_state *usb) { if (usb->periodic.head != usb->periodic.tail) { - cvmx_usbcx_hptxsts_t tx_status; + union cvmx_usbcx_hptxsts tx_status; tx_status.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HPTXSTS(usb->index)); if (__cvmx_usb_fill_tx_hw(usb, &usb->periodic, tx_status.s.ptxfspcavail)) - USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), cvmx_usbcx_gintmsk_t, ptxfempmsk, 1); + USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), union cvmx_usbcx_gintmsk, ptxfempmsk, 1); else - USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), cvmx_usbcx_gintmsk_t, ptxfempmsk, 0); + USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), union cvmx_usbcx_gintmsk, ptxfempmsk, 0); } if (usb->nonperiodic.head != usb->nonperiodic.tail) { - cvmx_usbcx_gnptxsts_t tx_status; + union cvmx_usbcx_gnptxsts tx_status; tx_status.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_GNPTXSTS(usb->index)); if (__cvmx_usb_fill_tx_hw(usb, &usb->nonperiodic, tx_status.s.nptxfspcavail)) - USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), cvmx_usbcx_gintmsk_t, nptxfempmsk, 1); + USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), union cvmx_usbcx_gintmsk, nptxfempmsk, 1); else - USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), cvmx_usbcx_gintmsk_t, nptxfempmsk, 0); + USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), union cvmx_usbcx_gintmsk, nptxfempmsk, 0); } return; @@ -1395,9 +1395,9 @@ static void __cvmx_usb_poll_tx_fifo(struct cvmx_usb_internal_state *usb) */ static void __cvmx_usb_fill_tx_fifo(struct cvmx_usb_internal_state *usb, int channel) { - cvmx_usbcx_hccharx_t hcchar; - cvmx_usbcx_hcspltx_t usbc_hcsplt; - cvmx_usbcx_hctsizx_t usbc_hctsiz; + union cvmx_usbcx_hccharx hcchar; + union cvmx_usbcx_hcspltx usbc_hcsplt; + union cvmx_usbcx_hctsizx usbc_hctsiz; struct cvmx_usb_tx_fifo *fifo; /* We only need to fill data on outbound channels */ @@ -1452,7 +1452,7 @@ static void __cvmx_usb_start_channel_control(struct cvmx_usb_internal_state *usb cvmx_phys_to_ptr(transaction->control_header); int bytes_to_transfer = transaction->buffer_length - transaction->actual_bytes; int packets_to_transfer; - cvmx_usbcx_hctsizx_t usbc_hctsiz; + union cvmx_usbcx_hctsizx usbc_hctsiz; usbc_hctsiz.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index)); @@ -1465,7 +1465,7 @@ static void __cvmx_usb_start_channel_control(struct cvmx_usb_internal_state *usb usbc_hctsiz.s.pid = 3; /* Setup */ bytes_to_transfer = sizeof(*header); /* All Control operations start with a setup going OUT */ - USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), cvmx_usbcx_hccharx_t, epdir, CVMX_USB_DIRECTION_OUT); + USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), union cvmx_usbcx_hccharx, epdir, CVMX_USB_DIRECTION_OUT); /* * Setup send the control header instead of the buffer data. The * buffer data will be used in the next stage @@ -1476,8 +1476,8 @@ static void __cvmx_usb_start_channel_control(struct cvmx_usb_internal_state *usb usbc_hctsiz.s.pid = 3; /* Setup */ bytes_to_transfer = 0; /* All Control operations start with a setup going OUT */ - USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), cvmx_usbcx_hccharx_t, epdir, CVMX_USB_DIRECTION_OUT); - USB_SET_FIELD32(CVMX_USBCX_HCSPLTX(channel, usb->index), cvmx_usbcx_hcspltx_t, compsplt, 1); + USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), union cvmx_usbcx_hccharx, epdir, CVMX_USB_DIRECTION_OUT); + USB_SET_FIELD32(CVMX_USBCX_HCSPLTX(channel, usb->index), union cvmx_usbcx_hcspltx, compsplt, 1); break; case CVMX_USB_STAGE_DATA: usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe); @@ -1488,7 +1488,7 @@ static void __cvmx_usb_start_channel_control(struct cvmx_usb_internal_state *usb bytes_to_transfer = pipe->max_packet; } USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), - cvmx_usbcx_hccharx_t, epdir, + union cvmx_usbcx_hccharx, epdir, ((header->s.request_type & 0x80) ? CVMX_USB_DIRECTION_IN : CVMX_USB_DIRECTION_OUT)); @@ -1498,16 +1498,16 @@ static void __cvmx_usb_start_channel_control(struct cvmx_usb_internal_state *usb if (!(header->s.request_type & 0x80)) bytes_to_transfer = 0; USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), - cvmx_usbcx_hccharx_t, epdir, + union cvmx_usbcx_hccharx, epdir, ((header->s.request_type & 0x80) ? CVMX_USB_DIRECTION_IN : CVMX_USB_DIRECTION_OUT)); - USB_SET_FIELD32(CVMX_USBCX_HCSPLTX(channel, usb->index), cvmx_usbcx_hcspltx_t, compsplt, 1); + USB_SET_FIELD32(CVMX_USBCX_HCSPLTX(channel, usb->index), union cvmx_usbcx_hcspltx, compsplt, 1); break; case CVMX_USB_STAGE_STATUS: usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe); bytes_to_transfer = 0; - USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), cvmx_usbcx_hccharx_t, epdir, + USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), union cvmx_usbcx_hccharx, epdir, ((header->s.request_type & 0x80) ? CVMX_USB_DIRECTION_OUT : CVMX_USB_DIRECTION_IN)); @@ -1515,11 +1515,11 @@ static void __cvmx_usb_start_channel_control(struct cvmx_usb_internal_state *usb case CVMX_USB_STAGE_STATUS_SPLIT_COMPLETE: usbc_hctsiz.s.pid = __cvmx_usb_get_data_pid(pipe); bytes_to_transfer = 0; - USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), cvmx_usbcx_hccharx_t, epdir, + USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), union cvmx_usbcx_hccharx, epdir, ((header->s.request_type & 0x80) ? CVMX_USB_DIRECTION_OUT : CVMX_USB_DIRECTION_IN)); - USB_SET_FIELD32(CVMX_USBCX_HCSPLTX(channel, usb->index), cvmx_usbcx_hcspltx_t, compsplt, 1); + USB_SET_FIELD32(CVMX_USBCX_HCSPLTX(channel, usb->index), union cvmx_usbcx_hcspltx, compsplt, 1); break; } @@ -1592,9 +1592,9 @@ static void __cvmx_usb_start_channel(struct cvmx_usb_internal_state *usb, /* Enable the channel interrupt bits */ { - cvmx_usbcx_hcintx_t usbc_hcint; - cvmx_usbcx_hcintmskx_t usbc_hcintmsk; - cvmx_usbcx_haintmsk_t usbc_haintmsk; + union cvmx_usbcx_hcintx usbc_hcint; + union cvmx_usbcx_hcintmskx usbc_hcintmsk; + union cvmx_usbcx_haintmsk usbc_haintmsk; /* Clear all channel status bits */ usbc_hcint.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCINTX(channel, usb->index)); @@ -1636,8 +1636,8 @@ static void __cvmx_usb_start_channel(struct cvmx_usb_internal_state *usb, /* Setup both the size of the transfer and the SPLIT characteristics */ { - cvmx_usbcx_hcspltx_t usbc_hcsplt = {.u32 = 0}; - cvmx_usbcx_hctsizx_t usbc_hctsiz = {.u32 = 0}; + union cvmx_usbcx_hcspltx usbc_hcsplt = {.u32 = 0}; + union cvmx_usbcx_hctsizx usbc_hctsiz = {.u32 = 0}; int packets_to_transfer; int bytes_to_transfer = transaction->buffer_length - transaction->actual_bytes; @@ -1781,7 +1781,7 @@ static void __cvmx_usb_start_channel(struct cvmx_usb_internal_state *usb, /* Setup the Host Channel Characteristics Register */ { - cvmx_usbcx_hccharx_t usbc_hcchar = {.u32 = 0}; + union cvmx_usbcx_hccharx usbc_hcchar = {.u32 = 0}; /* * Set the startframe odd/even properly. This is only used for @@ -1830,22 +1830,22 @@ static void __cvmx_usb_start_channel(struct cvmx_usb_internal_state *usb, */ if (pipe->transfer_dir == CVMX_USB_DIRECTION_OUT) { if (pipe->multi_count < 2) /* Need DATA0 */ - USB_SET_FIELD32(CVMX_USBCX_HCTSIZX(channel, usb->index), cvmx_usbcx_hctsizx_t, pid, 0); + USB_SET_FIELD32(CVMX_USBCX_HCTSIZX(channel, usb->index), union cvmx_usbcx_hctsizx, pid, 0); else /* Need MDATA */ - USB_SET_FIELD32(CVMX_USBCX_HCTSIZX(channel, usb->index), cvmx_usbcx_hctsizx_t, pid, 3); + USB_SET_FIELD32(CVMX_USBCX_HCTSIZX(channel, usb->index), union cvmx_usbcx_hctsizx, pid, 3); } } break; } { - cvmx_usbcx_hctsizx_t usbc_hctsiz = {.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index))}; + union cvmx_usbcx_hctsizx usbc_hctsiz = {.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HCTSIZX(channel, usb->index))}; transaction->xfersize = usbc_hctsiz.s.xfersize; transaction->pktcnt = usbc_hctsiz.s.pktcnt; } /* Remeber when we start a split transaction */ if (__cvmx_usb_pipe_needs_split(usb, pipe)) usb->active_split = transaction; - USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), cvmx_usbcx_hccharx_t, chena, 1); + USB_SET_FIELD32(CVMX_USBCX_HCCHARX(channel, usb->index), union cvmx_usbcx_hccharx, chena, 1); if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) __cvmx_usb_fill_tx_fifo(usb, channel); return; @@ -1897,8 +1897,8 @@ static void __cvmx_usb_schedule(struct cvmx_usb_internal_state *usb, int is_sof) if (usb->init_flags & CVMX_USB_INITIALIZE_FLAGS_NO_DMA) { /* Without DMA we need to be careful to not schedule something at the end of a frame and cause an overrun */ - cvmx_usbcx_hfnum_t hfnum = {.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HFNUM(usb->index))}; - cvmx_usbcx_hfir_t hfir = {.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HFIR(usb->index))}; + union cvmx_usbcx_hfnum hfnum = {.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HFNUM(usb->index))}; + union cvmx_usbcx_hfir hfir = {.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HFIR(usb->index))}; if (hfnum.s.frrem < hfir.s.frint/4) goto done; } @@ -1949,7 +1949,7 @@ done: pipe = pipe->next; } } - USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), cvmx_usbcx_gintmsk_t, sofmsk, need_sof); + USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), union cvmx_usbcx_gintmsk, sofmsk, need_sof); return; } @@ -2476,7 +2476,7 @@ int cvmx_usb_cancel(struct cvmx_usb_state *state, int pipe_handle, int submit_ha */ if ((pipe->head == transaction) && (pipe->flags & __CVMX_USB_PIPE_FLAGS_SCHEDULED)) { - cvmx_usbcx_hccharx_t usbc_hcchar; + union cvmx_usbcx_hccharx usbc_hcchar; usb->pipe_for_channel[pipe->channel] = NULL; pipe->flags &= ~__CVMX_USB_PIPE_FLAGS_SCHEDULED; @@ -2607,7 +2607,7 @@ int cvmx_usb_get_frame_number(struct cvmx_usb_state *state) { int frame_number; struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state; - cvmx_usbcx_hfnum_t usbc_hfnum; + union cvmx_usbcx_hfnum usbc_hfnum; usbc_hfnum.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HFNUM(usb->index)); frame_number = usbc_hfnum.s.frnum; @@ -2626,9 +2626,9 @@ int cvmx_usb_get_frame_number(struct cvmx_usb_state *state) */ static int __cvmx_usb_poll_channel(struct cvmx_usb_internal_state *usb, int channel) { - cvmx_usbcx_hcintx_t usbc_hcint; - cvmx_usbcx_hctsizx_t usbc_hctsiz; - cvmx_usbcx_hccharx_t usbc_hcchar; + union cvmx_usbcx_hcintx usbc_hcint; + union cvmx_usbcx_hctsizx usbc_hctsiz; + union cvmx_usbcx_hccharx usbc_hcchar; struct cvmx_usb_pipe *pipe; struct cvmx_usb_transaction *transaction; int bytes_this_transfer; @@ -2658,7 +2658,7 @@ static int __cvmx_usb_poll_channel(struct cvmx_usb_internal_state *usb, int chan */ if (!usbc_hcint.s.chhltd) { if (usbc_hcchar.s.chena) { - cvmx_usbcx_hcintmskx_t hcintmsk; + union cvmx_usbcx_hcintmskx hcintmsk; /* Disable all interrupts except CHHLTD */ hcintmsk.u32 = 0; hcintmsk.s.chhltdmsk = 1; @@ -3065,8 +3065,8 @@ static int __cvmx_usb_poll_channel(struct cvmx_usb_internal_state *usb, int chan */ int cvmx_usb_poll(struct cvmx_usb_state *state) { - cvmx_usbcx_hfnum_t usbc_hfnum; - cvmx_usbcx_gintsts_t usbc_gintsts; + union cvmx_usbcx_hfnum usbc_hfnum; + union cvmx_usbcx_gintsts usbc_gintsts; struct cvmx_usb_internal_state *usb = (struct cvmx_usb_internal_state *)state; CVMX_PREFETCH(usb, 0); @@ -3105,7 +3105,7 @@ int cvmx_usb_poll(struct cvmx_usb_state *state) __cvmx_usb_poll_tx_fifo(usb); } if (usbc_gintsts.s.disconnint || usbc_gintsts.s.prtint) { - cvmx_usbcx_hprt_t usbc_hprt; + union cvmx_usbcx_hprt usbc_hprt; /* * Disconnect Detected Interrupt (DisconnInt) * Asserted when a device disconnect is detected. @@ -3141,7 +3141,7 @@ int cvmx_usb_poll(struct cvmx_usb_state *state) * must clear the appropriate status bit in the HCINTn register * to clear this bit. */ - cvmx_usbcx_haint_t usbc_haint; + union cvmx_usbcx_haint usbc_haint; usbc_haint.u32 = __cvmx_usb_read_csr32(usb, CVMX_USBCX_HAINT(usb->index)); while (usbc_haint.u32) { int channel; diff --git a/drivers/staging/octeon-usb/cvmx-usbcx-defs.h b/drivers/staging/octeon-usb/cvmx-usbcx-defs.h index 394e84662ce8..d349d77bc359 100644 --- a/drivers/staging/octeon-usb/cvmx-usbcx-defs.h +++ b/drivers/staging/octeon-usb/cvmx-usbcx-defs.h @@ -140,7 +140,6 @@ union cvmx_usbcx_gahbcfg { uint32_t glblintrmsk : 1; } s; }; -typedef union cvmx_usbcx_gahbcfg cvmx_usbcx_gahbcfg_t; /** * cvmx_usbc#_ghwcfg3 @@ -210,7 +209,6 @@ union cvmx_usbcx_ghwcfg3 { uint32_t xfersizewidth : 4; } s; }; -typedef union cvmx_usbcx_ghwcfg3 cvmx_usbcx_ghwcfg3_t; /** * cvmx_usbc#_gintmsk @@ -299,7 +297,6 @@ union cvmx_usbcx_gintmsk { uint32_t reserved_0_0 : 1; } s; }; -typedef union cvmx_usbcx_gintmsk cvmx_usbcx_gintmsk_t; /** * cvmx_usbc#_gintsts @@ -529,7 +526,6 @@ union cvmx_usbcx_gintsts { uint32_t curmod : 1; } s; }; -typedef union cvmx_usbcx_gintsts cvmx_usbcx_gintsts_t; /** * cvmx_usbc#_gnptxfsiz @@ -556,7 +552,6 @@ union cvmx_usbcx_gnptxfsiz { uint32_t nptxfstaddr : 16; } s; }; -typedef union cvmx_usbcx_gnptxfsiz cvmx_usbcx_gnptxfsiz_t; /** * cvmx_usbc#_gnptxsts @@ -609,7 +604,6 @@ union cvmx_usbcx_gnptxsts { uint32_t nptxfspcavail : 16; } s; }; -typedef union cvmx_usbcx_gnptxsts cvmx_usbcx_gnptxsts_t; /** * cvmx_usbc#_grstctl @@ -737,7 +731,6 @@ union cvmx_usbcx_grstctl { uint32_t csftrst : 1; } s; }; -typedef union cvmx_usbcx_grstctl cvmx_usbcx_grstctl_t; /** * cvmx_usbc#_grxfsiz @@ -761,7 +754,6 @@ union cvmx_usbcx_grxfsiz { uint32_t rxfdep : 16; } s; }; -typedef union cvmx_usbcx_grxfsiz cvmx_usbcx_grxfsiz_t; /** * cvmx_usbc#_grxstsph @@ -807,7 +799,6 @@ union cvmx_usbcx_grxstsph { uint32_t chnum : 4; } s; }; -typedef union cvmx_usbcx_grxstsph cvmx_usbcx_grxstsph_t; /** * cvmx_usbc#_gusbcfg @@ -896,7 +887,6 @@ union cvmx_usbcx_gusbcfg { uint32_t toutcal : 3; } s; }; -typedef union cvmx_usbcx_gusbcfg cvmx_usbcx_gusbcfg_t; /** * cvmx_usbc#_haint @@ -922,7 +912,6 @@ union cvmx_usbcx_haint { uint32_t haint : 16; } s; }; -typedef union cvmx_usbcx_haint cvmx_usbcx_haint_t; /** * cvmx_usbc#_haintmsk @@ -947,7 +936,6 @@ union cvmx_usbcx_haintmsk { uint32_t haintmsk : 16; } s; }; -typedef union cvmx_usbcx_haintmsk cvmx_usbcx_haintmsk_t; /** * cvmx_usbc#_hcchar# @@ -1027,7 +1015,6 @@ union cvmx_usbcx_hccharx { uint32_t mps : 11; } s; }; -typedef union cvmx_usbcx_hccharx cvmx_usbcx_hccharx_t; /** * cvmx_usbc#_hcfg @@ -1075,7 +1062,6 @@ union cvmx_usbcx_hcfg { uint32_t fslspclksel : 2; } s; }; -typedef union cvmx_usbcx_hcfg cvmx_usbcx_hcfg_t; /** * cvmx_usbc#_hcint# @@ -1126,7 +1112,6 @@ union cvmx_usbcx_hcintx { uint32_t xfercompl : 1; } s; }; -typedef union cvmx_usbcx_hcintx cvmx_usbcx_hcintx_t; /** * cvmx_usbc#_hcintmsk# @@ -1168,7 +1153,6 @@ union cvmx_usbcx_hcintmskx { uint32_t xfercomplmsk : 1; } s; }; -typedef union cvmx_usbcx_hcintmskx cvmx_usbcx_hcintmskx_t; /** * cvmx_usbc#_hcsplt# @@ -1213,7 +1197,6 @@ union cvmx_usbcx_hcspltx { uint32_t prtaddr : 7; } s; }; -typedef union cvmx_usbcx_hcspltx cvmx_usbcx_hcspltx_t; /** * cvmx_usbc#_hctsiz# @@ -1257,7 +1240,6 @@ union cvmx_usbcx_hctsizx { uint32_t xfersize : 19; } s; }; -typedef union cvmx_usbcx_hctsizx cvmx_usbcx_hctsizx_t; /** * cvmx_usbc#_hfir @@ -1293,7 +1275,6 @@ union cvmx_usbcx_hfir { uint32_t frint : 16; } s; }; -typedef union cvmx_usbcx_hfir cvmx_usbcx_hfir_t; /** * cvmx_usbc#_hfnum @@ -1323,7 +1304,6 @@ union cvmx_usbcx_hfnum { uint32_t frnum : 16; } s; }; -typedef union cvmx_usbcx_hfnum cvmx_usbcx_hfnum_t; /** * cvmx_usbc#_hprt @@ -1464,7 +1444,6 @@ union cvmx_usbcx_hprt { uint32_t prtconnsts : 1; } s; }; -typedef union cvmx_usbcx_hprt cvmx_usbcx_hprt_t; /** * cvmx_usbc#_hptxfsiz @@ -1489,7 +1468,6 @@ union cvmx_usbcx_hptxfsiz { uint32_t ptxfstaddr : 16; } s; }; -typedef union cvmx_usbcx_hptxfsiz cvmx_usbcx_hptxfsiz_t; /** * cvmx_usbc#_hptxsts @@ -1546,6 +1524,5 @@ union cvmx_usbcx_hptxsts { uint32_t ptxfspcavail : 16; } s; }; -typedef union cvmx_usbcx_hptxsts cvmx_usbcx_hptxsts_t; #endif diff --git a/drivers/staging/octeon-usb/cvmx-usbnx-defs.h b/drivers/staging/octeon-usb/cvmx-usbnx-defs.h index 96d706770fc6..e06aafa5726a 100644 --- a/drivers/staging/octeon-usb/cvmx-usbnx-defs.h +++ b/drivers/staging/octeon-usb/cvmx-usbnx-defs.h @@ -337,7 +337,6 @@ union cvmx_usbnx_clk_ctl { struct cvmx_usbnx_clk_ctl_cn50xx cn52xx; struct cvmx_usbnx_clk_ctl_cn50xx cn56xx; }; -typedef union cvmx_usbnx_clk_ctl cvmx_usbnx_clk_ctl_t; /** * cvmx_usbn#_usbp_ctl_status @@ -882,6 +881,5 @@ union cvmx_usbnx_usbp_ctl_status { uint64_t ate_reset : 1; } cn52xx; }; -typedef union cvmx_usbnx_usbp_ctl_status cvmx_usbnx_usbp_ctl_status_t; #endif From d4f09e28d7bc5c1adde8229b1e89401f23fb44f9 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 30 Jul 2013 19:59:40 +0900 Subject: [PATCH 1270/3400] USB: host: use dev_get_platdata() Use the wrapper function for retrieving the platform data instead of accessing dev->platform_data directly. Signed-off-by: Jingoo Han Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-fsl.c | 14 +++++++------- drivers/usb/host/ehci-mv.c | 2 +- drivers/usb/host/ehci-mxc.c | 4 ++-- drivers/usb/host/ehci-omap.c | 4 ++-- drivers/usb/host/ehci-orion.c | 2 +- drivers/usb/host/ehci-platform.c | 12 ++++++------ drivers/usb/host/ehci-s5p.c | 2 +- drivers/usb/host/ehci-sh.c | 2 +- drivers/usb/host/ehci-tegra.c | 2 +- drivers/usb/host/ehci-tilegx.c | 4 ++-- drivers/usb/host/fsl-mph-dr-of.c | 4 ++-- drivers/usb/host/imx21-hcd.c | 2 +- drivers/usb/host/isp116x-hcd.c | 2 +- drivers/usb/host/isp1362-hcd.c | 2 +- drivers/usb/host/isp1760-if.c | 2 +- drivers/usb/host/ohci-at91.c | 12 ++++++------ drivers/usb/host/ohci-da8xx.c | 8 ++++---- drivers/usb/host/ohci-exynos.c | 2 +- drivers/usb/host/ohci-omap.c | 4 ++-- drivers/usb/host/ohci-platform.c | 10 +++++----- drivers/usb/host/ohci-pxa27x.c | 8 ++++---- drivers/usb/host/ohci-s3c2410.c | 11 ++++++----- drivers/usb/host/ohci-tilegx.c | 4 ++-- drivers/usb/host/r8a66597-hcd.c | 2 +- drivers/usb/host/sl811-hcd.c | 2 +- drivers/usb/host/u132-hcd.c | 6 +++--- 26 files changed, 65 insertions(+), 64 deletions(-) diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index bd831ec06dcd..45eee6e9c6c8 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -57,7 +57,7 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver, pr_debug("initializing FSL-SOC USB Controller\n"); /* Need platform data for setup */ - pdata = (struct fsl_usb2_platform_data *)pdev->dev.platform_data; + pdata = (struct fsl_usb2_platform_data *)dev_get_platdata(&pdev->dev); if (!pdata) { dev_err(&pdev->dev, "No platform data for %s.\n", dev_name(&pdev->dev)); @@ -190,7 +190,7 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver, static void usb_hcd_fsl_remove(struct usb_hcd *hcd, struct platform_device *pdev) { - struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; + struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev); if (!IS_ERR_OR_NULL(hcd->phy)) { otg_set_host(hcd->phy->otg, NULL); @@ -218,7 +218,7 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd, struct ehci_hcd *ehci = hcd_to_ehci(hcd); void __iomem *non_ehci = hcd->regs; struct device *dev = hcd->self.controller; - struct fsl_usb2_platform_data *pdata = dev->platform_data; + struct fsl_usb2_platform_data *pdata = dev_get_platdata(dev); if (pdata->controller_ver < 0) { dev_warn(hcd->self.controller, "Could not get controller version\n"); @@ -291,7 +291,7 @@ static int ehci_fsl_usb_setup(struct ehci_hcd *ehci) struct fsl_usb2_platform_data *pdata; void __iomem *non_ehci = hcd->regs; - pdata = hcd->self.controller->platform_data; + pdata = dev_get_platdata(hcd->self.controller); if (pdata->have_sysif_regs) { /* @@ -363,7 +363,7 @@ static int ehci_fsl_setup(struct usb_hcd *hcd) struct device *dev; dev = hcd->self.controller; - pdata = hcd->self.controller->platform_data; + pdata = dev_get_platdata(hcd->self.controller); ehci->big_endian_desc = pdata->big_endian_desc; ehci->big_endian_mmio = pdata->big_endian_mmio; @@ -415,7 +415,7 @@ static int ehci_fsl_mpc512x_drv_suspend(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct ehci_hcd *ehci = hcd_to_ehci(hcd); - struct fsl_usb2_platform_data *pdata = dev->platform_data; + struct fsl_usb2_platform_data *pdata = dev_get_platdata(dev); u32 tmp; #ifdef DEBUG @@ -484,7 +484,7 @@ static int ehci_fsl_mpc512x_drv_resume(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct ehci_hcd *ehci = hcd_to_ehci(hcd); - struct fsl_usb2_platform_data *pdata = dev->platform_data; + struct fsl_usb2_platform_data *pdata = dev_get_platdata(dev); u32 tmp; dev_dbg(dev, "suspend=%d already_suspended=%d\n", diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c index 915c2db96dce..35cdbd88bbbe 100644 --- a/drivers/usb/host/ehci-mv.c +++ b/drivers/usb/host/ehci-mv.c @@ -131,7 +131,7 @@ static const struct hc_driver mv_ehci_hc_driver = { static int mv_ehci_probe(struct platform_device *pdev) { - struct mv_usb_platform_data *pdata = pdev->dev.platform_data; + struct mv_usb_platform_data *pdata = dev_get_platdata(&pdev->dev); struct usb_hcd *hcd; struct ehci_hcd *ehci; struct ehci_hcd_mv *ehci_mv; diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c index 030b53958845..5899ad6626c7 100644 --- a/drivers/usb/host/ehci-mxc.c +++ b/drivers/usb/host/ehci-mxc.c @@ -49,7 +49,7 @@ static const struct ehci_driver_overrides ehci_mxc_overrides __initconst = { static int ehci_mxc_drv_probe(struct platform_device *pdev) { - struct mxc_usbh_platform_data *pdata = pdev->dev.platform_data; + struct mxc_usbh_platform_data *pdata = dev_get_platdata(&pdev->dev); struct usb_hcd *hcd; struct resource *res; int irq, ret; @@ -174,7 +174,7 @@ err_alloc: static int ehci_mxc_drv_remove(struct platform_device *pdev) { - struct mxc_usbh_platform_data *pdata = pdev->dev.platform_data; + struct mxc_usbh_platform_data *pdata = dev_get_platdata(&pdev->dev); struct usb_hcd *hcd = platform_get_drvdata(pdev); struct ehci_hcd *ehci = hcd_to_ehci(hcd); struct ehci_mxc_priv *priv = (struct ehci_mxc_priv *) ehci->priv; diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index 4384d07115d1..78b01fa475bb 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -100,7 +100,7 @@ static const struct ehci_driver_overrides ehci_omap_overrides __initdata = { static int ehci_hcd_omap_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct usbhs_omap_platform_data *pdata = dev->platform_data; + struct usbhs_omap_platform_data *pdata = dev_get_platdata(dev); struct resource *res; struct usb_hcd *hcd; void __iomem *regs; @@ -119,7 +119,7 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) /* For DT boot, get platform data from parent. i.e. usbhshost */ if (dev->of_node) { - pdata = dev->parent->platform_data; + pdata = dev_get_platdata(dev->parent); dev->platform_data = pdata; } diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c index 1a450aa13ebf..d1dfb9db5b42 100644 --- a/drivers/usb/host/ehci-orion.c +++ b/drivers/usb/host/ehci-orion.c @@ -139,7 +139,7 @@ ehci_orion_conf_mbus_windows(struct usb_hcd *hcd, static int ehci_orion_drv_probe(struct platform_device *pdev) { - struct orion_ehci_data *pd = pdev->dev.platform_data; + struct orion_ehci_data *pd = dev_get_platdata(&pdev->dev); const struct mbus_dram_target_info *dram; struct resource *res; struct usb_hcd *hcd; diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c index 5196d728517d..f6b790ca8cf2 100644 --- a/drivers/usb/host/ehci-platform.c +++ b/drivers/usb/host/ehci-platform.c @@ -39,7 +39,7 @@ static const char hcd_name[] = "ehci-platform"; static int ehci_platform_reset(struct usb_hcd *hcd) { struct platform_device *pdev = to_platform_device(hcd->self.controller); - struct usb_ehci_pdata *pdata = pdev->dev.platform_data; + struct usb_ehci_pdata *pdata = dev_get_platdata(&pdev->dev); struct ehci_hcd *ehci = hcd_to_ehci(hcd); int retval; @@ -87,14 +87,14 @@ static int ehci_platform_probe(struct platform_device *dev) * use reasonable defaults so platforms don't have to provide these. * with DT probing on ARM, none of these are set. */ - if (!dev->dev.platform_data) + if (!dev_get_platdata(&dev->dev)) dev->dev.platform_data = &ehci_platform_defaults; if (!dev->dev.dma_mask) dev->dev.dma_mask = &dev->dev.coherent_dma_mask; if (!dev->dev.coherent_dma_mask) dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); - pdata = dev->dev.platform_data; + pdata = dev_get_platdata(&dev->dev); irq = platform_get_irq(dev, 0); if (irq < 0) { @@ -148,7 +148,7 @@ err_power: static int ehci_platform_remove(struct platform_device *dev) { struct usb_hcd *hcd = platform_get_drvdata(dev); - struct usb_ehci_pdata *pdata = dev->dev.platform_data; + struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev); usb_remove_hcd(hcd); usb_put_hcd(hcd); @@ -167,7 +167,7 @@ static int ehci_platform_remove(struct platform_device *dev) static int ehci_platform_suspend(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); - struct usb_ehci_pdata *pdata = dev->platform_data; + struct usb_ehci_pdata *pdata = dev_get_platdata(dev); struct platform_device *pdev = container_of(dev, struct platform_device, dev); bool do_wakeup = device_may_wakeup(dev); @@ -184,7 +184,7 @@ static int ehci_platform_suspend(struct device *dev) static int ehci_platform_resume(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); - struct usb_ehci_pdata *pdata = dev->platform_data; + struct usb_ehci_pdata *pdata = dev_get_platdata(dev); struct platform_device *pdev = container_of(dev, struct platform_device, dev); diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c index aba645bd4866..7c3de95c7054 100644 --- a/drivers/usb/host/ehci-s5p.c +++ b/drivers/usb/host/ehci-s5p.c @@ -75,7 +75,7 @@ static void s5p_setup_vbus_gpio(struct platform_device *pdev) static int s5p_ehci_probe(struct platform_device *pdev) { - struct s5p_ehci_platdata *pdata = pdev->dev.platform_data; + struct s5p_ehci_platdata *pdata = dev_get_platdata(&pdev->dev); struct s5p_ehci_hcd *s5p_ehci; struct usb_hcd *hcd; struct ehci_hcd *ehci; diff --git a/drivers/usb/host/ehci-sh.c b/drivers/usb/host/ehci-sh.c index c4c0ee92a397..93e59a13bc1f 100644 --- a/drivers/usb/host/ehci-sh.c +++ b/drivers/usb/host/ehci-sh.c @@ -104,7 +104,7 @@ static int ehci_hcd_sh_probe(struct platform_device *pdev) goto fail_create_hcd; } - pdata = pdev->dev.platform_data; + pdata = dev_get_platdata(&pdev->dev); /* initialize hcd */ hcd = usb_create_hcd(&ehci_sh_hc_driver, &pdev->dev, diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index 6ee7ef79b4f8..5cd33cf783da 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -361,7 +361,7 @@ static int tegra_ehci_probe(struct platform_device *pdev) struct device_node *np_phy; struct usb_phy *u_phy; - pdata = pdev->dev.platform_data; + pdata = dev_get_platdata(&pdev->dev); if (!pdata) { dev_err(&pdev->dev, "Platform data missing\n"); return -EINVAL; diff --git a/drivers/usb/host/ehci-tilegx.c b/drivers/usb/host/ehci-tilegx.c index d72b2929c03d..cca4be90a864 100644 --- a/drivers/usb/host/ehci-tilegx.c +++ b/drivers/usb/host/ehci-tilegx.c @@ -101,7 +101,7 @@ static int ehci_hcd_tilegx_drv_probe(struct platform_device *pdev) { struct usb_hcd *hcd; struct ehci_hcd *ehci; - struct tilegx_usb_platform_data *pdata = pdev->dev.platform_data; + struct tilegx_usb_platform_data *pdata = dev_get_platdata(&pdev->dev); pte_t pte = { 0 }; int my_cpu = smp_processor_id(); int ret; @@ -186,7 +186,7 @@ err_hcd: static int ehci_hcd_tilegx_drv_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); - struct tilegx_usb_platform_data *pdata = pdev->dev.platform_data; + struct tilegx_usb_platform_data *pdata = dev_get_platdata(&pdev->dev); usb_remove_hcd(hcd); usb_put_hcd(hcd); diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c index 11e0b79ff9d5..cfbff7161828 100644 --- a/drivers/usb/host/fsl-mph-dr-of.c +++ b/drivers/usb/host/fsl-mph-dr-of.c @@ -258,7 +258,7 @@ static int fsl_usb2_mph_dr_of_remove(struct platform_device *ofdev) int fsl_usb2_mpc5121_init(struct platform_device *pdev) { - struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; + struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev); struct clk *clk; char clk_name[10]; int base, clk_num; @@ -298,7 +298,7 @@ int fsl_usb2_mpc5121_init(struct platform_device *pdev) static void fsl_usb2_mpc5121_exit(struct platform_device *pdev) { - struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; + struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev); pdata->regs = NULL; diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c index 03dc4d9cbeca..60a5de505ca1 100644 --- a/drivers/usb/host/imx21-hcd.c +++ b/drivers/usb/host/imx21-hcd.c @@ -1860,7 +1860,7 @@ static int imx21_probe(struct platform_device *pdev) imx21 = hcd_to_imx21(hcd); imx21->hcd = hcd; imx21->dev = &pdev->dev; - imx21->pdata = pdev->dev.platform_data; + imx21->pdata = dev_get_platdata(&pdev->dev); if (!imx21->pdata) imx21->pdata = &default_pdata; diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index b64e661618bb..c7d0f8f231be 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c @@ -1626,7 +1626,7 @@ static int isp116x_probe(struct platform_device *pdev) isp116x->addr_reg = addr_reg; spin_lock_init(&isp116x->lock); INIT_LIST_HEAD(&isp116x->async); - isp116x->board = pdev->dev.platform_data; + isp116x->board = dev_get_platdata(&pdev->dev); if (!isp116x->board) { ERR("Platform data structure not initialized\n"); diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c index c15463b898e2..6f29abad6815 100644 --- a/drivers/usb/host/isp1362-hcd.c +++ b/drivers/usb/host/isp1362-hcd.c @@ -2725,7 +2725,7 @@ static int isp1362_probe(struct platform_device *pdev) INIT_LIST_HEAD(&isp1362_hcd->periodic); INIT_LIST_HEAD(&isp1362_hcd->isoc); INIT_LIST_HEAD(&isp1362_hcd->remove_list); - isp1362_hcd->board = pdev->dev.platform_data; + isp1362_hcd->board = dev_get_platdata(&pdev->dev); #if USE_PLATFORM_DELAY if (!isp1362_hcd->board->delay) { dev_err(hcd->self.controller, "No platform delay function given\n"); diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index 3df49b169b53..df931e9ba5b5 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c @@ -351,7 +351,7 @@ static int isp1760_plat_probe(struct platform_device *pdev) struct resource *mem_res; struct resource *irq_res; resource_size_t mem_size; - struct isp1760_platform_data *priv = pdev->dev.platform_data; + struct isp1760_platform_data *priv = dev_get_platdata(&pdev->dev); unsigned int devflags = 0; unsigned long irqflags = IRQF_SHARED; diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 9677f6831209..a87564559e03 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -225,7 +225,7 @@ static void usb_hcd_at91_remove(struct usb_hcd *hcd, static int ohci_at91_reset (struct usb_hcd *hcd) { - struct at91_usbh_data *board = hcd->self.controller->platform_data; + struct at91_usbh_data *board = dev_get_platdata(hcd->self.controller); struct ohci_hcd *ohci = hcd_to_ohci (hcd); int ret; @@ -280,7 +280,7 @@ static int ohci_at91_usb_get_power(struct at91_usbh_data *pdata, int port) */ static int ohci_at91_hub_status_data(struct usb_hcd *hcd, char *buf) { - struct at91_usbh_data *pdata = hcd->self.controller->platform_data; + struct at91_usbh_data *pdata = dev_get_platdata(hcd->self.controller); int length = ohci_hub_status_data(hcd, buf); int port; @@ -301,7 +301,7 @@ static int ohci_at91_hub_status_data(struct usb_hcd *hcd, char *buf) static int ohci_at91_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength) { - struct at91_usbh_data *pdata = hcd->self.controller->platform_data; + struct at91_usbh_data *pdata = dev_get_platdata(hcd->self.controller); struct usb_hub_descriptor *desc; int ret = -EINVAL; u32 *data = (u32 *)buf; @@ -461,7 +461,7 @@ static const struct hc_driver ohci_at91_hc_driver = { static irqreturn_t ohci_hcd_at91_overcurrent_irq(int irq, void *data) { struct platform_device *pdev = data; - struct at91_usbh_data *pdata = pdev->dev.platform_data; + struct at91_usbh_data *pdata = dev_get_platdata(&pdev->dev); int val, gpio, port; /* From the GPIO notifying the over-current situation, find @@ -567,7 +567,7 @@ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev) if (ret) return ret; - pdata = pdev->dev.platform_data; + pdata = dev_get_platdata(&pdev->dev); if (pdata) { at91_for_each_port(i) { @@ -643,7 +643,7 @@ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev) static int ohci_hcd_at91_drv_remove(struct platform_device *pdev) { - struct at91_usbh_data *pdata = pdev->dev.platform_data; + struct at91_usbh_data *pdata = dev_get_platdata(&pdev->dev); int i; if (pdata) { diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c index 6aaa9c9c8eb0..9be59f11e051 100644 --- a/drivers/usb/host/ohci-da8xx.c +++ b/drivers/usb/host/ohci-da8xx.c @@ -85,7 +85,7 @@ static void ohci_da8xx_ocic_handler(struct da8xx_ohci_root_hub *hub, static int ohci_da8xx_init(struct usb_hcd *hcd) { struct device *dev = hcd->self.controller; - struct da8xx_ohci_root_hub *hub = dev->platform_data; + struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev); struct ohci_hcd *ohci = hcd_to_ohci(hcd); int result; u32 rh_a; @@ -171,7 +171,7 @@ static int ohci_da8xx_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength) { struct device *dev = hcd->self.controller; - struct da8xx_ohci_root_hub *hub = dev->platform_data; + struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev); int temp; switch (typeReq) { @@ -292,7 +292,7 @@ static const struct hc_driver ohci_da8xx_hc_driver = { static int usb_hcd_da8xx_probe(const struct hc_driver *driver, struct platform_device *pdev) { - struct da8xx_ohci_root_hub *hub = pdev->dev.platform_data; + struct da8xx_ohci_root_hub *hub = dev_get_platdata(&pdev->dev); struct usb_hcd *hcd; struct resource *mem; int error, irq; @@ -380,7 +380,7 @@ err0: static inline void usb_hcd_da8xx_remove(struct usb_hcd *hcd, struct platform_device *pdev) { - struct da8xx_ohci_root_hub *hub = pdev->dev.platform_data; + struct da8xx_ohci_root_hub *hub = dev_get_platdata(&pdev->dev); hub->ocic_notify(NULL); usb_remove_hcd(hcd); diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c index b0b542c14e31..dc6ee9adacf5 100644 --- a/drivers/usb/host/ohci-exynos.c +++ b/drivers/usb/host/ohci-exynos.c @@ -100,7 +100,7 @@ static const struct hc_driver exynos_ohci_hc_driver = { static int exynos_ohci_probe(struct platform_device *pdev) { - struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data; + struct exynos4_ohci_platdata *pdata = dev_get_platdata(&pdev->dev); struct exynos_ohci_hcd *exynos_ohci; struct usb_hcd *hcd; struct ohci_hcd *ohci; diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index 8747fa6a51b7..31d3a12eb486 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c @@ -191,7 +191,7 @@ static void start_hnp(struct ohci_hcd *ohci) static int ohci_omap_init(struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci(hcd); - struct omap_usb_config *config = hcd->self.controller->platform_data; + struct omap_usb_config *config = dev_get_platdata(hcd->self.controller); int need_transceiver = (config->otg != 0); int ret; @@ -427,7 +427,7 @@ ohci_omap_start (struct usb_hcd *hcd) if (!host_enabled) return 0; - config = hcd->self.controller->platform_data; + config = dev_get_platdata(hcd->self.controller); if (config->otg || config->rwc) { ohci->hc_control = OHCI_CTRL_RWC; writel(OHCI_CTRL_RWC, &ohci->regs->control); diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c index bc30475c3a23..a4c6410f0ed4 100644 --- a/drivers/usb/host/ohci-platform.c +++ b/drivers/usb/host/ohci-platform.c @@ -33,7 +33,7 @@ static const char hcd_name[] = "ohci-platform"; static int ohci_platform_reset(struct usb_hcd *hcd) { struct platform_device *pdev = to_platform_device(hcd->self.controller); - struct usb_ohci_pdata *pdata = pdev->dev.platform_data; + struct usb_ohci_pdata *pdata = dev_get_platdata(&pdev->dev); struct ohci_hcd *ohci = hcd_to_ohci(hcd); if (pdata->big_endian_desc) @@ -59,7 +59,7 @@ static int ohci_platform_probe(struct platform_device *dev) { struct usb_hcd *hcd; struct resource *res_mem; - struct usb_ohci_pdata *pdata = dev->dev.platform_data; + struct usb_ohci_pdata *pdata = dev_get_platdata(&dev->dev); int irq; int err = -ENOMEM; @@ -124,7 +124,7 @@ err_power: static int ohci_platform_remove(struct platform_device *dev) { struct usb_hcd *hcd = platform_get_drvdata(dev); - struct usb_ohci_pdata *pdata = dev->dev.platform_data; + struct usb_ohci_pdata *pdata = dev_get_platdata(&dev->dev); usb_remove_hcd(hcd); usb_put_hcd(hcd); @@ -139,7 +139,7 @@ static int ohci_platform_remove(struct platform_device *dev) static int ohci_platform_suspend(struct device *dev) { - struct usb_ohci_pdata *pdata = dev->platform_data; + struct usb_ohci_pdata *pdata = dev_get_platdata(dev); struct platform_device *pdev = container_of(dev, struct platform_device, dev); @@ -152,7 +152,7 @@ static int ohci_platform_suspend(struct device *dev) static int ohci_platform_resume(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); - struct usb_ohci_pdata *pdata = dev->platform_data; + struct usb_ohci_pdata *pdata = dev_get_platdata(dev); struct platform_device *pdev = container_of(dev, struct platform_device, dev); diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index 3a9c01d8b79c..93371a235e82 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c @@ -219,7 +219,7 @@ static int pxa27x_start_hc(struct pxa27x_ohci *ohci, struct device *dev) struct pxaohci_platform_data *inf; uint32_t uhchr; - inf = dev->platform_data; + inf = dev_get_platdata(dev); clk_prepare_enable(ohci->clk); @@ -256,7 +256,7 @@ static void pxa27x_stop_hc(struct pxa27x_ohci *ohci, struct device *dev) struct pxaohci_platform_data *inf; uint32_t uhccoms; - inf = dev->platform_data; + inf = dev_get_platdata(dev); if (cpu_is_pxa3xx()) pxa3xx_u2d_stop_hc(&ohci_to_hcd(&ohci->ohci)->self); @@ -364,7 +364,7 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device if (retval) return retval; - inf = pdev->dev.platform_data; + inf = dev_get_platdata(&pdev->dev); if (!inf) return -ENODEV; @@ -577,7 +577,7 @@ static int ohci_hcd_pxa27x_drv_resume(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct pxa27x_ohci *ohci = to_pxa27x_ohci(hcd); - struct pxaohci_platform_data *inf = dev->platform_data; + struct pxaohci_platform_data *inf = dev_get_platdata(dev); int status; if (time_before(jiffies, ohci->ohci.next_statechange)) diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c index e125770b893c..4919afa4125e 100644 --- a/drivers/usb/host/ohci-s3c2410.c +++ b/drivers/usb/host/ohci-s3c2410.c @@ -38,12 +38,12 @@ static void s3c2410_hcd_oc(struct s3c2410_hcd_info *info, int port_oc); static struct s3c2410_hcd_info *to_s3c2410_info(struct usb_hcd *hcd) { - return hcd->self.controller->platform_data; + return dev_get_platdata(hcd->self.controller); } static void s3c2410_start_hc(struct platform_device *dev, struct usb_hcd *hcd) { - struct s3c2410_hcd_info *info = dev->dev.platform_data; + struct s3c2410_hcd_info *info = dev_get_platdata(&dev->dev); dev_dbg(&dev->dev, "s3c2410_start_hc:\n"); @@ -63,7 +63,7 @@ static void s3c2410_start_hc(struct platform_device *dev, struct usb_hcd *hcd) static void s3c2410_stop_hc(struct platform_device *dev) { - struct s3c2410_hcd_info *info = dev->dev.platform_data; + struct s3c2410_hcd_info *info = dev_get_platdata(&dev->dev); dev_dbg(&dev->dev, "s3c2410_stop_hc:\n"); @@ -339,10 +339,11 @@ static int usb_hcd_s3c2410_probe(const struct hc_driver *driver, struct platform_device *dev) { struct usb_hcd *hcd = NULL; + struct s3c2410_hcd_info *info = dev_get_platdata(&dev->dev); int retval; - s3c2410_usb_set_power(dev->dev.platform_data, 1, 1); - s3c2410_usb_set_power(dev->dev.platform_data, 2, 1); + s3c2410_usb_set_power(info, 1, 1); + s3c2410_usb_set_power(info, 2, 1); hcd = usb_create_hcd(driver, &dev->dev, "s3c24xx"); if (hcd == NULL) diff --git a/drivers/usb/host/ohci-tilegx.c b/drivers/usb/host/ohci-tilegx.c index 197d514fe0d1..22540ab71f55 100644 --- a/drivers/usb/host/ohci-tilegx.c +++ b/drivers/usb/host/ohci-tilegx.c @@ -95,7 +95,7 @@ static const struct hc_driver ohci_tilegx_hc_driver = { static int ohci_hcd_tilegx_drv_probe(struct platform_device *pdev) { struct usb_hcd *hcd; - struct tilegx_usb_platform_data *pdata = pdev->dev.platform_data; + struct tilegx_usb_platform_data *pdata = dev_get_platdata(&pdev->dev); pte_t pte = { 0 }; int my_cpu = smp_processor_id(); int ret; @@ -175,7 +175,7 @@ err_hcd: static int ohci_hcd_tilegx_drv_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); - struct tilegx_usb_platform_data* pdata = pdev->dev.platform_data; + struct tilegx_usb_platform_data *pdata = dev_get_platdata(&pdev->dev); usb_remove_hcd(hcd); usb_put_hcd(hcd); diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index a6fd8f5371df..a9eef6822a24 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -2467,7 +2467,7 @@ static int r8a66597_probe(struct platform_device *pdev) r8a66597 = hcd_to_r8a66597(hcd); memset(r8a66597, 0, sizeof(struct r8a66597)); dev_set_drvdata(&pdev->dev, r8a66597); - r8a66597->pdata = pdev->dev.platform_data; + r8a66597->pdata = dev_get_platdata(&pdev->dev); r8a66597->irq_sense_low = irq_trigger == IRQF_TRIGGER_LOW; if (r8a66597->pdata->on_chip) { diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index d8938630e092..5477bf5df218 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c @@ -1691,7 +1691,7 @@ sl811h_probe(struct platform_device *dev) spin_lock_init(&sl811->lock); INIT_LIST_HEAD(&sl811->async); - sl811->board = dev->dev.platform_data; + sl811->board = dev_get_platdata(&dev->dev); init_timer(&sl811->timer); sl811->timer.function = sl811h_timer; sl811->timer.data = (unsigned long) sl811; diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index 5c124bf5d018..e402beb5a069 100644 --- a/drivers/usb/host/u132-hcd.c +++ b/drivers/usb/host/u132-hcd.c @@ -1809,9 +1809,9 @@ static int u132_hcd_start(struct usb_hcd *hcd) struct platform_device *pdev = to_platform_device(hcd->self.controller); u16 vendor = ((struct u132_platform_data *) - (pdev->dev.platform_data))->vendor; + dev_get_platdata(&pdev->dev))->vendor; u16 device = ((struct u132_platform_data *) - (pdev->dev.platform_data))->device; + dev_get_platdata(&pdev->dev))->device; mutex_lock(&u132->sw_lock); msleep(10); if (vendor == PCI_VENDOR_ID_AMD && device == 0x740c) { @@ -3034,7 +3034,7 @@ static void u132_initialise(struct u132 *u132, struct platform_device *pdev) int addrs = MAX_U132_ADDRS; int udevs = MAX_U132_UDEVS; int endps = MAX_U132_ENDPS; - u132->board = pdev->dev.platform_data; + u132->board = dev_get_platdata(&pdev->dev); u132->platform_dev = pdev; u132->power = 0; u132->reset = 0; From 574de559c1797618fd8ed03576837eb3113c5d26 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Tue, 30 Jul 2013 17:06:57 +0900 Subject: [PATCH 1271/3400] serial: use dev_get_platdata() Use the wrapper function for retrieving the platform data instead of accessing dev->platform_data directly. Signed-off-by: Jingoo Han Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_core.c | 2 +- drivers/tty/serial/altera_jtaguart.c | 3 ++- drivers/tty/serial/altera_uart.c | 2 +- drivers/tty/serial/amba-pl010.c | 2 +- drivers/tty/serial/amba-pl011.c | 14 +++++++------- drivers/tty/serial/ar933x_uart.c | 2 +- drivers/tty/serial/arc_uart.c | 2 +- drivers/tty/serial/atmel_serial.c | 10 +++++----- drivers/tty/serial/bfin_sport_uart.c | 7 ++++--- drivers/tty/serial/bfin_uart.c | 11 ++++++----- drivers/tty/serial/ifx6x60.c | 2 +- drivers/tty/serial/imx.c | 10 +++++----- drivers/tty/serial/max3100.c | 2 +- drivers/tty/serial/mcf.c | 3 ++- drivers/tty/serial/mpsc.c | 4 ++-- drivers/tty/serial/msm_serial_hs.c | 2 +- drivers/tty/serial/omap-serial.c | 6 +++--- drivers/tty/serial/samsung.c | 4 ++-- drivers/tty/serial/sc26xx.c | 2 +- drivers/tty/serial/serial_txx9.c | 2 +- drivers/tty/serial/sh-sci.c | 2 +- drivers/tty/serial/vr41xx_siu.c | 2 +- 22 files changed, 50 insertions(+), 46 deletions(-) diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 86c00b1c5583..570df9d2a5d2 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -3062,7 +3062,7 @@ void serial8250_resume_port(int line) */ static int serial8250_probe(struct platform_device *dev) { - struct plat_serial8250_port *p = dev->dev.platform_data; + struct plat_serial8250_port *p = dev_get_platdata(&dev->dev); struct uart_8250_port uart; int ret, i, irqflag = 0; diff --git a/drivers/tty/serial/altera_jtaguart.c b/drivers/tty/serial/altera_jtaguart.c index c6bdb943726b..2299a34225d4 100644 --- a/drivers/tty/serial/altera_jtaguart.c +++ b/drivers/tty/serial/altera_jtaguart.c @@ -408,7 +408,8 @@ static struct uart_driver altera_jtaguart_driver = { static int altera_jtaguart_probe(struct platform_device *pdev) { - struct altera_jtaguart_platform_uart *platp = pdev->dev.platform_data; + struct altera_jtaguart_platform_uart *platp = + dev_get_platdata(&pdev->dev); struct uart_port *port; struct resource *res_irq, *res_mem; int i = pdev->id; diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c index 1d46966e2a65..fa638db9a98c 100644 --- a/drivers/tty/serial/altera_uart.c +++ b/drivers/tty/serial/altera_uart.c @@ -534,7 +534,7 @@ static int altera_uart_get_of_uartclk(struct platform_device *pdev, static int altera_uart_probe(struct platform_device *pdev) { - struct altera_uart_platform_uart *platp = pdev->dev.platform_data; + struct altera_uart_platform_uart *platp = dev_get_platdata(&pdev->dev); struct uart_port *port; struct resource *res_mem; struct resource *res_irq; diff --git a/drivers/tty/serial/amba-pl010.c b/drivers/tty/serial/amba-pl010.c index c36840519527..8b90f0b6dfdf 100644 --- a/drivers/tty/serial/amba-pl010.c +++ b/drivers/tty/serial/amba-pl010.c @@ -721,7 +721,7 @@ static int pl010_probe(struct amba_device *dev, const struct amba_id *id) uap->port.flags = UPF_BOOT_AUTOCONF; uap->port.line = i; uap->dev = dev; - uap->data = dev->dev.platform_data; + uap->data = dev_get_platdata(&dev->dev); amba_ports[i] = uap; diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 28b35ad9c6cd..eb38fb851b4e 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -265,7 +265,7 @@ static void pl011_sgbuf_free(struct dma_chan *chan, struct pl011_sgbuf *sg, static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port *uap) { /* DMA is the sole user of the platform data right now */ - struct amba_pl011_data *plat = uap->port.dev->platform_data; + struct amba_pl011_data *plat = dev_get_platdata(uap->port.dev); struct dma_slave_config tx_conf = { .dst_addr = uap->port.mapbase + UART01x_DR, .dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE, @@ -1497,10 +1497,10 @@ static int pl011_hwinit(struct uart_port *port) uap->im = readw(uap->port.membase + UART011_IMSC); writew(UART011_RTIM | UART011_RXIM, uap->port.membase + UART011_IMSC); - if (uap->port.dev->platform_data) { + if (dev_get_platdata(uap->port.dev)) { struct amba_pl011_data *plat; - plat = uap->port.dev->platform_data; + plat = dev_get_platdata(uap->port.dev); if (plat->init) plat->init(); } @@ -1645,10 +1645,10 @@ static void pl011_shutdown(struct uart_port *port) /* Optionally let pins go into sleep states */ pinctrl_pm_select_sleep_state(port->dev); - if (uap->port.dev->platform_data) { + if (dev_get_platdata(uap->port.dev)) { struct amba_pl011_data *plat; - plat = uap->port.dev->platform_data; + plat = dev_get_platdata(uap->port.dev); if (plat->exit) plat->exit(); } @@ -2002,10 +2002,10 @@ static int __init pl011_console_setup(struct console *co, char *options) if (ret) return ret; - if (uap->port.dev->platform_data) { + if (dev_get_platdata(uap->port.dev)) { struct amba_pl011_data *plat; - plat = uap->port.dev->platform_data; + plat = dev_get_platdata(uap->port.dev); if (plat->init) plat->init(); } diff --git a/drivers/tty/serial/ar933x_uart.c b/drivers/tty/serial/ar933x_uart.c index 9824dfb1e4fe..7aa9062153e8 100644 --- a/drivers/tty/serial/ar933x_uart.c +++ b/drivers/tty/serial/ar933x_uart.c @@ -629,7 +629,7 @@ static int ar933x_uart_probe(struct platform_device *pdev) int id; int ret; - pdata = pdev->dev.platform_data; + pdata = dev_get_platdata(&pdev->dev); if (!pdata) return -EINVAL; diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c index cbf1d155b7b2..2f195f0d7a11 100644 --- a/drivers/tty/serial/arc_uart.c +++ b/drivers/tty/serial/arc_uart.c @@ -528,7 +528,7 @@ arc_uart_init_one(struct platform_device *pdev, int dev_id) unsigned long *plat_data; struct arc_uart_port *uart = &arc_uart_ports[dev_id]; - plat_data = ((unsigned long *)(pdev->dev.platform_data)); + plat_data = (unsigned long *)dev_get_platdata(&pdev->dev); if (!plat_data) return -ENODEV; diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 7e2cb31497c3..d067285a2d20 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -1393,7 +1393,7 @@ static int atmel_init_property(struct atmel_uart_port *atmel_port, struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; - struct atmel_uart_data *pdata = pdev->dev.platform_data; + struct atmel_uart_data *pdata = dev_get_platdata(&pdev->dev); if (np) { /* DMA/PDC usage specification */ @@ -1437,7 +1437,7 @@ static void atmel_init_rs485(struct atmel_uart_port *atmel_port, struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; - struct atmel_uart_data *pdata = pdev->dev.platform_data; + struct atmel_uart_data *pdata = dev_get_platdata(&pdev->dev); if (np) { u32 rs485_delay[2]; @@ -2028,7 +2028,7 @@ static int atmel_init_port(struct atmel_uart_port *atmel_port, { int ret; struct uart_port *port = &atmel_port->uart; - struct atmel_uart_data *pdata = pdev->dev.platform_data; + struct atmel_uart_data *pdata = dev_get_platdata(&pdev->dev); if (!atmel_init_property(atmel_port, pdev)) atmel_set_ops(port); @@ -2226,7 +2226,7 @@ static int __init atmel_console_init(void) int ret; if (atmel_default_console_device) { struct atmel_uart_data *pdata = - atmel_default_console_device->dev.platform_data; + dev_get_platdata(&atmel_default_console_device->dev); int id = pdata->num; struct atmel_uart_port *port = &atmel_ports[id]; @@ -2334,7 +2334,7 @@ static int atmel_serial_probe(struct platform_device *pdev) { struct atmel_uart_port *port; struct device_node *np = pdev->dev.of_node; - struct atmel_uart_data *pdata = pdev->dev.platform_data; + struct atmel_uart_data *pdata = dev_get_platdata(&pdev->dev); void *data; int ret = -ENODEV; diff --git a/drivers/tty/serial/bfin_sport_uart.c b/drivers/tty/serial/bfin_sport_uart.c index 487c173b0f72..424ed36c26f1 100644 --- a/drivers/tty/serial/bfin_sport_uart.c +++ b/drivers/tty/serial/bfin_sport_uart.c @@ -766,7 +766,8 @@ static int sport_uart_probe(struct platform_device *pdev) } ret = peripheral_request_list( - (unsigned short *)pdev->dev.platform_data, DRV_NAME); + (unsigned short *)dev_get_platdata(&pdev->dev), + DRV_NAME); if (ret) { dev_err(&pdev->dev, "Fail to request SPORT peripherals\n"); @@ -843,7 +844,7 @@ out_error_unmap: iounmap(sport->port.membase); out_error_free_peripherals: peripheral_free_list( - (unsigned short *)pdev->dev.platform_data); + (unsigned short *)dev_get_platdata(&pdev->dev)); out_error_free_mem: kfree(sport); bfin_sport_uart_ports[pdev->id] = NULL; @@ -863,7 +864,7 @@ static int sport_uart_remove(struct platform_device *pdev) uart_remove_one_port(&sport_uart_reg, &sport->port); iounmap(sport->port.membase); peripheral_free_list( - (unsigned short *)pdev->dev.platform_data); + (unsigned short *)dev_get_platdata(&pdev->dev)); kfree(sport); bfin_sport_uart_ports[pdev->id] = NULL; } diff --git a/drivers/tty/serial/bfin_uart.c b/drivers/tty/serial/bfin_uart.c index 72031d754dc0..378f3c383992 100644 --- a/drivers/tty/serial/bfin_uart.c +++ b/drivers/tty/serial/bfin_uart.c @@ -1240,7 +1240,8 @@ static int bfin_serial_probe(struct platform_device *pdev) */ #endif ret = peripheral_request_list( - (unsigned short *)pdev->dev.platform_data, DRIVER_NAME); + (unsigned short *)dev_get_platdata(&pdev->dev), + DRIVER_NAME); if (ret) { dev_err(&pdev->dev, "fail to request bfin serial peripherals\n"); @@ -1358,7 +1359,7 @@ out_error_unmap: iounmap(uart->port.membase); out_error_free_peripherals: peripheral_free_list( - (unsigned short *)pdev->dev.platform_data); + (unsigned short *)dev_get_platdata(&pdev->dev)); out_error_free_mem: kfree(uart); bfin_serial_ports[pdev->id] = NULL; @@ -1377,7 +1378,7 @@ static int bfin_serial_remove(struct platform_device *pdev) uart_remove_one_port(&bfin_serial_reg, &uart->port); iounmap(uart->port.membase); peripheral_free_list( - (unsigned short *)pdev->dev.platform_data); + (unsigned short *)dev_get_platdata(&pdev->dev)); kfree(uart); bfin_serial_ports[pdev->id] = NULL; } @@ -1432,7 +1433,7 @@ static int bfin_earlyprintk_probe(struct platform_device *pdev) } ret = peripheral_request_list( - (unsigned short *)pdev->dev.platform_data, DRIVER_NAME); + (unsigned short *)dev_get_platdata(&pdev->dev), DRIVER_NAME); if (ret) { dev_err(&pdev->dev, "fail to request bfin serial peripherals\n"); @@ -1463,7 +1464,7 @@ static int bfin_earlyprintk_probe(struct platform_device *pdev) out_error_free_peripherals: peripheral_free_list( - (unsigned short *)pdev->dev.platform_data); + (unsigned short *)dev_get_platdata(&pdev->dev)); return ret; } diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index 8b1534c424af..af286e6713eb 100644 --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c @@ -1008,7 +1008,7 @@ static int ifx_spi_spi_probe(struct spi_device *spi) return -ENODEV; } - pl_data = (struct ifx_modem_platform_data *)spi->dev.platform_data; + pl_data = (struct ifx_modem_platform_data *)dev_get_platdata(&spi->dev); if (!pl_data) { dev_err(&spi->dev, "missing platform data!"); return -ENODEV; diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 90655b875bab..a5f32c7c6c66 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -1222,7 +1222,7 @@ static int imx_startup(struct uart_port *port) if (USE_IRDA(sport)) { struct imxuart_platform_data *pdata; - pdata = sport->port.dev->platform_data; + pdata = dev_get_platdata(sport->port.dev); sport->irda_inv_rx = pdata->irda_inv_rx; sport->irda_inv_tx = pdata->irda_inv_tx; sport->trcv_delay = pdata->transceiver_delay; @@ -1265,7 +1265,7 @@ static void imx_shutdown(struct uart_port *port) if (USE_IRDA(sport)) { struct imxuart_platform_data *pdata; - pdata = sport->port.dev->platform_data; + pdata = dev_get_platdata(sport->port.dev); if (pdata->irda_enable) pdata->irda_enable(0); } @@ -1925,7 +1925,7 @@ static inline int serial_imx_probe_dt(struct imx_port *sport, static void serial_imx_probe_pdata(struct imx_port *sport, struct platform_device *pdev) { - struct imxuart_platform_data *pdata = pdev->dev.platform_data; + struct imxuart_platform_data *pdata = dev_get_platdata(&pdev->dev); sport->port.line = pdev->id; sport->devdata = (struct imx_uart_data *) pdev->id_entry->driver_data; @@ -2000,7 +2000,7 @@ static int serial_imx_probe(struct platform_device *pdev) imx_ports[sport->port.line] = sport; - pdata = pdev->dev.platform_data; + pdata = dev_get_platdata(&pdev->dev); if (pdata && pdata->init) { ret = pdata->init(pdev); if (ret) @@ -2024,7 +2024,7 @@ static int serial_imx_remove(struct platform_device *pdev) struct imxuart_platform_data *pdata; struct imx_port *sport = platform_get_drvdata(pdev); - pdata = pdev->dev.platform_data; + pdata = dev_get_platdata(&pdev->dev); uart_remove_one_port(&imx_reg, &sport->port); diff --git a/drivers/tty/serial/max3100.c b/drivers/tty/serial/max3100.c index 35866d5872ad..79f9a9eff545 100644 --- a/drivers/tty/serial/max3100.c +++ b/drivers/tty/serial/max3100.c @@ -779,7 +779,7 @@ static int max3100_probe(struct spi_device *spi) max3100s[i]->irq = spi->irq; spin_lock_init(&max3100s[i]->conf_lock); spi_set_drvdata(spi, max3100s[i]); - pdata = spi->dev.platform_data; + pdata = dev_get_platdata(&spi->dev); max3100s[i]->crystal = pdata->crystal; max3100s[i]->loopback = pdata->loopback; max3100s[i]->poll_time = pdata->poll_time * HZ / 1000; diff --git a/drivers/tty/serial/mcf.c b/drivers/tty/serial/mcf.c index 65be0c00c4bf..a2e97c96e159 100644 --- a/drivers/tty/serial/mcf.c +++ b/drivers/tty/serial/mcf.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -644,7 +645,7 @@ static struct uart_driver mcf_driver = { static int mcf_probe(struct platform_device *pdev) { - struct mcf_platform_uart *platp = pdev->dev.platform_data; + struct mcf_platform_uart *platp = dev_get_platdata(&pdev->dev); struct uart_port *port; int i; diff --git a/drivers/tty/serial/mpsc.c b/drivers/tty/serial/mpsc.c index bc24f4931670..fba52578d02f 100644 --- a/drivers/tty/serial/mpsc.c +++ b/drivers/tty/serial/mpsc.c @@ -1884,7 +1884,7 @@ static int mpsc_shared_drv_probe(struct platform_device *dev) if (dev->id == 0) { if (!(rc = mpsc_shared_map_regs(dev))) { pdata = (struct mpsc_shared_pdata *) - dev->dev.platform_data; + dev_get_platdata(&dev->dev); mpsc_shared_regs.MPSC_MRR_m = pdata->mrr_val; mpsc_shared_regs.MPSC_RCRR_m= pdata->rcrr_val; @@ -2025,7 +2025,7 @@ static void mpsc_drv_get_platform_data(struct mpsc_port_info *pi, { struct mpsc_pdata *pdata; - pdata = (struct mpsc_pdata *)pd->dev.platform_data; + pdata = (struct mpsc_pdata *)dev_get_platdata(&pd->dev); pi->port.uartclk = pdata->brg_clk_freq; pi->port.iotype = UPIO_MEM; diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c index 4ca2f64861e6..48e94961a9e5 100644 --- a/drivers/tty/serial/msm_serial_hs.c +++ b/drivers/tty/serial/msm_serial_hs.c @@ -1618,7 +1618,7 @@ static int msm_hs_probe(struct platform_device *pdev) struct msm_hs_port *msm_uport; struct resource *resource; const struct msm_serial_hs_platform_data *pdata = - pdev->dev.platform_data; + dev_get_platdata(&pdev->dev); if (pdev->id < 0 || pdev->id >= UARTDM_NR) { printk(KERN_ERR "Invalid plaform device ID = %d\n", pdev->id); diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index c77bf0cf2684..c7517063eb9b 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -200,7 +200,7 @@ static inline void serial_omap_clear_fifos(struct uart_omap_port *up) static int serial_omap_get_context_loss_count(struct uart_omap_port *up) { - struct omap_uart_port_info *pdata = up->dev->platform_data; + struct omap_uart_port_info *pdata = dev_get_platdata(up->dev); if (!pdata || !pdata->get_context_loss_count) return -EINVAL; @@ -210,7 +210,7 @@ static int serial_omap_get_context_loss_count(struct uart_omap_port *up) static void serial_omap_enable_wakeup(struct uart_omap_port *up, bool enable) { - struct omap_uart_port_info *pdata = up->dev->platform_data; + struct omap_uart_port_info *pdata = dev_get_platdata(up->dev); if (!pdata || !pdata->enable_wakeup) return; @@ -1409,7 +1409,7 @@ static int serial_omap_probe(struct platform_device *pdev) { struct uart_omap_port *up; struct resource *mem, *irq; - struct omap_uart_port_info *omap_up_info = pdev->dev.platform_data; + struct omap_uart_port_info *omap_up_info = dev_get_platdata(&pdev->dev); int ret; if (pdev->dev.of_node) { diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index 376079b9bd75..019b9154d7d4 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c @@ -1250,8 +1250,8 @@ static int s3c24xx_serial_probe(struct platform_device *pdev) ourport->baudclk = ERR_PTR(-EINVAL); ourport->info = ourport->drv_data->info; - ourport->cfg = (pdev->dev.platform_data) ? - (struct s3c2410_uartcfg *)pdev->dev.platform_data : + ourport->cfg = (dev_get_platdata(&pdev->dev)) ? + (struct s3c2410_uartcfg *)dev_get_platdata(&pdev->dev) : ourport->drv_data->def_cfg; ourport->port.fifosize = (ourport->info->fifosize) ? diff --git a/drivers/tty/serial/sc26xx.c b/drivers/tty/serial/sc26xx.c index 4b1434d53e9d..887b4f770749 100644 --- a/drivers/tty/serial/sc26xx.c +++ b/drivers/tty/serial/sc26xx.c @@ -637,7 +637,7 @@ static int sc26xx_probe(struct platform_device *dev) { struct resource *res; struct uart_sc26xx_port *up; - unsigned int *sc26xx_data = dev->dev.platform_data; + unsigned int *sc26xx_data = dev_get_platdata(&dev->dev); int err; res = platform_get_resource(dev, IORESOURCE_MEM, 0); diff --git a/drivers/tty/serial/serial_txx9.c b/drivers/tty/serial/serial_txx9.c index fe48a0c2b4ca..440a962412da 100644 --- a/drivers/tty/serial/serial_txx9.c +++ b/drivers/tty/serial/serial_txx9.c @@ -1097,7 +1097,7 @@ static void serial_txx9_unregister_port(int line) */ static int serial_txx9_probe(struct platform_device *dev) { - struct uart_port *p = dev->dev.platform_data; + struct uart_port *p = dev_get_platdata(&dev->dev); struct uart_port port; int ret, i; diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 7477e0ea5cdb..72ca870f8e57 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2380,7 +2380,7 @@ static char early_serial_buf[32]; static int sci_probe_earlyprintk(struct platform_device *pdev) { - struct plat_sci_port *cfg = pdev->dev.platform_data; + struct plat_sci_port *cfg = dev_get_platdata(&pdev->dev); if (early_serial_console.data) return -EEXIST; diff --git a/drivers/tty/serial/vr41xx_siu.c b/drivers/tty/serial/vr41xx_siu.c index f655997f44af..a63c14bc9a24 100644 --- a/drivers/tty/serial/vr41xx_siu.c +++ b/drivers/tty/serial/vr41xx_siu.c @@ -705,7 +705,7 @@ static int siu_init_ports(struct platform_device *pdev) { struct uart_port *port; struct resource *res; - int *type = pdev->dev.platform_data; + int *type = dev_get_platdata(&pdev->dev); int i; if (!type) From 11f1ad3ab4c2b2f208f7ef5b0360903bdf00df61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 30 Jul 2013 16:35:20 +0200 Subject: [PATCH 1272/3400] serial/efm32-uart: don't use pdev->id to determine the port's line MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pdev->id is not a valid choice for device-tree probed devices. So use the (properly determined) line from efm32_uart_probe consistenly Signed-off-by: Uwe Kleine-König Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/efm32-uart.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/tty/serial/efm32-uart.c b/drivers/tty/serial/efm32-uart.c index 868dbfb9f893..ce1ebbb0fe0d 100644 --- a/drivers/tty/serial/efm32-uart.c +++ b/drivers/tty/serial/efm32-uart.c @@ -698,6 +698,7 @@ static int efm32_uart_probe(struct platform_device *pdev) { struct efm32_uart_port *efm_port; struct resource *res; + unsigned int line; int ret; efm_port = kzalloc(sizeof(*efm_port), GFP_KERNEL); @@ -752,16 +753,17 @@ static int efm32_uart_probe(struct platform_device *pdev) efm_port->pdata = *pdata; } - if (efm_port->port.line >= 0 && - efm_port->port.line < ARRAY_SIZE(efm32_uart_ports)) - efm32_uart_ports[efm_port->port.line] = efm_port; + line = efm_port->port.line; + + if (line >= 0 && line < ARRAY_SIZE(efm32_uart_ports)) + efm32_uart_ports[line] = efm_port; ret = uart_add_one_port(&efm32_uart_reg, &efm_port->port); if (ret) { dev_dbg(&pdev->dev, "failed to add port: %d\n", ret); - if (pdev->id >= 0 && pdev->id < ARRAY_SIZE(efm32_uart_ports)) - efm32_uart_ports[pdev->id] = NULL; + if (line >= 0 && line < ARRAY_SIZE(efm32_uart_ports)) + efm32_uart_ports[line] = NULL; err_get_rxirq: err_too_small: err_get_base: @@ -777,11 +779,12 @@ err_get_base: static int efm32_uart_remove(struct platform_device *pdev) { struct efm32_uart_port *efm_port = platform_get_drvdata(pdev); + unsigned int line = efm_port->port.line; uart_remove_one_port(&efm32_uart_reg, &efm_port->port); - if (pdev->id >= 0 && pdev->id < ARRAY_SIZE(efm32_uart_ports)) - efm32_uart_ports[pdev->id] = NULL; + if (line >= 0 && line < ARRAY_SIZE(efm32_uart_ports)) + efm32_uart_ports[line] = NULL; kfree(efm_port); From 3fc1eb5fe5318d3eff9938240c29cc6ce2d6ce4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 30 Jul 2013 16:35:21 +0200 Subject: [PATCH 1273/3400] serial/efm32-uart: don't slur over failure in probe_dt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Uwe Kleine-König Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/efm32-uart.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/efm32-uart.c b/drivers/tty/serial/efm32-uart.c index ce1ebbb0fe0d..98adaa1c054f 100644 --- a/drivers/tty/serial/efm32-uart.c +++ b/drivers/tty/serial/efm32-uart.c @@ -751,7 +751,8 @@ static int efm32_uart_probe(struct platform_device *pdev) if (pdata) efm_port->pdata = *pdata; - } + } else if (ret < 0) + goto err_probe_dt; line = efm_port->port.line; @@ -764,6 +765,7 @@ static int efm32_uart_probe(struct platform_device *pdev) if (line >= 0 && line < ARRAY_SIZE(efm32_uart_ports)) efm32_uart_ports[line] = NULL; +err_probe_dt: err_get_rxirq: err_too_small: err_get_base: From e087ab74f3dd30105041e1c68db209f235b63042 Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Wed, 31 Jul 2013 14:56:29 +0400 Subject: [PATCH 1274/3400] serial: sccnxp: Disable regulator on error The patch disables the regulator in case of errors, if we have it. In addition, the patch adds support for deferred regulator probe and makes error path are a bit clean. Signed-off-by: Alexander Shiyan Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sccnxp.c | 40 +++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c index 98555179fe10..12a5c265f43a 100644 --- a/drivers/tty/serial/sccnxp.c +++ b/drivers/tty/serial/sccnxp.c @@ -787,10 +787,9 @@ static int sccnxp_probe(struct platform_device *pdev) struct sccnxp_port *s; void __iomem *membase; - if (!res) { - dev_err(&pdev->dev, "Missing memory resource data\n"); - return -EADDRNOTAVAIL; - } + membase = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(membase)) + return PTR_ERR(membase); s = devm_kzalloc(&pdev->dev, sizeof(struct sccnxp_port), GFP_KERNEL); if (!s) { @@ -885,10 +884,20 @@ static int sccnxp_probe(struct platform_device *pdev) break; default: dev_err(&pdev->dev, "Unsupported chip type %i\n", chiptype); - ret = -ENOTSUPP; - goto err_out; + return -ENOTSUPP; } + s->regulator = devm_regulator_get(&pdev->dev, "vcc"); + if (!IS_ERR(s->regulator)) { + ret = regulator_enable(s->regulator); + if (ret) { + dev_err(&pdev->dev, + "Failed to enable regulator: %i\n", ret); + return ret; + } + } else if (PTR_ERR(s->regulator) == -EPROBE_DEFER) + return -EPROBE_DEFER; + if (!pdata) { dev_warn(&pdev->dev, "No platform data supplied, using defaults\n"); @@ -919,22 +928,6 @@ static int sccnxp_probe(struct platform_device *pdev) goto err_out; } - s->regulator = devm_regulator_get(&pdev->dev, "VCC"); - if (!IS_ERR(s->regulator)) { - ret = regulator_enable(s->regulator); - if (ret) { - dev_err(&pdev->dev, - "Failed to enable regulator: %i\n", ret); - return ret; - } - } - - membase = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(membase)) { - ret = PTR_ERR(membase); - goto err_out; - } - s->uart.owner = THIS_MODULE; s->uart.dev_name = "ttySC"; s->uart.major = SCCNXP_MAJOR; @@ -997,6 +990,9 @@ static int sccnxp_probe(struct platform_device *pdev) } err_out: + if (!IS_ERR(s->regulator)) + return regulator_disable(s->regulator); + return ret; } From 90efa75f7ab0be5677f0cca155dbf0b39eacdd03 Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Wed, 31 Jul 2013 14:56:30 +0400 Subject: [PATCH 1275/3400] serial: sccnxp: Using CLK API for getting UART clock This patch removes "frequency" parameter from SCCNXP platform_data and uses CLK API for getting clock. If CLK ommited, default IC frequency will be used instead. Signed-off-by: Alexander Shiyan Signed-off-by: Greg Kroah-Hartman --- arch/mips/sni/a20r.c | 1 - drivers/tty/serial/sccnxp.c | 36 +++++++++++++-------- include/linux/platform_data/serial-sccnxp.h | 3 -- 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/arch/mips/sni/a20r.c b/arch/mips/sni/a20r.c index dd0ab982d77e..f9407e170476 100644 --- a/arch/mips/sni/a20r.c +++ b/arch/mips/sni/a20r.c @@ -122,7 +122,6 @@ static struct resource sc26xx_rsrc[] = { static struct sccnxp_pdata sccnxp_data = { .reg_shift = 2, - .frequency = 3686400, .mctrl_cfg[0] = MCTRL_SIG(DTR_OP, LINE_OP7) | MCTRL_SIG(RTS_OP, LINE_OP3) | MCTRL_SIG(DSR_IP, LINE_IP5) | diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c index 12a5c265f43a..81e70477e6fd 100644 --- a/drivers/tty/serial/sccnxp.c +++ b/drivers/tty/serial/sccnxp.c @@ -15,6 +15,7 @@ #define SUPPORT_SYSRQ #endif +#include #include #include #include @@ -783,9 +784,10 @@ static int sccnxp_probe(struct platform_device *pdev) struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); int chiptype = pdev->id_entry->driver_data; struct sccnxp_pdata *pdata = dev_get_platdata(&pdev->dev); - int i, ret, fifosize, freq_min, freq_max; + int i, ret, fifosize, freq_min, freq_max, uartclk; struct sccnxp_port *s; void __iomem *membase; + struct clk *clk; membase = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(membase)) @@ -898,11 +900,25 @@ static int sccnxp_probe(struct platform_device *pdev) } else if (PTR_ERR(s->regulator) == -EPROBE_DEFER) return -EPROBE_DEFER; - if (!pdata) { - dev_warn(&pdev->dev, - "No platform data supplied, using defaults\n"); - s->pdata.frequency = s->freq_std; + clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(clk)) { + if (PTR_ERR(clk) == -EPROBE_DEFER) { + ret = -EPROBE_DEFER; + goto err_out; + } + dev_notice(&pdev->dev, "Using default clock frequency\n"); + uartclk = s->freq_std; } else + uartclk = clk_get_rate(clk); + + /* Check input frequency */ + if ((uartclk < freq_min) || (uartclk > freq_max)) { + dev_err(&pdev->dev, "Frequency out of bounds\n"); + ret = -EINVAL; + goto err_out; + } + + if (pdata) memcpy(&s->pdata, pdata, sizeof(struct sccnxp_pdata)); if (s->pdata.poll_time_us) { @@ -920,14 +936,6 @@ static int sccnxp_probe(struct platform_device *pdev) } } - /* Check input frequency */ - if ((s->pdata.frequency < freq_min) || - (s->pdata.frequency > freq_max)) { - dev_err(&pdev->dev, "Frequency out of bounds\n"); - ret = -EINVAL; - goto err_out; - } - s->uart.owner = THIS_MODULE; s->uart.dev_name = "ttySC"; s->uart.major = SCCNXP_MAJOR; @@ -959,7 +967,7 @@ static int sccnxp_probe(struct platform_device *pdev) s->port[i].mapbase = res->start; s->port[i].membase = membase; s->port[i].regshift = s->pdata.reg_shift; - s->port[i].uartclk = s->pdata.frequency; + s->port[i].uartclk = uartclk; s->port[i].ops = &sccnxp_ops; uart_add_one_port(&s->uart, &s->port[i]); /* Set direction to input */ diff --git a/include/linux/platform_data/serial-sccnxp.h b/include/linux/platform_data/serial-sccnxp.h index bdc510d03245..af0c8c3b89ae 100644 --- a/include/linux/platform_data/serial-sccnxp.h +++ b/include/linux/platform_data/serial-sccnxp.h @@ -60,7 +60,6 @@ * }; * * static struct sccnxp_pdata sc2892_info = { - * .frequency = 3686400, * .mctrl_cfg[0] = MCTRL_SIG(DIR_OP, LINE_OP0), * .mctrl_cfg[1] = MCTRL_SIG(DIR_OP, LINE_OP1), * }; @@ -78,8 +77,6 @@ /* SCCNXP platform data structure */ struct sccnxp_pdata { - /* Frequency (extrenal clock or crystal) */ - int frequency; /* Shift for A0 line */ const u8 reg_shift; /* Modem control lines configuration */ From ea4c39beace859139bc184a1aebdccdc12c04a2e Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Wed, 31 Jul 2013 14:56:31 +0400 Subject: [PATCH 1276/3400] serial: sccnxp: Using structure for each supported IC instead of switch in probe This patch replaces switch in probe function to constant structure for each supported IC. This makes code a bit smaller and cleaner and helps adding DT support to the driver in the future. Signed-off-by: Alexander Shiyan Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sccnxp.c | 272 ++++++++++++++++-------------------- 1 file changed, 124 insertions(+), 148 deletions(-) diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c index 81e70477e6fd..49e9bbfe6cab 100644 --- a/drivers/tty/serial/sccnxp.c +++ b/drivers/tty/serial/sccnxp.c @@ -95,16 +95,17 @@ #define MCTRL_IBIT(cfg, sig) ((((cfg) >> (sig)) & 0xf) - LINE_IP0) #define MCTRL_OBIT(cfg, sig) ((((cfg) >> (sig)) & 0xf) - LINE_OP0) -/* Supported chip types */ -enum { - SCCNXP_TYPE_SC2681 = 2681, - SCCNXP_TYPE_SC2691 = 2691, - SCCNXP_TYPE_SC2692 = 2692, - SCCNXP_TYPE_SC2891 = 2891, - SCCNXP_TYPE_SC2892 = 2892, - SCCNXP_TYPE_SC28202 = 28202, - SCCNXP_TYPE_SC68681 = 68681, - SCCNXP_TYPE_SC68692 = 68692, +#define SCCNXP_HAVE_IO 0x00000001 +#define SCCNXP_HAVE_MR0 0x00000002 + +struct sccnxp_chip { + const char *name; + unsigned int nr; + unsigned long freq_min; + unsigned long freq_std; + unsigned long freq_max; + unsigned int flags; + unsigned int fifosize; }; struct sccnxp_port { @@ -112,16 +113,10 @@ struct sccnxp_port { struct uart_port port[SCCNXP_MAX_UARTS]; bool opened[SCCNXP_MAX_UARTS]; - const char *name; int irq; - u8 imr; - u8 addr_mask; - int freq_std; - int flags; -#define SCCNXP_HAVE_IO 0x00000001 -#define SCCNXP_HAVE_MR0 0x00000002 + struct sccnxp_chip *chip; #ifdef CONFIG_SERIAL_SCCNXP_CONSOLE struct console console; @@ -137,29 +132,94 @@ struct sccnxp_port { struct regulator *regulator; }; -static inline u8 sccnxp_raw_read(void __iomem *base, u8 reg, u8 shift) -{ - return readb(base + (reg << shift)); -} +static const struct sccnxp_chip sc2681 = { + .name = "SC2681", + .nr = 2, + .freq_min = 1000000, + .freq_std = 3686400, + .freq_max = 4000000, + .flags = SCCNXP_HAVE_IO, + .fifosize = 3, +}; -static inline void sccnxp_raw_write(void __iomem *base, u8 reg, u8 shift, u8 v) -{ - writeb(v, base + (reg << shift)); -} +static const struct sccnxp_chip sc2691 = { + .name = "SC2691", + .nr = 1, + .freq_min = 1000000, + .freq_std = 3686400, + .freq_max = 4000000, + .flags = 0, + .fifosize = 3, +}; + +static const struct sccnxp_chip sc2692 = { + .name = "SC2692", + .nr = 2, + .freq_min = 1000000, + .freq_std = 3686400, + .freq_max = 4000000, + .flags = SCCNXP_HAVE_IO, + .fifosize = 3, +}; + +static const struct sccnxp_chip sc2891 = { + .name = "SC2891", + .nr = 1, + .freq_min = 100000, + .freq_std = 3686400, + .freq_max = 8000000, + .flags = SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0, + .fifosize = 16, +}; + +static const struct sccnxp_chip sc2892 = { + .name = "SC2892", + .nr = 2, + .freq_min = 100000, + .freq_std = 3686400, + .freq_max = 8000000, + .flags = SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0, + .fifosize = 16, +}; + +static const struct sccnxp_chip sc28202 = { + .name = "SC28202", + .nr = 2, + .freq_min = 1000000, + .freq_std = 14745600, + .freq_max = 50000000, + .flags = SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0, + .fifosize = 256, +}; + +static const struct sccnxp_chip sc68681 = { + .name = "SC68681", + .nr = 2, + .freq_min = 1000000, + .freq_std = 3686400, + .freq_max = 4000000, + .flags = SCCNXP_HAVE_IO, + .fifosize = 3, +}; + +static const struct sccnxp_chip sc68692 = { + .name = "SC68692", + .nr = 2, + .freq_min = 1000000, + .freq_std = 3686400, + .freq_max = 4000000, + .flags = SCCNXP_HAVE_IO, + .fifosize = 3, +}; static inline u8 sccnxp_read(struct uart_port *port, u8 reg) { - struct sccnxp_port *s = dev_get_drvdata(port->dev); - - return sccnxp_raw_read(port->membase, reg & s->addr_mask, - port->regshift); + return readb(port->membase + (reg << port->regshift)); } static inline void sccnxp_write(struct uart_port *port, u8 reg, u8 v) { - struct sccnxp_port *s = dev_get_drvdata(port->dev); - - sccnxp_raw_write(port->membase, reg & s->addr_mask, port->regshift, v); + writeb(v, port->membase + (reg << port->regshift)); } static inline u8 sccnxp_port_read(struct uart_port *port, u8 reg) @@ -225,13 +285,14 @@ static int sccnxp_set_baud(struct uart_port *port, int baud) { struct sccnxp_port *s = dev_get_drvdata(port->dev); int div_std, tmp_baud, bestbaud = baud, besterr = -1; + struct sccnxp_chip *chip = s->chip; u8 i, acr = 0, csr = 0, mr0 = 0; /* Find best baud from table */ for (i = 0; baud_std[i].baud && besterr; i++) { - if (baud_std[i].mr0 && !(s->flags & SCCNXP_HAVE_MR0)) + if (baud_std[i].mr0 && !(chip->flags & SCCNXP_HAVE_MR0)) continue; - div_std = DIV_ROUND_CLOSEST(s->freq_std, baud_std[i].baud); + div_std = DIV_ROUND_CLOSEST(chip->freq_std, baud_std[i].baud); tmp_baud = DIV_ROUND_CLOSEST(port->uartclk, div_std); if (!sccnxp_update_best_err(baud, tmp_baud, &besterr)) { acr = baud_std[i].acr; @@ -241,7 +302,7 @@ static int sccnxp_set_baud(struct uart_port *port, int baud) } } - if (s->flags & SCCNXP_HAVE_MR0) { + if (chip->flags & SCCNXP_HAVE_MR0) { /* Enable FIFO, set half level for TX */ mr0 |= MR0_FIFO | MR0_TXLVL; /* Update MR0 */ @@ -364,7 +425,7 @@ static void sccnxp_handle_tx(struct uart_port *port) sccnxp_disable_irq(port, IMR_TXRDY); /* Set direction to input */ - if (s->flags & SCCNXP_HAVE_IO) + if (s->chip->flags & SCCNXP_HAVE_IO) sccnxp_set_bit(port, DIR_OP, 0); } return; @@ -438,7 +499,7 @@ static void sccnxp_start_tx(struct uart_port *port) spin_lock_irqsave(&s->lock, flags); /* Set direction to output */ - if (s->flags & SCCNXP_HAVE_IO) + if (s->chip->flags & SCCNXP_HAVE_IO) sccnxp_set_bit(port, DIR_OP, 1); sccnxp_enable_irq(port, IMR_TXRDY); @@ -484,7 +545,7 @@ static void sccnxp_set_mctrl(struct uart_port *port, unsigned int mctrl) struct sccnxp_port *s = dev_get_drvdata(port->dev); unsigned long flags; - if (!(s->flags & SCCNXP_HAVE_IO)) + if (!(s->chip->flags & SCCNXP_HAVE_IO)) return; spin_lock_irqsave(&s->lock, flags); @@ -502,7 +563,7 @@ static unsigned int sccnxp_get_mctrl(struct uart_port *port) struct sccnxp_port *s = dev_get_drvdata(port->dev); unsigned int mctrl = TIOCM_DSR | TIOCM_CTS | TIOCM_CAR; - if (!(s->flags & SCCNXP_HAVE_IO)) + if (!(s->chip->flags & SCCNXP_HAVE_IO)) return mctrl; spin_lock_irqsave(&s->lock, flags); @@ -618,7 +679,7 @@ static void sccnxp_set_termios(struct uart_port *port, /* Setup baudrate */ baud = uart_get_baud_rate(port, termios, old, 50, - (s->flags & SCCNXP_HAVE_MR0) ? + (s->chip->flags & SCCNXP_HAVE_MR0) ? 230400 : 38400); baud = sccnxp_set_baud(port, baud); @@ -642,7 +703,7 @@ static int sccnxp_startup(struct uart_port *port) spin_lock_irqsave(&s->lock, flags); - if (s->flags & SCCNXP_HAVE_IO) { + if (s->chip->flags & SCCNXP_HAVE_IO) { /* Outputs are controlled manually */ sccnxp_write(port, SCCNXP_OPCR_REG, 0); } @@ -682,7 +743,7 @@ static void sccnxp_shutdown(struct uart_port *port) sccnxp_port_write(port, SCCNXP_CR_REG, CR_RX_DISABLE | CR_TX_DISABLE); /* Leave direction to input */ - if (s->flags & SCCNXP_HAVE_IO) + if (s->chip->flags & SCCNXP_HAVE_IO) sccnxp_set_bit(port, DIR_OP, 0); spin_unlock_irqrestore(&s->lock, flags); @@ -692,7 +753,7 @@ static const char *sccnxp_type(struct uart_port *port) { struct sccnxp_port *s = dev_get_drvdata(port->dev); - return (port->type == PORT_SC26XX) ? s->name : NULL; + return (port->type == PORT_SC26XX) ? s->chip->name : NULL; } static void sccnxp_release_port(struct uart_port *port) @@ -779,12 +840,24 @@ static int sccnxp_console_setup(struct console *co, char *options) } #endif +static const struct platform_device_id sccnxp_id_table[] = { + { .name = "sc2681", .driver_data = (kernel_ulong_t)&sc2681, }, + { .name = "sc2691", .driver_data = (kernel_ulong_t)&sc2691, }, + { .name = "sc2692", .driver_data = (kernel_ulong_t)&sc2692, }, + { .name = "sc2891", .driver_data = (kernel_ulong_t)&sc2891, }, + { .name = "sc2892", .driver_data = (kernel_ulong_t)&sc2892, }, + { .name = "sc28202", .driver_data = (kernel_ulong_t)&sc28202, }, + { .name = "sc68681", .driver_data = (kernel_ulong_t)&sc68681, }, + { .name = "sc68692", .driver_data = (kernel_ulong_t)&sc68692, }, + { } +}; +MODULE_DEVICE_TABLE(platform, sccnxp_id_table); + static int sccnxp_probe(struct platform_device *pdev) { struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - int chiptype = pdev->id_entry->driver_data; struct sccnxp_pdata *pdata = dev_get_platdata(&pdev->dev); - int i, ret, fifosize, freq_min, freq_max, uartclk; + int i, ret, uartclk; struct sccnxp_port *s; void __iomem *membase; struct clk *clk; @@ -802,92 +875,7 @@ static int sccnxp_probe(struct platform_device *pdev) spin_lock_init(&s->lock); - /* Individual chip settings */ - switch (chiptype) { - case SCCNXP_TYPE_SC2681: - s->name = "SC2681"; - s->uart.nr = 2; - s->freq_std = 3686400; - s->addr_mask = 0x0f; - s->flags = SCCNXP_HAVE_IO; - fifosize = 3; - freq_min = 1000000; - freq_max = 4000000; - break; - case SCCNXP_TYPE_SC2691: - s->name = "SC2691"; - s->uart.nr = 1; - s->freq_std = 3686400; - s->addr_mask = 0x07; - s->flags = 0; - fifosize = 3; - freq_min = 1000000; - freq_max = 4000000; - break; - case SCCNXP_TYPE_SC2692: - s->name = "SC2692"; - s->uart.nr = 2; - s->freq_std = 3686400; - s->addr_mask = 0x0f; - s->flags = SCCNXP_HAVE_IO; - fifosize = 3; - freq_min = 1000000; - freq_max = 4000000; - break; - case SCCNXP_TYPE_SC2891: - s->name = "SC2891"; - s->uart.nr = 1; - s->freq_std = 3686400; - s->addr_mask = 0x0f; - s->flags = SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0; - fifosize = 16; - freq_min = 100000; - freq_max = 8000000; - break; - case SCCNXP_TYPE_SC2892: - s->name = "SC2892"; - s->uart.nr = 2; - s->freq_std = 3686400; - s->addr_mask = 0x0f; - s->flags = SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0; - fifosize = 16; - freq_min = 100000; - freq_max = 8000000; - break; - case SCCNXP_TYPE_SC28202: - s->name = "SC28202"; - s->uart.nr = 2; - s->freq_std = 14745600; - s->addr_mask = 0x7f; - s->flags = SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0; - fifosize = 256; - freq_min = 1000000; - freq_max = 50000000; - break; - case SCCNXP_TYPE_SC68681: - s->name = "SC68681"; - s->uart.nr = 2; - s->freq_std = 3686400; - s->addr_mask = 0x0f; - s->flags = SCCNXP_HAVE_IO; - fifosize = 3; - freq_min = 1000000; - freq_max = 4000000; - break; - case SCCNXP_TYPE_SC68692: - s->name = "SC68692"; - s->uart.nr = 2; - s->freq_std = 3686400; - s->addr_mask = 0x0f; - s->flags = SCCNXP_HAVE_IO; - fifosize = 3; - freq_min = 1000000; - freq_max = 4000000; - break; - default: - dev_err(&pdev->dev, "Unsupported chip type %i\n", chiptype); - return -ENOTSUPP; - } + s->chip = (struct sccnxp_chip *)pdev->id_entry->driver_data; s->regulator = devm_regulator_get(&pdev->dev, "vcc"); if (!IS_ERR(s->regulator)) { @@ -907,12 +895,12 @@ static int sccnxp_probe(struct platform_device *pdev) goto err_out; } dev_notice(&pdev->dev, "Using default clock frequency\n"); - uartclk = s->freq_std; + uartclk = s->chip->freq_std; } else uartclk = clk_get_rate(clk); /* Check input frequency */ - if ((uartclk < freq_min) || (uartclk > freq_max)) { + if ((uartclk < s->chip->freq_min) || (uartclk > s->chip->freq_max)) { dev_err(&pdev->dev, "Frequency out of bounds\n"); ret = -EINVAL; goto err_out; @@ -940,6 +928,7 @@ static int sccnxp_probe(struct platform_device *pdev) s->uart.dev_name = "ttySC"; s->uart.major = SCCNXP_MAJOR; s->uart.minor = SCCNXP_MINOR; + s->uart.nr = s->chip->nr; #ifdef CONFIG_SERIAL_SCCNXP_CONSOLE s->uart.cons = &s->console; s->uart.cons->device = uart_console_device; @@ -961,7 +950,7 @@ static int sccnxp_probe(struct platform_device *pdev) s->port[i].dev = &pdev->dev; s->port[i].irq = s->irq; s->port[i].type = PORT_SC26XX; - s->port[i].fifosize = fifosize; + s->port[i].fifosize = s->chip->fifosize; s->port[i].flags = UPF_SKIP_TEST | UPF_FIXED_TYPE; s->port[i].iotype = UPIO_MEM; s->port[i].mapbase = res->start; @@ -971,7 +960,7 @@ static int sccnxp_probe(struct platform_device *pdev) s->port[i].ops = &sccnxp_ops; uart_add_one_port(&s->uart, &s->port[i]); /* Set direction to input */ - if (s->flags & SCCNXP_HAVE_IO) + if (s->chip->flags & SCCNXP_HAVE_IO) sccnxp_set_bit(&s->port[i], DIR_OP, 0); } @@ -1025,19 +1014,6 @@ static int sccnxp_remove(struct platform_device *pdev) return 0; } -static const struct platform_device_id sccnxp_id_table[] = { - { "sc2681", SCCNXP_TYPE_SC2681 }, - { "sc2691", SCCNXP_TYPE_SC2691 }, - { "sc2692", SCCNXP_TYPE_SC2692 }, - { "sc2891", SCCNXP_TYPE_SC2891 }, - { "sc2892", SCCNXP_TYPE_SC2892 }, - { "sc28202", SCCNXP_TYPE_SC28202 }, - { "sc68681", SCCNXP_TYPE_SC68681 }, - { "sc68692", SCCNXP_TYPE_SC68692 }, - { }, -}; -MODULE_DEVICE_TABLE(platform, sccnxp_id_table); - static struct platform_driver sccnxp_uart_driver = { .driver = { .name = SCCNXP_NAME, From 85c996907473e4ef824774b97b26499adf66521f Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Wed, 31 Jul 2013 14:55:45 +0400 Subject: [PATCH 1277/3400] serial: sccnxp: Add DT support Add DT support to the SCCNCP serial driver. Signed-off-by: Alexander Shiyan Signed-off-by: Greg Kroah-Hartman --- .../bindings/tty/serial/sccnxp-serial.txt | 53 +++++++++++++++++++ drivers/tty/serial/sccnxp.c | 46 ++++++++++++---- include/linux/platform_data/serial-sccnxp.h | 6 +-- 3 files changed, 93 insertions(+), 12 deletions(-) create mode 100644 Documentation/devicetree/bindings/tty/serial/sccnxp-serial.txt diff --git a/Documentation/devicetree/bindings/tty/serial/sccnxp-serial.txt b/Documentation/devicetree/bindings/tty/serial/sccnxp-serial.txt new file mode 100644 index 000000000000..d18b1698133e --- /dev/null +++ b/Documentation/devicetree/bindings/tty/serial/sccnxp-serial.txt @@ -0,0 +1,53 @@ +* NXP (Philips) SCC+++(SCN+++) serial driver + +Required properties: +- compatible: Should be "nxp,". The supported ICs include sc2681, + sc2691, sc2692, sc2891, sc2892, sc28202, sc68681 and sc68692. +- reg: Address and length of the register set for the device. +- interrupts: Should contain the interrupt number. If omitted, + polling mode will be used instead, so "poll-interval" property should + be populated in this case. + +Optional properties: +- clocks: Phandle to input clock. If omitted, default IC frequency will be + used instead. +- poll-interval: Poll interval time in nanoseconds. +- vcc-supply: The regulator supplying the VCC to drive the chip. +- nxp,sccnxp-io-cfg: Array contains values for the emulated modem signals. + The number of values depends on the UART-number in the selected chip. + Each value should be composed according to the following rules: + (LINE1 << SIGNAL1) | ... | (LINEX << SIGNALX), where: + LINE - VALUE: + OP0 - 1 + OP1 - 2 + OP2 - 3 + OP3 - 4 + OP4 - 5 + OP5 - 6 + OP6 - 7 + OP7 - 8 + IP0 - 9 + IP1 - 10 + IP2 - 11 + IP3 - 12 + IP4 - 13 + IP5 - 14 + IP6 - 15 + SIGNAL - VALUE: + DTR - 0 + RTS - 4 + DSR - 8 + CTS - 12 + DCD - 16 + RNG - 20 + DIR - 24 + +Example (Dual UART with direction control on OP0 & OP1): +sc2892@10100000 { + compatible = "nxp,sc2892"; + reg = <0x10100000 0x10>; + poll-interval = <10000>; + clocks = <&sc2892_clk>; + vcc-supply = <&sc2892_reg>; + nxp,sccnxp-io-cfg = <0x01000000 0x02000000>; +}; diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c index 49e9bbfe6cab..67f73d1a8e7b 100644 --- a/drivers/tty/serial/sccnxp.c +++ b/drivers/tty/serial/sccnxp.c @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include #include #include @@ -853,10 +855,25 @@ static const struct platform_device_id sccnxp_id_table[] = { }; MODULE_DEVICE_TABLE(platform, sccnxp_id_table); +static const struct of_device_id sccnxp_dt_id_table[] = { + { .compatible = "nxp,sc2681", .data = &sc2681, }, + { .compatible = "nxp,sc2691", .data = &sc2691, }, + { .compatible = "nxp,sc2692", .data = &sc2692, }, + { .compatible = "nxp,sc2891", .data = &sc2891, }, + { .compatible = "nxp,sc2892", .data = &sc2892, }, + { .compatible = "nxp,sc28202", .data = &sc28202, }, + { .compatible = "nxp,sc68681", .data = &sc68681, }, + { .compatible = "nxp,sc68692", .data = &sc68692, }, + { } +}; +MODULE_DEVICE_TABLE(of, sccnxp_dt_id_table); + static int sccnxp_probe(struct platform_device *pdev) { struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); struct sccnxp_pdata *pdata = dev_get_platdata(&pdev->dev); + const struct of_device_id *of_id = + of_match_device(sccnxp_dt_id_table, &pdev->dev); int i, ret, uartclk; struct sccnxp_port *s; void __iomem *membase; @@ -875,7 +892,22 @@ static int sccnxp_probe(struct platform_device *pdev) spin_lock_init(&s->lock); - s->chip = (struct sccnxp_chip *)pdev->id_entry->driver_data; + if (of_id) { + s->chip = (struct sccnxp_chip *)of_id->data; + + of_property_read_u32(pdev->dev.of_node, "poll-interval", + &s->pdata.poll_time_us); + of_property_read_u32(pdev->dev.of_node, "reg-shift", + &s->pdata.reg_shift); + of_property_read_u32_array(pdev->dev.of_node, + "nxp,sccnxp-io-cfg", + s->pdata.mctrl_cfg, s->chip->nr); + } else { + s->chip = (struct sccnxp_chip *)pdev->id_entry->driver_data; + + if (pdata) + memcpy(&s->pdata, pdata, sizeof(struct sccnxp_pdata)); + } s->regulator = devm_regulator_get(&pdev->dev, "vcc"); if (!IS_ERR(s->regulator)) { @@ -906,16 +938,11 @@ static int sccnxp_probe(struct platform_device *pdev) goto err_out; } - if (pdata) - memcpy(&s->pdata, pdata, sizeof(struct sccnxp_pdata)); - if (s->pdata.poll_time_us) { dev_info(&pdev->dev, "Using poll mode, resolution %u usecs\n", s->pdata.poll_time_us); s->poll = 1; - } - - if (!s->poll) { + } else { s->irq = platform_get_irq(pdev, 0); if (s->irq < 0) { dev_err(&pdev->dev, "Missing irq resource data\n"); @@ -1016,8 +1043,9 @@ static int sccnxp_remove(struct platform_device *pdev) static struct platform_driver sccnxp_uart_driver = { .driver = { - .name = SCCNXP_NAME, - .owner = THIS_MODULE, + .name = SCCNXP_NAME, + .owner = THIS_MODULE, + .of_match_table = sccnxp_dt_id_table, }, .probe = sccnxp_probe, .remove = sccnxp_remove, diff --git a/include/linux/platform_data/serial-sccnxp.h b/include/linux/platform_data/serial-sccnxp.h index af0c8c3b89ae..98373d6add27 100644 --- a/include/linux/platform_data/serial-sccnxp.h +++ b/include/linux/platform_data/serial-sccnxp.h @@ -78,11 +78,11 @@ /* SCCNXP platform data structure */ struct sccnxp_pdata { /* Shift for A0 line */ - const u8 reg_shift; + u32 reg_shift; /* Modem control lines configuration */ - const u32 mctrl_cfg[SCCNXP_MAX_UARTS]; + u32 mctrl_cfg[SCCNXP_MAX_UARTS]; /* Timer value for polling mode (usecs) */ - const unsigned int poll_time_us; + u32 poll_time_us; }; #endif From b8bdad608213caffa081a97d2e937e5fe08c4046 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frank=20Sch=C3=A4fer?= Date: Tue, 30 Jul 2013 21:49:04 +0200 Subject: [PATCH 1278/3400] USB: pl2303: restrict the divisor based baud rate encoding method to the "HX" chip type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's not clear if the type_0 and type_1 chips support the divisor based baud rate encoding method, so don't use it until anyone with such chip has tested it to avoid regressions with the following patches. Even if it has been working fine with these chips since the code has been added 2 years ago, this change will not cause any regressions, because the baud rates currently supported/allowed with the divisor based method are supported with the direct method, too. The code for the divisor based method also isn't entirely correct (yet), so that the direct encoding method actually works better (sets the baud rate more precisely). Signed-off-by: Frank Schäfer Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/pl2303.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 1e6de4cd079d..244820193e10 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -305,10 +305,14 @@ static void pl2303_encode_baudrate(struct tty_struct *tty, if (spriv->type != HX) baud = min_t(int, baud, 1228800); - if (baud <= 115200) { + if (spriv->type != HX || baud <= 115200) { + /* Direct (standard) baud rate encoding method */ put_unaligned_le32(baud, buf); } else { /* + * NOTE: it's not clear if the type_0/1 chips + * support this method + * * Apparently the formula for higher speeds is: * baudrate = 12M * 32 / (2^buf[1]) / buf[0] */ From aa52aeea2725839bdd3dcce394486e9a043065e0 Mon Sep 17 00:00:00 2001 From: Asias He Date: Thu, 1 Aug 2013 11:07:18 +0930 Subject: [PATCH 1279/3400] virtio-scsi: Fix virtqueue affinity setup vscsi->num_queues counts the number of request virtqueue which does not include the control and event virtqueue. It is wrong to subtract VIRTIO_SCSI_VQ_BASE from vscsi->num_queues. This patch fixes the following panic. (qemu) device_del scsi0 BUG: unable to handle kernel NULL pointer dereference at 0000000000000020 IP: [] __virtscsi_set_affinity+0x6f/0x120 PGD 0 Oops: 0000 [#1] SMP Modules linked in: CPU: 0 PID: 659 Comm: kworker/0:1 Not tainted 3.11.0-rc2+ #1172 Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011 Workqueue: kacpi_hotplug _handle_hotplug_event_func task: ffff88007bee1cc0 ti: ffff88007bfe4000 task.ti: ffff88007bfe4000 RIP: 0010:[] [] __virtscsi_set_affinity+0x6f/0x120 RSP: 0018:ffff88007bfe5a38 EFLAGS: 00010202 RAX: 0000000000000010 RBX: ffff880077fd0d28 RCX: 0000000000000050 RDX: 0000000000000000 RSI: 0000000000000246 RDI: 0000000000000000 RBP: ffff88007bfe5a58 R08: ffff880077f6ff00 R09: 0000000000000001 R10: ffffffff8143e673 R11: 0000000000000001 R12: 0000000000000001 R13: ffff880077fd0800 R14: 0000000000000000 R15: ffff88007bf489b0 FS: 0000000000000000(0000) GS:ffff88007ea00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 0000000000000020 CR3: 0000000079f8b000 CR4: 00000000000006f0 Stack: ffff880077fd0d28 0000000000000000 ffff880077fd0800 0000000000000008 ffff88007bfe5a78 ffffffff8179b37d ffff88007bccc800 ffff88007bccc800 ffff88007bfe5a98 ffffffff8179b3b6 ffff88007bccc800 ffff880077fd0d28 Call Trace: [] virtscsi_set_affinity+0x2d/0x40 [] virtscsi_remove_vqs+0x26/0x50 [] virtscsi_remove+0x82/0xa0 [] virtio_dev_remove+0x22/0x70 [] __device_release_driver+0x69/0xd0 [] device_release_driver+0x2d/0x40 [] bus_remove_device+0x116/0x150 [] device_del+0x126/0x1e0 [] device_unregister+0x16/0x30 [] unregister_virtio_device+0x19/0x30 [] virtio_pci_remove+0x36/0x80 [] pci_device_remove+0x37/0x70 [] __device_release_driver+0x69/0xd0 [] device_release_driver+0x2d/0x40 [] bus_remove_device+0x116/0x150 [] device_del+0x126/0x1e0 [] pci_stop_bus_device+0x9c/0xb0 [] pci_stop_and_remove_bus_device+0x16/0x30 [] acpiphp_disable_slot+0x8e/0x150 [] hotplug_event_func+0xba/0x1a0 [] ? acpi_os_release_object+0xe/0x12 [] _handle_hotplug_event_func+0x31/0x70 [] process_one_work+0x183/0x500 [] worker_thread+0x122/0x400 [] ? manage_workers+0x2d0/0x2d0 [] kthread+0xce/0xe0 [] ? kthread_freezable_should_stop+0x70/0x70 [] ret_from_fork+0x7c/0xb0 [] ? kthread_freezable_should_stop+0x70/0x70 Code: 01 00 00 00 74 59 45 31 e4 83 bb c8 01 00 00 02 74 46 66 2e 0f 1f 84 00 00 00 00 00 49 63 c4 48 c1 e0 04 48 8b bc 0 3 10 02 00 00 <48> 8b 47 20 48 8b 80 d0 01 00 00 48 8b 40 50 48 85 c0 74 07 be RIP [] __virtscsi_set_affinity+0x6f/0x120 RSP CR2: 0000000000000020 ---[ end trace 99679331a3775f48 ]--- CC: stable@vger.kernel.org Signed-off-by: Asias He Reviewed-by: Wanlong Gao Signed-off-by: Rusty Russell --- drivers/scsi/virtio_scsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index 2168258fb2c3..74b88efde6ad 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c @@ -751,7 +751,7 @@ static void __virtscsi_set_affinity(struct virtio_scsi *vscsi, bool affinity) vscsi->affinity_hint_set = true; } else { - for (i = 0; i < vscsi->num_queues - VIRTIO_SCSI_VQ_BASE; i++) + for (i = 0; i < vscsi->num_queues; i++) virtqueue_set_affinity(vscsi->req_vqs[i].vq, -1); vscsi->affinity_hint_set = false; From 40c32592668b727cbfcf7b1c0567f581bd62a5e4 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Wed, 3 Jul 2013 23:33:50 -0400 Subject: [PATCH 1280/3400] tracing/kprobes: Fail to unregister if probe event files are in use When a probe is being removed, it cleans up the event files that correspond to the probe. But there is a race between writing to one of these files and deleting the probe. This is especially true for the "enable" file. CPU 0 CPU 1 ----- ----- fd = open("enable",O_WRONLY); probes_open() release_all_trace_probes() unregister_trace_probe() if (trace_probe_is_enabled(tp)) return -EBUSY write(fd, "1", 1) __ftrace_set_clr_event() call->class->reg() (kprobe_register) enable_trace_probe(tp) __unregister_trace_probe(tp); list_del(&tp->list) unregister_probe_event(tp) <-- fails! free_trace_probe(tp) write(fd, "0", 1) __ftrace_set_clr_event() call->class->unreg (kprobe_register) disable_trace_probe(tp) <-- BOOM! A test program was written that used two threads to simulate the above scenario adding a nanosleep() interval to change the timings and after several thousand runs, it was able to trigger this bug and crash: BUG: unable to handle kernel paging request at 00000005000000f9 IP: [] probes_open+0x3b/0xa7 PGD 7808a067 PUD 0 Oops: 0000 [#1] PREEMPT SMP Dumping ftrace buffer: --------------------------------- Modules linked in: ipt_MASQUERADE sunrpc ip6t_REJECT nf_conntrack_ipv6 CPU: 1 PID: 2070 Comm: test-kprobe-rem Not tainted 3.11.0-rc3-test+ #47 Hardware name: To Be Filled By O.E.M. To Be Filled By O.E.M./To be filled by O.E.M., BIOS SDBLI944.86P 05/08/2007 task: ffff880077756440 ti: ffff880076e52000 task.ti: ffff880076e52000 RIP: 0010:[] [] probes_open+0x3b/0xa7 RSP: 0018:ffff880076e53c38 EFLAGS: 00010203 RAX: 0000000500000001 RBX: ffff88007844f440 RCX: 0000000000000003 RDX: 0000000000000003 RSI: 0000000000000003 RDI: ffff880076e52000 RBP: ffff880076e53c58 R08: ffff880076e53bd8 R09: 0000000000000000 R10: ffff880077756440 R11: 0000000000000006 R12: ffffffff810dee35 R13: ffff880079250418 R14: 0000000000000000 R15: ffff88007844f450 FS: 00007f87a276f700(0000) GS:ffff88007d480000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 00000005000000f9 CR3: 0000000077262000 CR4: 00000000000007e0 Stack: ffff880076e53c58 ffffffff81219ea0 ffff88007844f440 ffffffff810dee35 ffff880076e53ca8 ffffffff81130f78 ffff8800772986c0 ffff8800796f93a0 ffffffff81d1b5d8 ffff880076e53e04 0000000000000000 ffff88007844f440 Call Trace: [] ? security_file_open+0x2c/0x30 [] ? unregister_trace_probe+0x4b/0x4b [] do_dentry_open+0x162/0x226 [] finish_open+0x46/0x54 [] do_last+0x7f6/0x996 [] ? inode_permission+0x42/0x44 [] path_openat+0x232/0x496 [] do_filp_open+0x3a/0x8a [] ? __alloc_fd+0x168/0x17a [] do_sys_open+0x70/0x102 [] ? trace_hardirqs_on_caller+0x160/0x197 [] SyS_open+0x1e/0x20 [] system_call_fastpath+0x16/0x1b Code: e5 41 54 53 48 89 f3 48 83 ec 10 48 23 56 78 48 39 c2 75 6c 31 f6 48 c7 RIP [] probes_open+0x3b/0xa7 RSP CR2: 00000005000000f9 ---[ end trace 35f17d68fc569897 ]--- The unregister_trace_probe() must be done first, and if it fails it must fail the removal of the kprobe. Several changes have already been made by Oleg Nesterov and Masami Hiramatsu to allow moving the unregister_probe_event() before the removal of the probe and exit the function if it fails. This prevents the tp structure from being used after it is freed. Link: http://lkml.kernel.org/r/20130704034038.819592356@goodmis.org Acked-by: Masami Hiramatsu Signed-off-by: Steven Rostedt --- kernel/trace/trace_kprobe.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 3811487e7a7a..243f6834d026 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c @@ -95,7 +95,7 @@ static __kprobes bool trace_probe_is_on_module(struct trace_probe *tp) } static int register_probe_event(struct trace_probe *tp); -static void unregister_probe_event(struct trace_probe *tp); +static int unregister_probe_event(struct trace_probe *tp); static DEFINE_MUTEX(probe_lock); static LIST_HEAD(probe_list); @@ -351,9 +351,12 @@ static int unregister_trace_probe(struct trace_probe *tp) if (trace_probe_is_enabled(tp)) return -EBUSY; + /* Will fail if probe is being used by ftrace or perf */ + if (unregister_probe_event(tp)) + return -EBUSY; + __unregister_trace_probe(tp); list_del(&tp->list); - unregister_probe_event(tp); return 0; } @@ -632,7 +635,9 @@ static int release_all_trace_probes(void) /* TODO: Use batch unregistration */ while (!list_empty(&probe_list)) { tp = list_entry(probe_list.next, struct trace_probe, list); - unregister_trace_probe(tp); + ret = unregister_trace_probe(tp); + if (ret) + goto end; free_trace_probe(tp); } @@ -1247,11 +1252,15 @@ static int register_probe_event(struct trace_probe *tp) return ret; } -static void unregister_probe_event(struct trace_probe *tp) +static int unregister_probe_event(struct trace_probe *tp) { + int ret; + /* tp->event is unregistered in trace_remove_event_call() */ - trace_remove_event_call(&tp->call); - kfree(tp->call.print_fmt); + ret = trace_remove_event_call(&tp->call); + if (!ret) + kfree(tp->call.print_fmt); + return ret; } /* Make a debugfs interface for controlling probe points */ From 8f898fbbe5ee5e20a77c4074472a1fd088dc47d1 Mon Sep 17 00:00:00 2001 From: Rik van Riel Date: Wed, 31 Jul 2013 22:14:21 -0400 Subject: [PATCH 1281/3400] sched/x86: Optimize switch_mm() for multi-threaded workloads Dick Fowles, Don Zickus and Joe Mario have been working on improvements to perf, and noticed heavy cache line contention on the mm_cpumask, running linpack on a 60 core / 120 thread system. The cause turned out to be unnecessary atomic accesses to the mm_cpumask. When in lazy TLB mode, the CPU is only removed from the mm_cpumask if there is a TLB flush event. Most of the time, no such TLB flush happens, and the kernel skips the TLB reload. It can also skip the atomic memory set & test. Here is a summary of Joe's test results: * The __schedule function dropped from 24% of all program cycles down to 5.5%. * The cacheline contention/hotness for accesses to that bitmask went from being the 1st/2nd hottest - down to the 84th hottest (0.3% of all shared misses which is now quite cold) * The average load latency for the bit-test-n-set instruction in __schedule dropped from 10k-15k cycles down to an average of 600 cycles. * The linpack program results improved from 133 GFlops to 144 GFlops. Peak GFlops rose from 133 to 153. Reported-by: Don Zickus Reported-by: Joe Mario Tested-by: Joe Mario Signed-off-by: Rik van Riel Reviewed-by: Paul Turner Acked-by: Linus Torvalds Link: http://lkml.kernel.org/r/20130731221421.616d3d20@annuminas.surriel.com [ Made the comments consistent around the modified code. ] Signed-off-by: Ingo Molnar --- arch/x86/include/asm/mmu_context.h | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h index cdbf36776106..be12c534fd59 100644 --- a/arch/x86/include/asm/mmu_context.h +++ b/arch/x86/include/asm/mmu_context.h @@ -45,22 +45,28 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, /* Re-load page tables */ load_cr3(next->pgd); - /* stop flush ipis for the previous mm */ + /* Stop flush ipis for the previous mm */ cpumask_clear_cpu(cpu, mm_cpumask(prev)); - /* - * load the LDT, if the LDT is different: - */ + /* 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 { + else { this_cpu_write(cpu_tlbstate.state, TLBSTATE_OK); BUG_ON(this_cpu_read(cpu_tlbstate.active_mm) != next); - if (!cpumask_test_and_set_cpu(cpu, mm_cpumask(next))) { - /* We were in lazy tlb mode and leave_mm disabled + if (!cpumask_test_cpu(cpu, mm_cpumask(next))) { + /* + * On established mms, the mm_cpumask is only changed + * from irq context, from ptep_clear_flush() while in + * lazy tlb mode, and here. Irqs are blocked during + * schedule, protecting us from simultaneous changes. + */ + cpumask_set_cpu(cpu, mm_cpumask(next)); + /* + * 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. */ From 71ffe9c77dd7a2b62207953091efa8dafec958dd Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 25 Jul 2013 10:37:49 +0200 Subject: [PATCH 1282/3400] netfilter: xt_TCPMSS: fix handling of malformed TCP header and options Make sure the packet has enough room for the TCP header and that it is not malformed. While at it, store tcph->doff*4 in a variable, as it is used several times. This patch also fixes a possible off by one in case of malformed TCP options. Reported-by: Julian Anastasov Signed-off-by: Pablo Neira Ayuso --- net/netfilter/xt_TCPMSS.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c index 7011c71646f0..6113cc7efffc 100644 --- a/net/netfilter/xt_TCPMSS.c +++ b/net/netfilter/xt_TCPMSS.c @@ -52,7 +52,8 @@ tcpmss_mangle_packet(struct sk_buff *skb, { const struct xt_tcpmss_info *info = par->targinfo; struct tcphdr *tcph; - unsigned int tcplen, i; + int len, tcp_hdrlen; + unsigned int i; __be16 oldval; u16 newmss; u8 *opt; @@ -64,11 +65,14 @@ tcpmss_mangle_packet(struct sk_buff *skb, if (!skb_make_writable(skb, skb->len)) return -1; - tcplen = skb->len - tcphoff; - tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); + len = skb->len - tcphoff; + if (len < (int)sizeof(struct tcphdr)) + return -1; - /* Header cannot be larger than the packet */ - if (tcplen < tcph->doff*4) + tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); + tcp_hdrlen = tcph->doff * 4; + + if (len < tcp_hdrlen) return -1; if (info->mss == XT_TCPMSS_CLAMP_PMTU) { @@ -87,9 +91,8 @@ tcpmss_mangle_packet(struct sk_buff *skb, newmss = info->mss; opt = (u_int8_t *)tcph; - for (i = sizeof(struct tcphdr); i < tcph->doff*4; i += optlen(opt, i)) { - if (opt[i] == TCPOPT_MSS && tcph->doff*4 - i >= TCPOLEN_MSS && - opt[i+1] == TCPOLEN_MSS) { + for (i = sizeof(struct tcphdr); i <= tcp_hdrlen - TCPOLEN_MSS; i += optlen(opt, i)) { + if (opt[i] == TCPOPT_MSS && opt[i+1] == TCPOLEN_MSS) { u_int16_t oldmss; oldmss = (opt[i+2] << 8) | opt[i+3]; @@ -112,9 +115,10 @@ tcpmss_mangle_packet(struct sk_buff *skb, } /* There is data after the header so the option can't be added - without moving it, and doing so may make the SYN packet - itself too large. Accept the packet unmodified instead. */ - if (tcplen > tcph->doff*4) + * without moving it, and doing so may make the SYN packet + * itself too large. Accept the packet unmodified instead. + */ + if (len > tcp_hdrlen) return 0; /* @@ -143,10 +147,10 @@ tcpmss_mangle_packet(struct sk_buff *skb, newmss = min(newmss, (u16)1220); opt = (u_int8_t *)tcph + sizeof(struct tcphdr); - memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr)); + memmove(opt + TCPOLEN_MSS, opt, len - sizeof(struct tcphdr)); inet_proto_csum_replace2(&tcph->check, skb, - htons(tcplen), htons(tcplen + TCPOLEN_MSS), 1); + htons(len), htons(len + TCPOLEN_MSS), 1); opt[0] = TCPOPT_MSS; opt[1] = TCPOLEN_MSS; opt[2] = (newmss & 0xff00) >> 8; From a206bcb3b02025b23137f3228109d72e0f835c05 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 25 Jul 2013 10:46:46 +0200 Subject: [PATCH 1283/3400] netfilter: xt_TCPOPTSTRIP: fix possible off by one access Fix a possible off by one access since optlen() touches opt[offset+1] unsafely when i == tcp_hdrlen(skb) - 1. This patch replaces tcp_hdrlen() by the local variable tcp_hdrlen that stores the TCP header length, to save some cycles. Reported-by: Julian Anastasov Signed-off-by: Pablo Neira Ayuso --- net/netfilter/xt_TCPOPTSTRIP.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/net/netfilter/xt_TCPOPTSTRIP.c b/net/netfilter/xt_TCPOPTSTRIP.c index b68fa191710f..625fa1d636a0 100644 --- a/net/netfilter/xt_TCPOPTSTRIP.c +++ b/net/netfilter/xt_TCPOPTSTRIP.c @@ -38,7 +38,7 @@ tcpoptstrip_mangle_packet(struct sk_buff *skb, struct tcphdr *tcph; u_int16_t n, o; u_int8_t *opt; - int len; + int len, tcp_hdrlen; /* This is a fragment, no TCP header is available */ if (par->fragoff != 0) @@ -52,7 +52,9 @@ tcpoptstrip_mangle_packet(struct sk_buff *skb, return NF_DROP; tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); - if (tcph->doff * 4 > len) + tcp_hdrlen = tcph->doff * 4; + + if (len < tcp_hdrlen) return NF_DROP; opt = (u_int8_t *)tcph; @@ -61,10 +63,10 @@ tcpoptstrip_mangle_packet(struct sk_buff *skb, * Walk through all TCP options - if we find some option to remove, * set all octets to %TCPOPT_NOP and adjust checksum. */ - for (i = sizeof(struct tcphdr); i < tcp_hdrlen(skb); i += optl) { + for (i = sizeof(struct tcphdr); i < tcp_hdrlen - 1; i += optl) { optl = optlen(opt, i); - if (i + optl > tcp_hdrlen(skb)) + if (i + optl > tcp_hdrlen) break; if (!tcpoptstrip_test_bit(info->strip_bmap, opt[i])) From 2865a8fb44cc32420407362cbda80c10fa09c6b2 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Thu, 1 Aug 2013 09:56:36 +0800 Subject: [PATCH 1284/3400] workqueue: copy workqueue_attrs with all fields $echo '0' > /sys/bus/workqueue/devices/xxx/numa $cat /sys/bus/workqueue/devices/xxx/numa I got 1. It should be 0, the reason is copy_workqueue_attrs() called in apply_workqueue_attrs() doesn't copy no_numa field. Fix it by making copy_workqueue_attrs() copy ->no_numa too. This would also make get_unbound_pool() set a pool's ->no_numa attribute according to the workqueue attributes used when the pool was created. While harmelss, as ->no_numa isn't a pool attribute, this is a bit confusing. Clear it explicitly. tj: Updated description and comments a bit. Signed-off-by: Shaohua Li Signed-off-by: Tejun Heo Cc: stable@vger.kernel.org --- kernel/workqueue.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 55f5f0afcd0d..726adc84b3ca 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -3416,6 +3416,12 @@ static void copy_workqueue_attrs(struct workqueue_attrs *to, { to->nice = from->nice; cpumask_copy(to->cpumask, from->cpumask); + /* + * Unlike hash and equality test, this function doesn't ignore + * ->no_numa as it is used for both pool and wq attrs. Instead, + * get_unbound_pool() explicitly clears ->no_numa after copying. + */ + to->no_numa = from->no_numa; } /* hash value of the content of @attr */ @@ -3583,6 +3589,12 @@ static struct worker_pool *get_unbound_pool(const struct workqueue_attrs *attrs) lockdep_set_subclass(&pool->lock, 1); /* see put_pwq() */ copy_workqueue_attrs(pool->attrs, attrs); + /* + * no_numa isn't a worker_pool attribute, always clear it. See + * 'struct workqueue_attrs' comments for detail. + */ + pool->attrs->no_numa = false; + /* if cpumask is contained inside a NUMA node, we belong to that node */ if (wq_numa_enabled) { for_each_node(node) { From 876ede8b2b9880615be0de3ec7b8afd0a1786e76 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Thu, 1 Aug 2013 09:51:47 +0800 Subject: [PATCH 1285/3400] cgroup: restructure the failure path in cgroup_write_event_control() It uses a single label and checks the validity of each pointer. This is err-prone, and actually we had a bug because one of the check was insufficient. Use multi lables as we do in other places. v2: - drop initializations of local variables. Signed-off-by: Li Zefan Signed-off-by: Tejun Heo --- kernel/cgroup.c | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 3f6593333525..9f6dab22289e 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -3934,11 +3934,11 @@ static void cgroup_event_ptable_queue_proc(struct file *file, static int cgroup_write_event_control(struct cgroup *cgrp, struct cftype *cft, const char *buffer) { - struct cgroup_event *event = NULL; + struct cgroup_event *event; struct cgroup *cgrp_cfile; unsigned int efd, cfd; - struct file *efile = NULL; - struct file *cfile = NULL; + struct file *efile; + struct file *cfile; char *endp; int ret; @@ -3964,31 +3964,31 @@ static int cgroup_write_event_control(struct cgroup *cgrp, struct cftype *cft, efile = eventfd_fget(efd); if (IS_ERR(efile)) { ret = PTR_ERR(efile); - goto fail; + goto out_kfree; } event->eventfd = eventfd_ctx_fileget(efile); if (IS_ERR(event->eventfd)) { ret = PTR_ERR(event->eventfd); - goto fail; + goto out_put_efile; } cfile = fget(cfd); if (!cfile) { ret = -EBADF; - goto fail; + goto out_put_eventfd; } /* the process need read permission on control file */ /* AV: shouldn't we check that it's been opened for read instead? */ ret = inode_permission(file_inode(cfile), MAY_READ); if (ret < 0) - goto fail; + goto out_put_cfile; event->cft = __file_cft(cfile); if (IS_ERR(event->cft)) { ret = PTR_ERR(event->cft); - goto fail; + goto out_put_cfile; } /* @@ -3998,18 +3998,18 @@ static int cgroup_write_event_control(struct cgroup *cgrp, struct cftype *cft, cgrp_cfile = __d_cgrp(cfile->f_dentry->d_parent); if (cgrp_cfile != cgrp) { ret = -EINVAL; - goto fail; + goto out_put_cfile; } if (!event->cft->register_event || !event->cft->unregister_event) { ret = -EINVAL; - goto fail; + goto out_put_cfile; } ret = event->cft->register_event(cgrp, event->cft, event->eventfd, buffer); if (ret) - goto fail; + goto out_put_cfile; efile->f_op->poll(efile, &event->pt); @@ -4029,16 +4029,13 @@ static int cgroup_write_event_control(struct cgroup *cgrp, struct cftype *cft, return 0; -fail: - if (cfile) - fput(cfile); - - if (event && event->eventfd && !IS_ERR(event->eventfd)) - eventfd_ctx_put(event->eventfd); - - if (!IS_ERR_OR_NULL(efile)) - fput(efile); - +out_put_cfile: + fput(cfile); +out_put_eventfd: + eventfd_ctx_put(event->eventfd); +out_put_efile: + fput(efile); +out_kfree: kfree(event); return ret; From b395890a092d8ecbe54f005179e3dec4b6bf752a Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Thu, 1 Aug 2013 09:52:15 +0800 Subject: [PATCH 1286/3400] cgroup: rename cgroup_pidlist->mutex It's a rw_semaphore not a mutex. Signed-off-by: Li Zefan Signed-off-by: Tejun Heo --- kernel/cgroup.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 9f6dab22289e..9420662df87e 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -3436,7 +3436,7 @@ struct cgroup_pidlist { /* pointer to the cgroup we belong to, for list removal purposes */ struct cgroup *owner; /* protects the other fields */ - struct rw_semaphore mutex; + struct rw_semaphore rwsem; }; /* @@ -3509,7 +3509,7 @@ static struct cgroup_pidlist *cgroup_pidlist_find(struct cgroup *cgrp, struct pid_namespace *ns = task_active_pid_ns(current); /* - * We can't drop the pidlist_mutex before taking the l->mutex in case + * We can't drop the pidlist_mutex before taking the l->rwsem in case * the last ref-holder is trying to remove l from the list at the same * time. Holding the pidlist_mutex precludes somebody taking whichever * list we find out from under us - compare release_pid_array(). @@ -3518,7 +3518,7 @@ static struct cgroup_pidlist *cgroup_pidlist_find(struct cgroup *cgrp, list_for_each_entry(l, &cgrp->pidlists, links) { if (l->key.type == type && l->key.ns == ns) { /* make sure l doesn't vanish out from under us */ - down_write(&l->mutex); + down_write(&l->rwsem); mutex_unlock(&cgrp->pidlist_mutex); return l; } @@ -3529,8 +3529,8 @@ static struct cgroup_pidlist *cgroup_pidlist_find(struct cgroup *cgrp, mutex_unlock(&cgrp->pidlist_mutex); return l; } - init_rwsem(&l->mutex); - down_write(&l->mutex); + init_rwsem(&l->rwsem); + down_write(&l->rwsem); l->key.type = type; l->key.ns = get_pid_ns(ns); l->owner = cgrp; @@ -3591,7 +3591,7 @@ static int pidlist_array_load(struct cgroup *cgrp, enum cgroup_filetype type, l->list = array; l->length = length; l->use_count++; - up_write(&l->mutex); + up_write(&l->rwsem); *lp = l; return 0; } @@ -3669,7 +3669,7 @@ static void *cgroup_pidlist_start(struct seq_file *s, loff_t *pos) int index = 0, pid = *pos; int *iter; - down_read(&l->mutex); + down_read(&l->rwsem); if (pid) { int end = l->length; @@ -3696,7 +3696,7 @@ static void *cgroup_pidlist_start(struct seq_file *s, loff_t *pos) static void cgroup_pidlist_stop(struct seq_file *s, void *v) { struct cgroup_pidlist *l = s->private; - up_read(&l->mutex); + up_read(&l->rwsem); } static void *cgroup_pidlist_next(struct seq_file *s, void *v, loff_t *pos) @@ -3742,7 +3742,7 @@ static void cgroup_release_pid_array(struct cgroup_pidlist *l) * pidlist_mutex, we have to take pidlist_mutex first. */ mutex_lock(&l->owner->pidlist_mutex); - down_write(&l->mutex); + down_write(&l->rwsem); BUG_ON(!l->use_count); if (!--l->use_count) { /* we're the last user if refcount is 0; remove and free */ @@ -3750,12 +3750,12 @@ static void cgroup_release_pid_array(struct cgroup_pidlist *l) mutex_unlock(&l->owner->pidlist_mutex); pidlist_free(l->list); put_pid_ns(l->key.ns); - up_write(&l->mutex); + up_write(&l->rwsem); kfree(l); return; } mutex_unlock(&l->owner->pidlist_mutex); - up_write(&l->mutex); + up_write(&l->rwsem); } static int cgroup_pidlist_release(struct inode *inode, struct file *file) From f091f3f07328f75d20a2a5970d1f8b58d95fc990 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lothar=20Wa=C3=9Fmann?= Date: Wed, 31 Jul 2013 16:44:29 +0200 Subject: [PATCH 1287/3400] ASoC: sgtl5000: prevent playback to be muted when terminating concurrent capture MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a sound capture/playback is terminated while a playback/capture is running, power_vag_event() will clear SGTL5000_CHIP_ANA_POWER in the SND_SOC_DAPM_PRE_PMD event, thus muting the respective other channel. Don't clear SGTL5000_CHIP_ANA_POWER when both DAC and ADC are active to prevent this. Signed-off-by: Lothar Waßmann Reviewed-by: Fabio Estevam Signed-off-by: Mark Brown --- sound/soc/codecs/sgtl5000.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 6c8a9e7bee25..9303c7d011b2 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -153,6 +153,8 @@ static int mic_bias_event(struct snd_soc_dapm_widget *w, static int power_vag_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { + const u32 mask = SGTL5000_DAC_POWERUP | SGTL5000_ADC_POWERUP; + switch (event) { case SND_SOC_DAPM_POST_PMU: snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER, @@ -160,9 +162,17 @@ static int power_vag_event(struct snd_soc_dapm_widget *w, break; case SND_SOC_DAPM_PRE_PMD: - snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER, - SGTL5000_VAG_POWERUP, 0); - msleep(400); + /* + * Don't clear VAG_POWERUP, when both DAC and ADC are + * operational to prevent inadvertently starving the + * other one of them. + */ + if ((snd_soc_read(w->codec, SGTL5000_CHIP_ANA_POWER) & + mask) != mask) { + snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER, + SGTL5000_VAG_POWERUP, 0); + msleep(400); + } break; default: break; From 65f2b226763bc348a9b9145aa5e17e7e3f6d8c35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lothar=20Wa=C3=9Fmann?= Date: Wed, 31 Jul 2013 16:44:30 +0200 Subject: [PATCH 1288/3400] ASoC: sgtl5000: fix buggy 'Capture Attenuate Switch' control MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The SGTL5000 Capture Attenuate Switch (or "ADC Volume Range Reduction" as it is called in the manual) is single bit only. Signed-off-by: Lothar Waßmann Reviewed-by: Fabio Estevam Signed-off-by: Mark Brown --- sound/soc/codecs/sgtl5000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 9303c7d011b2..760e8bfeacaa 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -398,7 +398,7 @@ static const struct snd_kcontrol_new sgtl5000_snd_controls[] = { SOC_DOUBLE("Capture Volume", SGTL5000_CHIP_ANA_ADC_CTRL, 0, 4, 0xf, 0), SOC_SINGLE_TLV("Capture Attenuate Switch (-6dB)", SGTL5000_CHIP_ANA_ADC_CTRL, - 8, 2, 0, capture_6db_attenuate), + 8, 1, 0, capture_6db_attenuate), SOC_SINGLE("Capture ZC Switch", SGTL5000_CHIP_ANA_CTRL, 1, 1, 0), SOC_DOUBLE_TLV("Headphone Playback Volume", From ce1be10bf6dc8406ae773f0ac6265585a4154d37 Mon Sep 17 00:00:00 2001 From: Yijing Wang Date: Thu, 1 Aug 2013 21:05:27 +0800 Subject: [PATCH 1289/3400] PCI: Fix comment typo for pci_add_cap_save_buffer() Fix trivial comment typo for pci_add_cap_save_buffer(). Signed-off-by: Yijing Wang Signed-off-by: Bjorn Helgaas --- drivers/pci/pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index e37fea6e178d..69dcd32e0fe8 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1992,7 +1992,7 @@ static void pci_add_saved_cap(struct pci_dev *pci_dev, } /** - * pci_add_save_buffer - allocate buffer for saving given capability registers + * pci_add_cap_save_buffer - allocate buffer for saving given capability registers * @dev: the PCI device * @cap: the capability to allocate the buffer for * @size: requested size of the buffer From fe581391147cb3d738d961d0f1233d91a9e1113c Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 1 Aug 2013 18:30:38 +0200 Subject: [PATCH 1290/3400] ASoC: dapm: Fix empty list check in dapm_new_mux() list_first_entry() will always return a valid pointer, even if the list is empty. So the check whether path is NULL will always be false. So we end up calling dapm_create_or_share_mixmux_kcontrol() with a path struct that points right in the middle of the widget struct and by trying to modify the path the widgets memory will become corrupted. Fix this by using list_emtpy() to check if the widget doesn't have any paths. Signed-off-by: Lars-Peter Clausen Tested-by: Stephen Warren Signed-off-by: Mark Brown Cc: stable@vger.kernel.org --- sound/soc/soc-dapm.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index bd16010441cc..4375c9f2b791 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -679,13 +679,14 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w) return -EINVAL; } - path = list_first_entry(&w->sources, struct snd_soc_dapm_path, - list_sink); - if (!path) { + if (list_empty(&w->sources)) { dev_err(dapm->dev, "ASoC: mux %s has no paths\n", w->name); return -EINVAL; } + path = list_first_entry(&w->sources, struct snd_soc_dapm_path, + list_sink); + ret = dapm_create_or_share_mixmux_kcontrol(w, 0, path); if (ret < 0) return ret; From 3a20446f02bfb71d68ae9ec673268bb7823f878c Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 1 Aug 2013 17:09:23 -0400 Subject: [PATCH 1291/3400] USB: EHCI: keep better track of resuming ports The ehci-hcd driver isn't as careful as it should be about the way it uses ehci->resuming_ports. One of the omissions was fixed recently by commit 47a64a13d54 (USB: EHCI: Fix resume signalling on remote wakeup), but there are other places that need attention: When a port's suspend feature is explicitly cleared, the corresponding bit in resuming_ports should be set and the core should be notified about the port resume. We don't need to clear a resuming_ports bit when a reset completes. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hub.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 6dce37555c4f..6d0e59306ed9 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -801,6 +801,8 @@ static int ehci_hub_control ( ehci_writel(ehci, temp | PORT_RESUME, status_reg); ehci->reset_done[wIndex] = jiffies + msecs_to_jiffies(20); + set_bit(wIndex, &ehci->resuming_ports); + usb_hcd_start_port_resume(&hcd->self, wIndex); break; case USB_PORT_FEAT_C_SUSPEND: clear_bit(wIndex, &ehci->port_c_suspend); @@ -911,7 +913,6 @@ static int ehci_hub_control ( ehci->reset_done[wIndex])) { status |= USB_PORT_STAT_C_RESET << 16; ehci->reset_done [wIndex] = 0; - clear_bit(wIndex, &ehci->resuming_ports); /* force reset to complete */ ehci_writel(ehci, temp & ~(PORT_RWC_BITS | PORT_RESET), From 6753f4cf29046f4a2ae68c3a93bf6e6e6dce9fb7 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 1 Aug 2013 17:09:28 -0400 Subject: [PATCH 1292/3400] USB: EHCI: don't depend on hardware for tracking port resets and resumes In theory, an EHCI controller can turn off the PORT_RESUME or PORT_RESET bits in a port status register all by itself (and some controllers actually do this). We shouldn't depend on these bits being set correctly. This patch rearranges the code in ehci-hcd that handles completion of port resets and resumes. We guarantee that ehci->reset_done[portnum] is nonzero if a reset or resume is in progress, and that the portnum bit is set in ehci->resuming_ports if the operation is a resume. (To help enforce this guarantee, the patch prevents suspended ports from being reset.) Therefore it's not necessary to look at the port status bits to learn what's going on. The patch looks bigger than it really is, because it changes the indentation level of a sizeable region of code. Most of what it actually does is interchange some tests. The only functional changes are testing reset_done and resuming_ports rather than PORT_RESUME and PORT_RESET, removing a now-unnecessary check for spontaneous resets of the PORT_RESUME and PORT_RESET bits, and preventing a suspended or resuming port from being reset. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hub.c | 58 ++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 33 deletions(-) diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 6d0e59306ed9..6e69ee1a3371 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -867,11 +867,11 @@ static int ehci_hub_control ( } } - /* whoever resumes must GetPortStatus to complete it!! */ - if (temp & PORT_RESUME) { + /* no reset or resume pending */ + if (!ehci->reset_done[wIndex]) { /* Remote Wakeup received? */ - if (!ehci->reset_done[wIndex]) { + if (temp & PORT_RESUME) { /* resume signaling for 20 msec */ ehci->reset_done[wIndex] = jiffies + msecs_to_jiffies(20); @@ -882,35 +882,32 @@ static int ehci_hub_control ( ehci->reset_done[wIndex]); } - /* resume completed? */ - else if (time_after_eq(jiffies, - ehci->reset_done[wIndex])) { - clear_bit(wIndex, &ehci->suspended_ports); - set_bit(wIndex, &ehci->port_c_suspend); - ehci->reset_done[wIndex] = 0; - usb_hcd_end_port_resume(&hcd->self, wIndex); + /* reset or resume not yet complete */ + } else if (!time_after_eq(jiffies, ehci->reset_done[wIndex])) { + ; /* wait until it is complete */ - /* stop resume signaling */ - temp &= ~(PORT_RWC_BITS | - PORT_SUSPEND | PORT_RESUME); - ehci_writel(ehci, temp, status_reg); - clear_bit(wIndex, &ehci->resuming_ports); - retval = ehci_handshake(ehci, status_reg, - PORT_RESUME, 0, 2000 /* 2msec */); - if (retval != 0) { - ehci_err(ehci, - "port %d resume error %d\n", + /* resume completed */ + } else if (test_bit(wIndex, &ehci->resuming_ports)) { + clear_bit(wIndex, &ehci->suspended_ports); + set_bit(wIndex, &ehci->port_c_suspend); + ehci->reset_done[wIndex] = 0; + usb_hcd_end_port_resume(&hcd->self, wIndex); + + /* stop resume signaling */ + temp &= ~(PORT_RWC_BITS | PORT_SUSPEND | PORT_RESUME); + ehci_writel(ehci, temp, status_reg); + clear_bit(wIndex, &ehci->resuming_ports); + retval = ehci_handshake(ehci, status_reg, + PORT_RESUME, 0, 2000 /* 2msec */); + if (retval != 0) { + ehci_err(ehci, "port %d resume error %d\n", wIndex + 1, retval); - goto error; - } - temp = ehci_readl(ehci, status_reg); + goto error; } - } + temp = ehci_readl(ehci, status_reg); /* whoever resets must GetPortStatus to complete it!! */ - if ((temp & PORT_RESET) - && time_after_eq(jiffies, - ehci->reset_done[wIndex])) { + } else { status |= USB_PORT_STAT_C_RESET << 16; ehci->reset_done [wIndex] = 0; @@ -933,11 +930,6 @@ static int ehci_hub_control ( ehci_readl(ehci, status_reg)); } - if (!(temp & (PORT_RESUME|PORT_RESET))) { - ehci->reset_done[wIndex] = 0; - clear_bit(wIndex, &ehci->resuming_ports); - } - /* transfer dedicated ports to the companion hc */ if ((temp & PORT_CONNECT) && test_bit(wIndex, &ehci->companion_ports)) { @@ -1058,7 +1050,7 @@ static int ehci_hub_control ( status_reg); break; case USB_PORT_FEAT_RESET: - if (temp & PORT_RESUME) + if (temp & (PORT_SUSPEND|PORT_RESUME)) goto error; /* line status bits may report this as low speed, * which can be fine if this root hub has a From 0b99d58902dd82fa51216eb8e0d6ddd8c43e90e4 Mon Sep 17 00:00:00 2001 From: Lidza Louina Date: Thu, 1 Aug 2013 17:00:20 -0400 Subject: [PATCH 1293/3400] staging: dgnc: add dgnc digi driver This patch adds the DGNC driver. This is a TTY Serial Port Driver for the Digi International Neo and Classic PCI based product line by Digi International . This driver isn't hooked up to the build system because it doesn't build, it merely adds the driver written by Digi to the kernel tree so that it can be cleaned up and fixed up properly over time. Cc: Mark Hounschell Signed-off-by: Lidza Louina Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dgnc/Kconfig | 6 + drivers/staging/dgnc/Makefile | 7 + drivers/staging/dgnc/Makefile.inc | 133 + drivers/staging/dgnc/dgnc_cls.c | 1412 +++++++++++ drivers/staging/dgnc/dgnc_cls.h | 90 + drivers/staging/dgnc/dgnc_driver.c | 1028 ++++++++ drivers/staging/dgnc/dgnc_driver.h | 566 +++++ drivers/staging/dgnc/dgnc_kcompat.h | 91 + drivers/staging/dgnc/dgnc_mgmt.c | 313 +++ drivers/staging/dgnc/dgnc_mgmt.h | 37 + drivers/staging/dgnc/dgnc_neo.c | 1977 +++++++++++++++ drivers/staging/dgnc/dgnc_neo.h | 157 ++ drivers/staging/dgnc/dgnc_pci.h | 77 + drivers/staging/dgnc/dgnc_proc.c | 1551 ++++++++++++ drivers/staging/dgnc/dgnc_proc.h | 147 ++ drivers/staging/dgnc/dgnc_sysfs.c | 761 ++++++ drivers/staging/dgnc/dgnc_sysfs.h | 49 + drivers/staging/dgnc/dgnc_trace.c | 187 ++ drivers/staging/dgnc/dgnc_trace.h | 45 + drivers/staging/dgnc/dgnc_tty.c | 3648 +++++++++++++++++++++++++++ drivers/staging/dgnc/dgnc_tty.h | 42 + drivers/staging/dgnc/dgnc_types.h | 36 + drivers/staging/dgnc/digi.h | 419 +++ drivers/staging/dgnc/dpacompat.h | 115 + 24 files changed, 12894 insertions(+) create mode 100644 drivers/staging/dgnc/Kconfig create mode 100644 drivers/staging/dgnc/Makefile create mode 100644 drivers/staging/dgnc/Makefile.inc create mode 100644 drivers/staging/dgnc/dgnc_cls.c create mode 100644 drivers/staging/dgnc/dgnc_cls.h create mode 100644 drivers/staging/dgnc/dgnc_driver.c create mode 100644 drivers/staging/dgnc/dgnc_driver.h create mode 100644 drivers/staging/dgnc/dgnc_kcompat.h create mode 100644 drivers/staging/dgnc/dgnc_mgmt.c create mode 100644 drivers/staging/dgnc/dgnc_mgmt.h create mode 100644 drivers/staging/dgnc/dgnc_neo.c create mode 100644 drivers/staging/dgnc/dgnc_neo.h create mode 100644 drivers/staging/dgnc/dgnc_pci.h create mode 100644 drivers/staging/dgnc/dgnc_proc.c create mode 100644 drivers/staging/dgnc/dgnc_proc.h create mode 100644 drivers/staging/dgnc/dgnc_sysfs.c create mode 100644 drivers/staging/dgnc/dgnc_sysfs.h create mode 100644 drivers/staging/dgnc/dgnc_trace.c create mode 100644 drivers/staging/dgnc/dgnc_trace.h create mode 100644 drivers/staging/dgnc/dgnc_tty.c create mode 100644 drivers/staging/dgnc/dgnc_tty.h create mode 100644 drivers/staging/dgnc/dgnc_types.h create mode 100644 drivers/staging/dgnc/digi.h create mode 100644 drivers/staging/dgnc/dpacompat.h diff --git a/drivers/staging/dgnc/Kconfig b/drivers/staging/dgnc/Kconfig new file mode 100644 index 000000000000..23daaa5d520e --- /dev/null +++ b/drivers/staging/dgnc/Kconfig @@ -0,0 +1,6 @@ +config DGNC + tristate "Digi Neo and Classic PCI Products" + default n + depends on TTY + ---help--- + Driver for the Digi International Neo and Classic PCI based product line. diff --git a/drivers/staging/dgnc/Makefile b/drivers/staging/dgnc/Makefile new file mode 100644 index 000000000000..c4c96dc5a541 --- /dev/null +++ b/drivers/staging/dgnc/Makefile @@ -0,0 +1,7 @@ +EXTRA_CFLAGS += -DDG_NAME=\"dgnc-1.3-16\" -DDG_PART=\"40002369_F\" + +obj-$(CONFIG_DGNC) += dgnc.o + +dgnc-objs := dgnc_cls.o dgnc_driver.o\ + dgnc_mgmt.o dgnc_neo.o\ + dgnc_proc.o dgnc_trace.o dgnc_tty.o dgnc_sysfs.o diff --git a/drivers/staging/dgnc/Makefile.inc b/drivers/staging/dgnc/Makefile.inc new file mode 100644 index 000000000000..6ca38c731c39 --- /dev/null +++ b/drivers/staging/dgnc/Makefile.inc @@ -0,0 +1,133 @@ +# +# From Makefile.inc +# + +# +# Common definitions go here. +# + +# +# TRUE_VERSION is the version string used in the driver build, +# it is intended to be in the form: +# +# 2.0-0 +# +# A string noting a particular special modification could be +# used as well. This string will be reported when the driver +# is loaded, and will be exposed by its /proc/dgnc/info +# interface. +# +TRUE_VERSION="1.3-16" + +# +# DGNC_PART_NUM is the part number string for the driver package. +# It should be in the form: +# +# 40002369_A +# +DGNC_PART_NUM=40002369_F + +# +# DGNC_REL_NOTE is the part number string for the driver release +# notes. It should be in the form: +# +# 93000517_A +# +DGNC_REL_NOTE=93000517_F + +# +# DGNC_PKG_VER is the "version" number string included in the +# various documentation and packaging files. It should be +# in the form: +# +# 1.0 +# +DGNC_PKG_VER=1.3 + +# +# DGNC_PKG_REV is the "revision" of this version. Together, +# a linux module revision is built with: +# +# ${DGNC_PKG_VER}-${DGNC_PKG_REV} +# +DGNC_PKG_REV=16 + +# +# DRP_PKG_DATE is the "date" string included in (for now) the +# release notes. It should be in the form: +# +# 11/04/2003 +# +DGNC_PKG_DATE=10/17/2008 + +INIT_DIR= $(shell \ + if [ -d /etc/rc.d/init.d ]; \ + then echo "$(RPM_BUILD_ROOT)/etc/rc.d/init.d"; \ + else echo "$(RPM_BUILD_ROOT)/etc/init.d"; fi) + +# +# Miscelaneous path macro's +# + +PACKAGE= dgnc +DEVDIR= /dev/dg/$(PACKAGE) +SRCDIR= /usr/src/dg/$(PACKAGE) +BINDIR= /usr/bin +DRVLIBDIR= /etc/$(PACKAGE) +MANDIR= /usr/man +USRLIBDIR= /usr/lib +DGNCDIR= /etc/dgnc + + +INIT_DIR= $(shell \ + if [ -d /etc/rc.d/init.d ]; \ + then echo "/etc/rc.d/init.d"; \ + else echo "/etc/init.d"; fi) + + +# +# From Makefile +# +ifndef MYPWD +MYPWD = $(shell pwd) +endif + +ifeq ($(KERNDIR),) + KERNVERS := $(shell uname -r) + KERNDIR :=/lib/modules/${KERNVERS}/ +endif + +# Grab version and other important stuff + +RPMNAME := $(PACKAGE)-$(TRUE_VERSION) + +PARTNUM := $(DGNC_PART_NUM) + +RELNOTES := $(DGNC_REL_NOTE) + +MODDIR = $(shell echo $(BUILDROOT)/lib/modules/3.4.36-lcrs/misc) +LSMOD = /sbin/lsmod +RMMOD = /sbin/rmmod +INSMOD = /sbin/insmod +NEW_TTY_LOCKING = No +NEW_TTY_BUFFERING = No +REGISTER_TTYS_WITH_SYSFS = No + +# Send in some extra things... +EXTRA_CFLAGS += -I${MYPWD} -I${MYPWD}/include -I${MYPWD}/../../commoninc\ + -I${MYPWD}/../../dpa -DLINUX -DDG_NAME=\"$(RPMNAME)\"\ + -DDG_PART=\"$(PARTNUM)\" -DDGNC_TRACER + +ifeq ($(NEW_TTY_LOCKING),Yes) + EXTRA_CFLAGS += -DNEW_TTY_LOCKING +endif + +ifeq ($(NEW_TTY_BUFFERING),Yes) + EXTRA_CFLAGS += -DNEW_TTY_BUFFERING +endif + +ifeq ($(REGISTER_TTYS_WITH_SYSFS),Yes) + EXTRA_CFLAGS += -DREGISTER_TTYS_WITH_SYSFS +endif + +# Conform to correct kbuild conventions... diff --git a/drivers/staging/dgnc/dgnc_cls.c b/drivers/staging/dgnc/dgnc_cls.c new file mode 100644 index 000000000000..83ded18e4ae2 --- /dev/null +++ b/drivers/staging/dgnc/dgnc_cls.c @@ -0,0 +1,1412 @@ +/* + * Copyright 2003 Digi International (www.digi.com) + * Scott H Kilau + * + * 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, EXPRESS OR IMPLIED; 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. + * + * + * NOTE TO LINUX KERNEL HACKERS: DO NOT REFORMAT THIS CODE! + * + * This is shared code between Digi's CVS archive and the + * Linux Kernel sources. + * Changing the source just for reformatting needlessly breaks + * our CVS diff history. + * + * Send any bug fixes/changes to: Eng.Linux at digi dot com. + * Thank you. + * + * + * $Id: dgnc_cls.c,v 1.1.1.1 2009/05/20 12:19:19 markh Exp $ + */ + +#include +#include +#include /* For jiffies, task states */ +#include /* For tasklet and interrupt structs/defines */ +#include /* For udelay */ +#include /* For read[bwl]/write[bwl] */ +#include /* For struct async_serial */ +#include /* For the various UART offsets */ +#include + +#include "dgnc_driver.h" /* Driver main header file */ +#include "dgnc_cls.h" +#include "dgnc_tty.h" +#include "dgnc_trace.h" + +static inline void cls_parse_isr(struct board_t *brd, uint port); +static inline void cls_clear_break(struct channel_t *ch, int force); +static inline void cls_set_cts_flow_control(struct channel_t *ch); +static inline void cls_set_rts_flow_control(struct channel_t *ch); +static inline void cls_set_ixon_flow_control(struct channel_t *ch); +static inline void cls_set_ixoff_flow_control(struct channel_t *ch); +static inline void cls_set_no_output_flow_control(struct channel_t *ch); +static inline void cls_set_no_input_flow_control(struct channel_t *ch); +static void cls_parse_modem(struct channel_t *ch, uchar signals); +static void cls_tasklet(unsigned long data); +static void cls_vpd(struct board_t *brd); +static void cls_uart_init(struct channel_t *ch); +static void cls_uart_off(struct channel_t *ch); +static int cls_drain(struct tty_struct *tty, uint seconds); +static void cls_param(struct tty_struct *tty); +static void cls_assert_modem_signals(struct channel_t *ch); +static void cls_flush_uart_write(struct channel_t *ch); +static void cls_flush_uart_read(struct channel_t *ch); +static void cls_disable_receiver(struct channel_t *ch); +static void cls_enable_receiver(struct channel_t *ch); +static void cls_send_break(struct channel_t *ch, int msecs); +static void cls_send_start_character(struct channel_t *ch); +static void cls_send_stop_character(struct channel_t *ch); +static void cls_copy_data_from_uart_to_queue(struct channel_t *ch); +static void cls_copy_data_from_queue_to_uart(struct channel_t *ch); +static uint cls_get_uart_bytes_left(struct channel_t *ch); +static void cls_send_immediate_char(struct channel_t *ch, unsigned char); +static irqreturn_t cls_intr(int irq, void *voidbrd); + +struct board_ops dgnc_cls_ops = { + .tasklet = cls_tasklet, + .intr = cls_intr, + .uart_init = cls_uart_init, + .uart_off = cls_uart_off, + .drain = cls_drain, + .param = cls_param, + .vpd = cls_vpd, + .assert_modem_signals = cls_assert_modem_signals, + .flush_uart_write = cls_flush_uart_write, + .flush_uart_read = cls_flush_uart_read, + .disable_receiver = cls_disable_receiver, + .enable_receiver = cls_enable_receiver, + .send_break = cls_send_break, + .send_start_character = cls_send_start_character, + .send_stop_character = cls_send_stop_character, + .copy_data_from_queue_to_uart = cls_copy_data_from_queue_to_uart, + .get_uart_bytes_left = cls_get_uart_bytes_left, + .send_immediate_char = cls_send_immediate_char +}; + + +static inline void cls_set_cts_flow_control(struct channel_t *ch) +{ + uchar lcrb = readb(&ch->ch_cls_uart->lcr); + uchar ier = readb(&ch->ch_cls_uart->ier); + uchar isr_fcr = 0; + + DPR_PARAM(("Setting CTSFLOW\n")); + + /* + * The Enhanced Register Set may only be accessed when + * the Line Control Register is set to 0xBFh. + */ + writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr); + + isr_fcr = readb(&ch->ch_cls_uart->isr_fcr); + + /* Turn on CTS flow control, turn off IXON flow control */ + isr_fcr |= (UART_EXAR654_EFR_ECB | UART_EXAR654_EFR_CTSDSR); + isr_fcr &= ~(UART_EXAR654_EFR_IXON); + + writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr); + + /* Write old LCR value back out, which turns enhanced access off */ + writeb(lcrb, &ch->ch_cls_uart->lcr); + + /* Enable interrupts for CTS flow, turn off interrupts for received XOFF chars */ + ier |= (UART_EXAR654_IER_CTSDSR); + ier &= ~(UART_EXAR654_IER_XOFF); + writeb(ier, &ch->ch_cls_uart->ier); + + /* Set the usual FIFO values */ + writeb((UART_FCR_ENABLE_FIFO), &ch->ch_cls_uart->isr_fcr); + + writeb((UART_FCR_ENABLE_FIFO | UART_16654_FCR_RXTRIGGER_56 | + UART_16654_FCR_TXTRIGGER_16 | UART_FCR_CLEAR_RCVR), + &ch->ch_cls_uart->isr_fcr); + + ch->ch_t_tlevel = 16; + +} + + +static inline void cls_set_ixon_flow_control(struct channel_t *ch) +{ + uchar lcrb = readb(&ch->ch_cls_uart->lcr); + uchar ier = readb(&ch->ch_cls_uart->ier); + uchar isr_fcr = 0; + + DPR_PARAM(("Setting IXON FLOW\n")); + + /* + * The Enhanced Register Set may only be accessed when + * the Line Control Register is set to 0xBFh. + */ + writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr); + + isr_fcr = readb(&ch->ch_cls_uart->isr_fcr); + + /* Turn on IXON flow control, turn off CTS flow control */ + isr_fcr |= (UART_EXAR654_EFR_ECB | UART_EXAR654_EFR_IXON); + isr_fcr &= ~(UART_EXAR654_EFR_CTSDSR); + + writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr); + + /* Now set our current start/stop chars while in enhanced mode */ + writeb(ch->ch_startc, &ch->ch_cls_uart->mcr); + writeb(0, &ch->ch_cls_uart->lsr); + writeb(ch->ch_stopc, &ch->ch_cls_uart->msr); + writeb(0, &ch->ch_cls_uart->spr); + + /* Write old LCR value back out, which turns enhanced access off */ + writeb(lcrb, &ch->ch_cls_uart->lcr); + + /* Disable interrupts for CTS flow, turn on interrupts for received XOFF chars */ + ier &= ~(UART_EXAR654_IER_CTSDSR); + ier |= (UART_EXAR654_IER_XOFF); + writeb(ier, &ch->ch_cls_uart->ier); + + /* Set the usual FIFO values */ + writeb((UART_FCR_ENABLE_FIFO), &ch->ch_cls_uart->isr_fcr); + + writeb((UART_FCR_ENABLE_FIFO | UART_16654_FCR_RXTRIGGER_16 | + UART_16654_FCR_TXTRIGGER_16 | UART_FCR_CLEAR_RCVR), + &ch->ch_cls_uart->isr_fcr); + +} + + +static inline void cls_set_no_output_flow_control(struct channel_t *ch) +{ + uchar lcrb = readb(&ch->ch_cls_uart->lcr); + uchar ier = readb(&ch->ch_cls_uart->ier); + uchar isr_fcr = 0; + + DPR_PARAM(("Unsetting Output FLOW\n")); + + /* + * The Enhanced Register Set may only be accessed when + * the Line Control Register is set to 0xBFh. + */ + writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr); + + isr_fcr = readb(&ch->ch_cls_uart->isr_fcr); + + /* Turn off IXON flow control, turn off CTS flow control */ + isr_fcr |= (UART_EXAR654_EFR_ECB); + isr_fcr &= ~(UART_EXAR654_EFR_CTSDSR | UART_EXAR654_EFR_IXON); + + writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr); + + /* Write old LCR value back out, which turns enhanced access off */ + writeb(lcrb, &ch->ch_cls_uart->lcr); + + /* Disable interrupts for CTS flow, turn off interrupts for received XOFF chars */ + ier &= ~(UART_EXAR654_IER_CTSDSR); + ier &= ~(UART_EXAR654_IER_XOFF); + writeb(ier, &ch->ch_cls_uart->ier); + + /* Set the usual FIFO values */ + writeb((UART_FCR_ENABLE_FIFO), &ch->ch_cls_uart->isr_fcr); + + writeb((UART_FCR_ENABLE_FIFO | UART_16654_FCR_RXTRIGGER_16 | + UART_16654_FCR_TXTRIGGER_16 | UART_FCR_CLEAR_RCVR), + &ch->ch_cls_uart->isr_fcr); + + ch->ch_r_watermark = 0; + ch->ch_t_tlevel = 16; + ch->ch_r_tlevel = 16; + +} + + +static inline void cls_set_rts_flow_control(struct channel_t *ch) +{ + uchar lcrb = readb(&ch->ch_cls_uart->lcr); + uchar ier = readb(&ch->ch_cls_uart->ier); + uchar isr_fcr = 0; + + DPR_PARAM(("Setting RTSFLOW\n")); + + /* + * The Enhanced Register Set may only be accessed when + * the Line Control Register is set to 0xBFh. + */ + writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr); + + isr_fcr = readb(&ch->ch_cls_uart->isr_fcr); + + /* Turn on RTS flow control, turn off IXOFF flow control */ + isr_fcr |= (UART_EXAR654_EFR_ECB | UART_EXAR654_EFR_RTSDTR); + isr_fcr &= ~(UART_EXAR654_EFR_IXOFF); + + writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr); + + /* Write old LCR value back out, which turns enhanced access off */ + writeb(lcrb, &ch->ch_cls_uart->lcr); + + /* Enable interrupts for RTS flow */ + ier |= (UART_EXAR654_IER_RTSDTR); + writeb(ier, &ch->ch_cls_uart->ier); + + /* Set the usual FIFO values */ + writeb((UART_FCR_ENABLE_FIFO), &ch->ch_cls_uart->isr_fcr); + + writeb((UART_FCR_ENABLE_FIFO | UART_16654_FCR_RXTRIGGER_56 | + UART_16654_FCR_TXTRIGGER_16 | UART_FCR_CLEAR_RCVR), + &ch->ch_cls_uart->isr_fcr); + + + ch->ch_r_watermark = 4; + ch->ch_r_tlevel = 8; + +} + + +static inline void cls_set_ixoff_flow_control(struct channel_t *ch) +{ + uchar lcrb = readb(&ch->ch_cls_uart->lcr); + uchar ier = readb(&ch->ch_cls_uart->ier); + uchar isr_fcr = 0; + + DPR_PARAM(("Setting IXOFF FLOW\n")); + + /* + * The Enhanced Register Set may only be accessed when + * the Line Control Register is set to 0xBFh. + */ + writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr); + + isr_fcr = readb(&ch->ch_cls_uart->isr_fcr); + + /* Turn on IXOFF flow control, turn off RTS flow control */ + isr_fcr |= (UART_EXAR654_EFR_ECB | UART_EXAR654_EFR_IXOFF); + isr_fcr &= ~(UART_EXAR654_EFR_RTSDTR); + + writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr); + + /* Now set our current start/stop chars while in enhanced mode */ + writeb(ch->ch_startc, &ch->ch_cls_uart->mcr); + writeb(0, &ch->ch_cls_uart->lsr); + writeb(ch->ch_stopc, &ch->ch_cls_uart->msr); + writeb(0, &ch->ch_cls_uart->spr); + + /* Write old LCR value back out, which turns enhanced access off */ + writeb(lcrb, &ch->ch_cls_uart->lcr); + + /* Disable interrupts for RTS flow */ + ier &= ~(UART_EXAR654_IER_RTSDTR); + writeb(ier, &ch->ch_cls_uart->ier); + + /* Set the usual FIFO values */ + writeb((UART_FCR_ENABLE_FIFO), &ch->ch_cls_uart->isr_fcr); + + writeb((UART_FCR_ENABLE_FIFO | UART_16654_FCR_RXTRIGGER_16 | + UART_16654_FCR_TXTRIGGER_16 | UART_FCR_CLEAR_RCVR), + &ch->ch_cls_uart->isr_fcr); + +} + + +static inline void cls_set_no_input_flow_control(struct channel_t *ch) +{ + uchar lcrb = readb(&ch->ch_cls_uart->lcr); + uchar ier = readb(&ch->ch_cls_uart->ier); + uchar isr_fcr = 0; + + DPR_PARAM(("Unsetting Input FLOW\n")); + + /* + * The Enhanced Register Set may only be accessed when + * the Line Control Register is set to 0xBFh. + */ + writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr); + + isr_fcr = readb(&ch->ch_cls_uart->isr_fcr); + + /* Turn off IXOFF flow control, turn off RTS flow control */ + isr_fcr |= (UART_EXAR654_EFR_ECB); + isr_fcr &= ~(UART_EXAR654_EFR_RTSDTR | UART_EXAR654_EFR_IXOFF); + + writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr); + + /* Write old LCR value back out, which turns enhanced access off */ + writeb(lcrb, &ch->ch_cls_uart->lcr); + + /* Disable interrupts for RTS flow */ + ier &= ~(UART_EXAR654_IER_RTSDTR); + writeb(ier, &ch->ch_cls_uart->ier); + + /* Set the usual FIFO values */ + writeb((UART_FCR_ENABLE_FIFO), &ch->ch_cls_uart->isr_fcr); + + writeb((UART_FCR_ENABLE_FIFO | UART_16654_FCR_RXTRIGGER_16 | + UART_16654_FCR_TXTRIGGER_16 | UART_FCR_CLEAR_RCVR), + &ch->ch_cls_uart->isr_fcr); + + ch->ch_t_tlevel = 16; + ch->ch_r_tlevel = 16; + +} + + +/* + * cls_clear_break. + * Determines whether its time to shut off break condition. + * + * No locks are assumed to be held when calling this function. + * channel lock is held and released in this function. + */ +static inline void cls_clear_break(struct channel_t *ch, int force) +{ + ulong lock_flags; + + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + DGNC_LOCK(ch->ch_lock, lock_flags); + + /* Bail if we aren't currently sending a break. */ + if (!ch->ch_stop_sending_break) { + DGNC_UNLOCK(ch->ch_lock, lock_flags); + return; + } + + /* Turn break off, and unset some variables */ + if (ch->ch_flags & CH_BREAK_SENDING) { + if ((jiffies >= ch->ch_stop_sending_break) || force) { + uchar temp = readb(&ch->ch_cls_uart->lcr); + writeb((temp & ~UART_LCR_SBC), &ch->ch_cls_uart->lcr); + ch->ch_flags &= ~(CH_BREAK_SENDING); + ch->ch_stop_sending_break = 0; + DPR_IOCTL(("Finishing UART_LCR_SBC! finished: %lx\n", jiffies)); + } + } + DGNC_UNLOCK(ch->ch_lock, lock_flags); +} + + +/* Parse the ISR register for the specific port */ +static inline void cls_parse_isr(struct board_t *brd, uint port) +{ + struct channel_t *ch; + uchar isr = 0; + ulong lock_flags; + + /* + * No need to verify board pointer, it was already + * verified in the interrupt routine. + */ + + if (port > brd->nasync) + return; + + ch = brd->channels[port]; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + /* Here we try to figure out what caused the interrupt to happen */ + while (1) { + + isr = readb(&ch->ch_cls_uart->isr_fcr); + + /* Bail if no pending interrupt on port */ + if (isr & UART_IIR_NO_INT) { + break; + } + + DPR_INTR(("%s:%d port: %x isr: %x\n", __FILE__, __LINE__, port, isr)); + + /* Receive Interrupt pending */ + if (isr & (UART_IIR_RDI | UART_IIR_RDI_TIMEOUT)) { + /* Read data from uart -> queue */ + brd->intr_rx++; + ch->ch_intr_rx++; + cls_copy_data_from_uart_to_queue(ch); + dgnc_check_queue_flow_control(ch); + } + + /* Transmit Hold register empty pending */ + if (isr & UART_IIR_THRI) { + /* Transfer data (if any) from Write Queue -> UART. */ + DGNC_LOCK(ch->ch_lock, lock_flags); + ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); + brd->intr_tx++; + ch->ch_intr_tx++; + DGNC_UNLOCK(ch->ch_lock, lock_flags); + cls_copy_data_from_queue_to_uart(ch); + } + + /* Received Xoff signal/Special character */ + if (isr & UART_IIR_XOFF) { + /* Empty */ + } + + /* CTS/RTS change of state */ + if (isr & UART_IIR_CTSRTS) { + brd->intr_modem++; + ch->ch_intr_modem++; + /* + * Don't need to do anything, the cls_parse_modem + * below will grab the updated modem signals. + */ + } + + /* Parse any modem signal changes */ + DPR_INTR(("MOD_STAT: sending to parse_modem_sigs\n")); + cls_parse_modem(ch, readb(&ch->ch_cls_uart->msr)); + } +} + + +/* + * cls_param() + * Send any/all changes to the line to the UART. + */ +static void cls_param(struct tty_struct *tty) +{ + uchar lcr = 0; + uchar uart_lcr = 0; + uchar ier = 0; + uchar uart_ier = 0; + uint baud = 9600; + int quot = 0; + struct board_t *bd; + struct channel_t *ch; + struct un_t *un; + + if (!tty || tty->magic != TTY_MAGIC) { + return; + } + + un = (struct un_t *) tty->driver_data; + if (!un || un->magic != DGNC_UNIT_MAGIC) { + return; + } + + ch = un->un_ch; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) { + return; + } + + bd = ch->ch_bd; + if (!bd || bd->magic != DGNC_BOARD_MAGIC) { + return; + } + + DPR_PARAM(("param start: tdev: %x cflags: %x oflags: %x iflags: %x\n", + ch->ch_tun.un_dev, ch->ch_c_cflag, ch->ch_c_oflag, ch->ch_c_iflag)); + + /* + * If baud rate is zero, flush queues, and set mval to drop DTR. + */ + if ((ch->ch_c_cflag & (CBAUD)) == 0) { + ch->ch_r_head = ch->ch_r_tail = 0; + ch->ch_e_head = ch->ch_e_tail = 0; + ch->ch_w_head = ch->ch_w_tail = 0; + + cls_flush_uart_write(ch); + cls_flush_uart_read(ch); + + /* The baudrate is B0 so all modem lines are to be dropped. */ + ch->ch_flags |= (CH_BAUD0); + ch->ch_mostat &= ~(UART_MCR_RTS | UART_MCR_DTR); + cls_assert_modem_signals(ch); + ch->ch_old_baud = 0; + return; + } else if (ch->ch_custom_speed) { + + baud = ch->ch_custom_speed; + /* Handle transition from B0 */ + if (ch->ch_flags & CH_BAUD0) { + ch->ch_flags &= ~(CH_BAUD0); + + /* + * Bring back up RTS and DTR... + * Also handle RTS or DTR toggle if set. + */ + if (!(ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE)) + ch->ch_mostat |= (UART_MCR_RTS); + if (!(ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE)) + ch->ch_mostat |= (UART_MCR_DTR); + } + + } else { + int iindex = 0; + int jindex = 0; + + ulong bauds[4][16] = { + { /* slowbaud */ + 0, 50, 75, 110, + 134, 150, 200, 300, + 600, 1200, 1800, 2400, + 4800, 9600, 19200, 38400 }, + { /* slowbaud & CBAUDEX */ + 0, 57600, 115200, 230400, + 460800, 150, 200, 921600, + 600, 1200, 1800, 2400, + 4800, 9600, 19200, 38400 }, + { /* fastbaud */ + 0, 57600, 76800, 115200, + 131657, 153600, 230400, 460800, + 921600, 1200, 1800, 2400, + 4800, 9600, 19200, 38400 }, + { /* fastbaud & CBAUDEX */ + 0, 57600, 115200, 230400, + 460800, 150, 200, 921600, + 600, 1200, 1800, 2400, + 4800, 9600, 19200, 38400 } + }; + + /* Only use the TXPrint baud rate if the terminal unit is NOT open */ + if (!(ch->ch_tun.un_flags & UN_ISOPEN) && (un->un_type == DGNC_PRINT)) + baud = C_BAUD(ch->ch_pun.un_tty) & 0xff; + else + baud = C_BAUD(ch->ch_tun.un_tty) & 0xff; + + if (ch->ch_c_cflag & CBAUDEX) + iindex = 1; + + if (ch->ch_digi.digi_flags & DIGI_FAST) + iindex += 2; + + jindex = baud; + + if ((iindex >= 0) && (iindex < 4) && (jindex >= 0) && (jindex < 16)) { + baud = bauds[iindex][jindex]; + } else { + DPR_IOCTL(("baud indices were out of range (%d)(%d)", + iindex, jindex)); + baud = 0; + } + + if (baud == 0) + baud = 9600; + + /* Handle transition from B0 */ + if (ch->ch_flags & CH_BAUD0) { + ch->ch_flags &= ~(CH_BAUD0); + + /* + * Bring back up RTS and DTR... + * Also handle RTS or DTR toggle if set. + */ + if (!(ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE)) + ch->ch_mostat |= (UART_MCR_RTS); + if (!(ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE)) + ch->ch_mostat |= (UART_MCR_DTR); + } + } + + if (ch->ch_c_cflag & PARENB) { + lcr |= UART_LCR_PARITY; + } + + if (!(ch->ch_c_cflag & PARODD)) { + lcr |= UART_LCR_EPAR; + } + + /* + * Not all platforms support mark/space parity, + * so this will hide behind an ifdef. + */ +#ifdef CMSPAR + if (ch->ch_c_cflag & CMSPAR) + lcr |= UART_LCR_SPAR; +#endif + + if (ch->ch_c_cflag & CSTOPB) + lcr |= UART_LCR_STOP; + + switch (ch->ch_c_cflag & CSIZE) { + case CS5: + lcr |= UART_LCR_WLEN5; + break; + case CS6: + lcr |= UART_LCR_WLEN6; + break; + case CS7: + lcr |= UART_LCR_WLEN7; + break; + case CS8: + default: + lcr |= UART_LCR_WLEN8; + break; + } + + ier = uart_ier = readb(&ch->ch_cls_uart->ier); + uart_lcr = readb(&ch->ch_cls_uart->lcr); + + if (baud == 0) + baud = 9600; + + quot = ch->ch_bd->bd_dividend / baud; + + if (quot != 0 && ch->ch_old_baud != baud) { + ch->ch_old_baud = baud; + writeb(UART_LCR_DLAB, &ch->ch_cls_uart->lcr); + writeb((quot & 0xff), &ch->ch_cls_uart->txrx); + writeb((quot >> 8), &ch->ch_cls_uart->ier); + writeb(lcr, &ch->ch_cls_uart->lcr); + } + + if (uart_lcr != lcr) + writeb(lcr, &ch->ch_cls_uart->lcr); + + if (ch->ch_c_cflag & CREAD) { + ier |= (UART_IER_RDI | UART_IER_RLSI); + } + else { + ier &= ~(UART_IER_RDI | UART_IER_RLSI); + } + + /* + * Have the UART interrupt on modem signal changes ONLY when + * we are in hardware flow control mode, or CLOCAL/FORCEDCD is not set. + */ + if ((ch->ch_digi.digi_flags & CTSPACE) || (ch->ch_digi.digi_flags & RTSPACE) || + (ch->ch_c_cflag & CRTSCTS) || !(ch->ch_digi.digi_flags & DIGI_FORCEDCD) || + !(ch->ch_c_cflag & CLOCAL)) + { + ier |= UART_IER_MSI; + } + else { + ier &= ~UART_IER_MSI; + } + + ier |= UART_IER_THRI; + + if (ier != uart_ier) + writeb(ier, &ch->ch_cls_uart->ier); + + if (ch->ch_digi.digi_flags & CTSPACE || ch->ch_c_cflag & CRTSCTS) { + cls_set_cts_flow_control(ch); + } + else if (ch->ch_c_iflag & IXON) { + /* If start/stop is set to disable, then we should disable flow control */ + if ((ch->ch_startc == _POSIX_VDISABLE) || (ch->ch_stopc == _POSIX_VDISABLE)) + cls_set_no_output_flow_control(ch); + else + cls_set_ixon_flow_control(ch); + } + else { + cls_set_no_output_flow_control(ch); + } + + if (ch->ch_digi.digi_flags & RTSPACE || ch->ch_c_cflag & CRTSCTS) { + cls_set_rts_flow_control(ch); + } + else if (ch->ch_c_iflag & IXOFF) { + /* If start/stop is set to disable, then we should disable flow control */ + if ((ch->ch_startc == _POSIX_VDISABLE) || (ch->ch_stopc == _POSIX_VDISABLE)) + cls_set_no_input_flow_control(ch); + else + cls_set_ixoff_flow_control(ch); + } + else { + cls_set_no_input_flow_control(ch); + } + + cls_assert_modem_signals(ch); + + /* Get current status of the modem signals now */ + cls_parse_modem(ch, readb(&ch->ch_cls_uart->msr)); +} + + +/* + * Our board poller function. + */ +static void cls_tasklet(unsigned long data) +{ + struct board_t *bd = (struct board_t *) data; + struct channel_t *ch; + ulong lock_flags; + int i; + int state = 0; + int ports = 0; + + if (!bd || bd->magic != DGNC_BOARD_MAGIC) { + APR(("poll_tasklet() - NULL or bad bd.\n")); + return; + } + + /* Cache a couple board values */ + DGNC_LOCK(bd->bd_lock, lock_flags); + state = bd->state; + ports = bd->nasync; + DGNC_UNLOCK(bd->bd_lock, lock_flags); + + /* + * Do NOT allow the interrupt routine to read the intr registers + * Until we release this lock. + */ + DGNC_LOCK(bd->bd_intr_lock, lock_flags); + + /* + * If board is ready, parse deeper to see if there is anything to do. + */ + if ((state == BOARD_READY) && (ports > 0)) { + + /* Loop on each port */ + for (i = 0; i < ports; i++) { + ch = bd->channels[i]; + if (!ch) + continue; + + /* + * NOTE: Remember you CANNOT hold any channel + * locks when calling input. + * During input processing, its possible we + * will call ld, which might do callbacks back + * into us. + */ + dgnc_input(ch); + + /* + * Channel lock is grabbed and then released + * inside this routine. + */ + cls_copy_data_from_queue_to_uart(ch); + dgnc_wakeup_writes(ch); + + /* + * Check carrier function. + */ + dgnc_carrier(ch); + + /* + * The timing check of turning off the break is done + * inside clear_break() + */ + if (ch->ch_stop_sending_break) + cls_clear_break(ch, 0); + } + } + + DGNC_UNLOCK(bd->bd_intr_lock, lock_flags); + +} + + +/* + * cls_intr() + * + * Classic specific interrupt handler. + */ +static irqreturn_t cls_intr(int irq, void *voidbrd) +{ + struct board_t *brd = (struct board_t *) voidbrd; + uint i = 0; + uchar poll_reg; + unsigned long lock_flags; + + if (!brd) { + APR(("Received interrupt (%d) with null board associated\n", irq)); + return IRQ_NONE; + } + + /* + * Check to make sure its for us. + */ + if (brd->magic != DGNC_BOARD_MAGIC) { + APR(("Received interrupt (%d) with a board pointer that wasn't ours!\n", irq)); + return IRQ_NONE; + } + + DGNC_LOCK(brd->bd_intr_lock, lock_flags); + + brd->intr_count++; + + /* + * Check the board's global interrupt offset to see if we + * we actually do have an interrupt pending for us. + */ + poll_reg = readb(brd->re_map_membase + UART_CLASSIC_POLL_ADDR_OFFSET); + + /* If 0, no interrupts pending */ + if (!poll_reg) { + DPR_INTR(("Kernel interrupted to me, but no pending interrupts...\n")); + DGNC_UNLOCK(brd->bd_intr_lock, lock_flags); + return IRQ_NONE; + } + + DPR_INTR(("%s:%d poll_reg: %x\n", __FILE__, __LINE__, poll_reg)); + + /* Parse each port to find out what caused the interrupt */ + for (i = 0; i < brd->nasync; i++) { + cls_parse_isr(brd, i); + } + + /* + * Schedule tasklet to more in-depth servicing at a better time. + */ + tasklet_schedule(&brd->helper_tasklet); + + DGNC_UNLOCK(brd->bd_intr_lock, lock_flags); + + DPR_INTR(("dgnc_intr finish.\n")); + return IRQ_HANDLED; +} + + +static void cls_disable_receiver(struct channel_t *ch) +{ + uchar tmp = readb(&ch->ch_cls_uart->ier); + tmp &= ~(UART_IER_RDI); + writeb(tmp, &ch->ch_cls_uart->ier); +} + + +static void cls_enable_receiver(struct channel_t *ch) +{ + uchar tmp = readb(&ch->ch_cls_uart->ier); + tmp |= (UART_IER_RDI); + writeb(tmp, &ch->ch_cls_uart->ier); +} + + +static void cls_copy_data_from_uart_to_queue(struct channel_t *ch) +{ + int qleft = 0; + uchar linestatus = 0; + uchar error_mask = 0; + ushort head; + ushort tail; + ulong lock_flags; + + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + DGNC_LOCK(ch->ch_lock, lock_flags); + + /* cache head and tail of queue */ + head = ch->ch_r_head; + tail = ch->ch_r_tail; + + /* Store how much space we have left in the queue */ + if ((qleft = tail - head - 1) < 0) + qleft += RQUEUEMASK + 1; + + /* + * Create a mask to determine whether we should + * insert the character (if any) into our queue. + */ + if (ch->ch_c_iflag & IGNBRK) + error_mask |= UART_LSR_BI; + + while (1) { + linestatus = readb(&ch->ch_cls_uart->lsr); + + if (!(linestatus & (UART_LSR_DR))) + break; + + /* + * Discard character if we are ignoring the error mask. + */ + if (linestatus & error_mask) { + uchar discard; + linestatus = 0; + discard = readb(&ch->ch_cls_uart->txrx); + continue; + } + + /* + * If our queue is full, we have no choice but to drop some data. + * The assumption is that HWFLOW or SWFLOW should have stopped + * things way way before we got to this point. + * + * I decided that I wanted to ditch the oldest data first, + * I hope thats okay with everyone? Yes? Good. + */ + while (qleft < 1) { + DPR_READ(("Queue full, dropping DATA:%x LSR:%x\n", + ch->ch_rqueue[tail], ch->ch_equeue[tail])); + + ch->ch_r_tail = tail = (tail + 1) & RQUEUEMASK; + ch->ch_err_overrun++; + qleft++; + } + + ch->ch_equeue[head] = linestatus & (UART_LSR_BI | UART_LSR_PE | UART_LSR_FE); + ch->ch_rqueue[head] = readb(&ch->ch_cls_uart->txrx); + dgnc_sniff_nowait_nolock(ch, "UART READ", ch->ch_rqueue + head, 1); + + qleft--; + + DPR_READ(("DATA/LSR pair: %x %x\n", ch->ch_rqueue[head], ch->ch_equeue[head])); + + if (ch->ch_equeue[head] & UART_LSR_PE) + ch->ch_err_parity++; + if (ch->ch_equeue[head] & UART_LSR_BI) + ch->ch_err_break++; + if (ch->ch_equeue[head] & UART_LSR_FE) + ch->ch_err_frame++; + + /* Add to, and flip head if needed */ + head = (head + 1) & RQUEUEMASK; + ch->ch_rxcount++; + } + + /* + * Write new final heads to channel structure. + */ + ch->ch_r_head = head & RQUEUEMASK; + ch->ch_e_head = head & EQUEUEMASK; + + DGNC_UNLOCK(ch->ch_lock, lock_flags); +} + + +/* + * This function basically goes to sleep for secs, or until + * it gets signalled that the port has fully drained. + */ +static int cls_drain(struct tty_struct *tty, uint seconds) +{ + ulong lock_flags; + struct channel_t *ch; + struct un_t *un; + int rc = 0; + + if (!tty || tty->magic != TTY_MAGIC) { + return (-ENXIO); + } + + un = (struct un_t *) tty->driver_data; + if (!un || un->magic != DGNC_UNIT_MAGIC) { + return (-ENXIO); + } + + ch = un->un_ch; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) { + return (-ENXIO); + } + + DGNC_LOCK(ch->ch_lock, lock_flags); + un->un_flags |= UN_EMPTY; + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + /* + * NOTE: Do something with time passed in. + */ + rc = wait_event_interruptible(un->un_flags_wait, ((un->un_flags & UN_EMPTY) == 0)); + + /* If ret is non-zero, user ctrl-c'ed us */ + if (rc) + DPR_IOCTL(("%d Drain - User ctrl c'ed\n", __LINE__)); + + return (rc); +} + + +/* Channel lock MUST be held before calling this function! */ +static void cls_flush_uart_write(struct channel_t *ch) +{ + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) { + return; + } + + writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_XMIT), &ch->ch_cls_uart->isr_fcr); + udelay(10); + + ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); +} + + +/* Channel lock MUST be held before calling this function! */ +static void cls_flush_uart_read(struct channel_t *ch) +{ + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) { + return; + } + + /* + * For complete POSIX compatibility, we should be purging the + * read FIFO in the UART here. + * + * However, doing the statement below also incorrectly flushes + * write data as well as just basically trashing the FIFO. + * + * I believe this is a BUG in this UART. + * So for now, we will leave the code #ifdef'ed out... + */ +#if 0 + writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR), &ch->ch_cls_uart->isr_fcr); +#endif + udelay(10); +} + + +static void cls_copy_data_from_queue_to_uart(struct channel_t *ch) +{ + ushort head; + ushort tail; + int n; + int qlen; + uint len_written = 0; + ulong lock_flags; + + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + DGNC_LOCK(ch->ch_lock, lock_flags); + + /* No data to write to the UART */ + if (ch->ch_w_tail == ch->ch_w_head) { + DGNC_UNLOCK(ch->ch_lock, lock_flags); + return; + } + + /* If port is "stopped", don't send any data to the UART */ + if ((ch->ch_flags & CH_FORCED_STOP) || (ch->ch_flags & CH_BREAK_SENDING)) { + DGNC_UNLOCK(ch->ch_lock, lock_flags); + return; + } + + if (!(ch->ch_flags & (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM))) { + DGNC_UNLOCK(ch->ch_lock, lock_flags); + return; + } + + n = 32; + + /* cache head and tail of queue */ + head = ch->ch_w_head & WQUEUEMASK; + tail = ch->ch_w_tail & WQUEUEMASK; + qlen = (head - tail) & WQUEUEMASK; + + /* Find minimum of the FIFO space, versus queue length */ + n = min(n, qlen); + + while (n > 0) { + + /* + * If RTS Toggle mode is on, turn on RTS now if not already set, + * and make sure we get an event when the data transfer has completed. + */ + if (ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE) { + if (!(ch->ch_mostat & UART_MCR_RTS)) { + ch->ch_mostat |= (UART_MCR_RTS); + cls_assert_modem_signals(ch); + } + ch->ch_tun.un_flags |= (UN_EMPTY); + } + + /* + * If DTR Toggle mode is on, turn on DTR now if not already set, + * and make sure we get an event when the data transfer has completed. + */ + if (ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE) { + if (!(ch->ch_mostat & UART_MCR_DTR)) { + ch->ch_mostat |= (UART_MCR_DTR); + cls_assert_modem_signals(ch); + } + ch->ch_tun.un_flags |= (UN_EMPTY); + } + writeb(ch->ch_wqueue[ch->ch_w_tail], &ch->ch_cls_uart->txrx); + dgnc_sniff_nowait_nolock(ch, "UART WRITE", ch->ch_wqueue + ch->ch_w_tail, 1); + DPR_WRITE(("Tx data: %x\n", ch->ch_wqueue[ch->ch_w_tail])); + ch->ch_w_tail++; + ch->ch_w_tail &= WQUEUEMASK; + ch->ch_txcount++; + len_written++; + n--; + } + + if (len_written > 0) + ch->ch_flags &= ~(CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + return; +} + + +static void cls_parse_modem(struct channel_t *ch, uchar signals) +{ + volatile uchar msignals = signals; + + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + DPR_MSIGS(("cls_parse_modem: port: %d signals: %d\n", ch->ch_portnum, msignals)); + + /* + * Do altpin switching. Altpin switches DCD and DSR. + * This prolly breaks DSRPACE, so we should be more clever here. + */ + if (ch->ch_digi.digi_flags & DIGI_ALTPIN) { + uchar mswap = signals; + if (mswap & UART_MSR_DDCD) { + msignals &= ~UART_MSR_DDCD; + msignals |= UART_MSR_DDSR; + } + if (mswap & UART_MSR_DDSR) { + msignals &= ~UART_MSR_DDSR; + msignals |= UART_MSR_DDCD; + } + if (mswap & UART_MSR_DCD) { + msignals &= ~UART_MSR_DCD; + msignals |= UART_MSR_DSR; + } + if (mswap & UART_MSR_DSR) { + msignals &= ~UART_MSR_DSR; + msignals |= UART_MSR_DCD; + } + } + + /* Scrub off lower bits. They signify delta's, which I don't care about */ + signals &= 0xf0; + + if (msignals & UART_MSR_DCD) + ch->ch_mistat |= UART_MSR_DCD; + else + ch->ch_mistat &= ~UART_MSR_DCD; + + if (msignals & UART_MSR_DSR) + ch->ch_mistat |= UART_MSR_DSR; + else + ch->ch_mistat &= ~UART_MSR_DSR; + + if (msignals & UART_MSR_RI) + ch->ch_mistat |= UART_MSR_RI; + else + ch->ch_mistat &= ~UART_MSR_RI; + + if (msignals & UART_MSR_CTS) + ch->ch_mistat |= UART_MSR_CTS; + else + ch->ch_mistat &= ~UART_MSR_CTS; + + + DPR_MSIGS(("Port: %d DTR: %d RTS: %d CTS: %d DSR: %d " "RI: %d CD: %d\n", + ch->ch_portnum, + !!((ch->ch_mistat | ch->ch_mostat) & UART_MCR_DTR), + !!((ch->ch_mistat | ch->ch_mostat) & UART_MCR_RTS), + !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_CTS), + !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_DSR), + !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_RI), + !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_DCD))); +} + + +/* Make the UART raise any of the output signals we want up */ +static void cls_assert_modem_signals(struct channel_t *ch) +{ + uchar out; + + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + out = ch->ch_mostat; + + if (ch->ch_flags & CH_LOOPBACK) + out |= UART_MCR_LOOP; + + writeb(out, &ch->ch_cls_uart->mcr); + + /* Give time for the UART to actually drop the signals */ + udelay(10); +} + + +static void cls_send_start_character(struct channel_t *ch) +{ + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + if (ch->ch_startc != _POSIX_VDISABLE) { + ch->ch_xon_sends++; + writeb(ch->ch_startc, &ch->ch_cls_uart->txrx); + } +} + + +static void cls_send_stop_character(struct channel_t *ch) +{ + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + if (ch->ch_stopc != _POSIX_VDISABLE) { + ch->ch_xoff_sends++; + writeb(ch->ch_stopc, &ch->ch_cls_uart->txrx); + } +} + + +/* Inits UART */ +static void cls_uart_init(struct channel_t *ch) +{ + uchar lcrb = readb(&ch->ch_cls_uart->lcr); + uchar isr_fcr = 0; + + writeb(0, &ch->ch_cls_uart->ier); + + /* + * The Enhanced Register Set may only be accessed when + * the Line Control Register is set to 0xBFh. + */ + writeb(UART_EXAR654_ENHANCED_REGISTER_SET, &ch->ch_cls_uart->lcr); + + isr_fcr = readb(&ch->ch_cls_uart->isr_fcr); + + /* Turn on Enhanced/Extended controls */ + isr_fcr |= (UART_EXAR654_EFR_ECB); + + writeb(isr_fcr, &ch->ch_cls_uart->isr_fcr); + + /* Write old LCR value back out, which turns enhanced access off */ + writeb(lcrb, &ch->ch_cls_uart->lcr); + + /* Clear out UART and FIFO */ + readb(&ch->ch_cls_uart->txrx); + + writeb((UART_FCR_ENABLE_FIFO|UART_FCR_CLEAR_RCVR|UART_FCR_CLEAR_XMIT), &ch->ch_cls_uart->isr_fcr); + udelay(10); + + ch->ch_flags |= (CH_FIFO_ENABLED | CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); + + readb(&ch->ch_cls_uart->lsr); + readb(&ch->ch_cls_uart->msr); +} + + +/* + * Turns off UART. + */ +static void cls_uart_off(struct channel_t *ch) +{ + writeb(0, &ch->ch_cls_uart->ier); +} + + +/* + * cls_get_uarts_bytes_left. + * Returns 0 is nothing left in the FIFO, returns 1 otherwise. + * + * The channel lock MUST be held by the calling function. + */ +static uint cls_get_uart_bytes_left(struct channel_t *ch) +{ + uchar left = 0; + uchar lsr = 0; + + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return 0; + + lsr = readb(&ch->ch_cls_uart->lsr); + + /* Determine whether the Transmitter is empty or not */ + if (!(lsr & UART_LSR_TEMT)) { + if (ch->ch_flags & CH_TX_FIFO_EMPTY) { + tasklet_schedule(&ch->ch_bd->helper_tasklet); + } + left = 1; + } + else { + ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); + left = 0; + } + + return left; +} + + +/* + * cls_send_break. + * Starts sending a break thru the UART. + * + * The channel lock MUST be held by the calling function. + */ +static void cls_send_break(struct channel_t *ch, int msecs) +{ + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + /* + * If we receive a time of 0, this means turn off the break. + */ + if (msecs == 0) { + /* Turn break off, and unset some variables */ + if (ch->ch_flags & CH_BREAK_SENDING) { + uchar temp = readb(&ch->ch_cls_uart->lcr); + writeb((temp & ~UART_LCR_SBC), &ch->ch_cls_uart->lcr); + ch->ch_flags &= ~(CH_BREAK_SENDING); + ch->ch_stop_sending_break = 0; + DPR_IOCTL(("Finishing UART_LCR_SBC! finished: %lx\n", jiffies)); + } + return; + } + + /* + * Set the time we should stop sending the break. + * If we are already sending a break, toss away the existing + * time to stop, and use this new value instead. + */ + ch->ch_stop_sending_break = jiffies + dgnc_jiffies_from_ms(msecs); + + /* Tell the UART to start sending the break */ + if (!(ch->ch_flags & CH_BREAK_SENDING)) { + uchar temp = readb(&ch->ch_cls_uart->lcr); + writeb((temp | UART_LCR_SBC), &ch->ch_cls_uart->lcr); + ch->ch_flags |= (CH_BREAK_SENDING); + DPR_IOCTL(("Port %d. Starting UART_LCR_SBC! start: %lx should end: %lx\n", + ch->ch_portnum, jiffies, ch->ch_stop_sending_break)); + } +} + + +/* + * cls_send_immediate_char. + * Sends a specific character as soon as possible to the UART, + * jumping over any bytes that might be in the write queue. + * + * The channel lock MUST be held by the calling function. + */ +static void cls_send_immediate_char(struct channel_t *ch, unsigned char c) +{ + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + writeb(c, &ch->ch_cls_uart->txrx); +} + +static void cls_vpd(struct board_t *brd) +{ + ulong vpdbase; /* Start of io base of the card */ + uchar *re_map_vpdbase;/* Remapped memory of the card */ + int i = 0; + + + vpdbase = pci_resource_start(brd->pdev, 3); + + /* No VPD */ + if (!vpdbase) + return; + + re_map_vpdbase = ioremap(vpdbase, 0x400); + + if (!re_map_vpdbase) + return; + + /* Store the VPD into our buffer */ + for (i = 0; i < 0x40; i++) { + brd->vpd[i] = readb(re_map_vpdbase + i); + printk("%x ", brd->vpd[i]); + } + printk("\n"); + + if (re_map_vpdbase) + iounmap(re_map_vpdbase); +} + diff --git a/drivers/staging/dgnc/dgnc_cls.h b/drivers/staging/dgnc/dgnc_cls.h new file mode 100644 index 000000000000..dca5ea38cd54 --- /dev/null +++ b/drivers/staging/dgnc/dgnc_cls.h @@ -0,0 +1,90 @@ +/* + * Copyright 2003 Digi International (www.digi.com) + * Scott H Kilau + * + * 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, EXPRESS OR IMPLIED; 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. + * + * NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!! + * + */ + +#ifndef __DGNC_CLS_H +#define __DGNC_CLS_H + +#include "dgnc_types.h" + + +/************************************************************************ + * Per channel/port Classic UART structure * + ************************************************************************ + * Base Structure Entries Usage Meanings to Host * + * * + * W = read write R = read only * + * U = Unused. * + ************************************************************************/ + +struct cls_uart_struct { + volatile uchar txrx; /* WR RHR/THR - Holding Reg */ + volatile uchar ier; /* WR IER - Interrupt Enable Reg */ + volatile uchar isr_fcr; /* WR ISR/FCR - Interrupt Status Reg/Fifo Control Reg */ + volatile uchar lcr; /* WR LCR - Line Control Reg */ + volatile uchar mcr; /* WR MCR - Modem Control Reg */ + volatile uchar lsr; /* WR LSR - Line Status Reg */ + volatile uchar msr; /* WR MSR - Modem Status Reg */ + volatile uchar spr; /* WR SPR - Scratch Pad Reg */ +}; + +/* Where to read the interrupt register (8bits) */ +#define UART_CLASSIC_POLL_ADDR_OFFSET 0x40 + +#define UART_EXAR654_ENHANCED_REGISTER_SET 0xBF + +#define UART_16654_FCR_TXTRIGGER_8 0x0 +#define UART_16654_FCR_TXTRIGGER_16 0x10 +#define UART_16654_FCR_TXTRIGGER_32 0x20 +#define UART_16654_FCR_TXTRIGGER_56 0x30 + +#define UART_16654_FCR_RXTRIGGER_8 0x0 +#define UART_16654_FCR_RXTRIGGER_16 0x40 +#define UART_16654_FCR_RXTRIGGER_56 0x80 +#define UART_16654_FCR_RXTRIGGER_60 0xC0 + +#define UART_IIR_XOFF 0x10 /* Received Xoff signal/Special character */ +#define UART_IIR_CTSRTS 0x20 /* Received CTS/RTS change of state */ +#define UART_IIR_RDI_TIMEOUT 0x0C /* Receiver data TIMEOUT */ + +/* + * These are the EXTENDED definitions for the Exar 654's Interrupt + * Enable Register. + */ +#define UART_EXAR654_EFR_ECB 0x10 /* Enhanced control bit */ +#define UART_EXAR654_EFR_IXON 0x2 /* Receiver compares Xon1/Xoff1 */ +#define UART_EXAR654_EFR_IXOFF 0x8 /* Transmit Xon1/Xoff1 */ +#define UART_EXAR654_EFR_RTSDTR 0x40 /* Auto RTS/DTR Flow Control Enable */ +#define UART_EXAR654_EFR_CTSDSR 0x80 /* Auto CTS/DSR Flow COntrol Enable */ + +#define UART_EXAR654_XOFF_DETECT 0x1 /* Indicates whether chip saw an incoming XOFF char */ +#define UART_EXAR654_XON_DETECT 0x2 /* Indicates whether chip saw an incoming XON char */ + +#define UART_EXAR654_IER_XOFF 0x20 /* Xoff Interrupt Enable */ +#define UART_EXAR654_IER_RTSDTR 0x40 /* Output Interrupt Enable */ +#define UART_EXAR654_IER_CTSDSR 0x80 /* Input Interrupt Enable */ + +/* + * Our Global Variables + */ +extern struct board_ops dgnc_cls_ops; + +#endif diff --git a/drivers/staging/dgnc/dgnc_driver.c b/drivers/staging/dgnc/dgnc_driver.c new file mode 100644 index 000000000000..7c88de773745 --- /dev/null +++ b/drivers/staging/dgnc/dgnc_driver.c @@ -0,0 +1,1028 @@ +/* + * Copyright 2003 Digi International (www.digi.com) + * Scott H Kilau + * + * 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, EXPRESS OR IMPLIED; 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. + * + * + * NOTE TO LINUX KERNEL HACKERS: DO NOT REFORMAT THIS CODE! + * + * This is shared code between Digi's CVS archive and the + * Linux Kernel sources. + * Changing the source just for reformatting needlessly breaks + * our CVS diff history. + * + * Send any bug fixes/changes to: Eng.Linux at digi dot com. + * Thank you. + * + * $Id: dgnc_driver.c,v 1.3 2011/06/23 12:47:35 markh Exp $ + * + */ + + +#include +#include +#include +#include + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39) +#include +#endif + +#include "dgnc_driver.h" +#include "dgnc_pci.h" +#include "dgnc_proc.h" +#include "dpacompat.h" +#include "dgnc_mgmt.h" +#include "dgnc_tty.h" +#include "dgnc_trace.h" +#include "dgnc_cls.h" +#include "dgnc_neo.h" +#include "dgnc_sysfs.h" + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Digi International, http://www.digi.com"); +MODULE_DESCRIPTION("Driver for the Digi International Neo and Classic PCI based product line"); +MODULE_SUPPORTED_DEVICE("dgnc"); + +/* + * insmod command line overrideable parameters + * + * NOTE: we use a set of macros to create the variables, which allows + * us to specify the variable type, name, initial value, and description. + */ +PARM_INT(debug, 0x00, 0644, "Driver debugging level"); +PARM_INT(rawreadok, 1, 0644, "Bypass flip buffers on input"); +PARM_INT(trcbuf_size, 0x100000, 0644, "Debugging trace buffer size."); + +/************************************************************************** + * + * protos for this file + * + */ +static int dgnc_start(void); +static int dgnc_finalize_board_init(struct board_t *brd); +static void dgnc_init_globals(void); +static int dgnc_found_board(struct pci_dev *pdev, int id); +static void dgnc_cleanup_board(struct board_t *brd); +static void dgnc_poll_handler(ulong dummy); +static int dgnc_init_pci(void); +static int dgnc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); +static void dgnc_remove_one(struct pci_dev *dev); +static int dgnc_probe1(struct pci_dev *pdev, int card_type); +static void dgnc_do_remap(struct board_t *brd); +static void dgnc_mbuf(struct board_t *brd, const char *fmt, ...); + + +/* Driver load/unload functions */ +int dgnc_init_module(void); +void dgnc_cleanup_module(void); + +module_init(dgnc_init_module); +module_exit(dgnc_cleanup_module); + + +/* + * File operations permitted on Control/Management major. + */ +static struct file_operations dgnc_BoardFops = +{ + .owner = THIS_MODULE, +#ifdef HAVE_UNLOCKED_IOCTL + .unlocked_ioctl = dgnc_mgmt_ioctl, +#else + .ioctl = dgnc_mgmt_ioctl, +#endif + .open = dgnc_mgmt_open, + .release = dgnc_mgmt_close +}; + + +/* + * Globals + */ +uint dgnc_NumBoards; +struct board_t *dgnc_Board[MAXBOARDS]; +DEFINE_SPINLOCK(dgnc_global_lock); +int dgnc_driver_state = DRIVER_INITIALIZED; +ulong dgnc_poll_counter; +uint dgnc_Major; +int dgnc_poll_tick = 20; /* Poll interval - 20 ms */ + +/* + * Static vars. + */ +static uint dgnc_Major_Control_Registered = FALSE; +static uint dgnc_driver_start = FALSE; + +static struct class *dgnc_class; + +/* + * Poller stuff + */ +static DEFINE_SPINLOCK(dgnc_poll_lock); /* Poll scheduling lock */ +static ulong dgnc_poll_time; /* Time of next poll */ +static uint dgnc_poll_stop; /* Used to tell poller to stop */ +static struct timer_list dgnc_poll_timer; + + +static struct pci_device_id dgnc_pci_tbl[] = { + { DIGI_VID, PCI_DEVICE_CLASSIC_4_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { DIGI_VID, PCI_DEVICE_CLASSIC_4_422_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 }, + { DIGI_VID, PCI_DEVICE_CLASSIC_8_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 }, + { DIGI_VID, PCI_DEVICE_CLASSIC_8_422_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 }, + { DIGI_VID, PCI_DEVICE_NEO_4_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 }, + { DIGI_VID, PCI_DEVICE_NEO_8_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 }, + { DIGI_VID, PCI_DEVICE_NEO_2DB9_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6 }, + { DIGI_VID, PCI_DEVICE_NEO_2DB9PRI_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7 }, + { DIGI_VID, PCI_DEVICE_NEO_2RJ45_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 }, + { DIGI_VID, PCI_DEVICE_NEO_2RJ45PRI_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9 }, + { DIGI_VID, PCI_DEVICE_NEO_1_422_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10 }, + { DIGI_VID, PCI_DEVICE_NEO_1_422_485_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11 }, + { DIGI_VID, PCI_DEVICE_NEO_2_422_485_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12 }, + { DIGI_VID, PCI_DEVICE_NEO_EXPRESS_8_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13 }, + { DIGI_VID, PCI_DEVICE_NEO_EXPRESS_4_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14 }, + { DIGI_VID, PCI_DEVICE_NEO_EXPRESS_4RJ45_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15 }, + { DIGI_VID, PCI_DEVICE_NEO_EXPRESS_8RJ45_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 16 }, + {0,} /* 0 terminated list. */ +}; +MODULE_DEVICE_TABLE(pci, dgnc_pci_tbl); + +struct board_id { + uchar *name; + uint maxports; + unsigned int is_pci_express; +}; + +static struct board_id dgnc_Ids[] = +{ + { PCI_DEVICE_CLASSIC_4_PCI_NAME, 4, 0 }, + { PCI_DEVICE_CLASSIC_4_422_PCI_NAME, 4, 0 }, + { PCI_DEVICE_CLASSIC_8_PCI_NAME, 8, 0 }, + { PCI_DEVICE_CLASSIC_8_422_PCI_NAME, 8, 0 }, + { PCI_DEVICE_NEO_4_PCI_NAME, 4, 0 }, + { PCI_DEVICE_NEO_8_PCI_NAME, 8, 0 }, + { PCI_DEVICE_NEO_2DB9_PCI_NAME, 2, 0 }, + { PCI_DEVICE_NEO_2DB9PRI_PCI_NAME, 2, 0 }, + { PCI_DEVICE_NEO_2RJ45_PCI_NAME, 2, 0 }, + { PCI_DEVICE_NEO_2RJ45PRI_PCI_NAME, 2, 0 }, + { PCI_DEVICE_NEO_1_422_PCI_NAME, 1, 0 }, + { PCI_DEVICE_NEO_1_422_485_PCI_NAME, 1, 0 }, + { PCI_DEVICE_NEO_2_422_485_PCI_NAME, 2, 0 }, + { PCI_DEVICE_NEO_EXPRESS_8_PCI_NAME, 8, 1 }, + { PCI_DEVICE_NEO_EXPRESS_4_PCI_NAME, 4, 1 }, + { PCI_DEVICE_NEO_EXPRESS_4RJ45_PCI_NAME, 4, 1 }, + { PCI_DEVICE_NEO_EXPRESS_8RJ45_PCI_NAME, 8, 1 }, + { NULL, 0, 0 } +}; + +static struct pci_driver dgnc_driver = { + .name = "dgnc", + .probe = dgnc_init_one, + .id_table = dgnc_pci_tbl, + .remove = dgnc_remove_one, +}; + + +char *dgnc_state_text[] = { + "Board Failed", + "Board Found", + "Board READY", +}; + +char *dgnc_driver_state_text[] = { + "Driver Initialized", + "Driver Ready." +}; + + + +/************************************************************************ + * + * Driver load/unload functions + * + ************************************************************************/ + + +/* + * init_module() + * + * Module load. This is where it all starts. + */ +int dgnc_init_module(void) +{ + int rc = 0; + + APR(("%s, Digi International Part Number %s\n", DG_NAME, DG_PART)); + + /* + * Initialize global stuff + */ + rc = dgnc_start(); + + if (rc < 0) { + return(rc); + } + + /* + * Find and configure all the cards + */ + rc = dgnc_init_pci(); + + /* + * If something went wrong in the scan, bail out of driver. + */ + if (rc < 0) { + /* Only unregister the pci driver if it was actually registered. */ + if (dgnc_NumBoards) + pci_unregister_driver(&dgnc_driver); + else + printk("WARNING: dgnc driver load failed. No Digi Neo or Classic boards found.\n"); + + dgnc_cleanup_module(); + } + else { + dgnc_create_driver_sysfiles(&dgnc_driver); + } + + DPR_INIT(("Finished init_module. Returning %d\n", rc)); + return (rc); +} + + +/* + * Start of driver. + */ +static int dgnc_start(void) +{ + int rc = 0; + unsigned long flags; + + if (dgnc_driver_start == FALSE) { + + dgnc_driver_start = TRUE; + + /* make sure that the globals are init'd before we do anything else */ + dgnc_init_globals(); + + dgnc_NumBoards = 0; + + APR(("For the tools package or updated drivers please visit http://www.digi.com\n")); + + /* + * Register our base character device into the kernel. + * This allows the download daemon to connect to the downld device + * before any of the boards are init'ed. + */ + if (!dgnc_Major_Control_Registered) { + /* + * Register management/dpa devices + */ + rc = register_chrdev(0, "dgnc", &dgnc_BoardFops); + if (rc <= 0) { + APR(("Can't register dgnc driver device (%d)\n", rc)); + rc = -ENXIO; + return(rc); + } + dgnc_Major = rc; + + dgnc_class = class_create(THIS_MODULE, "dgnc_mgmt"); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) + device_create_drvdata(dgnc_class, NULL, + MKDEV(dgnc_Major, 0), + NULL, "dgnc_mgmt"); +#else + device_create(dgnc_class, NULL, + MKDEV(dgnc_Major, 0), + NULL, "dgnc_mgmt"); +#endif + + dgnc_Major_Control_Registered = TRUE; + } + + /* + * Register our basic stuff in /proc/dgnc + */ + dgnc_proc_register_basic_prescan(); + + /* + * Init any global tty stuff. + */ + rc = dgnc_tty_preinit(); + + if (rc < 0) { + APR(("tty preinit - not enough memory (%d)\n", rc)); + return(rc); + } + + /* Start the poller */ + DGNC_LOCK(dgnc_poll_lock, flags); + init_timer(&dgnc_poll_timer); + dgnc_poll_timer.function = dgnc_poll_handler; + dgnc_poll_timer.data = 0; + dgnc_poll_time = jiffies + dgnc_jiffies_from_ms(dgnc_poll_tick); + dgnc_poll_timer.expires = dgnc_poll_time; + DGNC_UNLOCK(dgnc_poll_lock, flags); + + add_timer(&dgnc_poll_timer); + + dgnc_driver_state = DRIVER_READY; + } + + return(rc); +} + +/* + * Register pci driver, and return how many boards we have. + */ +static int dgnc_init_pci(void) +{ + return pci_register_driver(&dgnc_driver); +} + + +/* returns count (>= 0), or negative on error */ +static int dgnc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + int rc; + + /* wake up and enable device */ + rc = pci_enable_device(pdev); + + if (rc < 0) { + rc = -EIO; + } else { + rc = dgnc_probe1(pdev, ent->driver_data); + if (rc == 0) { + dgnc_NumBoards++; + DPR_INIT(("Incrementing numboards to %d\n", dgnc_NumBoards)); + } + } + return rc; +} + +static int dgnc_probe1(struct pci_dev *pdev, int card_type) +{ + return dgnc_found_board(pdev, card_type); +} + + +static void dgnc_remove_one(struct pci_dev *dev) +{ + /* Do Nothing */ +} + +/* + * dgnc_cleanup_module() + * + * Module unload. This is where it all ends. + */ +void dgnc_cleanup_module(void) +{ + int i; + ulong lock_flags; + + DGNC_LOCK(dgnc_poll_lock, lock_flags); + dgnc_poll_stop = 1; + DGNC_UNLOCK(dgnc_poll_lock, lock_flags); + + /* Turn off poller right away. */ + del_timer_sync(&dgnc_poll_timer); + + dgnc_proc_unregister_all(); + + dgnc_remove_driver_sysfiles(&dgnc_driver); + + if (dgnc_Major_Control_Registered) { + device_destroy(dgnc_class, MKDEV(dgnc_Major, 0)); + class_destroy(dgnc_class); + unregister_chrdev(dgnc_Major, "dgnc"); + } + + for (i = 0; i < dgnc_NumBoards; ++i) { + dgnc_remove_ports_sysfiles(dgnc_Board[i]); + dgnc_tty_uninit(dgnc_Board[i]); + dgnc_cleanup_board(dgnc_Board[i]); + } + + dgnc_tty_post_uninit(); + +#if defined(DGNC_TRACER) + /* last thing, make sure we release the tracebuffer */ + dgnc_tracer_free(); +#endif + if (dgnc_NumBoards) + pci_unregister_driver(&dgnc_driver); +} + + +/* + * dgnc_cleanup_board() + * + * Free all the memory associated with a board + */ +static void dgnc_cleanup_board(struct board_t *brd) +{ + int i = 0; + + if(!brd || brd->magic != DGNC_BOARD_MAGIC) + return; + + switch (brd->device) { + case PCI_DEVICE_CLASSIC_4_DID: + case PCI_DEVICE_CLASSIC_8_DID: + case PCI_DEVICE_CLASSIC_4_422_DID: + case PCI_DEVICE_CLASSIC_8_422_DID: + + /* Tell card not to interrupt anymore. */ + outb(0, brd->iobase + 0x4c); + break; + + default: + break; + } + + if (brd->irq) + free_irq(brd->irq, brd); + + tasklet_kill(&brd->helper_tasklet); + + if (brd->re_map_membase) { + iounmap(brd->re_map_membase); + brd->re_map_membase = NULL; + } + + if (brd->msgbuf_head) { + unsigned long flags; + + DGNC_LOCK(dgnc_global_lock, flags); + brd->msgbuf = NULL; + printk(brd->msgbuf_head); + kfree(brd->msgbuf_head); + brd->msgbuf_head = NULL; + DGNC_UNLOCK(dgnc_global_lock, flags); + } + + /* Free all allocated channels structs */ + for (i = 0; i < MAXPORTS ; i++) { + if (brd->channels[i]) { + if (brd->channels[i]->ch_rqueue) + kfree(brd->channels[i]->ch_rqueue); + if (brd->channels[i]->ch_equeue) + kfree(brd->channels[i]->ch_equeue); + if (brd->channels[i]->ch_wqueue) + kfree(brd->channels[i]->ch_wqueue); + + kfree(brd->channels[i]); + brd->channels[i] = NULL; + } + } + + if (brd->flipbuf) + kfree(brd->flipbuf); + + dgnc_Board[brd->boardnum] = NULL; + + kfree(brd); +} + + +/* + * dgnc_found_board() + * + * A board has been found, init it. + */ +static int dgnc_found_board(struct pci_dev *pdev, int id) +{ + struct board_t *brd; + unsigned int pci_irq; + int i = 0; + int rc = 0; + unsigned long flags; + + /* get the board structure and prep it */ + brd = dgnc_Board[dgnc_NumBoards] = + (struct board_t *) dgnc_driver_kzmalloc(sizeof(struct board_t), GFP_KERNEL); + if (!brd) { + APR(("memory allocation for board structure failed\n")); + return(-ENOMEM); + } + + /* make a temporary message buffer for the boot messages */ + brd->msgbuf = brd->msgbuf_head = + (char *) dgnc_driver_kzmalloc(sizeof(char) * 8192, GFP_KERNEL); + if (!brd->msgbuf) { + kfree(brd); + APR(("memory allocation for board msgbuf failed\n")); + return(-ENOMEM); + } + + /* store the info for the board we've found */ + brd->magic = DGNC_BOARD_MAGIC; + brd->boardnum = dgnc_NumBoards; + brd->vendor = dgnc_pci_tbl[id].vendor; + brd->device = dgnc_pci_tbl[id].device; + brd->pdev = pdev; + brd->pci_bus = pdev->bus->number; + brd->pci_slot = PCI_SLOT(pdev->devfn); + brd->name = dgnc_Ids[id].name; + brd->maxports = dgnc_Ids[id].maxports; + if (dgnc_Ids[i].is_pci_express) + brd->bd_flags |= BD_IS_PCI_EXPRESS; + brd->dpastatus = BD_NOFEP; + init_waitqueue_head(&brd->state_wait); + + DGNC_SPINLOCK_INIT(brd->bd_lock); + DGNC_SPINLOCK_INIT(brd->bd_intr_lock); + + brd->state = BOARD_FOUND; + + for (i = 0; i < MAXPORTS; i++) { + brd->channels[i] = NULL; + } + + /* store which card & revision we have */ + pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &brd->subvendor); + pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &brd->subdevice); + pci_read_config_byte(pdev, PCI_REVISION_ID, &brd->rev); + + pci_irq = pdev->irq; + brd->irq = pci_irq; + + + switch(brd->device) { + + case PCI_DEVICE_CLASSIC_4_DID: + case PCI_DEVICE_CLASSIC_8_DID: + case PCI_DEVICE_CLASSIC_4_422_DID: + case PCI_DEVICE_CLASSIC_8_422_DID: + + brd->dpatype = T_CLASSIC | T_PCIBUS; + + DPR_INIT(("dgnc_found_board - Classic.\n")); + + /* + * For PCI ClassicBoards + * PCI Local Address (i.e. "resource" number) space + * 0 PLX Memory Mapped Config + * 1 PLX I/O Mapped Config + * 2 I/O Mapped UARTs and Status + * 3 Memory Mapped VPD + * 4 Memory Mapped UARTs and Status + */ + + + /* get the PCI Base Address Registers */ + brd->membase = pci_resource_start(pdev, 4); + + if (!brd->membase) { + APR(("card has no PCI IO resources, failing board.\n")); + return -ENODEV; + } + + brd->membase_end = pci_resource_end(pdev, 4); + + if (brd->membase & 1) + brd->membase &= ~3; + else + brd->membase &= ~15; + + brd->iobase = pci_resource_start(pdev, 1); + brd->iobase_end = pci_resource_end(pdev, 1); + brd->iobase = ((unsigned int) (brd->iobase)) & 0xFFFE; + + /* Assign the board_ops struct */ + brd->bd_ops = &dgnc_cls_ops; + + brd->bd_uart_offset = 0x8; + brd->bd_dividend = 921600; + + dgnc_do_remap(brd); + + /* Get and store the board VPD, if it exists */ + brd->bd_ops->vpd(brd); + + /* + * Enable Local Interrupt 1 (0x1), + * Local Interrupt 1 Polarity Active high (0x2), + * Enable PCI interrupt (0x40) + */ + outb(0x43, brd->iobase + 0x4c); + + break; + + + case PCI_DEVICE_NEO_4_DID: + case PCI_DEVICE_NEO_8_DID: + case PCI_DEVICE_NEO_2DB9_DID: + case PCI_DEVICE_NEO_2DB9PRI_DID: + case PCI_DEVICE_NEO_2RJ45_DID: + case PCI_DEVICE_NEO_2RJ45PRI_DID: + case PCI_DEVICE_NEO_1_422_DID: + case PCI_DEVICE_NEO_1_422_485_DID: + case PCI_DEVICE_NEO_2_422_485_DID: + case PCI_DEVICE_NEO_EXPRESS_8_DID: + case PCI_DEVICE_NEO_EXPRESS_4_DID: + case PCI_DEVICE_NEO_EXPRESS_4RJ45_DID: + case PCI_DEVICE_NEO_EXPRESS_8RJ45_DID: + + /* + * This chip is set up 100% when we get to it. + * No need to enable global interrupts or anything. + */ + if (brd->bd_flags & BD_IS_PCI_EXPRESS) + brd->dpatype = T_NEO_EXPRESS | T_PCIBUS; + else + brd->dpatype = T_NEO | T_PCIBUS; + + DPR_INIT(("dgnc_found_board - NEO.\n")); + + /* get the PCI Base Address Registers */ + brd->membase = pci_resource_start(pdev, 0); + brd->membase_end = pci_resource_end(pdev, 0); + + if (brd->membase & 1) + brd->membase &= ~3; + else + brd->membase &= ~15; + + /* Assign the board_ops struct */ + brd->bd_ops = &dgnc_neo_ops; + + brd->bd_uart_offset = 0x200; + brd->bd_dividend = 921600; + + dgnc_do_remap(brd); + + if (brd->re_map_membase) { + + /* After remap is complete, we need to read and store the dvid */ + brd->dvid = readb(brd->re_map_membase + 0x8D); + + /* Get and store the board VPD, if it exists */ + brd->bd_ops->vpd(brd); + } + break; + + default: + APR(("Did not find any compatible Neo or Classic PCI boards in system.\n")); + return (-ENXIO); + + } + + /* + * Do tty device initialization. + */ + + rc = dgnc_tty_register(brd); + if (rc < 0) { + dgnc_tty_uninit(brd); + APR(("Can't register tty devices (%d)\n", rc)); + brd->state = BOARD_FAILED; + brd->dpastatus = BD_NOFEP; + goto failed; + } + + rc = dgnc_finalize_board_init(brd); + if (rc < 0) { + APR(("Can't finalize board init (%d)\n", rc)); + brd->state = BOARD_FAILED; + brd->dpastatus = BD_NOFEP; + + goto failed; + } + + rc = dgnc_tty_init(brd); + if (rc < 0) { + dgnc_tty_uninit(brd); + APR(("Can't init tty devices (%d)\n", rc)); + brd->state = BOARD_FAILED; + brd->dpastatus = BD_NOFEP; + + goto failed; + } + + brd->state = BOARD_READY; + brd->dpastatus = BD_RUNNING; + + dgnc_create_ports_sysfiles(brd); + + /* init our poll helper tasklet */ + tasklet_init(&brd->helper_tasklet, brd->bd_ops->tasklet, (unsigned long) brd); + + /* Log the information about the board */ + dgnc_mbuf(brd, DRVSTR": board %d: %s (rev %d), irq %d\n", + dgnc_NumBoards, brd->name, brd->rev, brd->irq); + + DPR_INIT(("dgnc_scan(%d) - printing out the msgbuf\n", i)); + DGNC_LOCK(dgnc_global_lock, flags); + brd->msgbuf = NULL; + printk(brd->msgbuf_head); + kfree(brd->msgbuf_head); + brd->msgbuf_head = NULL; + DGNC_UNLOCK(dgnc_global_lock, flags); + + /* + * allocate flip buffer for board. + * + * Okay to malloc with GFP_KERNEL, we are not at interrupt + * context, and there are no locks held. + */ + brd->flipbuf = dgnc_driver_kzmalloc(MYFLIPLEN, GFP_KERNEL); + + dgnc_proc_register_basic_postscan(dgnc_NumBoards); + + wake_up_interruptible(&brd->state_wait); + + return(0); + +failed: + + return (-ENXIO); + +} + + +static int dgnc_finalize_board_init(struct board_t *brd) { + int rc = 0; + + DPR_INIT(("dgnc_finalize_board_init() - start\n")); + + if (!brd || brd->magic != DGNC_BOARD_MAGIC) + return(-ENODEV); + + DPR_INIT(("dgnc_finalize_board_init() - start #2\n")); + + if (brd->irq) { + rc = request_irq(brd->irq, brd->bd_ops->intr, IRQF_SHARED, "DGNC", brd); + + if (rc) { + printk("Failed to hook IRQ %d\n",brd->irq); + brd->state = BOARD_FAILED; + brd->dpastatus = BD_NOFEP; + rc = -ENODEV; + } else { + DPR_INIT(("Requested and received usage of IRQ %d\n", brd->irq)); + } + } + return(rc); +} + +/* + * Remap PCI memory. + */ +static void dgnc_do_remap(struct board_t *brd) +{ + + if (!brd || brd->magic != DGNC_BOARD_MAGIC) + return; + + brd->re_map_membase = ioremap(brd->membase, 0x1000); + + DPR_INIT(("remapped mem: 0x%p\n", brd->re_map_membase)); +} + + +/***************************************************************************** +* +* Function: +* +* dgnc_poll_handler +* +* Author: +* +* Scott H Kilau +* +* Parameters: +* +* dummy -- ignored +* +* Return Values: +* +* none +* +* Description: +* +* As each timer expires, it determines (a) whether the "transmit" +* waiter needs to be woken up, and (b) whether the poller needs to +* be rescheduled. +* +******************************************************************************/ + +static void dgnc_poll_handler(ulong dummy) +{ + struct board_t *brd; + unsigned long lock_flags; + int i; + unsigned long new_time; + + dgnc_poll_counter++; + + /* + * Do not start the board state machine until + * driver tells us its up and running, and has + * everything it needs. + */ + if (dgnc_driver_state != DRIVER_READY) { + goto schedule_poller; + } + + /* Go thru each board, kicking off a tasklet for each if needed */ + for (i = 0; i < dgnc_NumBoards; i++) { + brd = dgnc_Board[i]; + + DGNC_LOCK(brd->bd_lock, lock_flags); + + /* If board is in a failed state, don't bother scheduling a tasklet */ + if (brd->state == BOARD_FAILED) { + DGNC_UNLOCK(brd->bd_lock, lock_flags); + continue; + } + + /* Schedule a poll helper task */ + tasklet_schedule(&brd->helper_tasklet); + + DGNC_UNLOCK(brd->bd_lock, lock_flags); + } + +schedule_poller: + + /* + * Schedule ourself back at the nominal wakeup interval. + */ + DGNC_LOCK(dgnc_poll_lock, lock_flags); + dgnc_poll_time += dgnc_jiffies_from_ms(dgnc_poll_tick); + + new_time = dgnc_poll_time - jiffies; + + if ((ulong) new_time >= 2 * dgnc_poll_tick) { + dgnc_poll_time = jiffies + dgnc_jiffies_from_ms(dgnc_poll_tick); + } + + init_timer(&dgnc_poll_timer); + dgnc_poll_timer.function = dgnc_poll_handler; + dgnc_poll_timer.data = 0; + dgnc_poll_timer.expires = dgnc_poll_time; + DGNC_UNLOCK(dgnc_poll_lock, lock_flags); + + if (!dgnc_poll_stop) + add_timer(&dgnc_poll_timer); +} + +/* + * dgnc_init_globals() + * + * This is where we initialize the globals from the static insmod + * configuration variables. These are declared near the head of + * this file. + */ +static void dgnc_init_globals(void) +{ + int i = 0; + + dgnc_rawreadok = rawreadok; + dgnc_trcbuf_size = trcbuf_size; + dgnc_debug = debug; + + for (i = 0; i < MAXBOARDS; i++) { + dgnc_Board[i] = NULL; + } + + init_timer(&dgnc_poll_timer); +} + + +/************************************************************************ + * + * Utility functions + * + ************************************************************************/ + + +/* + * dgnc_driver_kzmalloc() + * + * Malloc and clear memory, + */ +void *dgnc_driver_kzmalloc(size_t size, int priority) +{ + void *p = kmalloc(size, priority); + if(p) + memset(p, 0, size); + return(p); +} + + +/* + * dgnc_mbuf() + * + * Used to print to the message buffer during board init. + */ +static void dgnc_mbuf(struct board_t *brd, const char *fmt, ...) { + va_list ap; + char buf[1024]; + int i; + unsigned long flags; + + DGNC_LOCK(dgnc_global_lock, flags); + + /* Format buf using fmt and arguments contained in ap. */ + va_start(ap, fmt); + i = vsprintf(buf, fmt, ap); + va_end(ap); + + DPR((buf)); + + if (!brd || !brd->msgbuf) { + printk(buf); + DGNC_UNLOCK(dgnc_global_lock, flags); + return; + } + + memcpy(brd->msgbuf, buf, strlen(buf)); + brd->msgbuf += strlen(buf); + *brd->msgbuf = (char) NULL; + + DGNC_UNLOCK(dgnc_global_lock, flags); +} + + +/* + * dgnc_ms_sleep() + * + * Put the driver to sleep for x ms's + * + * Returns 0 if timed out, !0 (showing signal) if interrupted by a signal. + */ +int dgnc_ms_sleep(ulong ms) +{ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout((ms * HZ) / 1000); + return (signal_pending(current)); +} + + + +/* + * dgnc_ioctl_name() : Returns a text version of each ioctl value. + */ +char *dgnc_ioctl_name(int cmd) +{ + switch(cmd) { + + case TCGETA: return("TCGETA"); + case TCGETS: return("TCGETS"); + case TCSETA: return("TCSETA"); + case TCSETS: return("TCSETS"); + case TCSETAW: return("TCSETAW"); + case TCSETSW: return("TCSETSW"); + case TCSETAF: return("TCSETAF"); + case TCSETSF: return("TCSETSF"); + case TCSBRK: return("TCSBRK"); + case TCXONC: return("TCXONC"); + case TCFLSH: return("TCFLSH"); + case TIOCGSID: return("TIOCGSID"); + + case TIOCGETD: return("TIOCGETD"); + case TIOCSETD: return("TIOCSETD"); + case TIOCGWINSZ: return("TIOCGWINSZ"); + case TIOCSWINSZ: return("TIOCSWINSZ"); + + case TIOCMGET: return("TIOCMGET"); + case TIOCMSET: return("TIOCMSET"); + case TIOCMBIS: return("TIOCMBIS"); + case TIOCMBIC: return("TIOCMBIC"); + + /* from digi.h */ + case DIGI_SETA: return("DIGI_SETA"); + case DIGI_SETAW: return("DIGI_SETAW"); + case DIGI_SETAF: return("DIGI_SETAF"); + case DIGI_SETFLOW: return("DIGI_SETFLOW"); + case DIGI_SETAFLOW: return("DIGI_SETAFLOW"); + case DIGI_GETFLOW: return("DIGI_GETFLOW"); + case DIGI_GETAFLOW: return("DIGI_GETAFLOW"); + case DIGI_GETA: return("DIGI_GETA"); + case DIGI_GEDELAY: return("DIGI_GEDELAY"); + case DIGI_SEDELAY: return("DIGI_SEDELAY"); + case DIGI_GETCUSTOMBAUD: return("DIGI_GETCUSTOMBAUD"); + case DIGI_SETCUSTOMBAUD: return("DIGI_SETCUSTOMBAUD"); + case TIOCMODG: return("TIOCMODG"); + case TIOCMODS: return("TIOCMODS"); + case TIOCSDTR: return("TIOCSDTR"); + case TIOCCDTR: return("TIOCCDTR"); + + default: return("unknown"); + } +} diff --git a/drivers/staging/dgnc/dgnc_driver.h b/drivers/staging/dgnc/dgnc_driver.h new file mode 100644 index 000000000000..43177f47209b --- /dev/null +++ b/drivers/staging/dgnc/dgnc_driver.h @@ -0,0 +1,566 @@ +/* + * Copyright 2003 Digi International (www.digi.com) + * Scott H Kilau + * + * 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, EXPRESS OR IMPLIED; 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. + * + * NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!! + * + ************************************************************************* + * + * Driver includes + * + *************************************************************************/ + +#ifndef __DGNC_DRIVER_H +#define __DGNC_DRIVER_H + +#include /* To get the current Linux version */ +#include /* To pick up the varions Linux types */ +#include /* To pick up the various tty structs/defines */ +#include /* For irqreturn_t type */ + +#include "dgnc_types.h" /* Additional types needed by the Digi header files */ +#include "digi.h" /* Digi specific ioctl header */ +#include "dgnc_kcompat.h" /* Kernel 2.4/2.6 compat includes */ +#include "dgnc_sysfs.h" /* Support for SYSFS */ + +/************************************************************************* + * + * Driver defines + * + *************************************************************************/ + +/* + * Driver identification, error and debugging statments + * + * In theory, you can change all occurances of "digi" in the next + * three lines, and the driver printk's will all automagically change. + * + * APR((fmt, args, ...)); Always prints message + * DPR((fmt, args, ...)); Only prints if DGNC_TRACER is defined at + * compile time and dgnc_debug!=0 + */ +#define PROCSTR "dgnc" /* /proc entries */ +#define DEVSTR "/dev/dg/dgnc" /* /dev entries */ +#define DRVSTR "dgnc" /* Driver name string + * displayed by APR */ +#define APR(args) do { PRINTF_TO_KMEM(args); printk(DRVSTR": "); printk args; \ + } while (0) +#define RAPR(args) do { PRINTF_TO_KMEM(args); printk args; } while (0) + +#define TRC_TO_CONSOLE 1 + +/* + * Debugging levels can be set using debug insmod variable + * They can also be compiled out completely. + */ + +#define DBG_INIT (dgnc_debug & 0x01) +#define DBG_BASIC (dgnc_debug & 0x02) +#define DBG_CORE (dgnc_debug & 0x04) + +#define DBG_OPEN (dgnc_debug & 0x08) +#define DBG_CLOSE (dgnc_debug & 0x10) +#define DBG_READ (dgnc_debug & 0x20) +#define DBG_WRITE (dgnc_debug & 0x40) + +#define DBG_IOCTL (dgnc_debug & 0x80) + +#define DBG_PROC (dgnc_debug & 0x100) +#define DBG_PARAM (dgnc_debug & 0x200) +#define DBG_PSCAN (dgnc_debug & 0x400) +#define DBG_EVENT (dgnc_debug & 0x800) + +#define DBG_DRAIN (dgnc_debug & 0x1000) +#define DBG_MSIGS (dgnc_debug & 0x2000) + +#define DBG_MGMT (dgnc_debug & 0x4000) +#define DBG_INTR (dgnc_debug & 0x8000) + +#define DBG_CARR (dgnc_debug & 0x10000) + + +#if defined(DGNC_TRACER) + +# if defined(TRC_TO_KMEM) +/* Choose one: */ +# define TRC_ON_OVERFLOW_WRAP_AROUND +# undef TRC_ON_OVERFLOW_SHIFT_BUFFER +# endif //TRC_TO_KMEM + +# define TRC_MAXMSG 1024 +# define TRC_OVERFLOW "(OVERFLOW)" +# define TRC_DTRC "/usr/bin/dtrc" + +#if defined TRC_TO_CONSOLE +#define PRINTF_TO_CONSOLE(args) { printk(DRVSTR": "); printk args; } +#else //!defined TRACE_TO_CONSOLE +#define PRINTF_TO_CONSOLE(args) +#endif + +#if defined TRC_TO_KMEM +#define PRINTF_TO_KMEM(args) dgnc_tracef args +#else //!defined TRC_TO_KMEM +#define PRINTF_TO_KMEM(args) +#endif + +#define TRC(args) { PRINTF_TO_KMEM(args); PRINTF_TO_CONSOLE(args) } + +# define DPR_INIT(ARGS) if (DBG_INIT) TRC(ARGS) +# define DPR_BASIC(ARGS) if (DBG_BASIC) TRC(ARGS) +# define DPR_CORE(ARGS) if (DBG_CORE) TRC(ARGS) +# define DPR_OPEN(ARGS) if (DBG_OPEN) TRC(ARGS) +# define DPR_CLOSE(ARGS) if (DBG_CLOSE) TRC(ARGS) +# define DPR_READ(ARGS) if (DBG_READ) TRC(ARGS) +# define DPR_WRITE(ARGS) if (DBG_WRITE) TRC(ARGS) +# define DPR_IOCTL(ARGS) if (DBG_IOCTL) TRC(ARGS) +# define DPR_PROC(ARGS) if (DBG_PROC) TRC(ARGS) +# define DPR_PARAM(ARGS) if (DBG_PARAM) TRC(ARGS) +# define DPR_PSCAN(ARGS) if (DBG_PSCAN) TRC(ARGS) +# define DPR_EVENT(ARGS) if (DBG_EVENT) TRC(ARGS) +# define DPR_DRAIN(ARGS) if (DBG_DRAIN) TRC(ARGS) +# define DPR_CARR(ARGS) if (DBG_CARR) TRC(ARGS) +# define DPR_MGMT(ARGS) if (DBG_MGMT) TRC(ARGS) +# define DPR_INTR(ARGS) if (DBG_INTR) TRC(ARGS) +# define DPR_MSIGS(ARGS) if (DBG_MSIGS) TRC(ARGS) + +# define DPR(ARGS) if (dgnc_debug) TRC(ARGS) +# define P(X) dgnc_tracef(#X "=%p\n", X) +# define X(X) dgnc_tracef(#X "=%x\n", X) + +#else//!defined DGNC_TRACER + +#define PRINTF_TO_KMEM(args) +# define TRC(ARGS) +# define DPR_INIT(ARGS) +# define DPR_BASIC(ARGS) +# define DPR_CORE(ARGS) +# define DPR_OPEN(ARGS) +# define DPR_CLOSE(ARGS) +# define DPR_READ(ARGS) +# define DPR_WRITE(ARGS) +# define DPR_IOCTL(ARGS) +# define DPR_PROC(ARGS) +# define DPR_PARAM(ARGS) +# define DPR_PSCAN(ARGS) +# define DPR_EVENT(ARGS) +# define DPR_DRAIN(ARGS) +# define DPR_CARR(ARGS) +# define DPR_MGMT(ARGS) +# define DPR_INTR(ARGS) +# define DPR_MSIGS(ARGS) + +# define DPR(args) + +#endif//DGNC_TRACER + +/* Number of boards we support at once. */ +#define MAXBOARDS 20 +#define MAXPORTS 8 +#define MAXTTYNAMELEN 200 + +/* Our 3 magic numbers for our board, channel and unit structs */ +#define DGNC_BOARD_MAGIC 0x5c6df104 +#define DGNC_CHANNEL_MAGIC 0x6c6df104 +#define DGNC_UNIT_MAGIC 0x7c6df104 + +/* Serial port types */ +#define DGNC_SERIAL 0 +#define DGNC_PRINT 1 + +#define SERIAL_TYPE_NORMAL 1 + +#define PORT_NUM(dev) ((dev) & 0x7f) +#define IS_PRINT(dev) (((dev) & 0xff) >= 0x80) + +/* MAX number of stop characters we will send when our read queue is getting full */ +#define MAX_STOPS_SENT 5 + +/* 4 extra for alignment play space */ +#define WRITEBUFLEN ((4096) + 4) +#define MYFLIPLEN N_TTY_BUF_SIZE + +#define dgnc_jiffies_from_ms(a) (((a) * HZ) / 1000) + +/* + * Define a local default termios struct. All ports will be created + * with this termios initially. This is the same structure that is defined + * as the default in tty_io.c with the same settings overriden as in serial.c + * + * In short, this should match the internal serial ports' defaults. + */ +#define DEFAULT_IFLAGS (ICRNL | IXON) +#define DEFAULT_OFLAGS (OPOST | ONLCR) +#define DEFAULT_CFLAGS (B9600 | CS8 | CREAD | HUPCL | CLOCAL) +#define DEFAULT_LFLAGS (ISIG | ICANON | ECHO | ECHOE | ECHOK | \ + ECHOCTL | ECHOKE | IEXTEN) + +#ifndef _POSIX_VDISABLE +#define _POSIX_VDISABLE '\0' +#endif + +#define SNIFF_MAX 65536 /* Sniff buffer size (2^n) */ +#define SNIFF_MASK (SNIFF_MAX - 1) /* Sniff wrap mask */ + +/* + * Lock function/defines. + * Makes spotting lock/unlock locations easier. + */ +# define DGNC_SPINLOCK_INIT(x) spin_lock_init(&(x)) +# define DGNC_LOCK(x,y) spin_lock_irqsave(&(x), y) +# define DGNC_UNLOCK(x,y) spin_unlock_irqrestore(&(x), y) + +/* + * All the possible states the driver can be while being loaded. + */ +enum { + DRIVER_INITIALIZED = 0, + DRIVER_READY +}; + +/* + * All the possible states the board can be while booting up. + */ +enum { + BOARD_FAILED = 0, + BOARD_FOUND, + BOARD_READY +}; + + +/************************************************************************* + * + * Structures and closely related defines. + * + *************************************************************************/ + +struct board_t; +struct channel_t; + +/************************************************************************ + * Per board operations structure * + ************************************************************************/ +struct board_ops { + void (*tasklet) (unsigned long data); + irqreturn_t (*intr) (int irq, void *voidbrd); + void (*uart_init) (struct channel_t *ch); + void (*uart_off) (struct channel_t *ch); + int (*drain) (struct tty_struct *tty, uint seconds); + void (*param) (struct tty_struct *tty); + void (*vpd) (struct board_t *brd); + void (*assert_modem_signals) (struct channel_t *ch); + void (*flush_uart_write) (struct channel_t *ch); + void (*flush_uart_read) (struct channel_t *ch); + void (*disable_receiver) (struct channel_t *ch); + void (*enable_receiver) (struct channel_t *ch); + void (*send_break) (struct channel_t *ch, int); + void (*send_start_character) (struct channel_t *ch); + void (*send_stop_character) (struct channel_t *ch); + void (*copy_data_from_queue_to_uart) (struct channel_t *ch); + uint (*get_uart_bytes_left) (struct channel_t *ch); + void (*send_immediate_char) (struct channel_t *ch, unsigned char); +}; + +/************************************************************************ + * Device flag definitions for bd_flags. + ************************************************************************/ +#define BD_IS_PCI_EXPRESS 0x0001 /* Is a PCI Express board */ + + +/* + * Per-board information + */ +struct board_t +{ + int magic; /* Board Magic number. */ + int boardnum; /* Board number: 0-32 */ + + int type; /* Type of board */ + char *name; /* Product Name */ + struct pci_dev *pdev; /* Pointer to the pci_dev struct */ + unsigned long bd_flags; /* Board flags */ + u16 vendor; /* PCI vendor ID */ + u16 device; /* PCI device ID */ + u16 subvendor; /* PCI subsystem vendor ID */ + u16 subdevice; /* PCI subsystem device ID */ + uchar rev; /* PCI revision ID */ + uint pci_bus; /* PCI bus value */ + uint pci_slot; /* PCI slot value */ + uint maxports; /* MAX ports this board can handle */ + uchar dvid; /* Board specific device id */ + uchar vpd[128]; /* VPD of board, if found */ + uchar serial_num[20]; /* Serial number of board, if found in VPD */ + + spinlock_t bd_lock; /* Used to protect board */ + + spinlock_t bd_intr_lock; /* Used to protect the poller tasklet and + * the interrupt routine from each other. + */ + + uint state; /* State of card. */ + wait_queue_head_t state_wait; /* Place to sleep on for state change */ + + struct tasklet_struct helper_tasklet; /* Poll helper tasklet */ + + uint nasync; /* Number of ports on card */ + + uint irq; /* Interrupt request number */ + ulong intr_count; /* Count of interrupts */ + ulong intr_modem; /* Count of interrupts */ + ulong intr_tx; /* Count of interrupts */ + ulong intr_rx; /* Count of interrupts */ + + ulong membase; /* Start of base memory of the card */ + ulong membase_end; /* End of base memory of the card */ + + uchar *re_map_membase;/* Remapped memory of the card */ + + ulong iobase; /* Start of io base of the card */ + ulong iobase_end; /* End of io base of the card */ + + uint bd_uart_offset; /* Space between each UART */ + + struct channel_t *channels[MAXPORTS]; /* array of pointers to our channels. */ + + struct tty_driver SerialDriver; + char SerialName[200]; + struct tty_driver PrintDriver; + char PrintName[200]; + + uint dgnc_Major_Serial_Registered; + uint dgnc_Major_TransparentPrint_Registered; + + uint dgnc_Serial_Major; + uint dgnc_TransparentPrint_Major; + + uint TtyRefCnt; + + char *flipbuf; /* Our flip buffer, alloced if board is found */ + + u16 dpatype; /* The board "type", as defined by DPA */ + u16 dpastatus; /* The board "status", as defined by DPA */ + + /* + * Mgmt data. + */ + char *msgbuf_head; + char *msgbuf; + + uint bd_dividend; /* Board/UARTs specific dividend */ + + struct board_ops *bd_ops; + + /* /proc/ entries */ + struct proc_dir_entry *proc_entry_pointer; + struct dgnc_proc_entry *dgnc_board_table; + +}; + + +/************************************************************************ + * Unit flag definitions for un_flags. + ************************************************************************/ +#define UN_ISOPEN 0x0001 /* Device is open */ +#define UN_CLOSING 0x0002 /* Line is being closed */ +#define UN_IMM 0x0004 /* Service immediately */ +#define UN_BUSY 0x0008 /* Some work this channel */ +#define UN_BREAKI 0x0010 /* Input break received */ +#define UN_PWAIT 0x0020 /* Printer waiting for terminal */ +#define UN_TIME 0x0040 /* Waiting on time */ +#define UN_EMPTY 0x0080 /* Waiting output queue empty */ +#define UN_LOW 0x0100 /* Waiting output low water mark*/ +#define UN_EXCL_OPEN 0x0200 /* Open for exclusive use */ +#define UN_WOPEN 0x0400 /* Device waiting for open */ +#define UN_WIOCTL 0x0800 /* Device waiting for open */ +#define UN_HANGUP 0x8000 /* Carrier lost */ + +struct device; + +/************************************************************************ + * Structure for terminal or printer unit. + ************************************************************************/ +struct un_t { + int magic; /* Unit Magic Number. */ + struct channel_t *un_ch; + ulong un_time; + uint un_type; + uint un_open_count; /* Counter of opens to port */ + struct tty_struct *un_tty;/* Pointer to unit tty structure */ + uint un_flags; /* Unit flags */ + wait_queue_head_t un_flags_wait; /* Place to sleep to wait on unit */ + uint un_dev; /* Minor device number */ + struct device *un_sysfs; +}; + + +/************************************************************************ + * Device flag definitions for ch_flags. + ************************************************************************/ +#define CH_PRON 0x0001 /* Printer on string */ +#define CH_STOP 0x0002 /* Output is stopped */ +#define CH_STOPI 0x0004 /* Input is stopped */ +#define CH_CD 0x0008 /* Carrier is present */ +#define CH_FCAR 0x0010 /* Carrier forced on */ +#define CH_HANGUP 0x0020 /* Hangup received */ + +#define CH_RECEIVER_OFF 0x0040 /* Receiver is off */ +#define CH_OPENING 0x0080 /* Port in fragile open state */ +#define CH_CLOSING 0x0100 /* Port in fragile close state */ +#define CH_FIFO_ENABLED 0x0200 /* Port has FIFOs enabled */ +#define CH_TX_FIFO_EMPTY 0x0400 /* TX Fifo is completely empty */ +#define CH_TX_FIFO_LWM 0x0800 /* TX Fifo is below Low Water */ +#define CH_BREAK_SENDING 0x1000 /* Break is being sent */ +#define CH_LOOPBACK 0x2000 /* Channel is in lookback mode */ +#define CH_FLIPBUF_IN_USE 0x4000 /* Channel's flipbuf is in use */ +#define CH_BAUD0 0x08000 /* Used for checking B0 transitions */ +#define CH_FORCED_STOP 0x20000 /* Output is forcibly stopped */ +#define CH_FORCED_STOPI 0x40000 /* Input is forcibly stopped */ + +/* + * Definitions for ch_sniff_flags + */ +#define SNIFF_OPEN 0x1 +#define SNIFF_WAIT_DATA 0x2 +#define SNIFF_WAIT_SPACE 0x4 + + +/* Our Read/Error/Write queue sizes */ +#define RQUEUEMASK 0x1FFF /* 8 K - 1 */ +#define EQUEUEMASK 0x1FFF /* 8 K - 1 */ +#define WQUEUEMASK 0x0FFF /* 4 K - 1 */ +#define RQUEUESIZE (RQUEUEMASK + 1) +#define EQUEUESIZE RQUEUESIZE +#define WQUEUESIZE (WQUEUEMASK + 1) + + +/************************************************************************ + * Channel information structure. + ************************************************************************/ +struct channel_t { + int magic; /* Channel Magic Number */ + struct board_t *ch_bd; /* Board structure pointer */ + struct digi_t ch_digi; /* Transparent Print structure */ + struct un_t ch_tun; /* Terminal unit info */ + struct un_t ch_pun; /* Printer unit info */ + + spinlock_t ch_lock; /* provide for serialization */ + wait_queue_head_t ch_flags_wait; + + uint ch_portnum; /* Port number, 0 offset. */ + uint ch_open_count; /* open count */ + uint ch_flags; /* Channel flags */ + + ulong ch_close_delay; /* How long we should drop RTS/DTR for */ + + ulong ch_cpstime; /* Time for CPS calculations */ + + tcflag_t ch_c_iflag; /* channel iflags */ + tcflag_t ch_c_cflag; /* channel cflags */ + tcflag_t ch_c_oflag; /* channel oflags */ + tcflag_t ch_c_lflag; /* channel lflags */ + uchar ch_stopc; /* Stop character */ + uchar ch_startc; /* Start character */ + + uint ch_old_baud; /* Cache of the current baud */ + uint ch_custom_speed;/* Custom baud, if set */ + + uint ch_wopen; /* Waiting for open process cnt */ + + uchar ch_mostat; /* FEP output modem status */ + uchar ch_mistat; /* FEP input modem status */ + + struct neo_uart_struct *ch_neo_uart; /* Pointer to the "mapped" UART struct */ + struct cls_uart_struct *ch_cls_uart; /* Pointer to the "mapped" UART struct */ + + uchar ch_cached_lsr; /* Cached value of the LSR register */ + + uchar *ch_rqueue; /* Our read queue buffer - malloc'ed */ + ushort ch_r_head; /* Head location of the read queue */ + ushort ch_r_tail; /* Tail location of the read queue */ + + uchar *ch_equeue; /* Our error queue buffer - malloc'ed */ + ushort ch_e_head; /* Head location of the error queue */ + ushort ch_e_tail; /* Tail location of the error queue */ + + uchar *ch_wqueue; /* Our write queue buffer - malloc'ed */ + ushort ch_w_head; /* Head location of the write queue */ + ushort ch_w_tail; /* Tail location of the write queue */ + + ulong ch_rxcount; /* total of data received so far */ + ulong ch_txcount; /* total of data transmitted so far */ + + uchar ch_r_tlevel; /* Receive Trigger level */ + uchar ch_t_tlevel; /* Transmit Trigger level */ + + uchar ch_r_watermark; /* Receive Watermark */ + + ulong ch_stop_sending_break; /* Time we should STOP sending a break */ + + uint ch_stops_sent; /* How many times I have sent a stop character + * to try to stop the other guy sending. + */ + ulong ch_err_parity; /* Count of parity errors on channel */ + ulong ch_err_frame; /* Count of framing errors on channel */ + ulong ch_err_break; /* Count of breaks on channel */ + ulong ch_err_overrun; /* Count of overruns on channel */ + + ulong ch_xon_sends; /* Count of xons transmitted */ + ulong ch_xoff_sends; /* Count of xoffs transmitted */ + + ulong ch_intr_modem; /* Count of interrupts */ + ulong ch_intr_tx; /* Count of interrupts */ + ulong ch_intr_rx; /* Count of interrupts */ + + + /* /proc// entries */ + struct proc_dir_entry *proc_entry_pointer; + struct dgnc_proc_entry *dgnc_channel_table; + + uint ch_sniff_in; + uint ch_sniff_out; + char *ch_sniff_buf; /* Sniff buffer for proc */ + ulong ch_sniff_flags; /* Channel flags */ + wait_queue_head_t ch_sniff_wait; +}; + + +/************************************************************************* + * + * Prototypes for non-static functions used in more than one module + * + *************************************************************************/ + +extern int dgnc_ms_sleep(ulong ms); +extern void *dgnc_driver_kzmalloc(size_t size, int priority); +extern char *dgnc_ioctl_name(int cmd); + +/* + * Our Global Variables. + */ +extern int dgnc_driver_state; /* The state of the driver */ +extern uint dgnc_Major; /* Our driver/mgmt major */ +extern int dgnc_debug; /* Debug variable */ +extern int dgnc_rawreadok; /* Set if user wants rawreads */ +extern int dgnc_poll_tick; /* Poll interval - 20 ms */ +extern int dgnc_trcbuf_size; /* Size of the ringbuffer */ +extern spinlock_t dgnc_global_lock; /* Driver global spinlock */ +extern uint dgnc_NumBoards; /* Total number of boards */ +extern struct board_t *dgnc_Board[MAXBOARDS]; /* Array of board structs */ +extern ulong dgnc_poll_counter; /* Times the poller has run */ +extern char *dgnc_state_text[]; /* Array of state text */ +extern char *dgnc_driver_state_text[];/* Array of driver state text */ + +#endif diff --git a/drivers/staging/dgnc/dgnc_kcompat.h b/drivers/staging/dgnc/dgnc_kcompat.h new file mode 100644 index 000000000000..3f69e1dddcaf --- /dev/null +++ b/drivers/staging/dgnc/dgnc_kcompat.h @@ -0,0 +1,91 @@ +/* + * Copyright 2004 Digi International (www.digi.com) + * Scott H Kilau + * + * 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, EXPRESS OR IMPLIED; 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. + * + * NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!! + * + ************************************************************************* + * + * This file is intended to contain all the kernel "differences" between the + * various kernels that we support. + * + *************************************************************************/ + +#ifndef __DGNC_KCOMPAT_H +#define __DGNC_KCOMPAT_H + +# ifndef KERNEL_VERSION +# define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) +# endif + + +#if !defined(TTY_FLIPBUF_SIZE) +# define TTY_FLIPBUF_SIZE 512 +#endif + + +/* Sparse stuff */ +# ifndef __user +# define __user +# define __kernel +# define __safe +# define __force +# define __chk_user_ptr(x) (void)0 +# endif + + +# define PARM_STR(VAR, INIT, PERM, DESC) \ + static char *VAR = INIT; \ + char *dgnc_##VAR; \ + module_param(VAR, charp, PERM); \ + MODULE_PARM_DESC(VAR, DESC); + +# define PARM_INT(VAR, INIT, PERM, DESC) \ + static int VAR = INIT; \ + int dgnc_##VAR; \ + module_param(VAR, int, PERM); \ + MODULE_PARM_DESC(VAR, DESC); + +# define PARM_ULONG(VAR, INIT, PERM, DESC) \ + static ulong VAR = INIT; \ + ulong dgnc_##VAR; \ + module_param(VAR, long, PERM); \ + MODULE_PARM_DESC(VAR, DESC); + + + + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) + + + +/* NOTHING YET */ + + + +# else + + + +# error "this driver does not support anything below the 2.6.27 kernel series." + + + +# endif + +#endif /* ! __DGNC_KCOMPAT_H */ diff --git a/drivers/staging/dgnc/dgnc_mgmt.c b/drivers/staging/dgnc/dgnc_mgmt.c new file mode 100644 index 000000000000..b8e47920111d --- /dev/null +++ b/drivers/staging/dgnc/dgnc_mgmt.c @@ -0,0 +1,313 @@ +/* + * Copyright 2003 Digi International (www.digi.com) + * Scott H Kilau + * + * 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, EXPRESS OR IMPLIED; 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. + * + * + * NOTE TO LINUX KERNEL HACKERS: DO NOT REFORMAT THIS CODE! + * + * This is shared code between Digi's CVS archive and the + * Linux Kernel sources. + * Changing the source just for reformatting needlessly breaks + * our CVS diff history. + * + * Send any bug fixes/changes to: Eng.Linux at digi dot com. + * Thank you. + * + */ + +/************************************************************************ + * + * This file implements the mgmt functionality for the + * Neo and ClassicBoard based product lines. + * + ************************************************************************ + * $Id: dgnc_mgmt.c,v 1.2 2010/12/14 20:08:29 markh Exp $ + */ +#include +#include +#include +#include /* For jiffies, task states */ +#include /* For tasklet and interrupt structs/defines */ +#include +#include +#include /* For copy_from_user/copy_to_user */ + +#include "dgnc_driver.h" +#include "dgnc_pci.h" +#include "dgnc_proc.h" +#include "dgnc_kcompat.h" /* Kernel 2.4/2.6 compat includes */ +#include "dgnc_mgmt.h" +#include "dpacompat.h" + + +/* Our "in use" variables, to enforce 1 open only */ +static int dgnc_mgmt_in_use[MAXMGMTDEVICES]; + + +/* + * dgnc_mgmt_open() + * + * Open the mgmt/downld/dpa device + */ +int dgnc_mgmt_open(struct inode *inode, struct file *file) +{ + unsigned long lock_flags; + unsigned int minor = iminor(inode); + + DPR_MGMT(("dgnc_mgmt_open start.\n")); + + DGNC_LOCK(dgnc_global_lock, lock_flags); + + /* mgmt device */ + if (minor < MAXMGMTDEVICES) { + /* Only allow 1 open at a time on mgmt device */ + if (dgnc_mgmt_in_use[minor]) { + DGNC_UNLOCK(dgnc_global_lock, lock_flags); + return (-EBUSY); + } + dgnc_mgmt_in_use[minor]++; + } + else { + DGNC_UNLOCK(dgnc_global_lock, lock_flags); + return (-ENXIO); + } + + DGNC_UNLOCK(dgnc_global_lock, lock_flags); + + DPR_MGMT(("dgnc_mgmt_open finish.\n")); + + return 0; +} + + +/* + * dgnc_mgmt_close() + * + * Open the mgmt/dpa device + */ +int dgnc_mgmt_close(struct inode *inode, struct file *file) +{ + unsigned long lock_flags; + unsigned int minor = iminor(inode); + + DPR_MGMT(("dgnc_mgmt_close start.\n")); + + DGNC_LOCK(dgnc_global_lock, lock_flags); + + /* mgmt device */ + if (minor < MAXMGMTDEVICES) { + if (dgnc_mgmt_in_use[minor]) { + dgnc_mgmt_in_use[minor] = 0; + } + } + DGNC_UNLOCK(dgnc_global_lock, lock_flags); + + DPR_MGMT(("dgnc_mgmt_close finish.\n")); + + return 0; +} + + +/* + * dgnc_mgmt_ioctl() + * + * ioctl the mgmt/dpa device + */ +#ifdef HAVE_UNLOCKED_IOCTL +long dgnc_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct inode *inode = file->f_dentry->d_inode; +#else +int dgnc_mgmt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ +#endif + unsigned long lock_flags; + void __user *uarg = (void __user *) arg; + + DPR_MGMT(("dgnc_mgmt_ioctl start.\n")); + + switch (cmd) { + + case DIGI_GETDD: + { + /* + * This returns the total number of boards + * in the system, as well as driver version + * and has space for a reserved entry + */ + struct digi_dinfo ddi; + + DGNC_LOCK(dgnc_global_lock, lock_flags); + + ddi.dinfo_nboards = dgnc_NumBoards; + sprintf(ddi.dinfo_version, "%s", DG_PART); + + DGNC_UNLOCK(dgnc_global_lock, lock_flags); + + DPR_MGMT(("DIGI_GETDD returning numboards: %d version: %s\n", + ddi.dinfo_nboards, ddi.dinfo_version)); + + if (copy_to_user(uarg, &ddi, sizeof (ddi))) + return(-EFAULT); + + break; + } + + case DIGI_GETBD: + { + int brd; + + struct digi_info di; + + if (copy_from_user(&brd, uarg, sizeof(int))) { + return(-EFAULT); + } + + DPR_MGMT(("DIGI_GETBD asking about board: %d\n", brd)); + + if ((brd < 0) || (brd > dgnc_NumBoards) || (dgnc_NumBoards == 0)) + return (-ENODEV); + + memset(&di, 0, sizeof(di)); + + di.info_bdnum = brd; + + DGNC_LOCK(dgnc_Board[brd]->bd_lock, lock_flags); + + di.info_bdtype = dgnc_Board[brd]->dpatype; + di.info_bdstate = dgnc_Board[brd]->dpastatus; + di.info_ioport = 0; + di.info_physaddr = (ulong) dgnc_Board[brd]->membase; + di.info_physsize = (ulong) dgnc_Board[brd]->membase - dgnc_Board[brd]->membase_end; + if (dgnc_Board[brd]->state != BOARD_FAILED) + di.info_nports = dgnc_Board[brd]->nasync; + else + di.info_nports = 0; + + DGNC_UNLOCK(dgnc_Board[brd]->bd_lock, lock_flags); + + DPR_MGMT(("DIGI_GETBD returning type: %x state: %x ports: %x size: %x\n", + di.info_bdtype, di.info_bdstate, di.info_nports, di.info_physsize)); + + if (copy_to_user(uarg, &di, sizeof (di))) + return (-EFAULT); + + break; + } + + case DIGI_GET_NI_INFO: + { + struct channel_t *ch; + struct ni_info ni; + uchar mstat = 0; + uint board = 0; + uint channel = 0; + + if (copy_from_user(&ni, uarg, sizeof(struct ni_info))) { + return(-EFAULT); + } + + DPR_MGMT(("DIGI_GETBD asking about board: %d channel: %d\n", + ni.board, ni.channel)); + + board = ni.board; + channel = ni.channel; + + /* Verify boundaries on board */ + if ((board < 0) || (board > dgnc_NumBoards) || (dgnc_NumBoards == 0)) + return (-ENODEV); + + /* Verify boundaries on channel */ + if ((channel < 0) || (channel > dgnc_Board[board]->nasync)) + return (-ENODEV); + + ch = dgnc_Board[board]->channels[channel]; + + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return (-ENODEV); + + memset(&ni, 0, sizeof(ni)); + ni.board = board; + ni.channel = channel; + + DGNC_LOCK(ch->ch_lock, lock_flags); + + mstat = (ch->ch_mostat | ch->ch_mistat); + + if (mstat & UART_MCR_DTR) { + ni.mstat |= TIOCM_DTR; + ni.dtr = TIOCM_DTR; + } + if (mstat & UART_MCR_RTS) { + ni.mstat |= TIOCM_RTS; + ni.rts = TIOCM_RTS; + } + if (mstat & UART_MSR_CTS) { + ni.mstat |= TIOCM_CTS; + ni.cts = TIOCM_CTS; + } + if (mstat & UART_MSR_RI) { + ni.mstat |= TIOCM_RI; + ni.ri = TIOCM_RI; + } + if (mstat & UART_MSR_DCD) { + ni.mstat |= TIOCM_CD; + ni.dcd = TIOCM_CD; + } + if (mstat & UART_MSR_DSR) + ni.mstat |= TIOCM_DSR; + + ni.iflag = ch->ch_c_iflag; + ni.oflag = ch->ch_c_oflag; + ni.cflag = ch->ch_c_cflag; + ni.lflag = ch->ch_c_lflag; + + if (ch->ch_digi.digi_flags & CTSPACE || ch->ch_c_cflag & CRTSCTS) + ni.hflow = 1; + else + ni.hflow = 0; + + if ((ch->ch_flags & CH_STOPI) || (ch->ch_flags & CH_FORCED_STOPI)) + ni.recv_stopped = 1; + else + ni.recv_stopped = 0; + + if ((ch->ch_flags & CH_STOP) || (ch->ch_flags & CH_FORCED_STOP)) + ni.xmit_stopped = 1; + else + ni.xmit_stopped = 0; + + ni.curtx = ch->ch_txcount; + ni.currx = ch->ch_rxcount; + + ni.baud = ch->ch_old_baud; + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + if (copy_to_user(uarg, &ni, sizeof(ni))) + return (-EFAULT); + + break; + } + + + } + + DPR_MGMT(("dgnc_mgmt_ioctl finish.\n")); + + return 0; +} diff --git a/drivers/staging/dgnc/dgnc_mgmt.h b/drivers/staging/dgnc/dgnc_mgmt.h new file mode 100644 index 000000000000..a0d1338ee545 --- /dev/null +++ b/drivers/staging/dgnc/dgnc_mgmt.h @@ -0,0 +1,37 @@ +/* + * Copyright 2003 Digi International (www.digi.com) + * Scott H Kilau + * + * 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, EXPRESS OR IMPLIED; 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. + * + * NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!! + */ + +#ifndef __DGNC_MGMT_H +#define __DGNC_MGMT_H + +#define MAXMGMTDEVICES 8 + +int dgnc_mgmt_open(struct inode *inode, struct file *file); +int dgnc_mgmt_close(struct inode *inode, struct file *file); + +#ifdef HAVE_UNLOCKED_IOCTL +long dgnc_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg); +#else +int dgnc_mgmt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); +#endif + +#endif + diff --git a/drivers/staging/dgnc/dgnc_neo.c b/drivers/staging/dgnc/dgnc_neo.c new file mode 100644 index 000000000000..503db8fae166 --- /dev/null +++ b/drivers/staging/dgnc/dgnc_neo.c @@ -0,0 +1,1977 @@ +/* + * Copyright 2003 Digi International (www.digi.com) + * Scott H Kilau + * + * 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, EXPRESS OR IMPLIED; 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. + * + * + * NOTE TO LINUX KERNEL HACKERS: DO NOT REFORMAT THIS CODE! + * + * This is shared code between Digi's CVS archive and the + * Linux Kernel sources. + * Changing the source just for reformatting needlessly breaks + * our CVS diff history. + * + * Send any bug fixes/changes to: Eng.Linux at digi dot com. + * Thank you. + * + * + * $Id: dgnc_neo.c,v 1.1.1.1 2009/05/20 12:19:19 markh Exp $ + */ + + +#include +#include +#include /* For jiffies, task states */ +#include /* For tasklet and interrupt structs/defines */ +#include /* For udelay */ +#include /* For read[bwl]/write[bwl] */ +#include /* For struct async_serial */ +#include /* For the various UART offsets */ + +#include "dgnc_driver.h" /* Driver main header file */ +#include "dgnc_neo.h" /* Our header file */ +#include "dgnc_tty.h" +#include "dgnc_trace.h" + +static inline void neo_parse_lsr(struct board_t *brd, uint port); +static inline void neo_parse_isr(struct board_t *brd, uint port); +static void neo_copy_data_from_uart_to_queue(struct channel_t *ch); +static inline void neo_clear_break(struct channel_t *ch, int force); +static inline void neo_set_cts_flow_control(struct channel_t *ch); +static inline void neo_set_rts_flow_control(struct channel_t *ch); +static inline void neo_set_ixon_flow_control(struct channel_t *ch); +static inline void neo_set_ixoff_flow_control(struct channel_t *ch); +static inline void neo_set_no_output_flow_control(struct channel_t *ch); +static inline void neo_set_no_input_flow_control(struct channel_t *ch); +static inline void neo_set_new_start_stop_chars(struct channel_t *ch); +static void neo_parse_modem(struct channel_t *ch, uchar signals); +static void neo_tasklet(unsigned long data); +static void neo_vpd(struct board_t *brd); +static void neo_uart_init(struct channel_t *ch); +static void neo_uart_off(struct channel_t *ch); +static int neo_drain(struct tty_struct *tty, uint seconds); +static void neo_param(struct tty_struct *tty); +static void neo_assert_modem_signals(struct channel_t *ch); +static void neo_flush_uart_write(struct channel_t *ch); +static void neo_flush_uart_read(struct channel_t *ch); +static void neo_disable_receiver(struct channel_t *ch); +static void neo_enable_receiver(struct channel_t *ch); +static void neo_send_break(struct channel_t *ch, int msecs); +static void neo_send_start_character(struct channel_t *ch); +static void neo_send_stop_character(struct channel_t *ch); +static void neo_copy_data_from_queue_to_uart(struct channel_t *ch); +static uint neo_get_uart_bytes_left(struct channel_t *ch); +static void neo_send_immediate_char(struct channel_t *ch, unsigned char c); +static irqreturn_t neo_intr(int irq, void *voidbrd); + + +struct board_ops dgnc_neo_ops = { + .tasklet = neo_tasklet, + .intr = neo_intr, + .uart_init = neo_uart_init, + .uart_off = neo_uart_off, + .drain = neo_drain, + .param = neo_param, + .vpd = neo_vpd, + .assert_modem_signals = neo_assert_modem_signals, + .flush_uart_write = neo_flush_uart_write, + .flush_uart_read = neo_flush_uart_read, + .disable_receiver = neo_disable_receiver, + .enable_receiver = neo_enable_receiver, + .send_break = neo_send_break, + .send_start_character = neo_send_start_character, + .send_stop_character = neo_send_stop_character, + .copy_data_from_queue_to_uart = neo_copy_data_from_queue_to_uart, + .get_uart_bytes_left = neo_get_uart_bytes_left, + .send_immediate_char = neo_send_immediate_char +}; + +static uint dgnc_offset_table[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; + + +/* + * This function allows calls to ensure that all outstanding + * PCI writes have been completed, by doing a PCI read against + * a non-destructive, read-only location on the Neo card. + * + * In this case, we are reading the DVID (Read-only Device Identification) + * value of the Neo card. + */ +static inline void neo_pci_posting_flush(struct board_t *bd) +{ + readb(bd->re_map_membase + 0x8D); +} + +static inline void neo_set_cts_flow_control(struct channel_t *ch) +{ + uchar ier = readb(&ch->ch_neo_uart->ier); + uchar efr = readb(&ch->ch_neo_uart->efr); + + + DPR_PARAM(("Setting CTSFLOW\n")); + + /* Turn on auto CTS flow control */ +#if 1 + ier |= (UART_17158_IER_CTSDSR); +#else + ier &= ~(UART_17158_IER_CTSDSR); +#endif + + efr |= (UART_17158_EFR_ECB | UART_17158_EFR_CTSDSR); + + /* Turn off auto Xon flow control */ + efr &= ~(UART_17158_EFR_IXON); + + /* Why? Becuz Exar's spec says we have to zero it out before setting it */ + writeb(0, &ch->ch_neo_uart->efr); + + /* Turn on UART enhanced bits */ + writeb(efr, &ch->ch_neo_uart->efr); + + /* Turn on table D, with 8 char hi/low watermarks */ + writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_4DELAY), &ch->ch_neo_uart->fctr); + + /* Feed the UART our trigger levels */ + writeb(8, &ch->ch_neo_uart->tfifo); + ch->ch_t_tlevel = 8; + + writeb(ier, &ch->ch_neo_uart->ier); + + neo_pci_posting_flush(ch->ch_bd); +} + + +static inline void neo_set_rts_flow_control(struct channel_t *ch) +{ + uchar ier = readb(&ch->ch_neo_uart->ier); + uchar efr = readb(&ch->ch_neo_uart->efr); + + DPR_PARAM(("Setting RTSFLOW\n")); + + /* Turn on auto RTS flow control */ +#if 1 + ier |= (UART_17158_IER_RTSDTR); +#else + ier &= ~(UART_17158_IER_RTSDTR); +#endif + efr |= (UART_17158_EFR_ECB | UART_17158_EFR_RTSDTR); + + /* Turn off auto Xoff flow control */ + ier &= ~(UART_17158_IER_XOFF); + efr &= ~(UART_17158_EFR_IXOFF); + + /* Why? Becuz Exar's spec says we have to zero it out before setting it */ + writeb(0, &ch->ch_neo_uart->efr); + + /* Turn on UART enhanced bits */ + writeb(efr, &ch->ch_neo_uart->efr); + + writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_4DELAY), &ch->ch_neo_uart->fctr); + ch->ch_r_watermark = 4; + + writeb(32, &ch->ch_neo_uart->rfifo); + ch->ch_r_tlevel = 32; + + writeb(ier, &ch->ch_neo_uart->ier); + + /* + * From the Neo UART spec sheet: + * The auto RTS/DTR function must be started by asserting + * RTS/DTR# output pin (MCR bit-0 or 1 to logic 1 after + * it is enabled. + */ + ch->ch_mostat |= (UART_MCR_RTS); + + neo_pci_posting_flush(ch->ch_bd); +} + + +static inline void neo_set_ixon_flow_control(struct channel_t *ch) +{ + uchar ier = readb(&ch->ch_neo_uart->ier); + uchar efr = readb(&ch->ch_neo_uart->efr); + + DPR_PARAM(("Setting IXON FLOW\n")); + + /* Turn off auto CTS flow control */ + ier &= ~(UART_17158_IER_CTSDSR); + efr &= ~(UART_17158_EFR_CTSDSR); + + /* Turn on auto Xon flow control */ + efr |= (UART_17158_EFR_ECB | UART_17158_EFR_IXON); + + /* Why? Becuz Exar's spec says we have to zero it out before setting it */ + writeb(0, &ch->ch_neo_uart->efr); + + /* Turn on UART enhanced bits */ + writeb(efr, &ch->ch_neo_uart->efr); + + writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY), &ch->ch_neo_uart->fctr); + ch->ch_r_watermark = 4; + + writeb(32, &ch->ch_neo_uart->rfifo); + ch->ch_r_tlevel = 32; + + /* Tell UART what start/stop chars it should be looking for */ + writeb(ch->ch_startc, &ch->ch_neo_uart->xonchar1); + writeb(0, &ch->ch_neo_uart->xonchar2); + + writeb(ch->ch_stopc, &ch->ch_neo_uart->xoffchar1); + writeb(0, &ch->ch_neo_uart->xoffchar2); + + writeb(ier, &ch->ch_neo_uart->ier); + + neo_pci_posting_flush(ch->ch_bd); +} + + +static inline void neo_set_ixoff_flow_control(struct channel_t *ch) +{ + uchar ier = readb(&ch->ch_neo_uart->ier); + uchar efr = readb(&ch->ch_neo_uart->efr); + + DPR_PARAM(("Setting IXOFF FLOW\n")); + + /* Turn off auto RTS flow control */ + ier &= ~(UART_17158_IER_RTSDTR); + efr &= ~(UART_17158_EFR_RTSDTR); + + /* Turn on auto Xoff flow control */ + ier |= (UART_17158_IER_XOFF); + efr |= (UART_17158_EFR_ECB | UART_17158_EFR_IXOFF); + + /* Why? Becuz Exar's spec says we have to zero it out before setting it */ + writeb(0, &ch->ch_neo_uart->efr); + + /* Turn on UART enhanced bits */ + writeb(efr, &ch->ch_neo_uart->efr); + + /* Turn on table D, with 8 char hi/low watermarks */ + writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY), &ch->ch_neo_uart->fctr); + + writeb(8, &ch->ch_neo_uart->tfifo); + ch->ch_t_tlevel = 8; + + /* Tell UART what start/stop chars it should be looking for */ + writeb(ch->ch_startc, &ch->ch_neo_uart->xonchar1); + writeb(0, &ch->ch_neo_uart->xonchar2); + + writeb(ch->ch_stopc, &ch->ch_neo_uart->xoffchar1); + writeb(0, &ch->ch_neo_uart->xoffchar2); + + writeb(ier, &ch->ch_neo_uart->ier); + + neo_pci_posting_flush(ch->ch_bd); +} + + +static inline void neo_set_no_input_flow_control(struct channel_t *ch) +{ + uchar ier = readb(&ch->ch_neo_uart->ier); + uchar efr = readb(&ch->ch_neo_uart->efr); + + DPR_PARAM(("Unsetting Input FLOW\n")); + + /* Turn off auto RTS flow control */ + ier &= ~(UART_17158_IER_RTSDTR); + efr &= ~(UART_17158_EFR_RTSDTR); + + /* Turn off auto Xoff flow control */ + ier &= ~(UART_17158_IER_XOFF); + if (ch->ch_c_iflag & IXON) + efr &= ~(UART_17158_EFR_IXOFF); + else + efr &= ~(UART_17158_EFR_ECB | UART_17158_EFR_IXOFF); + + + /* Why? Becuz Exar's spec says we have to zero it out before setting it */ + writeb(0, &ch->ch_neo_uart->efr); + + /* Turn on UART enhanced bits */ + writeb(efr, &ch->ch_neo_uart->efr); + + /* Turn on table D, with 8 char hi/low watermarks */ + writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY), &ch->ch_neo_uart->fctr); + + ch->ch_r_watermark = 0; + + writeb(16, &ch->ch_neo_uart->tfifo); + ch->ch_t_tlevel = 16; + + writeb(16, &ch->ch_neo_uart->rfifo); + ch->ch_r_tlevel = 16; + + writeb(ier, &ch->ch_neo_uart->ier); + + neo_pci_posting_flush(ch->ch_bd); +} + + +static inline void neo_set_no_output_flow_control(struct channel_t *ch) +{ + uchar ier = readb(&ch->ch_neo_uart->ier); + uchar efr = readb(&ch->ch_neo_uart->efr); + + DPR_PARAM(("Unsetting Output FLOW\n")); + + /* Turn off auto CTS flow control */ + ier &= ~(UART_17158_IER_CTSDSR); + efr &= ~(UART_17158_EFR_CTSDSR); + + /* Turn off auto Xon flow control */ + if (ch->ch_c_iflag & IXOFF) + efr &= ~(UART_17158_EFR_IXON); + else + efr &= ~(UART_17158_EFR_ECB | UART_17158_EFR_IXON); + + /* Why? Becuz Exar's spec says we have to zero it out before setting it */ + writeb(0, &ch->ch_neo_uart->efr); + + /* Turn on UART enhanced bits */ + writeb(efr, &ch->ch_neo_uart->efr); + + /* Turn on table D, with 8 char hi/low watermarks */ + writeb((UART_17158_FCTR_TRGD | UART_17158_FCTR_RTS_8DELAY), &ch->ch_neo_uart->fctr); + + ch->ch_r_watermark = 0; + + writeb(16, &ch->ch_neo_uart->tfifo); + ch->ch_t_tlevel = 16; + + writeb(16, &ch->ch_neo_uart->rfifo); + ch->ch_r_tlevel = 16; + + writeb(ier, &ch->ch_neo_uart->ier); + + neo_pci_posting_flush(ch->ch_bd); +} + + +/* change UARTs start/stop chars */ +static inline void neo_set_new_start_stop_chars(struct channel_t *ch) +{ + + /* if hardware flow control is set, then skip this whole thing */ + if (ch->ch_digi.digi_flags & (CTSPACE | RTSPACE) || ch->ch_c_cflag & CRTSCTS) + return; + + DPR_PARAM(("In new start stop chars\n")); + + /* Tell UART what start/stop chars it should be looking for */ + writeb(ch->ch_startc, &ch->ch_neo_uart->xonchar1); + writeb(0, &ch->ch_neo_uart->xonchar2); + + writeb(ch->ch_stopc, &ch->ch_neo_uart->xoffchar1); + writeb(0, &ch->ch_neo_uart->xoffchar2); + + neo_pci_posting_flush(ch->ch_bd); +} + + +/* + * No locks are assumed to be held when calling this function. + */ +static inline void neo_clear_break(struct channel_t *ch, int force) +{ + ulong lock_flags; + + DGNC_LOCK(ch->ch_lock, lock_flags); + + /* Bail if we aren't currently sending a break. */ + if (!ch->ch_stop_sending_break) { + DGNC_UNLOCK(ch->ch_lock, lock_flags); + return; + } + + /* Turn break off, and unset some variables */ + if (ch->ch_flags & CH_BREAK_SENDING) { + if ((jiffies >= ch->ch_stop_sending_break) || force) { + uchar temp = readb(&ch->ch_neo_uart->lcr); + writeb((temp & ~UART_LCR_SBC), &ch->ch_neo_uart->lcr); + neo_pci_posting_flush(ch->ch_bd); + ch->ch_flags &= ~(CH_BREAK_SENDING); + ch->ch_stop_sending_break = 0; + DPR_IOCTL(("Finishing UART_LCR_SBC! finished: %lx\n", jiffies)); + } + } + DGNC_UNLOCK(ch->ch_lock, lock_flags); +} + + +/* + * Parse the ISR register. + */ +static inline void neo_parse_isr(struct board_t *brd, uint port) +{ + struct channel_t *ch; + uchar isr; + uchar cause; + ulong lock_flags; + + if (!brd || brd->magic != DGNC_BOARD_MAGIC) + return; + + if (port > brd->maxports) + return; + + ch = brd->channels[port]; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + /* Here we try to figure out what caused the interrupt to happen */ + while (1) { + + isr = readb(&ch->ch_neo_uart->isr_fcr); + + /* Bail if no pending interrupt */ + if (isr & UART_IIR_NO_INT) { + break; + } + + /* + * Yank off the upper 2 bits, which just show that the FIFO's are enabled. + */ + isr &= ~(UART_17158_IIR_FIFO_ENABLED); + + DPR_INTR(("%s:%d isr: %x\n", __FILE__, __LINE__, isr)); + + if (isr & (UART_17158_IIR_RDI_TIMEOUT | UART_IIR_RDI)) { + /* Read data from uart -> queue */ + brd->intr_rx++; + ch->ch_intr_rx++; + neo_copy_data_from_uart_to_queue(ch); + + /* Call our tty layer to enforce queue flow control if needed. */ + DGNC_LOCK(ch->ch_lock, lock_flags); + dgnc_check_queue_flow_control(ch); + DGNC_UNLOCK(ch->ch_lock, lock_flags); + } + + if (isr & UART_IIR_THRI) { + brd->intr_tx++; + ch->ch_intr_tx++; + /* Transfer data (if any) from Write Queue -> UART. */ + DGNC_LOCK(ch->ch_lock, lock_flags); + ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); + DGNC_UNLOCK(ch->ch_lock, lock_flags); + neo_copy_data_from_queue_to_uart(ch); + } + + if (isr & UART_17158_IIR_XONXOFF) { + cause = readb(&ch->ch_neo_uart->xoffchar1); + + DPR_INTR(("Port %d. Got ISR_XONXOFF: cause:%x\n", port, cause)); + + /* + * Since the UART detected either an XON or + * XOFF match, we need to figure out which + * one it was, so we can suspend or resume data flow. + */ + if (cause == UART_17158_XON_DETECT) { + /* Is output stopped right now, if so, resume it */ + if (brd->channels[port]->ch_flags & CH_STOP) { + DGNC_LOCK(ch->ch_lock, lock_flags); + ch->ch_flags &= ~(CH_STOP); + DGNC_UNLOCK(ch->ch_lock, lock_flags); + } + DPR_INTR(("Port %d. XON detected in incoming data\n", port)); + } + else if (cause == UART_17158_XOFF_DETECT) { + if (!(brd->channels[port]->ch_flags & CH_STOP)) { + DGNC_LOCK(ch->ch_lock, lock_flags); + ch->ch_flags |= CH_STOP; + DGNC_UNLOCK(ch->ch_lock, lock_flags); + DPR_INTR(("Setting CH_STOP\n")); + } + DPR_INTR(("Port: %d. XOFF detected in incoming data\n", port)); + } + } + + if (isr & UART_17158_IIR_HWFLOW_STATE_CHANGE) { + /* + * If we get here, this means the hardware is doing auto flow control. + * Check to see whether RTS/DTR or CTS/DSR caused this interrupt. + */ + brd->intr_modem++; + ch->ch_intr_modem++; + cause = readb(&ch->ch_neo_uart->mcr); + /* Which pin is doing auto flow? RTS or DTR? */ + if ((cause & 0x4) == 0) { + if (cause & UART_MCR_RTS) { + DGNC_LOCK(ch->ch_lock, lock_flags); + ch->ch_mostat |= UART_MCR_RTS; + DGNC_UNLOCK(ch->ch_lock, lock_flags); + } + else { + DGNC_LOCK(ch->ch_lock, lock_flags); + ch->ch_mostat &= ~(UART_MCR_RTS); + DGNC_UNLOCK(ch->ch_lock, lock_flags); + } + } else { + if (cause & UART_MCR_DTR) { + DGNC_LOCK(ch->ch_lock, lock_flags); + ch->ch_mostat |= UART_MCR_DTR; + DGNC_UNLOCK(ch->ch_lock, lock_flags); + } + else { + DGNC_LOCK(ch->ch_lock, lock_flags); + ch->ch_mostat &= ~(UART_MCR_DTR); + DGNC_UNLOCK(ch->ch_lock, lock_flags); + } + } + } + + /* Parse any modem signal changes */ + DPR_INTR(("MOD_STAT: sending to parse_modem_sigs\n")); + neo_parse_modem(ch, readb(&ch->ch_neo_uart->msr)); + } +} + + +static inline void neo_parse_lsr(struct board_t *brd, uint port) +{ + struct channel_t *ch; + int linestatus; + ulong lock_flags; + + if (!brd) + return; + + if (brd->magic != DGNC_BOARD_MAGIC) + return; + + if (port > brd->maxports) + return; + + ch = brd->channels[port]; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + linestatus = readb(&ch->ch_neo_uart->lsr); + + DPR_INTR(("%s:%d port: %d linestatus: %x\n", __FILE__, __LINE__, port, linestatus)); + + ch->ch_cached_lsr |= linestatus; + + if (ch->ch_cached_lsr & UART_LSR_DR) { + brd->intr_rx++; + ch->ch_intr_rx++; + /* Read data from uart -> queue */ + neo_copy_data_from_uart_to_queue(ch); + DGNC_LOCK(ch->ch_lock, lock_flags); + dgnc_check_queue_flow_control(ch); + DGNC_UNLOCK(ch->ch_lock, lock_flags); + } + + /* + * This is a special flag. It indicates that at least 1 + * RX error (parity, framing, or break) has happened. + * Mark this in our struct, which will tell me that I have + *to do the special RX+LSR read for this FIFO load. + */ + if (linestatus & UART_17158_RX_FIFO_DATA_ERROR) { + DPR_INTR(("%s:%d Port: %d Got an RX error, need to parse LSR\n", + __FILE__, __LINE__, port)); + } + + /* + * The next 3 tests should *NOT* happen, as the above test + * should encapsulate all 3... At least, thats what Exar says. + */ + + if (linestatus & UART_LSR_PE) { + ch->ch_err_parity++; + DPR_INTR(("%s:%d Port: %d. PAR ERR!\n", __FILE__, __LINE__, port)); + } + + if (linestatus & UART_LSR_FE) { + ch->ch_err_frame++; + DPR_INTR(("%s:%d Port: %d. FRM ERR!\n", __FILE__, __LINE__, port)); + } + + if (linestatus & UART_LSR_BI) { + ch->ch_err_break++; + DPR_INTR(("%s:%d Port: %d. BRK INTR!\n", __FILE__, __LINE__, port)); + } + + if (linestatus & UART_LSR_OE) { + /* + * Rx Oruns. Exar says that an orun will NOT corrupt + * the FIFO. It will just replace the holding register + * with this new data byte. So basically just ignore this. + * Probably we should eventually have an orun stat in our driver... + */ + ch->ch_err_overrun++; + DPR_INTR(("%s:%d Port: %d. Rx Overrun!\n", __FILE__, __LINE__, port)); + } + + if (linestatus & UART_LSR_THRE) { + brd->intr_tx++; + ch->ch_intr_tx++; + DGNC_LOCK(ch->ch_lock, lock_flags); + ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + /* Transfer data (if any) from Write Queue -> UART. */ + neo_copy_data_from_queue_to_uart(ch); + } + else if (linestatus & UART_17158_TX_AND_FIFO_CLR) { + brd->intr_tx++; + ch->ch_intr_tx++; + DGNC_LOCK(ch->ch_lock, lock_flags); + ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + /* Transfer data (if any) from Write Queue -> UART. */ + neo_copy_data_from_queue_to_uart(ch); + } +} + + +/* + * neo_param() + * Send any/all changes to the line to the UART. + */ +static void neo_param(struct tty_struct *tty) +{ + uchar lcr = 0; + uchar uart_lcr = 0; + uchar ier = 0; + uchar uart_ier = 0; + uint baud = 9600; + int quot = 0; + struct board_t *bd; + struct channel_t *ch; + struct un_t *un; + + if (!tty || tty->magic != TTY_MAGIC) { + return; + } + + un = (struct un_t *) tty->driver_data; + if (!un || un->magic != DGNC_UNIT_MAGIC) { + return; + } + + ch = un->un_ch; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) { + return; + } + + bd = ch->ch_bd; + if (!bd || bd->magic != DGNC_BOARD_MAGIC) { + return; + } + + DPR_PARAM(("param start: tdev: %x cflags: %x oflags: %x iflags: %x\n", + ch->ch_tun.un_dev, ch->ch_c_cflag, ch->ch_c_oflag, ch->ch_c_iflag)); + + /* + * If baud rate is zero, flush queues, and set mval to drop DTR. + */ + if ((ch->ch_c_cflag & (CBAUD)) == 0) { + ch->ch_r_head = ch->ch_r_tail = 0; + ch->ch_e_head = ch->ch_e_tail = 0; + ch->ch_w_head = ch->ch_w_tail = 0; + + neo_flush_uart_write(ch); + neo_flush_uart_read(ch); + + /* The baudrate is B0 so all modem lines are to be dropped. */ + ch->ch_flags |= (CH_BAUD0); + ch->ch_mostat &= ~(UART_MCR_RTS | UART_MCR_DTR); + neo_assert_modem_signals(ch); + ch->ch_old_baud = 0; + return; + + } else if (ch->ch_custom_speed) { + + baud = ch->ch_custom_speed; + /* Handle transition from B0 */ + if (ch->ch_flags & CH_BAUD0) { + ch->ch_flags &= ~(CH_BAUD0); + + /* + * Bring back up RTS and DTR... + * Also handle RTS or DTR toggle if set. + */ + if (!(ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE)) + ch->ch_mostat |= (UART_MCR_RTS); + if (!(ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE)) + ch->ch_mostat |= (UART_MCR_DTR); + } + } else { + int iindex = 0; + int jindex = 0; + + ulong bauds[4][16] = { + { /* slowbaud */ + 0, 50, 75, 110, + 134, 150, 200, 300, + 600, 1200, 1800, 2400, + 4800, 9600, 19200, 38400 }, + { /* slowbaud & CBAUDEX */ + 0, 57600, 115200, 230400, + 460800, 150, 200, 921600, + 600, 1200, 1800, 2400, + 4800, 9600, 19200, 38400 }, + { /* fastbaud */ + 0, 57600, 76800, 115200, + 131657, 153600, 230400, 460800, + 921600, 1200, 1800, 2400, + 4800, 9600, 19200, 38400 }, + { /* fastbaud & CBAUDEX */ + 0, 57600, 115200, 230400, + 460800, 150, 200, 921600, + 600, 1200, 1800, 2400, + 4800, 9600, 19200, 38400 } + }; + + /* Only use the TXPrint baud rate if the terminal unit is NOT open */ + if (!(ch->ch_tun.un_flags & UN_ISOPEN) && (un->un_type == DGNC_PRINT)) + baud = C_BAUD(ch->ch_pun.un_tty) & 0xff; + else + baud = C_BAUD(ch->ch_tun.un_tty) & 0xff; + + if (ch->ch_c_cflag & CBAUDEX) + iindex = 1; + + if (ch->ch_digi.digi_flags & DIGI_FAST) + iindex += 2; + + jindex = baud; + + if ((iindex >= 0) && (iindex < 4) && (jindex >= 0) && (jindex < 16)) { + baud = bauds[iindex][jindex]; + } else { + DPR_IOCTL(("baud indices were out of range (%d)(%d)", + iindex, jindex)); + baud = 0; + } + + if (baud == 0) + baud = 9600; + + /* Handle transition from B0 */ + if (ch->ch_flags & CH_BAUD0) { + ch->ch_flags &= ~(CH_BAUD0); + + /* + * Bring back up RTS and DTR... + * Also handle RTS or DTR toggle if set. + */ + if (!(ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE)) + ch->ch_mostat |= (UART_MCR_RTS); + if (!(ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE)) + ch->ch_mostat |= (UART_MCR_DTR); + } + } + + if (ch->ch_c_cflag & PARENB) { + lcr |= UART_LCR_PARITY; + } + + if (!(ch->ch_c_cflag & PARODD)) { + lcr |= UART_LCR_EPAR; + } + + /* + * Not all platforms support mark/space parity, + * so this will hide behind an ifdef. + */ +#ifdef CMSPAR + if (ch->ch_c_cflag & CMSPAR) + lcr |= UART_LCR_SPAR; +#endif + + if (ch->ch_c_cflag & CSTOPB) + lcr |= UART_LCR_STOP; + + switch (ch->ch_c_cflag & CSIZE) { + case CS5: + lcr |= UART_LCR_WLEN5; + break; + case CS6: + lcr |= UART_LCR_WLEN6; + break; + case CS7: + lcr |= UART_LCR_WLEN7; + break; + case CS8: + default: + lcr |= UART_LCR_WLEN8; + break; + } + + ier = uart_ier = readb(&ch->ch_neo_uart->ier); + uart_lcr = readb(&ch->ch_neo_uart->lcr); + + if (baud == 0) + baud = 9600; + + quot = ch->ch_bd->bd_dividend / baud; + + if (quot != 0 && ch->ch_old_baud != baud) { + ch->ch_old_baud = baud; + writeb(UART_LCR_DLAB, &ch->ch_neo_uart->lcr); + writeb((quot & 0xff), &ch->ch_neo_uart->txrx); + writeb((quot >> 8), &ch->ch_neo_uart->ier); + writeb(lcr, &ch->ch_neo_uart->lcr); + } + + if (uart_lcr != lcr) + writeb(lcr, &ch->ch_neo_uart->lcr); + + if (ch->ch_c_cflag & CREAD) { + ier |= (UART_IER_RDI | UART_IER_RLSI); + } + else { + ier &= ~(UART_IER_RDI | UART_IER_RLSI); + } + + /* + * Have the UART interrupt on modem signal changes ONLY when + * we are in hardware flow control mode, or CLOCAL/FORCEDCD is not set. + */ + if ((ch->ch_digi.digi_flags & CTSPACE) || (ch->ch_digi.digi_flags & RTSPACE) || + (ch->ch_c_cflag & CRTSCTS) || !(ch->ch_digi.digi_flags & DIGI_FORCEDCD) || + !(ch->ch_c_cflag & CLOCAL)) + { + ier |= UART_IER_MSI; + } + else { + ier &= ~UART_IER_MSI; + } + + ier |= UART_IER_THRI; + + if (ier != uart_ier) + writeb(ier, &ch->ch_neo_uart->ier); + + /* Set new start/stop chars */ + neo_set_new_start_stop_chars(ch); + + if (ch->ch_digi.digi_flags & CTSPACE || ch->ch_c_cflag & CRTSCTS) { + neo_set_cts_flow_control(ch); + } + else if (ch->ch_c_iflag & IXON) { + /* If start/stop is set to disable, then we should disable flow control */ + if ((ch->ch_startc == _POSIX_VDISABLE) || (ch->ch_stopc == _POSIX_VDISABLE)) + neo_set_no_output_flow_control(ch); + else + neo_set_ixon_flow_control(ch); + } + else { + neo_set_no_output_flow_control(ch); + } + + if (ch->ch_digi.digi_flags & RTSPACE || ch->ch_c_cflag & CRTSCTS) { + neo_set_rts_flow_control(ch); + } + else if (ch->ch_c_iflag & IXOFF) { + /* If start/stop is set to disable, then we should disable flow control */ + if ((ch->ch_startc == _POSIX_VDISABLE) || (ch->ch_stopc == _POSIX_VDISABLE)) + neo_set_no_input_flow_control(ch); + else + neo_set_ixoff_flow_control(ch); + } + else { + neo_set_no_input_flow_control(ch); + } + + /* + * Adjust the RX FIFO Trigger level if baud is less than 9600. + * Not exactly elegant, but this is needed because of the Exar chip's + * delay on firing off the RX FIFO interrupt on slower baud rates. + */ + if (baud < 9600) { + writeb(1, &ch->ch_neo_uart->rfifo); + ch->ch_r_tlevel = 1; + } + + neo_assert_modem_signals(ch); + + /* Get current status of the modem signals now */ + neo_parse_modem(ch, readb(&ch->ch_neo_uart->msr)); +} + + +/* + * Our board poller function. + */ +static void neo_tasklet(unsigned long data) +{ + struct board_t *bd = (struct board_t *) data; + struct channel_t *ch; + ulong lock_flags; + int i; + int state = 0; + int ports = 0; + + if (!bd || bd->magic != DGNC_BOARD_MAGIC) { + APR(("poll_tasklet() - NULL or bad bd.\n")); + return; + } + + /* Cache a couple board values */ + DGNC_LOCK(bd->bd_lock, lock_flags); + state = bd->state; + ports = bd->nasync; + DGNC_UNLOCK(bd->bd_lock, lock_flags); + + /* + * Do NOT allow the interrupt routine to read the intr registers + * Until we release this lock. + */ + DGNC_LOCK(bd->bd_intr_lock, lock_flags); + + /* + * If board is ready, parse deeper to see if there is anything to do. + */ + if ((state == BOARD_READY) && (ports > 0)) { + /* Loop on each port */ + for (i = 0; i < ports; i++) { + ch = bd->channels[i]; + + /* Just being careful... */ + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + continue; + + /* + * NOTE: Remember you CANNOT hold any channel + * locks when calling the input routine. + * + * During input processing, its possible we + * will call the Linux ld, which might in turn, + * do a callback right back into us, resulting + * in us trying to grab the channel lock twice! + */ + dgnc_input(ch); + + /* + * Channel lock is grabbed and then released + * inside both of these routines, but neither + * call anything else that could call back into us. + */ + neo_copy_data_from_queue_to_uart(ch); + dgnc_wakeup_writes(ch); + + /* + * Call carrier carrier function, in case something + * has changed. + */ + dgnc_carrier(ch); + + /* + * Check to see if we need to turn off a sending break. + * The timing check is done inside clear_break() + */ + if (ch->ch_stop_sending_break) + neo_clear_break(ch, 0); + } + } + + /* Allow interrupt routine to access the interrupt register again */ + DGNC_UNLOCK(bd->bd_intr_lock, lock_flags); + +} + + +/* + * dgnc_neo_intr() + * + * Neo specific interrupt handler. + */ +static irqreturn_t neo_intr(int irq, void *voidbrd) +{ + struct board_t *brd = (struct board_t *) voidbrd; + struct channel_t *ch; + int port = 0; + int type = 0; + int current_port; + u32 tmp; + u32 uart_poll; + unsigned long lock_flags; + unsigned long lock_flags2; + + if (!brd) { + APR(("Received interrupt (%d) with null board associated\n", irq)); + return IRQ_NONE; + } + + /* + * Check to make sure its for us. + */ + if (brd->magic != DGNC_BOARD_MAGIC) { + APR(("Received interrupt (%d) with a board pointer that wasn't ours!\n", irq)); + return IRQ_NONE; + } + + brd->intr_count++; + + /* Lock out the slow poller from running on this board. */ + DGNC_LOCK(brd->bd_intr_lock, lock_flags); + + /* + * Read in "extended" IRQ information from the 32bit Neo register. + * Bits 0-7: What port triggered the interrupt. + * Bits 8-31: Each 3bits indicate what type of interrupt occurred. + */ + uart_poll = readl(brd->re_map_membase + UART_17158_POLL_ADDR_OFFSET); + + DPR_INTR(("%s:%d uart_poll: %x\n", __FILE__, __LINE__, uart_poll)); + + /* + * If 0, no interrupts pending. + * This can happen if the IRQ is shared among a couple Neo/Classic boards. + */ + if (!uart_poll) { + DPR_INTR(("Kernel interrupted to me, but no pending interrupts...\n")); + DGNC_UNLOCK(brd->bd_intr_lock, lock_flags); + return IRQ_NONE; + } + + /* At this point, we have at least SOMETHING to service, dig further... */ + + current_port = 0; + + /* Loop on each port */ + while ((uart_poll & 0xff) != 0) { + + tmp = uart_poll; + + /* Check current port to see if it has interrupt pending */ + if ((tmp & dgnc_offset_table[current_port]) != 0) { + port = current_port; + type = tmp >> (8 + (port * 3)); + type &= 0x7; + } else { + current_port++; + continue; + } + + DPR_INTR(("%s:%d port: %x type: %x\n", __FILE__, __LINE__, port, type)); + + /* Remove this port + type from uart_poll */ + uart_poll &= ~(dgnc_offset_table[port]); + + if (!type) { + /* If no type, just ignore it, and move onto next port */ + DPR_INTR(("Interrupt with no type! port: %d\n", port)); + continue; + } + + /* Switch on type of interrupt we have */ + switch (type) { + + case UART_17158_RXRDY_TIMEOUT: + /* + * RXRDY Time-out is cleared by reading data in the + * RX FIFO until it falls below the trigger level. + */ + + /* Verify the port is in range. */ + if (port > brd->nasync) + continue; + + ch = brd->channels[port]; + neo_copy_data_from_uart_to_queue(ch); + + /* Call our tty layer to enforce queue flow control if needed. */ + DGNC_LOCK(ch->ch_lock, lock_flags2); + dgnc_check_queue_flow_control(ch); + DGNC_UNLOCK(ch->ch_lock, lock_flags2); + + continue; + + case UART_17158_RX_LINE_STATUS: + /* + * RXRDY and RX LINE Status (logic OR of LSR[4:1]) + */ + neo_parse_lsr(brd, port); + continue; + + case UART_17158_TXRDY: + /* + * TXRDY interrupt clears after reading ISR register for the UART channel. + */ + + /* + * Yes, this is odd... + * Why would I check EVERY possibility of type of + * interrupt, when we know its TXRDY??? + * Becuz for some reason, even tho we got triggered for TXRDY, + * it seems to be occassionally wrong. Instead of TX, which + * it should be, I was getting things like RXDY too. Weird. + */ + neo_parse_isr(brd, port); + continue; + + case UART_17158_MSR: + /* + * MSR or flow control was seen. + */ + neo_parse_isr(brd, port); + continue; + + default: + /* + * The UART triggered us with a bogus interrupt type. + * It appears the Exar chip, when REALLY bogged down, will throw + * these once and awhile. + * Its harmless, just ignore it and move on. + */ + DPR_INTR(("%s:%d Unknown Interrupt type: %x\n", __FILE__, __LINE__, type)); + continue; + } + } + + /* + * Schedule tasklet to more in-depth servicing at a better time. + */ + tasklet_schedule(&brd->helper_tasklet); + + DGNC_UNLOCK(brd->bd_intr_lock, lock_flags); + + DPR_INTR(("dgnc_intr finish.\n")); + return IRQ_HANDLED; +} + + +/* + * Neo specific way of turning off the receiver. + * Used as a way to enforce queue flow control when in + * hardware flow control mode. + */ +static void neo_disable_receiver(struct channel_t *ch) +{ + uchar tmp = readb(&ch->ch_neo_uart->ier); + tmp &= ~(UART_IER_RDI); + writeb(tmp, &ch->ch_neo_uart->ier); + neo_pci_posting_flush(ch->ch_bd); +} + + +/* + * Neo specific way of turning on the receiver. + * Used as a way to un-enforce queue flow control when in + * hardware flow control mode. + */ +static void neo_enable_receiver(struct channel_t *ch) +{ + uchar tmp = readb(&ch->ch_neo_uart->ier); + tmp |= (UART_IER_RDI); + writeb(tmp, &ch->ch_neo_uart->ier); + neo_pci_posting_flush(ch->ch_bd); +} + + +static void neo_copy_data_from_uart_to_queue(struct channel_t *ch) +{ + int qleft = 0; + uchar linestatus = 0; + uchar error_mask = 0; + int n = 0; + int total = 0; + ushort head; + ushort tail; + ulong lock_flags; + + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + DGNC_LOCK(ch->ch_lock, lock_flags); + + /* cache head and tail of queue */ + head = ch->ch_r_head & RQUEUEMASK; + tail = ch->ch_r_tail & RQUEUEMASK; + + /* Get our cached LSR */ + linestatus = ch->ch_cached_lsr; + ch->ch_cached_lsr = 0; + + /* Store how much space we have left in the queue */ + if ((qleft = tail - head - 1) < 0) + qleft += RQUEUEMASK + 1; + + /* + * If the UART is not in FIFO mode, force the FIFO copy to + * NOT be run, by setting total to 0. + * + * On the other hand, if the UART IS in FIFO mode, then ask + * the UART to give us an approximation of data it has RX'ed. + */ + if (!(ch->ch_flags & CH_FIFO_ENABLED)) + total = 0; + else { + total = readb(&ch->ch_neo_uart->rfifo); + + /* + * EXAR chip bug - RX FIFO COUNT - Fudge factor. + * + * This resolves a problem/bug with the Exar chip that sometimes + * returns a bogus value in the rfifo register. + * The count can be any where from 0-3 bytes "off". + * Bizarre, but true. + */ + if ((ch->ch_bd->dvid & 0xf0) >= UART_XR17E158_DVID) { + total -= 1; + } + else { + total -= 3; + } + } + + + /* + * Finally, bound the copy to make sure we don't overflow + * our own queue... + * The byte by byte copy loop below this loop this will + * deal with the queue overflow possibility. + */ + total = min(total, qleft); + + while (total > 0) { + + /* + * Grab the linestatus register, we need to check + * to see if there are any errors in the FIFO. + */ + linestatus = readb(&ch->ch_neo_uart->lsr); + + /* + * Break out if there is a FIFO error somewhere. + * This will allow us to go byte by byte down below, + * finding the exact location of the error. + */ + if (linestatus & UART_17158_RX_FIFO_DATA_ERROR) + break; + + /* Make sure we don't go over the end of our queue */ + n = min(((uint) total), (RQUEUESIZE - (uint) head)); + + /* + * Cut down n even further if needed, this is to fix + * a problem with memcpy_fromio() with the Neo on the + * IBM pSeries platform. + * 15 bytes max appears to be the magic number. + */ + n = min((uint) n, (uint) 12); + + /* + * Since we are grabbing the linestatus register, which + * will reset some bits after our read, we need to ensure + * we don't miss our TX FIFO emptys. + */ + if (linestatus & (UART_LSR_THRE | UART_17158_TX_AND_FIFO_CLR)) { + ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); + } + + linestatus = 0; + + /* Copy data from uart to the queue */ + memcpy_fromio(ch->ch_rqueue + head, &ch->ch_neo_uart->txrxburst, n); + dgnc_sniff_nowait_nolock(ch, "UART READ", ch->ch_rqueue + head, n); + + /* + * Since RX_FIFO_DATA_ERROR was 0, we are guarenteed + * that all the data currently in the FIFO is free of + * breaks and parity/frame/orun errors. + */ + memset(ch->ch_equeue + head, 0, n); + + /* Add to and flip head if needed */ + head = (head + n) & RQUEUEMASK; + total -= n; + qleft -= n; + ch->ch_rxcount += n; + } + + /* + * Create a mask to determine whether we should + * insert the character (if any) into our queue. + */ + if (ch->ch_c_iflag & IGNBRK) + error_mask |= UART_LSR_BI; + + /* + * Now cleanup any leftover bytes still in the UART. + * Also deal with any possible queue overflow here as well. + */ + while (1) { + + /* + * Its possible we have a linestatus from the loop above + * this, so we "OR" on any extra bits. + */ + linestatus |= readb(&ch->ch_neo_uart->lsr); + + /* + * If the chip tells us there is no more data pending to + * be read, we can then leave. + * But before we do, cache the linestatus, just in case. + */ + if (!(linestatus & UART_LSR_DR)) { + ch->ch_cached_lsr = linestatus; + break; + } + + /* No need to store this bit */ + linestatus &= ~UART_LSR_DR; + + /* + * Since we are grabbing the linestatus register, which + * will reset some bits after our read, we need to ensure + * we don't miss our TX FIFO emptys. + */ + if (linestatus & (UART_LSR_THRE | UART_17158_TX_AND_FIFO_CLR)) { + linestatus &= ~(UART_LSR_THRE | UART_17158_TX_AND_FIFO_CLR); + ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); + } + + /* + * Discard character if we are ignoring the error mask. + */ + if (linestatus & error_mask) { + uchar discard; + linestatus = 0; + memcpy_fromio(&discard, &ch->ch_neo_uart->txrxburst, 1); + continue; + } + + /* + * If our queue is full, we have no choice but to drop some data. + * The assumption is that HWFLOW or SWFLOW should have stopped + * things way way before we got to this point. + * + * I decided that I wanted to ditch the oldest data first, + * I hope thats okay with everyone? Yes? Good. + */ + while (qleft < 1) { + DPR_READ(("Queue full, dropping DATA:%x LSR:%x\n", + ch->ch_rqueue[tail], ch->ch_equeue[tail])); + + ch->ch_r_tail = tail = (tail + 1) & RQUEUEMASK; + ch->ch_err_overrun++; + qleft++; + } + + memcpy_fromio(ch->ch_rqueue + head, &ch->ch_neo_uart->txrxburst, 1); + ch->ch_equeue[head] = (uchar) linestatus; + dgnc_sniff_nowait_nolock(ch, "UART READ", ch->ch_rqueue + head, 1); + + DPR_READ(("DATA/LSR pair: %x %x\n", ch->ch_rqueue[head], ch->ch_equeue[head])); + + /* Ditch any remaining linestatus value. */ + linestatus = 0; + + /* Add to and flip head if needed */ + head = (head + 1) & RQUEUEMASK; + + qleft--; + ch->ch_rxcount++; + } + + /* + * Write new final heads to channel structure. + */ + ch->ch_r_head = head & RQUEUEMASK; + ch->ch_e_head = head & EQUEUEMASK; + + DGNC_UNLOCK(ch->ch_lock, lock_flags); +} + + +/* + * This function basically goes to sleep for secs, or until + * it gets signalled that the port has fully drained. + */ +static int neo_drain(struct tty_struct *tty, uint seconds) +{ + ulong lock_flags; + struct channel_t *ch; + struct un_t *un; + int rc = 0; + + if (!tty || tty->magic != TTY_MAGIC) { + return (-ENXIO); + } + + un = (struct un_t *) tty->driver_data; + if (!un || un->magic != DGNC_UNIT_MAGIC) { + return (-ENXIO); + } + + ch = un->un_ch; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) { + return (-ENXIO); + } + + DPR_IOCTL(("%d Drain wait started.\n", __LINE__)); + + DGNC_LOCK(ch->ch_lock, lock_flags); + un->un_flags |= UN_EMPTY; + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + /* + * Go to sleep waiting for the tty layer to wake me back up when + * the empty flag goes away. + * + * NOTE: TODO: Do something with time passed in. + */ + rc = wait_event_interruptible(un->un_flags_wait, ((un->un_flags & UN_EMPTY) == 0)); + + /* If ret is non-zero, user ctrl-c'ed us */ + if (rc) { + DPR_IOCTL(("%d Drain - User ctrl c'ed\n", __LINE__)); + } + else { + DPR_IOCTL(("%d Drain wait finished.\n", __LINE__)); + } + + return (rc); +} + + +/* + * Flush the WRITE FIFO on the Neo. + * + * NOTE: Channel lock MUST be held before calling this function! + */ +static void neo_flush_uart_write(struct channel_t *ch) +{ + uchar tmp = 0; + int i = 0; + + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) { + return; + } + + writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_XMIT), &ch->ch_neo_uart->isr_fcr); + neo_pci_posting_flush(ch->ch_bd); + + for (i = 0; i < 10; i++) { + + /* Check to see if the UART feels it completely flushed the FIFO. */ + tmp = readb(&ch->ch_neo_uart->isr_fcr); + if (tmp & 4) { + DPR_IOCTL(("Still flushing TX UART... i: %d\n", i)); + udelay(10); + } + else + break; + } + + ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); +} + + +/* + * Flush the READ FIFO on the Neo. + * + * NOTE: Channel lock MUST be held before calling this function! + */ +static void neo_flush_uart_read(struct channel_t *ch) +{ + uchar tmp = 0; + int i = 0; + + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) { + return; + } + + writeb((UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR), &ch->ch_neo_uart->isr_fcr); + neo_pci_posting_flush(ch->ch_bd); + + for (i = 0; i < 10; i++) { + + /* Check to see if the UART feels it completely flushed the FIFO. */ + tmp = readb(&ch->ch_neo_uart->isr_fcr); + if (tmp & 2) { + DPR_IOCTL(("Still flushing RX UART... i: %d\n", i)); + udelay(10); + } + else + break; + } +} + + +static void neo_copy_data_from_queue_to_uart(struct channel_t *ch) +{ + ushort head; + ushort tail; + int n; + int s; + int qlen; + uint len_written = 0; + ulong lock_flags; + + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + DGNC_LOCK(ch->ch_lock, lock_flags); + + /* No data to write to the UART */ + if (ch->ch_w_tail == ch->ch_w_head) { + DGNC_UNLOCK(ch->ch_lock, lock_flags); + return; + } + + /* If port is "stopped", don't send any data to the UART */ + if ((ch->ch_flags & CH_FORCED_STOP) || (ch->ch_flags & CH_BREAK_SENDING)) { + DGNC_UNLOCK(ch->ch_lock, lock_flags); + return; + } + + /* + * If FIFOs are disabled. Send data directly to txrx register + */ + if (!(ch->ch_flags & CH_FIFO_ENABLED)) { + uchar lsrbits = readb(&ch->ch_neo_uart->lsr); + + /* Cache the LSR bits for later parsing */ + ch->ch_cached_lsr |= lsrbits; + if (ch->ch_cached_lsr & UART_LSR_THRE) { + ch->ch_cached_lsr &= ~(UART_LSR_THRE); + + /* + * If RTS Toggle mode is on, turn on RTS now if not already set, + * and make sure we get an event when the data transfer has completed. + */ + if (ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE) { + if (!(ch->ch_mostat & UART_MCR_RTS)) { + ch->ch_mostat |= (UART_MCR_RTS); + neo_assert_modem_signals(ch); + } + ch->ch_tun.un_flags |= (UN_EMPTY); + } + /* + * If DTR Toggle mode is on, turn on DTR now if not already set, + * and make sure we get an event when the data transfer has completed. + */ + if (ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE) { + if (!(ch->ch_mostat & UART_MCR_DTR)) { + ch->ch_mostat |= (UART_MCR_DTR); + neo_assert_modem_signals(ch); + } + ch->ch_tun.un_flags |= (UN_EMPTY); + } + + writeb(ch->ch_wqueue[ch->ch_w_tail], &ch->ch_neo_uart->txrx); + DPR_WRITE(("Tx data: %x\n", ch->ch_wqueue[ch->ch_w_head])); + ch->ch_w_tail++; + ch->ch_w_tail &= WQUEUEMASK; + ch->ch_txcount++; + } + DGNC_UNLOCK(ch->ch_lock, lock_flags); + return; + } + + /* + * We have to do it this way, because of the EXAR TXFIFO count bug. + */ + if ((ch->ch_bd->dvid & 0xf0) < UART_XR17E158_DVID) { + if (!(ch->ch_flags & (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM))) { + DGNC_UNLOCK(ch->ch_lock, lock_flags); + return; + } + + len_written = 0; + + n = readb(&ch->ch_neo_uart->tfifo); + + if ((unsigned int) n > ch->ch_t_tlevel) { + DGNC_UNLOCK(ch->ch_lock, lock_flags); + return; + } + + n = UART_17158_TX_FIFOSIZE - ch->ch_t_tlevel; + } + else { + n = UART_17158_TX_FIFOSIZE - readb(&ch->ch_neo_uart->tfifo); + } + + /* cache head and tail of queue */ + head = ch->ch_w_head & WQUEUEMASK; + tail = ch->ch_w_tail & WQUEUEMASK; + qlen = (head - tail) & WQUEUEMASK; + + /* Find minimum of the FIFO space, versus queue length */ + n = min(n, qlen); + + while (n > 0) { + + s = ((head >= tail) ? head : WQUEUESIZE) - tail; + s = min(s, n); + + if (s <= 0) + break; + + /* + * If RTS Toggle mode is on, turn on RTS now if not already set, + * and make sure we get an event when the data transfer has completed. + */ + if (ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE) { + if (!(ch->ch_mostat & UART_MCR_RTS)) { + ch->ch_mostat |= (UART_MCR_RTS); + neo_assert_modem_signals(ch); + } + ch->ch_tun.un_flags |= (UN_EMPTY); + } + + /* + * If DTR Toggle mode is on, turn on DTR now if not already set, + * and make sure we get an event when the data transfer has completed. + */ + if (ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE) { + if (!(ch->ch_mostat & UART_MCR_DTR)) { + ch->ch_mostat |= (UART_MCR_DTR); + neo_assert_modem_signals(ch); + } + ch->ch_tun.un_flags |= (UN_EMPTY); + } + + memcpy_toio(&ch->ch_neo_uart->txrxburst, ch->ch_wqueue + tail, s); + dgnc_sniff_nowait_nolock(ch, "UART WRITE", ch->ch_wqueue + tail, s); + + /* Add and flip queue if needed */ + tail = (tail + s) & WQUEUEMASK; + n -= s; + ch->ch_txcount += s; + len_written += s; + } + + /* Update the final tail */ + ch->ch_w_tail = tail & WQUEUEMASK; + + if (len_written > 0) { + neo_pci_posting_flush(ch->ch_bd); + ch->ch_flags &= ~(CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); + } + + DGNC_UNLOCK(ch->ch_lock, lock_flags); +} + + +static void neo_parse_modem(struct channel_t *ch, uchar signals) +{ + volatile uchar msignals = signals; + + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + DPR_MSIGS(("neo_parse_modem: port: %d msignals: %x\n", ch->ch_portnum, msignals)); + + /* + * Do altpin switching. Altpin switches DCD and DSR. + * This prolly breaks DSRPACE, so we should be more clever here. + */ + if (ch->ch_digi.digi_flags & DIGI_ALTPIN) { + uchar mswap = msignals; + + if (mswap & UART_MSR_DDCD) { + msignals &= ~UART_MSR_DDCD; + msignals |= UART_MSR_DDSR; + } + if (mswap & UART_MSR_DDSR) { + msignals &= ~UART_MSR_DDSR; + msignals |= UART_MSR_DDCD; + } + if (mswap & UART_MSR_DCD) { + msignals &= ~UART_MSR_DCD; + msignals |= UART_MSR_DSR; + } + if (mswap & UART_MSR_DSR) { + msignals &= ~UART_MSR_DSR; + msignals |= UART_MSR_DCD; + } + } + + /* Scrub off lower bits. They signify delta's, which I don't care about */ + msignals &= 0xf0; + + if (msignals & UART_MSR_DCD) + ch->ch_mistat |= UART_MSR_DCD; + else + ch->ch_mistat &= ~UART_MSR_DCD; + + if (msignals & UART_MSR_DSR) + ch->ch_mistat |= UART_MSR_DSR; + else + ch->ch_mistat &= ~UART_MSR_DSR; + + if (msignals & UART_MSR_RI) + ch->ch_mistat |= UART_MSR_RI; + else + ch->ch_mistat &= ~UART_MSR_RI; + + if (msignals & UART_MSR_CTS) + ch->ch_mistat |= UART_MSR_CTS; + else + ch->ch_mistat &= ~UART_MSR_CTS; + + DPR_MSIGS(("Port: %d DTR: %d RTS: %d CTS: %d DSR: %d " "RI: %d CD: %d\n", + ch->ch_portnum, + !!((ch->ch_mistat | ch->ch_mostat) & UART_MCR_DTR), + !!((ch->ch_mistat | ch->ch_mostat) & UART_MCR_RTS), + !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_CTS), + !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_DSR), + !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_RI), + !!((ch->ch_mistat | ch->ch_mostat) & UART_MSR_DCD))); +} + + +/* Make the UART raise any of the output signals we want up */ +static void neo_assert_modem_signals(struct channel_t *ch) +{ + uchar out; + + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + out = ch->ch_mostat; + + if (ch->ch_flags & CH_LOOPBACK) + out |= UART_MCR_LOOP; + + writeb(out, &ch->ch_neo_uart->mcr); + neo_pci_posting_flush(ch->ch_bd); + + /* Give time for the UART to actually raise/drop the signals */ + udelay(10); +} + + +static void neo_send_start_character(struct channel_t *ch) +{ + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + if (ch->ch_startc != _POSIX_VDISABLE) { + ch->ch_xon_sends++; + writeb(ch->ch_startc, &ch->ch_neo_uart->txrx); + neo_pci_posting_flush(ch->ch_bd); + udelay(10); + } +} + + +static void neo_send_stop_character(struct channel_t *ch) +{ + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + if (ch->ch_stopc != _POSIX_VDISABLE) { + ch->ch_xoff_sends++; + writeb(ch->ch_stopc, &ch->ch_neo_uart->txrx); + neo_pci_posting_flush(ch->ch_bd); + udelay(10); + } +} + + +/* + * neo_uart_init + */ +static void neo_uart_init(struct channel_t *ch) +{ + + writeb(0, &ch->ch_neo_uart->ier); + writeb(0, &ch->ch_neo_uart->efr); + writeb(UART_EFR_ECB, &ch->ch_neo_uart->efr); + + + /* Clear out UART and FIFO */ + readb(&ch->ch_neo_uart->txrx); + writeb((UART_FCR_ENABLE_FIFO|UART_FCR_CLEAR_RCVR|UART_FCR_CLEAR_XMIT), &ch->ch_neo_uart->isr_fcr); + readb(&ch->ch_neo_uart->lsr); + readb(&ch->ch_neo_uart->msr); + + ch->ch_flags |= CH_FIFO_ENABLED; + + /* Assert any signals we want up */ + writeb(ch->ch_mostat, &ch->ch_neo_uart->mcr); + neo_pci_posting_flush(ch->ch_bd); +} + + +/* + * Make the UART completely turn off. + */ +static void neo_uart_off(struct channel_t *ch) +{ + /* Turn off UART enhanced bits */ + writeb(0, &ch->ch_neo_uart->efr); + + /* Stop all interrupts from occurring. */ + writeb(0, &ch->ch_neo_uart->ier); + neo_pci_posting_flush(ch->ch_bd); +} + + +static uint neo_get_uart_bytes_left(struct channel_t *ch) +{ + uchar left = 0; + uchar lsr = readb(&ch->ch_neo_uart->lsr); + + /* We must cache the LSR as some of the bits get reset once read... */ + ch->ch_cached_lsr |= lsr; + + /* Determine whether the Transmitter is empty or not */ + if (!(lsr & UART_LSR_TEMT)) { + if (ch->ch_flags & CH_TX_FIFO_EMPTY) { + tasklet_schedule(&ch->ch_bd->helper_tasklet); + } + left = 1; + } else { + ch->ch_flags |= (CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); + left = 0; + } + + return left; +} + + +/* Channel lock MUST be held by the calling function! */ +static void neo_send_break(struct channel_t *ch, int msecs) +{ + /* + * If we receive a time of 0, this means turn off the break. + */ + if (msecs == 0) { + if (ch->ch_flags & CH_BREAK_SENDING) { + uchar temp = readb(&ch->ch_neo_uart->lcr); + writeb((temp & ~UART_LCR_SBC), &ch->ch_neo_uart->lcr); + neo_pci_posting_flush(ch->ch_bd); + ch->ch_flags &= ~(CH_BREAK_SENDING); + ch->ch_stop_sending_break = 0; + DPR_IOCTL(("Finishing UART_LCR_SBC! finished: %lx\n", jiffies)); + } + return; + } + + /* + * Set the time we should stop sending the break. + * If we are already sending a break, toss away the existing + * time to stop, and use this new value instead. + */ + ch->ch_stop_sending_break = jiffies + dgnc_jiffies_from_ms(msecs); + + /* Tell the UART to start sending the break */ + if (!(ch->ch_flags & CH_BREAK_SENDING)) { + uchar temp = readb(&ch->ch_neo_uart->lcr); + writeb((temp | UART_LCR_SBC), &ch->ch_neo_uart->lcr); + neo_pci_posting_flush(ch->ch_bd); + ch->ch_flags |= (CH_BREAK_SENDING); + DPR_IOCTL(("Port %d. Starting UART_LCR_SBC! start: %lx should end: %lx\n", + ch->ch_portnum, jiffies, ch->ch_stop_sending_break)); + } +} + + +/* + * neo_send_immediate_char. + * + * Sends a specific character as soon as possible to the UART, + * jumping over any bytes that might be in the write queue. + * + * The channel lock MUST be held by the calling function. + */ +static void neo_send_immediate_char(struct channel_t *ch, unsigned char c) +{ + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + writeb(c, &ch->ch_neo_uart->txrx); + neo_pci_posting_flush(ch->ch_bd); +} + + +static unsigned int neo_read_eeprom(unsigned char *base, unsigned int address) +{ + unsigned int enable; + unsigned int bits; + unsigned int databit; + unsigned int val; + + /* enable chip select */ + writeb(NEO_EECS, base + NEO_EEREG); + /* READ */ + enable = (address | 0x180); + + for (bits = 9; bits--; ) { + databit = (enable & (1 << bits)) ? NEO_EEDI : 0; + /* Set read address */ + writeb(databit | NEO_EECS, base + NEO_EEREG); + writeb(databit | NEO_EECS | NEO_EECK, base + NEO_EEREG); + } + + val = 0; + + for (bits = 17; bits--; ) { + /* clock to EEPROM */ + writeb(NEO_EECS, base + NEO_EEREG); + writeb(NEO_EECS | NEO_EECK, base + NEO_EEREG); + val <<= 1; + /* read EEPROM */ + if (readb(base + NEO_EEREG) & NEO_EEDO) + val |= 1; + } + + /* clock falling edge */ + writeb(NEO_EECS, base + NEO_EEREG); + + /* drop chip select */ + writeb(0x00, base + NEO_EEREG); + + return val; +} + + +static void neo_vpd(struct board_t *brd) +{ + unsigned int i = 0; + unsigned int a; + + if (!brd || brd->magic != DGNC_BOARD_MAGIC) + return; + + if (!brd->re_map_membase) + return; + + /* Store the VPD into our buffer */ + for (i = 0; i < NEO_VPD_IMAGESIZE; i++) { + a = neo_read_eeprom(brd->re_map_membase, i); + brd->vpd[i*2] = a & 0xff; + brd->vpd[(i*2)+1] = (a >> 8) & 0xff; + } + + if (((brd->vpd[0x08] != 0x82) /* long resource name tag */ + && (brd->vpd[0x10] != 0x82)) /* long resource name tag (PCI-66 files)*/ + || (brd->vpd[0x7F] != 0x78)) /* small resource end tag */ + { + memset(brd->vpd, '\0', NEO_VPD_IMAGESIZE); + } + else { + /* Search for the serial number */ + for (i = 0; i < NEO_VPD_IMAGESIZE * 2; i++) { + if (brd->vpd[i] == 'S' && brd->vpd[i + 1] == 'N') { + strncpy(brd->serial_num, &(brd->vpd[i + 3]), 9); + } + } + } +} diff --git a/drivers/staging/dgnc/dgnc_neo.h b/drivers/staging/dgnc/dgnc_neo.h new file mode 100644 index 000000000000..ffb42099b9fd --- /dev/null +++ b/drivers/staging/dgnc/dgnc_neo.h @@ -0,0 +1,157 @@ +/* + * Copyright 2003 Digi International (www.digi.com) + * Scott H Kilau + * + * 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, EXPRESS OR IMPLIED; 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. + * + * NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!! + * + */ + +#ifndef __DGNC_NEO_H +#define __DGNC_NEO_H + +#include "dgnc_types.h" +#include "dgnc_driver.h" + +/************************************************************************ + * Per channel/port NEO UART structure * + ************************************************************************ + * Base Structure Entries Usage Meanings to Host * + * * + * W = read write R = read only * + * U = Unused. * + ************************************************************************/ + +struct neo_uart_struct { + volatile uchar txrx; /* WR RHR/THR - Holding Reg */ + volatile uchar ier; /* WR IER - Interrupt Enable Reg */ + volatile uchar isr_fcr; /* WR ISR/FCR - Interrupt Status Reg/Fifo Control Reg */ + volatile uchar lcr; /* WR LCR - Line Control Reg */ + volatile uchar mcr; /* WR MCR - Modem Control Reg */ + volatile uchar lsr; /* WR LSR - Line Status Reg */ + volatile uchar msr; /* WR MSR - Modem Status Reg */ + volatile uchar spr; /* WR SPR - Scratch Pad Reg */ + volatile uchar fctr; /* WR FCTR - Feature Control Reg */ + volatile uchar efr; /* WR EFR - Enhanced Function Reg */ + volatile uchar tfifo; /* WR TXCNT/TXTRG - Transmit FIFO Reg */ + volatile uchar rfifo; /* WR RXCNT/RXTRG - Recieve FIFO Reg */ + volatile uchar xoffchar1; /* WR XOFF 1 - XOff Character 1 Reg */ + volatile uchar xoffchar2; /* WR XOFF 2 - XOff Character 2 Reg */ + volatile uchar xonchar1; /* WR XON 1 - Xon Character 1 Reg */ + volatile uchar xonchar2; /* WR XON 2 - XOn Character 2 Reg */ + + volatile uchar reserved1[0x2ff - 0x200]; /* U Reserved by Exar */ + volatile uchar txrxburst[64]; /* RW 64 bytes of RX/TX FIFO Data */ + volatile uchar reserved2[0x37f - 0x340]; /* U Reserved by Exar */ + volatile uchar rxburst_with_errors[64]; /* R 64 bytes of RX FIFO Data + LSR */ +}; + +/* Where to read the extended interrupt register (32bits instead of 8bits) */ +#define UART_17158_POLL_ADDR_OFFSET 0x80 + +/* These are the current dvid's of the Neo boards */ +#define UART_XR17C158_DVID 0x20 +#define UART_XR17D158_DVID 0x20 +#define UART_XR17E158_DVID 0x40 + +#define NEO_EECK 0x10 /* Clock */ +#define NEO_EECS 0x20 /* Chip Select */ +#define NEO_EEDI 0x40 /* Data In is an Output Pin */ +#define NEO_EEDO 0x80 /* Data Out is an Input Pin */ +#define NEO_EEREG 0x8E /* offset to EEPROM control reg */ + + +#define NEO_VPD_IMAGESIZE 0x40 /* size of image to read from EEPROM in words */ +#define NEO_VPD_IMAGEBYTES (NEO_VPD_IMAGESIZE * 2) + +/* + * These are the redefinitions for the FCTR on the XR17C158, since + * Exar made them different than their earlier design. (XR16C854) + */ + +/* These are only applicable when table D is selected */ +#define UART_17158_FCTR_RTS_NODELAY 0x00 +#define UART_17158_FCTR_RTS_4DELAY 0x01 +#define UART_17158_FCTR_RTS_6DELAY 0x02 +#define UART_17158_FCTR_RTS_8DELAY 0x03 +#define UART_17158_FCTR_RTS_12DELAY 0x12 +#define UART_17158_FCTR_RTS_16DELAY 0x05 +#define UART_17158_FCTR_RTS_20DELAY 0x13 +#define UART_17158_FCTR_RTS_24DELAY 0x06 +#define UART_17158_FCTR_RTS_28DELAY 0x14 +#define UART_17158_FCTR_RTS_32DELAY 0x07 +#define UART_17158_FCTR_RTS_36DELAY 0x16 +#define UART_17158_FCTR_RTS_40DELAY 0x08 +#define UART_17158_FCTR_RTS_44DELAY 0x09 +#define UART_17158_FCTR_RTS_48DELAY 0x10 +#define UART_17158_FCTR_RTS_52DELAY 0x11 + +#define UART_17158_FCTR_RTS_IRDA 0x10 +#define UART_17158_FCTR_RS485 0x20 +#define UART_17158_FCTR_TRGA 0x00 +#define UART_17158_FCTR_TRGB 0x40 +#define UART_17158_FCTR_TRGC 0x80 +#define UART_17158_FCTR_TRGD 0xC0 + +/* 17158 trigger table selects.. */ +#define UART_17158_FCTR_BIT6 0x40 +#define UART_17158_FCTR_BIT7 0x80 + +/* 17158 TX/RX memmapped buffer offsets */ +#define UART_17158_RX_FIFOSIZE 64 +#define UART_17158_TX_FIFOSIZE 64 + +/* 17158 Extended IIR's */ +#define UART_17158_IIR_RDI_TIMEOUT 0x0C /* Receiver data TIMEOUT */ +#define UART_17158_IIR_XONXOFF 0x10 /* Received an XON/XOFF char */ +#define UART_17158_IIR_HWFLOW_STATE_CHANGE 0x20 /* CTS/DSR or RTS/DTR state change */ +#define UART_17158_IIR_FIFO_ENABLED 0xC0 /* 16550 FIFOs are Enabled */ + +/* + * These are the extended interrupts that get sent + * back to us from the UART's 32bit interrupt register + */ +#define UART_17158_RX_LINE_STATUS 0x1 /* RX Ready */ +#define UART_17158_RXRDY_TIMEOUT 0x2 /* RX Ready Timeout */ +#define UART_17158_TXRDY 0x3 /* TX Ready */ +#define UART_17158_MSR 0x4 /* Modem State Change */ +#define UART_17158_TX_AND_FIFO_CLR 0x40 /* Transmitter Holding Reg Empty */ +#define UART_17158_RX_FIFO_DATA_ERROR 0x80 /* UART detected an RX FIFO Data error */ + +/* + * These are the EXTENDED definitions for the 17C158's Interrupt + * Enable Register. + */ +#define UART_17158_EFR_ECB 0x10 /* Enhanced control bit */ +#define UART_17158_EFR_IXON 0x2 /* Receiver compares Xon1/Xoff1 */ +#define UART_17158_EFR_IXOFF 0x8 /* Transmit Xon1/Xoff1 */ +#define UART_17158_EFR_RTSDTR 0x40 /* Auto RTS/DTR Flow Control Enable */ +#define UART_17158_EFR_CTSDSR 0x80 /* Auto CTS/DSR Flow COntrol Enable */ + +#define UART_17158_XOFF_DETECT 0x1 /* Indicates whether chip saw an incoming XOFF char */ +#define UART_17158_XON_DETECT 0x2 /* Indicates whether chip saw an incoming XON char */ + +#define UART_17158_IER_RSVD1 0x10 /* Reserved by Exar */ +#define UART_17158_IER_XOFF 0x20 /* Xoff Interrupt Enable */ +#define UART_17158_IER_RTSDTR 0x40 /* Output Interrupt Enable */ +#define UART_17158_IER_CTSDSR 0x80 /* Input Interrupt Enable */ + +/* + * Our Global Variables + */ +extern struct board_ops dgnc_neo_ops; + +#endif diff --git a/drivers/staging/dgnc/dgnc_pci.h b/drivers/staging/dgnc/dgnc_pci.h new file mode 100644 index 000000000000..5550707ba1fb --- /dev/null +++ b/drivers/staging/dgnc/dgnc_pci.h @@ -0,0 +1,77 @@ +/* + * Copyright 2003 Digi International (www.digi.com) + * Scott H Kilau + * + * 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, EXPRESS OR IMPLIED; 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. + * + * NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!! + */ + +/* $Id: dgnc_pci.h,v 1.1.1.1 2009/05/20 12:19:19 markh Exp $ */ + +#ifndef __DGNC_PCI_H +#define __DGNC_PCI_H + +#define PCIMAX 32 /* maximum number of PCI boards */ + +#define DIGI_VID 0x114F + +#define PCI_DEVICE_CLASSIC_4_DID 0x0028 +#define PCI_DEVICE_CLASSIC_8_DID 0x0029 +#define PCI_DEVICE_CLASSIC_4_422_DID 0x00D0 +#define PCI_DEVICE_CLASSIC_8_422_DID 0x00D1 +#define PCI_DEVICE_NEO_4_DID 0x00B0 +#define PCI_DEVICE_NEO_8_DID 0x00B1 +#define PCI_DEVICE_NEO_2DB9_DID 0x00C8 +#define PCI_DEVICE_NEO_2DB9PRI_DID 0x00C9 +#define PCI_DEVICE_NEO_2RJ45_DID 0x00CA +#define PCI_DEVICE_NEO_2RJ45PRI_DID 0x00CB +#define PCI_DEVICE_NEO_1_422_DID 0x00CC +#define PCI_DEVICE_NEO_1_422_485_DID 0x00CD +#define PCI_DEVICE_NEO_2_422_485_DID 0x00CE +#define PCI_DEVICE_NEO_EXPRESS_8_DID 0x00F0 +#define PCI_DEVICE_NEO_EXPRESS_4_DID 0x00F1 +#define PCI_DEVICE_NEO_EXPRESS_4RJ45_DID 0x00F2 +#define PCI_DEVICE_NEO_EXPRESS_8RJ45_DID 0x00F3 +#define PCI_DEVICE_NEO_EXPRESS_4_IBM_DID 0x00F4 + +#define PCI_DEVICE_CLASSIC_4_PCI_NAME "ClassicBoard 4 PCI" +#define PCI_DEVICE_CLASSIC_8_PCI_NAME "ClassicBoard 8 PCI" +#define PCI_DEVICE_CLASSIC_4_422_PCI_NAME "ClassicBoard 4 422 PCI" +#define PCI_DEVICE_CLASSIC_8_422_PCI_NAME "ClassicBoard 8 422 PCI" +#define PCI_DEVICE_NEO_4_PCI_NAME "Neo 4 PCI" +#define PCI_DEVICE_NEO_8_PCI_NAME "Neo 8 PCI" +#define PCI_DEVICE_NEO_2DB9_PCI_NAME "Neo 2 - DB9 Universal PCI" +#define PCI_DEVICE_NEO_2DB9PRI_PCI_NAME "Neo 2 - DB9 Universal PCI - Powered Ring Indicator" +#define PCI_DEVICE_NEO_2RJ45_PCI_NAME "Neo 2 - RJ45 Universal PCI" +#define PCI_DEVICE_NEO_2RJ45PRI_PCI_NAME "Neo 2 - RJ45 Universal PCI - Powered Ring Indicator" +#define PCI_DEVICE_NEO_1_422_PCI_NAME "Neo 1 422 PCI" +#define PCI_DEVICE_NEO_1_422_485_PCI_NAME "Neo 1 422/485 PCI" +#define PCI_DEVICE_NEO_2_422_485_PCI_NAME "Neo 2 422/485 PCI" + +#define PCI_DEVICE_NEO_EXPRESS_8_PCI_NAME "Neo 8 PCI Express" +#define PCI_DEVICE_NEO_EXPRESS_4_PCI_NAME "Neo 4 PCI Express" +#define PCI_DEVICE_NEO_EXPRESS_4RJ45_PCI_NAME "Neo 4 PCI Express RJ45" +#define PCI_DEVICE_NEO_EXPRESS_8RJ45_PCI_NAME "Neo 8 PCI Express RJ45" +#define PCI_DEVICE_NEO_EXPRESS_4_IBM_PCI_NAME "Neo 4 PCI Express IBM" + + +/* Size of Memory and I/O for PCI (4 K) */ +#define PCI_RAM_SIZE 0x1000 + +/* Size of Memory (2MB) */ +#define PCI_MEM_SIZE 0x1000 + +#endif diff --git a/drivers/staging/dgnc/dgnc_proc.c b/drivers/staging/dgnc/dgnc_proc.c new file mode 100644 index 000000000000..8fbaf3b38e60 --- /dev/null +++ b/drivers/staging/dgnc/dgnc_proc.c @@ -0,0 +1,1551 @@ +/* + * Copyright 2003 Digi International (www.digi.com) + * Scott H Kilau + * + * 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, EXPRESS OR IMPLIED; 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. + * + * + * NOTE TO LINUX KERNEL HACKERS: DO NOT REFORMAT THIS CODE! + * + * This is shared code between Digi's CVS archive and the + * Linux Kernel sources. + * Changing the source just for reformatting needlessly breaks + * our CVS diff history. + * + * Send any bug fixes/changes to: Eng.Linux at digi dot com. + * Thank you. + * + * + * $Id: dgnc_proc.c,v 1.3 2011/06/22 12:16:35 markh Exp $ + */ + +#include +#include +#include /* For jiffies, task states */ +#include /* For tasklet and interrupt structs/defines */ +#include +#include +#include +#include +#include /* For in_egroup_p() */ +#include +#include /* For copy_from_user/copy_to_user */ + +#include "dgnc_driver.h" +#include "dgnc_proc.h" +#include "dgnc_mgmt.h" + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) +#define init_MUTEX(sem) sema_init(sem, 1) +#define DECLARE_MUTEX(name) \ + struct semaphore name = __SEMAPHORE_INITIALIZER(name, 1) +#endif + + +/* The /proc/dgnc directory */ +static struct proc_dir_entry *ProcDGNC; + + +/* File operation declarations */ +static int dgnc_gen_proc_open(struct inode *, struct file *); +static int dgnc_gen_proc_close(struct inode *, struct file *); +static ssize_t dgnc_gen_proc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos); +static ssize_t dgnc_gen_proc_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos); + +static int dgnc_proc_chk_perm(struct inode *, int); + +static const struct file_operations dgnc_proc_file_ops = +{ + .owner = THIS_MODULE, + .read = dgnc_gen_proc_read, /* read */ + .write = dgnc_gen_proc_write, /* write */ + .open = dgnc_gen_proc_open, /* open */ + .release = dgnc_gen_proc_close, /* release */ +}; + + +static struct inode_operations dgnc_proc_inode_ops = +{ + .permission = dgnc_proc_chk_perm +}; + + +static void dgnc_register_proc_table(struct dgnc_proc_entry *, struct proc_dir_entry *); +static void dgnc_unregister_proc_table(struct dgnc_proc_entry *, struct proc_dir_entry *); +static void dgnc_remove_proc_entry(struct proc_dir_entry *pde); + + +/* Stuff in /proc/ */ +static int dgnc_read_info(struct dgnc_proc_entry *table, int dir, struct file *filp, + char __user *buffer, ssize_t *lenp, loff_t *ppos); +static int dgnc_write_info(struct dgnc_proc_entry *table, int dir, struct file *filp, + const char __user *buffer, ssize_t *lenp, loff_t *ppos); + +static int dgnc_read_mknod(struct dgnc_proc_entry *table, int dir, struct file *filp, + char __user *buffer, ssize_t *lenp, loff_t *ppos); + +static struct dgnc_proc_entry dgnc_table[] = { + {DGNC_INFO, "info", 0600, NULL, NULL, NULL, &dgnc_read_info, &dgnc_write_info, + NULL, __SEMAPHORE_INITIALIZER(dgnc_table[0].excl_sem, 1), 0, NULL }, + {DGNC_MKNOD, "mknod", 0600, NULL, NULL, NULL, &dgnc_read_mknod, NULL, + NULL, __SEMAPHORE_INITIALIZER(dgnc_table[1].excl_sem, 1), 0, NULL }, + {0} +}; + + +/* Stuff in /proc// */ +static int dgnc_read_board_info(struct dgnc_proc_entry *table, int dir, struct file *filp, + char __user *buffer, ssize_t *lenp, loff_t *ppos); +static int dgnc_read_board_vpd(struct dgnc_proc_entry *table, int dir, struct file *filp, + char __user *buffer, ssize_t *lenp, loff_t *ppos); +static int dgnc_read_board_mknod(struct dgnc_proc_entry *table, int dir, struct file *filp, + char __user *buffer, ssize_t *lenp, loff_t *ppos); +static int dgnc_read_board_ttystats(struct dgnc_proc_entry *table, int dir, struct file *filp, + char __user *buffer, ssize_t *lenp, loff_t *ppos); +static int dgnc_read_board_ttyintr(struct dgnc_proc_entry *table, int dir, struct file *filp, + char __user *buffer, ssize_t *lenp, loff_t *ppos); +static int dgnc_read_board_ttyflags(struct dgnc_proc_entry *table, int dir, struct file *filp, + char __user *buffer, ssize_t *lenp, loff_t *ppos); + +static struct dgnc_proc_entry dgnc_board_table[] = { + {DGNC_BOARD_INFO, "info", 0600, NULL, NULL, NULL, &dgnc_read_board_info, NULL, + NULL, __SEMAPHORE_INITIALIZER(dgnc_board_table[0].excl_sem, 1), 0, NULL }, + {DGNC_BOARD_VPD, "vpd", 0600, NULL, NULL, NULL, &dgnc_read_board_vpd, NULL, + NULL, __SEMAPHORE_INITIALIZER(dgnc_board_table[1].excl_sem, 1), 0, NULL }, + {DGNC_BOARD_TTYSTATS, "stats", 0600, NULL, NULL, NULL, &dgnc_read_board_ttystats, NULL, + NULL, __SEMAPHORE_INITIALIZER(dgnc_board_table[2].excl_sem, 1), 0, NULL }, + {DGNC_BOARD_TTYINTR, "intr", 0600, NULL, NULL, NULL, &dgnc_read_board_ttyintr, NULL, + NULL, __SEMAPHORE_INITIALIZER(dgnc_board_table[3].excl_sem, 1), 0, NULL }, + {DGNC_BOARD_TTYFLAGS, "flags", 0600, NULL, NULL, NULL, &dgnc_read_board_ttyflags, NULL, + NULL, __SEMAPHORE_INITIALIZER(dgnc_board_table[4].excl_sem, 1), 0, NULL }, + {DGNC_BOARD_MKNOD, "mknod", 0600, NULL, NULL, NULL, &dgnc_read_board_mknod, NULL, + NULL, __SEMAPHORE_INITIALIZER(dgnc_board_table[5].excl_sem, 1), 0, NULL }, + {0} +}; + + +/* Stuff in /proc// */ +static int dgnc_read_channel_info(struct dgnc_proc_entry *table, int dir, struct file *filp, + char __user *buffer, ssize_t *lenp, loff_t *ppos); +static int dgnc_open_channel_sniff(struct dgnc_proc_entry *table, int dir, struct file *filp, + void *buffer, ssize_t *lenp, loff_t *ppos); +static int dgnc_close_channel_sniff(struct dgnc_proc_entry *table, int dir, struct file *filp, + void *buffer, ssize_t *lenp, loff_t *ppos); +static int dgnc_read_channel_sniff(struct dgnc_proc_entry *table, int dir, struct file *filp, + char __user *buffer, ssize_t *lenp, loff_t *ppos); +static int dgnc_read_channel_custom_ttyname(struct dgnc_proc_entry *table, int dir, struct file *filp, + char __user *buffer, ssize_t *lenp, loff_t *ppos); +static int dgnc_read_channel_custom_prname(struct dgnc_proc_entry *table, int dir, struct file *filp, + char __user *buffer, ssize_t *lenp, loff_t *ppos); + +static struct dgnc_proc_entry dgnc_channel_table[] = { + {DGNC_PORT_INFO, "info", 0600, NULL, NULL, NULL, &dgnc_read_channel_info, NULL, + NULL, __SEMAPHORE_INITIALIZER(dgnc_channel_table[0].excl_sem, 1), 0, NULL }, + {DGNC_PORT_SNIFF, "sniff", 0600, NULL, &dgnc_open_channel_sniff, &dgnc_close_channel_sniff, &dgnc_read_channel_sniff, NULL, + NULL, __SEMAPHORE_INITIALIZER(dgnc_channel_table[1].excl_sem, 1), 0, NULL}, + {DGNC_PORT_CUSTOM_TTYNAME, "ttyname", 0600, NULL, NULL, NULL, &dgnc_read_channel_custom_ttyname, NULL, + NULL, __SEMAPHORE_INITIALIZER(dgnc_channel_table[2].excl_sem, 1), 0, NULL }, + {DGNC_PORT_CUSTOM_PRNAME, "prname", 0600, NULL, NULL, NULL, &dgnc_read_channel_custom_prname, NULL, + NULL, __SEMAPHORE_INITIALIZER(dgnc_channel_table[3].excl_sem, 1), 0, NULL }, + {0} +}; + + +/* + * dgnc_test_perm does NOT grant the superuser all rights automatically, because + * some entries are readonly even to root. + */ +static inline int dgnc_test_perm(int mode, int op) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) + if (!current->euid) +#else + if (!current_euid()) +#endif + mode >>= 6; + else if (in_egroup_p(0)) + mode >>= 3; + if ((mode & op & 0007) == op) + return 0; + if (capable(CAP_SYS_ADMIN)) + return 0; + return -EACCES; +} + + +/* + * /proc/sys support + */ +static inline int dgnc_proc_match(int len, const char *name, struct proc_dir_entry *de) +{ + if (!de || !de->low_ino) + return 0; + if (de->namelen != len) + return 0; + return !memcmp(name, de->name, len); +} + + +/* + * Scan the entries in table and add them all to /proc at the position + * referred to by "root" + */ +static void dgnc_register_proc_table(struct dgnc_proc_entry *table, struct proc_dir_entry *root) +{ + struct proc_dir_entry *de; + int len; + mode_t mode; + + for (; table->magic; table++) { + /* Can't do anything without a proc name. */ + if (!table->name) { + DPR_PROC(("dgnc_register_proc_table, no name...\n")); + continue; + } + + /* Maybe we can't do anything with it... */ + if (!table->read_handler && !table->write_handler && !table->child) { + DPR_PROC((KERN_WARNING "DGNC PROC: Can't register %s\n", table->name)); + continue; + } + + len = strlen(table->name); + mode = table->mode; + de = NULL; + + if (!table->child) { + mode |= S_IFREG; + } else { + mode |= S_IFDIR; + for (de = root->subdir; de; de = de->next) { + if (dgnc_proc_match(len, table->name, de)) + break; + } + + /* If the subdir exists already, de is non-NULL */ + } + + if (!de) { + de = create_proc_entry(table->name, mode, root); + if (!de) + continue; + de->data = (void *) table; + if (!table->child) { + de->proc_iops = &dgnc_proc_inode_ops; + de->proc_fops = &dgnc_proc_file_ops; + } + } + + table->de = de; + + if (de->mode & S_IFDIR) + dgnc_register_proc_table(table->child, de); + + } +} + + + +/* + * Unregister a /proc sysctl table and any subdirectories. + */ +static void dgnc_unregister_proc_table(struct dgnc_proc_entry *table, struct proc_dir_entry *root) +{ + struct proc_dir_entry *de; + + for (; table->magic; table++) { + if (!(de = table->de)) + continue; + + if (de->mode & S_IFDIR) { + if (!table->child) { + DPR_PROC((KERN_ALERT "Help - malformed sysctl tree on free\n")); + continue; + } + + /* recurse down into subdirectory... */ + DPR_PROC(("Recursing down a directory...\n")); + dgnc_unregister_proc_table(table->child, de); + + /* Don't unregister directories which still have entries.. */ + if (de->subdir) + continue; + } + + /* Don't unregister proc entries that are still being used.. */ + if ((atomic_read(&de->count)) != 1) { + DPR_PROC(("proc entry in use... Not removing...\n")); + continue; + } + + dgnc_remove_proc_entry(de); + table->de = NULL; + } +} + + + +static int dgnc_gen_proc_open(struct inode *inode, struct file *file) +{ + struct proc_dir_entry *de; + struct dgnc_proc_entry *entry; + int (*handler) (struct dgnc_proc_entry *table, int dir, struct file *filp, + void *buffer, ssize_t *lenp, loff_t *ppos); + int ret = 0, error = 0; + + de = (struct proc_dir_entry *) PDE(file->f_dentry->d_inode); + if (!de || !de->data) { + ret = -ENXIO; + goto done; + } + + entry = (struct dgnc_proc_entry *) de->data; + if (!entry) { + ret = -ENXIO; + goto done; + } + + down(&entry->excl_sem); + + if (entry->excl_cnt) { + ret = -EBUSY; + } else { + entry->excl_cnt++; + + handler = entry->open_handler; + if (handler) { + error = (*handler) (entry, OUTBOUND, file, NULL, NULL, NULL); + if (error) { + entry->excl_cnt--; + ret = error; + } + } + } + + up(&entry->excl_sem); + +done: + + return ret; +} + + +static int dgnc_gen_proc_close(struct inode *inode, struct file *file) +{ + struct proc_dir_entry *de; + int (*handler) (struct dgnc_proc_entry *table, int dir, struct file *filp, + void *buffer, ssize_t *lenp, loff_t *ppos); + struct dgnc_proc_entry *entry; + int error = 0; + + de = (struct proc_dir_entry *) PDE(file->f_dentry->d_inode); + if (!de || !de->data) + goto done; + + entry = (struct dgnc_proc_entry *) de->data; + if (!entry) + goto done; + + down(&entry->excl_sem); + + if (entry->excl_cnt) + entry->excl_cnt = 0; + + + handler = entry->close_handler; + if (handler) { + error = (*handler) (entry, OUTBOUND, file, NULL, NULL, NULL); + } + + up(&entry->excl_sem); + +done: + return 0; +} + + +static ssize_t dgnc_gen_proc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) +{ + struct proc_dir_entry *de; + struct dgnc_proc_entry *entry; + int (*handler) (struct dgnc_proc_entry *table, int dir, struct file *filp, + char __user *buffer, ssize_t *lenp, loff_t *ppos2); + ssize_t res; + ssize_t error; + + de = (struct proc_dir_entry*) PDE(file->f_dentry->d_inode); + if (!de || !de->data) + return -ENXIO; + + entry = (struct dgnc_proc_entry *) de->data; + if (!entry) + return -ENXIO; + + /* Test for read permission */ + if (dgnc_test_perm(entry->mode, 4)) + return -EPERM; + + res = count; + + handler = entry->read_handler; + if (!handler) + return -ENXIO; + + error = (*handler) (entry, OUTBOUND, file, buf, &res, ppos); + if (error) + return error; + + return res; +} + + +static ssize_t dgnc_gen_proc_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct proc_dir_entry *de; + struct dgnc_proc_entry *entry; + int (*handler) (struct dgnc_proc_entry *table, int dir, struct file *filp, + const char __user *buffer, ssize_t *lenp, loff_t *ppos2); + ssize_t res; + ssize_t error; + + de = (struct proc_dir_entry *) PDE(file->f_dentry->d_inode); + if (!de || !de->data) + return -ENXIO; + + entry = (struct dgnc_proc_entry *) de->data; + if (!entry) + return -ENXIO; + + /* Test for write permission */ + if (dgnc_test_perm(entry->mode, 2)) + return -EPERM; + + res = count; + + handler = entry->write_handler; + if (!handler) + return -ENXIO; + + error = (*handler) (entry, INBOUND, file, buf, &res, ppos); + if (error) + return error; + + return res; +} + + +static int dgnc_proc_chk_perm(struct inode *inode, int op) +{ + return dgnc_test_perm(inode->i_mode, op); +} + + +/* + * Return what is (hopefully) useful information about the + * driver. + */ +static int dgnc_read_info(struct dgnc_proc_entry *table, int dir, struct file *filp, + char __user *buffer, ssize_t *lenp, loff_t *ppos) +{ + static int done = 0; + static char buf[4096]; + char *p = buf; + + DPR_PROC(("dgnc_proc_info\n")); + + if (done) { + done = 0; + *lenp = 0; + return 0; + } + + p += sprintf(p, "Driver:\t\t%s\n", DG_NAME); + p += sprintf(p, "\n"); + p += sprintf(p, "Debug:\t\t0x%x\n", dgnc_debug); + p += sprintf(p, "Sysfs Support:\t0x1\n"); + p += sprintf(p, "Rawreadok:\t0x%x\n", dgnc_rawreadok); + p += sprintf(p, "Max Boards:\t%d\n", MAXBOARDS); + p += sprintf(p, "Total Boards:\t%d\n", dgnc_NumBoards); + p += sprintf(p, "Poll rate:\t%dms\n", dgnc_poll_tick); + p += sprintf(p, "Poll counter:\t%ld\n", dgnc_poll_counter); + p += sprintf(p, "State:\t\t%s\n", dgnc_driver_state_text[dgnc_driver_state]); + + if (copy_to_user(buffer, buf, (p - (char *) buf))) + return -EFAULT; + + *lenp = p - (char *) buf; + *ppos += p - (char *) buf; + done = 1; + return 0; +} + + +/* + * When writing to the "info" entry point, I actually allow one + * to modify certain variables. This may be a sleazy overload + * of this /proc entry, but I don't want: + * + * a. to clutter /proc more than I have to + * b. to overload the "config" entry, which would be somewhat + * more natural + * c. necessarily advertise the fact this ability exists + * + * The continued support of this feature has not yet been + * guaranteed. + * + * Writing operates on a "state machine" principle. + * + * State 0: waiting for a symbol to start. Waiting for anything + * which isn't " ' = or whitespace. + * State 1: reading a symbol. If the character is a space, move + * to state 2. If =, move to state 3. If " or ', move + * to state 0. + * State 2: Waiting for =... suck whitespace. If anything other + * than whitespace, drop to state 0. + * State 3: Got =. Suck whitespace waiting for value to start. + * If " or ', go to state 4 (and remember which quote it + * was). Otherwise, go to state 5. + * State 4: Reading value, within quotes. Everything is added to + * value up until the matching quote. When you hit the + * matching quote, try to set the variable, then state 0. + * State 5: Reading value, outside quotes. Everything not " ' = + * or whitespace goes in value. Hitting one of the + * terminators tosses us back to state 0 after trying to + * set the variable. + */ +typedef enum { + INFO_NONE, INFO_INT, INFO_CHAR, INFO_SHORT, + INFO_LONG, INFO_PTR, INFO_STRING, INFO_END +} info_proc_var_val; + +static struct { + char *name; + info_proc_var_val type; + int rw; /* 0=readonly */ + void *val_ptr; +} dgnc_info_vars[] = { + { "rawreadok", INFO_INT, 1, (void *) &dgnc_rawreadok }, + { "pollrate", INFO_INT, 1, (void *) &dgnc_poll_tick }, + { NULL, INFO_NONE, 0, NULL }, + { "debug", INFO_LONG, 1, (void *) &dgnc_debug }, + { NULL, INFO_END, 0, NULL } +}; + +static void dgnc_set_info_var(char *name, char *val) +{ + int i; + unsigned long newval; + unsigned char charval; + unsigned short shortval; + unsigned int intval; + + for (i = 0; dgnc_info_vars[i].type != INFO_END; i++) { + if (dgnc_info_vars[i].name) + if (!strcmp(name, dgnc_info_vars[i].name)) + break; + } + + if (dgnc_info_vars[i].type == INFO_END) + return; + if (dgnc_info_vars[i].rw == 0) + return; + if (dgnc_info_vars[i].val_ptr == NULL) + return; + + newval = simple_strtoul(val, NULL, 0 ); + + switch (dgnc_info_vars[i].type) { + case INFO_CHAR: + charval = newval & 0xff; + APR(("Modifying %s (%lx) <= 0x%02x (%d)\n", + name, (long)(dgnc_info_vars[i].val_ptr ), + charval, charval)); + *(uchar *)(dgnc_info_vars[i].val_ptr) = charval; + break; + case INFO_SHORT: + shortval = newval & 0xffff; + APR(("Modifying %s (%lx) <= 0x%04x (%d)\n", + name, (long)(dgnc_info_vars[i].val_ptr), + shortval, shortval)); + *(ushort *)(dgnc_info_vars[i].val_ptr) = shortval; + break; + case INFO_INT: + intval = newval & 0xffffffff; + APR(("Modifying %s (%lx) <= 0x%08x (%d)\n", + name, (long)(dgnc_info_vars[i].val_ptr), + intval, intval)); + *(uint *)(dgnc_info_vars[i].val_ptr) = intval; + break; + case INFO_LONG: + APR(("Modifying %s (%lx) <= 0x%lx (%ld)\n", + name, (long)(dgnc_info_vars[i].val_ptr), + newval, newval)); + *(ulong *)(dgnc_info_vars[i].val_ptr) = newval; + break; + case INFO_PTR: + case INFO_STRING: + case INFO_END: + case INFO_NONE: + default: + break; + } +} + +static int dgnc_write_info(struct dgnc_proc_entry *table, int dir, struct file *filp, + const char __user *buffer, ssize_t *lenp, loff_t *ppos) +{ + static int state = 0; + #define MAXSYM 255 + static int sympos, valpos; + static char sym[MAXSYM + 1]; + static char val[MAXSYM + 1]; + static int quotchar = 0; + + int i; + + long len; + #define INBUFLEN 256 + char inbuf[INBUFLEN]; + + if (*ppos == 0) { + state = 0; + sympos = 0; sym[0] = 0; + valpos = 0; val[0] = 0; + quotchar = 0; + } + + if ((!*lenp) || (dir != INBOUND)) { + *lenp = 0; + return 0; + } + + len = *lenp; + + if (len > INBUFLEN - 1) + len = INBUFLEN - 1; + + if (copy_from_user(inbuf, buffer, len)) + return -EFAULT; + + inbuf[len] = 0; + + for (i = 0; i < len; i++) { + unsigned char c = inbuf[i]; + + switch (state) { + case 0: + quotchar = sympos = valpos = sym[0] = val[0] = 0; + if (!isspace(c) && (c != '\"') && + (c != '\'') && (c != '=')) { + sym[sympos++] = c; + state = 1; + break; + } + break; + case 1: + if (isspace(c)) { + sym[sympos] = 0; + state = 2; + break; + } + if (c == '=') { + sym[sympos] = 0; + state = 3; + break; + } + if ((c == '\"' ) || ( c == '\'' )) { + state = 0; + break; + } + if (sympos < MAXSYM) sym[sympos++] = c; + break; + case 2: + if (isspace(c)) break; + if (c == '=') { + state = 3; + break; + } + if ((c != '\"') && (c != '\'')) { + quotchar = sympos = valpos = sym[0] = val[0] = 0; + sym[sympos++] = c; + state = 1; + break; + } + state = 0; + break; + case 3: + if (isspace(c)) break; + if (c == '=') { + state = 0; + break; + } + if ((c == '\"') || (c == '\'')) { + state = 4; + quotchar = c; + break; + } + val[valpos++] = c; + state = 5; + break; + case 4: + if (c == quotchar) { + val[valpos] = 0; + dgnc_set_info_var(sym, val); + state = 0; + break; + } + if (valpos < MAXSYM) val[valpos++] = c; + break; + case 5: + if (isspace(c) || (c == '\"') || + (c == '\'') || (c == '=')) { + val[valpos] = 0; + dgnc_set_info_var(sym, val); + state = 0; + break; + } + if (valpos < MAXSYM) val[valpos++] = c; + break; + default: + break; + } + } + + *lenp = len; + *ppos += len; + + return len; +} + + +/* + * Return mknod information for the driver's devices. + */ +static int dgnc_read_mknod(struct dgnc_proc_entry *table, int dir, struct file *filp, + char __user *buffer, ssize_t *lenp, loff_t *ppos) +{ + static int done = 0; + static char buf[4096]; + char *p = buf; + int i = 0; + + DPR_PROC(("dgnc_proc_info\n")); + + if (done) { + done = 0; + *lenp = 0; + return 0; + } + + DPR_PROC(("dgnc_proc_mknod\n")); + + p += sprintf(p, "#\tCreate the management devices.\n"); + + for (i = 0; i < MAXMGMTDEVICES; i++) { + char tmp[100]; + sprintf(tmp, "/dev/dg/dgnc/mgmt%d", i); + p += sprintf(p, "%s\t%d\t%d\t%d\n", + tmp, dgnc_Major, i, 1); + } + + if (copy_to_user(buffer, buf, (p - (char *) buf))) + return -EFAULT; + + *lenp = p - (char *) buf; + *ppos += p - (char *) buf; + done = 1; + return 0; +} + + +/* + * Return what is (hopefully) useful information about the specific board. + */ +static int dgnc_read_board_info(struct dgnc_proc_entry *table, int dir, struct file *filp, + char __user *buffer, ssize_t *lenp, loff_t *ppos) +{ + struct board_t *brd; + static int done = 0; + static char buf[4096]; + char *p = buf; + char *name; + + DPR_PROC(("dgnc_proc_brd_info\n")); + + brd = (struct board_t *) table->data; + + if (done || !brd || (brd->magic != DGNC_BOARD_MAGIC)) { + done = 0; + *lenp = 0; + return 0; + } + + name = brd->name; + + p += sprintf(p, "Board Name = %s\n", name); + if (brd->serial_num[0] == '\0') + p += sprintf(p, "Serial number = \n"); + else + p += sprintf(p, "Serial number = %s\n", brd->serial_num); + + p += sprintf(p, "Board Type = %d\n", brd->type); + p += sprintf(p, "Number of Ports = %d\n", brd->nasync); + + /* + * report some things about the PCI bus that are important + * to some applications + */ + p += sprintf(p, "Vendor ID = 0x%x\n", brd->vendor); + p += sprintf(p, "Device ID = 0x%x\n", brd->device); + p += sprintf(p, "Subvendor ID = 0x%x\n", brd->subvendor); + p += sprintf(p, "Subdevice ID = 0x%x\n", brd->subdevice); + p += sprintf(p, "Bus = %d\n", brd->pci_bus); + p += sprintf(p, "Slot = %d\n", brd->pci_slot); + + /* + * report the physical addresses assigned to us when we got + * registered + */ + p += sprintf(p, "Memory Base Address = 0x%lx\n", brd->membase); + p += sprintf(p, "Remapped Memory Base Address = 0x%p\n", brd->re_map_membase); + + p += sprintf(p, "Current state of board = %s\n", dgnc_state_text[brd->state]); + p += sprintf(p, "Interrupt #: %d. Times interrupted: %ld\n", + brd->irq, brd->intr_count); + + p += sprintf(p, "TX interrupts: %ld RX interrupts: %ld\n", + brd->intr_tx, brd->intr_rx); + p += sprintf(p, "Modem interrupts: %ld\n", brd->intr_modem); + + p += sprintf(p, "Majors allocated to board = TTY: %d PR: %d\n", + brd->SerialDriver.major, brd->PrintDriver.major); + + + if (copy_to_user(buffer, buf, (p - (char *) buf))) + return -EFAULT; + + *lenp = p - (char *) buf; + *ppos += p - (char *) buf; + done = 1; + return 0; +} + + + +static int dgnc_read_board_vpd(struct dgnc_proc_entry *table, int dir, struct file *filp, + char __user *buffer, ssize_t *lenp, loff_t *ppos) +{ + struct board_t *brd; + static int done = 0; + static char buf[4096]; + int i = 0, j = 0; + char *p = buf; + + DPR_PROC(("dgnc_proc_brd_info\n")); + + brd = (struct board_t *) table->data; + + if (done || !brd || (brd->magic != DGNC_BOARD_MAGIC)) { + done = 0; + *lenp = 0; + return 0; + } + + p += sprintf(p, "\n 0 1 2 3 4 5 6 7 8 9 A B C D E F ASCII\n"); + + for (i = 0; i < 0x40 * 2; i++) { + j = i; + if (!(i % 16)) { + if (j > 0) { + p += sprintf(p, " "); + for (j = i - 16; j < i; j++) { + if (0x20 <= brd->vpd[j] && brd->vpd[j] <= 0x7e) + p += sprintf(p, "%c", brd->vpd[j]); + else + p += sprintf(p, "."); + } + p += sprintf(p, "\n"); + } + p += sprintf(p, "%04X ", i); + } + p += sprintf(p, "%02X ", brd->vpd[i]); + } + if (!(i % 16)) { + p += sprintf(p, " "); + for (j = i - 16; j < i; j++) { + if (0x20 <= brd->vpd[j] && brd->vpd[j] <= 0x7e) + p += sprintf(p, "%c", brd->vpd[j]); + else + p += sprintf(p, "."); + } + p += sprintf(p, "\n"); + } + + p += sprintf(p, "\n"); + + if (copy_to_user(buffer, buf, (p - (char *) buf))) + return -EFAULT; + + *lenp = p - (char *) buf; + *ppos += p - (char *) buf; + done = 1; + return 0; +} + + +/* + * Return what is (hopefully) useful stats about the specific board's ttys + */ +static int dgnc_read_board_ttystats(struct dgnc_proc_entry *table, int dir, struct file *filp, + char __user *buffer, ssize_t *lenp, loff_t *ppos) +{ + struct board_t *brd; + static int done = 0; + static char buf[4096]; + char *p = buf; + int i = 0; + + DPR_PROC(("dgnc_proc_brd_info\n")); + + brd = (struct board_t *) table->data; + + if (done || !brd || (brd->magic != DGNC_BOARD_MAGIC)) { + done = 0; + *lenp = 0; + return 0; + } + + /* Prepare the Header Labels */ + p += sprintf(p, "%2s %10s %23s %10s %9s\n", + "Ch", "Chars Rx", " Rx Par--Brk--Frm--Ovr", + "Chars Tx", "XON XOFF"); + + for (i = 0; i < brd->nasync; i++) { + + struct channel_t *ch = brd->channels[i]; + + p += sprintf(p, "%2d ", i); + p += sprintf(p, "%10ld ", ch->ch_rxcount); + p += sprintf(p, " %4ld %4ld %4ld %4ld ", ch->ch_err_parity, + ch->ch_err_break, ch->ch_err_frame, ch->ch_err_overrun); + p += sprintf(p, "%10ld ", ch->ch_txcount); + p += sprintf(p, "%4ld %4ld ", ch->ch_xon_sends, ch->ch_xoff_sends); + + p += sprintf(p, "\n"); + } + + if (copy_to_user(buffer, buf, (p - (char *) buf))) + return -EFAULT; + + *lenp = p - (char *) buf; + *ppos += p - (char *) buf; + done = 1; + return 0; +} + + +/* + * Return what is (hopefully) useful stats about the specific board's tty intrs + */ +static int dgnc_read_board_ttyintr(struct dgnc_proc_entry *table, int dir, struct file *filp, + char __user *buffer, ssize_t *lenp, loff_t *ppos) +{ + struct board_t *brd; + static int done = 0; + static char buf[4096]; + char *p = buf; + int i = 0; + + DPR_PROC(("dgnc_proc_brd_info\n")); + + brd = (struct board_t *) table->data; + + if (done || !brd || (brd->magic != DGNC_BOARD_MAGIC)) { + done = 0; + *lenp = 0; + return 0; + } + + /* Prepare the Header Labels */ + p += sprintf(p, "%2s %14s %14s %14s\n", + "Ch", "TX interrupts", "RX interrupts", "Modem interrupts"); + + for (i = 0; i < brd->nasync; i++) { + + struct channel_t *ch = brd->channels[i]; + + p += sprintf(p, "%2d ", i); + + p += sprintf(p, " %14ld %14ld %14ld", + ch->ch_intr_tx, ch->ch_intr_rx, ch->ch_intr_modem); + + p += sprintf(p, "\n"); + } + + if (copy_to_user(buffer, buf, (p - (char *) buf))) + return -EFAULT; + + *lenp = p - (char *) buf; + *ppos += p - (char *) buf; + done = 1; + return 0; +} + + +/* + * Return what is (hopefully) useful flags about the specific board's ttys + */ +static int dgnc_read_board_ttyflags(struct dgnc_proc_entry *table, int dir, struct file *filp, + char __user *buffer, ssize_t *lenp, loff_t *ppos) +{ + struct board_t *brd; + static int done = 0; + static char buf[4096]; + char *p = buf; + int i = 0; + + DPR_PROC(("dgnc_proc_brd_info\n")); + + brd = (struct board_t *) table->data; + + if (done || !brd || (brd->magic != DGNC_BOARD_MAGIC)) { + done = 0; + *lenp = 0; + return 0; + } + + /* Prepare the Header Labels */ + p += sprintf(p, "%2s %5s %5s %5s %5s %5s %10s Line Status Flags\n", + "Ch", "CFlag", "IFlag", "OFlag", "LFlag", "DFlag", "Baud"); + + for (i = 0; i < brd->nasync; i++) { + + struct channel_t *ch = brd->channels[i]; + + p += sprintf(p, "%2d ", i); + p += sprintf(p, "%5x ", ch->ch_c_cflag); + p += sprintf(p, "%5x ", ch->ch_c_iflag); + p += sprintf(p, "%5x ", ch->ch_c_oflag); + p += sprintf(p, "%5x ", ch->ch_c_lflag); + p += sprintf(p, "%5x ", ch->ch_digi.digi_flags); + p += sprintf(p, "%10d ", ch->ch_old_baud); + + if (!ch->ch_open_count) { + p += sprintf(p, " -- -- -- -- -- -- --") ; + } else { + p += sprintf(p, " op %s %s %s %s %s %s", + (ch->ch_mostat & UART_MCR_RTS) ? "rs" : "--", + (ch->ch_mistat & UART_MSR_CTS) ? "cs" : "--", + (ch->ch_mostat & UART_MCR_DTR) ? "tr" : "--", + (ch->ch_mistat & UART_MSR_DSR) ? "mr" : "--", + (ch->ch_mistat & UART_MSR_DCD) ? "cd" : "--", + (ch->ch_mistat & UART_MSR_RI) ? "ri" : "--"); + } + + p += sprintf(p, "\n"); + } + if (copy_to_user(buffer, buf, (p - (char *) buf))) + return -EFAULT; + + *lenp = p - (char *) buf; + *ppos += p - (char *) buf; + done = 1; + return 0; +} + + +/* + * Return mknod information for the board's devices. + */ +static int dgnc_read_board_mknod(struct dgnc_proc_entry *table, int dir, struct file *filp, + char __user *buffer, ssize_t *lenp, loff_t *ppos) +{ + struct board_t *brd; + static int done = 0; + static char buf[4096]; + char str[MAXTTYNAMELEN]; + char *p = buf; + + DPR_PROC(("dgnc_proc_brd_info\n")); + + brd = (struct board_t *) table->data; + + if (done || !brd || (brd->magic != DGNC_BOARD_MAGIC)) { + done = 0; + *lenp = 0; + return 0; + } + + /* + * For each board, output the device information in + * a handy table format... + */ + p += sprintf(p, "# Create the TTY and PR devices\n"); + + /* TTY devices */ + sprintf(str, "ttyn%d%%p", brd->boardnum + 1); + p += sprintf(p, "%s\t\t\t%d\t%d\t%d\n", str, + brd->dgnc_Serial_Major, 0, brd->maxports); + + /* PR devices */ + sprintf(str, "prn%d%%p", brd->boardnum + 1); + p += sprintf(p, "%s\t\t\t%d\t%d\t%d\n", str, + brd->dgnc_TransparentPrint_Major, 128, brd->maxports); + + if (copy_to_user(buffer, buf, (p - (char *) buf))) + return -EFAULT; + + *lenp = p - (char *) buf; + *ppos += p - (char *) buf; + done = 1; + return 0; +} + + +/* + * Return what is (hopefully) useful information about the specific channel. + */ +static int dgnc_read_channel_info(struct dgnc_proc_entry *table, int dir, struct file *filp, + char __user *buffer, ssize_t *lenp, loff_t *ppos) +{ + struct channel_t *ch; + static int done = 0; + static char buf[4096]; + char *p = buf; + + DPR_PROC(("dgnc_proc_info\n")); + + ch = (struct channel_t *) table->data; + + if (done || !ch || (ch->magic != DGNC_CHANNEL_MAGIC)) { + done = 0; + *lenp = 0; + return 0; + } + + p += sprintf(p, "Port number:\t\t%d\n", ch->ch_portnum); + p += sprintf(p, "\n"); + + /* Prepare the Header Labels */ + p += sprintf(p, "%10s %23s %10s %9s\n", + "Chars Rx", " Rx Par--Brk--Frm--Ovr", + "Chars Tx", "XON XOFF"); + p += sprintf(p, "%10ld ", ch->ch_rxcount); + p += sprintf(p, " %4ld %4ld %4ld %4ld ", ch->ch_err_parity, + ch->ch_err_break, ch->ch_err_frame, ch->ch_err_overrun); + p += sprintf(p, "%10ld ", ch->ch_txcount); + p += sprintf(p, "%4ld %4ld ", ch->ch_xon_sends, ch->ch_xoff_sends); + p += sprintf(p, "\n\n"); + + /* Prepare the Header Labels */ + p += sprintf(p, "%5s %5s %5s %5s %5s %10s Line Status Flags\n", + "CFlag", "IFlag", "OFlag", "LFlag", "DFlag", "Baud"); + + p += sprintf(p, "%5x ", ch->ch_c_cflag); + p += sprintf(p, "%5x ", ch->ch_c_iflag); + p += sprintf(p, "%5x ", ch->ch_c_oflag); + p += sprintf(p, "%5x ", ch->ch_c_lflag); + p += sprintf(p, "%5x ", ch->ch_digi.digi_flags); + p += sprintf(p, "%10d ", ch->ch_old_baud); + if (!ch->ch_open_count) { + p += sprintf(p, " -- -- -- -- -- -- --") ; + } else { + p += sprintf(p, " op %s %s %s %s %s %s", + (ch->ch_mostat & UART_MCR_RTS) ? "rs" : "--", + (ch->ch_mistat & UART_MSR_CTS) ? "cs" : "--", + (ch->ch_mostat & UART_MCR_DTR) ? "tr" : "--", + (ch->ch_mistat & UART_MSR_DSR) ? "mr" : "--", + (ch->ch_mistat & UART_MSR_DCD) ? "cd" : "--", + (ch->ch_mistat & UART_MSR_RI) ? "ri" : "--"); + } + p += sprintf(p, "\n\n"); + + if (copy_to_user(buffer, buf, (p - (char *) buf))) + return -EFAULT; + + *lenp = p - (char *) buf; + *ppos += p - (char *) buf; + done = 1; + return 0; +} + + +/* + * Return mknod information for the board's devices. + */ +static int dgnc_read_channel_custom_ttyname(struct dgnc_proc_entry *table, int dir, struct file *filp, + char __user *buffer, ssize_t *lenp, loff_t *ppos) +{ + struct channel_t *ch; + struct board_t *brd; + static int done = 0; + static char buf[4096]; + char *p = buf; + int cn; + int bn; + + DPR_PROC(("dgnc_proc_brd_info\n")); + + ch = (struct channel_t *) table->data; + + if (done || !ch || (ch->magic != DGNC_CHANNEL_MAGIC)) { + done = 0; + *lenp = 0; + return 0; + } + + brd = ch->ch_bd; + + if (done || !brd || (brd->magic != DGNC_BOARD_MAGIC)) { + done = 0; + *lenp = 0; + return 0; + } + + bn = brd->boardnum; + cn = ch->ch_portnum; + + p += sprintf(p, "ttyn%d%c\n", bn + 1, 'a' + cn); + + if (copy_to_user(buffer, buf, (p - (char *) buf))) + return -EFAULT; + + *lenp = p - (char *) buf; + *ppos += p - (char *) buf; + done = 1; + return 0; +} + + + + +/* + * Return mknod information for the board's devices. + */ +static int dgnc_read_channel_custom_prname(struct dgnc_proc_entry *table, int dir, struct file *filp, + char __user *buffer, ssize_t *lenp, loff_t *ppos) +{ + struct channel_t *ch; + struct board_t *brd; + static int done = 0; + static char buf[4096]; + char *p = buf; + int cn; + int bn; + + DPR_PROC(("dgnc_proc_brd_info\n")); + + ch = (struct channel_t *) table->data; + + if (done || !ch || (ch->magic != DGNC_CHANNEL_MAGIC)) { + done = 0; + *lenp = 0; + return 0; + } + + brd = ch->ch_bd; + + if (done || !brd || (brd->magic != DGNC_BOARD_MAGIC)) { + done = 0; + *lenp = 0; + return 0; + } + + bn = brd->boardnum; + cn = ch->ch_portnum; + + p += sprintf(p, "prn%d%c\n", bn + 1, 'a' + cn); + + if (copy_to_user(buffer, buf, (p - (char *) buf))) + return -EFAULT; + + *lenp = p - (char *) buf; + *ppos += p - (char *) buf; + done = 1; + return 0; +} + + +static int dgnc_open_channel_sniff(struct dgnc_proc_entry *table, int dir, struct file *filp, + void *buffer, ssize_t *lenp, loff_t *ppos) +{ + struct channel_t *ch; + ulong lock_flags; + + ch = (struct channel_t *) table->data; + + if (!ch || (ch->magic != DGNC_CHANNEL_MAGIC)) + return 0; + + ch->ch_sniff_buf = dgnc_driver_kzmalloc(SNIFF_MAX, GFP_KERNEL); + + DGNC_LOCK(ch->ch_lock, lock_flags); + ch->ch_sniff_flags |= SNIFF_OPEN; + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + return 0; +} + +static int dgnc_close_channel_sniff(struct dgnc_proc_entry *table, int dir, struct file *filp, + void *buffer, ssize_t *lenp, loff_t *ppos) +{ + struct channel_t *ch; + ulong lock_flags; + + ch = (struct channel_t *) table->data; + + if (!ch || (ch->magic != DGNC_CHANNEL_MAGIC)) + return 0; + + DGNC_LOCK(ch->ch_lock, lock_flags); + ch->ch_sniff_flags &= ~(SNIFF_OPEN); + kfree(ch->ch_sniff_buf); + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + return 0; +} + + +/* + * Copy data from the monitoring buffer to the user, freeing space + * in the monitoring buffer for more messages + * + */ +static int dgnc_read_channel_sniff(struct dgnc_proc_entry *table, int dir, struct file *filp, + char __user *buffer, ssize_t *lenp, loff_t *ppos) +{ + struct channel_t *ch; + int n; + int r; + int offset = 0; + int res = 0; + ssize_t rtn = 0; + ulong lock_flags; + + ch = (struct channel_t *) table->data; + + if (!ch || (ch->magic != DGNC_CHANNEL_MAGIC)) { + rtn = -ENXIO; + goto done; + } + + /* + * Wait for some data to appear in the buffer. + */ + DGNC_LOCK(ch->ch_lock, lock_flags); + + for (;;) { + n = (ch->ch_sniff_in - ch->ch_sniff_out) & SNIFF_MASK; + + if (n != 0) + break; + + ch->ch_sniff_flags |= SNIFF_WAIT_DATA; + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + /* + * Go to sleep waiting until the condition becomes true. + */ + rtn = wait_event_interruptible(ch->ch_sniff_wait, + ((ch->ch_sniff_flags & SNIFF_WAIT_DATA) == 0)); + + if (rtn) + goto done; + + DGNC_LOCK(ch->ch_lock, lock_flags); + } + + /* + * Read whatever is there. + */ + + if (n > *lenp) + n = *lenp; + + res = n; + + r = SNIFF_MAX - ch->ch_sniff_out; + + if (r <= n) { + DGNC_UNLOCK(ch->ch_lock, lock_flags); + rtn = copy_to_user(buffer, ch->ch_sniff_buf + ch->ch_sniff_out, r); + if (rtn) { + rtn = -EFAULT; + goto done; + } + + DGNC_LOCK(ch->ch_lock, lock_flags); + + ch->ch_sniff_out = 0; + n -= r; + offset = r; + } + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + rtn = copy_to_user(buffer + offset, ch->ch_sniff_buf + ch->ch_sniff_out, n); + if (rtn) { + rtn = -EFAULT; + goto done; + } + DGNC_LOCK(ch->ch_lock, lock_flags); + + ch->ch_sniff_out += n; + *ppos += res; + rtn = res; +// rtn = 0; + + /* + * Wakeup any thread waiting for buffer space. + */ + + if (ch->ch_sniff_flags & SNIFF_WAIT_SPACE) { + ch->ch_sniff_flags &= ~SNIFF_WAIT_SPACE; + wake_up_interruptible(&ch->ch_sniff_wait); + } + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + +done: + return rtn; +} + + +/* + * Register the basic /proc/dgnc files that appear whenever + * the driver is loaded. + */ +void dgnc_proc_register_basic_prescan(void) +{ + /* + * Register /proc/dgnc + */ + ProcDGNC = proc_create("dgnc", (0700 | S_IFDIR), NULL, &dgnc_proc_file_ops); + dgnc_register_proc_table(dgnc_table, ProcDGNC); +} + + +/* + * Register the basic /proc/dgnc files that appear whenever + * the driver is loaded. + */ +void dgnc_proc_register_basic_postscan(int board_num) +{ + int i, j; + char board[10]; + sprintf(board, "%d", board_num); + + /* Set proc board entry pointer */ + dgnc_Board[board_num]->proc_entry_pointer = create_proc_entry(board, (0700 | S_IFDIR), ProcDGNC); + + /* Create a new copy of the board_table... */ + dgnc_Board[board_num]->dgnc_board_table = dgnc_driver_kzmalloc(sizeof(dgnc_board_table), + GFP_KERNEL); + + /* Now copy the default table into that memory */ + memcpy(dgnc_Board[board_num]->dgnc_board_table, dgnc_board_table, sizeof(dgnc_board_table)); + + /* Initialize semaphores in each table slot */ + for (i = 0; i < 999; i++) { + if (!dgnc_Board[board_num]->dgnc_board_table[i].magic) { + break; + } + + init_MUTEX(&(dgnc_Board[board_num]->dgnc_board_table[i].excl_sem)); + dgnc_Board[board_num]->dgnc_board_table[i].data = dgnc_Board[board_num]; + + } + + /* Register board table into proc */ + dgnc_register_proc_table(dgnc_Board[board_num]->dgnc_board_table, + dgnc_Board[board_num]->proc_entry_pointer); + + /* + * Add new entries for each port. + */ + for (i = 0; i < dgnc_Board[board_num]->nasync; i++) { + + char channel[10]; + sprintf(channel, "%d", i); + + /* Set proc channel entry pointer */ + dgnc_Board[board_num]->channels[i]->proc_entry_pointer = + create_proc_entry(channel, (0700 | S_IFDIR), + dgnc_Board[board_num]->proc_entry_pointer); + + /* Create a new copy of the channel_table... */ + dgnc_Board[board_num]->channels[i]->dgnc_channel_table = + dgnc_driver_kzmalloc(sizeof(dgnc_channel_table), GFP_KERNEL); + + /* Now copy the default table into that memory */ + memcpy(dgnc_Board[board_num]->channels[i]->dgnc_channel_table, + dgnc_channel_table, sizeof(dgnc_channel_table)); + + /* Initialize semaphores in each table slot */ + for (j = 0; j < 999; j++) { + if (!dgnc_Board[board_num]->channels[i]->dgnc_channel_table[j].magic) { + break; + } + + init_MUTEX(&(dgnc_Board[board_num]->channels[i]->dgnc_channel_table[j].excl_sem)); + dgnc_Board[board_num]->channels[i]->dgnc_channel_table[j].data = + dgnc_Board[board_num]->channels[i]; + } + + /* Register channel table into proc */ + dgnc_register_proc_table(dgnc_Board[board_num]->channels[i]->dgnc_channel_table, + dgnc_Board[board_num]->channels[i]->proc_entry_pointer); + } +} + + +static void dgnc_remove_proc_entry(struct proc_dir_entry *pde) +{ + if (!pde) { + DPR_PROC(("dgnc_remove_proc_entry... NULL entry... not removing...\n")); + return; + } + + remove_proc_entry(pde->name, pde->parent); +} + + +void dgnc_proc_unregister_all(void) +{ + int i = 0, j = 0; + + /* Walk each board, blowing away their proc entries... */ + for (i = 0; i < dgnc_NumBoards; i++) { + + /* Walk each channel, blowing away their proc entries... */ + for (j = 0; j < dgnc_Board[i]->nasync; j++) { + + dgnc_unregister_proc_table(dgnc_Board[i]->channels[j]->dgnc_channel_table, + dgnc_Board[i]->channels[j]->proc_entry_pointer); + dgnc_remove_proc_entry(dgnc_Board[i]->channels[j]->proc_entry_pointer); + kfree(dgnc_Board[i]->channels[j]->dgnc_channel_table); + } + + dgnc_unregister_proc_table(dgnc_Board[i]->dgnc_board_table, + dgnc_Board[i]->proc_entry_pointer); + dgnc_remove_proc_entry(dgnc_Board[i]->proc_entry_pointer); + kfree(dgnc_Board[i]->dgnc_board_table); + } + + /* Blow away the top proc entry */ + dgnc_unregister_proc_table(dgnc_table, ProcDGNC); + dgnc_remove_proc_entry(ProcDGNC); +} diff --git a/drivers/staging/dgnc/dgnc_proc.h b/drivers/staging/dgnc/dgnc_proc.h new file mode 100644 index 000000000000..19670e29d570 --- /dev/null +++ b/drivers/staging/dgnc/dgnc_proc.h @@ -0,0 +1,147 @@ +/* + * Copyright 2003 Digi International (www.digi.com) + * Scott H Kilau + * + * 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, EXPRESS OR IMPLIED; 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. + * + * NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!! + * + * + * $Id: dgnc_proc.h,v 1.1.1.1 2009/05/20 12:19:19 markh Exp $ + * + * Description: + * + * Describes the private structures used to manipulate the "special" + * proc constructs (not read-only) used by the Digi Neo software. + * The concept is borrowed heavily from the "sysctl" interface of + * the kernel. I decided not to use the structures and functions + * provided by the kernel for two reasons: + * + * 1. Due to the planned use of "/proc" in the Neo driver, many + * of the functions of the "sysctl" interface would go unused. + * A simpler interface will be easier to maintain. + * + * 2. I'd rather divorce our "added package" from the kernel internals. + * If the "sysctl" structures should change, I will be insulated + * from those changes. These "/proc" entries won't be under the + * "sys" tree anyway, so there is no need to maintain a strict + * dependence relationship. + * + * Author: + * + * Scott H Kilau + * + */ + +#ifndef _DGNC_RW_PROC_H +#define _DGNC_RW_PROC_H + +/* + * The list of DGNC entries with r/w capabilities. + * These magic numbers are used for identification purposes. + */ +enum { + DGNC_INFO = 1, /* Get info about the running module */ + DGNC_MKNOD = 2, /* Get info about driver devices */ + DGNC_BOARD_INFO = 3, /* Get info about the specific board */ + DGNC_BOARD_VPD = 4, /* Get info about the board's VPD */ + DGNC_BOARD_TTYSTATS = 5, /* Get info about the board's tty stats */ + DGNC_BOARD_TTYINTR = 6, /* Get info about the board's tty intrs */ + DGNC_BOARD_TTYFLAGS = 7, /* Get info about the board's tty flags */ + DGNC_BOARD_MKNOD = 8, /* Get info about board devices */ + DGNC_PORT_INFO = 9, /* Get info about the specific port */ + DGNC_PORT_SNIFF = 10, /* Sniff data in/out of specific port */ + DGNC_PORT_CUSTOM_TTYNAME = 11, /* Get info about UDEV tty name */ + DGNC_PORT_CUSTOM_PRNAME = 12, /* Get info about UDEV pr name */ +}; + +/* + * Directions for proc handlers + */ +enum { + INBOUND = 1, /* Data being written to kernel */ + OUTBOUND = 2, /* Data being read from the kernel */ +}; + +/* + * Each entry in a DGNC proc directory is described with a + * "dgnc_proc_entry" structure. A collection of these + * entries (in an array) represents the members associated + * with a particular "/proc" directory, and is referred to + * as a table. All "tables" are terminated by an entry with + * zeros for every member. + * + * The structure members are as follows: + * + * int magic -- ID number associated with this particular + * entry. Should be unique across all of + * DGNC. + * + * const char *name -- ASCII name associated with the /proc entry. + * + * mode_t mode -- File access permisssions for the /proc entry. + * + * dgnc_proc_entry *child -- When set, this entry refers to a directory, + * and points to the table which describes the + * entries in the subdirectory + * + * dgnc_proc_handler *open_handler -- When set, points to the fxn which + * does any "extra" open stuff. + * + * dgnc_proc_handler *close_handler -- When set, points to the fxn which + * does any "extra" close stuff. + * + * dgnc_proc_handler *read_handler -- When set, points to the fxn which + * handle outbound data flow + * + * dgnc_proc_handler *write_handler -- When set, points to the fxn which + * handles inbound data flow + * + * struct proc_dir_entry *de -- Pointer to the directory entry for this + * object once registered. Used to grab + * the handle of the object for + * unregistration + * + * void *data; When set, points to the parent structure + * + */ + +struct dgnc_proc_entry { + int magic; /* Integer identifier */ + const char *name; /* ASCII identifier */ + mode_t mode; /* File access permissions */ + struct dgnc_proc_entry *child; /* Child pointer */ + + int (*open_handler) (struct dgnc_proc_entry *table, int dir, struct file *filp, + void *buffer, ssize_t *lenp, loff_t *ppos); + int (*close_handler) (struct dgnc_proc_entry *table, int dir, struct file *filp, + void *buffer, ssize_t *lenp, loff_t *ppos); + int (*read_handler) (struct dgnc_proc_entry *table, int dir, struct file *filp, + char __user *buffer, ssize_t *lenp, loff_t *ppos); + int (*write_handler) (struct dgnc_proc_entry *table, int dir, struct file *filp, + const char __user *buffer, ssize_t *lenp, loff_t *ppos); + + struct proc_dir_entry *de; /* proc entry pointer */ + struct semaphore excl_sem; /* Protects exclusive access var */ + int excl_cnt; /* Counts number of curr accesses */ + void *data; /* Allows storing a pointer to parent */ +}; + +void dgnc_proc_register_basic_prescan(void); +void dgnc_proc_register_basic_postscan(int board_num); +void dgnc_proc_unregister_all(void); + + +#endif /* _DGNC_RW_PROC_H */ diff --git a/drivers/staging/dgnc/dgnc_sysfs.c b/drivers/staging/dgnc/dgnc_sysfs.c new file mode 100644 index 000000000000..af49e44382f5 --- /dev/null +++ b/drivers/staging/dgnc/dgnc_sysfs.c @@ -0,0 +1,761 @@ +/* + * Copyright 2004 Digi International (www.digi.com) + * Scott H Kilau + * + * 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, EXPRESS OR IMPLIED; 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. + * + * + * NOTE TO LINUX KERNEL HACKERS: DO NOT REFORMAT THIS CODE! + * + * This is shared code between Digi's CVS archive and the + * Linux Kernel sources. + * Changing the source just for reformatting needlessly breaks + * our CVS diff history. + * + * Send any bug fixes/changes to: Eng.Linux at digi dot com. + * Thank you. + * + * + * + * $Id: dgnc_sysfs.c,v 1.1.1.1 2009/05/20 12:19:19 markh Exp $ + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dgnc_driver.h" +#include "dgnc_proc.h" +#include "dgnc_mgmt.h" + + +static ssize_t dgnc_driver_version_show(struct device_driver *ddp, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%s\n", DG_PART); +} +static DRIVER_ATTR(version, S_IRUSR, dgnc_driver_version_show, NULL); + + +static ssize_t dgnc_driver_boards_show(struct device_driver *ddp, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", dgnc_NumBoards); +} +static DRIVER_ATTR(boards, S_IRUSR, dgnc_driver_boards_show, NULL); + + +static ssize_t dgnc_driver_maxboards_show(struct device_driver *ddp, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", MAXBOARDS); +} +static DRIVER_ATTR(maxboards, S_IRUSR, dgnc_driver_maxboards_show, NULL); + + +static ssize_t dgnc_driver_pollcounter_show(struct device_driver *ddp, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%ld\n", dgnc_poll_counter); +} +static DRIVER_ATTR(pollcounter, S_IRUSR, dgnc_driver_pollcounter_show, NULL); + + +static ssize_t dgnc_driver_state_show(struct device_driver *ddp, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%s\n", dgnc_driver_state_text[dgnc_driver_state]); +} +static DRIVER_ATTR(state, S_IRUSR, dgnc_driver_state_show, NULL); + + +static ssize_t dgnc_driver_debug_show(struct device_driver *ddp, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "0x%x\n", dgnc_debug); +} + +static ssize_t dgnc_driver_debug_store(struct device_driver *ddp, const char *buf, size_t count) +{ + sscanf(buf, "0x%x\n", &dgnc_debug); + return count; +} +static DRIVER_ATTR(debug, (S_IRUSR | S_IWUSR), dgnc_driver_debug_show, dgnc_driver_debug_store); + + +static ssize_t dgnc_driver_rawreadok_show(struct device_driver *ddp, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "0x%x\n", dgnc_rawreadok); +} + +static ssize_t dgnc_driver_rawreadok_store(struct device_driver *ddp, const char *buf, size_t count) +{ + sscanf(buf, "0x%x\n", &dgnc_rawreadok); + return count; +} +static DRIVER_ATTR(rawreadok, (S_IRUSR | S_IWUSR), dgnc_driver_rawreadok_show, dgnc_driver_rawreadok_store); + + +static ssize_t dgnc_driver_pollrate_show(struct device_driver *ddp, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%dms\n", dgnc_poll_tick); +} + +static ssize_t dgnc_driver_pollrate_store(struct device_driver *ddp, const char *buf, size_t count) +{ + sscanf(buf, "%d\n", &dgnc_poll_tick); + return count; +} +static DRIVER_ATTR(pollrate, (S_IRUSR | S_IWUSR), dgnc_driver_pollrate_show, dgnc_driver_pollrate_store); + + +void dgnc_create_driver_sysfiles(struct pci_driver *dgnc_driver) +{ + int rc = 0; + struct device_driver *driverfs = &dgnc_driver->driver; + + rc |= driver_create_file(driverfs, &driver_attr_version); + rc |= driver_create_file(driverfs, &driver_attr_boards); + rc |= driver_create_file(driverfs, &driver_attr_maxboards); + rc |= driver_create_file(driverfs, &driver_attr_debug); + rc |= driver_create_file(driverfs, &driver_attr_rawreadok); + rc |= driver_create_file(driverfs, &driver_attr_pollrate); + rc |= driver_create_file(driverfs, &driver_attr_pollcounter); + rc |= driver_create_file(driverfs, &driver_attr_state); + if (rc) { + printk(KERN_ERR "DGNC: sysfs driver_create_file failed!\n"); + } +} + + +void dgnc_remove_driver_sysfiles(struct pci_driver *dgnc_driver) +{ + struct device_driver *driverfs = &dgnc_driver->driver; + driver_remove_file(driverfs, &driver_attr_version); + driver_remove_file(driverfs, &driver_attr_boards); + driver_remove_file(driverfs, &driver_attr_maxboards); + driver_remove_file(driverfs, &driver_attr_debug); + driver_remove_file(driverfs, &driver_attr_rawreadok); + driver_remove_file(driverfs, &driver_attr_pollrate); + driver_remove_file(driverfs, &driver_attr_pollcounter); + driver_remove_file(driverfs, &driver_attr_state); +} + + +#define DGNC_VERIFY_BOARD(p, bd) \ + if (!p) \ + return (0); \ + \ + bd = dev_get_drvdata(p); \ + if (!bd || bd->magic != DGNC_BOARD_MAGIC) \ + return (0); \ + if (bd->state != BOARD_READY) \ + return (0); \ + + + +static ssize_t dgnc_vpd_show(struct device *p, struct device_attribute *attr, char *buf) +{ + struct board_t *bd; + int count = 0; + int i = 0; + + DGNC_VERIFY_BOARD(p, bd); + + count += sprintf(buf + count, "\n 0 1 2 3 4 5 6 7 8 9 A B C D E F"); + for (i = 0; i < 0x40 * 2; i++) { + if (!(i % 16)) + count += sprintf(buf + count, "\n%04X ", i * 2); + count += sprintf(buf + count, "%02X ", bd->vpd[i]); + } + count += sprintf(buf + count, "\n"); + + return count; +} +static DEVICE_ATTR(vpd, S_IRUSR, dgnc_vpd_show, NULL); + +static ssize_t dgnc_serial_number_show(struct device *p, struct device_attribute *attr, char *buf) +{ + struct board_t *bd; + int count = 0; + + DGNC_VERIFY_BOARD(p, bd); + + if (bd->serial_num[0] == '\0') + count += sprintf(buf + count, "\n"); + else + count += sprintf(buf + count, "%s\n", bd->serial_num); + + return count; +} +static DEVICE_ATTR(serial_number, S_IRUSR, dgnc_serial_number_show, NULL); + + +static ssize_t dgnc_ports_state_show(struct device *p, struct device_attribute *attr, char *buf) +{ + struct board_t *bd; + int count = 0; + int i = 0; + + DGNC_VERIFY_BOARD(p, bd); + + for (i = 0; i < bd->nasync; i++) { + count += snprintf(buf + count, PAGE_SIZE - count, + "%d %s\n", bd->channels[i]->ch_portnum, + bd->channels[i]->ch_open_count ? "Open" : "Closed"); + } + return count; +} +static DEVICE_ATTR(ports_state, S_IRUSR, dgnc_ports_state_show, NULL); + + +static ssize_t dgnc_ports_baud_show(struct device *p, struct device_attribute *attr, char *buf) +{ + struct board_t *bd; + int count = 0; + int i = 0; + + DGNC_VERIFY_BOARD(p, bd); + + for (i = 0; i < bd->nasync; i++) { + count += snprintf(buf + count, PAGE_SIZE - count, + "%d %d\n", bd->channels[i]->ch_portnum, bd->channels[i]->ch_old_baud); + } + return count; +} +static DEVICE_ATTR(ports_baud, S_IRUSR, dgnc_ports_baud_show, NULL); + + +static ssize_t dgnc_ports_msignals_show(struct device *p, struct device_attribute *attr, char *buf) +{ + struct board_t *bd; + int count = 0; + int i = 0; + + DGNC_VERIFY_BOARD(p, bd); + + for (i = 0; i < bd->nasync; i++) { + if (bd->channels[i]->ch_open_count) { + count += snprintf(buf + count, PAGE_SIZE - count, + "%d %s %s %s %s %s %s\n", bd->channels[i]->ch_portnum, + (bd->channels[i]->ch_mostat & UART_MCR_RTS) ? "RTS" : "", + (bd->channels[i]->ch_mistat & UART_MSR_CTS) ? "CTS" : "", + (bd->channels[i]->ch_mostat & UART_MCR_DTR) ? "DTR" : "", + (bd->channels[i]->ch_mistat & UART_MSR_DSR) ? "DSR" : "", + (bd->channels[i]->ch_mistat & UART_MSR_DCD) ? "DCD" : "", + (bd->channels[i]->ch_mistat & UART_MSR_RI) ? "RI" : ""); + } else { + count += snprintf(buf + count, PAGE_SIZE - count, + "%d\n", bd->channels[i]->ch_portnum); + } + } + return count; +} +static DEVICE_ATTR(ports_msignals, S_IRUSR, dgnc_ports_msignals_show, NULL); + + +static ssize_t dgnc_ports_iflag_show(struct device *p, struct device_attribute *attr, char *buf) +{ + struct board_t *bd; + int count = 0; + int i = 0; + + DGNC_VERIFY_BOARD(p, bd); + + for (i = 0; i < bd->nasync; i++) { + count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n", + bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_iflag); + } + return count; +} +static DEVICE_ATTR(ports_iflag, S_IRUSR, dgnc_ports_iflag_show, NULL); + + +static ssize_t dgnc_ports_cflag_show(struct device *p, struct device_attribute *attr, char *buf) +{ + struct board_t *bd; + int count = 0; + int i = 0; + + DGNC_VERIFY_BOARD(p, bd); + + for (i = 0; i < bd->nasync; i++) { + count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n", + bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_cflag); + } + return count; +} +static DEVICE_ATTR(ports_cflag, S_IRUSR, dgnc_ports_cflag_show, NULL); + + +static ssize_t dgnc_ports_oflag_show(struct device *p, struct device_attribute *attr, char *buf) +{ + struct board_t *bd; + int count = 0; + int i = 0; + + DGNC_VERIFY_BOARD(p, bd); + + for (i = 0; i < bd->nasync; i++) { + count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n", + bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_oflag); + } + return count; +} +static DEVICE_ATTR(ports_oflag, S_IRUSR, dgnc_ports_oflag_show, NULL); + + +static ssize_t dgnc_ports_lflag_show(struct device *p, struct device_attribute *attr, char *buf) +{ + struct board_t *bd; + int count = 0; + int i = 0; + + DGNC_VERIFY_BOARD(p, bd); + + for (i = 0; i < bd->nasync; i++) { + count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n", + bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_lflag); + } + return count; +} +static DEVICE_ATTR(ports_lflag, S_IRUSR, dgnc_ports_lflag_show, NULL); + + +static ssize_t dgnc_ports_digi_flag_show(struct device *p, struct device_attribute *attr, char *buf) +{ + struct board_t *bd; + int count = 0; + int i = 0; + + DGNC_VERIFY_BOARD(p, bd); + + for (i = 0; i < bd->nasync; i++) { + count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n", + bd->channels[i]->ch_portnum, bd->channels[i]->ch_digi.digi_flags); + } + return count; +} +static DEVICE_ATTR(ports_digi_flag, S_IRUSR, dgnc_ports_digi_flag_show, NULL); + + +static ssize_t dgnc_ports_rxcount_show(struct device *p, struct device_attribute *attr, char *buf) +{ + struct board_t *bd; + int count = 0; + int i = 0; + + DGNC_VERIFY_BOARD(p, bd); + + for (i = 0; i < bd->nasync; i++) { + count += snprintf(buf + count, PAGE_SIZE - count, "%d %ld\n", + bd->channels[i]->ch_portnum, bd->channels[i]->ch_rxcount); + } + return count; +} +static DEVICE_ATTR(ports_rxcount, S_IRUSR, dgnc_ports_rxcount_show, NULL); + + +static ssize_t dgnc_ports_txcount_show(struct device *p, struct device_attribute *attr, char *buf) +{ + struct board_t *bd; + int count = 0; + int i = 0; + + DGNC_VERIFY_BOARD(p, bd); + + for (i = 0; i < bd->nasync; i++) { + count += snprintf(buf + count, PAGE_SIZE - count, "%d %ld\n", + bd->channels[i]->ch_portnum, bd->channels[i]->ch_txcount); + } + return count; +} +static DEVICE_ATTR(ports_txcount, S_IRUSR, dgnc_ports_txcount_show, NULL); + + +/* this function creates the sys files that will export each signal status + * to sysfs each value will be put in a separate filename + */ +void dgnc_create_ports_sysfiles(struct board_t *bd) +{ + int rc = 0; + + dev_set_drvdata(&bd->pdev->dev, bd); + rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_state); + rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_baud); + rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_msignals); + rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_iflag); + rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_cflag); + rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_oflag); + rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_lflag); + rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_digi_flag); + rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_rxcount); + rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_txcount); + rc |= device_create_file(&(bd->pdev->dev), &dev_attr_vpd); + rc |= device_create_file(&(bd->pdev->dev), &dev_attr_serial_number); + if (rc) { + printk(KERN_ERR "DGNC: sysfs device_create_file failed!\n"); + } +} + + +/* removes all the sys files created for that port */ +void dgnc_remove_ports_sysfiles(struct board_t *bd) +{ + device_remove_file(&(bd->pdev->dev), &dev_attr_ports_state); + device_remove_file(&(bd->pdev->dev), &dev_attr_ports_baud); + device_remove_file(&(bd->pdev->dev), &dev_attr_ports_msignals); + device_remove_file(&(bd->pdev->dev), &dev_attr_ports_iflag); + device_remove_file(&(bd->pdev->dev), &dev_attr_ports_cflag); + device_remove_file(&(bd->pdev->dev), &dev_attr_ports_oflag); + device_remove_file(&(bd->pdev->dev), &dev_attr_ports_lflag); + device_remove_file(&(bd->pdev->dev), &dev_attr_ports_digi_flag); + device_remove_file(&(bd->pdev->dev), &dev_attr_ports_rxcount); + device_remove_file(&(bd->pdev->dev), &dev_attr_ports_txcount); + device_remove_file(&(bd->pdev->dev), &dev_attr_vpd); + device_remove_file(&(bd->pdev->dev), &dev_attr_serial_number); +} + + +static ssize_t dgnc_tty_state_show(struct device *d, struct device_attribute *attr, char *buf) +{ + struct board_t *bd; + struct channel_t *ch; + struct un_t *un; + + if (!d) + return (0); + un = (struct un_t *) dev_get_drvdata(d); + if (!un || un->magic != DGNC_UNIT_MAGIC) + return (0); + ch = un->un_ch; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return (0); + bd = ch->ch_bd; + if (!bd || bd->magic != DGNC_BOARD_MAGIC) + return (0); + if (bd->state != BOARD_READY) + return (0); + + return snprintf(buf, PAGE_SIZE, "%s", un->un_open_count ? "Open" : "Closed"); +} +static DEVICE_ATTR(state, S_IRUSR, dgnc_tty_state_show, NULL); + + +static ssize_t dgnc_tty_baud_show(struct device *d, struct device_attribute *attr, char *buf) +{ + struct board_t *bd; + struct channel_t *ch; + struct un_t *un; + + if (!d) + return (0); + un = (struct un_t *) dev_get_drvdata(d); + if (!un || un->magic != DGNC_UNIT_MAGIC) + return (0); + ch = un->un_ch; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return (0); + bd = ch->ch_bd; + if (!bd || bd->magic != DGNC_BOARD_MAGIC) + return (0); + if (bd->state != BOARD_READY) + return (0); + + return snprintf(buf, PAGE_SIZE, "%d\n", ch->ch_old_baud); +} +static DEVICE_ATTR(baud, S_IRUSR, dgnc_tty_baud_show, NULL); + + +static ssize_t dgnc_tty_msignals_show(struct device *d, struct device_attribute *attr, char *buf) +{ + struct board_t *bd; + struct channel_t *ch; + struct un_t *un; + + if (!d) + return (0); + un = (struct un_t *) dev_get_drvdata(d); + if (!un || un->magic != DGNC_UNIT_MAGIC) + return (0); + ch = un->un_ch; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return (0); + bd = ch->ch_bd; + if (!bd || bd->magic != DGNC_BOARD_MAGIC) + return (0); + if (bd->state != BOARD_READY) + return (0); + + if (ch->ch_open_count) { + return snprintf(buf, PAGE_SIZE, "%s %s %s %s %s %s\n", + (ch->ch_mostat & UART_MCR_RTS) ? "RTS" : "", + (ch->ch_mistat & UART_MSR_CTS) ? "CTS" : "", + (ch->ch_mostat & UART_MCR_DTR) ? "DTR" : "", + (ch->ch_mistat & UART_MSR_DSR) ? "DSR" : "", + (ch->ch_mistat & UART_MSR_DCD) ? "DCD" : "", + (ch->ch_mistat & UART_MSR_RI) ? "RI" : ""); + } + return 0; +} +static DEVICE_ATTR(msignals, S_IRUSR, dgnc_tty_msignals_show, NULL); + + +static ssize_t dgnc_tty_iflag_show(struct device *d, struct device_attribute *attr, char *buf) +{ + struct board_t *bd; + struct channel_t *ch; + struct un_t *un; + + if (!d) + return (0); + un = (struct un_t *) dev_get_drvdata(d); + if (!un || un->magic != DGNC_UNIT_MAGIC) + return (0); + ch = un->un_ch; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return (0); + bd = ch->ch_bd; + if (!bd || bd->magic != DGNC_BOARD_MAGIC) + return (0); + if (bd->state != BOARD_READY) + return (0); + + return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_iflag); +} +static DEVICE_ATTR(iflag, S_IRUSR, dgnc_tty_iflag_show, NULL); + + +static ssize_t dgnc_tty_cflag_show(struct device *d, struct device_attribute *attr, char *buf) +{ + struct board_t *bd; + struct channel_t *ch; + struct un_t *un; + + if (!d) + return (0); + un = (struct un_t *) dev_get_drvdata(d); + if (!un || un->magic != DGNC_UNIT_MAGIC) + return (0); + ch = un->un_ch; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return (0); + bd = ch->ch_bd; + if (!bd || bd->magic != DGNC_BOARD_MAGIC) + return (0); + if (bd->state != BOARD_READY) + return (0); + + return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_cflag); +} +static DEVICE_ATTR(cflag, S_IRUSR, dgnc_tty_cflag_show, NULL); + + +static ssize_t dgnc_tty_oflag_show(struct device *d, struct device_attribute *attr, char *buf) +{ + struct board_t *bd; + struct channel_t *ch; + struct un_t *un; + + if (!d) + return (0); + un = (struct un_t *) dev_get_drvdata(d); + if (!un || un->magic != DGNC_UNIT_MAGIC) + return (0); + ch = un->un_ch; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return (0); + bd = ch->ch_bd; + if (!bd || bd->magic != DGNC_BOARD_MAGIC) + return (0); + if (bd->state != BOARD_READY) + return (0); + + return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_oflag); +} +static DEVICE_ATTR(oflag, S_IRUSR, dgnc_tty_oflag_show, NULL); + + +static ssize_t dgnc_tty_lflag_show(struct device *d, struct device_attribute *attr, char *buf) +{ + struct board_t *bd; + struct channel_t *ch; + struct un_t *un; + + if (!d) + return (0); + un = (struct un_t *) dev_get_drvdata(d); + if (!un || un->magic != DGNC_UNIT_MAGIC) + return (0); + ch = un->un_ch; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return (0); + bd = ch->ch_bd; + if (!bd || bd->magic != DGNC_BOARD_MAGIC) + return (0); + if (bd->state != BOARD_READY) + return (0); + + return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_lflag); +} +static DEVICE_ATTR(lflag, S_IRUSR, dgnc_tty_lflag_show, NULL); + + +static ssize_t dgnc_tty_digi_flag_show(struct device *d, struct device_attribute *attr, char *buf) +{ + struct board_t *bd; + struct channel_t *ch; + struct un_t *un; + + if (!d) + return (0); + un = (struct un_t *) dev_get_drvdata(d); + if (!un || un->magic != DGNC_UNIT_MAGIC) + return (0); + ch = un->un_ch; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return (0); + bd = ch->ch_bd; + if (!bd || bd->magic != DGNC_BOARD_MAGIC) + return (0); + if (bd->state != BOARD_READY) + return (0); + + return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_digi.digi_flags); +} +static DEVICE_ATTR(digi_flag, S_IRUSR, dgnc_tty_digi_flag_show, NULL); + + +static ssize_t dgnc_tty_rxcount_show(struct device *d, struct device_attribute *attr, char *buf) +{ + struct board_t *bd; + struct channel_t *ch; + struct un_t *un; + + if (!d) + return (0); + un = (struct un_t *) dev_get_drvdata(d); + if (!un || un->magic != DGNC_UNIT_MAGIC) + return (0); + ch = un->un_ch; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return (0); + bd = ch->ch_bd; + if (!bd || bd->magic != DGNC_BOARD_MAGIC) + return (0); + if (bd->state != BOARD_READY) + return (0); + + return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_rxcount); +} +static DEVICE_ATTR(rxcount, S_IRUSR, dgnc_tty_rxcount_show, NULL); + + +static ssize_t dgnc_tty_txcount_show(struct device *d, struct device_attribute *attr, char *buf) +{ + struct board_t *bd; + struct channel_t *ch; + struct un_t *un; + + if (!d) + return (0); + un = (struct un_t *) dev_get_drvdata(d); + if (!un || un->magic != DGNC_UNIT_MAGIC) + return (0); + ch = un->un_ch; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return (0); + bd = ch->ch_bd; + if (!bd || bd->magic != DGNC_BOARD_MAGIC) + return (0); + if (bd->state != BOARD_READY) + return (0); + + return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_txcount); +} +static DEVICE_ATTR(txcount, S_IRUSR, dgnc_tty_txcount_show, NULL); + + +static ssize_t dgnc_tty_name_show(struct device *d, struct device_attribute *attr, char *buf) +{ + struct board_t *bd; + struct channel_t *ch; + struct un_t *un; + + if (!d) + return (0); + un = (struct un_t *) dev_get_drvdata(d); + if (!un || un->magic != DGNC_UNIT_MAGIC) + return (0); + ch = un->un_ch; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return (0); + bd = ch->ch_bd; + if (!bd || bd->magic != DGNC_BOARD_MAGIC) + return (0); + if (bd->state != BOARD_READY) + return (0); + + return snprintf(buf, PAGE_SIZE, "%sn%d%c\n", + (un->un_type == DGNC_PRINT) ? "pr" : "tty", + bd->boardnum + 1, 'a' + ch->ch_portnum); +} +static DEVICE_ATTR(custom_name, S_IRUSR, dgnc_tty_name_show, NULL); + + +static struct attribute *dgnc_sysfs_tty_entries[] = { + &dev_attr_state.attr, + &dev_attr_baud.attr, + &dev_attr_msignals.attr, + &dev_attr_iflag.attr, + &dev_attr_cflag.attr, + &dev_attr_oflag.attr, + &dev_attr_lflag.attr, + &dev_attr_digi_flag.attr, + &dev_attr_rxcount.attr, + &dev_attr_txcount.attr, + &dev_attr_custom_name.attr, + NULL +}; + + +static struct attribute_group dgnc_tty_attribute_group = { + .name = NULL, + .attrs = dgnc_sysfs_tty_entries, +}; + + +void dgnc_create_tty_sysfs(struct un_t *un, struct device *c) +{ + int ret; + + ret = sysfs_create_group(&c->kobj, &dgnc_tty_attribute_group); + if (ret) { + printk(KERN_ERR "dgnc: failed to create sysfs tty device attributes.\n"); + sysfs_remove_group(&c->kobj, &dgnc_tty_attribute_group); + return; + } + + dev_set_drvdata(c, un); + +} + + +void dgnc_remove_tty_sysfs(struct device *c) +{ + sysfs_remove_group(&c->kobj, &dgnc_tty_attribute_group); +} + diff --git a/drivers/staging/dgnc/dgnc_sysfs.h b/drivers/staging/dgnc/dgnc_sysfs.h new file mode 100644 index 000000000000..fe991103668c --- /dev/null +++ b/drivers/staging/dgnc/dgnc_sysfs.h @@ -0,0 +1,49 @@ +/* + * Copyright 2003 Digi International (www.digi.com) + * Scott H Kilau + * + * 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, EXPRESS OR IMPLIED; 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. + * + * NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!! + */ + +#ifndef __DGNC_SYSFS_H +#define __DGNC_SYSFS_H + +#include "dgnc_driver.h" + +#include + +struct board_t; +struct channel_t; +struct un_t; +struct pci_driver; +struct class_device; + +extern void dgnc_create_ports_sysfiles(struct board_t *bd); +extern void dgnc_remove_ports_sysfiles(struct board_t *bd); + +extern void dgnc_create_driver_sysfiles(struct pci_driver *); +extern void dgnc_remove_driver_sysfiles(struct pci_driver *); + +extern int dgnc_tty_class_init(void); +extern int dgnc_tty_class_destroy(void); + +extern void dgnc_create_tty_sysfs(struct un_t *un, struct device *c); +extern void dgnc_remove_tty_sysfs(struct device *c); + + + +#endif diff --git a/drivers/staging/dgnc/dgnc_trace.c b/drivers/staging/dgnc/dgnc_trace.c new file mode 100644 index 000000000000..ea710e565798 --- /dev/null +++ b/drivers/staging/dgnc/dgnc_trace.c @@ -0,0 +1,187 @@ +/* + * Copyright 2003 Digi International (www.digi.com) + * Scott H Kilau + * + * 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, EXPRESS OR IMPLIED; 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. + * + * + * NOTE TO LINUX KERNEL HACKERS: DO NOT REFORMAT THIS CODE! + * + * This is shared code between Digi's CVS archive and the + * Linux Kernel sources. + * Changing the source just for reformatting needlessly breaks + * our CVS diff history. + * + * Send any bug fixes/changes to: Eng.Linux at digi dot com. + * Thank you. + * + */ + +/* $Id: dgnc_trace.c,v 1.1.1.1 2009/05/20 12:19:19 markh Exp $ */ + +#include +#include +#include /* For jiffies, task states */ +#include /* For tasklet and interrupt structs/defines */ +#include + +#include "dgnc_driver.h" + +#define TRC_TO_CONSOLE 1 + +/* file level globals */ +static char *dgnc_trcbuf; /* the ringbuffer */ + +#if defined(TRC_TO_KMEM) +static int dgnc_trcbufi = 0; /* index of the tilde at the end of */ +#endif + +#if defined(TRC_TO_KMEM) +static DEFINE_SPINLOCK(dgnc_tracef_lock); +#endif + + +#if 0 + +#if !defined(TRC_TO_KMEM) && !defined(TRC_TO_CONSOLE) + +void dgnc_tracef(const char *fmt, ...) +{ + return; +} + +#else /* !defined(TRC_TO_KMEM) && !defined(TRC_TO_CONSOLE) */ + +void dgnc_tracef(const char *fmt, ...) +{ + va_list ap; + char buf[TRC_MAXMSG+1]; + size_t lenbuf; + int i; + static int failed = FALSE; +# if defined(TRC_TO_KMEM) + unsigned long flags; +#endif + + if(failed) + return; +# if defined(TRC_TO_KMEM) + DGNC_LOCK(dgnc_tracef_lock, flags); +#endif + + /* Format buf using fmt and arguments contained in ap. */ + va_start(ap, fmt); + i = vsprintf(buf, fmt, ap); + va_end(ap); + lenbuf = strlen(buf); + +# if defined(TRC_TO_KMEM) + { + static int initd=0; + + /* + * Now, in addition to (or instead of) printing this stuff out + * (which is a buffered operation), also tuck it away into a + * corner of memory which can be examined post-crash in kdb. + */ + if (!initd) { + dgnc_trcbuf = (char *) vmalloc(dgnc_trcbuf_size); + if(!dgnc_trcbuf) { + failed = TRUE; + printk("dgnc: tracing init failed!\n"); + return; + } + + memset(dgnc_trcbuf, '\0', dgnc_trcbuf_size); + dgnc_trcbufi = 0; + initd++; + + printk("dgnc: tracing enabled - " TRC_DTRC + " 0x%lx 0x%x\n", + (unsigned long)dgnc_trcbuf, + dgnc_trcbuf_size); + } + +# if defined(TRC_ON_OVERFLOW_WRAP_AROUND) + /* + * This is the less CPU-intensive way to do things. We simply + * wrap around before we fall off the end of the buffer. A + * tilde (~) demarcates the current end of the trace. + * + * This method should be used if you are concerned about race + * conditions as it is less likely to affect the timing of + * things. + */ + + if (dgnc_trcbufi + lenbuf >= dgnc_trcbuf_size) { + /* We are wrapping, so wipe out the last tilde. */ + dgnc_trcbuf[dgnc_trcbufi] = '\0'; + /* put the new string at the beginning of the buffer */ + dgnc_trcbufi = 0; + } + + strcpy(&dgnc_trcbuf[dgnc_trcbufi], buf); + dgnc_trcbufi += lenbuf; + dgnc_trcbuf[dgnc_trcbufi] = '~'; + +# elif defined(TRC_ON_OVERFLOW_SHIFT_BUFFER) + /* + * This is the more CPU-intensive way to do things. If we + * venture into the last 1/8 of the buffer, we shift the + * last 7/8 of the buffer forward, wiping out the first 1/8. + * Advantage: No wrap-around, only truncation from the + * beginning. + * + * This method should not be used if you are concerned about + * timing changes affecting the behaviour of the driver (ie, + * race conditions). + */ + strcpy(&dgnc_trcbuf[dgnc_trcbufi], buf); + dgnc_trcbufi += lenbuf; + dgnc_trcbuf[dgnc_trcbufi] = '~'; + dgnc_trcbuf[dgnc_trcbufi+1] = '\0'; + + /* If we're near the end of the trace buffer... */ + if (dgnc_trcbufi > (dgnc_trcbuf_size/8)*7) { + /* Wipe out the first eighth to make some more room. */ + strcpy(dgnc_trcbuf, &dgnc_trcbuf[dgnc_trcbuf_size/8]); + dgnc_trcbufi = strlen(dgnc_trcbuf)-1; + /* Plop overflow message at the top of the buffer. */ + bcopy(TRC_OVERFLOW, dgnc_trcbuf, strlen(TRC_OVERFLOW)); + } +# else +# error "TRC_ON_OVERFLOW_WRAP_AROUND or TRC_ON_OVERFLOW_SHIFT_BUFFER?" +# endif + } + DGNC_UNLOCK(dgnc_tracef_lock, flags); + +# endif /* defined(TRC_TO_KMEM) */ +} + +#endif /* !defined(TRC_TO_KMEM) && !defined(TRC_TO_CONSOLE) */ + +#endif + + +/* + * dgnc_tracer_free() + * + * + */ +void dgnc_tracer_free(void) +{ + if(dgnc_trcbuf) + vfree(dgnc_trcbuf); +} diff --git a/drivers/staging/dgnc/dgnc_trace.h b/drivers/staging/dgnc/dgnc_trace.h new file mode 100644 index 000000000000..1e8870bf8eee --- /dev/null +++ b/drivers/staging/dgnc/dgnc_trace.h @@ -0,0 +1,45 @@ +/* + * Copyright 2003 Digi International (www.digi.com) + * Scott H Kilau + * + * 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, EXPRESS OR IMPLIED; 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. + * + * NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!! + * + ***************************************************************************** + * Header file for dgnc_trace.c + * + * $Id: dgnc_trace.h,v 1.1.1.1 2009/05/20 12:19:19 markh Exp $ + */ + +#ifndef __DGNC_TRACE_H +#define __DGNC_TRACE_H + +#include "dgnc_driver.h" + +#if 0 + +# if !defined(TRC_TO_KMEM) && !defined(TRC_TO_CONSOLE) + void dgnc_tracef(const char *fmt, ...); +# else + void dgnc_tracef(const char *fmt, ...); +# endif + +#endif + +void dgnc_tracer_free(void); + +#endif + diff --git a/drivers/staging/dgnc/dgnc_tty.c b/drivers/staging/dgnc/dgnc_tty.c new file mode 100644 index 000000000000..461e88161808 --- /dev/null +++ b/drivers/staging/dgnc/dgnc_tty.c @@ -0,0 +1,3648 @@ +/* + * Copyright 2003 Digi International (www.digi.com) + * Scott H Kilau + * + * 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, EXPRESS OR IMPLIED; 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. + * + * + * NOTE TO LINUX KERNEL HACKERS: DO NOT REFORMAT THIS CODE! + * + * This is shared code between Digi's CVS archive and the + * Linux Kernel sources. + * Changing the source just for reformatting needlessly breaks + * our CVS diff history. + * + * Send any bug fixes/changes to: Eng.Linux at digi dot com. + * Thank you. + */ + +/************************************************************************ + * + * This file implements the tty driver functionality for the + * Neo and ClassicBoard PCI based product lines. + * + ************************************************************************ + * + * $Id: dgnc_tty.c,v 1.5 2013/04/30 19:18:30 markh Exp $ + */ + +#include +#include +#include /* For jiffies, task states */ +#include /* For tasklet and interrupt structs/defines */ +#include +#include +#include +#include +#include +#include +#include /* For udelay */ +#include /* For copy_from_user/copy_to_user */ +#include + +#include "dgnc_driver.h" +#include "dgnc_tty.h" +#include "dgnc_types.h" +#include "dgnc_trace.h" +#include "dgnc_neo.h" +#include "dgnc_cls.h" +#include "dpacompat.h" +#include "dgnc_sysfs.h" + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) +#define init_MUTEX(sem) sema_init(sem, 1) +#define DECLARE_MUTEX(name) \ + struct semaphore name = __SEMAPHORE_INITIALIZER(name, 1) +#endif + +/* + * internal variables + */ +static struct board_t *dgnc_BoardsByMajor[256]; +static uchar *dgnc_TmpWriteBuf = NULL; +static DECLARE_MUTEX(dgnc_TmpWriteSem); + +/* + * Default transparent print information. + */ +static struct digi_t dgnc_digi_init = { + .digi_flags = DIGI_COOK, /* Flags */ + .digi_maxcps = 100, /* Max CPS */ + .digi_maxchar = 50, /* Max chars in print queue */ + .digi_bufsize = 100, /* Printer buffer size */ + .digi_onlen = 4, /* size of printer on string */ + .digi_offlen = 4, /* size of printer off string */ + .digi_onstr = "\033[5i", /* ANSI printer on string ] */ + .digi_offstr = "\033[4i", /* ANSI printer off string ] */ + .digi_term = "ansi" /* default terminal type */ +}; + + +/* + * Define a local default termios struct. All ports will be created + * with this termios initially. + * + * This defines a raw port at 9600 baud, 8 data bits, no parity, + * 1 stop bit. + */ +static struct ktermios DgncDefaultTermios = +{ + .c_iflag = (DEFAULT_IFLAGS), /* iflags */ + .c_oflag = (DEFAULT_OFLAGS), /* oflags */ + .c_cflag = (DEFAULT_CFLAGS), /* cflags */ + .c_lflag = (DEFAULT_LFLAGS), /* lflags */ + .c_cc = INIT_C_CC, + .c_line = 0, +}; + + +/* Our function prototypes */ +static int dgnc_tty_open(struct tty_struct *tty, struct file *file); +static void dgnc_tty_close(struct tty_struct *tty, struct file *file); +static int dgnc_block_til_ready(struct tty_struct *tty, struct file *file, struct channel_t *ch); +static int dgnc_tty_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); +static int dgnc_tty_digigeta(struct tty_struct *tty, struct digi_t __user *retinfo); +static int dgnc_tty_digiseta(struct tty_struct *tty, struct digi_t __user *new_info); +static int dgnc_tty_write_room(struct tty_struct* tty); +static int dgnc_tty_put_char(struct tty_struct *tty, unsigned char c); +static int dgnc_tty_chars_in_buffer(struct tty_struct* tty); +static void dgnc_tty_start(struct tty_struct *tty); +static void dgnc_tty_stop(struct tty_struct *tty); +static void dgnc_tty_throttle(struct tty_struct *tty); +static void dgnc_tty_unthrottle(struct tty_struct *tty); +static void dgnc_tty_flush_chars(struct tty_struct *tty); +static void dgnc_tty_flush_buffer(struct tty_struct *tty); +static void dgnc_tty_hangup(struct tty_struct *tty); +static int dgnc_set_modem_info(struct tty_struct *tty, unsigned int command, unsigned int __user *value); +static int dgnc_get_modem_info(struct channel_t *ch, unsigned int __user *value); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39) +static int dgnc_tty_tiocmget(struct tty_struct *tty); +static int dgnc_tty_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); +#else +static int dgnc_tty_tiocmget(struct tty_struct *tty, struct file *file); +static int dgnc_tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); +#endif +static int dgnc_tty_send_break(struct tty_struct *tty, int msec); +static void dgnc_tty_wait_until_sent(struct tty_struct *tty, int timeout); +static int dgnc_tty_write(struct tty_struct *tty, const unsigned char *buf, int count); +static void dgnc_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios); +static void dgnc_tty_send_xchar(struct tty_struct *tty, char ch); + + +static const struct tty_operations dgnc_tty_ops = { + .open = dgnc_tty_open, + .close = dgnc_tty_close, + .write = dgnc_tty_write, + .write_room = dgnc_tty_write_room, + .flush_buffer = dgnc_tty_flush_buffer, + .chars_in_buffer = dgnc_tty_chars_in_buffer, + .flush_chars = dgnc_tty_flush_chars, + .ioctl = dgnc_tty_ioctl, + .set_termios = dgnc_tty_set_termios, + .stop = dgnc_tty_stop, + .start = dgnc_tty_start, + .throttle = dgnc_tty_throttle, + .unthrottle = dgnc_tty_unthrottle, + .hangup = dgnc_tty_hangup, + .put_char = dgnc_tty_put_char, + .tiocmget = dgnc_tty_tiocmget, + .tiocmset = dgnc_tty_tiocmset, + .break_ctl = dgnc_tty_send_break, + .wait_until_sent = dgnc_tty_wait_until_sent, + .send_xchar = dgnc_tty_send_xchar +}; + +/************************************************************************ + * + * TTY Initialization/Cleanup Functions + * + ************************************************************************/ + +/* + * dgnc_tty_preinit() + * + * Initialize any global tty related data before we download any boards. + */ +int dgnc_tty_preinit(void) +{ + /* + * Allocate a buffer for doing the copy from user space to + * kernel space in dgnc_write(). We only use one buffer and + * control access to it with a semaphore. If we are paging, we + * are already in trouble so one buffer won't hurt much anyway. + * + * We are okay to sleep in the malloc, as this routine + * is only called during module load, (not in interrupt context), + * and with no locks held. + */ + dgnc_TmpWriteBuf = kmalloc(WRITEBUFLEN, GFP_KERNEL); + + if (!dgnc_TmpWriteBuf) { + DPR_INIT(("unable to allocate tmp write buf")); + return (-ENOMEM); + } + + return(0); +} + + +/* + * dgnc_tty_register() + * + * Init the tty subsystem for this board. + */ +int dgnc_tty_register(struct board_t *brd) +{ + int rc = 0; + + DPR_INIT(("tty_register start\n")); + + memset(&brd->SerialDriver, 0, sizeof(struct tty_driver)); + memset(&brd->PrintDriver, 0, sizeof(struct tty_driver)); + + brd->SerialDriver.magic = TTY_DRIVER_MAGIC; + + snprintf(brd->SerialName, MAXTTYNAMELEN, "tty_dgnc_%d_", brd->boardnum); + + brd->SerialDriver.name = brd->SerialName; + brd->SerialDriver.name_base = 0; + brd->SerialDriver.major = 0; + brd->SerialDriver.minor_start = 0; + brd->SerialDriver.num = brd->maxports; + brd->SerialDriver.type = TTY_DRIVER_TYPE_SERIAL; + brd->SerialDriver.subtype = SERIAL_TYPE_NORMAL; + brd->SerialDriver.init_termios = DgncDefaultTermios; + brd->SerialDriver.driver_name = DRVSTR; + brd->SerialDriver.flags = (TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK); + + /* + * The kernel wants space to store pointers to + * tty_struct's and termios's. + */ + brd->SerialDriver.ttys = dgnc_driver_kzmalloc(brd->maxports * sizeof(struct tty_struct *), GFP_KERNEL); + if (!brd->SerialDriver.ttys) + return(-ENOMEM); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) + brd->SerialDriver.refcount = brd->TtyRefCnt; +#else + kref_init(&brd->SerialDriver.kref); +#endif + + brd->SerialDriver.termios = dgnc_driver_kzmalloc(brd->maxports * sizeof(struct ktermios *), GFP_KERNEL); + if (!brd->SerialDriver.termios) + return(-ENOMEM); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) + brd->SerialDriver.termios_locked = dgnc_driver_kzmalloc(brd->maxports * sizeof(struct ktermios *), GFP_KERNEL); + if (!brd->SerialDriver.termios_locked) + return(-ENOMEM); +#endif + /* + * Entry points for driver. Called by the kernel from + * tty_io.c and n_tty.c. + */ + tty_set_operations(&brd->SerialDriver, &dgnc_tty_ops); + + if (!brd->dgnc_Major_Serial_Registered) { + /* Register tty devices */ + rc = tty_register_driver(&brd->SerialDriver); + if (rc < 0) { + APR(("Can't register tty device (%d)\n", rc)); + return(rc); + } + brd->dgnc_Major_Serial_Registered = TRUE; + } + + /* + * If we're doing transparent print, we have to do all of the above + * again, seperately so we don't get the LD confused about what major + * we are when we get into the dgnc_tty_open() routine. + */ + brd->PrintDriver.magic = TTY_DRIVER_MAGIC; + snprintf(brd->PrintName, MAXTTYNAMELEN, "pr_dgnc_%d_", brd->boardnum); + + brd->PrintDriver.name = brd->PrintName; + brd->PrintDriver.name_base = 0; + brd->PrintDriver.major = brd->SerialDriver.major; + brd->PrintDriver.minor_start = 0x80; + brd->PrintDriver.num = brd->maxports; + brd->PrintDriver.type = TTY_DRIVER_TYPE_SERIAL; + brd->PrintDriver.subtype = SERIAL_TYPE_NORMAL; + brd->PrintDriver.init_termios = DgncDefaultTermios; + brd->PrintDriver.driver_name = DRVSTR; + brd->PrintDriver.flags = (TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK); + + /* + * The kernel wants space to store pointers to + * tty_struct's and termios's. Must be seperate from + * the Serial Driver so we don't get confused + */ + brd->PrintDriver.ttys = dgnc_driver_kzmalloc(brd->maxports * sizeof(struct tty_struct *), GFP_KERNEL); + if (!brd->PrintDriver.ttys) + return(-ENOMEM); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) + brd->PrintDriver.refcount = brd->TtyRefCnt; +#else + kref_init(&brd->PrintDriver.kref); +#endif + + brd->PrintDriver.termios = dgnc_driver_kzmalloc(brd->maxports * sizeof(struct ktermios *), GFP_KERNEL); + if (!brd->PrintDriver.termios) + return(-ENOMEM); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) + brd->PrintDriver.termios_locked = dgnc_driver_kzmalloc(brd->maxports * sizeof(struct ktermios *), GFP_KERNEL); + if (!brd->PrintDriver.termios_locked) + return(-ENOMEM); +#endif + + /* + * Entry points for driver. Called by the kernel from + * tty_io.c and n_tty.c. + */ + tty_set_operations(&brd->PrintDriver, &dgnc_tty_ops); + + if (!brd->dgnc_Major_TransparentPrint_Registered) { + /* Register Transparent Print devices */ + rc = tty_register_driver(&brd->PrintDriver); + if (rc < 0) { + APR(("Can't register Transparent Print device (%d)\n", rc)); + return(rc); + } + brd->dgnc_Major_TransparentPrint_Registered = TRUE; + } + + dgnc_BoardsByMajor[brd->SerialDriver.major] = brd; + brd->dgnc_Serial_Major = brd->SerialDriver.major; + brd->dgnc_TransparentPrint_Major = brd->PrintDriver.major; + + DPR_INIT(("DGNC REGISTER TTY: MAJOR: %d\n", brd->SerialDriver.major)); + + return (rc); +} + + +/* + * dgnc_tty_init() + * + * Init the tty subsystem. Called once per board after board has been + * downloaded and init'ed. + */ +int dgnc_tty_init(struct board_t *brd) +{ + int i; + uchar *vaddr; + struct channel_t *ch; + + if (!brd) + return (-ENXIO); + + DPR_INIT(("dgnc_tty_init start\n")); + + /* + * Initialize board structure elements. + */ + + vaddr = brd->re_map_membase; + + brd->nasync = brd->maxports; + + /* + * Allocate channel memory that might not have been allocated + * when the driver was first loaded. + */ + for (i = 0; i < brd->nasync; i++) { + if (!brd->channels[i]) { + + /* + * Okay to malloc with GFP_KERNEL, we are not at + * interrupt context, and there are no locks held. + */ + brd->channels[i] = dgnc_driver_kzmalloc(sizeof(struct channel_t), GFP_KERNEL); + if (!brd->channels[i]) { + DPR_CORE(("%s:%d Unable to allocate memory for channel struct\n", + __FILE__, __LINE__)); + } + } + } + + ch = brd->channels[0]; + vaddr = brd->re_map_membase; + + /* Set up channel variables */ + for (i = 0; i < brd->nasync; i++, ch = brd->channels[i]) { + + if (!brd->channels[i]) + continue; + + DGNC_SPINLOCK_INIT(ch->ch_lock); + + /* Store all our magic numbers */ + ch->magic = DGNC_CHANNEL_MAGIC; + ch->ch_tun.magic = DGNC_UNIT_MAGIC; + ch->ch_tun.un_ch = ch; + ch->ch_tun.un_type = DGNC_SERIAL; + ch->ch_tun.un_dev = i; + + ch->ch_pun.magic = DGNC_UNIT_MAGIC; + ch->ch_pun.un_ch = ch; + ch->ch_pun.un_type = DGNC_PRINT; + ch->ch_pun.un_dev = i + 128; + + if (brd->bd_uart_offset == 0x200) + ch->ch_neo_uart = (struct neo_uart_struct *) ((ulong) vaddr + (brd->bd_uart_offset * i)); + else + ch->ch_cls_uart = (struct cls_uart_struct *) ((ulong) vaddr + (brd->bd_uart_offset * i)); + + ch->ch_bd = brd; + ch->ch_portnum = i; + ch->ch_digi = dgnc_digi_init; + + /* .25 second delay */ + ch->ch_close_delay = 250; + + init_waitqueue_head(&ch->ch_flags_wait); + init_waitqueue_head(&ch->ch_tun.un_flags_wait); + init_waitqueue_head(&ch->ch_pun.un_flags_wait); + init_waitqueue_head(&ch->ch_sniff_wait); + + { + struct device *classp; + classp = tty_register_device(&brd->SerialDriver, i, + &(ch->ch_bd->pdev->dev)); + ch->ch_tun.un_sysfs = classp; + dgnc_create_tty_sysfs(&ch->ch_tun, classp); + + classp = tty_register_device(&brd->PrintDriver, i, + &(ch->ch_bd->pdev->dev)); + ch->ch_pun.un_sysfs = classp; + dgnc_create_tty_sysfs(&ch->ch_pun, classp); + } + + } + + DPR_INIT(("dgnc_tty_init finish\n")); + + return (0); +} + + +/* + * dgnc_tty_post_uninit() + * + * UnInitialize any global tty related data. + */ +void dgnc_tty_post_uninit(void) +{ + if (dgnc_TmpWriteBuf) { + kfree(dgnc_TmpWriteBuf); + dgnc_TmpWriteBuf = NULL; + } +} + + +/* + * dgnc_tty_uninit() + * + * Uninitialize the TTY portion of this driver. Free all memory and + * resources. + */ +void dgnc_tty_uninit(struct board_t *brd) +{ + int i = 0; + + if (brd->dgnc_Major_Serial_Registered) { + dgnc_BoardsByMajor[brd->SerialDriver.major] = NULL; + brd->dgnc_Serial_Major = 0; + for (i = 0; i < brd->nasync; i++) { + dgnc_remove_tty_sysfs(brd->channels[i]->ch_tun.un_sysfs); + tty_unregister_device(&brd->SerialDriver, i); + } + tty_unregister_driver(&brd->SerialDriver); + brd->dgnc_Major_Serial_Registered = FALSE; + } + + if (brd->dgnc_Major_TransparentPrint_Registered) { + dgnc_BoardsByMajor[brd->PrintDriver.major] = NULL; + brd->dgnc_TransparentPrint_Major = 0; + for (i = 0; i < brd->nasync; i++) { + dgnc_remove_tty_sysfs(brd->channels[i]->ch_pun.un_sysfs); + tty_unregister_device(&brd->PrintDriver, i); + } + tty_unregister_driver(&brd->PrintDriver); + brd->dgnc_Major_TransparentPrint_Registered = FALSE; + } + + if (brd->SerialDriver.ttys) { + kfree(brd->SerialDriver.ttys); + brd->SerialDriver.ttys = NULL; + } + if (brd->PrintDriver.ttys) { + kfree(brd->PrintDriver.ttys); + brd->PrintDriver.ttys = NULL; + } +} + + +#define TMPBUFLEN (1024) + +/* + * dgnc_sniff - Dump data out to the "sniff" buffer if the + * proc sniff file is opened... + */ +void dgnc_sniff_nowait_nolock(struct channel_t *ch, uchar *text, uchar *buf, int len) +{ + struct timeval tv; + int n; + int r; + int nbuf; + int i; + int tmpbuflen; + char tmpbuf[TMPBUFLEN]; + char *p = tmpbuf; + int too_much_data; + + /* Leave if sniff not open */ + if (!(ch->ch_sniff_flags & SNIFF_OPEN)) + return; + + do_gettimeofday(&tv); + + /* Create our header for data dump */ + p += sprintf(p, "<%ld %ld><%s><", tv.tv_sec, tv.tv_usec, text); + tmpbuflen = p - tmpbuf; + + do { + too_much_data = 0; + + for (i = 0; i < len && tmpbuflen < (TMPBUFLEN - 4); i++) { + p += sprintf(p, "%02x ", *buf); + buf++; + tmpbuflen = p - tmpbuf; + } + + if (tmpbuflen < (TMPBUFLEN - 4)) { + if (i > 0) + p += sprintf(p - 1, "%s\n", ">"); + else + p += sprintf(p, "%s\n", ">"); + } else { + too_much_data = 1; + len -= i; + } + + nbuf = strlen(tmpbuf); + p = tmpbuf; + + /* + * Loop while data remains. + */ + while (nbuf > 0 && ch->ch_sniff_buf != 0) { + /* + * Determine the amount of available space left in the + * buffer. If there's none, wait until some appears. + */ + n = (ch->ch_sniff_out - ch->ch_sniff_in - 1) & SNIFF_MASK; + + /* + * If there is no space left to write to in our sniff buffer, + * we have no choice but to drop the data. + * We *cannot* sleep here waiting for space, because this + * function was probably called by the interrupt/timer routines! + */ + if (n == 0) { + return; + } + + /* + * Copy as much data as will fit. + */ + + if (n > nbuf) + n = nbuf; + + r = SNIFF_MAX - ch->ch_sniff_in; + + if (r <= n) { + memcpy(ch->ch_sniff_buf + ch->ch_sniff_in, p, r); + + n -= r; + ch->ch_sniff_in = 0; + p += r; + nbuf -= r; + } + + memcpy(ch->ch_sniff_buf + ch->ch_sniff_in, p, n); + + ch->ch_sniff_in += n; + p += n; + nbuf -= n; + + /* + * Wakeup any thread waiting for data + */ + if (ch->ch_sniff_flags & SNIFF_WAIT_DATA) { + ch->ch_sniff_flags &= ~SNIFF_WAIT_DATA; + wake_up_interruptible(&ch->ch_sniff_wait); + } + } + + /* + * If the user sent us too much data to push into our tmpbuf, + * we need to keep looping around on all the data. + */ + if (too_much_data) { + p = tmpbuf; + tmpbuflen = 0; + } + + } while (too_much_data); +} + + +/*======================================================================= + * + * dgnc_wmove - Write data to transmit queue. + * + * ch - Pointer to channel structure. + * buf - Poiter to characters to be moved. + * n - Number of characters to move. + * + *=======================================================================*/ +static void dgnc_wmove(struct channel_t *ch, char *buf, uint n) +{ + int remain; + uint head; + + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + head = ch->ch_w_head & WQUEUEMASK; + + /* + * If the write wraps over the top of the circular buffer, + * move the portion up to the wrap point, and reset the + * pointers to the bottom. + */ + remain = WQUEUESIZE - head; + + if (n >= remain) { + n -= remain; + memcpy(ch->ch_wqueue + head, buf, remain); + head = 0; + buf += remain; + } + + if (n > 0) { + /* + * Move rest of data. + */ + remain = n; + memcpy(ch->ch_wqueue + head, buf, remain); + head += remain; + } + + head &= WQUEUEMASK; + ch->ch_w_head = head; +} + + + + +/*======================================================================= + * + * dgnc_input - Process received data. + * + * ch - Pointer to channel structure. + * + *=======================================================================*/ +void dgnc_input(struct channel_t *ch) +{ + struct board_t *bd; + struct tty_struct *tp; + struct tty_ldisc *ld; + uint rmask; + ushort head; + ushort tail; + int data_len; + ulong lock_flags; + int flip_len; + int len = 0; + int n = 0; + char *buf = NULL; + int s = 0; + int i = 0; + + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + tp = ch->ch_tun.un_tty; + + bd = ch->ch_bd; + if(!bd || bd->magic != DGNC_BOARD_MAGIC) + return; + + DGNC_LOCK(ch->ch_lock, lock_flags); + + /* + * Figure the number of characters in the buffer. + * Exit immediately if none. + */ + rmask = RQUEUEMASK; + head = ch->ch_r_head & rmask; + tail = ch->ch_r_tail & rmask; + data_len = (head - tail) & rmask; + + if (data_len == 0) { + DGNC_UNLOCK(ch->ch_lock, lock_flags); + return; + } + + DPR_READ(("dgnc_input start\n")); + + /* + * If the device is not open, or CREAD is off, + * flush input data and return immediately. + */ + if (!tp || (tp->magic != TTY_MAGIC) || !(ch->ch_tun.un_flags & UN_ISOPEN) || + !(tp->termios->c_cflag & CREAD) || (ch->ch_tun.un_flags & UN_CLOSING)) { + + DPR_READ(("input. dropping %d bytes on port %d...\n", data_len, ch->ch_portnum)); + DPR_READ(("input. tp: %p tp->magic: %x MAGIC:%x ch flags: %x\n", + tp, tp ? tp->magic : 0, TTY_MAGIC, ch->ch_tun.un_flags)); + + ch->ch_r_head = tail; + + /* Force queue flow control to be released, if needed */ + dgnc_check_queue_flow_control(ch); + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + return; + } + + /* + * If we are throttled, simply don't read any data. + */ + if (ch->ch_flags & CH_FORCED_STOPI) { + DGNC_UNLOCK(ch->ch_lock, lock_flags); + DPR_READ(("Port %d throttled, not reading any data. head: %x tail: %x\n", + ch->ch_portnum, head, tail)); + return; + } + + DPR_READ(("dgnc_input start 2\n")); + + /* Decide how much data we can send into the tty layer */ + if (dgnc_rawreadok && tp->real_raw) + flip_len = MYFLIPLEN; + else + flip_len = TTY_FLIPBUF_SIZE; + + /* Chop down the length, if needed */ + len = min(data_len, flip_len); + len = min(len, (N_TTY_BUF_SIZE - 1) - tp->read_cnt); + + ld = tty_ldisc_ref(tp); + +#ifdef TTY_DONT_FLIP + /* + * If the DONT_FLIP flag is on, don't flush our buffer, and act + * like the ld doesn't have any space to put the data right now. + */ + if (test_bit(TTY_DONT_FLIP, &tp->flags)) + len = 0; +#endif + + /* + * If we were unable to get a reference to the ld, + * don't flush our buffer, and act like the ld doesn't + * have any space to put the data right now. + */ + if (!ld) { + len = 0; + } else { + /* + * If ld doesn't have a pointer to a receive_buf function, + * flush the data, then act like the ld doesn't have any + * space to put the data right now. + */ + if (!ld->ops->receive_buf) { + ch->ch_r_head = ch->ch_r_tail; + len = 0; + } + } + + if (len <= 0) { + DGNC_UNLOCK(ch->ch_lock, lock_flags); + if (ld) + tty_ldisc_deref(ld); + return; + } + + /* + * The tty layer in the kernel has changed in 2.6.16+. + * + * The flip buffers in the tty structure are no longer exposed, + * and probably will be going away eventually. + * + * If we are completely raw, we don't need to go through a lot + * of the tty layers that exist. + * In this case, we take the shortest and fastest route we + * can to relay the data to the user. + * + * On the other hand, if we are not raw, we need to go through + * the new 2.6.16+ tty layer, which has its API more well defined. + */ + if (dgnc_rawreadok && tp->real_raw) { + + if (ch->ch_flags & CH_FLIPBUF_IN_USE) { + DPR_READ(("DGNC - FLIPBUF in use. delaying input\n")); + DGNC_UNLOCK(ch->ch_lock, lock_flags); + if (ld) + tty_ldisc_deref(ld); + return; + } + + ch->ch_flags |= CH_FLIPBUF_IN_USE; + buf = ch->ch_bd->flipbuf; + + n = len; + + /* + * n now contains the most amount of data we can copy, + * bounded either by the flip buffer size or the amount + * of data the card actually has pending... + */ + while (n) { + s = ((head >= tail) ? head : RQUEUESIZE) - tail; + s = min(s, n); + + if (s <= 0) + break; + + memcpy(buf, ch->ch_rqueue + tail, s); + dgnc_sniff_nowait_nolock(ch, "USER READ", ch->ch_rqueue + tail, s); + + tail += s; + buf += s; + + n -= s; + /* Flip queue if needed */ + tail &= rmask; + } + + ch->ch_r_tail = tail & rmask; + ch->ch_e_tail = tail & rmask; + + dgnc_check_queue_flow_control(ch); + + /* !!! WE *MUST* LET GO OF ALL LOCKS BEFORE CALLING RECEIVE BUF !!! */ + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + DPR_READ(("dgnc_input. %d real_raw len:%d calling receive_buf for buffer for board %d\n", + __LINE__, len, ch->ch_bd->boardnum)); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) + tp->ldisc->ops->receive_buf(tp, ch->ch_bd->flipbuf, NULL, len); +#else + tp->ldisc.ops->receive_buf(tp, ch->ch_bd->flipbuf, NULL, len); +#endif + + /* Allow use of channel flip buffer again */ + DGNC_LOCK(ch->ch_lock, lock_flags); + ch->ch_flags &= ~CH_FLIPBUF_IN_USE; + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + } + else { + len = tty_buffer_request_room(tp, len); + n = len; + + /* + * n now contains the most amount of data we can copy, + * bounded either by how much the Linux tty layer can handle, + * or the amount of data the card actually has pending... + */ + while (n) { + s = ((head >= tail) ? head : RQUEUESIZE) - tail; + s = min(s, n); + + if (s <= 0) + break; + + /* + * If conditions are such that ld needs to see all + * UART errors, we will have to walk each character + * and error byte and send them to the buffer one at + * a time. + */ + if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) { + for (i = 0; i < s; i++) { + if (*(ch->ch_equeue + tail + i) & UART_LSR_BI) + tty_insert_flip_char(tp, *(ch->ch_rqueue + tail + i), TTY_BREAK); + else if (*(ch->ch_equeue + tail + i) & UART_LSR_PE) + tty_insert_flip_char(tp, *(ch->ch_rqueue + tail + i), TTY_PARITY); + else if (*(ch->ch_equeue + tail + i) & UART_LSR_FE) + tty_insert_flip_char(tp, *(ch->ch_rqueue + tail + i), TTY_FRAME); + else + tty_insert_flip_char(tp, *(ch->ch_rqueue + tail + i), TTY_NORMAL); + } + } + else { + tty_insert_flip_string(tp, ch->ch_rqueue + tail, s); + } + + dgnc_sniff_nowait_nolock(ch, "USER READ", ch->ch_rqueue + tail, s); + + tail += s; + n -= s; + /* Flip queue if needed */ + tail &= rmask; + } + + ch->ch_r_tail = tail & rmask; + ch->ch_e_tail = tail & rmask; + dgnc_check_queue_flow_control(ch); + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + /* Tell the tty layer its okay to "eat" the data now */ + tty_flip_buffer_push(tp); + } + + if (ld) + tty_ldisc_deref(ld); + + DPR_READ(("dgnc_input - finish\n")); +} + + +/************************************************************************ + * Determines when CARRIER changes state and takes appropriate + * action. + ************************************************************************/ +void dgnc_carrier(struct channel_t *ch) +{ + struct board_t *bd; + + int virt_carrier = 0; + int phys_carrier = 0; + + DPR_CARR(("dgnc_carrier called...\n")); + + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + bd = ch->ch_bd; + + if (!bd || bd->magic != DGNC_BOARD_MAGIC) + return; + + if (ch->ch_mistat & UART_MSR_DCD) { + DPR_CARR(("mistat: %x D_CD: %x\n", ch->ch_mistat, ch->ch_mistat & UART_MSR_DCD)); + phys_carrier = 1; + } + + if (ch->ch_digi.digi_flags & DIGI_FORCEDCD) { + virt_carrier = 1; + } + + if (ch->ch_c_cflag & CLOCAL) { + virt_carrier = 1; + } + + + DPR_CARR(("DCD: physical: %d virt: %d\n", phys_carrier, virt_carrier)); + + /* + * Test for a VIRTUAL carrier transition to HIGH. + */ + if (((ch->ch_flags & CH_FCAR) == 0) && (virt_carrier == 1)) { + + /* + * When carrier rises, wake any threads waiting + * for carrier in the open routine. + */ + + DPR_CARR(("carrier: virt DCD rose\n")); + + if (waitqueue_active(&(ch->ch_flags_wait))) + wake_up_interruptible(&ch->ch_flags_wait); + } + + /* + * Test for a PHYSICAL carrier transition to HIGH. + */ + if (((ch->ch_flags & CH_CD) == 0) && (phys_carrier == 1)) { + + /* + * When carrier rises, wake any threads waiting + * for carrier in the open routine. + */ + + DPR_CARR(("carrier: physical DCD rose\n")); + + if (waitqueue_active(&(ch->ch_flags_wait))) + wake_up_interruptible(&ch->ch_flags_wait); + } + + /* + * Test for a PHYSICAL transition to low, so long as we aren't + * currently ignoring physical transitions (which is what "virtual + * carrier" indicates). + * + * The transition of the virtual carrier to low really doesn't + * matter... it really only means "ignore carrier state", not + * "make pretend that carrier is there". + */ + if ((virt_carrier == 0) && ((ch->ch_flags & CH_CD) != 0) && + (phys_carrier == 0)) + { + + /* + * When carrier drops: + * + * Drop carrier on all open units. + * + * Flush queues, waking up any task waiting in the + * line discipline. + * + * Send a hangup to the control terminal. + * + * Enable all select calls. + */ + if (waitqueue_active(&(ch->ch_flags_wait))) + wake_up_interruptible(&ch->ch_flags_wait); + + if (ch->ch_tun.un_open_count > 0) { + DPR_CARR(("Sending tty hangup\n")); + tty_hangup(ch->ch_tun.un_tty); + } + + if (ch->ch_pun.un_open_count > 0) { + DPR_CARR(("Sending pr hangup\n")); + tty_hangup(ch->ch_pun.un_tty); + } + } + + /* + * Make sure that our cached values reflect the current reality. + */ + if (virt_carrier == 1) + ch->ch_flags |= CH_FCAR; + else + ch->ch_flags &= ~CH_FCAR; + + if (phys_carrier == 1) + ch->ch_flags |= CH_CD; + else + ch->ch_flags &= ~CH_CD; +} + +/* + * Assign the custom baud rate to the channel structure + */ +static void dgnc_set_custom_speed(struct channel_t *ch, uint newrate) +{ + int testdiv; + int testrate_high; + int testrate_low; + int deltahigh; + int deltalow; + + if (newrate < 0) + newrate = 0; + + /* + * Since the divisor is stored in a 16-bit integer, we make sure + * we don't allow any rates smaller than a 16-bit integer would allow. + * And of course, rates above the dividend won't fly. + */ + if (newrate && newrate < ((ch->ch_bd->bd_dividend / 0xFFFF) + 1)) + newrate = ((ch->ch_bd->bd_dividend / 0xFFFF) + 1); + + if (newrate && newrate > ch->ch_bd->bd_dividend) + newrate = ch->ch_bd->bd_dividend; + + while (newrate > 0) { + testdiv = ch->ch_bd->bd_dividend / newrate; + + /* + * If we try to figure out what rate the board would use + * with the test divisor, it will be either equal or higher + * than the requested baud rate. If we then determine the + * rate with a divisor one higher, we will get the next lower + * supported rate below the requested. + */ + testrate_high = ch->ch_bd->bd_dividend / testdiv; + testrate_low = ch->ch_bd->bd_dividend / (testdiv + 1); + + /* + * If the rate for the requested divisor is correct, just + * use it and be done. + */ + if (testrate_high == newrate ) + break; + + /* + * Otherwise, pick the rate that is closer (i.e. whichever rate + * has a smaller delta). + */ + deltahigh = testrate_high - newrate; + deltalow = newrate - testrate_low; + + if (deltahigh < deltalow) { + newrate = testrate_high; + } else { + newrate = testrate_low; + } + + break; + } + + ch->ch_custom_speed = newrate; + + return; +} + + +void dgnc_check_queue_flow_control(struct channel_t *ch) +{ + int qleft = 0; + + /* Store how much space we have left in the queue */ + if ((qleft = ch->ch_r_tail - ch->ch_r_head - 1) < 0) + qleft += RQUEUEMASK + 1; + + /* + * Check to see if we should enforce flow control on our queue because + * the ld (or user) isn't reading data out of our queue fast enuf. + * + * NOTE: This is done based on what the current flow control of the + * port is set for. + * + * 1) HWFLOW (RTS) - Turn off the UART's Receive interrupt. + * This will cause the UART's FIFO to back up, and force + * the RTS signal to be dropped. + * 2) SWFLOW (IXOFF) - Keep trying to send a stop character to + * the other side, in hopes it will stop sending data to us. + * 3) NONE - Nothing we can do. We will simply drop any extra data + * that gets sent into us when the queue fills up. + */ + if (qleft < 256) { + /* HWFLOW */ + if (ch->ch_digi.digi_flags & CTSPACE || ch->ch_c_cflag & CRTSCTS) { + if(!(ch->ch_flags & CH_RECEIVER_OFF)) { + ch->ch_bd->bd_ops->disable_receiver(ch); + ch->ch_flags |= (CH_RECEIVER_OFF); + DPR_READ(("Internal queue hit hilevel mark (%d)! Turning off interrupts.\n", + qleft)); + } + } + /* SWFLOW */ + else if (ch->ch_c_iflag & IXOFF) { + if (ch->ch_stops_sent <= MAX_STOPS_SENT) { + ch->ch_bd->bd_ops->send_stop_character(ch); + ch->ch_stops_sent++; + DPR_READ(("Sending stop char! Times sent: %x\n", ch->ch_stops_sent)); + } + } + /* No FLOW */ + else { + /* Empty... Can't do anything about the impending overflow... */ + } + } + + /* + * Check to see if we should unenforce flow control because + * ld (or user) finally read enuf data out of our queue. + * + * NOTE: This is done based on what the current flow control of the + * port is set for. + * + * 1) HWFLOW (RTS) - Turn back on the UART's Receive interrupt. + * This will cause the UART's FIFO to raise RTS back up, + * which will allow the other side to start sending data again. + * 2) SWFLOW (IXOFF) - Send a start character to + * the other side, so it will start sending data to us again. + * 3) NONE - Do nothing. Since we didn't do anything to turn off the + * other side, we don't need to do anything now. + */ + if (qleft > (RQUEUESIZE / 2)) { + /* HWFLOW */ + if (ch->ch_digi.digi_flags & RTSPACE || ch->ch_c_cflag & CRTSCTS) { + if (ch->ch_flags & CH_RECEIVER_OFF) { + ch->ch_bd->bd_ops->enable_receiver(ch); + ch->ch_flags &= ~(CH_RECEIVER_OFF); + DPR_READ(("Internal queue hit lowlevel mark (%d)! Turning on interrupts.\n", + qleft)); + } + } + /* SWFLOW */ + else if (ch->ch_c_iflag & IXOFF && ch->ch_stops_sent) { + ch->ch_stops_sent = 0; + ch->ch_bd->bd_ops->send_start_character(ch); + DPR_READ(("Sending start char!\n")); + } + /* No FLOW */ + else { + /* Nothing needed. */ + } + } +} + + +void dgnc_wakeup_writes(struct channel_t *ch) +{ + int qlen = 0; + ulong lock_flags; + + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + DGNC_LOCK(ch->ch_lock, lock_flags); + + /* + * If channel now has space, wake up anyone waiting on the condition. + */ + if ((qlen = ch->ch_w_head - ch->ch_w_tail) < 0) + qlen += WQUEUESIZE; + + if (qlen >= (WQUEUESIZE - 256)) { + DGNC_UNLOCK(ch->ch_lock, lock_flags); + return; + } + + if (ch->ch_tun.un_flags & UN_ISOPEN) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) + if ((ch->ch_tun.un_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + ch->ch_tun.un_tty->ldisc->ops->write_wakeup) + { + DGNC_UNLOCK(ch->ch_lock, lock_flags); + (ch->ch_tun.un_tty->ldisc->ops->write_wakeup)(ch->ch_tun.un_tty); + DGNC_LOCK(ch->ch_lock, lock_flags); + } +#else + if ((ch->ch_tun.un_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + ch->ch_tun.un_tty->ldisc.ops->write_wakeup) + { + DGNC_UNLOCK(ch->ch_lock, lock_flags); + (ch->ch_tun.un_tty->ldisc.ops->write_wakeup)(ch->ch_tun.un_tty); + DGNC_LOCK(ch->ch_lock, lock_flags); + } +#endif + + wake_up_interruptible(&ch->ch_tun.un_tty->write_wait); + + /* + * If unit is set to wait until empty, check to make sure + * the queue AND FIFO are both empty. + */ + if (ch->ch_tun.un_flags & UN_EMPTY) { + if ((qlen == 0) && (ch->ch_bd->bd_ops->get_uart_bytes_left(ch) == 0)) { + ch->ch_tun.un_flags &= ~(UN_EMPTY); + + /* + * If RTS Toggle mode is on, whenever + * the queue and UART is empty, keep RTS low. + */ + if (ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE) { + ch->ch_mostat &= ~(UART_MCR_RTS); + ch->ch_bd->bd_ops->assert_modem_signals(ch); + } + + /* + * If DTR Toggle mode is on, whenever + * the queue and UART is empty, keep DTR low. + */ + if (ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE) { + ch->ch_mostat &= ~(UART_MCR_DTR); + ch->ch_bd->bd_ops->assert_modem_signals(ch); + } + } + } + + wake_up_interruptible(&ch->ch_tun.un_flags_wait); + } + + if (ch->ch_pun.un_flags & UN_ISOPEN) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) + if ((ch->ch_pun.un_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + ch->ch_pun.un_tty->ldisc->ops->write_wakeup) + { + DGNC_UNLOCK(ch->ch_lock, lock_flags); + (ch->ch_pun.un_tty->ldisc->ops->write_wakeup)(ch->ch_pun.un_tty); + DGNC_LOCK(ch->ch_lock, lock_flags); + } +#else + if ((ch->ch_pun.un_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + ch->ch_pun.un_tty->ldisc.ops->write_wakeup) + { + DGNC_UNLOCK(ch->ch_lock, lock_flags); + (ch->ch_pun.un_tty->ldisc.ops->write_wakeup)(ch->ch_pun.un_tty); + DGNC_LOCK(ch->ch_lock, lock_flags); + } +#endif + + wake_up_interruptible(&ch->ch_pun.un_tty->write_wait); + + /* + * If unit is set to wait until empty, check to make sure + * the queue AND FIFO are both empty. + */ + if (ch->ch_pun.un_flags & UN_EMPTY) { + if ((qlen == 0) && (ch->ch_bd->bd_ops->get_uart_bytes_left(ch) == 0)) { + ch->ch_pun.un_flags &= ~(UN_EMPTY); + } + } + + wake_up_interruptible(&ch->ch_pun.un_flags_wait); + } + + DGNC_UNLOCK(ch->ch_lock, lock_flags); +} + + + +/************************************************************************ + * + * TTY Entry points and helper functions + * + ************************************************************************/ + +/* + * dgnc_tty_open() + * + */ +static int dgnc_tty_open(struct tty_struct *tty, struct file *file) +{ + struct board_t *brd; + struct channel_t *ch; + struct un_t *un; + uint major = 0; + uint minor = 0; + int rc = 0; + ulong lock_flags; + + rc = 0; + + major = MAJOR(tty_devnum(tty)); + minor = MINOR(tty_devnum(tty)); + + if (major > 255) { + return -ENXIO; + } + + /* Get board pointer from our array of majors we have allocated */ + brd = dgnc_BoardsByMajor[major]; + if (!brd) { + return -ENXIO; + } + + /* + * If board is not yet up to a state of READY, go to + * sleep waiting for it to happen or they cancel the open. + */ + rc = wait_event_interruptible(brd->state_wait, + (brd->state & BOARD_READY)); + + if (rc) { + return rc; + } + + DGNC_LOCK(brd->bd_lock, lock_flags); + + /* If opened device is greater than our number of ports, bail. */ + if (PORT_NUM(minor) > brd->nasync) { + DGNC_UNLOCK(brd->bd_lock, lock_flags); + return -ENXIO; + } + + ch = brd->channels[PORT_NUM(minor)]; + if (!ch) { + DGNC_UNLOCK(brd->bd_lock, lock_flags); + return -ENXIO; + } + + /* Drop board lock */ + DGNC_UNLOCK(brd->bd_lock, lock_flags); + + /* Grab channel lock */ + DGNC_LOCK(ch->ch_lock, lock_flags); + + /* Figure out our type */ + if (!IS_PRINT(minor)) { + un = &brd->channels[PORT_NUM(minor)]->ch_tun; + un->un_type = DGNC_SERIAL; + } + else if (IS_PRINT(minor)) { + un = &brd->channels[PORT_NUM(minor)]->ch_pun; + un->un_type = DGNC_PRINT; + } + else { + DGNC_UNLOCK(ch->ch_lock, lock_flags); + DPR_OPEN(("%d Unknown TYPE!\n", __LINE__)); + return -ENXIO; + } + + /* + * If the port is still in a previous open, and in a state + * where we simply cannot safely keep going, wait until the + * state clears. + */ + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + rc = wait_event_interruptible(ch->ch_flags_wait, ((ch->ch_flags & CH_OPENING) == 0)); + + /* If ret is non-zero, user ctrl-c'ed us */ + if (rc) { + DPR_OPEN(("%d User ctrl c'ed\n", __LINE__)); + return -EINTR; + } + + /* + * If either unit is in the middle of the fragile part of close, + * we just cannot touch the channel safely. + * Go to sleep, knowing that when the channel can be + * touched safely, the close routine will signal the + * ch_flags_wait to wake us back up. + */ + rc = wait_event_interruptible(ch->ch_flags_wait, + (((ch->ch_tun.un_flags | ch->ch_pun.un_flags) & UN_CLOSING) == 0)); + + /* If ret is non-zero, user ctrl-c'ed us */ + if (rc) { + DPR_OPEN(("%d User ctrl c'ed\n", __LINE__)); + return -EINTR; + } + + DGNC_LOCK(ch->ch_lock, lock_flags); + + + /* Store our unit into driver_data, so we always have it available. */ + tty->driver_data = un; + + DPR_OPEN(("Open called. MAJOR: %d MINOR:%d PORT_NUM: %x unit: %p NAME: %s\n", + MAJOR(tty_devnum(tty)), MINOR(tty_devnum(tty)), PORT_NUM(minor), un, brd->name)); + + DPR_OPEN(("%d: tflag=%x pflag=%x\n", __LINE__, ch->ch_tun.un_flags, ch->ch_pun.un_flags)); + + /* + * Initialize tty's + */ + if (!(un->un_flags & UN_ISOPEN)) { + /* Store important variables. */ + un->un_tty = tty; + + /* Maybe do something here to the TTY struct as well? */ + } + + + /* + * Allocate channel buffers for read/write/error. + * Set flag, so we don't get trounced on. + */ + ch->ch_flags |= (CH_OPENING); + + /* Drop locks, as malloc with GFP_KERNEL can sleep */ + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + if (!ch->ch_rqueue) + ch->ch_rqueue = dgnc_driver_kzmalloc(RQUEUESIZE, GFP_KERNEL); + if (!ch->ch_equeue) + ch->ch_equeue = dgnc_driver_kzmalloc(EQUEUESIZE, GFP_KERNEL); + if (!ch->ch_wqueue) + ch->ch_wqueue = dgnc_driver_kzmalloc(WQUEUESIZE, GFP_KERNEL); + + DGNC_LOCK(ch->ch_lock, lock_flags); + + ch->ch_flags &= ~(CH_OPENING); + wake_up_interruptible(&ch->ch_flags_wait); + + /* + * Initialize if neither terminal or printer is open. + */ + if (!((ch->ch_tun.un_flags | ch->ch_pun.un_flags) & UN_ISOPEN)) { + + DPR_OPEN(("dgnc_open: initializing channel in open...\n")); + + /* + * Flush input queues. + */ + ch->ch_r_head = ch->ch_r_tail = 0; + ch->ch_e_head = ch->ch_e_tail = 0; + ch->ch_w_head = ch->ch_w_tail = 0; + + brd->bd_ops->flush_uart_write(ch); + brd->bd_ops->flush_uart_read(ch); + + ch->ch_flags = 0; + ch->ch_cached_lsr = 0; + ch->ch_stop_sending_break = 0; + ch->ch_stops_sent = 0; + + ch->ch_c_cflag = tty->termios->c_cflag; + ch->ch_c_iflag = tty->termios->c_iflag; + ch->ch_c_oflag = tty->termios->c_oflag; + ch->ch_c_lflag = tty->termios->c_lflag; + ch->ch_startc = tty->termios->c_cc[VSTART]; + ch->ch_stopc = tty->termios->c_cc[VSTOP]; + + /* + * Bring up RTS and DTR... + * Also handle RTS or DTR toggle if set. + */ + if (!(ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE)) + ch->ch_mostat |= (UART_MCR_RTS); + if (!(ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE)) + ch->ch_mostat |= (UART_MCR_DTR); + + /* Tell UART to init itself */ + brd->bd_ops->uart_init(ch); + } + + /* + * Run param in case we changed anything + */ + brd->bd_ops->param(tty); + + dgnc_carrier(ch); + + /* + * follow protocol for opening port + */ + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + rc = dgnc_block_til_ready(tty, file, ch); + + if (rc) { + DPR_OPEN(("dgnc_tty_open returning after dgnc_block_til_ready " + "with %d\n", rc)); + } + + /* No going back now, increment our unit and channel counters */ + DGNC_LOCK(ch->ch_lock, lock_flags); + ch->ch_open_count++; + un->un_open_count++; + un->un_flags |= (UN_ISOPEN); + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + DPR_OPEN(("dgnc_tty_open finished\n")); + return (rc); +} + + +/* + * dgnc_block_til_ready() + * + * Wait for DCD, if needed. + */ +static int dgnc_block_til_ready(struct tty_struct *tty, struct file *file, struct channel_t *ch) +{ + int retval = 0; + struct un_t *un = NULL; + ulong lock_flags; + uint old_flags = 0; + int sleep_on_un_flags = 0; + + if (!tty || tty->magic != TTY_MAGIC || !file || !ch || ch->magic != DGNC_CHANNEL_MAGIC) { + return (-ENXIO); + } + + un = tty->driver_data; + if (!un || un->magic != DGNC_UNIT_MAGIC) { + return (-ENXIO); + } + + DPR_OPEN(("dgnc_block_til_ready - before block.\n")); + + DGNC_LOCK(ch->ch_lock, lock_flags); + + ch->ch_wopen++; + + /* Loop forever */ + while (1) { + + sleep_on_un_flags = 0; + + /* + * If board has failed somehow during our sleep, bail with error. + */ + if (ch->ch_bd->state == BOARD_FAILED) { + retval = -ENXIO; + break; + } + + /* If tty was hung up, break out of loop and set error. */ + if (tty_hung_up_p(file)) { + retval = -EAGAIN; + break; + } + + /* + * If either unit is in the middle of the fragile part of close, + * we just cannot touch the channel safely. + * Go back to sleep, knowing that when the channel can be + * touched safely, the close routine will signal the + * ch_wait_flags to wake us back up. + */ + if (!((ch->ch_tun.un_flags | ch->ch_pun.un_flags) & UN_CLOSING)) { + + /* + * Our conditions to leave cleanly and happily: + * 1) NONBLOCKING on the tty is set. + * 2) CLOCAL is set. + * 3) DCD (fake or real) is active. + */ + + if (file->f_flags & O_NONBLOCK) { + break; + } + + if (tty->flags & (1 << TTY_IO_ERROR)) { + retval = -EIO; + break; + } + + if (ch->ch_flags & CH_CD) { + DPR_OPEN(("%d: ch_flags: %x\n", __LINE__, ch->ch_flags)); + break; + } + + if (ch->ch_flags & CH_FCAR) { + DPR_OPEN(("%d: ch_flags: %x\n", __LINE__, ch->ch_flags)); + break; + } + } + else { + sleep_on_un_flags = 1; + } + + /* + * If there is a signal pending, the user probably + * interrupted (ctrl-c) us. + * Leave loop with error set. + */ + if (signal_pending(current)) { + DPR_OPEN(("%d: signal pending...\n", __LINE__)); + retval = -ERESTARTSYS; + break; + } + + DPR_OPEN(("dgnc_block_til_ready - blocking.\n")); + + /* + * Store the flags before we let go of channel lock + */ + if (sleep_on_un_flags) + old_flags = ch->ch_tun.un_flags | ch->ch_pun.un_flags; + else + old_flags = ch->ch_flags; + + /* + * Let go of channel lock before calling schedule. + * Our poller will get any FEP events and wake us up when DCD + * eventually goes active. + */ + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + DPR_OPEN(("Going to sleep on %s flags...\n", + (sleep_on_un_flags ? "un" : "ch"))); + + /* + * Wait for something in the flags to change from the current value. + */ + if (sleep_on_un_flags) { + retval = wait_event_interruptible(un->un_flags_wait, + (old_flags != (ch->ch_tun.un_flags | ch->ch_pun.un_flags))); + } + else { + retval = wait_event_interruptible(ch->ch_flags_wait, + (old_flags != ch->ch_flags)); + } + + DPR_OPEN(("After sleep... retval: %x\n", retval)); + + /* + * We got woken up for some reason. + * Before looping around, grab our channel lock. + */ + DGNC_LOCK(ch->ch_lock, lock_flags); + } + + ch->ch_wopen--; + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + DPR_OPEN(("dgnc_block_til_ready - after blocking.\n")); + + if (retval) { + DPR_OPEN(("dgnc_block_til_ready - done. error. retval: %x\n", retval)); + return(retval); + } + + DPR_OPEN(("dgnc_block_til_ready - done no error. jiffies: %lu\n", jiffies)); + + return(0); +} + + +/* + * dgnc_tty_hangup() + * + * Hangup the port. Like a close, but don't wait for output to drain. + */ +static void dgnc_tty_hangup(struct tty_struct *tty) +{ + struct un_t *un; + + if (!tty || tty->magic != TTY_MAGIC) + return; + + un = tty->driver_data; + if (!un || un->magic != DGNC_UNIT_MAGIC) + return; + + DPR_CLOSE(("dgnc_hangup called. ch->ch_open_count: %d un->un_open_count: %d\n", + un->un_ch->ch_open_count, un->un_open_count)); + + /* flush the transmit queues */ + dgnc_tty_flush_buffer(tty); + + DPR_CLOSE(("dgnc_hangup finished. ch->ch_open_count: %d un->un_open_count: %d\n", + un->un_ch->ch_open_count, un->un_open_count)); +} + + +/* + * dgnc_tty_close() + * + */ +static void dgnc_tty_close(struct tty_struct *tty, struct file *file) +{ + struct ktermios *ts; + struct board_t *bd; + struct channel_t *ch; + struct un_t *un; + ulong lock_flags; + int rc = 0; + + if (!tty || tty->magic != TTY_MAGIC) + return; + + un = tty->driver_data; + if (!un || un->magic != DGNC_UNIT_MAGIC) + return; + + ch = un->un_ch; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + bd = ch->ch_bd; + if (!bd || bd->magic != DGNC_BOARD_MAGIC) + return; + + ts = tty->termios; + + DPR_CLOSE(("Close called\n")); + + DGNC_LOCK(ch->ch_lock, lock_flags); + + /* + * Determine if this is the last close or not - and if we agree about + * which type of close it is with the Line Discipline + */ + if ((tty->count == 1) && (un->un_open_count != 1)) { + /* + * Uh, oh. tty->count is 1, which means that the tty + * structure will be freed. un_open_count should always + * be one in these conditions. If it's greater than + * one, we've got real problems, since it means the + * serial port won't be shutdown. + */ + APR(("tty->count is 1, un open count is %d\n", un->un_open_count)); + un->un_open_count = 1; + } + + if (--un->un_open_count < 0) { + APR(("bad serial port open count of %d\n", un->un_open_count)); + un->un_open_count = 0; + } + + ch->ch_open_count--; + + if (ch->ch_open_count && un->un_open_count) { + DPR_CLOSE(("dgnc_tty_close: not last close ch: %d un:%d\n", + ch->ch_open_count, un->un_open_count)); + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + return; + } + + /* OK, its the last close on the unit */ + DPR_CLOSE(("dgnc_tty_close - last close on unit procedures\n")); + + un->un_flags |= UN_CLOSING; + + tty->closing = 1; + + + /* + * Only officially close channel if count is 0 and + * DIGI_PRINTER bit is not set. + */ + if ((ch->ch_open_count == 0) && !(ch->ch_digi.digi_flags & DIGI_PRINTER)) { + + ch->ch_flags &= ~(CH_STOPI | CH_FORCED_STOPI); + + /* + * turn off print device when closing print device. + */ + if ((un->un_type == DGNC_PRINT) && (ch->ch_flags & CH_PRON) ) { + dgnc_wmove(ch, ch->ch_digi.digi_offstr, + (int) ch->ch_digi.digi_offlen); + ch->ch_flags &= ~CH_PRON; + } + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + /* wait for output to drain */ + /* This will also return if we take an interrupt */ + + DPR_CLOSE(("Calling wait_for_drain\n")); + rc = bd->bd_ops->drain(tty, 0); + + DPR_CLOSE(("After calling wait_for_drain\n")); + + if (rc) { + DPR_BASIC(("dgnc_tty_close - bad return: %d ", rc)); + } + + dgnc_tty_flush_buffer(tty); + tty_ldisc_flush(tty); + + DGNC_LOCK(ch->ch_lock, lock_flags); + + tty->closing = 0; + + /* + * If we have HUPCL set, lower DTR and RTS + */ + if (ch->ch_c_cflag & HUPCL) { + DPR_CLOSE(("Close. HUPCL set, dropping DTR/RTS\n")); + + /* Drop RTS/DTR */ + ch->ch_mostat &= ~(UART_MCR_DTR | UART_MCR_RTS); + bd->bd_ops->assert_modem_signals(ch); + + /* + * Go to sleep to ensure RTS/DTR + * have been dropped for modems to see it. + */ + if (ch->ch_close_delay) { + DPR_CLOSE(("Close. Sleeping for RTS/DTR drop\n")); + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + dgnc_ms_sleep(ch->ch_close_delay); + DGNC_LOCK(ch->ch_lock, lock_flags); + + DPR_CLOSE(("Close. After sleeping for RTS/DTR drop\n")); + } + } + + ch->ch_old_baud = 0; + + /* Turn off UART interrupts for this port */ + ch->ch_bd->bd_ops->uart_off(ch); + } + else { + /* + * turn off print device when closing print device. + */ + if ((un->un_type == DGNC_PRINT) && (ch->ch_flags & CH_PRON) ) { + dgnc_wmove(ch, ch->ch_digi.digi_offstr, + (int) ch->ch_digi.digi_offlen); + ch->ch_flags &= ~CH_PRON; + } + } + + un->un_tty = NULL; + un->un_flags &= ~(UN_ISOPEN | UN_CLOSING); + + DPR_CLOSE(("Close. Doing wakeups\n")); + wake_up_interruptible(&ch->ch_flags_wait); + wake_up_interruptible(&un->un_flags_wait); + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + DPR_BASIC(("dgnc_tty_close - complete\n")); +} + + +/* + * dgnc_tty_chars_in_buffer() + * + * Return number of characters that have not been transmitted yet. + * + * This routine is used by the line discipline to determine if there + * is data waiting to be transmitted/drained/flushed or not. + */ +static int dgnc_tty_chars_in_buffer(struct tty_struct *tty) +{ + struct channel_t *ch = NULL; + struct un_t *un = NULL; + ushort thead; + ushort ttail; + uint tmask; + uint chars = 0; + ulong lock_flags = 0; + + if (tty == NULL) + return(0); + + un = tty->driver_data; + if (!un || un->magic != DGNC_UNIT_MAGIC) + return (0); + + ch = un->un_ch; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return (0); + + DGNC_LOCK(ch->ch_lock, lock_flags); + + tmask = WQUEUEMASK; + thead = ch->ch_w_head & tmask; + ttail = ch->ch_w_tail & tmask; + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + if (ttail == thead) { + chars = 0; + } else { + if (thead >= ttail) + chars = thead - ttail; + else + chars = thead - ttail + WQUEUESIZE; + } + + DPR_WRITE(("dgnc_tty_chars_in_buffer. Port: %x - %d (head: %d tail: %d)\n", + ch->ch_portnum, chars, thead, ttail)); + + return(chars); +} + + +/* + * dgnc_maxcps_room + * + * Reduces bytes_available to the max number of characters + * that can be sent currently given the maxcps value, and + * returns the new bytes_available. This only affects printer + * output. + */ +static int dgnc_maxcps_room(struct tty_struct *tty, int bytes_available) +{ + struct channel_t *ch = NULL; + struct un_t *un = NULL; + + if (!tty) + return (bytes_available); + + un = tty->driver_data; + if (!un || un->magic != DGNC_UNIT_MAGIC) + return (bytes_available); + + ch = un->un_ch; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return (bytes_available); + + /* + * If its not the Transparent print device, return + * the full data amount. + */ + if (un->un_type != DGNC_PRINT) + return (bytes_available); + + if (ch->ch_digi.digi_maxcps > 0 && ch->ch_digi.digi_bufsize > 0 ) { + int cps_limit = 0; + unsigned long current_time = jiffies; + unsigned long buffer_time = current_time + + (HZ * ch->ch_digi.digi_bufsize) / ch->ch_digi.digi_maxcps; + + if (ch->ch_cpstime < current_time) { + /* buffer is empty */ + ch->ch_cpstime = current_time; /* reset ch_cpstime */ + cps_limit = ch->ch_digi.digi_bufsize; + } + else if (ch->ch_cpstime < buffer_time) { + /* still room in the buffer */ + cps_limit = ((buffer_time - ch->ch_cpstime) * ch->ch_digi.digi_maxcps) / HZ; + } + else { + /* no room in the buffer */ + cps_limit = 0; + } + + bytes_available = min(cps_limit, bytes_available); + } + + return (bytes_available); +} + + +/* + * dgnc_tty_write_room() + * + * Return space available in Tx buffer + */ +static int dgnc_tty_write_room(struct tty_struct *tty) +{ + struct channel_t *ch = NULL; + struct un_t *un = NULL; + ushort head; + ushort tail; + ushort tmask; + int ret = 0; + ulong lock_flags = 0; + + if (tty == NULL || dgnc_TmpWriteBuf == NULL) + return(0); + + un = tty->driver_data; + if (!un || un->magic != DGNC_UNIT_MAGIC) + return (0); + + ch = un->un_ch; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return (0); + + DGNC_LOCK(ch->ch_lock, lock_flags); + + tmask = WQUEUEMASK; + head = (ch->ch_w_head) & tmask; + tail = (ch->ch_w_tail) & tmask; + + if ((ret = tail - head - 1) < 0) + ret += WQUEUESIZE; + + /* Limit printer to maxcps */ + ret = dgnc_maxcps_room(tty, ret); + + /* + * If we are printer device, leave space for + * possibly both the on and off strings. + */ + if (un->un_type == DGNC_PRINT) { + if (!(ch->ch_flags & CH_PRON)) + ret -= ch->ch_digi.digi_onlen; + ret -= ch->ch_digi.digi_offlen; + } + else { + if (ch->ch_flags & CH_PRON) + ret -= ch->ch_digi.digi_offlen; + } + + if (ret < 0) + ret = 0; + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + DPR_WRITE(("dgnc_tty_write_room - %d tail: %d head: %d\n", ret, tail, head)); + + return(ret); +} + + +/* + * dgnc_tty_put_char() + * + * Put a character into ch->ch_buf + * + * - used by the line discipline for OPOST processing + */ +static int dgnc_tty_put_char(struct tty_struct *tty, unsigned char c) +{ + /* + * Simply call tty_write. + */ + DPR_WRITE(("dgnc_tty_put_char called\n")); + dgnc_tty_write(tty, &c, 1); + return 1; +} + + +/* + * dgnc_tty_write() + * + * Take data from the user or kernel and send it out to the FEP. + * In here exists all the Transparent Print magic as well. + */ +static int dgnc_tty_write(struct tty_struct *tty, + const unsigned char *buf, int count) +{ + struct channel_t *ch = NULL; + struct un_t *un = NULL; + int bufcount = 0, n = 0; + int orig_count = 0; + ulong lock_flags; + ushort head; + ushort tail; + ushort tmask; + uint remain; + int from_user = 0; + + if (tty == NULL || dgnc_TmpWriteBuf == NULL) + return(0); + + un = tty->driver_data; + if (!un || un->magic != DGNC_UNIT_MAGIC) + return(0); + + ch = un->un_ch; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return(0); + + if (!count) + return(0); + + DPR_WRITE(("dgnc_tty_write: Port: %x tty=%p user=%d len=%d\n", + ch->ch_portnum, tty, from_user, count)); + + /* + * Store original amount of characters passed in. + * This helps to figure out if we should ask the FEP + * to send us an event when it has more space available. + */ + orig_count = count; + + DGNC_LOCK(ch->ch_lock, lock_flags); + + /* Get our space available for the channel from the board */ + tmask = WQUEUEMASK; + head = (ch->ch_w_head) & tmask; + tail = (ch->ch_w_tail) & tmask; + + if ((bufcount = tail - head - 1) < 0) + bufcount += WQUEUESIZE; + + DPR_WRITE(("%d: bufcount: %x count: %x tail: %x head: %x tmask: %x\n", + __LINE__, bufcount, count, tail, head, tmask)); + + /* + * Limit printer output to maxcps overall, with bursts allowed + * up to bufsize characters. + */ + bufcount = dgnc_maxcps_room(tty, bufcount); + + /* + * Take minimum of what the user wants to send, and the + * space available in the FEP buffer. + */ + count = min(count, bufcount); + + /* + * Bail if no space left. + */ + if (count <= 0) { + DGNC_UNLOCK(ch->ch_lock, lock_flags); + return(0); + } + + /* + * Output the printer ON string, if we are in terminal mode, but + * need to be in printer mode. + */ + if ((un->un_type == DGNC_PRINT) && !(ch->ch_flags & CH_PRON)) { + dgnc_wmove(ch, ch->ch_digi.digi_onstr, + (int) ch->ch_digi.digi_onlen); + head = (ch->ch_w_head) & tmask; + ch->ch_flags |= CH_PRON; + } + + /* + * On the other hand, output the printer OFF string, if we are + * currently in printer mode, but need to output to the terminal. + */ + if ((un->un_type != DGNC_PRINT) && (ch->ch_flags & CH_PRON)) { + dgnc_wmove(ch, ch->ch_digi.digi_offstr, + (int) ch->ch_digi.digi_offlen); + head = (ch->ch_w_head) & tmask; + ch->ch_flags &= ~CH_PRON; + } + + /* + * If there is nothing left to copy, or I can't handle any more data, leave. + */ + if (count <= 0) { + DGNC_UNLOCK(ch->ch_lock, lock_flags); + return(0); + } + + if (from_user) { + + count = min(count, WRITEBUFLEN); + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + /* + * If data is coming from user space, copy it into a temporary + * buffer so we don't get swapped out while doing the copy to + * the board. + */ + /* we're allowed to block if it's from_user */ + if (down_interruptible(&dgnc_TmpWriteSem)) { + return (-EINTR); + } + + /* + * copy_from_user() returns the number + * of bytes that could *NOT* be copied. + */ + count -= copy_from_user(dgnc_TmpWriteBuf, (const uchar __user *) buf, count); + + if (!count) { + up(&dgnc_TmpWriteSem); + return(-EFAULT); + } + + DGNC_LOCK(ch->ch_lock, lock_flags); + + buf = dgnc_TmpWriteBuf; + + } + + n = count; + + /* + * If the write wraps over the top of the circular buffer, + * move the portion up to the wrap point, and reset the + * pointers to the bottom. + */ + remain = WQUEUESIZE - head; + + if (n >= remain) { + n -= remain; + memcpy(ch->ch_wqueue + head, buf, remain); + dgnc_sniff_nowait_nolock(ch, "USER WRITE", ch->ch_wqueue + head, remain); + head = 0; + buf += remain; + } + + if (n > 0) { + /* + * Move rest of data. + */ + remain = n; + memcpy(ch->ch_wqueue + head, buf, remain); + dgnc_sniff_nowait_nolock(ch, "USER WRITE", ch->ch_wqueue + head, remain); + head += remain; + } + + if (count) { + head &= tmask; + ch->ch_w_head = head; + } + +#if 0 + /* + * If this is the print device, and the + * printer is still on, we need to turn it + * off before going idle. + */ + if (count == orig_count) { + if ((un->un_type == DGNC_PRINT) && (ch->ch_flags & CH_PRON)) { + head &= tmask; + ch->ch_w_head = head; + dgnc_wmove(ch, ch->ch_digi.digi_offstr, + (int) ch->ch_digi.digi_offlen); + head = (ch->ch_w_head) & tmask; + ch->ch_flags &= ~CH_PRON; + } + } +#endif + + /* Update printer buffer empty time. */ + if ((un->un_type == DGNC_PRINT) && (ch->ch_digi.digi_maxcps > 0) + && (ch->ch_digi.digi_bufsize > 0)) { + ch->ch_cpstime += (HZ * count) / ch->ch_digi.digi_maxcps; + } + + if (from_user) { + DGNC_UNLOCK(ch->ch_lock, lock_flags); + up(&dgnc_TmpWriteSem); + } else { + DGNC_UNLOCK(ch->ch_lock, lock_flags); + } + + DPR_WRITE(("Write finished - Write %d bytes of %d.\n", count, orig_count)); + + if (count) { + /* + * Channel lock is grabbed and then released + * inside this routine. + */ + ch->ch_bd->bd_ops->copy_data_from_queue_to_uart(ch); + } + + return (count); +} + + +/* + * Return modem signals to ld. + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39) +static int dgnc_tty_tiocmget(struct tty_struct *tty) +#else +static int dgnc_tty_tiocmget(struct tty_struct *tty, struct file *file) +#endif +{ + struct channel_t *ch; + struct un_t *un; + int result = -EIO; + uchar mstat = 0; + ulong lock_flags; + + if (!tty || tty->magic != TTY_MAGIC) + return result; + + un = tty->driver_data; + if (!un || un->magic != DGNC_UNIT_MAGIC) + return result; + + ch = un->un_ch; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return result; + + DPR_IOCTL(("dgnc_tty_tiocmget start\n")); + + DGNC_LOCK(ch->ch_lock, lock_flags); + + mstat = (ch->ch_mostat | ch->ch_mistat); + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + result = 0; + + if (mstat & UART_MCR_DTR) + result |= TIOCM_DTR; + if (mstat & UART_MCR_RTS) + result |= TIOCM_RTS; + if (mstat & UART_MSR_CTS) + result |= TIOCM_CTS; + if (mstat & UART_MSR_DSR) + result |= TIOCM_DSR; + if (mstat & UART_MSR_RI) + result |= TIOCM_RI; + if (mstat & UART_MSR_DCD) + result |= TIOCM_CD; + + DPR_IOCTL(("dgnc_tty_tiocmget finish\n")); + + return result; +} + + +/* + * dgnc_tty_tiocmset() + * + * Set modem signals, called by ld. + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39) +static int dgnc_tty_tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear) +#else +static int dgnc_tty_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) +#endif +{ + struct board_t *bd; + struct channel_t *ch; + struct un_t *un; + int ret = -EIO; + ulong lock_flags; + + if (!tty || tty->magic != TTY_MAGIC) + return ret; + + un = tty->driver_data; + if (!un || un->magic != DGNC_UNIT_MAGIC) + return ret; + + ch = un->un_ch; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return ret; + + bd = ch->ch_bd; + if (!bd || bd->magic != DGNC_BOARD_MAGIC) + return ret; + + DPR_IOCTL(("dgnc_tty_tiocmset start\n")); + + + DGNC_LOCK(ch->ch_lock, lock_flags); + + if (set & TIOCM_RTS) { + ch->ch_mostat |= UART_MCR_RTS; + } + + if (set & TIOCM_DTR) { + ch->ch_mostat |= UART_MCR_DTR; + } + + if (clear & TIOCM_RTS) { + ch->ch_mostat &= ~(UART_MCR_RTS); + } + + if (clear & TIOCM_DTR) { + ch->ch_mostat &= ~(UART_MCR_DTR); + } + + ch->ch_bd->bd_ops->assert_modem_signals(ch); + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + DPR_IOCTL(("dgnc_tty_tiocmset finish\n")); + + return (0); +} + + +/* + * dgnc_tty_send_break() + * + * Send a Break, called by ld. + */ +static int dgnc_tty_send_break(struct tty_struct *tty, int msec) +{ + struct board_t *bd; + struct channel_t *ch; + struct un_t *un; + int ret = -EIO; + ulong lock_flags; + + if (!tty || tty->magic != TTY_MAGIC) + return ret; + + un = tty->driver_data; + if (!un || un->magic != DGNC_UNIT_MAGIC) + return ret; + + ch = un->un_ch; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return ret; + + bd = ch->ch_bd; + if (!bd || bd->magic != DGNC_BOARD_MAGIC) + return ret; + + switch (msec) { + case -1: + msec = 0xFFFF; + break; + case 0: + msec = 0; + break; + default: + break; + } + + DPR_IOCTL(("dgnc_tty_send_break start 1. %lx\n", jiffies)); + + DGNC_LOCK(ch->ch_lock, lock_flags); + + ch->ch_bd->bd_ops->send_break(ch, msec); + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + DPR_IOCTL(("dgnc_tty_send_break finish\n")); + + return (0); + +} + + +/* + * dgnc_tty_wait_until_sent() + * + * wait until data has been transmitted, called by ld. + */ +static void dgnc_tty_wait_until_sent(struct tty_struct *tty, int timeout) +{ + struct board_t *bd; + struct channel_t *ch; + struct un_t *un; + int rc; + + if (!tty || tty->magic != TTY_MAGIC) + return; + + un = tty->driver_data; + if (!un || un->magic != DGNC_UNIT_MAGIC) + return; + + ch = un->un_ch; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + bd = ch->ch_bd; + if (!bd || bd->magic != DGNC_BOARD_MAGIC) + return; + + rc = bd->bd_ops->drain(tty, 0); + if (rc) { + DPR_IOCTL(("dgnc_tty_ioctl - bad return: %d ", rc)); + return; + } + return; +} + + +/* + * dgnc_send_xchar() + * + * send a high priority character, called by ld. + */ +static void dgnc_tty_send_xchar(struct tty_struct *tty, char c) +{ + struct board_t *bd; + struct channel_t *ch; + struct un_t *un; + ulong lock_flags; + + if (!tty || tty->magic != TTY_MAGIC) + return; + + un = tty->driver_data; + if (!un || un->magic != DGNC_UNIT_MAGIC) + return; + + ch = un->un_ch; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + bd = ch->ch_bd; + if (!bd || bd->magic != DGNC_BOARD_MAGIC) + return; + + DPR_IOCTL(("dgnc_tty_send_xchar start\n")); + printk("dgnc_tty_send_xchar start\n"); + + DGNC_LOCK(ch->ch_lock, lock_flags); + bd->bd_ops->send_immediate_char(ch, c); + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + DPR_IOCTL(("dgnc_tty_send_xchar finish\n")); + printk("dgnc_tty_send_xchar finish\n"); + return; +} + + + + +/* + * Return modem signals to ld. + */ +static inline int dgnc_get_mstat(struct channel_t *ch) +{ + unsigned char mstat; + int result = -EIO; + ulong lock_flags; + + DPR_IOCTL(("dgnc_getmstat start\n")); + + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return(-ENXIO); + + DGNC_LOCK(ch->ch_lock, lock_flags); + + mstat = (ch->ch_mostat | ch->ch_mistat); + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + result = 0; + + if (mstat & UART_MCR_DTR) + result |= TIOCM_DTR; + if (mstat & UART_MCR_RTS) + result |= TIOCM_RTS; + if (mstat & UART_MSR_CTS) + result |= TIOCM_CTS; + if (mstat & UART_MSR_DSR) + result |= TIOCM_DSR; + if (mstat & UART_MSR_RI) + result |= TIOCM_RI; + if (mstat & UART_MSR_DCD) + result |= TIOCM_CD; + + DPR_IOCTL(("dgnc_getmstat finish\n")); + + return(result); +} + + + +/* + * Return modem signals to ld. + */ +static int dgnc_get_modem_info(struct channel_t *ch, unsigned int __user *value) +{ + int result; + int rc; + + DPR_IOCTL(("dgnc_get_modem_info start\n")); + + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return(-ENXIO); + + result = dgnc_get_mstat(ch); + + if (result < 0) + return (-ENXIO); + + rc = put_user(result, value); + + DPR_IOCTL(("dgnc_get_modem_info finish\n")); + return(rc); +} + + +/* + * dgnc_set_modem_info() + * + * Set modem signals, called by ld. + */ +static int dgnc_set_modem_info(struct tty_struct *tty, unsigned int command, unsigned int __user *value) +{ + struct board_t *bd; + struct channel_t *ch; + struct un_t *un; + int ret = -ENXIO; + unsigned int arg = 0; + ulong lock_flags; + + if (!tty || tty->magic != TTY_MAGIC) + return ret; + + un = tty->driver_data; + if (!un || un->magic != DGNC_UNIT_MAGIC) + return ret; + + ch = un->un_ch; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return ret; + + bd = ch->ch_bd; + if (!bd || bd->magic != DGNC_BOARD_MAGIC) + return ret; + + ret = 0; + + DPR_IOCTL(("dgnc_set_modem_info() start\n")); + + ret = get_user(arg, value); + if (ret) + return(ret); + + switch (command) { + case TIOCMBIS: + if (arg & TIOCM_RTS) { + ch->ch_mostat |= UART_MCR_RTS; + } + + if (arg & TIOCM_DTR) { + ch->ch_mostat |= UART_MCR_DTR; + } + + break; + + case TIOCMBIC: + if (arg & TIOCM_RTS) { + ch->ch_mostat &= ~(UART_MCR_RTS); + } + + if (arg & TIOCM_DTR) { + ch->ch_mostat &= ~(UART_MCR_DTR); + } + + break; + + case TIOCMSET: + + if (arg & TIOCM_RTS) { + ch->ch_mostat |= UART_MCR_RTS; + } + else { + ch->ch_mostat &= ~(UART_MCR_RTS); + } + + if (arg & TIOCM_DTR) { + ch->ch_mostat |= UART_MCR_DTR; + } + else { + ch->ch_mostat &= ~(UART_MCR_DTR); + } + + break; + + default: + return(-EINVAL); + } + + DGNC_LOCK(ch->ch_lock, lock_flags); + + ch->ch_bd->bd_ops->assert_modem_signals(ch); + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + DPR_IOCTL(("dgnc_set_modem_info finish\n")); + + return (0); +} + + +/* + * dgnc_tty_digigeta() + * + * Ioctl to get the information for ditty. + * + * + * + */ +static int dgnc_tty_digigeta(struct tty_struct *tty, struct digi_t __user *retinfo) +{ + struct channel_t *ch; + struct un_t *un; + struct digi_t tmp; + ulong lock_flags; + + if (!retinfo) + return (-EFAULT); + + if (!tty || tty->magic != TTY_MAGIC) + return (-EFAULT); + + un = tty->driver_data; + if (!un || un->magic != DGNC_UNIT_MAGIC) + return (-EFAULT); + + ch = un->un_ch; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return (-EFAULT); + + memset(&tmp, 0, sizeof(tmp)); + + DGNC_LOCK(ch->ch_lock, lock_flags); + memcpy(&tmp, &ch->ch_digi, sizeof(tmp)); + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) + return (-EFAULT); + + return (0); +} + + +/* + * dgnc_tty_digiseta() + * + * Ioctl to set the information for ditty. + * + * + * + */ +static int dgnc_tty_digiseta(struct tty_struct *tty, struct digi_t __user *new_info) +{ + struct board_t *bd; + struct channel_t *ch; + struct un_t *un; + struct digi_t new_digi; + ulong lock_flags; + + DPR_IOCTL(("DIGI_SETA start\n")); + + if (!tty || tty->magic != TTY_MAGIC) + return (-EFAULT); + + un = tty->driver_data; + if (!un || un->magic != DGNC_UNIT_MAGIC) + return (-EFAULT); + + ch = un->un_ch; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return (-EFAULT); + + bd = ch->ch_bd; + if (!bd || bd->magic != DGNC_BOARD_MAGIC) + return (-EFAULT); + + if (copy_from_user(&new_digi, new_info, sizeof(struct digi_t))) { + DPR_IOCTL(("DIGI_SETA failed copy_from_user\n")); + return(-EFAULT); + } + + DGNC_LOCK(ch->ch_lock, lock_flags); + + /* + * Handle transistions to and from RTS Toggle. + */ + if (!(ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE) && (new_digi.digi_flags & DIGI_RTS_TOGGLE)) + ch->ch_mostat &= ~(UART_MCR_RTS); + if ((ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE) && !(new_digi.digi_flags & DIGI_RTS_TOGGLE)) + ch->ch_mostat |= (UART_MCR_RTS); + + /* + * Handle transistions to and from DTR Toggle. + */ + if (!(ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE) && (new_digi.digi_flags & DIGI_DTR_TOGGLE)) + ch->ch_mostat &= ~(UART_MCR_DTR); + if ((ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE) && !(new_digi.digi_flags & DIGI_DTR_TOGGLE)) + ch->ch_mostat |= (UART_MCR_DTR); + + memcpy(&ch->ch_digi, &new_digi, sizeof(struct digi_t)); + + if (ch->ch_digi.digi_maxcps < 1) + ch->ch_digi.digi_maxcps = 1; + + if (ch->ch_digi.digi_maxcps > 10000) + ch->ch_digi.digi_maxcps = 10000; + + if (ch->ch_digi.digi_bufsize < 10) + ch->ch_digi.digi_bufsize = 10; + + if (ch->ch_digi.digi_maxchar < 1) + ch->ch_digi.digi_maxchar = 1; + + if (ch->ch_digi.digi_maxchar > ch->ch_digi.digi_bufsize) + ch->ch_digi.digi_maxchar = ch->ch_digi.digi_bufsize; + + if (ch->ch_digi.digi_onlen > DIGI_PLEN) + ch->ch_digi.digi_onlen = DIGI_PLEN; + + if (ch->ch_digi.digi_offlen > DIGI_PLEN) + ch->ch_digi.digi_offlen = DIGI_PLEN; + + ch->ch_bd->bd_ops->param(tty); + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + DPR_IOCTL(("DIGI_SETA finish\n")); + + return(0); +} + + +/* + * dgnc_set_termios() + */ +static void dgnc_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios) +{ + struct board_t *bd; + struct channel_t *ch; + struct un_t *un; + unsigned long lock_flags; + + if (!tty || tty->magic != TTY_MAGIC) + return; + + un = tty->driver_data; + if (!un || un->magic != DGNC_UNIT_MAGIC) + return; + + ch = un->un_ch; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + bd = ch->ch_bd; + if (!bd || bd->magic != DGNC_BOARD_MAGIC) + return; + + DGNC_LOCK(ch->ch_lock, lock_flags); + + ch->ch_c_cflag = tty->termios->c_cflag; + ch->ch_c_iflag = tty->termios->c_iflag; + ch->ch_c_oflag = tty->termios->c_oflag; + ch->ch_c_lflag = tty->termios->c_lflag; + ch->ch_startc = tty->termios->c_cc[VSTART]; + ch->ch_stopc = tty->termios->c_cc[VSTOP]; + + ch->ch_bd->bd_ops->param(tty); + dgnc_carrier(ch); + + DGNC_UNLOCK(ch->ch_lock, lock_flags); +} + + +static void dgnc_tty_throttle(struct tty_struct *tty) +{ + struct channel_t *ch; + struct un_t *un; + ulong lock_flags = 0; + + if (!tty || tty->magic != TTY_MAGIC) + return; + + un = tty->driver_data; + if (!un || un->magic != DGNC_UNIT_MAGIC) + return; + + ch = un->un_ch; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + DPR_IOCTL(("dgnc_tty_throttle start\n")); + + DGNC_LOCK(ch->ch_lock, lock_flags); + + ch->ch_flags |= (CH_FORCED_STOPI); + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + DPR_IOCTL(("dgnc_tty_throttle finish\n")); +} + + +static void dgnc_tty_unthrottle(struct tty_struct *tty) +{ + struct channel_t *ch; + struct un_t *un; + ulong lock_flags; + + if (!tty || tty->magic != TTY_MAGIC) + return; + + un = tty->driver_data; + if (!un || un->magic != DGNC_UNIT_MAGIC) + return; + + ch = un->un_ch; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + DPR_IOCTL(("dgnc_tty_unthrottle start\n")); + + DGNC_LOCK(ch->ch_lock, lock_flags); + + ch->ch_flags &= ~(CH_FORCED_STOPI); + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + DPR_IOCTL(("dgnc_tty_unthrottle finish\n")); +} + + +static void dgnc_tty_start(struct tty_struct *tty) +{ + struct board_t *bd; + struct channel_t *ch; + struct un_t *un; + ulong lock_flags; + + if (!tty || tty->magic != TTY_MAGIC) + return; + + un = tty->driver_data; + if (!un || un->magic != DGNC_UNIT_MAGIC) + return; + + ch = un->un_ch; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + bd = ch->ch_bd; + if (!bd || bd->magic != DGNC_BOARD_MAGIC) + return; + + DPR_IOCTL(("dgcn_tty_start start\n")); + + DGNC_LOCK(ch->ch_lock, lock_flags); + + ch->ch_flags &= ~(CH_FORCED_STOP); + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + DPR_IOCTL(("dgnc_tty_start finish\n")); +} + + +static void dgnc_tty_stop(struct tty_struct *tty) +{ + struct board_t *bd; + struct channel_t *ch; + struct un_t *un; + ulong lock_flags; + + if (!tty || tty->magic != TTY_MAGIC) + return; + + un = tty->driver_data; + if (!un || un->magic != DGNC_UNIT_MAGIC) + return; + + ch = un->un_ch; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + bd = ch->ch_bd; + if (!bd || bd->magic != DGNC_BOARD_MAGIC) + return; + + DPR_IOCTL(("dgnc_tty_stop start\n")); + + DGNC_LOCK(ch->ch_lock, lock_flags); + + ch->ch_flags |= (CH_FORCED_STOP); + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + DPR_IOCTL(("dgnc_tty_stop finish\n")); +} + + +/* + * dgnc_tty_flush_chars() + * + * Flush the cook buffer + * + * Note to self, and any other poor souls who venture here: + * + * flush in this case DOES NOT mean dispose of the data. + * instead, it means "stop buffering and send it if you + * haven't already." Just guess how I figured that out... SRW 2-Jun-98 + * + * It is also always called in interrupt context - JAR 8-Sept-99 + */ +static void dgnc_tty_flush_chars(struct tty_struct *tty) +{ + struct board_t *bd; + struct channel_t *ch; + struct un_t *un; + ulong lock_flags; + + if (!tty || tty->magic != TTY_MAGIC) + return; + + un = tty->driver_data; + if (!un || un->magic != DGNC_UNIT_MAGIC) + return; + + ch = un->un_ch; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + bd = ch->ch_bd; + if (!bd || bd->magic != DGNC_BOARD_MAGIC) + return; + + DPR_IOCTL(("dgnc_tty_flush_chars start\n")); + + DGNC_LOCK(ch->ch_lock, lock_flags); + + /* Do something maybe here */ + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + DPR_IOCTL(("dgnc_tty_flush_chars finish\n")); +} + + + +/* + * dgnc_tty_flush_buffer() + * + * Flush Tx buffer (make in == out) + */ +static void dgnc_tty_flush_buffer(struct tty_struct *tty) +{ + struct channel_t *ch; + struct un_t *un; + ulong lock_flags; + + if (!tty || tty->magic != TTY_MAGIC) + return; + + un = tty->driver_data; + if (!un || un->magic != DGNC_UNIT_MAGIC) + return; + + ch = un->un_ch; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return; + + DPR_IOCTL(("dgnc_tty_flush_buffer on port: %d start\n", ch->ch_portnum)); + + DGNC_LOCK(ch->ch_lock, lock_flags); + + ch->ch_flags &= ~CH_STOP; + + /* Flush our write queue */ + ch->ch_w_head = ch->ch_w_tail; + + /* Flush UARTs transmit FIFO */ + ch->ch_bd->bd_ops->flush_uart_write(ch); + + if (ch->ch_tun.un_flags & (UN_LOW|UN_EMPTY)) { + ch->ch_tun.un_flags &= ~(UN_LOW|UN_EMPTY); + wake_up_interruptible(&ch->ch_tun.un_flags_wait); + } + if (ch->ch_pun.un_flags & (UN_LOW|UN_EMPTY)) { + ch->ch_pun.un_flags &= ~(UN_LOW|UN_EMPTY); + wake_up_interruptible(&ch->ch_pun.un_flags_wait); + } + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + DPR_IOCTL(("dgnc_tty_flush_buffer finish\n")); +} + + + +/***************************************************************************** + * + * The IOCTL function and all of its helpers + * + *****************************************************************************/ + +/* + * dgnc_tty_ioctl() + * + * The usual assortment of ioctl's + */ +static int dgnc_tty_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct board_t *bd; + struct channel_t *ch; + struct un_t *un; + int rc; + ulong lock_flags; + void __user *uarg = (void __user *) arg; + + if (!tty || tty->magic != TTY_MAGIC) + return (-ENODEV); + + un = tty->driver_data; + if (!un || un->magic != DGNC_UNIT_MAGIC) + return (-ENODEV); + + ch = un->un_ch; + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + return (-ENODEV); + + bd = ch->ch_bd; + if (!bd || bd->magic != DGNC_BOARD_MAGIC) + return (-ENODEV); + + DPR_IOCTL(("dgnc_tty_ioctl start on port %d - cmd %s (%x), arg %lx\n", + ch->ch_portnum, dgnc_ioctl_name(cmd), cmd, arg)); + + DGNC_LOCK(ch->ch_lock, lock_flags); + + if (un->un_open_count <= 0) { + DPR_BASIC(("dgnc_tty_ioctl - unit not open.\n")); + DGNC_UNLOCK(ch->ch_lock, lock_flags); + return(-EIO); + } + + switch (cmd) { + + /* Here are all the standard ioctl's that we MUST implement */ + + case TCSBRK: + /* + * TCSBRK is SVID version: non-zero arg --> no break + * this behaviour is exploited by tcdrain(). + * + * According to POSIX.1 spec (7.2.2.1.2) breaks should be + * between 0.25 and 0.5 seconds so we'll ask for something + * in the middle: 0.375 seconds. + */ + rc = tty_check_change(tty); + DGNC_UNLOCK(ch->ch_lock, lock_flags); + if (rc) { + return(rc); + } + + rc = ch->ch_bd->bd_ops->drain(tty, 0); + + if (rc) { + DPR_IOCTL(("dgnc_tty_ioctl - bad return: %d ", rc)); + return(-EINTR); + } + + DGNC_LOCK(ch->ch_lock, lock_flags); + + if(((cmd == TCSBRK) && (!arg)) || (cmd == TCSBRKP)) { + ch->ch_bd->bd_ops->send_break(ch, 250); + } + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + DPR_IOCTL(("dgnc_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n", + ch->ch_portnum, dgnc_ioctl_name(cmd), cmd, arg)); + + return(0); + + + case TCSBRKP: + /* support for POSIX tcsendbreak() + * According to POSIX.1 spec (7.2.2.1.2) breaks should be + * between 0.25 and 0.5 seconds so we'll ask for something + * in the middle: 0.375 seconds. + */ + rc = tty_check_change(tty); + DGNC_UNLOCK(ch->ch_lock, lock_flags); + if (rc) { + return(rc); + } + + rc = ch->ch_bd->bd_ops->drain(tty, 0); + if (rc) { + DPR_IOCTL(("dgnc_tty_ioctl - bad return: %d ", rc)); + return(-EINTR); + } + + DGNC_LOCK(ch->ch_lock, lock_flags); + + ch->ch_bd->bd_ops->send_break(ch, 250); + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + DPR_IOCTL(("dgnc_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n", + ch->ch_portnum, dgnc_ioctl_name(cmd), cmd, arg)); + + return(0); + + case TIOCSBRK: + rc = tty_check_change(tty); + DGNC_UNLOCK(ch->ch_lock, lock_flags); + if (rc) { + return(rc); + } + + rc = ch->ch_bd->bd_ops->drain(tty, 0); + if (rc) { + DPR_IOCTL(("dgnc_tty_ioctl - bad return: %d ", rc)); + return(-EINTR); + } + + DGNC_LOCK(ch->ch_lock, lock_flags); + + ch->ch_bd->bd_ops->send_break(ch, 250); + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + DPR_IOCTL(("dgnc_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n", + ch->ch_portnum, dgnc_ioctl_name(cmd), cmd, arg)); + + return(0); + + case TIOCCBRK: + /* Do Nothing */ + DGNC_UNLOCK(ch->ch_lock, lock_flags); + return 0; + + case TIOCGSOFTCAR: + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + rc = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *) arg); + return(rc); + + case TIOCSSOFTCAR: + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + rc = get_user(arg, (unsigned long __user *) arg); + if (rc) + return(rc); + + DGNC_LOCK(ch->ch_lock, lock_flags); + tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); + ch->ch_bd->bd_ops->param(tty); + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + return(0); + + case TIOCMGET: + DGNC_UNLOCK(ch->ch_lock, lock_flags); + return(dgnc_get_modem_info(ch, uarg)); + + case TIOCMBIS: + case TIOCMBIC: + case TIOCMSET: + DGNC_UNLOCK(ch->ch_lock, lock_flags); + return(dgnc_set_modem_info(tty, cmd, uarg)); + + /* + * Here are any additional ioctl's that we want to implement + */ + + case TCFLSH: + /* + * The linux tty driver doesn't have a flush + * input routine for the driver, assuming all backed + * up data is in the line disc. buffers. However, + * we all know that's not the case. Here, we + * act on the ioctl, but then lie and say we didn't + * so the line discipline will process the flush + * also. + */ + rc = tty_check_change(tty); + if (rc) { + DGNC_UNLOCK(ch->ch_lock, lock_flags); + return(rc); + } + + if ((arg == TCIFLUSH) || (arg == TCIOFLUSH)) { + ch->ch_r_head = ch->ch_r_tail; + ch->ch_bd->bd_ops->flush_uart_read(ch); + /* Force queue flow control to be released, if needed */ + dgnc_check_queue_flow_control(ch); + } + + if ((arg == TCOFLUSH) || (arg == TCIOFLUSH)) { + if (!(un->un_type == DGNC_PRINT)) { + ch->ch_w_head = ch->ch_w_tail; + ch->ch_bd->bd_ops->flush_uart_write(ch); + + if (ch->ch_tun.un_flags & (UN_LOW|UN_EMPTY)) { + ch->ch_tun.un_flags &= ~(UN_LOW|UN_EMPTY); + wake_up_interruptible(&ch->ch_tun.un_flags_wait); + } + + if (ch->ch_pun.un_flags & (UN_LOW|UN_EMPTY)) { + ch->ch_pun.un_flags &= ~(UN_LOW|UN_EMPTY); + wake_up_interruptible(&ch->ch_pun.un_flags_wait); + } + + } + } + + /* pretend we didn't recognize this IOCTL */ + DGNC_UNLOCK(ch->ch_lock, lock_flags); + return(-ENOIOCTLCMD); + +#ifdef TIOCGETP + case TIOCGETP: +#endif + case TCGETS: + case TCGETA: +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) + if (tty->ldisc->ops->ioctl) { +#else + if (tty->ldisc.ops->ioctl) { +#endif + int retval = (-ENXIO); + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + if (tty->termios) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) + retval = ((tty->ldisc->ops->ioctl) (tty, file, cmd, arg)); +#else + retval = ((tty->ldisc.ops->ioctl) (tty, file, cmd, arg)); +#endif + } + + DPR_IOCTL(("dgnc_tty_ioctl (LINE:%d) finish on port %d - cmd %s (%x), arg %lx\n", + __LINE__, ch->ch_portnum, dgnc_ioctl_name(cmd), cmd, arg)); + return(retval); + } + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + DPR_IOCTL(("dgnc_tty_ioctl (LINE:%d) finish on port %d - cmd %s (%x), arg %lx\n", + __LINE__, ch->ch_portnum, dgnc_ioctl_name(cmd), cmd, arg)); + + return(-ENOIOCTLCMD); + + case TCSETSF: + case TCSETSW: + /* + * The linux tty driver doesn't have a flush + * input routine for the driver, assuming all backed + * up data is in the line disc. buffers. However, + * we all know that's not the case. Here, we + * act on the ioctl, but then lie and say we didn't + * so the line discipline will process the flush + * also. + */ + if (cmd == TCSETSF) { + /* flush rx */ + ch->ch_flags &= ~CH_STOP; + ch->ch_r_head = ch->ch_r_tail; + ch->ch_bd->bd_ops->flush_uart_read(ch); + /* Force queue flow control to be released, if needed */ + dgnc_check_queue_flow_control(ch); + } + + /* now wait for all the output to drain */ + DGNC_UNLOCK(ch->ch_lock, lock_flags); + rc = ch->ch_bd->bd_ops->drain(tty, 0); + if (rc) { + DPR_IOCTL(("dgnc_tty_ioctl - bad return: %d\n", rc)); + return(-EINTR); + } + + DPR_IOCTL(("dgnc_tty_ioctl finish on port %d - cmd %s (%x), arg %lx\n", + ch->ch_portnum, dgnc_ioctl_name(cmd), cmd, arg)); + + /* pretend we didn't recognize this */ + return(-ENOIOCTLCMD); + + case TCSETAW: + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + rc = ch->ch_bd->bd_ops->drain(tty, 0); + if (rc) { + DPR_IOCTL(("dgnc_tty_ioctl - bad return: %d ", rc)); + return(-EINTR); + } + + /* pretend we didn't recognize this */ + return(-ENOIOCTLCMD); + + case TCXONC: + DGNC_UNLOCK(ch->ch_lock, lock_flags); + /* Make the ld do it */ + return(-ENOIOCTLCMD); + + case DIGI_GETA: + /* get information for ditty */ + DGNC_UNLOCK(ch->ch_lock, lock_flags); + return(dgnc_tty_digigeta(tty, uarg)); + + case DIGI_SETAW: + case DIGI_SETAF: + + /* set information for ditty */ + if (cmd == (DIGI_SETAW)) { + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + rc = ch->ch_bd->bd_ops->drain(tty, 0); + if (rc) { + DPR_IOCTL(("dgnc_tty_ioctl - bad return: %d ", rc)); + return(-EINTR); + } + DGNC_LOCK(ch->ch_lock, lock_flags); + } + else { + tty_ldisc_flush(tty); + } + /* fall thru */ + + case DIGI_SETA: + DGNC_UNLOCK(ch->ch_lock, lock_flags); + return(dgnc_tty_digiseta(tty, uarg)); + + case DIGI_LOOPBACK: + { + uint loopback = 0; + /* Let go of locks when accessing user space, could sleep */ + DGNC_UNLOCK(ch->ch_lock, lock_flags); + rc = get_user(loopback, (unsigned int __user *) arg); + if (rc) + return(rc); + DGNC_LOCK(ch->ch_lock, lock_flags); + + /* Enable/disable internal loopback for this port */ + if (loopback) + ch->ch_flags |= CH_LOOPBACK; + else + ch->ch_flags &= ~(CH_LOOPBACK); + + ch->ch_bd->bd_ops->param(tty); + DGNC_UNLOCK(ch->ch_lock, lock_flags); + return(0); + } + + case DIGI_GETCUSTOMBAUD: + DGNC_UNLOCK(ch->ch_lock, lock_flags); + rc = put_user(ch->ch_custom_speed, (unsigned int __user *) arg); + return(rc); + + case DIGI_SETCUSTOMBAUD: + { + uint new_rate; + /* Let go of locks when accessing user space, could sleep */ + DGNC_UNLOCK(ch->ch_lock, lock_flags); + rc = get_user(new_rate, (unsigned int __user *) arg); + if (rc) + return(rc); + DGNC_LOCK(ch->ch_lock, lock_flags); + dgnc_set_custom_speed(ch, new_rate); + ch->ch_bd->bd_ops->param(tty); + DGNC_UNLOCK(ch->ch_lock, lock_flags); + return(0); + } + + /* + * This ioctl allows insertion of a character into the front + * of any pending data to be transmitted. + * + * This ioctl is to satify the "Send Character Immediate" + * call that the RealPort protocol spec requires. + */ + case DIGI_REALPORT_SENDIMMEDIATE: + { + unsigned char c; + DGNC_UNLOCK(ch->ch_lock, lock_flags); + rc = get_user(c, (unsigned char __user *) arg); + if (rc) + return(rc); + DGNC_LOCK(ch->ch_lock, lock_flags); + ch->ch_bd->bd_ops->send_immediate_char(ch, c); + DGNC_UNLOCK(ch->ch_lock, lock_flags); + return(0); + } + + /* + * This ioctl returns all the current counts for the port. + * + * This ioctl is to satify the "Line Error Counters" + * call that the RealPort protocol spec requires. + */ + case DIGI_REALPORT_GETCOUNTERS: + { + struct digi_getcounter buf; + + buf.norun = ch->ch_err_overrun; + buf.noflow = 0; /* The driver doesn't keep this stat */ + buf.nframe = ch->ch_err_frame; + buf.nparity = ch->ch_err_parity; + buf.nbreak = ch->ch_err_break; + buf.rbytes = ch->ch_rxcount; + buf.tbytes = ch->ch_txcount; + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + if (copy_to_user(uarg, &buf, sizeof(struct digi_getcounter))) { + return (-EFAULT); + } + return(0); + } + + /* + * This ioctl returns all current events. + * + * This ioctl is to satify the "Event Reporting" + * call that the RealPort protocol spec requires. + */ + case DIGI_REALPORT_GETEVENTS: + { + unsigned int events = 0; + + /* NOTE: MORE EVENTS NEEDS TO BE ADDED HERE */ + if (ch->ch_flags & CH_BREAK_SENDING) + events |= EV_TXB; + if ((ch->ch_flags & CH_STOP) || (ch->ch_flags & CH_FORCED_STOP)) { + events |= (EV_OPU | EV_OPS); + } + if ((ch->ch_flags & CH_STOPI) || (ch->ch_flags & CH_FORCED_STOPI)) { + events |= (EV_IPU | EV_IPS); + } + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + rc = put_user(events, (unsigned int __user *) arg); + return(rc); + } + + /* + * This ioctl returns TOUT and TIN counters based + * upon the values passed in by the RealPort Server. + * It also passes back whether the UART Transmitter is + * empty as well. + */ + case DIGI_REALPORT_GETBUFFERS: + { + struct digi_getbuffer buf; + int tdist; + int count; + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + /* + * Get data from user first. + */ + if (copy_from_user(&buf, uarg, sizeof(struct digi_getbuffer))) { + return (-EFAULT); + } + + DGNC_LOCK(ch->ch_lock, lock_flags); + + /* + * Figure out how much data is in our RX and TX queues. + */ + buf.rxbuf = (ch->ch_r_head - ch->ch_r_tail) & RQUEUEMASK; + buf.txbuf = (ch->ch_w_head - ch->ch_w_tail) & WQUEUEMASK; + + /* + * Is the UART empty? Add that value to whats in our TX queue. + */ + count = buf.txbuf + ch->ch_bd->bd_ops->get_uart_bytes_left(ch); + + /* + * Figure out how much data the RealPort Server believes should + * be in our TX queue. + */ + tdist = (buf.tIn - buf.tOut) & 0xffff; + + /* + * If we have more data than the RealPort Server believes we + * should have, reduce our count to its amount. + * + * This count difference CAN happen because the Linux LD can + * insert more characters into our queue for OPOST processing + * that the RealPort Server doesn't know about. + */ + if (buf.txbuf > tdist) { + buf.txbuf = tdist; + } + + /* + * Report whether our queue and UART TX are completely empty. + */ + if (count) { + buf.txdone = 0; + } else { + buf.txdone = 1; + } + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + if (copy_to_user(uarg, &buf, sizeof(struct digi_getbuffer))) { + return (-EFAULT); + } + return(0); + } + default: + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + DPR_IOCTL(("dgnc_tty_ioctl - in default\n")); + DPR_IOCTL(("dgnc_tty_ioctl end - cmd %s (%x), arg %lx\n", + dgnc_ioctl_name(cmd), cmd, arg)); + + return(-ENOIOCTLCMD); + } + + DGNC_UNLOCK(ch->ch_lock, lock_flags); + + DPR_IOCTL(("dgnc_tty_ioctl end - cmd %s (%x), arg %lx\n", + dgnc_ioctl_name(cmd), cmd, arg)); + + return(0); +} diff --git a/drivers/staging/dgnc/dgnc_tty.h b/drivers/staging/dgnc/dgnc_tty.h new file mode 100644 index 000000000000..deb388d2f4cf --- /dev/null +++ b/drivers/staging/dgnc/dgnc_tty.h @@ -0,0 +1,42 @@ +/* + * Copyright 2003 Digi International (www.digi.com) + * Scott H Kilau + * + * 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, EXPRESS OR IMPLIED; 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. + * + * NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!! + */ + +#ifndef __DGNC_TTY_H +#define __DGNC_TTY_H + +#include "dgnc_driver.h" + +int dgnc_tty_register(struct board_t *brd); + +int dgnc_tty_preinit(void); +int dgnc_tty_init(struct board_t *); + +void dgnc_tty_post_uninit(void); +void dgnc_tty_uninit(struct board_t *); + +void dgnc_input(struct channel_t *ch); +void dgnc_carrier(struct channel_t *ch); +void dgnc_wakeup_writes(struct channel_t *ch); +void dgnc_check_queue_flow_control(struct channel_t *ch); + +void dgnc_sniff_nowait_nolock(struct channel_t *ch, uchar *text, uchar *buf, int nbuf); + +#endif diff --git a/drivers/staging/dgnc/dgnc_types.h b/drivers/staging/dgnc/dgnc_types.h new file mode 100644 index 000000000000..4fa358535f84 --- /dev/null +++ b/drivers/staging/dgnc/dgnc_types.h @@ -0,0 +1,36 @@ +/* + * Copyright 2003 Digi International (www.digi.com) + * Scott H Kilau + * + * 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, EXPRESS OR IMPLIED; 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. + * + * NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!! + */ + +#ifndef __DGNC_TYPES_H +#define __DGNC_TYPES_H + +#ifndef TRUE +# define TRUE 1 +#endif + +#ifndef FALSE +# define FALSE 0 +#endif + +/* Required for our shared headers! */ +typedef unsigned char uchar; + +#endif diff --git a/drivers/staging/dgnc/digi.h b/drivers/staging/dgnc/digi.h new file mode 100644 index 000000000000..ab903823ab07 --- /dev/null +++ b/drivers/staging/dgnc/digi.h @@ -0,0 +1,419 @@ +/* + * Copyright 2003 Digi International (www.digi.com) + * Scott H Kilau + * + * 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, EXPRESS OR IMPLIED; 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. + * + * $Id: digi.h,v 1.1.1.1 2009/05/20 12:19:19 markh Exp $ + * + * NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!! + */ + +#ifndef __DIGI_H +#define __DIGI_H + +/************************************************************************ + *** Definitions for Digi ditty(1) command. + ************************************************************************/ + + +/* + * Copyright (c) 1988-96 Digi International Inc., All Rights Reserved. + */ + +/************************************************************************ + * This module provides application access to special Digi + * serial line enhancements which are not standard UNIX(tm) features. + ************************************************************************/ + +#if !defined(TIOCMODG) + +#define TIOCMODG ('d'<<8) | 250 /* get modem ctrl state */ +#define TIOCMODS ('d'<<8) | 251 /* set modem ctrl state */ + +#ifndef TIOCM_LE +#define TIOCM_LE 0x01 /* line enable */ +#define TIOCM_DTR 0x02 /* data terminal ready */ +#define TIOCM_RTS 0x04 /* request to send */ +#define TIOCM_ST 0x08 /* secondary transmit */ +#define TIOCM_SR 0x10 /* secondary receive */ +#define TIOCM_CTS 0x20 /* clear to send */ +#define TIOCM_CAR 0x40 /* carrier detect */ +#define TIOCM_RNG 0x80 /* ring indicator */ +#define TIOCM_DSR 0x100 /* data set ready */ +#define TIOCM_RI TIOCM_RNG /* ring (alternate) */ +#define TIOCM_CD TIOCM_CAR /* carrier detect (alt) */ +#endif + +#endif + +#if !defined(TIOCMSET) +#define TIOCMSET ('d'<<8) | 252 /* set modem ctrl state */ +#define TIOCMGET ('d'<<8) | 253 /* set modem ctrl state */ +#endif + +#if !defined(TIOCMBIC) +#define TIOCMBIC ('d'<<8) | 254 /* set modem ctrl state */ +#define TIOCMBIS ('d'<<8) | 255 /* set modem ctrl state */ +#endif + + +#if !defined(TIOCSDTR) +#define TIOCSDTR ('e'<<8) | 0 /* set DTR */ +#define TIOCCDTR ('e'<<8) | 1 /* clear DTR */ +#endif + +/************************************************************************ + * Ioctl command arguments for DIGI parameters. + ************************************************************************/ +#define DIGI_GETA ('e'<<8) | 94 /* Read params */ + +#define DIGI_SETA ('e'<<8) | 95 /* Set params */ +#define DIGI_SETAW ('e'<<8) | 96 /* Drain & set params */ +#define DIGI_SETAF ('e'<<8) | 97 /* Drain, flush & set params */ + +#define DIGI_KME ('e'<<8) | 98 /* Read/Write Host */ + /* Adapter Memory */ + +#define DIGI_GETFLOW ('e'<<8) | 99 /* Get startc/stopc flow */ + /* control characters */ +#define DIGI_SETFLOW ('e'<<8) | 100 /* Set startc/stopc flow */ + /* control characters */ +#define DIGI_GETAFLOW ('e'<<8) | 101 /* Get Aux. startc/stopc */ + /* flow control chars */ +#define DIGI_SETAFLOW ('e'<<8) | 102 /* Set Aux. startc/stopc */ + /* flow control chars */ + +#define DIGI_GEDELAY ('d'<<8) | 246 /* Get edelay */ +#define DIGI_SEDELAY ('d'<<8) | 247 /* Set edelay */ + +struct digiflow_t { + unsigned char startc; /* flow cntl start char */ + unsigned char stopc; /* flow cntl stop char */ +}; + + +#ifdef FLOW_2200 +#define F2200_GETA ('e'<<8) | 104 /* Get 2x36 flow cntl flags */ +#define F2200_SETAW ('e'<<8) | 105 /* Set 2x36 flow cntl flags */ +#define F2200_MASK 0x03 /* 2200 flow cntl bit mask */ +#define FCNTL_2200 0x01 /* 2x36 terminal flow cntl */ +#define PCNTL_2200 0x02 /* 2x36 printer flow cntl */ +#define F2200_XON 0xf8 +#define P2200_XON 0xf9 +#define F2200_XOFF 0xfa +#define P2200_XOFF 0xfb + +#define FXOFF_MASK 0x03 /* 2200 flow status mask */ +#define RCVD_FXOFF 0x01 /* 2x36 Terminal XOFF rcvd */ +#define RCVD_PXOFF 0x02 /* 2x36 Printer XOFF rcvd */ +#endif + +/************************************************************************ + * Values for digi_flags + ************************************************************************/ +#define DIGI_IXON 0x0001 /* Handle IXON in the FEP */ +#define DIGI_FAST 0x0002 /* Fast baud rates */ +#define RTSPACE 0x0004 /* RTS input flow control */ +#define CTSPACE 0x0008 /* CTS output flow control */ +#define DSRPACE 0x0010 /* DSR output flow control */ +#define DCDPACE 0x0020 /* DCD output flow control */ +#define DTRPACE 0x0040 /* DTR input flow control */ +#define DIGI_COOK 0x0080 /* Cooked processing done in FEP */ +#define DIGI_FORCEDCD 0x0100 /* Force carrier */ +#define DIGI_ALTPIN 0x0200 /* Alternate RJ-45 pin config */ +#define DIGI_AIXON 0x0400 /* Aux flow control in fep */ +#define DIGI_PRINTER 0x0800 /* Hold port open for flow cntrl*/ +#define DIGI_PP_INPUT 0x1000 /* Change parallel port to input*/ +#define DIGI_DTR_TOGGLE 0x2000 /* Support DTR Toggle */ +#define DIGI_422 0x4000 /* for 422/232 selectable panel */ +#define DIGI_RTS_TOGGLE 0x8000 /* Support RTS Toggle */ + +/************************************************************************ + * These options are not supported on the comxi. + ************************************************************************/ +#define DIGI_COMXI (DIGI_FAST|DIGI_COOK|DSRPACE|DCDPACE|DTRPACE) + +#define DIGI_PLEN 28 /* String length */ +#define DIGI_TSIZ 10 /* Terminal string len */ + +/************************************************************************ + * Structure used with ioctl commands for DIGI parameters. + ************************************************************************/ +struct digi_t { + unsigned short digi_flags; /* Flags (see above) */ + unsigned short digi_maxcps; /* Max printer CPS */ + unsigned short digi_maxchar; /* Max chars in print queue */ + unsigned short digi_bufsize; /* Buffer size */ + unsigned char digi_onlen; /* Length of ON string */ + unsigned char digi_offlen; /* Length of OFF string */ + char digi_onstr[DIGI_PLEN]; /* Printer on string */ + char digi_offstr[DIGI_PLEN]; /* Printer off string */ + char digi_term[DIGI_TSIZ]; /* terminal string */ +}; + +/************************************************************************ + * KME definitions and structures. + ************************************************************************/ +#define RW_IDLE 0 /* Operation complete */ +#define RW_READ 1 /* Read Concentrator Memory */ +#define RW_WRITE 2 /* Write Concentrator Memory */ + +struct rw_t { + unsigned char rw_req; /* Request type */ + unsigned char rw_board; /* Host Adapter board number */ + unsigned char rw_conc; /* Concentrator number */ + unsigned char rw_reserved; /* Reserved for expansion */ + unsigned int rw_addr; /* Address in concentrator */ + unsigned short rw_size; /* Read/write request length */ + unsigned char rw_data[128]; /* Data to read/write */ +}; + +/*********************************************************************** + * Shrink Buffer and Board Information definitions and structures. + + ************************************************************************/ + /* Board type return codes */ +#define PCXI_TYPE 1 /* Board type at the designated port is a PC/Xi */ +#define PCXM_TYPE 2 /* Board type at the designated port is a PC/Xm */ +#define PCXE_TYPE 3 /* Board type at the designated port is a PC/Xe */ +#define MCXI_TYPE 4 /* Board type at the designated port is a MC/Xi */ +#define COMXI_TYPE 5 /* Board type at the designated port is a COM/Xi */ + + /* Non-Zero Result codes. */ +#define RESULT_NOBDFND 1 /* A Digi product at that port is not config installed */ +#define RESULT_NODESCT 2 /* A memory descriptor was not obtainable */ +#define RESULT_NOOSSIG 3 /* FEP/OS signature was not detected on the board */ +#define RESULT_TOOSML 4 /* Too small an area to shrink. */ +#define RESULT_NOCHAN 5 /* Channel structure for the board was not found */ + +struct shrink_buf_struct { + unsigned int shrink_buf_vaddr; /* Virtual address of board */ + unsigned int shrink_buf_phys; /* Physical address of board */ + unsigned int shrink_buf_bseg; /* Amount of board memory */ + unsigned int shrink_buf_hseg; /* '186 Begining of Dual-Port */ + + unsigned int shrink_buf_lseg; /* '186 Begining of freed memory */ + unsigned int shrink_buf_mseg; /* Linear address from start of + dual-port were freed memory + begins, host viewpoint. */ + + unsigned int shrink_buf_bdparam; /* Parameter for xxmemon and + xxmemoff */ + + unsigned int shrink_buf_reserva; /* Reserved */ + unsigned int shrink_buf_reservb; /* Reserved */ + unsigned int shrink_buf_reservc; /* Reserved */ + unsigned int shrink_buf_reservd; /* Reserved */ + + unsigned char shrink_buf_result; /* Reason for call failing + Zero is Good return */ + unsigned char shrink_buf_init; /* Non-Zero if it caused an + xxinit call. */ + + unsigned char shrink_buf_anports; /* Number of async ports */ + unsigned char shrink_buf_snports; /* Number of sync ports */ + unsigned char shrink_buf_type; /* Board type 1 = PC/Xi, + 2 = PC/Xm, + 3 = PC/Xe + 4 = MC/Xi + 5 = COMX/i */ + unsigned char shrink_buf_card; /* Card number */ + +}; + +/************************************************************************ + * Structure to get driver status information + ************************************************************************/ +struct digi_dinfo { + unsigned int dinfo_nboards; /* # boards configured */ + char dinfo_reserved[12]; /* for future expansion */ + char dinfo_version[16]; /* driver version */ +}; + +#define DIGI_GETDD ('d'<<8) | 248 /* get driver info */ + +/************************************************************************ + * Structure used with ioctl commands for per-board information + * + * physsize and memsize differ when board has "windowed" memory + ************************************************************************/ +struct digi_info { + unsigned int info_bdnum; /* Board number (0 based) */ + unsigned int info_ioport; /* io port address */ + unsigned int info_physaddr; /* memory address */ + unsigned int info_physsize; /* Size of host mem window */ + unsigned int info_memsize; /* Amount of dual-port mem */ + /* on board */ + unsigned short info_bdtype; /* Board type */ + unsigned short info_nports; /* number of ports */ + char info_bdstate; /* board state */ + char info_reserved[7]; /* for future expansion */ +}; + +#define DIGI_GETBD ('d'<<8) | 249 /* get board info */ + +struct digi_stat { + unsigned int info_chan; /* Channel number (0 based) */ + unsigned int info_brd; /* Board number (0 based) */ + unsigned int info_cflag; /* cflag for channel */ + unsigned int info_iflag; /* iflag for channel */ + unsigned int info_oflag; /* oflag for channel */ + unsigned int info_mstat; /* mstat for channel */ + unsigned int info_tx_data; /* tx_data for channel */ + unsigned int info_rx_data; /* rx_data for channel */ + unsigned int info_hflow; /* hflow for channel */ + unsigned int info_reserved[8]; /* for future expansion */ +}; + +#define DIGI_GETSTAT ('d'<<8) | 244 /* get board info */ +/************************************************************************ + * + * Structure used with ioctl commands for per-channel information + * + ************************************************************************/ +struct digi_ch { + unsigned int info_bdnum; /* Board number (0 based) */ + unsigned int info_channel; /* Channel index number */ + unsigned int info_ch_cflag; /* Channel cflag */ + unsigned int info_ch_iflag; /* Channel iflag */ + unsigned int info_ch_oflag; /* Channel oflag */ + unsigned int info_chsize; /* Channel structure size */ + unsigned int info_sleep_stat; /* sleep status */ + dev_t info_dev; /* device number */ + unsigned char info_initstate; /* Channel init state */ + unsigned char info_running; /* Channel running state */ + int reserved[8]; /* reserved for future use */ +}; + +/* +* This structure is used with the DIGI_FEPCMD ioctl to +* tell the driver which port to send the command for. +*/ +struct digi_cmd { + int cmd; + int word; + int ncmds; + int chan; /* channel index (zero based) */ + int bdid; /* board index (zero based) */ +}; + + +struct digi_getbuffer /* Struct for holding buffer use counts */ +{ + unsigned long tIn; + unsigned long tOut; + unsigned long rxbuf; + unsigned long txbuf; + unsigned long txdone; +}; + +struct digi_getcounter +{ + unsigned long norun; /* number of UART overrun errors */ + unsigned long noflow; /* number of buffer overflow errors */ + unsigned long nframe; /* number of framing errors */ + unsigned long nparity; /* number of parity errors */ + unsigned long nbreak; /* number of breaks received */ + unsigned long rbytes; /* number of received bytes */ + unsigned long tbytes; /* number of bytes transmitted fully */ +}; + +/* +* info_sleep_stat defines +*/ +#define INFO_RUNWAIT 0x0001 +#define INFO_WOPEN 0x0002 +#define INFO_TTIOW 0x0004 +#define INFO_CH_RWAIT 0x0008 +#define INFO_CH_WEMPTY 0x0010 +#define INFO_CH_WLOW 0x0020 +#define INFO_XXBUF_BUSY 0x0040 + +#define DIGI_GETCH ('d'<<8) | 245 /* get board info */ + +/* Board type definitions */ + +#define SUBTYPE 0007 +#define T_PCXI 0000 +#define T_PCXM 0001 +#define T_PCXE 0002 +#define T_PCXR 0003 +#define T_SP 0004 +#define T_SP_PLUS 0005 +# define T_HERC 0000 +# define T_HOU 0001 +# define T_LON 0002 +# define T_CHA 0003 +#define FAMILY 0070 +#define T_COMXI 0000 +#define T_PCXX 0010 +#define T_CX 0020 +#define T_EPC 0030 +#define T_PCLITE 0040 +#define T_SPXX 0050 +#define T_AVXX 0060 +#define T_DXB 0070 +#define T_A2K_4_8 0070 +#define BUSTYPE 0700 +#define T_ISABUS 0000 +#define T_MCBUS 0100 +#define T_EISABUS 0200 +#define T_PCIBUS 0400 + +/* Board State Definitions */ + +#define BD_RUNNING 0x0 +#define BD_REASON 0x7f +#define BD_NOTFOUND 0x1 +#define BD_NOIOPORT 0x2 +#define BD_NOMEM 0x3 +#define BD_NOBIOS 0x4 +#define BD_NOFEP 0x5 +#define BD_FAILED 0x6 +#define BD_ALLOCATED 0x7 +#define BD_TRIBOOT 0x8 +#define BD_BADKME 0x80 + +#define DIGI_SPOLL ('d'<<8) | 254 /* change poller rate */ + +#define DIGI_SETCUSTOMBAUD _IOW('e', 106, int) /* Set integer baud rate */ +#define DIGI_GETCUSTOMBAUD _IOR('e', 107, int) /* Get integer baud rate */ + +#define DIGI_REALPORT_GETBUFFERS ('e'<<8 ) | 108 +#define DIGI_REALPORT_SENDIMMEDIATE ('e'<<8 ) | 109 +#define DIGI_REALPORT_GETCOUNTERS ('e'<<8 ) | 110 +#define DIGI_REALPORT_GETEVENTS ('e'<<8 ) | 111 + +#define EV_OPU 0x0001 //! + * + * 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, EXPRESS OR IMPLIED; 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. + * + * NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!! + */ + + +/* + * This structure holds data needed for the intelligent <--> nonintelligent + * DPA translation + */ + struct ni_info { + int board; + int channel; + int dtr; + int rts; + int cts; + int dsr; + int ri; + int dcd; + int curtx; + int currx; + unsigned short iflag; + unsigned short oflag; + unsigned short cflag; + unsigned short lflag; + + unsigned int mstat; + unsigned char hflow; + + unsigned char xmit_stopped; + unsigned char recv_stopped; + + unsigned int baud; +}; + +#define RW_READ 1 +#define RW_WRITE 2 +#define DIGI_KME ('e'<<8) | 98 /* Read/Write Host */ + +#define SUBTYPE 0007 +#define T_PCXI 0000 +#define T_PCXEM 0001 +#define T_PCXE 0002 +#define T_PCXR 0003 +#define T_SP 0004 +#define T_SP_PLUS 0005 + +#define T_HERC 0000 +#define T_HOU 0001 +#define T_LON 0002 +#define T_CHA 0003 + +#define T_NEO 0000 +#define T_NEO_EXPRESS 0001 +#define T_CLASSIC 0002 + +#define FAMILY 0070 +#define T_COMXI 0000 +#define T_NI 0000 +#define T_PCXX 0010 +#define T_CX 0020 +#define T_EPC 0030 +#define T_PCLITE 0040 +#define T_SPXX 0050 +#define T_AVXX 0060 +#define T_DXB 0070 +#define T_A2K_4_8 0070 + +#define BUSTYPE 0700 +#define T_ISABUS 0000 +#define T_MCBUS 0100 +#define T_EISABUS 0200 +#define T_PCIBUS 0400 + +/* Board State Definitions */ + +#define BD_RUNNING 0x0 +#define BD_REASON 0x7f +#define BD_NOTFOUND 0x1 +#define BD_NOIOPORT 0x2 +#define BD_NOMEM 0x3 +#define BD_NOBIOS 0x4 +#define BD_NOFEP 0x5 +#define BD_FAILED 0x6 +#define BD_ALLOCATED 0x7 +#define BD_TRIBOOT 0x8 +#define BD_BADKME 0x80 + +#define DIGI_AIXON 0x0400 /* Aux flow control in fep */ + +/* Ioctls needed for dpa operation */ + +#define DIGI_GETDD ('d'<<8) | 248 /* get driver info */ +#define DIGI_GETBD ('d'<<8) | 249 /* get board info */ +#define DIGI_GET_NI_INFO ('d'<<8) | 250 /* nonintelligent state snfo */ + +/* Other special ioctls */ +#define DIGI_TIMERIRQ ('d'<<8) | 251 /* Enable/disable RS_TIMER use */ +#define DIGI_LOOPBACK ('d'<<8) | 252 /* Enable/disable UART internal loopback */ From c6c2401d8bbaf9edc189b4c35a8cb2780b8b988e Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Wed, 3 Jul 2013 23:33:51 -0400 Subject: [PATCH 1294/3400] tracing/uprobes: Fail to unregister if probe event files are in use Uprobes suffer the same problem that kprobes have. There's a race between writing to the "enable" file and removing the probe. The probe checks for it being in use and if it is not, goes about deleting the probe and the event that represents it. But the problem with that is, after it checks if it is in use it can be enabled, and the deletion of the event (access to the probe) will fail, as it is in use. But the uprobe will still be deleted. This is a problem as the event can reference the uprobe that was deleted. The fix is to remove the event first, and check to make sure the event removal succeeds. Then it is safe to remove the probe. When the event exists, either ftrace or perf can enable the probe and prevent the event from being removed. Link: http://lkml.kernel.org/r/20130704034038.991525256@goodmis.org Acked-by: Oleg Nesterov Signed-off-by: Steven Rostedt --- kernel/trace/trace_uprobe.c | 51 +++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c index a23d2d71188e..272261b5f94f 100644 --- a/kernel/trace/trace_uprobe.c +++ b/kernel/trace/trace_uprobe.c @@ -70,7 +70,7 @@ struct trace_uprobe { (sizeof(struct probe_arg) * (n))) static int register_uprobe_event(struct trace_uprobe *tu); -static void unregister_uprobe_event(struct trace_uprobe *tu); +static int unregister_uprobe_event(struct trace_uprobe *tu); static DEFINE_MUTEX(uprobe_lock); static LIST_HEAD(uprobe_list); @@ -164,11 +164,17 @@ static struct trace_uprobe *find_probe_event(const char *event, const char *grou } /* Unregister a trace_uprobe and probe_event: call with locking uprobe_lock */ -static void unregister_trace_uprobe(struct trace_uprobe *tu) +static int unregister_trace_uprobe(struct trace_uprobe *tu) { + int ret; + + ret = unregister_uprobe_event(tu); + if (ret) + return ret; + list_del(&tu->list); - unregister_uprobe_event(tu); free_trace_uprobe(tu); + return 0; } /* Register a trace_uprobe and probe_event */ @@ -181,9 +187,12 @@ static int register_trace_uprobe(struct trace_uprobe *tu) /* register as an event */ old_tp = find_probe_event(tu->call.name, tu->call.class->system); - if (old_tp) + if (old_tp) { /* delete old event */ - unregister_trace_uprobe(old_tp); + ret = unregister_trace_uprobe(old_tp); + if (ret) + goto end; + } ret = register_uprobe_event(tu); if (ret) { @@ -256,6 +265,8 @@ static int create_trace_uprobe(int argc, char **argv) group = UPROBE_EVENT_SYSTEM; if (is_delete) { + int ret; + if (!event) { pr_info("Delete command needs an event name.\n"); return -EINVAL; @@ -269,9 +280,9 @@ static int create_trace_uprobe(int argc, char **argv) return -ENOENT; } /* delete an event */ - unregister_trace_uprobe(tu); + ret = unregister_trace_uprobe(tu); mutex_unlock(&uprobe_lock); - return 0; + return ret; } if (argc < 2) { @@ -408,16 +419,20 @@ fail_address_parse: return ret; } -static void cleanup_all_probes(void) +static int cleanup_all_probes(void) { struct trace_uprobe *tu; + int ret = 0; mutex_lock(&uprobe_lock); while (!list_empty(&uprobe_list)) { tu = list_entry(uprobe_list.next, struct trace_uprobe, list); - unregister_trace_uprobe(tu); + ret = unregister_trace_uprobe(tu); + if (ret) + break; } mutex_unlock(&uprobe_lock); + return ret; } /* Probes listing interfaces */ @@ -462,8 +477,13 @@ static const struct seq_operations probes_seq_op = { static int probes_open(struct inode *inode, struct file *file) { - if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC)) - cleanup_all_probes(); + int ret; + + if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC)) { + ret = cleanup_all_probes(); + if (ret) + return ret; + } return seq_open(file, &probes_seq_op); } @@ -968,12 +988,17 @@ static int register_uprobe_event(struct trace_uprobe *tu) return ret; } -static void unregister_uprobe_event(struct trace_uprobe *tu) +static int unregister_uprobe_event(struct trace_uprobe *tu) { + int ret; + /* tu->event is unregistered in trace_remove_event_call() */ - trace_remove_event_call(&tu->call); + ret = trace_remove_event_call(&tu->call); + if (ret) + return ret; kfree(tu->call.print_fmt); tu->call.print_fmt = NULL; + return 0; } /* Make a trace interface for controling probe points */ From 6b0a1cf732f917f2eaccb4a0dd6ae7bfc3ccda15 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Thu, 1 Aug 2013 19:09:13 +0200 Subject: [PATCH 1295/3400] USB: ohci-at91: add usb_clk for transition to common clk framework The AT91 PMC (Power Management Controller) provides an USB clock used by USB Full Speed host (ohci) and USB Full Speed device (udc). The usb drivers (ohci and udc) must configure this clock to 48Mhz. This configuration was formely done in mach-at91/clock.c, but this implementation will be removed when moving to common clk framework. This patch adds support for usb clock retrieval and configuration, and is backward compatible with the current at91 clk implementation (if usb clk is not found, it does not configure/enable it). Changes since v1: - use IS_ENABLED(CONFIG_COMMON_CLK) to isolate new at91 clk support Signed-off-by: Boris BREZILLON Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-at91.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index a87564559e03..b3cdd1467521 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -31,8 +31,8 @@ #define at91_for_each_port(index) \ for ((index) = 0; (index) < AT91_MAX_USBH_PORTS; (index)++) -/* interface and function clocks; sometimes also an AHB clock */ -static struct clk *iclk, *fclk, *hclk; +/* interface, function and usb clocks; sometimes also an AHB clock */ +static struct clk *iclk, *fclk, *uclk, *hclk; static int clocked; extern int usb_disabled(void); @@ -41,6 +41,10 @@ extern int usb_disabled(void); static void at91_start_clock(void) { + if (IS_ENABLED(CONFIG_COMMON_CLK)) { + clk_set_rate(uclk, 48000000); + clk_prepare_enable(uclk); + } clk_prepare_enable(hclk); clk_prepare_enable(iclk); clk_prepare_enable(fclk); @@ -52,6 +56,8 @@ static void at91_stop_clock(void) clk_disable_unprepare(fclk); clk_disable_unprepare(iclk); clk_disable_unprepare(hclk); + if (IS_ENABLED(CONFIG_COMMON_CLK)) + clk_disable_unprepare(uclk); clocked = 0; } @@ -162,6 +168,14 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver, retval = PTR_ERR(hclk); goto err5; } + if (IS_ENABLED(CONFIG_COMMON_CLK)) { + uclk = clk_get(&pdev->dev, "usb_clk"); + if (IS_ERR(uclk)) { + dev_err(&pdev->dev, "failed to get uclk\n"); + retval = PTR_ERR(uclk); + goto err6; + } + } at91_start_hc(pdev); ohci_hcd_init(hcd_to_ohci(hcd)); @@ -173,6 +187,9 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver, /* Error handling */ at91_stop_hc(pdev); + if (IS_ENABLED(CONFIG_COMMON_CLK)) + clk_put(uclk); + err6: clk_put(hclk); err5: clk_put(fclk); @@ -212,6 +229,8 @@ static void usb_hcd_at91_remove(struct usb_hcd *hcd, release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); + if (IS_ENABLED(CONFIG_COMMON_CLK)) + clk_put(uclk); clk_put(hclk); clk_put(fclk); clk_put(iclk); From cfc25993e81f3fa68481d062be634d33184d5eae Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Wed, 29 May 2013 11:29:07 +0200 Subject: [PATCH 1296/3400] Drivers: hv: remove HV_DRV_VERSION Remove HV_DRV_VERSION, it has no meaning for upstream drivers. Initially it was supposed to show the "Linux Integration Services" version, now it is not in sync anymore with the out-of-tree drivers available from the MSFT website. The only place where a version string is still required is the KVP command "IntegrationServicesVersion" which is handled by tools/hv/hv_kvp_daemon.c. To satisfy such KVP request from the host pass the current string to the daemon during KVP userland registration. Signed-off-by: Olaf Hering Acked-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- drivers/hid/hid-hyperv.c | 1 - drivers/hv/hv_balloon.c | 1 - drivers/hv/hv_kvp.c | 2 ++ drivers/hv/hv_util.c | 1 - drivers/hv/vmbus_drv.c | 1 - drivers/net/hyperv/netvsc_drv.c | 2 -- drivers/scsi/storvsc_drv.c | 1 - drivers/video/hyperv_fb.c | 1 - include/linux/hyperv.h | 21 --------------------- 9 files changed, 2 insertions(+), 29 deletions(-) diff --git a/drivers/hid/hid-hyperv.c b/drivers/hid/hid-hyperv.c index 713217380b44..8fae6d1414cc 100644 --- a/drivers/hid/hid-hyperv.c +++ b/drivers/hid/hid-hyperv.c @@ -590,6 +590,5 @@ static void __exit mousevsc_exit(void) } MODULE_LICENSE("GPL"); -MODULE_VERSION(HV_DRV_VERSION); module_init(mousevsc_init); module_exit(mousevsc_exit); diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c index 2d094cfdb1e0..7e17a5495e02 100644 --- a/drivers/hv/hv_balloon.c +++ b/drivers/hv/hv_balloon.c @@ -1526,5 +1526,4 @@ static int __init init_balloon_drv(void) module_init(init_balloon_drv); MODULE_DESCRIPTION("Hyper-V Balloon"); -MODULE_VERSION(HV_DRV_VERSION); MODULE_LICENSE("GPL"); diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c index 53127209a404..28b03325b872 100644 --- a/drivers/hv/hv_kvp.c +++ b/drivers/hv/hv_kvp.c @@ -86,7 +86,9 @@ static u8 *recv_buffer; /* * Register the kernel component with the user-level daemon. * As part of this registration, pass the LIC version number. + * This number has no meaning, it satisfies the registration protocol. */ +#define HV_DRV_VERSION "3.1" static void kvp_register(int reg_value) diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c index c16164d4a28b..cb82233541b1 100644 --- a/drivers/hv/hv_util.c +++ b/drivers/hv/hv_util.c @@ -395,5 +395,4 @@ module_init(init_hyperv_utils); module_exit(exit_hyperv_utils); MODULE_DESCRIPTION("Hyper-V Utilities"); -MODULE_VERSION(HV_DRV_VERSION); MODULE_LICENSE("GPL"); diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index e8e071fc1d6d..f9fe46f52cfa 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -816,7 +816,6 @@ static void __exit vmbus_exit(void) MODULE_LICENSE("GPL"); -MODULE_VERSION(HV_DRV_VERSION); subsys_initcall(hv_acpi_init); module_exit(vmbus_exit); diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 23a0fff0df52..524f713f6017 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -306,7 +306,6 @@ static void netvsc_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info) { strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver)); - strlcpy(info->version, HV_DRV_VERSION, sizeof(info->version)); strlcpy(info->fw_version, "N/A", sizeof(info->fw_version)); } @@ -529,7 +528,6 @@ static int __init netvsc_drv_init(void) } MODULE_LICENSE("GPL"); -MODULE_VERSION(HV_DRV_VERSION); MODULE_DESCRIPTION("Microsoft Hyper-V network driver"); module_init(netvsc_drv_init); diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 83ec1aa85964..1a28f5632797 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1879,7 +1879,6 @@ static void __exit storvsc_drv_exit(void) } MODULE_LICENSE("GPL"); -MODULE_VERSION(HV_DRV_VERSION); MODULE_DESCRIPTION("Microsoft Hyper-V virtual storage driver"); module_init(storvsc_drv_init); module_exit(storvsc_drv_exit); diff --git a/drivers/video/hyperv_fb.c b/drivers/video/hyperv_fb.c index d4d2c5fe2488..8ac99b87c07e 100644 --- a/drivers/video/hyperv_fb.c +++ b/drivers/video/hyperv_fb.c @@ -825,5 +825,4 @@ module_init(hvfb_drv_init); module_exit(hvfb_drv_exit); MODULE_LICENSE("GPL"); -MODULE_VERSION(HV_DRV_VERSION); MODULE_DESCRIPTION("Microsoft Hyper-V Synthetic Video Frame Buffer Driver"); diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 49949079cf47..a3b8b2e2d244 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -463,27 +463,6 @@ hv_get_ringbuffer_availbytes(struct hv_ring_buffer_info *rbi, *read = dsize - *write; } - -/* - * We use the same version numbering for all Hyper-V modules. - * - * Definition of versioning is as follows; - * - * Major Number Changes for these scenarios; - * 1. When a new version of Windows Hyper-V - * is released. - * 2. A Major change has occurred in the - * Linux IC's. - * (For example the merge for the first time - * into the kernel) Every time the Major Number - * changes, the Revision number is reset to 0. - * Minor Number Changes when new functionality is added - * to the Linux IC's that is not a bug fix. - * - * 3.1 - Added completed hv_utils driver. Shutdown/Heartbeat/Timesync - */ -#define HV_DRV_VERSION "3.1" - /* * VMBUS version is 32 bit entity broken up into * two 16 bit quantities: major_number. minor_number. From b4919a5f95c09992f66d4b7cbe392c33731a5cec Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Thu, 1 Aug 2013 14:34:26 +0200 Subject: [PATCH 1297/3400] Tools: hv: fix send/recv buffer allocation hv_kvp_daemon fails to start in current openSuSE 13.1 snapshots because the kvp_send_buffer is too small to hold cn_msg+hv_kvp_msg, the very first sendmsg returns with EFAULT. In addition it fixes the Network info tab in Windows Server 2012R2 in SLES11. Adjust the code in kvp and vss daemon to allocate the needed buffers at runtime. To keep the code simple, the buffer_len includes also the nlmsghdr, although only the recv_buffer needs this extra space. Signed-off-by: Olaf Hering Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- tools/hv/hv_kvp_daemon.c | 15 ++++++++++++--- tools/hv/hv_vss_daemon.c | 15 ++++++++++++--- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c index 07819bfa7dba..657c1d27e02e 100644 --- a/tools/hv/hv_kvp_daemon.c +++ b/tools/hv/hv_kvp_daemon.c @@ -79,8 +79,6 @@ enum { DNS }; -static char kvp_send_buffer[4096]; -static char kvp_recv_buffer[4096 * 2]; static struct sockaddr_nl addr; static int in_hand_shake = 1; @@ -1437,10 +1435,21 @@ int main(void) int pool; char *if_name; struct hv_kvp_ipaddr_value *kvp_ip_val; + char *kvp_send_buffer; + char *kvp_recv_buffer; + size_t kvp_recv_buffer_len; daemon(1, 0); openlog("KVP", 0, LOG_USER); syslog(LOG_INFO, "KVP starting; pid is:%d", getpid()); + + kvp_recv_buffer_len = NLMSG_HDRLEN + sizeof(struct cn_msg) + sizeof(struct hv_kvp_msg); + kvp_send_buffer = calloc(1, kvp_recv_buffer_len); + kvp_recv_buffer = calloc(1, kvp_recv_buffer_len); + if (!(kvp_send_buffer && kvp_recv_buffer)) { + syslog(LOG_ERR, "Failed to allocate netlink buffers"); + exit(EXIT_FAILURE); + } /* * Retrieve OS release information. */ @@ -1514,7 +1523,7 @@ int main(void) continue; } - len = recvfrom(fd, kvp_recv_buffer, sizeof(kvp_recv_buffer), 0, + len = recvfrom(fd, kvp_recv_buffer, kvp_recv_buffer_len, 0, addr_p, &addr_l); if (len < 0) { diff --git a/tools/hv/hv_vss_daemon.c b/tools/hv/hv_vss_daemon.c index 826d499dc354..4213d0e3083f 100644 --- a/tools/hv/hv_vss_daemon.c +++ b/tools/hv/hv_vss_daemon.c @@ -38,8 +38,6 @@ #include #include -static char vss_recv_buffer[4096]; -static char vss_send_buffer[4096]; static struct sockaddr_nl addr; #ifndef SOL_NETLINK @@ -147,6 +145,9 @@ int main(void) struct cn_msg *incoming_cn_msg; int op; struct hv_vss_msg *vss_msg; + char *vss_send_buffer; + char *vss_recv_buffer; + size_t vss_recv_buffer_len; if (daemon(1, 0)) return 1; @@ -154,6 +155,14 @@ int main(void) openlog("Hyper-V VSS", 0, LOG_USER); syslog(LOG_INFO, "VSS starting; pid is:%d", getpid()); + vss_recv_buffer_len = NLMSG_HDRLEN + sizeof(struct cn_msg) + sizeof(struct hv_vss_msg); + vss_send_buffer = calloc(1, vss_recv_buffer_len); + vss_recv_buffer = calloc(1, vss_recv_buffer_len); + if (!(vss_send_buffer && vss_recv_buffer)) { + syslog(LOG_ERR, "Failed to allocate netlink buffers"); + exit(EXIT_FAILURE); + } + fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); if (fd < 0) { syslog(LOG_ERR, "netlink socket creation failed; error:%d %s", @@ -215,7 +224,7 @@ int main(void) continue; } - len = recvfrom(fd, vss_recv_buffer, sizeof(vss_recv_buffer), 0, + len = recvfrom(fd, vss_recv_buffer, vss_recv_buffer_len, 0, addr_p, &addr_l); if (len < 0) { From 00663d73e39a4aec0c310bb5fc1c2c8dfccf1319 Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Thu, 1 Aug 2013 14:43:12 +0200 Subject: [PATCH 1298/3400] Tools: hv: check return value of daemon to fix compiler warning. hv_kvp_daemon.c: In function 'main': hv_kvp_daemon.c:1441:8: warning: ignoring return value of 'daemon', declared with attribute warn_unused_result [-Wunused-result] Signed-off-by: Olaf Hering Signed-off-by: K. Y. Srinivasan Signed-off-by: Greg Kroah-Hartman --- tools/hv/hv_kvp_daemon.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c index 657c1d27e02e..418ac5548f98 100644 --- a/tools/hv/hv_kvp_daemon.c +++ b/tools/hv/hv_kvp_daemon.c @@ -1439,7 +1439,8 @@ int main(void) char *kvp_recv_buffer; size_t kvp_recv_buffer_len; - daemon(1, 0); + if (daemon(1, 0)) + return 1; openlog("KVP", 0, LOG_USER); syslog(LOG_INFO, "KVP starting; pid is:%d", getpid()); From cb50e5235b8ae5aa0fe422eaaa8e444024c5bd98 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Wed, 31 Jul 2013 14:05:45 -0400 Subject: [PATCH 1299/3400] tty: Only hangup once Instrumented testing shows a tty can be hungup multiple times [1]. Although concurrent hangups are properly serialized, multiple hangups for the same tty should be prevented. If tty has already been HUPPED, abort hangup. Note it is not necessary to cleanup file *redirect on subsequent hangups, as only TIOCCONS can set that value and ioctls are disabled after hangup. [1] Test performed by simulating a concurrent async hangup via tty_hangup() with a sync hangup via tty_vhangup(), while __tty_hangup() was instrumented with: diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 26bb78c..fe8b061 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -629,6 +629,8 @@ static void __tty_hangup(struct tty_struct *tty, int exit_session) tty_lock(tty); + WARN_ON(test_bit(TTY_HUPPED, &tty->flags)); + /* some functions below drop BTM, so we need this bit */ set_bit(TTY_HUPPING, &tty->flags); Test result: WARNING: at /home/peter/src/kernels/mainline/drivers/tty/tty_io.c:632 __tty_hangup+0x459/0x460() Modules linked in: ip6table_filter ip6_tables ebtable_nat <...snip...> CPU: 6 PID: 1197 Comm: kworker/6:2 Not tainted 3.10.0-0+rfcomm-xeon #0+rfcomm Hardware name: Dell Inc. Precision WorkStation T5400 /0RW203, BIOS A11 04/30/2012 Workqueue: events do_tty_hangup 0000000000000009 ffff8802b16d7d18 ffffffff816b553e ffff8802b16d7d58 ffffffff810407e0 ffff880254f95c00 ffff880254f95c00 ffff8802bfd92b00 ffff8802bfd96b00 ffff880254f95e40 0000000000000180 ffff8802b16d7d68 Call Trace: [] dump_stack+0x19/0x1b [] warn_slowpath_common+0x70/0xa0 [] warn_slowpath_null+0x1a/0x20 [] __tty_hangup+0x459/0x460 [] ? finish_task_switch+0xbc/0xe0 [] do_tty_hangup+0x17/0x20 [] process_one_work+0x16f/0x450 [] process_scheduled_works+0x2c/0x40 [] worker_thread+0x26a/0x380 [] ? rescuer_thread+0x310/0x310 [] kthread+0xc0/0xd0 [] ? destroy_compound_page+0x65/0x92 [] ? kthread_create_on_node+0x130/0x130 [] ret_from_fork+0x7c/0xb0 [] ? kthread_create_on_node+0x130/0x130 ---[ end trace 98d9f01536cf411e ]--- Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 26bb78c30a00..a9355ce1c6d5 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -629,6 +629,11 @@ static void __tty_hangup(struct tty_struct *tty, int exit_session) tty_lock(tty); + if (test_bit(TTY_HUPPED, &tty->flags)) { + tty_unlock(tty); + return; + } + /* some functions below drop BTM, so we need this bit */ set_bit(TTY_HUPPING, &tty->flags); From 5284eba7b37dfeffe75bfdf81a13e9efebe0480a Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Thu, 1 Aug 2013 21:49:19 -0700 Subject: [PATCH 1300/3400] serial/arc-uart: Handle Rx Error Interrupts w/o any data Currently, Rx error handling only triggers if there is some Rx data. Fix that by checking for error - before the data handling. Reported-by: Mischa Jonker Tested-by: Mischa Jonker Signed-off-by: Vineet Gupta Cc: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/arc_uart.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c index 2f195f0d7a11..e296c892df61 100644 --- a/drivers/tty/serial/arc_uart.c +++ b/drivers/tty/serial/arc_uart.c @@ -209,9 +209,9 @@ static void arc_serial_start_tx(struct uart_port *port) arc_serial_tx_chars(uart); } -static void arc_serial_rx_chars(struct arc_uart_port *uart) +static void arc_serial_rx_chars(struct arc_uart_port *uart, unsigned int status) { - unsigned int status, ch, flg = 0; + unsigned int ch, flg = 0; /* * UART has 4 deep RX-FIFO. Driver's recongnition of this fact @@ -222,11 +222,11 @@ static void arc_serial_rx_chars(struct arc_uart_port *uart) * before RX-EMPTY=0, implies some sort of buffering going on in the * controller, which is indeed the Rx-FIFO. */ - while (!((status = UART_GET_STATUS(uart)) & RXEMPTY)) { - - ch = UART_GET_DATA(uart); - uart->port.icount.rx++; - + do { + /* + * This could be an Rx Intr for err (no data), + * so check err and clear that Intr first + */ if (unlikely(status & (RXOERR | RXFERR))) { if (status & RXOERR) { uart->port.icount.overrun++; @@ -242,6 +242,12 @@ static void arc_serial_rx_chars(struct arc_uart_port *uart) } else flg = TTY_NORMAL; + if (status & RXEMPTY) + continue; + + ch = UART_GET_DATA(uart); + uart->port.icount.rx++; + if (unlikely(uart_handle_sysrq_char(&uart->port, ch))) goto done; @@ -249,7 +255,7 @@ static void arc_serial_rx_chars(struct arc_uart_port *uart) done: tty_flip_buffer_push(&uart->port.state->port); - } + } while (!((status = UART_GET_STATUS(uart)) & RXEMPTY)); } /* @@ -292,11 +298,11 @@ static irqreturn_t arc_serial_isr(int irq, void *dev_id) * notifications from the UART Controller. * To demultiplex between the two, we check the relevant bits */ - if ((status & RXIENB) && !(status & RXEMPTY)) { + if (status & RXIENB) { /* already in ISR, no need of xx_irqsave */ spin_lock(&uart->port.lock); - arc_serial_rx_chars(uart); + arc_serial_rx_chars(uart, status); spin_unlock(&uart->port.lock); } From 00a135b3952f6ccedfb688919c59bb3fa199a11f Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Thu, 1 Aug 2013 21:49:20 -0700 Subject: [PATCH 1301/3400] serial/arc-uart: Remove the goto/label Signed-off-by: Vineet Gupta Cc: Mischa Jonker Cc: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/arc_uart.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c index e296c892df61..6ac5270c74dd 100644 --- a/drivers/tty/serial/arc_uart.c +++ b/drivers/tty/serial/arc_uart.c @@ -248,12 +248,9 @@ static void arc_serial_rx_chars(struct arc_uart_port *uart, unsigned int status) ch = UART_GET_DATA(uart); uart->port.icount.rx++; - if (unlikely(uart_handle_sysrq_char(&uart->port, ch))) - goto done; + if (!(uart_handle_sysrq_char(&uart->port, ch))) + uart_insert_char(&uart->port, status, RXOERR, ch, flg); - uart_insert_char(&uart->port, status, RXOERR, ch, flg); - -done: tty_flip_buffer_push(&uart->port.state->port); } while (!((status = UART_GET_STATUS(uart)) & RXEMPTY)); } From 3ba35baa55fa4420f9ea7132d728ed68cfa37d28 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 1 Aug 2013 18:17:45 +0900 Subject: [PATCH 1302/3400] serial: sh-sci: use dev_get_platdata() Use the wrapper function for retrieving the platform data instead of accessing dev->platform_data directly Signed-off-by: Jingoo Han Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 72ca870f8e57..537750261aaa 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2469,7 +2469,7 @@ static int sci_probe_single(struct platform_device *dev, static int sci_probe(struct platform_device *dev) { - struct plat_sci_port *p = dev->dev.platform_data; + struct plat_sci_port *p = dev_get_platdata(&dev->dev); struct sci_port *sp = &sci_ports[dev->id]; int ret; From 64cb7ce9d4c44e96b54f9d8125817c9024031465 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Thu, 1 Aug 2013 09:32:29 +0900 Subject: [PATCH 1303/3400] staging: imx-drm: add missing MFD_SYSCON dependency for LDB Added missing MFD_SYSCON dependency for LVDS display bridge in order to fix the following link error. drivers/staging/imx-drm/imx-ldb.c:484: undefined reference to `syscon_regmap_lookup_by_phandle' Signed-off-by: Jingoo Han Acked-by: Philipp Zabel Signed-off-by: Greg Kroah-Hartman --- drivers/staging/imx-drm/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/imx-drm/Kconfig b/drivers/staging/imx-drm/Kconfig index 0f75afcc03c4..394254f7d6b5 100644 --- a/drivers/staging/imx-drm/Kconfig +++ b/drivers/staging/imx-drm/Kconfig @@ -32,7 +32,7 @@ config DRM_IMX_TVE config DRM_IMX_LDB tristate "Support for LVDS displays" - depends on DRM_IMX + depends on DRM_IMX && MFD_SYSCON help Choose this to enable the internal LVDS Display Bridge (LDB) found on i.MX53 and i.MX6 processors. From 8a3cac62efd0c447e017180aa7bf2638603ee21c Mon Sep 17 00:00:00 2001 From: Rupesh Gujare Date: Thu, 1 Aug 2013 18:40:00 +0100 Subject: [PATCH 1304/3400] staging: ozwpan: Use kernel list function for managing interface list. Managing interface list, is easier if we use kernel list_* API than managing it on our own. Signed-off-by: Rupesh Gujare Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ozwpan/ozproto.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/drivers/staging/ozwpan/ozproto.c b/drivers/staging/ozwpan/ozproto.c index ed22729ea90d..500800f9f0ee 100644 --- a/drivers/staging/ozwpan/ozproto.c +++ b/drivers/staging/ozwpan/ozproto.c @@ -37,7 +37,7 @@ struct oz_binding { struct packet_type ptype; char name[OZ_MAX_BINDING_LEN]; - struct oz_binding *next; + struct list_head link; }; /*------------------------------------------------------------------------------ @@ -45,7 +45,7 @@ struct oz_binding { */ static DEFINE_SPINLOCK(g_polling_lock); static LIST_HEAD(g_pd_list); -static struct oz_binding *g_binding ; +static LIST_HEAD(g_binding); static DEFINE_SPINLOCK(g_binding_lock); static struct sk_buff_head g_rx_queue; static u8 g_session_id; @@ -437,12 +437,13 @@ done: */ void oz_protocol_term(void) { + struct oz_binding *b, *t; + /* Walk the list of bindings and remove each one. */ spin_lock_bh(&g_binding_lock); - while (g_binding) { - struct oz_binding *b = g_binding; - g_binding = b->next; + list_for_each_entry_safe(b, t, &g_binding, link) { + list_del(&b->link); spin_unlock_bh(&g_binding_lock); dev_remove_pack(&b->ptype); if (b->ptype.dev) @@ -660,8 +661,7 @@ void oz_binding_add(char *net_dev) if (binding) { dev_add_pack(&binding->ptype); spin_lock_bh(&g_binding_lock); - binding->next = g_binding; - g_binding = binding; + list_add_tail(&binding->link, &g_binding); spin_unlock_bh(&g_binding_lock); } } @@ -710,28 +710,25 @@ static void pd_stop_all_for_device(struct net_device *net_dev) void oz_binding_remove(char *net_dev) { struct oz_binding *binding; - struct oz_binding **link; + int found = 0; + oz_dbg(ON, "Removing binding: %s\n", net_dev); spin_lock_bh(&g_binding_lock); - binding = g_binding; - link = &g_binding; - while (binding) { + list_for_each_entry(binding, &g_binding, link) { if (compare_binding_name(binding->name, net_dev)) { oz_dbg(ON, "Binding '%s' found\n", net_dev); - *link = binding->next; + found = 1; break; - } else { - link = &binding; - binding = binding->next; } } spin_unlock_bh(&g_binding_lock); - if (binding) { + if (found) { dev_remove_pack(&binding->ptype); if (binding->ptype.dev) { dev_put(binding->ptype.dev); pd_stop_all_for_device(binding->ptype.dev); } + list_del(&binding->link); kfree(binding); } } From 83e4817fc3a2092ac1545999705b799bea855bcb Mon Sep 17 00:00:00 2001 From: Rupesh Gujare Date: Thu, 1 Aug 2013 18:40:01 +0100 Subject: [PATCH 1305/3400] staging: ozwpan: Mark string as const Make sure that we mark const string so that it does not get modified. Signed-off-by: Rupesh Gujare Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ozwpan/ozproto.c | 6 +++--- drivers/staging/ozwpan/ozproto.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/ozwpan/ozproto.c b/drivers/staging/ozwpan/ozproto.c index 500800f9f0ee..2dbaba636e71 100644 --- a/drivers/staging/ozwpan/ozproto.c +++ b/drivers/staging/ozwpan/ozproto.c @@ -636,7 +636,7 @@ static int oz_pkt_recv(struct sk_buff *skb, struct net_device *dev, /*------------------------------------------------------------------------------ * Context: process */ -void oz_binding_add(char *net_dev) +void oz_binding_add(const char *net_dev) { struct oz_binding *binding; @@ -669,7 +669,7 @@ void oz_binding_add(char *net_dev) /*------------------------------------------------------------------------------ * Context: process */ -static int compare_binding_name(char *s1, char *s2) +static int compare_binding_name(const char *s1, const char *s2) { int i; for (i = 0; i < OZ_MAX_BINDING_LEN; i++) { @@ -707,7 +707,7 @@ static void pd_stop_all_for_device(struct net_device *net_dev) /*------------------------------------------------------------------------------ * Context: process */ -void oz_binding_remove(char *net_dev) +void oz_binding_remove(const char *net_dev) { struct oz_binding *binding; int found = 0; diff --git a/drivers/staging/ozwpan/ozproto.h b/drivers/staging/ozwpan/ozproto.h index 305c5321022d..e532347cfdfd 100644 --- a/drivers/staging/ozwpan/ozproto.h +++ b/drivers/staging/ozwpan/ozproto.h @@ -54,8 +54,8 @@ void oz_protocol_term(void); int oz_get_pd_list(struct oz_mac_addr *addr, int max_count); void oz_app_enable(int app_id, int enable); struct oz_pd *oz_pd_find(const u8 *mac_addr); -void oz_binding_add(char *net_dev); -void oz_binding_remove(char *net_dev); +void oz_binding_add(const char *net_dev); +void oz_binding_remove(const char *net_dev); void oz_timer_add(struct oz_pd *pd, int type, unsigned long due_time); void oz_timer_delete(struct oz_pd *pd, int type); void oz_pd_request_heartbeat(struct oz_pd *pd); From 4d6c9e57027940b6b492abac4c1b67710e38f366 Mon Sep 17 00:00:00 2001 From: Rupesh Gujare Date: Thu, 1 Aug 2013 18:40:02 +0100 Subject: [PATCH 1306/3400] staging: ozwpan: Use kernel strncmp function. Use kernel's strncmp() function instead of defining same within driver. Signed-off-by: Rupesh Gujare Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ozwpan/ozproto.c | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/drivers/staging/ozwpan/ozproto.c b/drivers/staging/ozwpan/ozproto.c index 2dbaba636e71..ec602863feca 100644 --- a/drivers/staging/ozwpan/ozproto.c +++ b/drivers/staging/ozwpan/ozproto.c @@ -666,21 +666,6 @@ void oz_binding_add(const char *net_dev) } } } -/*------------------------------------------------------------------------------ - * Context: process - */ -static int compare_binding_name(const char *s1, const char *s2) -{ - int i; - for (i = 0; i < OZ_MAX_BINDING_LEN; i++) { - if (*s1 != *s2) - return 0; - if (!*s1++) - return 1; - s2++; - } - return 1; -} /*------------------------------------------------------------------------------ * Context: process */ @@ -715,7 +700,7 @@ void oz_binding_remove(const char *net_dev) oz_dbg(ON, "Removing binding: %s\n", net_dev); spin_lock_bh(&g_binding_lock); list_for_each_entry(binding, &g_binding, link) { - if (compare_binding_name(binding->name, net_dev)) { + if (strncmp(binding->name, net_dev, OZ_MAX_BINDING_LEN) == 0) { oz_dbg(ON, "Binding '%s' found\n", net_dev); found = 1; break; From 2dc2ee5ccdaf88b41bf9c025acf14ebdc2959a21 Mon Sep 17 00:00:00 2001 From: Rupesh Gujare Date: Thu, 1 Aug 2013 18:40:03 +0100 Subject: [PATCH 1307/3400] staging: ozwpan: Drop oldest ISOC frame instead of dropping latest. In case of ISOC transfer, if TX queue is full then we start dropping latest frame, instead we should drop oldest frame & add latest frame to TX queue. Signed-off-by: Rupesh Gujare Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ozwpan/ozpd.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/staging/ozwpan/ozpd.c b/drivers/staging/ozwpan/ozpd.c index 86876bda29a5..17fd7b2aa88e 100644 --- a/drivers/staging/ozwpan/ozpd.c +++ b/drivers/staging/ozwpan/ozpd.c @@ -844,9 +844,20 @@ int oz_send_isoc_unit(struct oz_pd *pd, u8 ep_num, const u8 *data, int len) struct oz_tx_frame *isoc_unit = NULL; int nb = pd->nb_queued_isoc_frames; if (nb >= pd->isoc_latency) { + struct list_head *e; + struct oz_tx_frame *f; oz_dbg(TX_FRAMES, "Dropping ISOC Unit nb= %d\n", nb); - goto out; + spin_lock(&pd->tx_frame_lock); + list_for_each(e, &pd->tx_queue) { + f = container_of(e, struct oz_tx_frame, + link); + if (f->skb != NULL) { + oz_tx_isoc_free(pd, f); + break; + } + } + spin_unlock(&pd->tx_frame_lock); } isoc_unit = oz_tx_frame_alloc(pd); if (isoc_unit == NULL) From baaaef1383d3708f02b2316d2d6f2bda0980fad7 Mon Sep 17 00:00:00 2001 From: Rupesh Gujare Date: Thu, 1 Aug 2013 18:45:01 +0100 Subject: [PATCH 1308/3400] staging: ozwpan: Increase farewell report size. Farewell report size can be bigger than one byte, increase array size to accomodate maximum 32 bytes of farewell report. Signed-off-by: Rupesh Gujare Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ozwpan/ozpd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/ozwpan/ozpd.h b/drivers/staging/ozwpan/ozpd.h index a281753774e6..57e98c897711 100644 --- a/drivers/staging/ozwpan/ozpd.h +++ b/drivers/staging/ozwpan/ozpd.h @@ -48,7 +48,7 @@ struct oz_farewell { struct list_head link; u8 ep_num; u8 index; - u8 report[1]; + u8 report[32]; u8 len; }; From b50c460a6c03284f7e1b4cfe9266df0f9169ad24 Mon Sep 17 00:00:00 2001 From: Rupesh Gujare Date: Thu, 1 Aug 2013 18:45:02 +0100 Subject: [PATCH 1309/3400] staging: ozwpan: Set farewell report length. Fixes a bug where we were not setting length field causing wrong report size to be copied. Signed-off-by: Rupesh Gujare Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ozwpan/ozproto.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/ozwpan/ozproto.c b/drivers/staging/ozwpan/ozproto.c index ec602863feca..084307a1083f 100644 --- a/drivers/staging/ozwpan/ozproto.c +++ b/drivers/staging/ozwpan/ozproto.c @@ -296,6 +296,7 @@ static void oz_add_farewell(struct oz_pd *pd, u8 ep_num, u8 index, return; f->ep_num = ep_num; f->index = index; + f->len = len; memcpy(f->report, report, len); oz_dbg(ON, "RX: Adding farewell report\n"); spin_lock(&g_polling_lock); From 461a8ecb2d76fb6f3ac1a90eb886697db869d387 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 2 Aug 2013 15:25:19 +0800 Subject: [PATCH 1310/3400] Revert "serial: sccnxp: Add DT support" This reverts commit 85c996907473e4ef824774b97b26499adf66521f. Alexander wishes to remove this patch as it is incorrect. Reported-by: Alexander Shiyan Signed-off-by: Greg Kroah-Hartman --- .../bindings/tty/serial/sccnxp-serial.txt | 53 ------------------- drivers/tty/serial/sccnxp.c | 46 ++++------------ include/linux/platform_data/serial-sccnxp.h | 6 +-- 3 files changed, 12 insertions(+), 93 deletions(-) delete mode 100644 Documentation/devicetree/bindings/tty/serial/sccnxp-serial.txt diff --git a/Documentation/devicetree/bindings/tty/serial/sccnxp-serial.txt b/Documentation/devicetree/bindings/tty/serial/sccnxp-serial.txt deleted file mode 100644 index d18b1698133e..000000000000 --- a/Documentation/devicetree/bindings/tty/serial/sccnxp-serial.txt +++ /dev/null @@ -1,53 +0,0 @@ -* NXP (Philips) SCC+++(SCN+++) serial driver - -Required properties: -- compatible: Should be "nxp,". The supported ICs include sc2681, - sc2691, sc2692, sc2891, sc2892, sc28202, sc68681 and sc68692. -- reg: Address and length of the register set for the device. -- interrupts: Should contain the interrupt number. If omitted, - polling mode will be used instead, so "poll-interval" property should - be populated in this case. - -Optional properties: -- clocks: Phandle to input clock. If omitted, default IC frequency will be - used instead. -- poll-interval: Poll interval time in nanoseconds. -- vcc-supply: The regulator supplying the VCC to drive the chip. -- nxp,sccnxp-io-cfg: Array contains values for the emulated modem signals. - The number of values depends on the UART-number in the selected chip. - Each value should be composed according to the following rules: - (LINE1 << SIGNAL1) | ... | (LINEX << SIGNALX), where: - LINE - VALUE: - OP0 - 1 - OP1 - 2 - OP2 - 3 - OP3 - 4 - OP4 - 5 - OP5 - 6 - OP6 - 7 - OP7 - 8 - IP0 - 9 - IP1 - 10 - IP2 - 11 - IP3 - 12 - IP4 - 13 - IP5 - 14 - IP6 - 15 - SIGNAL - VALUE: - DTR - 0 - RTS - 4 - DSR - 8 - CTS - 12 - DCD - 16 - RNG - 20 - DIR - 24 - -Example (Dual UART with direction control on OP0 & OP1): -sc2892@10100000 { - compatible = "nxp,sc2892"; - reg = <0x10100000 0x10>; - poll-interval = <10000>; - clocks = <&sc2892_clk>; - vcc-supply = <&sc2892_reg>; - nxp,sccnxp-io-cfg = <0x01000000 0x02000000>; -}; diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c index 67f73d1a8e7b..49e9bbfe6cab 100644 --- a/drivers/tty/serial/sccnxp.c +++ b/drivers/tty/serial/sccnxp.c @@ -20,8 +20,6 @@ #include #include #include -#include -#include #include #include #include @@ -855,25 +853,10 @@ static const struct platform_device_id sccnxp_id_table[] = { }; MODULE_DEVICE_TABLE(platform, sccnxp_id_table); -static const struct of_device_id sccnxp_dt_id_table[] = { - { .compatible = "nxp,sc2681", .data = &sc2681, }, - { .compatible = "nxp,sc2691", .data = &sc2691, }, - { .compatible = "nxp,sc2692", .data = &sc2692, }, - { .compatible = "nxp,sc2891", .data = &sc2891, }, - { .compatible = "nxp,sc2892", .data = &sc2892, }, - { .compatible = "nxp,sc28202", .data = &sc28202, }, - { .compatible = "nxp,sc68681", .data = &sc68681, }, - { .compatible = "nxp,sc68692", .data = &sc68692, }, - { } -}; -MODULE_DEVICE_TABLE(of, sccnxp_dt_id_table); - static int sccnxp_probe(struct platform_device *pdev) { struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); struct sccnxp_pdata *pdata = dev_get_platdata(&pdev->dev); - const struct of_device_id *of_id = - of_match_device(sccnxp_dt_id_table, &pdev->dev); int i, ret, uartclk; struct sccnxp_port *s; void __iomem *membase; @@ -892,22 +875,7 @@ static int sccnxp_probe(struct platform_device *pdev) spin_lock_init(&s->lock); - if (of_id) { - s->chip = (struct sccnxp_chip *)of_id->data; - - of_property_read_u32(pdev->dev.of_node, "poll-interval", - &s->pdata.poll_time_us); - of_property_read_u32(pdev->dev.of_node, "reg-shift", - &s->pdata.reg_shift); - of_property_read_u32_array(pdev->dev.of_node, - "nxp,sccnxp-io-cfg", - s->pdata.mctrl_cfg, s->chip->nr); - } else { - s->chip = (struct sccnxp_chip *)pdev->id_entry->driver_data; - - if (pdata) - memcpy(&s->pdata, pdata, sizeof(struct sccnxp_pdata)); - } + s->chip = (struct sccnxp_chip *)pdev->id_entry->driver_data; s->regulator = devm_regulator_get(&pdev->dev, "vcc"); if (!IS_ERR(s->regulator)) { @@ -938,11 +906,16 @@ static int sccnxp_probe(struct platform_device *pdev) goto err_out; } + if (pdata) + memcpy(&s->pdata, pdata, sizeof(struct sccnxp_pdata)); + if (s->pdata.poll_time_us) { dev_info(&pdev->dev, "Using poll mode, resolution %u usecs\n", s->pdata.poll_time_us); s->poll = 1; - } else { + } + + if (!s->poll) { s->irq = platform_get_irq(pdev, 0); if (s->irq < 0) { dev_err(&pdev->dev, "Missing irq resource data\n"); @@ -1043,9 +1016,8 @@ static int sccnxp_remove(struct platform_device *pdev) static struct platform_driver sccnxp_uart_driver = { .driver = { - .name = SCCNXP_NAME, - .owner = THIS_MODULE, - .of_match_table = sccnxp_dt_id_table, + .name = SCCNXP_NAME, + .owner = THIS_MODULE, }, .probe = sccnxp_probe, .remove = sccnxp_remove, diff --git a/include/linux/platform_data/serial-sccnxp.h b/include/linux/platform_data/serial-sccnxp.h index 98373d6add27..af0c8c3b89ae 100644 --- a/include/linux/platform_data/serial-sccnxp.h +++ b/include/linux/platform_data/serial-sccnxp.h @@ -78,11 +78,11 @@ /* SCCNXP platform data structure */ struct sccnxp_pdata { /* Shift for A0 line */ - u32 reg_shift; + const u8 reg_shift; /* Modem control lines configuration */ - u32 mctrl_cfg[SCCNXP_MAX_UARTS]; + const u32 mctrl_cfg[SCCNXP_MAX_UARTS]; /* Timer value for polling mode (usecs) */ - u32 poll_time_us; + const unsigned int poll_time_us; }; #endif From 49126e47bf418081a4eb3686a8c736ca80da152c Mon Sep 17 00:00:00 2001 From: Xiong Zhou Date: Fri, 2 Aug 2013 13:50:48 +0800 Subject: [PATCH 1311/3400] staging/lustre: lloop depends on BLOCK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a config option for llite/lloop in lustre driver, making it depends on BLOCK to fix this better: drivers/staging/lustre/lustre/fid/../include/linux/lustre_compat25.h:117:2: error: implicit declaration of function ‘unregister_blkdev' Also, remove the wrapper ll_unregister_blkdev which depends on BLOCK in the header and just call unregister_blkdev in lloop.c based on Peng Tao's comment. Drop the redundant dependency on STAGING for LUSTRE_FS, remove some unnecessary jdb header files which depends on BLOCK btw. Signed-off-by: Xiong Zhou Reviewed-by: Peng Tao Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/Kconfig | 7 ++++++- drivers/staging/lustre/lustre/fld/fld_cache.c | 1 - drivers/staging/lustre/lustre/fld/fld_request.c | 1 - .../staging/lustre/lustre/include/linux/lustre_compat25.h | 7 ------- drivers/staging/lustre/lustre/llite/Makefile | 2 +- drivers/staging/lustre/lustre/llite/lloop.c | 6 ++---- drivers/staging/lustre/lustre/lvfs/fsfilt.c | 1 - 7 files changed, 9 insertions(+), 16 deletions(-) diff --git a/drivers/staging/lustre/lustre/Kconfig b/drivers/staging/lustre/lustre/Kconfig index 0b45de0726f6..4e898e491860 100644 --- a/drivers/staging/lustre/lustre/Kconfig +++ b/drivers/staging/lustre/lustre/Kconfig @@ -1,6 +1,6 @@ config LUSTRE_FS tristate "Lustre file system client support" - depends on STAGING && INET && BLOCK && m + depends on INET && m select LNET select CRYPTO select CRYPTO_CRC32 @@ -53,3 +53,8 @@ config LUSTRE_TRANSLATE_ERRNOS bool depends on LUSTRE_FS && !X86 default true + +config LUSTRE_LLITE_LLOOP + bool "Lustre virtual block device" + depends on LUSTRE_FS && BLOCK + default m diff --git a/drivers/staging/lustre/lustre/fld/fld_cache.c b/drivers/staging/lustre/lustre/fld/fld_cache.c index 347f2ae83bc8..84101076a656 100644 --- a/drivers/staging/lustre/lustre/fld/fld_cache.c +++ b/drivers/staging/lustre/lustre/fld/fld_cache.c @@ -45,7 +45,6 @@ # include # include -# include # include #include diff --git a/drivers/staging/lustre/lustre/fld/fld_request.c b/drivers/staging/lustre/lustre/fld/fld_request.c index c99b945cc8ef..049322a79140 100644 --- a/drivers/staging/lustre/lustre/fld/fld_request.c +++ b/drivers/staging/lustre/lustre/fld/fld_request.c @@ -44,7 +44,6 @@ # include # include -# include # include #include diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h b/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h index 426533b5d135..018e604490b7 100644 --- a/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h +++ b/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h @@ -111,13 +111,6 @@ static inline void ll_set_fs_pwd(struct fs_struct *fs, struct vfsmount *mnt, #define TREE_READ_LOCK_IRQ(mapping) spin_lock_irq(&(mapping)->tree_lock) #define TREE_READ_UNLOCK_IRQ(mapping) spin_unlock_irq(&(mapping)->tree_lock) -static inline -int ll_unregister_blkdev(unsigned int dev, const char *name) -{ - unregister_blkdev(dev, name); - return 0; -} - #define ll_invalidate_bdev(a,b) invalidate_bdev((a)) #ifndef FS_HAS_FIEMAP diff --git a/drivers/staging/lustre/lustre/llite/Makefile b/drivers/staging/lustre/lustre/llite/Makefile index dff0c0486e77..f493e0740004 100644 --- a/drivers/staging/lustre/lustre/llite/Makefile +++ b/drivers/staging/lustre/lustre/llite/Makefile @@ -1,5 +1,5 @@ obj-$(CONFIG_LUSTRE_FS) += lustre.o -obj-$(CONFIG_LUSTRE_FS) += llite_lloop.o +obj-$(CONFIG_LUSTRE_LLITE_LLOOP) += llite_lloop.o lustre-y := dcache.o dir.o file.o llite_close.o llite_lib.o llite_nfs.o \ rw.o lproc_llite.o namei.o symlink.o llite_mmap.o \ xattr.o remote_perm.o llite_rmtacl.o llite_capa.o \ diff --git a/drivers/staging/lustre/lustre/llite/lloop.c b/drivers/staging/lustre/lustre/llite/lloop.c index e063efc23af9..ae3dc9d5b484 100644 --- a/drivers/staging/lustre/lustre/llite/lloop.c +++ b/drivers/staging/lustre/lustre/llite/lloop.c @@ -848,10 +848,8 @@ static void lloop_exit(void) blk_cleanup_queue(loop_dev[i].lo_queue); put_disk(disks[i]); } - if (ll_unregister_blkdev(lloop_major, "lloop")) - CWARN("lloop: cannot unregister blkdev\n"); - else - CDEBUG(D_CONFIG, "unregistered lloop major %d\n", lloop_major); + + unregister_blkdev(lloop_major, "lloop"); OBD_FREE(disks, max_loop * sizeof(*disks)); OBD_FREE(loop_dev, max_loop * sizeof(*loop_dev)); diff --git a/drivers/staging/lustre/lustre/lvfs/fsfilt.c b/drivers/staging/lustre/lustre/lvfs/fsfilt.c index 064445cbdb57..ce71f805c6de 100644 --- a/drivers/staging/lustre/lustre/lvfs/fsfilt.c +++ b/drivers/staging/lustre/lustre/lvfs/fsfilt.c @@ -35,7 +35,6 @@ #define DEBUG_SUBSYSTEM S_FILTER #include -#include #include #include #include From 418690b60f04a0047f50f8650dc974dabeba195d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 2 Aug 2013 15:46:32 +0800 Subject: [PATCH 1312/3400] staging: lustre: remove ll_blkdev_put() It was a wrapper around blkdev_put(), totally useless. Cc: Peng Tao Cc: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/include/linux/lustre_compat25.h | 2 -- drivers/staging/lustre/lustre/llite/lloop.c | 6 +++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h b/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h index 018e604490b7..968cf7381a31 100644 --- a/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h +++ b/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h @@ -92,8 +92,6 @@ static inline void ll_set_fs_pwd(struct fs_struct *fs, struct vfsmount *mnt, # define ll_generic_permission(inode, mask, flags, check_acl) \ generic_permission(inode, mask) -#define ll_blkdev_put(a, b) blkdev_put(a, b) - #define ll_dentry_open(a,b,c) dentry_open(a,b,c) #define ll_vfs_symlink(dir, dentry, mnt, path, mode) \ diff --git a/drivers/staging/lustre/lustre/llite/lloop.c b/drivers/staging/lustre/lustre/llite/lloop.c index ae3dc9d5b484..83743c9d5333 100644 --- a/drivers/staging/lustre/lustre/llite/lloop.c +++ b/drivers/staging/lustre/lustre/llite/lloop.c @@ -617,7 +617,7 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode, case LL_IOC_LLOOP_DETACH: { err = loop_clr_fd(lo, bdev, 2); if (err == 0) - ll_blkdev_put(bdev, 0); /* grabbed in LLOOP_ATTACH */ + blkdev_put(bdev, 0); /* grabbed in LLOOP_ATTACH */ break; } @@ -712,7 +712,7 @@ static enum llioc_iter lloop_ioctl(struct inode *unused, struct file *file, err = loop_set_fd(lo, NULL, bdev, file); if (err) { fput(file); - ll_blkdev_put(bdev, 0); + blkdev_put(bdev, 0); } break; @@ -736,7 +736,7 @@ static enum llioc_iter lloop_ioctl(struct inode *unused, struct file *file, bdev = lo->lo_device; err = loop_clr_fd(lo, bdev, 1); if (err == 0) - ll_blkdev_put(bdev, 0); /* grabbed in LLOOP_ATTACH */ + blkdev_put(bdev, 0); /* grabbed in LLOOP_ATTACH */ break; } From dd4c3a486bdc5e01a007144b92c85a2d393f8161 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 2 Aug 2013 15:51:34 +0800 Subject: [PATCH 1313/3400] staging: lustre: remove ll_dentry_open() It was a wrapper around dentry_open(), totally useless. Cc: Peng Tao Cc: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/linux/lustre_compat25.h | 2 -- drivers/staging/lustre/lustre/lvfs/lvfs_linux.c | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h b/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h index 968cf7381a31..ac8f939fdaf3 100644 --- a/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h +++ b/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h @@ -92,8 +92,6 @@ static inline void ll_set_fs_pwd(struct fs_struct *fs, struct vfsmount *mnt, # define ll_generic_permission(inode, mask, flags, check_acl) \ generic_permission(inode, mask) -#define ll_dentry_open(a,b,c) dentry_open(a,b,c) - #define ll_vfs_symlink(dir, dentry, mnt, path, mode) \ vfs_symlink(dir, dentry, path) diff --git a/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c b/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c index 0f387913d6ff..d342e976317b 100644 --- a/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c +++ b/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c @@ -238,7 +238,7 @@ struct l_file *l_dentry_open(struct lvfs_run_ctxt *ctxt, struct l_dentry *de, .dentry = de, .mnt = ctxt->pwdmnt, }; - return ll_dentry_open(&path, flags, current_cred()); + return dentry_open(&path, flags, current_cred()); } EXPORT_SYMBOL(l_dentry_open); From 6f014339718fac7597a53d155a2aa1714091a9af Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 2 Aug 2013 15:56:22 +0800 Subject: [PATCH 1314/3400] staging: lustre: remove ll_generic_file_llseek_size() It was a wrapper around generic_file_llseek_size(), totally useless. Cc: Peng Tao Cc: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/linux/lustre_compat25.h | 4 ---- drivers/staging/lustre/lustre/llite/file.c | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h b/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h index ac8f939fdaf3..868f0742c77b 100644 --- a/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h +++ b/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h @@ -95,10 +95,6 @@ static inline void ll_set_fs_pwd(struct fs_struct *fs, struct vfsmount *mnt, #define ll_vfs_symlink(dir, dentry, mnt, path, mode) \ vfs_symlink(dir, dentry, path) - -#define ll_generic_file_llseek_size(file, offset, origin, maxbytes, eof) \ - generic_file_llseek_size(file, offset, origin, maxbytes, eof); - /* inode_dio_wait(i) use as-is for write lock */ # define inode_dio_write_done(i) do {} while (0) /* for write unlock */ # define inode_dio_read(i) atomic_inc(&(i)->i_dio_count) diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index b1df7f52ffec..56bd326e7221 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -2147,7 +2147,7 @@ loff_t ll_file_seek(struct file *file, loff_t offset, int origin) eof = i_size_read(inode); } - retval = ll_generic_file_llseek_size(file, offset, origin, + retval = generic_file_llseek_size(file, offset, origin, ll_file_maxbytes(inode), eof); RETURN(retval); } From 9c5fb72cc87a00262207d243aeb93e9c61f33573 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 2 Aug 2013 16:01:26 +0800 Subject: [PATCH 1315/3400] staging: lustre: remove ll_permission() It was a wrapper around inode_permission(), totally useless. Cc: Peng Tao Cc: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/linux/lustre_compat25.h | 2 -- drivers/staging/lustre/lustre/llite/file.c | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h b/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h index 868f0742c77b..65c7dd8eb965 100644 --- a/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h +++ b/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h @@ -87,8 +87,6 @@ static inline void ll_set_fs_pwd(struct fs_struct *fs, struct vfsmount *mnt, #define LTIME_S(time) (time.tv_sec) -#define ll_permission(inode,mask,nd) inode_permission(inode,mask) - # define ll_generic_permission(inode, mask, flags, check_acl) \ generic_permission(inode, mask) diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 56bd326e7221..0a6d28f7fb58 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -1756,8 +1756,8 @@ static int ll_swap_layouts(struct file *file1, struct file *file2, if (!S_ISREG(llss->inode2->i_mode)) GOTO(free, rc = -EINVAL); - if (ll_permission(llss->inode1, MAY_WRITE, NULL) || - ll_permission(llss->inode2, MAY_WRITE, NULL)) + if (inode_permission(llss->inode1, MAY_WRITE) || + inode_permission(llss->inode2, MAY_WRITE)) GOTO(free, rc = -EPERM); if (llss->inode2->i_sb != llss->inode1->i_sb) From 8707c96e960d34f9dfee15240b1797084512fcef Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 2 Aug 2013 16:08:01 +0800 Subject: [PATCH 1316/3400] staging: lustre: remove ll_generic_permission() It was a wrapper around generic_permission(), totally useless. Cc: Peng Tao Cc: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/linux/lustre_compat25.h | 3 --- drivers/staging/lustre/lustre/llite/file.c | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h b/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h index 65c7dd8eb965..b44bc03c5b9e 100644 --- a/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h +++ b/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h @@ -87,9 +87,6 @@ static inline void ll_set_fs_pwd(struct fs_struct *fs, struct vfsmount *mnt, #define LTIME_S(time) (time.tv_sec) -# define ll_generic_permission(inode, mask, flags, check_acl) \ - generic_permission(inode, mask) - #define ll_vfs_symlink(dir, dentry, mnt, path, mode) \ vfs_symlink(dir, dentry, path) diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 0a6d28f7fb58..20416fcf2e9c 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -2721,7 +2721,7 @@ int ll_inode_permission(struct inode *inode, int mask) return lustre_check_remote_perm(inode, mask); ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_INODE_PERM, 1); - rc = ll_generic_permission(inode, mask, flags, ll_check_acl); + rc = generic_permission(inode, mask); RETURN(rc); } From 077069aec22866a20a466beb2f65afa42957b78e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 2 Aug 2013 16:11:35 +0800 Subject: [PATCH 1317/3400] staging: lustre: remove ll_vfs_symlink() No one was ever even using it. Cc: Peng Tao Cc: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/linux/lustre_compat25.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h b/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h index b44bc03c5b9e..8691aee0b4d4 100644 --- a/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h +++ b/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h @@ -87,9 +87,6 @@ static inline void ll_set_fs_pwd(struct fs_struct *fs, struct vfsmount *mnt, #define LTIME_S(time) (time.tv_sec) -#define ll_vfs_symlink(dir, dentry, mnt, path, mode) \ - vfs_symlink(dir, dentry, path) - /* inode_dio_wait(i) use as-is for write lock */ # define inode_dio_write_done(i) do {} while (0) /* for write unlock */ # define inode_dio_read(i) atomic_inc(&(i)->i_dio_count) From db7392c2fb2fb149a5c9243f4189748b445bc1a3 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 2 Aug 2013 16:17:04 +0800 Subject: [PATCH 1318/3400] staging: lustre: remove ll_invalidate_bdev() It was a wrapper around invalidate_bdev(), totally useless. Cc: Peng Tao Cc: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/linux/lustre_compat25.h | 2 -- drivers/staging/lustre/lustre/llite/lloop.c | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h b/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h index 8691aee0b4d4..6f2707275e5d 100644 --- a/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h +++ b/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h @@ -95,8 +95,6 @@ static inline void ll_set_fs_pwd(struct fs_struct *fs, struct vfsmount *mnt, #define TREE_READ_LOCK_IRQ(mapping) spin_lock_irq(&(mapping)->tree_lock) #define TREE_READ_UNLOCK_IRQ(mapping) spin_unlock_irq(&(mapping)->tree_lock) -#define ll_invalidate_bdev(a,b) invalidate_bdev((a)) - #ifndef FS_HAS_FIEMAP #define FS_HAS_FIEMAP (0) #endif diff --git a/drivers/staging/lustre/lustre/llite/lloop.c b/drivers/staging/lustre/lustre/llite/lloop.c index 83743c9d5333..2340458b8a04 100644 --- a/drivers/staging/lustre/lustre/llite/lloop.c +++ b/drivers/staging/lustre/lustre/llite/lloop.c @@ -573,7 +573,7 @@ static int loop_clr_fd(struct lloop_device *lo, struct block_device *bdev, lo->lo_offset = 0; lo->lo_sizelimit = 0; lo->lo_flags = 0; - ll_invalidate_bdev(bdev, 0); + invalidate_bdev(bdev); set_capacity(disks[lo->lo_number], 0); bd_set_size(bdev, 0); mapping_set_gfp_mask(filp->f_mapping, gfp); From fb74d282d29dbb39ef20211a9cf2883f9f593bdd Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Fri, 2 Aug 2013 17:13:17 +0900 Subject: [PATCH 1319/3400] usb: dwc3: pci: add CONFIG_PM_SLEEP to suspend/resume functions Add CONFIG_PM_SLEEP to suspend/resume functions to fix the following build warning when CONFIG_PM_SLEEP is not selected. This is because sleep PM callbacks defined by SET_SYSTEM_SLEEP_PM_OPS are only used when the CONFIG_PM_SLEEP is enabled. Unnecessary CONFIG_PM ifdefs are removed. drivers/usb/dwc3/dwc3-pci.c:215:12: warning: 'dwc3_pci_suspend' defined but not used [-Wunused-function] drivers/usb/dwc3/dwc3-pci.c:224:12: warning: 'dwc3_pci_resume' defined but not used [-Wunused-function] Signed-off-by: Jingoo Han Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-pci.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index 5d746e5d6a0a..105535abcc4a 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c @@ -191,7 +191,7 @@ static DEFINE_PCI_DEVICE_TABLE(dwc3_pci_id_table) = { }; MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table); -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int dwc3_pci_suspend(struct device *dev) { struct pci_dev *pci = to_pci_dev(dev); @@ -216,23 +216,19 @@ static int dwc3_pci_resume(struct device *dev) return 0; } +#endif /* CONFIG_PM_SLEEP */ static const struct dev_pm_ops dwc3_pci_dev_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(dwc3_pci_suspend, dwc3_pci_resume) }; -#define DEV_PM_OPS (&dwc3_pci_dev_pm_ops) -#else -#define DEV_PM_OPS NULL -#endif /* CONFIG_PM */ - static struct pci_driver dwc3_pci_driver = { .name = "dwc3-pci", .id_table = dwc3_pci_id_table, .probe = dwc3_pci_probe, .remove = dwc3_pci_remove, .driver = { - .pm = DEV_PM_OPS, + .pm = &dwc3_pci_dev_pm_ops, }, }; From 027ca0d2fe779faf19c7c3414f840fdc851af41d Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Fri, 2 Aug 2013 17:16:33 +0900 Subject: [PATCH 1320/3400] usb: gadget: goku_udc: use NULL instead of 0 'req' is a pointer; thus, use NULL instead of 0 to fix the following sparse warning: drivers/usb/gadget/goku_udc.c:775:13: warning: Using plain integer as NULL pointer Signed-off-by: Jingoo Han Signed-off-by: Felipe Balbi --- drivers/usb/gadget/goku_udc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index 52dd6cc6c0aa..c64deb9e3d62 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c @@ -772,7 +772,7 @@ goku_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) } /* else pio or dma irq handler advances the queue. */ - if (likely(req != 0)) + if (likely(req != NULL)) list_add_tail(&req->queue, &ep->queue); if (likely(!list_empty(&ep->queue)) From 93487aa1639d2151820f3988f62005d0a00e9269 Mon Sep 17 00:00:00 2001 From: Jingoo Han Date: Fri, 2 Aug 2013 17:17:05 +0900 Subject: [PATCH 1321/3400] usb: gadget: fusb300_udc: Staticize fusb300_rdcxf() fusb300_rdcxf() used only in this file. Fix the following sparse warning: drivers/usb/gadget/fusb300_udc.c:560:6: warning: symbol 'fusb300_rdcxf' was not declared. Should it be static? Signed-off-by: Jingoo Han Signed-off-by: Felipe Balbi --- drivers/usb/gadget/fusb300_udc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/fusb300_udc.c b/drivers/usb/gadget/fusb300_udc.c index c83f3e165325..f1dd6daabe21 100644 --- a/drivers/usb/gadget/fusb300_udc.c +++ b/drivers/usb/gadget/fusb300_udc.c @@ -557,7 +557,7 @@ static void fusb300_set_cxdone(struct fusb300 *fusb300) } /* read data from cx fifo */ -void fusb300_rdcxf(struct fusb300 *fusb300, +static void fusb300_rdcxf(struct fusb300 *fusb300, u8 *buffer, u32 length) { int i = 0; From 20fbff1dfd9abcb15e368627986e1fed08b44ebe Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 2 Aug 2013 16:24:50 +0800 Subject: [PATCH 1322/3400] staging: lustre: remove ENTRY/EXIT_NESTING stuff These macros were empty, so remove them in anticipation of removing the entire ENTRY/EXIT macros. Cc: Peng Tao Cc: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h | 5 ----- drivers/staging/lustre/include/linux/libcfs/linux/libcfs.h | 3 --- 2 files changed, 8 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h index dd8ac2f52c9f..07082dc6fd86 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h @@ -272,7 +272,6 @@ long libcfs_log_return(struct libcfs_debug_msg_data *, long rc); #if BITS_PER_LONG > 32 #define RETURN(rc) \ do { \ - EXIT_NESTING; \ if (cfs_cdebug_show(D_TRACE, DEBUG_SUBSYSTEM)) { \ LIBCFS_DEBUG_MSG_DATA_DECL(msgdata, D_TRACE, NULL); \ return (typeof(rc))libcfs_log_return(&msgdata, \ @@ -289,7 +288,6 @@ do { \ */ #define RETURN(rc) \ do { \ - EXIT_NESTING; \ if (cfs_cdebug_show(D_TRACE, DEBUG_SUBSYSTEM)) { \ typeof(rc) __rc = (rc); \ LIBCFS_DEBUG_MSG_DATA_DECL(msgdata, D_TRACE, NULL); \ @@ -305,7 +303,6 @@ do { \ #define RETURN(rc) \ do { \ CDEBUG(D_TRACE, "Process leaving.\n"); \ - EXIT_NESTING; \ return (rc); \ } while (0) #else @@ -313,7 +310,6 @@ do { \ #endif /* __GNUC__ */ #define ENTRY \ -ENTRY_NESTING; \ do { \ CDEBUG(D_TRACE, "Process entered\n"); \ } while (0) @@ -321,7 +317,6 @@ do { \ #define EXIT \ do { \ CDEBUG(D_TRACE, "Process leaving\n"); \ - EXIT_NESTING; \ } while(0) #define RETURN_EXIT \ diff --git a/drivers/staging/lustre/include/linux/libcfs/linux/libcfs.h b/drivers/staging/lustre/include/linux/libcfs/linux/libcfs.h index 292a3ba1fb96..60ecaf63f9fb 100644 --- a/drivers/staging/lustre/include/linux/libcfs/linux/libcfs.h +++ b/drivers/staging/lustre/include/linux/libcfs/linux/libcfs.h @@ -97,9 +97,6 @@ do { \ /* initial pid */ #define LUSTRE_LNET_PID 12345 -#define ENTRY_NESTING_SUPPORT (1) -#define ENTRY_NESTING do {;} while (0) -#define EXIT_NESTING do {;} while (0) #define __current_nesting_level() (0) /** From 41e85ce8220c6e5fdef706fda6696cd291115b63 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Thu, 1 Aug 2013 18:59:41 +0200 Subject: [PATCH 1323/3400] hung_task debugging: Print more info when reporting the problem printk(KERN_ERR) from check_hung_task() likely means we have a bug, but unlike BUG_ON()/WARN_ON ()it doesn't show the kernel version, this complicates the bug-reports investigation. Add the additional pr_err() to print tainted/release/version like dump_stack_print_info() does, the output becomes: INFO: task perl:504 blocked for more than 2 seconds. Not tainted 3.11.0-rc1-10367-g136bb46-dirty #1763 "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. ... While at it, turn the old printk's into pr_err(). Signed-off-by: Oleg Nesterov Cc: ahecox@redhat.com Cc: Christopher Williams Cc: dwysocha@redhat.com Cc: gavin@redhat.com Cc: Mandeep Singh Baines Cc: nshi@redhat.com Cc: Linus Torvalds Cc: Andrew Morton Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20130801165941.GA17544@redhat.com Signed-off-by: Ingo Molnar --- kernel/hung_task.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/kernel/hung_task.c b/kernel/hung_task.c index 6df614912b9d..3e97fb126e6b 100644 --- a/kernel/hung_task.c +++ b/kernel/hung_task.c @@ -15,6 +15,7 @@ #include #include #include +#include /* * The number of tasks checked: @@ -99,10 +100,14 @@ static void check_hung_task(struct task_struct *t, unsigned long timeout) * Ok, the task did not get scheduled for more than 2 minutes, * complain: */ - printk(KERN_ERR "INFO: task %s:%d blocked for more than " - "%ld seconds.\n", t->comm, t->pid, timeout); - printk(KERN_ERR "\"echo 0 > /proc/sys/kernel/hung_task_timeout_secs\"" - " disables this message.\n"); + pr_err("INFO: task %s:%d blocked for more than %ld seconds.\n", + t->comm, t->pid, timeout); + pr_err(" %s %s %.*s\n", + print_tainted(), init_utsname()->release, + (int)strcspn(init_utsname()->version, " "), + init_utsname()->version); + pr_err("\"echo 0 > /proc/sys/kernel/hung_task_timeout_secs\"" + " disables this message.\n"); sched_show_task(t); debug_show_held_locks(t); From 005358c8c05998bef5e136ca7e7d6b1dc5326b49 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 2 Aug 2013 10:15:01 +0300 Subject: [PATCH 1324/3400] OMAPDSS: analog-tv-connector: compile fix connector-analog-tv.c uses omap_dss_pal_timings, defined in omapdss's venc.c, for default timings. omap_dss_pal_timings only exists when VENC is enabled in the kernel config, so disabling VENC breaks omap_dss_pal_timings connector-analog-tv compilation. Instead of adding dependency to VENC, add internal default timings to the connector driver, because the connector driver should not depend on VENC, and it can be used with any other analog TV encoder. Signed-off-by: Tomi Valkeinen --- .../omap2/displays-new/connector-analog-tv.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/video/omap2/displays-new/connector-analog-tv.c b/drivers/video/omap2/displays-new/connector-analog-tv.c index 5338f362293b..1b60698f141e 100644 --- a/drivers/video/omap2/displays-new/connector-analog-tv.c +++ b/drivers/video/omap2/displays-new/connector-analog-tv.c @@ -28,6 +28,20 @@ struct panel_drv_data { bool invert_polarity; }; +static const struct omap_video_timings tvc_pal_timings = { + .x_res = 720, + .y_res = 574, + .pixel_clock = 13500, + .hsw = 64, + .hfp = 12, + .hbp = 68, + .vsw = 5, + .vfp = 5, + .vbp = 41, + + .interlace = true, +}; + #define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev) static int tvc_connect(struct omap_dss_device *dssdev) @@ -212,14 +226,14 @@ static int tvc_probe(struct platform_device *pdev) return -ENODEV; } - ddata->timings = omap_dss_pal_timings; + ddata->timings = tvc_pal_timings; dssdev = &ddata->dssdev; dssdev->driver = &tvc_driver; dssdev->dev = &pdev->dev; dssdev->type = OMAP_DISPLAY_TYPE_VENC; dssdev->owner = THIS_MODULE; - dssdev->panel.timings = omap_dss_pal_timings; + dssdev->panel.timings = tvc_pal_timings; r = omapdss_register_display(dssdev); if (r) { From 208df1e4cbb13140d2f822cd2b15c00b51978776 Mon Sep 17 00:00:00 2001 From: Hector Palacios Date: Thu, 1 Aug 2013 10:40:35 +0200 Subject: [PATCH 1325/3400] video: mxsfb: fix color settings for 18bit data bus and 32bpp For a combination of 18bit LCD data bus width and a color mode of 32bpp, the driver was setting the color mapping to rgb666, which is wrong, as the color in memory realy has an rgb888 layout. This patch also removes the setting of flag CTRL_DF24 that makes the driver dimiss the upper 2 bits when handling 32/24bpp colors in a diplay with 18bit data bus width. This flag made true color images display wrong in such configurations. Finally, the color mapping rgb666 has also been removed as nobody is using it and high level applications like Qt5 cannot work with it either. Reference: https://lkml.org/lkml/2013/5/23/220 Signed-off-by: Hector Palacios Acked-by: Juergen Beisert Acked-by: Maxime Ripard Signed-off-by: Maxime Ripard Signed-off-by: Tomi Valkeinen --- drivers/video/mxsfb.c | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c index 3ba37713b1f9..dc09ebe4aba5 100644 --- a/drivers/video/mxsfb.c +++ b/drivers/video/mxsfb.c @@ -239,24 +239,6 @@ static const struct fb_bitfield def_rgb565[] = { } }; -static const struct fb_bitfield def_rgb666[] = { - [RED] = { - .offset = 16, - .length = 6, - }, - [GREEN] = { - .offset = 8, - .length = 6, - }, - [BLUE] = { - .offset = 0, - .length = 6, - }, - [TRANSP] = { /* no support for transparency */ - .length = 0, - } -}; - static const struct fb_bitfield def_rgb888[] = { [RED] = { .offset = 16, @@ -309,9 +291,6 @@ static int mxsfb_check_var(struct fb_var_screeninfo *var, break; case STMLCDIF_16BIT: case STMLCDIF_18BIT: - /* 24 bit to 18 bit mapping */ - rgb = def_rgb666; - break; case STMLCDIF_24BIT: /* real 24 bit */ rgb = def_rgb888; @@ -453,11 +432,6 @@ static int mxsfb_set_par(struct fb_info *fb_info) return -EINVAL; case STMLCDIF_16BIT: case STMLCDIF_18BIT: - /* 24 bit to 18 bit mapping */ - ctrl |= CTRL_DF24; /* ignore the upper 2 bits in - * each colour component - */ - break; case STMLCDIF_24BIT: /* real 24 bit */ break; From 29aaf4962a3bce337d37176858ef1025b9f29cc4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 2 Aug 2013 18:14:51 +0800 Subject: [PATCH 1326/3400] staging: lustre: remove ENTRY macro We have a kernel-wide function tracing system, so use that instead of rolling a custom one just for one filesystem. Cc: Peng Tao Cc: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../include/linux/libcfs/libcfs_debug.h | 5 - .../lustre/lnet/klnds/socklnd/socklnd_cb.c | 4 - .../lnet/klnds/socklnd/socklnd_lib-linux.c | 1 - drivers/staging/lustre/lnet/lnet/lib-eq.c | 2 - drivers/staging/lustre/lnet/lnet/lib-msg.c | 2 - drivers/staging/lustre/lnet/lnet/module.c | 1 - .../staging/lustre/lustre/fid/fid_request.c | 12 -- drivers/staging/lustre/lustre/fid/lproc_fid.c | 7 - drivers/staging/lustre/lustre/fld/fld_cache.c | 10 -- .../staging/lustre/lustre/fld/fld_request.c | 12 +- drivers/staging/lustre/lustre/fld/lproc_fld.c | 4 - .../lustre/lustre/include/lustre_cfg.h | 5 +- .../lustre/lustre/include/lustre_lib.h | 2 - .../lustre/lustre/include/lustre_log.h | 8 -- .../lustre/lustre/include/lustre_mdc.h | 2 - .../staging/lustre/lustre/include/obd_class.h | 128 +++--------------- .../staging/lustre/lustre/lclient/glimpse.c | 5 - .../lustre/lustre/lclient/lcommon_cl.c | 12 -- .../lustre/lustre/lclient/lcommon_misc.c | 2 - .../lustre/lustre/ldlm/interval_tree.c | 16 --- .../staging/lustre/lustre/ldlm/ldlm_extent.c | 2 - .../staging/lustre/lustre/ldlm/ldlm_flock.c | 8 -- drivers/staging/lustre/lustre/ldlm/ldlm_lib.c | 10 -- .../staging/lustre/lustre/ldlm/ldlm_lock.c | 38 +----- .../staging/lustre/lustre/ldlm/ldlm_lockd.c | 18 +-- .../staging/lustre/lustre/ldlm/ldlm_pool.c | 10 -- .../staging/lustre/lustre/ldlm/ldlm_request.c | 36 +---- .../lustre/lustre/ldlm/ldlm_resource.c | 7 +- drivers/staging/lustre/lustre/libcfs/debug.c | 1 - drivers/staging/lustre/lustre/libcfs/hash.c | 8 -- .../lustre/lustre/libcfs/kernel_user_comm.c | 3 - .../lustre/lustre/libcfs/libcfs_string.c | 1 - .../lustre/libcfs/linux/linux-curproc.c | 1 - .../lustre/lustre/libcfs/linux/linux-debug.c | 3 - .../lustre/lustre/libcfs/linux/linux-module.c | 1 - drivers/staging/lustre/lustre/libcfs/module.c | 4 - .../staging/lustre/lustre/libcfs/nidstrings.c | 2 - .../lustre/lustre/libcfs/upcall_cache.c | 7 - drivers/staging/lustre/lustre/llite/dcache.c | 13 +- drivers/staging/lustre/lustre/llite/dir.c | 14 -- drivers/staging/lustre/lustre/llite/file.c | 51 ------- .../staging/lustre/lustre/llite/llite_capa.c | 6 - .../staging/lustre/lustre/llite/llite_close.c | 8 -- .../staging/lustre/lustre/llite/llite_lib.c | 22 --- .../staging/lustre/lustre/llite/llite_mmap.c | 8 -- .../staging/lustre/lustre/llite/llite_nfs.c | 5 - .../staging/lustre/lustre/llite/lproc_llite.c | 2 - drivers/staging/lustre/lustre/llite/namei.c | 20 +-- .../staging/lustre/lustre/llite/remote_perm.c | 3 - drivers/staging/lustre/lustre/llite/rw.c | 12 -- drivers/staging/lustre/lustre/llite/rw26.c | 3 - .../staging/lustre/lustre/llite/statahead.c | 15 -- drivers/staging/lustre/lustre/llite/symlink.c | 3 - drivers/staging/lustre/lustre/llite/vvp_dev.c | 1 - drivers/staging/lustre/lustre/llite/vvp_io.c | 12 -- .../staging/lustre/lustre/llite/vvp_lock.c | 1 - .../staging/lustre/lustre/llite/vvp_page.c | 3 - drivers/staging/lustre/lustre/llite/xattr.c | 2 - drivers/staging/lustre/lustre/lmv/lmv_fld.c | 2 - .../staging/lustre/lustre/lmv/lmv_intent.c | 4 - drivers/staging/lustre/lustre/lmv/lmv_obd.c | 54 -------- drivers/staging/lustre/lustre/lov/lov_dev.c | 5 - drivers/staging/lustre/lustre/lov/lov_io.c | 27 +--- drivers/staging/lustre/lustre/lov/lov_lock.c | 29 ---- drivers/staging/lustre/lustre/lov/lov_log.c | 6 - drivers/staging/lustre/lustre/lov/lov_merge.c | 2 - drivers/staging/lustre/lustre/lov/lov_obd.c | 44 +----- .../staging/lustre/lustre/lov/lov_object.c | 17 --- .../staging/lustre/lustre/lov/lov_offset.c | 1 - drivers/staging/lustre/lustre/lov/lov_pack.c | 7 - drivers/staging/lustre/lustre/lov/lov_page.c | 5 - drivers/staging/lustre/lustre/lov/lov_pool.c | 11 -- .../staging/lustre/lustre/lov/lov_request.c | 32 ----- .../staging/lustre/lustre/lov/lovsub_dev.c | 4 - .../staging/lustre/lustre/lov/lovsub_lock.c | 13 -- .../staging/lustre/lustre/lov/lovsub_object.c | 5 - .../staging/lustre/lustre/lov/lovsub_page.c | 1 - .../staging/lustre/lustre/lvfs/lvfs_linux.c | 1 - drivers/staging/lustre/lustre/mdc/lproc_mdc.c | 1 - drivers/staging/lustre/lustre/mdc/mdc_lib.c | 2 +- drivers/staging/lustre/lustre/mdc/mdc_locks.c | 19 +-- drivers/staging/lustre/lustre/mdc/mdc_reint.c | 6 - .../staging/lustre/lustre/mdc/mdc_request.c | 49 +------ drivers/staging/lustre/lustre/mgc/libmgc.c | 5 - .../staging/lustre/lustre/mgc/mgc_request.c | 33 ----- drivers/staging/lustre/lustre/obdclass/acl.c | 4 - drivers/staging/lustre/lustre/obdclass/capa.c | 2 - .../staging/lustre/lustre/obdclass/cl_io.c | 55 -------- .../staging/lustre/lustre/obdclass/cl_lock.c | 53 +------- .../lustre/lustre/obdclass/cl_object.c | 8 -- .../staging/lustre/lustre/obdclass/cl_page.c | 34 ----- .../lustre/lustre/obdclass/class_obd.c | 4 - .../lustre/lustre/obdclass/dt_object.c | 6 - .../staging/lustre/lustre/obdclass/genops.c | 19 --- .../lustre/obdclass/linux/linux-module.c | 8 -- drivers/staging/lustre/lustre/obdclass/llog.c | 32 ----- .../staging/lustre/lustre/obdclass/llog_cat.c | 17 --- .../lustre/lustre/obdclass/llog_ioctl.c | 9 -- .../lustre/lustre/obdclass/llog_lvfs.c | 15 -- .../staging/lustre/lustre/obdclass/llog_obd.c | 9 +- .../staging/lustre/lustre/obdclass/llog_osd.c | 28 ---- .../lustre/lustre/obdclass/llog_swab.c | 5 - .../lustre/lustre/obdclass/llog_test.c | 19 --- .../lustre/lustre/obdclass/local_storage.c | 12 -- .../lustre/lustre/obdclass/lprocfs_status.c | 4 - .../lustre/lustre/obdclass/lu_object.c | 2 - .../lustre/lustre/obdclass/lustre_handles.c | 3 - .../lustre/lustre/obdclass/lustre_peer.c | 1 - .../staging/lustre/lustre/obdclass/md_attrs.c | 3 - .../lustre/lustre/obdclass/obd_config.c | 23 ---- .../lustre/lustre/obdclass/obd_mount.c | 12 -- drivers/staging/lustre/lustre/obdecho/echo.c | 9 -- .../lustre/lustre/obdecho/echo_client.c | 52 ------- drivers/staging/lustre/lustre/osc/osc_cache.c | 31 ----- drivers/staging/lustre/lustre/osc/osc_dev.c | 1 - drivers/staging/lustre/lustre/osc/osc_io.c | 8 -- drivers/staging/lustre/lustre/osc/osc_lock.c | 9 -- .../staging/lustre/lustre/osc/osc_object.c | 1 - drivers/staging/lustre/lustre/osc/osc_page.c | 7 +- drivers/staging/lustre/lustre/osc/osc_quota.c | 7 - .../staging/lustre/lustre/osc/osc_request.c | 48 ------- drivers/staging/lustre/lustre/ptlrpc/client.c | 27 ---- .../staging/lustre/lustre/ptlrpc/connection.c | 7 - drivers/staging/lustre/lustre/ptlrpc/events.c | 5 - .../lustre/lustre/ptlrpc/gss/gss_bulk.c | 6 - .../lustre/lustre/ptlrpc/gss/gss_cli_upcall.c | 1 - .../lustre/lustre/ptlrpc/gss/gss_keyring.c | 11 -- .../lustre/lustre/ptlrpc/gss/gss_krb5_mech.c | 1 - .../lustre/lustre/ptlrpc/gss/gss_pipefs.c | 12 -- .../lustre/lustre/ptlrpc/gss/gss_svc_upcall.c | 5 - .../lustre/lustre/ptlrpc/gss/sec_gss.c | 22 --- drivers/staging/lustre/lustre/ptlrpc/import.c | 14 -- .../lustre/lustre/ptlrpc/llog_client.c | 5 - .../staging/lustre/lustre/ptlrpc/llog_net.c | 1 - .../lustre/lustre/ptlrpc/llog_server.c | 12 -- .../lustre/lustre/ptlrpc/lproc_ptlrpc.c | 3 - drivers/staging/lustre/lustre/ptlrpc/niobuf.c | 5 - drivers/staging/lustre/lustre/ptlrpc/nrs.c | 18 --- .../lustre/lustre/ptlrpc/pack_generic.c | 9 +- drivers/staging/lustre/lustre/ptlrpc/pinger.c | 8 -- .../lustre/lustre/ptlrpc/ptlrpc_module.c | 1 - .../staging/lustre/lustre/ptlrpc/ptlrpcd.c | 10 -- .../staging/lustre/lustre/ptlrpc/recover.c | 8 -- drivers/staging/lustre/lustre/ptlrpc/sec.c | 17 --- .../staging/lustre/lustre/ptlrpc/sec_config.c | 6 - .../staging/lustre/lustre/ptlrpc/sec_plain.c | 16 --- .../staging/lustre/lustre/ptlrpc/service.c | 26 ---- 147 files changed, 42 insertions(+), 1763 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h index 07082dc6fd86..feb7a6bc6efe 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h @@ -309,11 +309,6 @@ do { \ # error "Unkown compiler" #endif /* __GNUC__ */ -#define ENTRY \ -do { \ - CDEBUG(D_TRACE, "Process entered\n"); \ -} while (0) - #define EXIT \ do { \ CDEBUG(D_TRACE, "Process leaving\n"); \ diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c index a3b8f77399ba..6a538497f9f8 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c @@ -343,7 +343,6 @@ ksocknal_receive (ksock_conn_t *conn) * Caller checks ksnc_rx_nob_wanted to determine * progress/completion. */ int rc; - ENTRY; if (ksocknal_data.ksnd_stall_rx != 0) { cfs_pause(cfs_time_seconds (ksocknal_data.ksnd_stall_rx)); @@ -389,7 +388,6 @@ ksocknal_tx_done (lnet_ni_t *ni, ksock_tx_t *tx) { lnet_msg_t *lnetmsg = tx->tx_lnetmsg; int rc = (tx->tx_resid == 0 && !tx->tx_zc_aborted) ? 0 : -EIO; - ENTRY; LASSERT(ni != NULL || tx->tx_conn != NULL); @@ -1562,7 +1560,6 @@ int ksocknal_scheduler(void *arg) void ksocknal_read_callback (ksock_conn_t *conn) { ksock_sched_t *sched; - ENTRY; sched = conn->ksnc_scheduler; @@ -1591,7 +1588,6 @@ void ksocknal_read_callback (ksock_conn_t *conn) void ksocknal_write_callback (ksock_conn_t *conn) { ksock_sched_t *sched; - ENTRY; sched = conn->ksnc_scheduler; diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.c index 76e442be5582..6cfcf7758c04 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.c @@ -964,7 +964,6 @@ static void ksocknal_data_ready (struct sock *sk, int n) { ksock_conn_t *conn; - ENTRY; /* interleave correctly with closing sockets... */ LASSERT(!in_irq()); diff --git a/drivers/staging/lustre/lnet/lnet/lib-eq.c b/drivers/staging/lustre/lnet/lnet/lib-eq.c index 78297a7d94e8..3b8808bf78d1 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-eq.c +++ b/drivers/staging/lustre/lnet/lnet/lib-eq.c @@ -244,7 +244,6 @@ lnet_eq_dequeue_event(lnet_eq_t *eq, lnet_event_t *ev) int new_index = eq->eq_deq_seq & (eq->eq_size - 1); lnet_event_t *new_event = &eq->eq_events[new_index]; int rc; - ENTRY; /* must called with lnet_eq_wait_lock hold */ if (LNET_SEQ_GT(eq->eq_deq_seq, new_event->sequence)) @@ -400,7 +399,6 @@ LNetEQPoll(lnet_handle_eq_t *eventqs, int neq, int timeout_ms, int wait = 1; int rc; int i; - ENTRY; LASSERT (the_lnet.ln_init); LASSERT (the_lnet.ln_refcount > 0); diff --git a/drivers/staging/lustre/lnet/lnet/lib-msg.c b/drivers/staging/lustre/lnet/lnet/lib-msg.c index 8f3a50bd5f69..214bf38745ae 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-msg.c +++ b/drivers/staging/lustre/lnet/lnet/lib-msg.c @@ -45,8 +45,6 @@ void lnet_build_unlink_event (lnet_libmd_t *md, lnet_event_t *ev) { - ENTRY; - memset(ev, 0, sizeof(*ev)); ev->status = 0; diff --git a/drivers/staging/lustre/lnet/lnet/module.c b/drivers/staging/lustre/lnet/lnet/module.c index c8323854580a..c57e46a384cd 100644 --- a/drivers/staging/lustre/lnet/lnet/module.c +++ b/drivers/staging/lustre/lnet/lnet/module.c @@ -114,7 +114,6 @@ int init_lnet(void) { int rc; - ENTRY; mutex_init(&lnet_config_mutex); diff --git a/drivers/staging/lustre/lustre/fid/fid_request.c b/drivers/staging/lustre/lustre/fid/fid_request.c index a279b5ae8e76..59ff87cea083 100644 --- a/drivers/staging/lustre/lustre/fid/fid_request.c +++ b/drivers/staging/lustre/lustre/fid/fid_request.c @@ -63,7 +63,6 @@ static int seq_client_rpc(struct lu_client_seq *seq, __u32 *op; unsigned int debug_mask; int rc; - ENTRY; req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp), &RQF_SEQ_QUERY, LUSTRE_MDS_VERSION, SEQ_QUERY); @@ -145,7 +144,6 @@ int seq_client_alloc_super(struct lu_client_seq *seq, const struct lu_env *env) { int rc; - ENTRY; mutex_lock(&seq->lcs_mutex); @@ -171,7 +169,6 @@ static int seq_client_alloc_meta(const struct lu_env *env, struct lu_client_seq *seq) { int rc; - ENTRY; if (seq->lcs_srv) { rc = 0; @@ -194,7 +191,6 @@ static int seq_client_alloc_seq(const struct lu_env *env, struct lu_client_seq *seq, seqno_t *seqnr) { int rc; - ENTRY; LASSERT(range_is_sane(&seq->lcs_space)); @@ -307,7 +303,6 @@ int seq_client_alloc_fid(const struct lu_env *env, { wait_queue_t link; int rc; - ENTRY; LASSERT(seq != NULL); LASSERT(fid != NULL); @@ -407,7 +402,6 @@ EXPORT_SYMBOL(seq_client_flush); static void seq_client_proc_fini(struct lu_client_seq *seq) { #ifdef LPROCFS - ENTRY; if (seq->lcs_proc_dir) { if (!IS_ERR(seq->lcs_proc_dir)) lprocfs_remove(&seq->lcs_proc_dir); @@ -421,7 +415,6 @@ static int seq_client_proc_init(struct lu_client_seq *seq) { #ifdef LPROCFS int rc; - ENTRY; seq->lcs_proc_dir = lprocfs_register(seq->lcs_name, seq_type_proc_dir, @@ -460,7 +453,6 @@ int seq_client_init(struct lu_client_seq *seq, struct lu_server_seq *srv) { int rc; - ENTRY; LASSERT(seq != NULL); LASSERT(prefix != NULL); @@ -495,8 +487,6 @@ EXPORT_SYMBOL(seq_client_init); void seq_client_fini(struct lu_client_seq *seq) { - ENTRY; - seq_client_proc_fini(seq); if (seq->lcs_exp != NULL) { @@ -515,7 +505,6 @@ int client_fid_init(struct obd_device *obd, struct client_obd *cli = &obd->u.cli; char *prefix; int rc; - ENTRY; OBD_ALLOC_PTR(cli->cl_seq); if (cli->cl_seq == NULL) @@ -544,7 +533,6 @@ EXPORT_SYMBOL(client_fid_init); int client_fid_fini(struct obd_device *obd) { struct client_obd *cli = &obd->u.cli; - ENTRY; if (cli->cl_seq != NULL) { seq_client_fini(cli->cl_seq); diff --git a/drivers/staging/lustre/lustre/fid/lproc_fid.c b/drivers/staging/lustre/lustre/fid/lproc_fid.c index 20d04488c04f..b1ad25706ed5 100644 --- a/drivers/staging/lustre/lustre/fid/lproc_fid.c +++ b/drivers/staging/lustre/lustre/fid/lproc_fid.c @@ -65,7 +65,6 @@ lprocfs_fid_write_common(const char *buffer, unsigned long count, { struct lu_seq_range tmp; int rc; - ENTRY; LASSERT(range != NULL); @@ -85,7 +84,6 @@ lprocfs_fid_space_seq_write(struct file *file, const char *buffer, { struct lu_client_seq *seq = ((struct seq_file *)file->private_data)->private; int rc; - ENTRY; LASSERT(seq != NULL); @@ -107,7 +105,6 @@ lprocfs_fid_space_seq_show(struct seq_file *m, void *unused) { struct lu_client_seq *seq = (struct lu_client_seq *)m->private; int rc; - ENTRY; LASSERT(seq != NULL); @@ -125,7 +122,6 @@ lprocfs_fid_width_seq_write(struct file *file, const char *buffer, struct lu_client_seq *seq = ((struct seq_file *)file->private_data)->private; __u64 max; int rc, val; - ENTRY; LASSERT(seq != NULL); @@ -158,7 +154,6 @@ lprocfs_fid_width_seq_show(struct seq_file *m, void *unused) { struct lu_client_seq *seq = (struct lu_client_seq *)m->private; int rc; - ENTRY; LASSERT(seq != NULL); @@ -174,7 +169,6 @@ lprocfs_fid_fid_seq_show(struct seq_file *m, void *unused) { struct lu_client_seq *seq = (struct lu_client_seq *)m->private; int rc; - ENTRY; LASSERT(seq != NULL); @@ -191,7 +185,6 @@ lprocfs_fid_server_seq_show(struct seq_file *m, void *unused) struct lu_client_seq *seq = (struct lu_client_seq *)m->private; struct client_obd *cli; int rc; - ENTRY; LASSERT(seq != NULL); diff --git a/drivers/staging/lustre/lustre/fld/fld_cache.c b/drivers/staging/lustre/lustre/fld/fld_cache.c index 84101076a656..9f9f9b5c6290 100644 --- a/drivers/staging/lustre/lustre/fld/fld_cache.c +++ b/drivers/staging/lustre/lustre/fld/fld_cache.c @@ -66,7 +66,6 @@ struct fld_cache *fld_cache_init(const char *name, int cache_size, int cache_threshold) { struct fld_cache *cache; - ENTRY; LASSERT(name != NULL); LASSERT(cache_threshold < cache_size); @@ -102,7 +101,6 @@ struct fld_cache *fld_cache_init(const char *name, void fld_cache_fini(struct fld_cache *cache) { __u64 pct; - ENTRY; LASSERT(cache != NULL); fld_cache_flush(cache); @@ -146,7 +144,6 @@ static void fld_fix_new_list(struct fld_cache *cache) struct lu_seq_range *c_range; struct lu_seq_range *n_range; struct list_head *head = &cache->fci_entries_head; - ENTRY; restart_fixup: @@ -226,7 +223,6 @@ static int fld_cache_shrink(struct fld_cache *cache) struct fld_cache_entry *flde; struct list_head *curr; int num = 0; - ENTRY; LASSERT(cache != NULL); @@ -255,8 +251,6 @@ static int fld_cache_shrink(struct fld_cache *cache) */ void fld_cache_flush(struct fld_cache *cache) { - ENTRY; - write_lock(&cache->fci_lock); cache->fci_cache_size = 0; fld_cache_shrink(cache); @@ -279,7 +273,6 @@ void fld_cache_punch_hole(struct fld_cache *cache, const seqno_t new_end = range->lsr_end; struct fld_cache_entry *fldt; - ENTRY; OBD_ALLOC_GFP(fldt, sizeof *fldt, GFP_ATOMIC); if (!fldt) { OBD_FREE_PTR(f_new); @@ -404,7 +397,6 @@ int fld_cache_insert_nolock(struct fld_cache *cache, const seqno_t new_start = f_new->fce_range.lsr_start; const seqno_t new_end = f_new->fce_range.lsr_end; __u32 new_flags = f_new->fce_range.lsr_flags; - ENTRY; /* * Duplicate entries are eliminated in insert op. @@ -521,7 +513,6 @@ struct fld_cache_entry *fld_cache_entry_lookup(struct fld_cache *cache, struct lu_seq_range *range) { struct fld_cache_entry *got = NULL; - ENTRY; read_lock(&cache->fci_lock); got = fld_cache_entry_lookup_nolock(cache, range); @@ -538,7 +529,6 @@ int fld_cache_lookup(struct fld_cache *cache, struct fld_cache_entry *flde; struct fld_cache_entry *prev = NULL; struct list_head *head; - ENTRY; read_lock(&cache->fci_lock); head = &cache->fci_entries_head; diff --git a/drivers/staging/lustre/lustre/fld/fld_request.c b/drivers/staging/lustre/lustre/fld/fld_request.c index 049322a79140..0c928dea899e 100644 --- a/drivers/staging/lustre/lustre/fld/fld_request.c +++ b/drivers/staging/lustre/lustre/fld/fld_request.c @@ -66,7 +66,7 @@ struct lu_context_key fld_thread_key; static int fld_req_avail(struct client_obd *cli, struct mdc_cache_waiter *mcw) { int rc; - ENTRY; + client_obd_list_lock(&cli->cl_loi_list_lock); rc = list_empty(&mcw->mcw_entry); client_obd_list_unlock(&cli->cl_loi_list_lock); @@ -124,7 +124,6 @@ fld_rrb_scan(struct lu_client_fld *fld, seqno_t seq) { struct lu_fld_target *target; int hash; - ENTRY; /* Because almost all of special sequence located in MDT0, * it should go to index 0 directly, instead of calculating @@ -180,7 +179,6 @@ static struct lu_fld_target * fld_client_get_target(struct lu_client_fld *fld, seqno_t seq) { struct lu_fld_target *target; - ENTRY; LASSERT(fld->lcf_hash != NULL); @@ -206,7 +204,6 @@ int fld_client_add_target(struct lu_client_fld *fld, { const char *name; struct lu_fld_target *target, *tmp; - ENTRY; LASSERT(tar != NULL); name = fld_target_name(tar); @@ -258,7 +255,6 @@ EXPORT_SYMBOL(fld_client_add_target); int fld_client_del_target(struct lu_client_fld *fld, __u64 idx) { struct lu_fld_target *target, *tmp; - ENTRY; spin_lock(&fld->lcf_lock); list_for_each_entry_safe(target, tmp, @@ -286,7 +282,6 @@ proc_dir_entry_t *fld_type_proc_dir = NULL; static int fld_client_proc_init(struct lu_client_fld *fld) { int rc; - ENTRY; fld->lcf_proc_dir = lprocfs_register(fld->lcf_name, fld_type_proc_dir, @@ -316,7 +311,6 @@ out_cleanup: void fld_client_proc_fini(struct lu_client_fld *fld) { - ENTRY; if (fld->lcf_proc_dir) { if (!IS_ERR(fld->lcf_proc_dir)) lprocfs_remove(&fld->lcf_proc_dir); @@ -348,7 +342,6 @@ int fld_client_init(struct lu_client_fld *fld, { int cache_size, cache_threshold; int rc; - ENTRY; LASSERT(fld != NULL); @@ -398,7 +391,6 @@ EXPORT_SYMBOL(fld_client_init); void fld_client_fini(struct lu_client_fld *fld) { struct lu_fld_target *target, *tmp; - ENTRY; spin_lock(&fld->lcf_lock); list_for_each_entry_safe(target, tmp, @@ -429,7 +421,6 @@ int fld_client_rpc(struct obd_export *exp, __u32 *op; int rc; struct obd_import *imp; - ENTRY; LASSERT(exp != NULL); @@ -479,7 +470,6 @@ int fld_client_lookup(struct lu_client_fld *fld, seqno_t seq, mdsno_t *mds, struct lu_seq_range res = { 0 }; struct lu_fld_target *target; int rc; - ENTRY; fld->lcf_flags |= LUSTRE_FLD_RUN; diff --git a/drivers/staging/lustre/lustre/fld/lproc_fld.c b/drivers/staging/lustre/lustre/fld/lproc_fld.c index 77322ba5bf31..cf1f765dcab8 100644 --- a/drivers/staging/lustre/lustre/fld/lproc_fld.c +++ b/drivers/staging/lustre/lustre/fld/lproc_fld.c @@ -62,7 +62,6 @@ fld_proc_targets_seq_show(struct seq_file *m, void *unused) { struct lu_client_fld *fld = (struct lu_client_fld *)m->private; struct lu_fld_target *target; - ENTRY; LASSERT(fld != NULL); @@ -79,7 +78,6 @@ static int fld_proc_hash_seq_show(struct seq_file *m, void *unused) { struct lu_client_fld *fld = (struct lu_client_fld *)m->private; - ENTRY; LASSERT(fld != NULL); @@ -97,7 +95,6 @@ fld_proc_hash_seq_write(struct file *file, const char *buffer, struct lu_client_fld *fld = ((struct seq_file *)file->private_data)->private; struct lu_fld_hash *hash = NULL; int i; - ENTRY; LASSERT(fld != NULL); @@ -128,7 +125,6 @@ fld_proc_cache_flush_write(struct file *file, const char __user *buffer, size_t count, loff_t *pos) { struct lu_client_fld *fld = file->private_data; - ENTRY; LASSERT(fld != NULL); diff --git a/drivers/staging/lustre/lustre/include/lustre_cfg.h b/drivers/staging/lustre/lustre/include/lustre_cfg.h index fbf94a081ffd..5004c9079a8b 100644 --- a/drivers/staging/lustre/lustre/include/lustre_cfg.h +++ b/drivers/staging/lustre/lustre/include/lustre_cfg.h @@ -211,7 +211,6 @@ static inline int lustre_cfg_len(__u32 bufcount, __u32 *buflens) { int i; int len; - ENTRY; len = LCFG_HDR_SIZE(bufcount); for (i = 0; i < bufcount; i++) @@ -230,8 +229,6 @@ static inline struct lustre_cfg *lustre_cfg_new(int cmd, char *ptr; int i; - ENTRY; - OBD_ALLOC(lcfg, lustre_cfg_len(bufs->lcfg_bufcount, bufs->lcfg_buflen)); if (!lcfg) @@ -263,7 +260,7 @@ static inline void lustre_cfg_free(struct lustre_cfg *lcfg) static inline int lustre_cfg_sanity_check(void *buf, int len) { struct lustre_cfg *lcfg = (struct lustre_cfg *)buf; - ENTRY; + if (!lcfg) RETURN(-EINVAL); diff --git a/drivers/staging/lustre/lustre/include/lustre_lib.h b/drivers/staging/lustre/lustre/include/lustre_lib.h index bdfc5391c6d2..007b2ddc7a9c 100644 --- a/drivers/staging/lustre/lustre/include/lustre_lib.h +++ b/drivers/staging/lustre/lustre/include/lustre_lib.h @@ -260,8 +260,6 @@ int obd_ioctl_popdata(void *arg, void *data, int len); static inline void obd_ioctl_freedata(char *buf, int len) { - ENTRY; - OBD_FREE_LARGE(buf, len); EXIT; return; diff --git a/drivers/staging/lustre/lustre/include/lustre_log.h b/drivers/staging/lustre/lustre/include/lustre_log.h index 714ab378e431..8f642f3e0105 100644 --- a/drivers/staging/lustre/lustre/include/lustre_log.h +++ b/drivers/staging/lustre/lustre/include/lustre_log.h @@ -469,8 +469,6 @@ static inline int llog_destroy(const struct lu_env *env, struct llog_operations *lop; int rc; - ENTRY; - rc = llog_handle2ops(handle, &lop); if (rc) RETURN(rc); @@ -489,8 +487,6 @@ static inline int llog_next_block(const struct lu_env *env, struct llog_operations *lop; int rc; - ENTRY; - rc = llog_handle2ops(loghandle, &lop); if (rc) RETURN(rc); @@ -509,8 +505,6 @@ static inline int llog_prev_block(const struct lu_env *env, struct llog_operations *lop; int rc; - ENTRY; - rc = llog_handle2ops(loghandle, &lop); if (rc) RETURN(rc); @@ -528,8 +522,6 @@ static inline int llog_connect(struct llog_ctxt *ctxt, struct llog_operations *lop; int rc; - ENTRY; - rc = llog_obd2ops(ctxt, &lop); if (rc) RETURN(rc); diff --git a/drivers/staging/lustre/lustre/include/lustre_mdc.h b/drivers/staging/lustre/lustre/include/lustre_mdc.h index 82d1f2f13031..e09646ade9d3 100644 --- a/drivers/staging/lustre/lustre/include/lustre_mdc.h +++ b/drivers/staging/lustre/lustre/include/lustre_mdc.h @@ -84,8 +84,6 @@ static inline void mdc_init_rpc_lock(struct mdc_rpc_lock *lck) static inline void mdc_get_rpc_lock(struct mdc_rpc_lock *lck, struct lookup_intent *it) { - ENTRY; - if (it != NULL && (it->it_op == IT_GETATTR || it->it_op == IT_LOOKUP || it->it_op == IT_LAYOUT)) return; diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h index de5c5853647f..c42996ba4f9c 100644 --- a/drivers/staging/lustre/lustre/include/obd_class.h +++ b/drivers/staging/lustre/lustre/include/obd_class.h @@ -495,7 +495,6 @@ static inline int obd_get_info(const struct lu_env *env, struct lov_stripe_md *lsm) { int rc; - ENTRY; EXP_CHECK_DT_OP(exp, get_info); EXP_COUNTER_INCREMENT(exp, get_info); @@ -511,7 +510,6 @@ static inline int obd_set_info_async(const struct lu_env *env, struct ptlrpc_request_set *set) { int rc; - ENTRY; EXP_CHECK_DT_OP(exp, set_info_async); EXP_COUNTER_INCREMENT(exp, set_info_async); @@ -547,7 +545,6 @@ static inline int obd_setup(struct obd_device *obd, struct lustre_cfg *cfg) { int rc; DECLARE_LU_VARS(ldt, d); - ENTRY; ldt = obd->obd_type->typ_lu; if (ldt != NULL) { @@ -585,7 +582,6 @@ static inline int obd_precleanup(struct obd_device *obd, { int rc; DECLARE_LU_VARS(ldt, d); - ENTRY; OBD_CHECK_DEV(obd); ldt = obd->obd_type->typ_lu; @@ -612,7 +608,6 @@ static inline int obd_cleanup(struct obd_device *obd) { int rc; DECLARE_LU_VARS(ldt, d); - ENTRY; OBD_CHECK_DEV(obd); @@ -637,8 +632,6 @@ static inline int obd_cleanup(struct obd_device *obd) static inline void obd_cleanup_client_import(struct obd_device *obd) { - ENTRY; - /* If we set up but never connected, the client import will not have been cleaned. */ down_write(&obd->u.cli.cl_sem); @@ -665,7 +658,6 @@ obd_process_config(struct obd_device *obd, int datalen, void *data) { int rc; DECLARE_LU_VARS(ldt, d); - ENTRY; OBD_CHECK_DEV(obd); @@ -702,7 +694,6 @@ static inline int obd_packmd(struct obd_export *exp, struct lov_stripe_md *mem_src) { int rc; - ENTRY; EXP_CHECK_DT_OP(exp, packmd); EXP_COUNTER_INCREMENT(exp, packmd); @@ -757,7 +748,6 @@ static inline int obd_unpackmd(struct obd_export *exp, int disk_len) { int rc; - ENTRY; EXP_CHECK_DT_OP(exp, unpackmd); EXP_COUNTER_INCREMENT(exp, unpackmd); @@ -790,7 +780,6 @@ static inline int obd_free_memmd(struct obd_export *exp, static inline int obd_precreate(struct obd_export *exp) { int rc; - ENTRY; EXP_CHECK_DT_OP(exp, precreate); OBD_COUNTER_INCREMENT(exp->exp_obd, precreate); @@ -805,7 +794,6 @@ static inline int obd_create_async(struct obd_export *exp, struct obd_trans_info *oti) { int rc; - ENTRY; EXP_CHECK_DT_OP(exp, create_async); EXP_COUNTER_INCREMENT(exp, create_async); @@ -819,7 +807,6 @@ static inline int obd_create(const struct lu_env *env, struct obd_export *exp, struct obd_trans_info *oti) { int rc; - ENTRY; EXP_CHECK_DT_OP(exp, create); EXP_COUNTER_INCREMENT(exp, create); @@ -834,7 +821,6 @@ static inline int obd_destroy(const struct lu_env *env, struct obd_export *exp, struct obd_export *md_exp, void *capa) { int rc; - ENTRY; EXP_CHECK_DT_OP(exp, destroy); EXP_COUNTER_INCREMENT(exp, destroy); @@ -847,7 +833,6 @@ static inline int obd_getattr(const struct lu_env *env, struct obd_export *exp, struct obd_info *oinfo) { int rc; - ENTRY; EXP_CHECK_DT_OP(exp, getattr); EXP_COUNTER_INCREMENT(exp, getattr); @@ -861,7 +846,6 @@ static inline int obd_getattr_async(struct obd_export *exp, struct ptlrpc_request_set *set) { int rc; - ENTRY; EXP_CHECK_DT_OP(exp, getattr_async); EXP_COUNTER_INCREMENT(exp, getattr_async); @@ -875,7 +859,6 @@ static inline int obd_setattr(const struct lu_env *env, struct obd_export *exp, struct obd_trans_info *oti) { int rc; - ENTRY; EXP_CHECK_DT_OP(exp, setattr); EXP_COUNTER_INCREMENT(exp, setattr); @@ -891,7 +874,6 @@ static inline int obd_setattr_rqset(struct obd_export *exp, { struct ptlrpc_request_set *set = NULL; int rc; - ENTRY; EXP_CHECK_DT_OP(exp, setattr_async); EXP_COUNTER_INCREMENT(exp, setattr_async); @@ -915,7 +897,6 @@ static inline int obd_setattr_async(struct obd_export *exp, struct ptlrpc_request_set *set) { int rc; - ENTRY; EXP_CHECK_DT_OP(exp, setattr_async); EXP_COUNTER_INCREMENT(exp, setattr_async); @@ -929,7 +910,6 @@ static inline int obd_add_conn(struct obd_import *imp, struct obd_uuid *uuid, { struct obd_device *obd = imp->imp_obd; int rc; - ENTRY; OBD_CHECK_DEV_ACTIVE(obd); OBD_CHECK_DT_OP(obd, add_conn, -EOPNOTSUPP); @@ -943,7 +923,6 @@ static inline int obd_del_conn(struct obd_import *imp, struct obd_uuid *uuid) { struct obd_device *obd = imp->imp_obd; int rc; - ENTRY; OBD_CHECK_DEV_ACTIVE(obd); OBD_CHECK_DT_OP(obd, del_conn, -EOPNOTSUPP); @@ -956,7 +935,6 @@ static inline int obd_del_conn(struct obd_import *imp, struct obd_uuid *uuid) static inline struct obd_uuid *obd_get_uuid(struct obd_export *exp) { struct obd_uuid *uuid; - ENTRY; OBD_CHECK_DT_OP(exp->exp_obd, get_uuid, NULL); EXP_COUNTER_INCREMENT(exp, get_uuid); @@ -979,7 +957,6 @@ static inline int obd_connect(const struct lu_env *env, int rc; __u64 ocf = data ? data->ocd_connect_flags : 0; /* for post-condition * check */ - ENTRY; OBD_CHECK_DEV_ACTIVE(obd); OBD_CHECK_DT_OP(obd, connect, -EOPNOTSUPP); @@ -1003,8 +980,6 @@ static inline int obd_reconnect(const struct lu_env *env, __u64 ocf = d ? d->ocd_connect_flags : 0; /* for post-condition * check */ - ENTRY; - OBD_CHECK_DEV_ACTIVE(obd); OBD_CHECK_DT_OP(obd, reconnect, 0); OBD_COUNTER_INCREMENT(obd, reconnect); @@ -1019,7 +994,6 @@ static inline int obd_reconnect(const struct lu_env *env, static inline int obd_disconnect(struct obd_export *exp) { int rc; - ENTRY; EXP_CHECK_DT_OP(exp, disconnect); EXP_COUNTER_INCREMENT(exp, disconnect); @@ -1032,7 +1006,6 @@ static inline int obd_fid_init(struct obd_device *obd, struct obd_export *exp, enum lu_cli_type type) { int rc; - ENTRY; OBD_CHECK_DT_OP(obd, fid_init, 0); OBD_COUNTER_INCREMENT(obd, fid_init); @@ -1044,7 +1017,6 @@ static inline int obd_fid_init(struct obd_device *obd, struct obd_export *exp, static inline int obd_fid_fini(struct obd_device *obd) { int rc; - ENTRY; OBD_CHECK_DT_OP(obd, fid_fini, 0); OBD_COUNTER_INCREMENT(obd, fid_fini); @@ -1058,7 +1030,6 @@ static inline int obd_fid_alloc(struct obd_export *exp, struct md_op_data *op_data) { int rc; - ENTRY; EXP_CHECK_DT_OP(exp, fid_alloc); EXP_COUNTER_INCREMENT(exp, fid_alloc); @@ -1070,7 +1041,6 @@ static inline int obd_fid_alloc(struct obd_export *exp, static inline int obd_ping(const struct lu_env *env, struct obd_export *exp) { int rc; - ENTRY; OBD_CHECK_DT_OP(exp->exp_obd, ping, 0); EXP_COUNTER_INCREMENT(exp, ping); @@ -1082,7 +1052,6 @@ static inline int obd_ping(const struct lu_env *env, struct obd_export *exp) static inline int obd_pool_new(struct obd_device *obd, char *poolname) { int rc; - ENTRY; OBD_CHECK_DT_OP(obd, pool_new, -EOPNOTSUPP); OBD_COUNTER_INCREMENT(obd, pool_new); @@ -1094,7 +1063,6 @@ static inline int obd_pool_new(struct obd_device *obd, char *poolname) static inline int obd_pool_del(struct obd_device *obd, char *poolname) { int rc; - ENTRY; OBD_CHECK_DT_OP(obd, pool_del, -EOPNOTSUPP); OBD_COUNTER_INCREMENT(obd, pool_del); @@ -1106,7 +1074,6 @@ static inline int obd_pool_del(struct obd_device *obd, char *poolname) static inline int obd_pool_add(struct obd_device *obd, char *poolname, char *ostname) { int rc; - ENTRY; OBD_CHECK_DT_OP(obd, pool_add, -EOPNOTSUPP); OBD_COUNTER_INCREMENT(obd, pool_add); @@ -1118,7 +1085,6 @@ static inline int obd_pool_add(struct obd_device *obd, char *poolname, char *ost static inline int obd_pool_rem(struct obd_device *obd, char *poolname, char *ostname) { int rc; - ENTRY; OBD_CHECK_DT_OP(obd, pool_rem, -EOPNOTSUPP); OBD_COUNTER_INCREMENT(obd, pool_rem); @@ -1129,7 +1095,6 @@ static inline int obd_pool_rem(struct obd_device *obd, char *poolname, char *ost static inline void obd_getref(struct obd_device *obd) { - ENTRY; if (OBT(obd) && OBP(obd, getref)) { OBD_COUNTER_INCREMENT(obd, getref); OBP(obd, getref)(obd); @@ -1139,7 +1104,6 @@ static inline void obd_getref(struct obd_device *obd) static inline void obd_putref(struct obd_device *obd) { - ENTRY; if (OBT(obd) && OBP(obd, putref)) { OBD_COUNTER_INCREMENT(obd, putref); OBP(obd, putref)(obd); @@ -1151,7 +1115,6 @@ static inline int obd_init_export(struct obd_export *exp) { int rc = 0; - ENTRY; if ((exp)->exp_obd != NULL && OBT((exp)->exp_obd) && OBP((exp)->exp_obd, init_export)) rc = OBP(exp->exp_obd, init_export)(exp); @@ -1160,7 +1123,6 @@ static inline int obd_init_export(struct obd_export *exp) static inline int obd_destroy_export(struct obd_export *exp) { - ENTRY; if ((exp)->exp_obd != NULL && OBT((exp)->exp_obd) && OBP((exp)->exp_obd, destroy_export)) OBP(exp->exp_obd, destroy_export)(exp); @@ -1172,7 +1134,7 @@ static inline int obd_extent_calc(struct obd_export *exp, int cmd, obd_off *offset) { int rc; - ENTRY; + EXP_CHECK_DT_OP(exp, extent_calc); rc = OBP(exp->exp_obd, extent_calc)(exp, md, cmd, offset); RETURN(rc); @@ -1198,7 +1160,6 @@ static inline int obd_statfs_async(struct obd_export *exp, { int rc = 0; struct obd_device *obd; - ENTRY; if (exp == NULL || exp->exp_obd == NULL) RETURN(-EINVAL); @@ -1234,7 +1195,6 @@ static inline int obd_statfs_rqset(struct obd_export *exp, struct ptlrpc_request_set *set = NULL; struct obd_info oinfo = { { { 0 } } }; int rc = 0; - ENTRY; set = ptlrpc_prep_set(); if (set == NULL) @@ -1258,7 +1218,6 @@ static inline int obd_statfs(const struct lu_env *env, struct obd_export *exp, { int rc = 0; struct obd_device *obd = exp->exp_obd; - ENTRY; if (obd == NULL) RETURN(-EINVAL); @@ -1294,7 +1253,6 @@ static inline int obd_sync_rqset(struct obd_export *exp, struct obd_info *oinfo, { struct ptlrpc_request_set *set = NULL; int rc; - ENTRY; OBD_CHECK_DT_OP(exp->exp_obd, sync, -EOPNOTSUPP); EXP_COUNTER_INCREMENT(exp, sync); @@ -1315,7 +1273,6 @@ static inline int obd_sync(const struct lu_env *env, struct obd_export *exp, struct ptlrpc_request_set *set) { int rc; - ENTRY; OBD_CHECK_DT_OP(exp->exp_obd, sync, -EOPNOTSUPP); EXP_COUNTER_INCREMENT(exp, sync); @@ -1330,7 +1287,6 @@ static inline int obd_punch_rqset(struct obd_export *exp, { struct ptlrpc_request_set *set = NULL; int rc; - ENTRY; EXP_CHECK_DT_OP(exp, punch); EXP_COUNTER_INCREMENT(exp, punch); @@ -1351,7 +1307,6 @@ static inline int obd_punch(const struct lu_env *env, struct obd_export *exp, struct ptlrpc_request_set *rqset) { int rc; - ENTRY; EXP_CHECK_DT_OP(exp, punch); EXP_COUNTER_INCREMENT(exp, punch); @@ -1365,7 +1320,6 @@ static inline int obd_brw(int cmd, struct obd_export *exp, struct brw_page *pg, struct obd_trans_info *oti) { int rc; - ENTRY; EXP_CHECK_DT_OP(exp, brw); EXP_COUNTER_INCREMENT(exp, brw); @@ -1389,7 +1343,6 @@ static inline int obd_preprw(const struct lu_env *env, int cmd, struct lustre_capa *capa) { int rc; - ENTRY; EXP_CHECK_DT_OP(exp, preprw); EXP_COUNTER_INCREMENT(exp, preprw); @@ -1406,8 +1359,6 @@ static inline int obd_commitrw(const struct lu_env *env, int cmd, struct niobuf_local *local, struct obd_trans_info *oti, int rc) { - ENTRY; - EXP_CHECK_DT_OP(exp, commitrw); EXP_COUNTER_INCREMENT(exp, commitrw); @@ -1421,7 +1372,6 @@ static inline int obd_merge_lvb(struct obd_export *exp, struct ost_lvb *lvb, int kms_only) { int rc; - ENTRY; EXP_CHECK_DT_OP(exp, merge_lvb); EXP_COUNTER_INCREMENT(exp, merge_lvb); @@ -1435,7 +1385,6 @@ static inline int obd_adjust_kms(struct obd_export *exp, int shrink) { int rc; - ENTRY; EXP_CHECK_DT_OP(exp, adjust_kms); EXP_COUNTER_INCREMENT(exp, adjust_kms); @@ -1448,7 +1397,6 @@ static inline int obd_iocontrol(unsigned int cmd, struct obd_export *exp, int len, void *karg, void *uarg) { int rc; - ENTRY; EXP_CHECK_DT_OP(exp, iocontrol); EXP_COUNTER_INCREMENT(exp, iocontrol); @@ -1463,7 +1411,6 @@ static inline int obd_enqueue_rqset(struct obd_export *exp, { struct ptlrpc_request_set *set = NULL; int rc; - ENTRY; EXP_CHECK_DT_OP(exp, enqueue); EXP_COUNTER_INCREMENT(exp, enqueue); @@ -1485,7 +1432,6 @@ static inline int obd_enqueue(struct obd_export *exp, struct ptlrpc_request_set *set) { int rc; - ENTRY; EXP_CHECK_DT_OP(exp, enqueue); EXP_COUNTER_INCREMENT(exp, enqueue); @@ -1499,7 +1445,6 @@ static inline int obd_change_cbdata(struct obd_export *exp, ldlm_iterator_t it, void *data) { int rc; - ENTRY; EXP_CHECK_DT_OP(exp, change_cbdata); EXP_COUNTER_INCREMENT(exp, change_cbdata); @@ -1513,7 +1458,6 @@ static inline int obd_find_cbdata(struct obd_export *exp, ldlm_iterator_t it, void *data) { int rc; - ENTRY; EXP_CHECK_DT_OP(exp, find_cbdata); EXP_COUNTER_INCREMENT(exp, find_cbdata); @@ -1527,7 +1471,6 @@ static inline int obd_cancel(struct obd_export *exp, struct lustre_handle *lockh) { int rc; - ENTRY; EXP_CHECK_DT_OP(exp, cancel); EXP_COUNTER_INCREMENT(exp, cancel); @@ -1542,7 +1485,6 @@ static inline int obd_cancel_unused(struct obd_export *exp, void *opaque) { int rc; - ENTRY; EXP_CHECK_DT_OP(exp, cancel_unused); EXP_COUNTER_INCREMENT(exp, cancel_unused); @@ -1556,7 +1498,6 @@ static inline int obd_pin(struct obd_export *exp, const struct lu_fid *fid, int flag) { int rc; - ENTRY; EXP_CHECK_DT_OP(exp, pin); EXP_COUNTER_INCREMENT(exp, pin); @@ -1569,7 +1510,6 @@ static inline int obd_unpin(struct obd_export *exp, struct obd_client_handle *handle, int flag) { int rc; - ENTRY; EXP_CHECK_DT_OP(exp, unpin); EXP_COUNTER_INCREMENT(exp, unpin); @@ -1583,7 +1523,6 @@ static inline void obd_import_event(struct obd_device *obd, struct obd_import *imp, enum obd_import_event event) { - ENTRY; if (!obd) { CERROR("NULL device\n"); EXIT; @@ -1600,7 +1539,6 @@ static inline int obd_llog_connect(struct obd_export *exp, struct llogd_conn_body *body) { int rc; - ENTRY; OBD_CHECK_DT_OP(exp->exp_obd, llog_connect, 0); EXP_COUNTER_INCREMENT(exp, llog_connect); @@ -1616,7 +1554,7 @@ static inline int obd_notify(struct obd_device *obd, void *data) { int rc; - ENTRY; + OBD_CHECK_DEV(obd); /* the check for async_recov is a complete hack - I'm hereby @@ -1669,7 +1607,6 @@ static inline int obd_quotacheck(struct obd_export *exp, struct obd_quotactl *oqctl) { int rc; - ENTRY; EXP_CHECK_DT_OP(exp, quotacheck); EXP_COUNTER_INCREMENT(exp, quotacheck); @@ -1682,7 +1619,6 @@ static inline int obd_quotactl(struct obd_export *exp, struct obd_quotactl *oqctl) { int rc; - ENTRY; EXP_CHECK_DT_OP(exp, quotactl); EXP_COUNTER_INCREMENT(exp, quotactl); @@ -1702,7 +1638,6 @@ static inline int obd_health_check(const struct lu_env *env, * <0 on error */ int rc; - ENTRY; /* don't use EXP_CHECK_DT_OP, because NULL method is normal here */ if (obd == NULL || !OBT(obd)) { @@ -1721,7 +1656,6 @@ static inline int obd_health_check(const struct lu_env *env, static inline int obd_register_observer(struct obd_device *obd, struct obd_device *observer) { - ENTRY; OBD_CHECK_DEV(obd); down_write(&obd->obd_observer_link_sem); if (obd->obd_observer && observer) { @@ -1736,7 +1670,6 @@ static inline int obd_register_observer(struct obd_device *obd, static inline int obd_pin_observer(struct obd_device *obd, struct obd_device **observer) { - ENTRY; down_read(&obd->obd_observer_link_sem); if (!obd->obd_observer) { *observer = NULL; @@ -1749,7 +1682,6 @@ static inline int obd_pin_observer(struct obd_device *obd, static inline int obd_unpin_observer(struct obd_device *obd) { - ENTRY; up_read(&obd->obd_observer_link_sem); RETURN(0); } @@ -1760,7 +1692,6 @@ static inline int obd_register_page_removal_cb(struct obd_export *exp, obd_pin_extent_cb pin_cb) { int rc; - ENTRY; OBD_CHECK_DT_OP(exp->exp_obd, register_page_removal_cb, 0); OBD_COUNTER_INCREMENT(exp->exp_obd, register_page_removal_cb); @@ -1773,7 +1704,6 @@ static inline int obd_unregister_page_removal_cb(struct obd_export *exp, obd_page_removal_cb_t cb) { int rc; - ENTRY; OBD_CHECK_DT_OP(exp->exp_obd, unregister_page_removal_cb, 0); OBD_COUNTER_INCREMENT(exp->exp_obd, unregister_page_removal_cb); @@ -1786,7 +1716,6 @@ static inline int obd_register_lock_cancel_cb(struct obd_export *exp, obd_lock_cancel_cb cb) { int rc; - ENTRY; OBD_CHECK_DT_OP(exp->exp_obd, register_lock_cancel_cb, 0); OBD_COUNTER_INCREMENT(exp->exp_obd, register_lock_cancel_cb); @@ -1799,7 +1728,6 @@ static inline int obd_unregister_lock_cancel_cb(struct obd_export *exp, obd_lock_cancel_cb cb) { int rc; - ENTRY; OBD_CHECK_DT_OP(exp->exp_obd, unregister_lock_cancel_cb, 0); OBD_COUNTER_INCREMENT(exp->exp_obd, unregister_lock_cancel_cb); @@ -1814,7 +1742,6 @@ static inline int md_getstatus(struct obd_export *exp, struct lu_fid *fid, struct obd_capa **pc) { int rc; - ENTRY; EXP_CHECK_MD_OP(exp, getstatus); EXP_MD_COUNTER_INCREMENT(exp, getstatus); @@ -1826,7 +1753,7 @@ static inline int md_getattr(struct obd_export *exp, struct md_op_data *op_data, struct ptlrpc_request **request) { int rc; - ENTRY; + EXP_CHECK_MD_OP(exp, getattr); EXP_MD_COUNTER_INCREMENT(exp, getattr); rc = MDP(exp->exp_obd, getattr)(exp, op_data, request); @@ -1837,7 +1764,7 @@ static inline int md_null_inode(struct obd_export *exp, const struct lu_fid *fid) { int rc; - ENTRY; + EXP_CHECK_MD_OP(exp, null_inode); EXP_MD_COUNTER_INCREMENT(exp, null_inode); rc = MDP(exp->exp_obd, null_inode)(exp, fid); @@ -1849,7 +1776,7 @@ static inline int md_find_cbdata(struct obd_export *exp, ldlm_iterator_t it, void *data) { int rc; - ENTRY; + EXP_CHECK_MD_OP(exp, find_cbdata); EXP_MD_COUNTER_INCREMENT(exp, find_cbdata); rc = MDP(exp->exp_obd, find_cbdata)(exp, fid, it, data); @@ -1861,7 +1788,7 @@ static inline int md_close(struct obd_export *exp, struct md_op_data *op_data, struct ptlrpc_request **request) { int rc; - ENTRY; + EXP_CHECK_MD_OP(exp, close); EXP_MD_COUNTER_INCREMENT(exp, close); rc = MDP(exp->exp_obd, close)(exp, op_data, mod, request); @@ -1874,7 +1801,7 @@ static inline int md_create(struct obd_export *exp, struct md_op_data *op_data, struct ptlrpc_request **request) { int rc; - ENTRY; + EXP_CHECK_MD_OP(exp, create); EXP_MD_COUNTER_INCREMENT(exp, create); rc = MDP(exp->exp_obd, create)(exp, op_data, data, datalen, mode, @@ -1887,7 +1814,7 @@ static inline int md_done_writing(struct obd_export *exp, struct md_open_data *mod) { int rc; - ENTRY; + EXP_CHECK_MD_OP(exp, done_writing); EXP_MD_COUNTER_INCREMENT(exp, done_writing); rc = MDP(exp->exp_obd, done_writing)(exp, op_data, mod); @@ -1904,7 +1831,7 @@ static inline int md_enqueue(struct obd_export *exp, int extra_lock_flags) { int rc; - ENTRY; + EXP_CHECK_MD_OP(exp, enqueue); EXP_MD_COUNTER_INCREMENT(exp, enqueue); rc = MDP(exp->exp_obd, enqueue)(exp, einfo, it, op_data, lockh, @@ -1917,7 +1844,7 @@ static inline int md_getattr_name(struct obd_export *exp, struct ptlrpc_request **request) { int rc; - ENTRY; + EXP_CHECK_MD_OP(exp, getattr_name); EXP_MD_COUNTER_INCREMENT(exp, getattr_name); rc = MDP(exp->exp_obd, getattr_name)(exp, op_data, request); @@ -1932,7 +1859,7 @@ static inline int md_intent_lock(struct obd_export *exp, __u64 extra_lock_flags) { int rc; - ENTRY; + EXP_CHECK_MD_OP(exp, intent_lock); EXP_MD_COUNTER_INCREMENT(exp, intent_lock); rc = MDP(exp->exp_obd, intent_lock)(exp, op_data, lmm, lmmsize, @@ -1945,7 +1872,7 @@ static inline int md_link(struct obd_export *exp, struct md_op_data *op_data, struct ptlrpc_request **request) { int rc; - ENTRY; + EXP_CHECK_MD_OP(exp, link); EXP_MD_COUNTER_INCREMENT(exp, link); rc = MDP(exp->exp_obd, link)(exp, op_data, request); @@ -1957,7 +1884,7 @@ static inline int md_rename(struct obd_export *exp, struct md_op_data *op_data, int newlen, struct ptlrpc_request **request) { int rc; - ENTRY; + EXP_CHECK_MD_OP(exp, rename); EXP_MD_COUNTER_INCREMENT(exp, rename); rc = MDP(exp->exp_obd, rename)(exp, op_data, old, oldlen, new, @@ -1971,7 +1898,7 @@ static inline int md_is_subdir(struct obd_export *exp, struct ptlrpc_request **request) { int rc; - ENTRY; + EXP_CHECK_MD_OP(exp, is_subdir); EXP_MD_COUNTER_INCREMENT(exp, is_subdir); rc = MDP(exp->exp_obd, is_subdir)(exp, pfid, cfid, request); @@ -1984,7 +1911,7 @@ static inline int md_setattr(struct obd_export *exp, struct md_op_data *op_data, struct md_open_data **mod) { int rc; - ENTRY; + EXP_CHECK_MD_OP(exp, setattr); EXP_MD_COUNTER_INCREMENT(exp, setattr); rc = MDP(exp->exp_obd, setattr)(exp, op_data, ea, ealen, @@ -1996,7 +1923,7 @@ static inline int md_sync(struct obd_export *exp, const struct lu_fid *fid, struct obd_capa *oc, struct ptlrpc_request **request) { int rc; - ENTRY; + EXP_CHECK_MD_OP(exp, sync); EXP_MD_COUNTER_INCREMENT(exp, sync); rc = MDP(exp->exp_obd, sync)(exp, fid, oc, request); @@ -2008,7 +1935,7 @@ static inline int md_readpage(struct obd_export *exp, struct md_op_data *opdata, struct ptlrpc_request **request) { int rc; - ENTRY; + EXP_CHECK_MD_OP(exp, readpage); EXP_MD_COUNTER_INCREMENT(exp, readpage); rc = MDP(exp->exp_obd, readpage)(exp, opdata, pages, request); @@ -2019,7 +1946,7 @@ static inline int md_unlink(struct obd_export *exp, struct md_op_data *op_data, struct ptlrpc_request **request) { int rc; - ENTRY; + EXP_CHECK_MD_OP(exp, unlink); EXP_MD_COUNTER_INCREMENT(exp, unlink); rc = MDP(exp->exp_obd, unlink)(exp, op_data, request); @@ -2032,7 +1959,6 @@ static inline int md_get_lustre_md(struct obd_export *exp, struct obd_export *md_exp, struct lustre_md *md) { - ENTRY; EXP_CHECK_MD_OP(exp, get_lustre_md); EXP_MD_COUNTER_INCREMENT(exp, get_lustre_md); RETURN(MDP(exp->exp_obd, get_lustre_md)(exp, req, dt_exp, md_exp, md)); @@ -2041,7 +1967,6 @@ static inline int md_get_lustre_md(struct obd_export *exp, static inline int md_free_lustre_md(struct obd_export *exp, struct lustre_md *md) { - ENTRY; EXP_CHECK_MD_OP(exp, free_lustre_md); EXP_MD_COUNTER_INCREMENT(exp, free_lustre_md); RETURN(MDP(exp->exp_obd, free_lustre_md)(exp, md)); @@ -2054,7 +1979,6 @@ static inline int md_setxattr(struct obd_export *exp, int output_size, int flags, __u32 suppgid, struct ptlrpc_request **request) { - ENTRY; EXP_CHECK_MD_OP(exp, setxattr); EXP_MD_COUNTER_INCREMENT(exp, setxattr); RETURN(MDP(exp->exp_obd, setxattr)(exp, fid, oc, valid, name, input, @@ -2069,7 +1993,6 @@ static inline int md_getxattr(struct obd_export *exp, int output_size, int flags, struct ptlrpc_request **request) { - ENTRY; EXP_CHECK_MD_OP(exp, getxattr); EXP_MD_COUNTER_INCREMENT(exp, getxattr); RETURN(MDP(exp->exp_obd, getxattr)(exp, fid, oc, valid, name, input, @@ -2081,7 +2004,6 @@ static inline int md_set_open_replay_data(struct obd_export *exp, struct obd_client_handle *och, struct ptlrpc_request *open_req) { - ENTRY; EXP_CHECK_MD_OP(exp, set_open_replay_data); EXP_MD_COUNTER_INCREMENT(exp, set_open_replay_data); RETURN(MDP(exp->exp_obd, set_open_replay_data)(exp, och, open_req)); @@ -2090,7 +2012,6 @@ static inline int md_set_open_replay_data(struct obd_export *exp, static inline int md_clear_open_replay_data(struct obd_export *exp, struct obd_client_handle *och) { - ENTRY; EXP_CHECK_MD_OP(exp, clear_open_replay_data); EXP_MD_COUNTER_INCREMENT(exp, clear_open_replay_data); RETURN(MDP(exp->exp_obd, clear_open_replay_data)(exp, och)); @@ -2099,7 +2020,6 @@ static inline int md_clear_open_replay_data(struct obd_export *exp, static inline int md_set_lock_data(struct obd_export *exp, __u64 *lockh, void *data, __u64 *bits) { - ENTRY; EXP_CHECK_MD_OP(exp, set_lock_data); EXP_MD_COUNTER_INCREMENT(exp, set_lock_data); RETURN(MDP(exp->exp_obd, set_lock_data)(exp, lockh, data, bits)); @@ -2113,7 +2033,6 @@ static inline int md_cancel_unused(struct obd_export *exp, void *opaque) { int rc; - ENTRY; EXP_CHECK_MD_OP(exp, cancel_unused); EXP_MD_COUNTER_INCREMENT(exp, cancel_unused); @@ -2130,7 +2049,6 @@ static inline ldlm_mode_t md_lock_match(struct obd_export *exp, __u64 flags, ldlm_mode_t mode, struct lustre_handle *lockh) { - ENTRY; EXP_CHECK_MD_OP(exp, lock_match); EXP_MD_COUNTER_INCREMENT(exp, lock_match); RETURN(MDP(exp->exp_obd, lock_match)(exp, flags, fid, type, @@ -2140,7 +2058,6 @@ static inline ldlm_mode_t md_lock_match(struct obd_export *exp, __u64 flags, static inline int md_init_ea_size(struct obd_export *exp, int easize, int def_asize, int cookiesize) { - ENTRY; EXP_CHECK_MD_OP(exp, init_ea_size); EXP_MD_COUNTER_INCREMENT(exp, init_ea_size); RETURN(MDP(exp->exp_obd, init_ea_size)(exp, easize, def_asize, @@ -2152,7 +2069,6 @@ static inline int md_get_remote_perm(struct obd_export *exp, struct obd_capa *oc, __u32 suppgid, struct ptlrpc_request **request) { - ENTRY; EXP_CHECK_MD_OP(exp, get_remote_perm); EXP_MD_COUNTER_INCREMENT(exp, get_remote_perm); RETURN(MDP(exp->exp_obd, get_remote_perm)(exp, fid, oc, suppgid, @@ -2163,7 +2079,7 @@ static inline int md_renew_capa(struct obd_export *exp, struct obd_capa *ocapa, renew_capa_cb_t cb) { int rc; - ENTRY; + EXP_CHECK_MD_OP(exp, renew_capa); EXP_MD_COUNTER_INCREMENT(exp, renew_capa); rc = MDP(exp->exp_obd, renew_capa)(exp, ocapa, cb); @@ -2176,7 +2092,7 @@ static inline int md_unpack_capa(struct obd_export *exp, struct obd_capa **oc) { int rc; - ENTRY; + EXP_CHECK_MD_OP(exp, unpack_capa); EXP_MD_COUNTER_INCREMENT(exp, unpack_capa); rc = MDP(exp->exp_obd, unpack_capa)(exp, req, field, oc); @@ -2188,7 +2104,7 @@ static inline int md_intent_getattr_async(struct obd_export *exp, struct ldlm_enqueue_info *einfo) { int rc; - ENTRY; + EXP_CHECK_MD_OP(exp, intent_getattr_async); EXP_MD_COUNTER_INCREMENT(exp, intent_getattr_async); rc = MDP(exp->exp_obd, intent_getattr_async)(exp, minfo, einfo); @@ -2200,7 +2116,7 @@ static inline int md_revalidate_lock(struct obd_export *exp, struct lu_fid *fid, __u64 *bits) { int rc; - ENTRY; + EXP_CHECK_MD_OP(exp, revalidate_lock); EXP_MD_COUNTER_INCREMENT(exp, revalidate_lock); rc = MDP(exp->exp_obd, revalidate_lock)(exp, it, fid, bits); diff --git a/drivers/staging/lustre/lustre/lclient/glimpse.c b/drivers/staging/lustre/lustre/lclient/glimpse.c index 7f3974be1f92..db72d89573b6 100644 --- a/drivers/staging/lustre/lustre/lclient/glimpse.c +++ b/drivers/staging/lustre/lustre/lclient/glimpse.c @@ -93,7 +93,6 @@ int cl_glimpse_lock(const struct lu_env *env, struct cl_io *io, struct cl_lock *lock; int result; - ENTRY; result = 0; if (!(lli->lli_flags & LLIF_MDS_SIZE_LOCK)) { CDEBUG(D_DLMTRACE, "Glimpsing inode "DFID"\n", PFID(fid)); @@ -203,8 +202,6 @@ int cl_glimpse_size0(struct inode *inode, int agl) int result; int refcheck; - ENTRY; - result = cl_io_get(inode, &env, &io, &refcheck); if (result > 0) { again: @@ -240,8 +237,6 @@ int cl_local_size(struct inode *inode) int result; int refcheck; - ENTRY; - if (!cl_i2info(inode)->lli_has_smd) RETURN(0); diff --git a/drivers/staging/lustre/lustre/lclient/lcommon_cl.c b/drivers/staging/lustre/lustre/lclient/lcommon_cl.c index c8690cb7731d..1d3c2340227b 100644 --- a/drivers/staging/lustre/lustre/lclient/lcommon_cl.c +++ b/drivers/staging/lustre/lustre/lclient/lcommon_cl.c @@ -169,7 +169,6 @@ int ccc_device_init(const struct lu_env *env, struct lu_device *d, { struct ccc_device *vdv; int rc; - ENTRY; vdv = lu2ccc_dev(d); vdv->cdv_next = lu2cl_dev(next); @@ -201,7 +200,6 @@ struct lu_device *ccc_device_alloc(const struct lu_env *env, struct lu_device *lud; struct cl_site *site; int rc; - ENTRY; OBD_ALLOC_PTR(vdv); if (vdv == NULL) @@ -418,7 +416,6 @@ int ccc_object_glimpse(const struct lu_env *env, { struct inode *inode = ccc_object_inode(obj); - ENTRY; lvb->lvb_mtime = cl_inode_mtime(inode); lvb->lvb_atime = cl_inode_atime(inode); lvb->lvb_ctime = cl_inode_ctime(inode); @@ -479,8 +476,6 @@ int ccc_page_is_under_lock(const struct lu_env *env, int result; - ENTRY; - if (io->ci_type == CIT_READ || io->ci_type == CIT_WRITE || io->ci_type == CIT_FAULT) { if (cio->cui_fd->fd_flags & LL_FILE_GROUP_LOCKED) @@ -559,7 +554,6 @@ int ccc_transient_page_prep(const struct lu_env *env, const struct cl_page_slice *slice, struct cl_io *unused) { - ENTRY; /* transient page should always be sent. */ RETURN(0); } @@ -623,7 +617,6 @@ int ccc_lock_fits_into(const struct lu_env *env, const struct ccc_io *cio = ccc_env_io(env); int result; - ENTRY; /* * Work around DLM peculiarity: it assumes that glimpse * (LDLM_FL_HAS_INTENT) lock is always LCK_PR, and returns reads lock @@ -655,7 +648,6 @@ void ccc_lock_state(const struct lu_env *env, enum cl_lock_state state) { struct cl_lock *lock = slice->cls_lock; - ENTRY; /* * Refresh inode attributes when the lock is moving into CLS_HELD @@ -707,7 +699,6 @@ int ccc_io_one_lock_index(const struct lu_env *env, struct cl_io *io, struct cl_object *obj = io->ci_obj; CLOBINVRNT(env, obj, ccc_object_invariant(obj)); - ENTRY; CDEBUG(D_VFSTRACE, "lock: %d [%lu, %lu]\n", mode, start, end); @@ -986,8 +977,6 @@ int cl_setattr_ost(struct inode *inode, const struct iattr *attr, int result; int refcheck; - ENTRY; - env = cl_env_get(&refcheck); if (IS_ERR(env)) RETURN(PTR_ERR(env)); @@ -1295,7 +1284,6 @@ __u64 cl_fid_build_ino(const struct lu_fid *fid, int api32) __u32 cl_fid_build_gen(const struct lu_fid *fid) { __u32 gen; - ENTRY; if (fid_is_igif(fid)) { gen = lu_igif_gen(fid); diff --git a/drivers/staging/lustre/lustre/lclient/lcommon_misc.c b/drivers/staging/lustre/lustre/lclient/lcommon_misc.c index 8ecbef92753d..d59a7a94e352 100644 --- a/drivers/staging/lustre/lustre/lclient/lcommon_misc.c +++ b/drivers/staging/lustre/lustre/lclient/lcommon_misc.c @@ -57,7 +57,6 @@ int cl_init_ea_size(struct obd_export *md_exp, struct obd_export *dt_exp) int rc, easize, def_easize, cookiesize; struct lov_desc desc; __u16 stripes; - ENTRY; rc = obd_get_info(NULL, dt_exp, sizeof(KEY_LOVDESC), KEY_LOVDESC, &valsize, &desc, NULL); @@ -95,7 +94,6 @@ int cl_ocd_update(struct obd_device *host, __u64 flags; int result; - ENTRY; if (!strcmp(watched->obd_type->typ_name, LUSTRE_OSC_NAME)) { cli = &watched->u.cli; lco = owner; diff --git a/drivers/staging/lustre/lustre/ldlm/interval_tree.c b/drivers/staging/lustre/lustre/ldlm/interval_tree.c index ce90c7e3c488..7de620aa295f 100644 --- a/drivers/staging/lustre/lustre/ldlm/interval_tree.c +++ b/drivers/staging/lustre/lustre/ldlm/interval_tree.c @@ -133,8 +133,6 @@ for (node = interval_last(root); node != NULL; \ static struct interval_node *interval_first(struct interval_node *node) { - ENTRY; - if (!node) RETURN(NULL); while (node->in_left) @@ -144,8 +142,6 @@ static struct interval_node *interval_first(struct interval_node *node) static struct interval_node *interval_last(struct interval_node *node) { - ENTRY; - if (!node) RETURN(NULL); while (node->in_right) @@ -155,8 +151,6 @@ static struct interval_node *interval_last(struct interval_node *node) static struct interval_node *interval_next(struct interval_node *node) { - ENTRY; - if (!node) RETURN(NULL); if (node->in_right) @@ -168,8 +162,6 @@ static struct interval_node *interval_next(struct interval_node *node) static struct interval_node *interval_prev(struct interval_node *node) { - ENTRY; - if (!node) RETURN(NULL); @@ -188,7 +180,6 @@ enum interval_iter interval_iterate(struct interval_node *root, { struct interval_node *node; enum interval_iter rc = INTERVAL_ITER_CONT; - ENTRY; interval_for_each(node, root) { rc = func(node, data); @@ -206,7 +197,6 @@ enum interval_iter interval_iterate_reverse(struct interval_node *root, { struct interval_node *node; enum interval_iter rc = INTERVAL_ITER_CONT; - ENTRY; interval_for_each_reverse(node, root) { rc = func(node, data); @@ -225,7 +215,6 @@ struct interval_node *interval_find(struct interval_node *root, { struct interval_node *walk = root; int rc; - ENTRY; while (walk) { rc = extent_compare(ex, &walk->in_extent); @@ -326,7 +315,6 @@ static void interval_insert_color(struct interval_node *node, struct interval_node **root) { struct interval_node *parent, *gparent; - ENTRY; while ((parent = node->in_parent) && node_is_red(parent)) { gparent = parent->in_parent; @@ -381,7 +369,6 @@ struct interval_node *interval_insert(struct interval_node *node, { struct interval_node **p, *parent = NULL; - ENTRY; LASSERT(!interval_is_intree(node)); p = root; @@ -423,7 +410,6 @@ static void interval_erase_color(struct interval_node *node, struct interval_node **root) { struct interval_node *tmp; - ENTRY; while (node_is_black_or_0(node) && node != *root) { if (parent->in_left == node) { @@ -501,7 +487,6 @@ static void update_maxhigh(struct interval_node *node, __u64 old_maxhigh) { __u64 left_max, right_max; - ENTRY; while (node) { left_max = node->in_left ? node->in_left->in_max_high : 0; @@ -521,7 +506,6 @@ void interval_erase(struct interval_node *node, { struct interval_node *child, *parent; int color; - ENTRY; LASSERT(interval_is_intree(node)); node->in_intree = 0; diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_extent.c b/drivers/staging/lustre/lustre/ldlm/ldlm_extent.c index f7432f78e396..92fa314c669a 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_extent.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_extent.c @@ -72,7 +72,6 @@ __u64 ldlm_extent_shift_kms(struct ldlm_lock *lock, __u64 old_kms) struct list_head *tmp; struct ldlm_lock *lck; __u64 kms = 0; - ENTRY; /* don't let another thread in ldlm_extent_shift_kms race in * just after we finish and take our lock into account in its @@ -103,7 +102,6 @@ struct kmem_cache *ldlm_interval_slab; struct ldlm_interval *ldlm_interval_alloc(struct ldlm_lock *lock) { struct ldlm_interval *node; - ENTRY; LASSERT(lock->l_resource->lr_type == LDLM_EXTENT); OBD_SLAB_ALLOC_PTR_GFP(node, ldlm_interval_slab, __GFP_IO); diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c index 39973cb110a3..b263121e2bf0 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c @@ -142,8 +142,6 @@ static inline void ldlm_flock_blocking_unlink(struct ldlm_lock *req) static inline void ldlm_flock_destroy(struct ldlm_lock *lock, ldlm_mode_t mode, __u64 flags) { - ENTRY; - LDLM_DEBUG(lock, "ldlm_flock_destroy(mode: %d, flags: 0x%llx)", mode, flags); @@ -254,7 +252,6 @@ ldlm_process_flock_lock(struct ldlm_lock *req, __u64 *flags, int first_enq, int splitted = 0; const struct ldlm_callback_suite null_cbs = { NULL }; int rc; - ENTRY; CDEBUG(D_DLMTRACE, "flags %#llx owner "LPU64" pid %u mode %u start " LPU64" end "LPU64"\n", *flags, @@ -546,7 +543,6 @@ static void ldlm_flock_interrupted_wait(void *data) { struct ldlm_lock *lock; - ENTRY; lock = ((struct ldlm_flock_wait_data *)data)->fwd_lock; @@ -581,7 +577,6 @@ ldlm_flock_completion_ast(struct ldlm_lock *lock, __u64 flags, void *data) struct l_wait_info lwi; ldlm_error_t err; int rc = 0; - ENTRY; CDEBUG(D_DLMTRACE, "flags: 0x%llx data: %p getlk: %p\n", flags, data, getlk); @@ -705,8 +700,6 @@ EXPORT_SYMBOL(ldlm_flock_completion_ast); int ldlm_flock_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc, void *data, int flag) { - ENTRY; - LASSERT(lock); LASSERT(flag == LDLM_CB_CANCELING); @@ -843,7 +836,6 @@ EXPORT_SYMBOL(ldlm_init_flock_export); void ldlm_destroy_flock_export(struct obd_export *exp) { - ENTRY; if (exp->exp_flock_hash) { cfs_hash_putref(exp->exp_flock_hash); exp->exp_flock_hash = NULL; diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c index 950f90acec04..d77156a98ad8 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c @@ -60,7 +60,6 @@ static int import_set_conn(struct obd_import *imp, struct obd_uuid *uuid, struct ptlrpc_connection *ptlrpc_conn; struct obd_import_conn *imp_conn = NULL, *item; int rc = 0; - ENTRY; if (!create && !priority) { CDEBUG(D_HA, "Nothing to do\n"); @@ -141,7 +140,6 @@ int client_import_del_conn(struct obd_import *imp, struct obd_uuid *uuid) struct obd_import_conn *imp_conn; struct obd_export *dlmexp; int rc = -ENOENT; - ENTRY; spin_lock(&imp->imp_lock); if (list_empty(&imp->imp_conn_list)) { @@ -200,7 +198,6 @@ int client_import_find_conn(struct obd_import *imp, lnet_nid_t peer, { struct obd_import_conn *conn; int rc = -ENOENT; - ENTRY; spin_lock(&imp->imp_lock); list_for_each_entry(conn, &imp->imp_conn_list, oic_item) { @@ -267,7 +264,6 @@ int client_obd_setup(struct obd_device *obddev, struct lustre_cfg *lcfg) ldlm_ns_type_t ns_type = LDLM_NS_TYPE_UNKNOWN; int rc; char *cli_name = lustre_cfg_buf(lcfg, 0); - ENTRY; /* In a more perfect world, we would hang a ptlrpc_client off of * obd_type and just use the values from there. */ @@ -466,8 +462,6 @@ EXPORT_SYMBOL(client_obd_setup); int client_obd_cleanup(struct obd_device *obddev) { - ENTRY; - ldlm_namespace_free_post(obddev->obd_namespace); obddev->obd_namespace = NULL; @@ -489,7 +483,6 @@ int client_connect_import(const struct lu_env *env, struct obd_connect_data *ocd; struct lustre_handle conn = { 0 }; int rc; - ENTRY; *exp = NULL; down_write(&cli->cl_sem); @@ -553,7 +546,6 @@ int client_disconnect_export(struct obd_export *exp) struct client_obd *cli; struct obd_import *imp; int rc = 0, err; - ENTRY; if (!obd) { CERROR("invalid export for disconnect: exp %p cookie "LPX64"\n", @@ -627,7 +619,6 @@ EXPORT_SYMBOL(client_disconnect_export); int target_pack_pool_reply(struct ptlrpc_request *req) { struct obd_device *obd; - ENTRY; /* Check that we still have all structures alive as this may * be some late RPC at shutdown time. */ @@ -674,7 +665,6 @@ void target_send_reply(struct ptlrpc_request *req, int rc, int fail_id) int netrc; struct ptlrpc_reply_state *rs; struct obd_export *exp; - ENTRY; if (req->rq_no_reply) { EXIT; diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c index a9174209aa8f..6b214d2ca562 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c @@ -188,8 +188,6 @@ EXPORT_SYMBOL(ldlm_lock_get); */ void ldlm_lock_put(struct ldlm_lock *lock) { - ENTRY; - LASSERT(lock->l_resource != LP_POISON); LASSERT(atomic_read(&lock->l_refc) > 0); if (atomic_dec_and_test(&lock->l_refc)) { @@ -253,7 +251,6 @@ int ldlm_lock_remove_from_lru(struct ldlm_lock *lock) struct ldlm_namespace *ns = ldlm_lock_to_ns(lock); int rc; - ENTRY; if (lock->l_flags & LDLM_FL_NS_SRV) { LASSERT(list_empty(&lock->l_lru)); RETURN(0); @@ -289,7 +286,6 @@ void ldlm_lock_add_to_lru(struct ldlm_lock *lock) { struct ldlm_namespace *ns = ldlm_lock_to_ns(lock); - ENTRY; spin_lock(&ns->ns_lock); ldlm_lock_add_to_lru_nolock(lock); spin_unlock(&ns->ns_lock); @@ -304,7 +300,6 @@ void ldlm_lock_touch_in_lru(struct ldlm_lock *lock) { struct ldlm_namespace *ns = ldlm_lock_to_ns(lock); - ENTRY; if (lock->l_flags & LDLM_FL_NS_SRV) { LASSERT(list_empty(&lock->l_lru)); EXIT; @@ -341,8 +336,6 @@ void ldlm_lock_touch_in_lru(struct ldlm_lock *lock) */ int ldlm_lock_destroy_internal(struct ldlm_lock *lock) { - ENTRY; - if (lock->l_readers || lock->l_writers) { LDLM_ERROR(lock, "lock still has references"); LBUG(); @@ -393,7 +386,7 @@ int ldlm_lock_destroy_internal(struct ldlm_lock *lock) void ldlm_lock_destroy(struct ldlm_lock *lock) { int first; - ENTRY; + lock_res_and_lock(lock); first = ldlm_lock_destroy_internal(lock); unlock_res_and_lock(lock); @@ -412,7 +405,7 @@ void ldlm_lock_destroy(struct ldlm_lock *lock) void ldlm_lock_destroy_nolock(struct ldlm_lock *lock) { int first; - ENTRY; + first = ldlm_lock_destroy_internal(lock); /* drop reference from hashtable only for first destroy */ if (first) { @@ -450,7 +443,6 @@ struct portals_handle_ops lock_handle_ops = { static struct ldlm_lock *ldlm_lock_new(struct ldlm_resource *resource) { struct ldlm_lock *lock; - ENTRY; if (resource == NULL) LBUG(); @@ -507,7 +499,6 @@ int ldlm_lock_change_resource(struct ldlm_namespace *ns, struct ldlm_lock *lock, struct ldlm_resource *oldres = lock->l_resource; struct ldlm_resource *newres; int type; - ENTRY; LASSERT(ns_is_client(ns)); @@ -586,7 +577,6 @@ struct ldlm_lock *__ldlm_handle2lock(const struct lustre_handle *handle, __u64 flags) { struct ldlm_lock *lock; - ENTRY; LASSERT(handle); @@ -728,7 +718,6 @@ void ldlm_add_cp_work_item(struct ldlm_lock *lock, struct list_head *work_list) void ldlm_add_ast_work_item(struct ldlm_lock *lock, struct ldlm_lock *new, struct list_head *work_list) { - ENTRY; check_res_locked(lock->l_resource); if (new) ldlm_add_bl_work_item(lock, new, work_list); @@ -853,7 +842,6 @@ void ldlm_lock_decref_internal_nolock(struct ldlm_lock *lock, __u32 mode) void ldlm_lock_decref_internal(struct ldlm_lock *lock, __u32 mode) { struct ldlm_namespace *ns; - ENTRY; lock_res_and_lock(lock); @@ -940,7 +928,6 @@ EXPORT_SYMBOL(ldlm_lock_decref); void ldlm_lock_decref_and_cancel(struct lustre_handle *lockh, __u32 mode) { struct ldlm_lock *lock = __ldlm_handle2lock(lockh, 0); - ENTRY; LASSERT(lock != NULL); @@ -979,7 +966,6 @@ static void search_granted_lock(struct list_head *queue, { struct list_head *tmp; struct ldlm_lock *lock, *mode_end, *policy_end; - ENTRY; list_for_each(tmp, queue) { lock = list_entry(tmp, struct ldlm_lock, l_res_link); @@ -1062,7 +1048,6 @@ static void ldlm_granted_list_add_lock(struct ldlm_lock *lock, struct sl_insert_point *prev) { struct ldlm_resource *res = lock->l_resource; - ENTRY; check_res_locked(res); @@ -1099,7 +1084,6 @@ static void ldlm_granted_list_add_lock(struct ldlm_lock *lock, static void ldlm_grant_lock_with_skiplist(struct ldlm_lock *lock) { struct sl_insert_point prev; - ENTRY; LASSERT(lock->l_req_mode == lock->l_granted_mode); @@ -1122,7 +1106,6 @@ static void ldlm_grant_lock_with_skiplist(struct ldlm_lock *lock) void ldlm_grant_lock(struct ldlm_lock *lock, struct list_head *work_list) { struct ldlm_resource *res = lock->l_resource; - ENTRY; check_res_locked(res); @@ -1304,7 +1287,6 @@ ldlm_mode_t ldlm_lock_match(struct ldlm_namespace *ns, __u64 flags, struct ldlm_resource *res; struct ldlm_lock *lock, *old_lock = NULL; int rc = 0; - ENTRY; if (ns == NULL) { old_lock = ldlm_handle2lock(lockh); @@ -1425,7 +1407,6 @@ ldlm_mode_t ldlm_revalidate_lock_handle(struct lustre_handle *lockh, { struct ldlm_lock *lock; ldlm_mode_t mode = 0; - ENTRY; lock = ldlm_handle2lock(lockh); if (lock != NULL) { @@ -1459,7 +1440,6 @@ int ldlm_fill_lvb(struct ldlm_lock *lock, struct req_capsule *pill, enum req_location loc, void *data, int size) { void *lvb; - ENTRY; LASSERT(data != NULL); LASSERT(size >= 0); @@ -1567,7 +1547,6 @@ struct ldlm_lock *ldlm_lock_create(struct ldlm_namespace *ns, { struct ldlm_lock *lock; struct ldlm_resource *res; - ENTRY; res = ldlm_resource_get(ns, NULL, res_id, type, 1); if (res == NULL) @@ -1634,7 +1613,6 @@ ldlm_error_t ldlm_lock_enqueue(struct ldlm_namespace *ns, int local = ns_is_client(ldlm_res_to_ns(res)); ldlm_error_t rc = ELDLM_OK; struct ldlm_interval *node = NULL; - ENTRY; lock->l_last_activity = cfs_time_current_sec(); /* policies are not executed on the client or during replay */ @@ -1736,7 +1714,6 @@ ldlm_work_bl_ast_lock(struct ptlrpc_request_set *rqset, void *opaq) struct ldlm_lock_desc d; int rc; struct ldlm_lock *lock; - ENTRY; if (list_empty(arg->list)) RETURN(-ENOENT); @@ -1773,7 +1750,6 @@ ldlm_work_cp_ast_lock(struct ptlrpc_request_set *rqset, void *opaq) int rc = 0; struct ldlm_lock *lock; ldlm_completion_callback completion_callback; - ENTRY; if (list_empty(arg->list)) RETURN(-ENOENT); @@ -1818,7 +1794,6 @@ ldlm_work_revoke_ast_lock(struct ptlrpc_request_set *rqset, void *opaq) struct ldlm_lock_desc desc; int rc; struct ldlm_lock *lock; - ENTRY; if (list_empty(arg->list)) RETURN(-ENOENT); @@ -1846,7 +1821,6 @@ int ldlm_work_gl_ast_lock(struct ptlrpc_request_set *rqset, void *opaq) struct ldlm_glimpse_work *gl_work; struct ldlm_lock *lock; int rc = 0; - ENTRY; if (list_empty(arg->list)) RETURN(-ENOENT); @@ -1958,8 +1932,6 @@ static int ldlm_reprocess_res(cfs_hash_t *hs, cfs_hash_bd_t *bd, */ void ldlm_reprocess_all_ns(struct ldlm_namespace *ns) { - ENTRY; - if (ns != NULL) { cfs_hash_for_each_nolock(ns->ns_rs_hash, ldlm_reprocess_res, NULL); @@ -1980,7 +1952,6 @@ void ldlm_reprocess_all(struct ldlm_resource *res) { LIST_HEAD(rpc_list); - ENTRY; if (!ns_is_client(ldlm_res_to_ns(res))) { CERROR("This is client-side-only module, cannot handle " "LDLM_NAMESPACE_SERVER resource type lock.\n"); @@ -2030,7 +2001,6 @@ void ldlm_lock_cancel(struct ldlm_lock *lock) { struct ldlm_resource *res; struct ldlm_namespace *ns; - ENTRY; lock_res_and_lock(lock); @@ -2077,7 +2047,6 @@ int ldlm_lock_set_data(struct lustre_handle *lockh, void *data) { struct ldlm_lock *lock = ldlm_handle2lock(lockh); int rc = -EINVAL; - ENTRY; if (lock) { if (lock->l_ast_data == NULL) @@ -2158,8 +2127,6 @@ void ldlm_cancel_locks_for_export(struct obd_export *exp) */ void ldlm_lock_downgrade(struct ldlm_lock *lock, int new_mode) { - ENTRY; - LASSERT(lock->l_granted_mode & (LCK_PW | LCK_EX)); LASSERT(new_mode == LCK_COS); @@ -2195,7 +2162,6 @@ struct ldlm_resource *ldlm_lock_convert(struct ldlm_lock *lock, int new_mode, struct ldlm_namespace *ns; int granted = 0; struct ldlm_interval *node; - ENTRY; /* Just return if mode is unchanged. */ if (new_mode == lock->l_granted_mode) { diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c index d18936a059d8..adab8b81c852 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c @@ -146,7 +146,6 @@ void ldlm_handle_bl_callback(struct ldlm_namespace *ns, struct ldlm_lock_desc *ld, struct ldlm_lock *lock) { int do_ast; - ENTRY; LDLM_DEBUG(lock, "client blocking AST callback handler"); @@ -188,7 +187,6 @@ static void ldlm_handle_cp_callback(struct ptlrpc_request *req, int lvb_len; LIST_HEAD(ast_list); int rc = 0; - ENTRY; LDLM_DEBUG(lock, "client completion callback handler START"); @@ -332,7 +330,6 @@ static void ldlm_handle_gl_callback(struct ptlrpc_request *req, struct ldlm_lock *lock) { int rc = -ENOSYS; - ENTRY; LDLM_DEBUG(lock, "client glimpse AST callback handler"); @@ -382,7 +379,6 @@ static int __ldlm_bl_to_thread(struct ldlm_bl_work_item *blwi, ldlm_cancel_flags_t cancel_flags) { struct ldlm_bl_pool *blp = ldlm_state->ldlm_bl_pool; - ENTRY; spin_lock(&blp->blp_lock); if (blwi->blwi_lock && @@ -446,8 +442,6 @@ static int ldlm_bl_to_thread(struct ldlm_namespace *ns, struct list_head *cancels, int count, ldlm_cancel_flags_t cancel_flags) { - ENTRY; - if (cancels && count == 0) RETURN(0); @@ -494,7 +488,6 @@ static int ldlm_handle_setinfo(struct ptlrpc_request *req) void *val; int keylen, vallen; int rc = -ENOSYS; - ENTRY; DEBUG_REQ(D_HSM, req, "%s: handle setinfo\n", obd->obd_name); @@ -568,7 +561,6 @@ static int ldlm_callback_handler(struct ptlrpc_request *req) struct ldlm_request *dlm_req; struct ldlm_lock *lock; int rc; - ENTRY; /* Requests arrive in sender's byte order. The ptlrpc service * handler has already checked and, if necessary, byte-swapped the @@ -834,7 +826,6 @@ static int ldlm_bl_thread_start(struct ldlm_bl_pool *blp) static int ldlm_bl_thread_main(void *arg) { struct ldlm_bl_pool *blp; - ENTRY; { struct ldlm_bl_thread_data *bltd = arg; @@ -916,7 +907,7 @@ static int ldlm_cleanup(void); int ldlm_get_ref(void) { int rc = 0; - ENTRY; + mutex_lock(&ldlm_ref_mutex); if (++ldlm_refcount == 1) { rc = ldlm_setup(); @@ -931,7 +922,6 @@ EXPORT_SYMBOL(ldlm_get_ref); void ldlm_put_ref(void) { - ENTRY; mutex_lock(&ldlm_ref_mutex); if (ldlm_refcount == 1) { int rc = ldlm_cleanup(); @@ -1018,8 +1008,6 @@ static cfs_hash_ops_t ldlm_export_lock_ops = { int ldlm_init_export(struct obd_export *exp) { - ENTRY; - exp->exp_lock_hash = cfs_hash_create(obd_uuid2str(&exp->exp_client_uuid), HASH_EXP_LOCK_CUR_BITS, @@ -1039,7 +1027,6 @@ EXPORT_SYMBOL(ldlm_init_export); void ldlm_destroy_export(struct obd_export *exp) { - ENTRY; cfs_hash_putref(exp->exp_lock_hash); exp->exp_lock_hash = NULL; @@ -1054,7 +1041,6 @@ static int ldlm_setup(void) struct ldlm_bl_pool *blp = NULL; int rc = 0; int i; - ENTRY; if (ldlm_state != NULL) RETURN(-EALREADY); @@ -1150,8 +1136,6 @@ static int ldlm_setup(void) static int ldlm_cleanup(void) { - ENTRY; - if (!list_empty(ldlm_namespace_list(LDLM_NAMESPACE_SERVER)) || !list_empty(ldlm_namespace_list(LDLM_NAMESPACE_CLIENT))) { CERROR("ldlm still has namespaces; clean these up first.\n"); diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c b/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c index 101af4be9ffb..5a1d11e0159a 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c @@ -335,7 +335,6 @@ static void ldlm_srv_pool_push_slv(struct ldlm_pool *pl) static int ldlm_srv_pool_recalc(struct ldlm_pool *pl) { time_t recalc_interval_sec; - ENTRY; recalc_interval_sec = cfs_time_current_sec() - pl->pl_recalc_time; if (recalc_interval_sec < pl->pl_recalc_period) @@ -473,7 +472,6 @@ static void ldlm_cli_pool_pop_slv(struct ldlm_pool *pl) static int ldlm_cli_pool_recalc(struct ldlm_pool *pl) { time_t recalc_interval_sec; - ENTRY; recalc_interval_sec = cfs_time_current_sec() - pl->pl_recalc_time; if (recalc_interval_sec < pl->pl_recalc_period) @@ -733,7 +731,6 @@ static int ldlm_pool_proc_init(struct ldlm_pool *pl) struct lprocfs_vars pool_vars[2]; char *var_name = NULL; int rc = 0; - ENTRY; OBD_ALLOC(var_name, MAX_STRING_SIZE + 1); if (!var_name) @@ -835,7 +832,6 @@ int ldlm_pool_init(struct ldlm_pool *pl, struct ldlm_namespace *ns, int idx, ldlm_side_t client) { int rc; - ENTRY; spin_lock_init(&pl->pl_lock); atomic_set(&pl->pl_granted, 0); @@ -873,7 +869,6 @@ EXPORT_SYMBOL(ldlm_pool_init); void ldlm_pool_fini(struct ldlm_pool *pl) { - ENTRY; ldlm_pool_proc_fini(pl); /* @@ -1302,7 +1297,6 @@ static int ldlm_pools_thread_main(void *arg) { struct ptlrpc_thread *thread = (struct ptlrpc_thread *)arg; int s_time, c_time; - ENTRY; thread_set_flags(thread, SVC_RUNNING); wake_up(&thread->t_ctl_waitq); @@ -1349,7 +1343,6 @@ static int ldlm_pools_thread_start(void) { struct l_wait_info lwi = { 0 }; task_t *task; - ENTRY; if (ldlm_pools_thread != NULL) RETURN(-EALREADY); @@ -1376,8 +1369,6 @@ static int ldlm_pools_thread_start(void) static void ldlm_pools_thread_stop(void) { - ENTRY; - if (ldlm_pools_thread == NULL) { EXIT; return; @@ -1400,7 +1391,6 @@ static void ldlm_pools_thread_stop(void) int ldlm_pools_init(void) { int rc; - ENTRY; rc = ldlm_pools_thread_start(); if (rc == 0) { diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c index 6f21a1204a64..0b6dc6a288a5 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c @@ -94,7 +94,6 @@ int ldlm_expired_completion_wait(void *data) struct obd_import *imp; struct obd_device *obd; - ENTRY; if (lock->l_conn_export == NULL) { static cfs_time_t next_dump = 0, last_dump = 0; @@ -184,8 +183,6 @@ static int ldlm_completion_tail(struct ldlm_lock *lock) */ int ldlm_completion_ast_async(struct ldlm_lock *lock, __u64 flags, void *data) { - ENTRY; - if (flags == LDLM_FL_WAIT_NOREPROC) { LDLM_DEBUG(lock, "client-side enqueue waiting on pending lock"); RETURN(0); @@ -234,7 +231,6 @@ int ldlm_completion_ast(struct ldlm_lock *lock, __u64 flags, void *data) struct l_wait_info lwi; __u32 timeout; int rc = 0; - ENTRY; if (flags == LDLM_FL_WAIT_NOREPROC) { LDLM_DEBUG(lock, "client-side enqueue waiting on pending lock"); @@ -316,7 +312,6 @@ EXPORT_SYMBOL(ldlm_completion_ast); int ldlm_blocking_ast_nocheck(struct ldlm_lock *lock) { int do_ast; - ENTRY; lock->l_flags |= LDLM_FL_CBPENDING; do_ast = (!lock->l_readers && !lock->l_writers); @@ -355,8 +350,6 @@ EXPORT_SYMBOL(ldlm_blocking_ast_nocheck); int ldlm_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc, void *data, int flag) { - ENTRY; - if (flag == LDLM_CB_CANCELING) { /* Don't need to do anything here. */ RETURN(0); @@ -424,7 +417,6 @@ int ldlm_cli_enqueue_local(struct ldlm_namespace *ns, .lcs_blocking = blocking, .lcs_glimpse = glimpse, }; - ENTRY; LASSERT(!(*flags & LDLM_FL_REPLAY)); if (unlikely(ns_is_client(ns))) { @@ -530,7 +522,6 @@ int ldlm_cli_enqueue_fini(struct obd_export *exp, struct ptlrpc_request *req, struct ldlm_reply *reply; int cleanup_phase = 1; int size = 0; - ENTRY; lock = ldlm_handle2lock(lockh); /* ldlm_cli_enqueue is holding a reference on this lock. */ @@ -763,7 +754,6 @@ int ldlm_prep_elc_req(struct obd_export *exp, struct ptlrpc_request *req, int flags, avail, to_free, pack = 0; LIST_HEAD(head); int rc; - ENTRY; if (cancels == NULL) cancels = &head; @@ -830,7 +820,6 @@ struct ptlrpc_request *ldlm_enqueue_pack(struct obd_export *exp, int lvb_len) { struct ptlrpc_request *req; int rc; - ENTRY; req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_LDLM_ENQUEUE); if (req == NULL) @@ -872,7 +861,6 @@ int ldlm_cli_enqueue(struct obd_export *exp, struct ptlrpc_request **reqp, int req_passed_in = 1; int rc, err; struct ptlrpc_request *req; - ENTRY; LASSERT(exp != NULL); @@ -1010,7 +998,7 @@ static int ldlm_cli_convert_local(struct ldlm_lock *lock, int new_mode, { struct ldlm_resource *res; int rc; - ENTRY; + if (ns_is_client(ldlm_lock_to_ns(lock))) { CERROR("Trying to cancel local lock\n"); LBUG(); @@ -1041,7 +1029,6 @@ int ldlm_cli_convert(struct lustre_handle *lockh, int new_mode, __u32 *flags) struct ldlm_resource *res; struct ptlrpc_request *req; int rc; - ENTRY; lock = ldlm_handle2lock(lockh); if (!lock) { @@ -1114,7 +1101,6 @@ EXPORT_SYMBOL(ldlm_cli_convert); static __u64 ldlm_cli_cancel_local(struct ldlm_lock *lock) { __u64 rc = LDLM_FL_LOCAL_ONLY; - ENTRY; if (lock->l_conn_export) { bool local_only; @@ -1158,7 +1144,6 @@ static void ldlm_cancel_pack(struct ptlrpc_request *req, struct ldlm_request *dlm; struct ldlm_lock *lock; int max, packed = 0; - ENTRY; dlm = req_capsule_client_get(&req->rq_pill, &RMF_DLM_REQ); LASSERT(dlm != NULL); @@ -1196,7 +1181,6 @@ int ldlm_cli_cancel_req(struct obd_export *exp, struct list_head *cancels, struct obd_import *imp; int free, sent = 0; int rc = 0; - ENTRY; LASSERT(exp != NULL); LASSERT(count > 0); @@ -1289,7 +1273,7 @@ int ldlm_cli_update_pool(struct ptlrpc_request *req) struct obd_device *obd; __u64 new_slv; __u32 new_limit; - ENTRY; + if (unlikely(!req->rq_import || !req->rq_import->imp_obd || !imp_connect_lru_resize(req->rq_import))) { @@ -1345,7 +1329,6 @@ int ldlm_cli_cancel(struct lustre_handle *lockh, struct ldlm_namespace *ns; struct ldlm_lock *lock; LIST_HEAD(cancels); - ENTRY; /* concurrent cancels on the same handle can happen */ lock = ldlm_handle2lock_long(lockh, LDLM_FL_CANCELING); @@ -1630,7 +1613,6 @@ static int ldlm_prepare_lru_list(struct ldlm_namespace *ns, struct list_head *ca ldlm_cancel_lru_policy_t pf; struct ldlm_lock *lock, *next; int added = 0, unused, remained; - ENTRY; spin_lock(&ns->ns_lock); unused = ns->ns_nr_unused; @@ -1781,7 +1763,6 @@ int ldlm_cancel_lru(struct ldlm_namespace *ns, int nr, { LIST_HEAD(cancels); int count, rc; - ENTRY; /* Just prepare the list of locks, do not actually cancel them yet. * Locks are cancelled later in a separate thread. */ @@ -1806,7 +1787,6 @@ int ldlm_cancel_resource_local(struct ldlm_resource *res, { struct ldlm_lock *lock; int count = 0; - ENTRY; lock_res(res); list_for_each_entry(lock, &res->lr_granted, l_res_link) { @@ -1866,7 +1846,6 @@ int ldlm_cli_cancel_list(struct list_head *cancels, int count, { struct ldlm_lock *lock; int res = 0; - ENTRY; if (list_empty(cancels) || count == 0) RETURN(0); @@ -1925,7 +1904,6 @@ int ldlm_cli_cancel_unused_resource(struct ldlm_namespace *ns, LIST_HEAD(cancels); int count; int rc; - ENTRY; res = ldlm_resource_get(ns, NULL, res_id, 0, 0); if (res == NULL) { @@ -1985,8 +1963,6 @@ int ldlm_cli_cancel_unused(struct ldlm_namespace *ns, .lc_opaque = opaque, }; - ENTRY; - if (ns == NULL) RETURN(ELDLM_OK); @@ -2011,8 +1987,6 @@ int ldlm_resource_foreach(struct ldlm_resource *res, ldlm_iterator_t iter, struct ldlm_lock *lock; int rc = LDLM_ITER_CONTINUE; - ENTRY; - if (!res) RETURN(LDLM_ITER_CONTINUE); @@ -2090,7 +2064,6 @@ int ldlm_resource_iterate(struct ldlm_namespace *ns, { struct ldlm_resource *res; int rc; - ENTRY; if (ns == NULL) { CERROR("must pass in namespace\n"); @@ -2139,7 +2112,6 @@ static int replay_lock_interpret(const struct lu_env *env, struct ldlm_reply *reply; struct obd_export *exp; - ENTRY; atomic_dec(&req->rq_import->imp_replay_inflight); if (rc != ELDLM_OK) GOTO(out, rc); @@ -2189,8 +2161,6 @@ static int replay_one_lock(struct obd_import *imp, struct ldlm_lock *lock) struct ldlm_async_args *aa; struct ldlm_request *body; int flags; - ENTRY; - /* Bug 11974: Do not replay a lock which is actively being canceled */ if (lock->l_flags & LDLM_FL_CANCELING) { @@ -2302,8 +2272,6 @@ int ldlm_replay_locks(struct obd_import *imp) struct ldlm_lock *lock, *next; int rc = 0; - ENTRY; - LASSERT(atomic_read(&imp->imp_replay_inflight) == 0); /* don't replay locks if import failed recovery */ diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c index 616cb17efc30..8b2b3fa16112 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c @@ -95,7 +95,6 @@ int ldlm_proc_setup(void) { "cancel_unused_locks_before_replay", &ldlm_rw_uint_fops, &ldlm_cancel_unused_locks_before_replay }, { NULL }}; - ENTRY; LASSERT(ldlm_ns_proc_dir == NULL); ldlm_type_proc_dir = lprocfs_register(OBD_LDLM_DEVICENAME, @@ -568,7 +567,6 @@ struct ldlm_namespace *ldlm_namespace_new(struct obd_device *obd, char *name, cfs_hash_bd_t bd; int idx; int rc; - ENTRY; LASSERT(obd != NULL); @@ -808,8 +806,6 @@ EXPORT_SYMBOL(ldlm_namespace_cleanup); */ static int __ldlm_namespace_free(struct ldlm_namespace *ns, int force) { - ENTRY; - /* At shutdown time, don't call the cancellation callback */ ldlm_namespace_cleanup(ns, force ? LDLM_FL_LOCAL_ONLY : 0); @@ -864,7 +860,7 @@ void ldlm_namespace_free_prior(struct ldlm_namespace *ns, int force) { int rc; - ENTRY; + if (!ns) { EXIT; return; @@ -901,7 +897,6 @@ void ldlm_namespace_free_prior(struct ldlm_namespace *ns, */ void ldlm_namespace_free_post(struct ldlm_namespace *ns) { - ENTRY; if (!ns) { EXIT; return; diff --git a/drivers/staging/lustre/lustre/libcfs/debug.c b/drivers/staging/lustre/lustre/libcfs/debug.c index 5a87b0832074..20682d8e7f2a 100644 --- a/drivers/staging/lustre/lustre/libcfs/debug.c +++ b/drivers/staging/lustre/lustre/libcfs/debug.c @@ -362,7 +362,6 @@ void libcfs_debug_dumplog(void) { wait_queue_t wait; task_t *dumper; - ENTRY; /* we're being careful to ensure that the kernel thread is * able to set our state to running as it exits before we diff --git a/drivers/staging/lustre/lustre/libcfs/hash.c b/drivers/staging/lustre/lustre/libcfs/hash.c index 98c76dfac3dd..bc7497a9b064 100644 --- a/drivers/staging/lustre/lustre/libcfs/hash.c +++ b/drivers/staging/lustre/lustre/libcfs/hash.c @@ -1026,8 +1026,6 @@ cfs_hash_create(char *name, unsigned cur_bits, unsigned max_bits, cfs_hash_t *hs; int len; - ENTRY; - CLASSERT(CFS_HASH_THETA_BITS < 15); LASSERT(name != NULL); @@ -1101,7 +1099,6 @@ cfs_hash_destroy(cfs_hash_t *hs) struct hlist_node *pos; cfs_hash_bd_t bd; int i; - ENTRY; LASSERT(hs != NULL); LASSERT(!cfs_hash_is_exiting(hs) && @@ -1449,7 +1446,6 @@ cfs_hash_for_each_tight(cfs_hash_t *hs, cfs_hash_for_each_cb_t func, int excl = !!remove_safe; int loop = 0; int i; - ENTRY; cfs_hash_for_each_enter(hs); @@ -1594,7 +1590,6 @@ cfs_hash_for_each_relax(cfs_hash_t *hs, cfs_hash_for_each_cb_t func, void *data) int stop_on_change; int rc; int i; - ENTRY; stop_on_change = cfs_hash_with_rehash_key(hs) || !cfs_hash_with_no_itemref(hs) || @@ -1649,8 +1644,6 @@ int cfs_hash_for_each_nolock(cfs_hash_t *hs, cfs_hash_for_each_cb_t func, void *data) { - ENTRY; - if (cfs_hash_with_no_lock(hs) || cfs_hash_with_rehash_key(hs) || !cfs_hash_with_no_itemref(hs)) @@ -1685,7 +1678,6 @@ cfs_hash_for_each_empty(cfs_hash_t *hs, cfs_hash_for_each_cb_t func, void *data) { unsigned i = 0; - ENTRY; if (cfs_hash_with_no_lock(hs)) return -EOPNOTSUPP; diff --git a/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c b/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c index d6d3b2e0f307..39cf56a09247 100644 --- a/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c +++ b/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c @@ -246,7 +246,6 @@ EXPORT_SYMBOL(libcfs_kkuc_group_add); int libcfs_kkuc_group_rem(int uid, int group) { struct kkuc_reg *reg, *next; - ENTRY; if (kkuc_groups[group].next == NULL) RETURN(0); @@ -284,7 +283,6 @@ int libcfs_kkuc_group_put(int group, void *payload) struct kkuc_reg *reg; int rc = 0; int one_success = 0; - ENTRY; down_read(&kg_sem); list_for_each_entry(reg, &kkuc_groups[group], kr_chain) { @@ -320,7 +318,6 @@ int libcfs_kkuc_group_foreach(int group, libcfs_kkuc_cb_t cb_func, { struct kkuc_reg *reg; int rc = 0; - ENTRY; if (group > KUC_GRP_MAX) { CDEBUG(D_WARNING, "Kernelcomm: bad group %d\n", group); diff --git a/drivers/staging/lustre/lustre/libcfs/libcfs_string.c b/drivers/staging/lustre/lustre/libcfs/libcfs_string.c index c7a19711bb6a..922debd0a412 100644 --- a/drivers/staging/lustre/lustre/libcfs/libcfs_string.c +++ b/drivers/staging/lustre/lustre/libcfs/libcfs_string.c @@ -69,7 +69,6 @@ int cfs_str2mask(const char *str, const char *(*bit2str)(int bit), const char *debugstr; char op = 0; int newmask = minmask, i, len, found = 0; - ENTRY; /* must be a list of tokens separated by whitespace * and optionally an operator ('+' or '-'). If an operator diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c index 706dfb39fc28..833c889348e2 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-curproc.c @@ -212,7 +212,6 @@ int cfs_get_environ(const char *key, char *value, int *val_len) int key_len = strlen(key); unsigned long addr; int rc; - ENTRY; buffer = kmalloc(buf_len, GFP_USER); if (!buffer) diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c index 9b57304e6caa..3e61a0d4574b 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c @@ -78,7 +78,6 @@ void libcfs_run_debug_log_upcall(char *file) "HOME=/", "PATH=/sbin:/bin:/usr/sbin:/usr/bin", NULL}; - ENTRY; argv[0] = lnet_debug_log_upcall; @@ -108,7 +107,6 @@ void libcfs_run_upcall(char **argv) "HOME=/", "PATH=/sbin:/bin:/usr/sbin:/usr/bin", NULL}; - ENTRY; argv[0] = lnet_upcall; argc = 1; @@ -141,7 +139,6 @@ void libcfs_run_lbug_upcall(struct libcfs_debug_msg_data *msgdata) char *argv[6]; char buf[32]; - ENTRY; snprintf (buf, sizeof buf, "%d", msgdata->msg_line); argv[1] = "LBUG"; diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c index 7449f4f18640..004ff71663af 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c @@ -45,7 +45,6 @@ int libcfs_ioctl_getdata(char *buf, char *end, void *arg) struct libcfs_ioctl_hdr *hdr; struct libcfs_ioctl_data *data; int err; - ENTRY; hdr = (struct libcfs_ioctl_hdr *)buf; data = (struct libcfs_ioctl_data *)buf; diff --git a/drivers/staging/lustre/lustre/libcfs/module.c b/drivers/staging/lustre/lustre/libcfs/module.c index 52525bc7ddb0..2a6db77bd062 100644 --- a/drivers/staging/lustre/lustre/libcfs/module.c +++ b/drivers/staging/lustre/lustre/libcfs/module.c @@ -155,7 +155,6 @@ kportal_memhog_alloc (struct libcfs_device_userstate *ldu, int npages, int flags static int libcfs_psdev_open(unsigned long flags, void *args) { struct libcfs_device_userstate *ldu; - ENTRY; try_module_get(THIS_MODULE); @@ -173,7 +172,6 @@ static int libcfs_psdev_open(unsigned long flags, void *args) static int libcfs_psdev_release(unsigned long flags, void *args) { struct libcfs_device_userstate *ldu; - ENTRY; ldu = (struct libcfs_device_userstate *)args; if (ldu != NULL) { @@ -222,7 +220,6 @@ static int libcfs_ioctl_int(struct cfs_psdev_file *pfile,unsigned long cmd, void *arg, struct libcfs_ioctl_data *data) { int err = -EINVAL; - ENTRY; switch (cmd) { case IOC_LIBCFS_CLEAR_DEBUG: @@ -330,7 +327,6 @@ static int libcfs_ioctl(struct cfs_psdev_file *pfile, unsigned long cmd, void *a char *buf; struct libcfs_ioctl_data *data; int err = 0; - ENTRY; LIBCFS_ALLOC_GFP(buf, 1024, GFP_IOFS); if (buf == NULL) diff --git a/drivers/staging/lustre/lustre/libcfs/nidstrings.c b/drivers/staging/lustre/lustre/libcfs/nidstrings.c index ccfd1078a906..0260e69a14dd 100644 --- a/drivers/staging/lustre/lustre/libcfs/nidstrings.c +++ b/drivers/staging/lustre/lustre/libcfs/nidstrings.c @@ -785,7 +785,6 @@ cfs_parse_nidlist(char *str, int len, struct list_head *nidlist) struct cfs_lstr src; struct cfs_lstr res; int rc; - ENTRY; src.ls_str = str; src.ls_len = len; @@ -834,7 +833,6 @@ int cfs_match_nid(lnet_nid_t nid, struct list_head *nidlist) { struct nidrange *nr; struct addrrange *ar; - ENTRY; list_for_each_entry(nr, nidlist, nr_link) { if (nr->nr_netstrfns->nf_type != LNET_NETTYP(LNET_NIDNET(nid))) diff --git a/drivers/staging/lustre/lustre/libcfs/upcall_cache.c b/drivers/staging/lustre/lustre/libcfs/upcall_cache.c index 18c68c3493b8..7663fb568371 100644 --- a/drivers/staging/lustre/lustre/libcfs/upcall_cache.c +++ b/drivers/staging/lustre/lustre/libcfs/upcall_cache.c @@ -152,7 +152,6 @@ struct upcall_cache_entry *upcall_cache_get_entry(struct upcall_cache *cache, struct list_head *head; wait_queue_t wait; int rc, found; - ENTRY; LASSERT(cache); @@ -273,8 +272,6 @@ EXPORT_SYMBOL(upcall_cache_get_entry); void upcall_cache_put_entry(struct upcall_cache *cache, struct upcall_cache_entry *entry) { - ENTRY; - if (!entry) { EXIT; return; @@ -294,7 +291,6 @@ int upcall_cache_downcall(struct upcall_cache *cache, __u32 err, __u64 key, struct upcall_cache_entry *entry = NULL; struct list_head *head; int found = 0, rc = 0; - ENTRY; LASSERT(cache); @@ -364,7 +360,6 @@ static void cache_flush(struct upcall_cache *cache, int force) { struct upcall_cache_entry *entry, *next; int i; - ENTRY; spin_lock(&cache->uc_lock); for (i = 0; i < UC_CACHE_HASH_SIZE; i++) { @@ -399,7 +394,6 @@ void upcall_cache_flush_one(struct upcall_cache *cache, __u64 key, void *args) struct list_head *head; struct upcall_cache_entry *entry; int found = 0; - ENTRY; head = &cache->uc_hashtable[UC_CACHE_HASH_INDEX(key)]; @@ -431,7 +425,6 @@ struct upcall_cache *upcall_cache_init(const char *name, const char *upcall, { struct upcall_cache *cache; int i; - ENTRY; LIBCFS_ALLOC(cache, sizeof(*cache)); if (!cache) diff --git a/drivers/staging/lustre/lustre/llite/dcache.c b/drivers/staging/lustre/lustre/llite/dcache.c index 0d49e1bfb6bb..628fae410bdb 100644 --- a/drivers/staging/lustre/lustre/llite/dcache.c +++ b/drivers/staging/lustre/lustre/llite/dcache.c @@ -59,7 +59,7 @@ static void free_dentry_data(struct rcu_head *head) static void ll_release(struct dentry *de) { struct ll_dentry_data *lld; - ENTRY; + LASSERT(de != NULL); lld = ll_d2d(de); if (lld == NULL) /* NFS copies the de->d_op methods (bug 4655) */ @@ -87,8 +87,6 @@ static void ll_release(struct dentry *de) int ll_dcompare(const struct dentry *parent, const struct dentry *dentry, unsigned int len, const char *str, const struct qstr *name) { - ENTRY; - if (len != name->len) RETURN(1); @@ -127,7 +125,6 @@ static int find_cbdata(struct inode *inode) struct ll_sb_info *sbi = ll_i2sbi(inode); struct lov_stripe_md *lsm; int rc = 0; - ENTRY; LASSERT(inode); rc = md_find_cbdata(sbi->ll_md_exp, ll_inode2fid(inode), @@ -154,7 +151,6 @@ static int find_cbdata(struct inode *inode) */ static int ll_ddelete(const struct dentry *de) { - ENTRY; LASSERT(de); CDEBUG(D_DENTRY, "%s dentry %.*s (%p, parent %p, inode %p) %s%s\n", @@ -184,7 +180,6 @@ static int ll_ddelete(const struct dentry *de) static int ll_set_dd(struct dentry *de) { - ENTRY; LASSERT(de != NULL); CDEBUG(D_DENTRY, "ldd on dentry %.*s (%p) parent %p inode %p refc %d\n", @@ -259,8 +254,6 @@ void ll_intent_drop_lock(struct lookup_intent *it) void ll_intent_release(struct lookup_intent *it) { - ENTRY; - CDEBUG(D_INFO, "intent %p released\n", it); ll_intent_drop_lock(it); /* We are still holding extra reference on a request, need to free it */ @@ -281,7 +274,6 @@ void ll_invalidate_aliases(struct inode *inode) { struct dentry *dentry; struct ll_d_hlist_node *p; - ENTRY; LASSERT(inode != NULL); @@ -315,7 +307,6 @@ int ll_revalidate_it_finish(struct ptlrpc_request *request, struct dentry *de) { int rc = 0; - ENTRY; if (!request) RETURN(0); @@ -370,7 +361,6 @@ int ll_revalidate_it(struct dentry *de, int lookup_flags, struct inode *parent = de->d_parent->d_inode; int rc; - ENTRY; CDEBUG(D_VFSTRACE, "VFS Op:name=%s,intent=%s\n", de->d_name.name, LL_IT2STR(it)); @@ -639,7 +629,6 @@ int ll_revalidate_nd(struct dentry *dentry, unsigned int flags) struct inode *parent = dentry->d_parent->d_inode; int unplug = 0; - ENTRY; CDEBUG(D_VFSTRACE, "VFS Op:name=%s,flags=%u\n", dentry->d_name.name, flags); diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 2ca8c4534bd5..55256812ae20 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -157,7 +157,6 @@ static int ll_dir_filler(void *_hash, struct page *page0) int npages; int i; int rc; - ENTRY; CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p) hash "LPU64"\n", inode->i_ino, inode->i_generation, inode, hash); @@ -489,7 +488,6 @@ int ll_dir_read(struct inode *inode, struct dir_context *ctx) struct ll_dir_chain chain; int done = 0; int rc = 0; - ENTRY; ll_dir_chain_init(&chain); @@ -603,7 +601,6 @@ static int ll_readdir(struct file *filp, struct dir_context *ctx) int hash64 = sbi->ll_flags & LL_SBI_64BIT_HASH; int api32 = ll_need_32bit_api(sbi); int rc; - ENTRY; CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p) pos %lu/%llu " " 32bit_api %d\n", inode->i_ino, inode->i_generation, @@ -664,8 +661,6 @@ int ll_dir_setdirstripe(struct inode *dir, struct lmv_user_md *lump, int mode; int err; - ENTRY; - mode = (0755 & (S_IRWXUGO|S_ISVTX) & ~current->fs->umask) | S_IFDIR; op_data = ll_prep_md_op_data(NULL, dir, NULL, filename, strlen(filename), mode, LUSTRE_OPC_MKDIR, @@ -696,7 +691,6 @@ int ll_dir_setstripe(struct inode *inode, struct lov_user_md *lump, struct lustre_sb_info *lsi = s2lsi(inode->i_sb); struct obd_device *mgc = lsi->lsi_mgc; int lum_size; - ENTRY; if (lump != NULL) { /* @@ -870,7 +864,6 @@ int ll_get_mdt_idx(struct inode *inode) struct ll_sb_info *sbi = ll_i2sbi(inode); struct md_op_data *op_data; int rc, mdtidx; - ENTRY; op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0, LUSTRE_OPC_ANY, NULL); @@ -904,7 +897,6 @@ static int ll_ioc_copy_start(struct super_block *sb, struct hsm_copy *copy) struct ll_sb_info *sbi = ll_s2sbi(sb); struct hsm_progress_kernel hpk; int rc; - ENTRY; /* Forge a hsm_progress based on data from copy. */ hpk.hpk_fid = copy->hc_hai.hai_fid; @@ -977,7 +969,6 @@ static int ll_ioc_copy_end(struct super_block *sb, struct hsm_copy *copy) struct ll_sb_info *sbi = ll_s2sbi(sb); struct hsm_progress_kernel hpk; int rc; - ENTRY; /* If you modify the logic here, also check llapi_hsm_copy_end(). */ /* Take care: copy->hc_hai.hai_action, len, gid and data are not @@ -1082,7 +1073,6 @@ static int quotactl_ioctl(struct ll_sb_info *sbi, struct if_quotactl *qctl) int id = qctl->qc_id; int valid = qctl->qc_valid; int rc = 0; - ENTRY; switch (cmd) { case LUSTRE_Q_INVALIDATE: @@ -1243,7 +1233,6 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg) struct ll_sb_info *sbi = ll_i2sbi(inode); struct obd_ioctl_data *data; int rc = 0; - ENTRY; CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), cmd=%#x\n", inode->i_ino, inode->i_generation, inode, cmd); @@ -1907,7 +1896,6 @@ static loff_t ll_dir_seek(struct file *file, loff_t offset, int origin) struct ll_sb_info *sbi = ll_i2sbi(inode); int api32 = ll_need_32bit_api(sbi); loff_t ret = -EINVAL; - ENTRY; mutex_lock(&inode->i_mutex); switch (origin) { @@ -1953,13 +1941,11 @@ out: int ll_dir_open(struct inode *inode, struct file *file) { - ENTRY; RETURN(ll_file_open(inode, file)); } int ll_dir_release(struct inode *inode, struct file *file) { - ENTRY; RETURN(ll_file_release(inode, file)); } diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 20416fcf2e9c..79f5394ac6b2 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -95,8 +95,6 @@ void ll_pack_inode2opdata(struct inode *inode, struct md_op_data *op_data, static void ll_prepare_close(struct inode *inode, struct md_op_data *op_data, struct obd_client_handle *och) { - ENTRY; - op_data->op_attr.ia_valid = ATTR_MODE | ATTR_ATIME | ATTR_ATIME_SET | ATTR_MTIME | ATTR_MTIME_SET | ATTR_CTIME | ATTR_CTIME_SET; @@ -126,7 +124,6 @@ static int ll_close_inode_openhandle(struct obd_export *md_exp, struct obd_device *obd = class_exp2obd(exp); int epoch_close = 1; int rc; - ENTRY; if (obd == NULL) { /* @@ -204,7 +201,6 @@ int ll_md_real_close(struct inode *inode, int flags) struct obd_client_handle *och; __u64 *och_usecount; int rc = 0; - ENTRY; if (flags & FMODE_WRITE) { och_p = &lli->lli_mds_write_och; @@ -243,7 +239,6 @@ int ll_md_close(struct obd_export *md_exp, struct inode *inode, struct ll_file_data *fd = LUSTRE_FPRIVATE(file); struct ll_inode_info *lli = ll_i2info(inode); int rc = 0; - ENTRY; /* clear group lock, if present */ if (unlikely(fd->fd_flags & LL_FILE_GROUP_LOCKED)) @@ -303,7 +298,6 @@ int ll_file_release(struct inode *inode, struct file *file) struct ll_sb_info *sbi = ll_i2sbi(inode); struct ll_inode_info *lli = ll_i2info(inode); int rc; - ENTRY; CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p)\n", inode->i_ino, inode->i_generation, inode); @@ -364,7 +358,6 @@ static int ll_intent_file_open(struct file *file, void *lmm, struct ptlrpc_request *req; __u32 opc = LUSTRE_OPC_ANY; int rc; - ENTRY; if (!parent) RETURN(-ENOENT); @@ -466,7 +459,6 @@ int ll_local_open(struct file *file, struct lookup_intent *it, { struct inode *inode = file->f_dentry->d_inode; struct ll_inode_info *lli = ll_i2info(inode); - ENTRY; LASSERT(!LUSTRE_FPRIVATE(file)); @@ -516,7 +508,6 @@ int ll_file_open(struct inode *inode, struct file *file) __u64 *och_usecount = NULL; struct ll_file_data *fd; int rc = 0, opendir_set = 0; - ENTRY; CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), flags %o\n", inode->i_ino, inode->i_generation, inode, file->f_flags); @@ -702,8 +693,6 @@ static int ll_lsm_getattr(struct lov_stripe_md *lsm, struct obd_export *exp, struct obd_info oinfo = { { { 0 } } }; int rc; - ENTRY; - LASSERT(lsm != NULL); oinfo.oi_md = lsm; @@ -751,7 +740,6 @@ int ll_inode_getattr(struct inode *inode, struct obdo *obdo, struct obd_capa *capa = ll_mdscapa_get(inode); struct lov_stripe_md *lsm; int rc; - ENTRY; lsm = ccc_inode_lsm_get(inode); rc = ll_lsm_getattr(lsm, ll_i2dtexp(inode), @@ -778,8 +766,6 @@ int ll_merge_lvb(const struct lu_env *env, struct inode *inode) struct ost_lvb lvb; int rc = 0; - ENTRY; - ll_inode_size_lock(inode); /* merge timestamps the most recently obtained from mds with timestamps obtained from osts */ @@ -862,7 +848,6 @@ ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args, struct ll_file_data *fd = LUSTRE_FPRIVATE(file); struct cl_io *io; ssize_t result; - ENTRY; restart: io = ccc_env_thread_io(env); @@ -988,7 +973,6 @@ static ssize_t ll_file_aio_read(struct kiocb *iocb, const struct iovec *iov, size_t count; ssize_t result; int refcheck; - ENTRY; result = ll_file_get_iov_count(iov, &nr_segs, &count); if (result) @@ -1017,7 +1001,6 @@ static ssize_t ll_file_read(struct file *file, char *buf, size_t count, struct kiocb *kiocb; ssize_t result; int refcheck; - ENTRY; env = cl_env_get(&refcheck); if (IS_ERR(env)) @@ -1049,7 +1032,6 @@ static ssize_t ll_file_aio_write(struct kiocb *iocb, const struct iovec *iov, size_t count; ssize_t result; int refcheck; - ENTRY; result = ll_file_get_iov_count(iov, &nr_segs, &count); if (result) @@ -1078,7 +1060,6 @@ static ssize_t ll_file_write(struct file *file, const char *buf, size_t count, struct kiocb *kiocb; ssize_t result; int refcheck; - ENTRY; env = cl_env_get(&refcheck); if (IS_ERR(env)) @@ -1112,7 +1093,6 @@ static ssize_t ll_file_splice_read(struct file *in_file, loff_t *ppos, struct vvp_io_args *args; ssize_t result; int refcheck; - ENTRY; env = cl_env_get(&refcheck); if (IS_ERR(env)) @@ -1136,7 +1116,6 @@ static int ll_lov_recreate(struct inode *inode, struct ost_id *oi, int lsm_size; int rc = 0; struct lov_stripe_md *lsm = NULL, *lsm2; - ENTRY; OBDO_ALLOC(oa); if (oa == NULL) @@ -1177,7 +1156,6 @@ static int ll_lov_recreate_obj(struct inode *inode, unsigned long arg) { struct ll_recreate_obj ucreat; struct ost_id oi; - ENTRY; if (!cfs_capable(CFS_CAP_SYS_ADMIN)) RETURN(-EPERM); @@ -1196,7 +1174,6 @@ static int ll_lov_recreate_fid(struct inode *inode, unsigned long arg) struct lu_fid fid; struct ost_id oi; obd_count ost_idx; - ENTRY; if (!cfs_capable(CFS_CAP_SYS_ADMIN)) RETURN(-EPERM); @@ -1215,7 +1192,6 @@ int ll_lov_setstripe_ea_info(struct inode *inode, struct file *file, struct lov_stripe_md *lsm = NULL; struct lookup_intent oit = {.it_op = IT_OPEN, .it_flags = flags}; int rc = 0; - ENTRY; lsm = ccc_inode_lsm_get(inode); if (lsm != NULL) { @@ -1337,7 +1313,6 @@ static int ll_lov_setea(struct inode *inode, struct file *file, int lum_size = sizeof(struct lov_user_md) + sizeof(struct lov_user_ost_data); int rc; - ENTRY; if (!cfs_capable(CFS_CAP_SYS_ADMIN)) RETURN(-EPERM); @@ -1366,7 +1341,6 @@ static int ll_lov_setstripe(struct inode *inode, struct file *file, struct lov_user_md_v3 *lumv3p = (struct lov_user_md_v3 *)arg; int lum_size, rc; int flags = FMODE_WRITE; - ENTRY; /* first try with v1 which is smaller than v3 */ lum_size = sizeof(struct lov_user_md_v1); @@ -1399,7 +1373,6 @@ static int ll_lov_getstripe(struct inode *inode, unsigned long arg) { struct lov_stripe_md *lsm; int rc = -ENODATA; - ENTRY; lsm = ccc_inode_lsm_get(inode); if (lsm != NULL) @@ -1415,7 +1388,6 @@ int ll_get_grouplock(struct inode *inode, struct file *file, unsigned long arg) struct ll_file_data *fd = LUSTRE_FPRIVATE(file); struct ccc_grouplock grouplock; int rc; - ENTRY; if (ll_file_nolock(file)) RETURN(-EOPNOTSUPP); @@ -1456,7 +1428,6 @@ int ll_put_grouplock(struct inode *inode, struct file *file, unsigned long arg) struct ll_inode_info *lli = ll_i2info(inode); struct ll_file_data *fd = LUSTRE_FPRIVATE(file); struct ccc_grouplock grouplock; - ENTRY; spin_lock(&lli->lli_lock); if (!(fd->fd_flags & LL_FILE_GROUP_LOCKED)) { @@ -1497,7 +1468,6 @@ int ll_release_openhandle(struct dentry *dentry, struct lookup_intent *it) struct inode *inode = dentry->d_inode; struct obd_client_handle *och; int rc; - ENTRY; LASSERT(inode); @@ -1541,7 +1511,6 @@ int ll_do_fiemap(struct inode *inode, struct ll_user_fiemap *fiemap, struct ll_fiemap_info_key fm_key = { .name = KEY_FIEMAP, }; int vallen = num_bytes; int rc; - ENTRY; /* Checks for fiemap flags */ if (fiemap->fm_flags & ~LUSTRE_FIEMAP_FLAGS_COMPAT) { @@ -1595,7 +1564,6 @@ int ll_fid2path(struct inode *inode, void *arg) struct obd_export *exp = ll_i2mdexp(inode); struct getinfo_fid2path *gfout, *gfin; int outsize, rc; - ENTRY; if (!cfs_capable(CFS_CAP_DAC_READ_SEARCH) && !(ll_i2sbi(inode)->ll_flags & LL_SBI_USER_FID2PATH)) @@ -1700,7 +1668,6 @@ int ll_data_version(struct inode *inode, __u64 *data_version, struct ll_sb_info *sbi = ll_i2sbi(inode); struct obdo *obdo = NULL; int rc; - ENTRY; /* If no stripe, we consider version is 0. */ lsm = ccc_inode_lsm_get(inode); @@ -1895,7 +1862,6 @@ long ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) struct inode *inode = file->f_dentry->d_inode; struct ll_file_data *fd = LUSTRE_FPRIVATE(file); int flags, rc; - ENTRY; CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p),cmd=%x\n", inode->i_ino, inode->i_generation, inode, cmd); @@ -2132,7 +2098,6 @@ loff_t ll_file_seek(struct file *file, loff_t offset, int origin) struct inode *inode = file->f_dentry->d_inode; loff_t retval, eof = 0; - ENTRY; retval = offset + ((origin == SEEK_END) ? i_size_read(inode) : (origin == SEEK_CUR) ? file->f_pos : 0); CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p), to=%llu=%#llx(%d)\n", @@ -2191,7 +2156,6 @@ int cl_sync_file_range(struct inode *inode, loff_t start, loff_t end, struct obd_capa *capa = NULL; struct cl_fsync_io *fio; int result; - ENTRY; if (mode != CL_FSYNC_NONE && mode != CL_FSYNC_LOCAL && mode != CL_FSYNC_DISCARD && mode != CL_FSYNC_ALL) @@ -2244,7 +2208,6 @@ int ll_fsync(struct file *file, loff_t start, loff_t end, int datasync) struct ptlrpc_request *req; struct obd_capa *oc; int rc, err; - ENTRY; CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p)\n", inode->i_ino, inode->i_generation, inode); @@ -2306,7 +2269,6 @@ int ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock) int flags = 0; int rc; int rc2 = 0; - ENTRY; CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu file_lock=%p\n", inode->i_ino, file_lock); @@ -2423,8 +2385,6 @@ int ll_file_flock(struct file *file, int cmd, struct file_lock *file_lock) int ll_file_noflock(struct file *file, int cmd, struct file_lock *file_lock) { - ENTRY; - RETURN(-ENOSYS); } @@ -2447,7 +2407,6 @@ int ll_have_md_lock(struct inode *inode, __u64 *bits, ldlm_mode_t l_req_mode) struct lu_fid *fid; __u64 flags; int i; - ENTRY; if (!inode) RETURN(0); @@ -2485,7 +2444,6 @@ ldlm_mode_t ll_take_md_lock(struct inode *inode, __u64 bits, ldlm_policy_data_t policy = { .l_inodebits = {bits}}; struct lu_fid *fid; ldlm_mode_t rc; - ENTRY; fid = &ll_i2info(inode)->lli_fid; CDEBUG(D_INFO, "trying to match res "DFID"\n", PFID(fid)); @@ -2522,7 +2480,6 @@ int __ll_inode_revalidate_it(struct dentry *dentry, struct lookup_intent *it, struct ptlrpc_request *req = NULL; struct obd_export *exp; int rc = 0; - ENTRY; LASSERT(inode != NULL); @@ -2617,7 +2574,6 @@ int ll_inode_revalidate_it(struct dentry *dentry, struct lookup_intent *it, { struct inode *inode = dentry->d_inode; int rc; - ENTRY; rc = __ll_inode_revalidate_it(dentry, it, ibits); if (rc != 0) @@ -2681,7 +2637,6 @@ struct posix_acl * ll_get_acl(struct inode *inode, int type) { struct ll_inode_info *lli = ll_i2info(inode); struct posix_acl *acl = NULL; - ENTRY; spin_lock(&lli->lli_lock); /* VFS' acl_permission_check->check_acl will release the refcount */ @@ -2695,7 +2650,6 @@ struct posix_acl * ll_get_acl(struct inode *inode, int type) int ll_inode_permission(struct inode *inode, int mask) { int rc = 0; - ENTRY; #ifdef MAY_NOT_BLOCK if (mask & MAY_NOT_BLOCK) @@ -2815,7 +2769,6 @@ void *ll_iocontrol_register(llioc_callback_t cb, int count, unsigned int *cmd) { unsigned int size; struct llioc_data *in_data = NULL; - ENTRY; if (cb == NULL || cmd == NULL || count > LLIOC_MAX_CMD || count < 0) @@ -2899,7 +2852,6 @@ int ll_layout_conf(struct inode *inode, const struct cl_object_conf *conf) struct cl_env_nest nest; struct lu_env *env; int result; - ENTRY; if (lli->lli_clob == NULL) RETURN(0); @@ -2939,7 +2891,6 @@ static int ll_layout_fetch(struct inode *inode, struct ldlm_lock *lock) void *lmm; int lmmsize; int rc; - ENTRY; CDEBUG(D_INODE, DFID" LVB_READY=%d l_lvb_data=%p l_lvb_len=%d\n", PFID(ll_inode2fid(inode)), !!(lock->l_flags & LDLM_FL_LVB_READY), @@ -3010,7 +2961,6 @@ static int ll_layout_lock_set(struct lustre_handle *lockh, ldlm_mode_t mode, int rc = 0; bool lvb_ready; bool wait_layout = false; - ENTRY; LASSERT(lustre_handle_is_used(lockh)); @@ -3132,7 +3082,6 @@ int ll_layout_refresh(struct inode *inode, __u32 *gen) .ei_cb_cp = ldlm_completion_ast, }; int rc; - ENTRY; *gen = lli->lli_layout_gen; if (!(sbi->ll_flags & LL_SBI_LAYOUT_LOCK)) diff --git a/drivers/staging/lustre/lustre/llite/llite_capa.c b/drivers/staging/lustre/lustre/llite/llite_capa.c index cfc5ad388c1c..061a0a574b5d 100644 --- a/drivers/staging/lustre/lustre/llite/llite_capa.c +++ b/drivers/staging/lustre/lustre/llite/llite_capa.c @@ -170,7 +170,6 @@ static int capa_thread_main(void *unused) struct inode *inode = NULL; struct l_wait_info lwi = { 0 }; int rc; - ENTRY; thread_set_flags(&ll_capa_thread, SVC_RUNNING); wake_up(&ll_capa_thread.t_ctl_waitq); @@ -291,7 +290,6 @@ void ll_capa_timer_callback(unsigned long unused) int ll_capa_thread_start(void) { task_t *task; - ENTRY; init_waitqueue_head(&ll_capa_thread.t_ctl_waitq); @@ -321,8 +319,6 @@ struct obd_capa *ll_osscapa_get(struct inode *inode, __u64 opc) struct obd_capa *ocapa; int found = 0; - ENTRY; - if ((ll_i2sbi(inode)->ll_flags & LL_SBI_OSS_CAPA) == 0) RETURN(NULL); @@ -376,7 +372,6 @@ struct obd_capa *ll_mdscapa_get(struct inode *inode) { struct ll_inode_info *lli = ll_i2info(inode); struct obd_capa *ocapa; - ENTRY; LASSERT(inode != NULL); @@ -524,7 +519,6 @@ int ll_update_capa(struct obd_capa *ocapa, struct lustre_capa *capa) { struct inode *inode = ocapa->u.cli.inode; int rc = 0; - ENTRY; LASSERT(ocapa); diff --git a/drivers/staging/lustre/lustre/llite/llite_close.c b/drivers/staging/lustre/lustre/llite/llite_close.c index 00b2b38d4c97..20481d8329b0 100644 --- a/drivers/staging/lustre/lustre/llite/llite_close.c +++ b/drivers/staging/lustre/lustre/llite/llite_close.c @@ -50,7 +50,6 @@ void vvp_write_pending(struct ccc_object *club, struct ccc_page *page) { struct ll_inode_info *lli = ll_i2info(club->cob_inode); - ENTRY; spin_lock(&lli->lli_lock); lli->lli_flags |= LLIF_SOM_DIRTY; if (page != NULL && list_empty(&page->cpg_pending_linkage)) @@ -66,7 +65,6 @@ void vvp_write_complete(struct ccc_object *club, struct ccc_page *page) struct ll_inode_info *lli = ll_i2info(club->cob_inode); int rc = 0; - ENTRY; spin_lock(&lli->lli_lock); if (page != NULL && !list_empty(&page->cpg_pending_linkage)) { list_del_init(&page->cpg_pending_linkage); @@ -85,7 +83,6 @@ void ll_queue_done_writing(struct inode *inode, unsigned long flags) { struct ll_inode_info *lli = ll_i2info(inode); struct ccc_object *club = cl2ccc(ll_i2info(inode)->lli_clob); - ENTRY; spin_lock(&lli->lli_lock); lli->lli_flags |= flags; @@ -126,7 +123,6 @@ void ll_queue_done_writing(struct inode *inode, unsigned long flags) void ll_done_writing_attr(struct inode *inode, struct md_op_data *op_data) { struct ll_inode_info *lli = ll_i2info(inode); - ENTRY; op_data->op_flags |= MF_SOM_CHANGE; /* Check if Size-on-MDS attributes are valid. */ @@ -149,7 +145,6 @@ void ll_ioepoch_close(struct inode *inode, struct md_op_data *op_data, { struct ll_inode_info *lli = ll_i2info(inode); struct ccc_object *club = cl2ccc(ll_i2info(inode)->lli_clob); - ENTRY; spin_lock(&lli->lli_lock); if (!(list_empty(&club->cob_pending_list))) { @@ -225,7 +220,6 @@ int ll_som_update(struct inode *inode, struct md_op_data *op_data) __u32 old_flags; struct obdo *oa; int rc; - ENTRY; LASSERT(op_data != NULL); if (lli->lli_flags & LLIF_MDS_SIZE_LOCK) @@ -293,7 +287,6 @@ static void ll_done_writing(struct inode *inode) struct obd_client_handle *och = NULL; struct md_op_data *op_data; int rc; - ENTRY; LASSERT(exp_connect_som(ll_i2mdexp(inode))); @@ -347,7 +340,6 @@ static struct ll_inode_info *ll_close_next_lli(struct ll_close_queue *lcq) static int ll_close_thread(void *arg) { struct ll_close_queue *lcq = arg; - ENTRY; complete(&lcq->lcq_comp); diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index b44a3d6d0edd..141243658d7c 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -78,7 +78,6 @@ static struct ll_sb_info *ll_init_sbi(void) struct sysinfo si; class_uuid_t uuid; int i; - ENTRY; OBD_ALLOC(sbi, sizeof(*sbi)); if (!sbi) @@ -146,7 +145,6 @@ static struct ll_sb_info *ll_init_sbi(void) void ll_free_sbi(struct super_block *sb) { struct ll_sb_info *sbi = ll_s2sbi(sb); - ENTRY; if (sbi != NULL) { spin_lock(&ll_sb_lock); @@ -177,7 +175,6 @@ static int client_common_fill_super(struct super_block *sb, char *md, char *dt, struct lustre_md lmd; obd_valid valid; int size, err, checksum; - ENTRY; obd = class_name2obd(md); if (!obd) { @@ -677,7 +674,6 @@ void lustre_dump_dentry(struct dentry *dentry, int recur) void client_common_put_super(struct super_block *sb) { struct ll_sb_info *sbi = ll_s2sbi(sb); - ENTRY; #ifdef CONFIG_FS_POSIX_ACL if (sbi->ll_flags & LL_SBI_RMT_CLIENT) { @@ -712,8 +708,6 @@ void ll_kill_super(struct super_block *sb) { struct ll_sb_info *sbi; - ENTRY; - /* not init sb ?*/ if (!(sb->s_flags & MS_ACTIVE)) return; @@ -733,7 +727,6 @@ char *ll_read_opt(const char *opt, char *data) { char *value; char *retval; - ENTRY; CDEBUG(D_SUPER, "option: %s, data %s\n", opt, data); if (strncmp(opt, data, strlen(opt))) @@ -766,7 +759,6 @@ static int ll_options(char *options, int *flags) { int tmp; char *s1 = options, *s2; - ENTRY; if (!options) RETURN(0); @@ -978,7 +970,6 @@ int ll_fill_super(struct super_block *sb, struct vfsmount *mnt) /* %p for void* in printf needs 16+2 characters: 0xffffffffffffffff */ const int instlen = sizeof(cfg->cfg_instance) * 2 + 2; int err; - ENTRY; CDEBUG(D_VFSTRACE, "VFS Op: sb %p\n", sb); @@ -1070,7 +1061,6 @@ void ll_put_super(struct super_block *sb) struct ll_sb_info *sbi = ll_s2sbi(sb); char *profilenm = get_profile_name(sb); int next, force = 1; - ENTRY; CDEBUG(D_VFSTRACE, "VFS Op: sb %p - %s\n", sb, profilenm); @@ -1177,7 +1167,6 @@ void ll_clear_inode(struct inode *inode) { struct ll_inode_info *lli = ll_i2info(inode); struct ll_sb_info *sbi = ll_i2sbi(inode); - ENTRY; CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p)\n", inode->i_ino, inode->i_generation, inode); @@ -1250,7 +1239,6 @@ int ll_md_setattr(struct dentry *dentry, struct md_op_data *op_data, struct ll_sb_info *sbi = ll_i2sbi(inode); struct ptlrpc_request *request = NULL; int rc, ia_valid; - ENTRY; op_data = ll_prep_md_op_data(op_data, inode, NULL, NULL, 0, 0, LUSTRE_OPC_ANY, NULL); @@ -1309,7 +1297,6 @@ static int ll_setattr_done_writing(struct inode *inode, { struct ll_inode_info *lli = ll_i2info(inode); int rc = 0; - ENTRY; LASSERT(op_data != NULL); if (!S_ISREG(inode->i_mode)) @@ -1375,7 +1362,6 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr) struct md_op_data *op_data = NULL; struct md_open_data *mod = NULL; int rc = 0, rc1 = 0; - ENTRY; CDEBUG(D_VFSTRACE, "%s: setattr inode %p/fid:"DFID" from %llu to %llu, " "valid %x\n", ll_get_fsname(inode->i_sb, NULL, 0), inode, @@ -1540,7 +1526,6 @@ int ll_statfs_internal(struct super_block *sb, struct obd_statfs *osfs, struct ll_sb_info *sbi = ll_s2sbi(sb); struct obd_statfs obd_osfs; int rc; - ENTRY; rc = obd_statfs(NULL, sbi->ll_md_exp, osfs, max_age, flags); if (rc) { @@ -1791,7 +1776,6 @@ void ll_read_inode2(struct inode *inode, void *opaque) { struct lustre_md *md = opaque; struct ll_inode_info *lli = ll_i2info(inode); - ENTRY; CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p)\n", PFID(&lli->lli_fid), inode); @@ -1840,7 +1824,6 @@ void ll_read_inode2(struct inode *inode, void *opaque) void ll_delete_inode(struct inode *inode) { struct cl_inode_info *lli = cl_i2info(inode); - ENTRY; if (S_ISREG(inode->i_mode) && lli->lli_clob != NULL) /* discard all dirty pages before truncating them, required by @@ -1874,7 +1857,6 @@ int ll_iocontrol(struct inode *inode, struct file *file, struct ll_sb_info *sbi = ll_i2sbi(inode); struct ptlrpc_request *req = NULL; int rc, flags = 0; - ENTRY; switch(cmd) { case FSFILT_IOC_GETFLAGS: { @@ -1984,8 +1966,6 @@ void ll_umount_begin(struct super_block *sb) struct ll_sb_info *sbi = ll_s2sbi(sb); struct obd_device *obd; struct obd_ioctl_data *ioc_data; - ENTRY; - CDEBUG(D_VFSTRACE, "VFS Op: superblock %p count %d active %d\n", sb, sb->s_count, atomic_read(&sb->s_active)); @@ -2066,7 +2046,6 @@ int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req, struct ll_sb_info *sbi = NULL; struct lustre_md md; int rc; - ENTRY; LASSERT(*inode || sb); sbi = sb ? ll_s2sbi(sb) : ll_i2sbi(*inode); @@ -2321,7 +2300,6 @@ int ll_get_obd_name(struct inode *inode, unsigned int cmd, unsigned long arg) { struct ll_sb_info *sbi = ll_i2sbi(inode); struct obd_device *obd; - ENTRY; if (cmd == OBD_IOC_GETDTNAME) obd = class_exp2obd(sbi->ll_dt_exp); diff --git a/drivers/staging/lustre/lustre/llite/llite_mmap.c b/drivers/staging/lustre/lustre/llite/llite_mmap.c index b59cbd704ab6..d98a40f61bfc 100644 --- a/drivers/staging/lustre/lustre/llite/llite_mmap.c +++ b/drivers/staging/lustre/lustre/llite/llite_mmap.c @@ -70,7 +70,6 @@ struct vm_area_struct *our_vma(struct mm_struct *mm, unsigned long addr, size_t count) { struct vm_area_struct *vma, *ret = NULL; - ENTRY; /* mmap_sem must have been held by caller. */ LASSERT(!down_write_trylock(&mm->mmap_sem)); @@ -109,7 +108,6 @@ struct cl_io *ll_fault_io_init(struct vm_area_struct *vma, struct cl_fault_io *fio; struct lu_env *env; int rc; - ENTRY; *env_ret = NULL; if (ll_file_nolock(file)) @@ -182,7 +180,6 @@ static int ll_page_mkwrite0(struct vm_area_struct *vma, struct page *vmpage, sigset_t set; struct inode *inode; struct ll_inode_info *lli; - ENTRY; LASSERT(vmpage != NULL); @@ -306,7 +303,6 @@ static int ll_fault0(struct vm_area_struct *vma, struct vm_fault *vmf) struct cl_env_nest nest; int result; int fault_ret = 0; - ENTRY; io = ll_fault_io_init(vma, &env, &nest, vmf->pgoff, &ra_flags); if (IS_ERR(io)) @@ -433,7 +429,6 @@ static void ll_vm_open(struct vm_area_struct * vma) struct inode *inode = vma->vm_file->f_dentry->d_inode; struct ccc_object *vob = cl_inode2ccc(inode); - ENTRY; LASSERT(vma->vm_file); LASSERT(atomic_read(&vob->cob_mmap_cnt) >= 0); atomic_inc(&vob->cob_mmap_cnt); @@ -448,7 +443,6 @@ static void ll_vm_close(struct vm_area_struct *vma) struct inode *inode = vma->vm_file->f_dentry->d_inode; struct ccc_object *vob = cl_inode2ccc(inode); - ENTRY; LASSERT(vma->vm_file); atomic_dec(&vob->cob_mmap_cnt); LASSERT(atomic_read(&vob->cob_mmap_cnt) >= 0); @@ -468,7 +462,6 @@ static inline unsigned long file_to_user(struct vm_area_struct *vma, __u64 byte) int ll_teardown_mmaps(struct address_space *mapping, __u64 first, __u64 last) { int rc = -ENOENT; - ENTRY; LASSERTF(last > first, "last "LPU64" first "LPU64"\n", last, first); if (mapping_mapped(mapping)) { @@ -491,7 +484,6 @@ int ll_file_mmap(struct file *file, struct vm_area_struct * vma) { struct inode *inode = file->f_dentry->d_inode; int rc; - ENTRY; if (ll_file_nolock(file)) RETURN(-EOPNOTSUPP); diff --git a/drivers/staging/lustre/lustre/llite/llite_nfs.c b/drivers/staging/lustre/lustre/llite/llite_nfs.c index 32362ece2a7b..d2661bb20db6 100644 --- a/drivers/staging/lustre/lustre/llite/llite_nfs.c +++ b/drivers/staging/lustre/lustre/llite/llite_nfs.c @@ -91,7 +91,6 @@ struct inode *search_inode_for_lustre(struct super_block *sb, ll_need_32bit_api(sbi)); struct md_op_data *op_data; int rc; - ENTRY; CDEBUG(D_INFO, "searching inode for:(%lu,"DFID")\n", hash, PFID(fid)); @@ -139,7 +138,6 @@ ll_iget_for_nfs(struct super_block *sb, struct lu_fid *fid, struct lu_fid *paren { struct inode *inode; struct dentry *result; - ENTRY; CDEBUG(D_INFO, "Get dentry for fid: "DFID"\n", PFID(fid)); if (!fid_is_sane(fid)) @@ -192,7 +190,6 @@ static int ll_encode_fh(struct inode *inode, __u32 *fh, int *plen, struct inode *parent) { struct lustre_nfs_fid *nfs_fid = (void *)fh; - ENTRY; CDEBUG(D_INFO, "encoding for (%lu,"DFID") maxlen=%d minlen=%d\n", inode->i_ino, PFID(ll_inode2fid(inode)), *plen, @@ -236,7 +233,6 @@ static int ll_get_name(struct dentry *dentry, char *name, .lgd_fid = ll_i2info(child->d_inode)->lli_fid, .ctx.actor = ll_nfs_get_name_filldir, }; - ENTRY; if (!dir || !S_ISDIR(dir->i_mode)) GOTO(out, rc = -ENOTDIR); @@ -288,7 +284,6 @@ static struct dentry *ll_get_parent(struct dentry *dchild) struct md_op_data *op_data; int rc; int lmmsize; - ENTRY; LASSERT(dir && S_ISDIR(dir->i_mode)); diff --git a/drivers/staging/lustre/lustre/llite/lproc_llite.c b/drivers/staging/lustre/lustre/llite/lproc_llite.c index 3ad391ae5894..8485aa166e43 100644 --- a/drivers/staging/lustre/lustre/llite/lproc_llite.c +++ b/drivers/staging/lustre/lustre/llite/lproc_llite.c @@ -379,7 +379,6 @@ static ssize_t ll_max_cached_mb_seq_write(struct file *file, const char *buffer, int mult, rc, pages_number; int diff = 0; int nrpages = 0; - ENTRY; mult = 1 << (20 - PAGE_CACHE_SHIFT); buffer = lprocfs_find_named_value(buffer, "max_cached_mb:", &count); @@ -855,7 +854,6 @@ int lprocfs_register_mountpoint(struct proc_dir_entry *parent, proc_dir_entry_t *dir; char name[MAX_STRING_SIZE + 1], *ptr; int err, id, len, rc; - ENTRY; memset(lvars, 0, sizeof(lvars)); diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index 333e55f692f1..cc0d0a70bd1f 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -77,8 +77,6 @@ static int ll_d_mountpoint(struct dentry *dparent, struct dentry *dchild, int ll_unlock(__u32 mode, struct lustre_handle *lockh) { - ENTRY; - ldlm_lock_decref(lockh, mode); RETURN(0); @@ -139,7 +137,6 @@ struct inode *ll_iget(struct super_block *sb, ino_t hash, struct lustre_md *md) { struct inode *inode; - ENTRY; LASSERT(hash != 0); inode = iget5_locked(sb, hash, ll_test_inode, ll_set_inode, md); @@ -200,7 +197,6 @@ int ll_md_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc, { int rc; struct lustre_handle lockh; - ENTRY; switch (flag) { case LDLM_CB_BLOCKING: @@ -433,7 +429,6 @@ int ll_lookup_it_finish(struct ptlrpc_request *request, struct inode *inode = NULL; __u64 bits = 0; int rc; - ENTRY; /* NB 1 request reference will be taken away by ll_intent_lock() * when I return */ @@ -496,7 +491,6 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry, struct it_cb_data icbd; __u32 opc; int rc; - ENTRY; if (dentry->d_name.len > ll_i2sbi(parent)->ll_namelen) RETURN(ERR_PTR(-ENAMETOOLONG)); @@ -621,7 +615,6 @@ static int ll_atomic_open(struct inode *dir, struct dentry *dentry, struct dentry *de; long long lookup_flags = LOOKUP_OPEN; int rc = 0; - ENTRY; CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p),file %p," "open_flags %x,mode %x opened %d\n", @@ -703,7 +696,6 @@ static struct inode *ll_create_node(struct inode *dir, const char *name, struct ptlrpc_request *request = NULL; struct ll_sb_info *sbi = ll_i2sbi(dir); int rc; - ENTRY; LASSERT(it && it->d.lustre.it_disposition); @@ -747,7 +739,6 @@ static int ll_create_it(struct inode *dir, struct dentry *dentry, int mode, { struct inode *inode; int rc = 0; - ENTRY; CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p),intent=%s\n", dentry->d_name.len, dentry->d_name.name, dir->i_ino, @@ -798,7 +789,6 @@ static int ll_new_node(struct inode *dir, struct qstr *name, int tgt_len = 0; int err; - ENTRY; if (unlikely(tgt != NULL)) tgt_len = strlen(tgt) + 1; @@ -835,7 +825,6 @@ static int ll_mknod_generic(struct inode *dir, struct qstr *name, int mode, unsigned rdev, struct dentry *dchild) { int err; - ENTRY; CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p) mode %o dev %x\n", name->len, name->name, dir->i_ino, dir->i_generation, dir, @@ -895,7 +884,6 @@ static int ll_symlink_generic(struct inode *dir, struct qstr *name, const char *tgt, struct dentry *dchild) { int err; - ENTRY; CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p),target=%.*s\n", name->len, name->name, dir->i_ino, dir->i_generation, @@ -918,7 +906,6 @@ static int ll_link_generic(struct inode *src, struct inode *dir, struct md_op_data *op_data; int err; - ENTRY; CDEBUG(D_VFSTRACE, "VFS Op: inode=%lu/%u(%p), dir=%lu/%u(%p), target=%.*s\n", src->i_ino, src->i_generation, src, dir->i_ino, @@ -947,7 +934,6 @@ static int ll_mkdir_generic(struct inode *dir, struct qstr *name, { int err; - ENTRY; CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p)\n", name->len, name->name, dir->i_ino, dir->i_generation, dir); @@ -985,7 +971,6 @@ static int ll_rmdir_generic(struct inode *dir, struct dentry *dparent, struct ptlrpc_request *request = NULL; struct md_op_data *op_data; int rc; - ENTRY; CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p)\n", name->len, name->name, dir->i_ino, dir->i_generation, dir); @@ -1019,7 +1004,6 @@ int ll_rmdir_entry(struct inode *dir, char *name, int namelen) struct ptlrpc_request *request = NULL; struct md_op_data *op_data; int rc; - ENTRY; CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p)\n", namelen, name, dir->i_ino, dir->i_generation, dir); @@ -1049,7 +1033,6 @@ int ll_objects_destroy(struct ptlrpc_request *request, struct inode *dir) struct obdo *oa; struct obd_capa *oc = NULL; int rc; - ENTRY; /* req is swabbed so this is safe */ body = req_capsule_server_get(&request->rq_pill, &RMF_MDT_BODY); @@ -1126,7 +1109,6 @@ static int ll_unlink_generic(struct inode *dir, struct dentry *dparent, struct ptlrpc_request *request = NULL; struct md_op_data *op_data; int rc; - ENTRY; CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p)\n", name->len, name->name, dir->i_ino, dir->i_generation, dir); @@ -1167,7 +1149,7 @@ static int ll_rename_generic(struct inode *src, struct dentry *src_dparent, struct ll_sb_info *sbi = ll_i2sbi(src); struct md_op_data *op_data; int err; - ENTRY; + CDEBUG(D_VFSTRACE,"VFS Op:oldname=%.*s,src_dir=%lu/%u(%p),newname=%.*s," "tgt_dir=%lu/%u(%p)\n", src_name->len, src_name->name, src->i_ino, src->i_generation, src, tgt_name->len, diff --git a/drivers/staging/lustre/lustre/llite/remote_perm.c b/drivers/staging/lustre/lustre/llite/remote_perm.c index 0bc334803c90..1d29d7ccb70c 100644 --- a/drivers/staging/lustre/lustre/llite/remote_perm.c +++ b/drivers/staging/lustre/lustre/llite/remote_perm.c @@ -123,7 +123,6 @@ static int do_check_remote_perm(struct ll_inode_info *lli, int mask) struct hlist_head *head; struct ll_remote_perm *lrp; int found = 0, rc; - ENTRY; if (!lli->lli_remote_perms) RETURN(-ENOENT); @@ -163,7 +162,6 @@ int ll_update_remote_perm(struct inode *inode, struct mdt_remote_perm *perm) struct ll_inode_info *lli = ll_i2info(inode); struct ll_remote_perm *lrp = NULL, *tmp = NULL; struct hlist_head *head, *perm_hash = NULL; - ENTRY; LASSERT(ll_i2sbi(inode)->ll_flags & LL_SBI_RMT_CLIENT); @@ -253,7 +251,6 @@ int lustre_check_remote_perm(struct inode *inode, int mask) struct obd_capa *oc; cfs_time_t save; int i = 0, rc; - ENTRY; do { save = lli->lli_rmtperm_time; diff --git a/drivers/staging/lustre/lustre/llite/rw.c b/drivers/staging/lustre/lustre/llite/rw.c index ab4e95c63554..41430004e270 100644 --- a/drivers/staging/lustre/lustre/llite/rw.c +++ b/drivers/staging/lustre/lustre/llite/rw.c @@ -225,7 +225,6 @@ int ll_prepare_write(struct file *file, struct page *vmpage, unsigned from, { struct ll_cl_context *lcc; int result; - ENTRY; lcc = ll_cl_init(file, vmpage, 1); if (!IS_ERR(lcc)) { @@ -264,7 +263,6 @@ int ll_commit_write(struct file *file, struct page *vmpage, unsigned from, struct cl_io *io; struct cl_page *page; int result = 0; - ENTRY; lcc = ll_cl_get(); env = lcc->lcc_env; @@ -322,7 +320,6 @@ static unsigned long ll_ra_count_get(struct ll_sb_info *sbi, { struct ll_ra_info *ra = &sbi->ll_ra_info; long ret; - ENTRY; /* If read-ahead pages left are less than 1M, do not do read-ahead, * otherwise it will form small read RPC(< 1M), which hurt server @@ -465,8 +462,6 @@ static int cl_read_ahead_page(const struct lu_env *env, struct cl_io *io, struct ccc_page *cp; int rc; - ENTRY; - rc = 0; cl_page_assume(env, io, page); lu_ref_add(&page->cp_reference, "ra", current); @@ -513,8 +508,6 @@ static int ll_read_ahead_page(const struct lu_env *env, struct cl_io *io, int rc = 0; const char *msg = NULL; - ENTRY; - gfp_mask = GFP_HIGHUSER & ~__GFP_WAIT; #ifdef __GFP_NOWARN gfp_mask |= __GFP_NOWARN; @@ -719,7 +712,6 @@ int ll_readahead(const struct lu_env *env, struct cl_io *io, struct cl_object *clob; int ret = 0; __u64 kms; - ENTRY; inode = mapping->host; lli = ll_i2info(inode); @@ -996,7 +988,6 @@ void ras_update(struct ll_sb_info *sbi, struct inode *inode, { struct ll_ra_info *ra = &sbi->ll_ra_info; int zero = 0, stride_detect = 0, ra_miss = 0; - ENTRY; spin_lock(&ras->ras_lock); @@ -1152,7 +1143,6 @@ int ll_writepage(struct page *vmpage, struct writeback_control *wbc) bool redirtied = false; bool unlocked = false; int result; - ENTRY; LASSERT(PageLocked(vmpage)); LASSERT(!PageWriteback(vmpage)); @@ -1244,7 +1234,6 @@ int ll_writepages(struct address_space *mapping, struct writeback_control *wbc) int range_whole = 0; int result; int ignore_layout = 0; - ENTRY; if (wbc->range_cyclic) { start = mapping->writeback_index << PAGE_CACHE_SHIFT; @@ -1285,7 +1274,6 @@ int ll_readpage(struct file *file, struct page *vmpage) { struct ll_cl_context *lcc; int result; - ENTRY; lcc = ll_cl_init(file, vmpage, 0); if (!IS_ERR(lcc)) { diff --git a/drivers/staging/lustre/lustre/llite/rw26.c b/drivers/staging/lustre/lustre/llite/rw26.c index 256ee6356b31..1a804773e43c 100644 --- a/drivers/staging/lustre/lustre/llite/rw26.c +++ b/drivers/staging/lustre/lustre/llite/rw26.c @@ -247,7 +247,6 @@ ssize_t ll_direct_rw_pages(const struct lu_env *env, struct cl_io *io, long page_size = cl_page_size(obj); bool do_io; int io_pages = 0; - ENTRY; queue = &io->ci_queue; cl_2queue_init(queue); @@ -381,7 +380,6 @@ static ssize_t ll_direct_IO_26(int rw, struct kiocb *iocb, unsigned long seg = 0; long size = MAX_DIO_SIZE; int refcheck; - ENTRY; if (!lli->lli_has_smd) RETURN(-EBADF); @@ -504,7 +502,6 @@ static int ll_write_begin(struct file *file, struct address_space *mapping, struct page *page; int rc; unsigned from = pos & (PAGE_CACHE_SIZE - 1); - ENTRY; page = grab_cache_page_write_begin(mapping, index, flags); if (!page) diff --git a/drivers/staging/lustre/lustre/llite/statahead.c b/drivers/staging/lustre/lustre/llite/statahead.c index 7747f8f2079d..be1c3a888702 100644 --- a/drivers/staging/lustre/lustre/llite/statahead.c +++ b/drivers/staging/lustre/lustre/llite/statahead.c @@ -200,7 +200,6 @@ ll_sa_entry_alloc(struct ll_statahead_info *sai, __u64 index, struct ll_sa_entry *entry; int entry_size; char *dname; - ENTRY; entry_size = sizeof(struct ll_sa_entry) + (len & ~3) + 4; OBD_ALLOC(entry, entry_size); @@ -465,7 +464,6 @@ static struct ll_statahead_info *ll_sai_alloc(void) { struct ll_statahead_info *sai; int i; - ENTRY; OBD_ALLOC_PTR(sai); if (!sai) @@ -510,7 +508,6 @@ static void ll_sai_put(struct ll_statahead_info *sai) { struct inode *inode = sai->sai_inode; struct ll_inode_info *lli = ll_i2info(inode); - ENTRY; if (atomic_dec_and_lock(&sai->sai_refcount, &lli->lli_sa_lock)) { struct ll_sa_entry *entry, *next; @@ -560,7 +557,6 @@ static void ll_agl_trigger(struct inode *inode, struct ll_statahead_info *sai) struct ll_inode_info *lli = ll_i2info(inode); __u64 index = lli->lli_agl_index; int rc; - ENTRY; LASSERT(list_empty(&lli->lli_agl_list)); @@ -628,7 +624,6 @@ static void ll_post_statahead(struct ll_statahead_info *sai) struct ptlrpc_request *req; struct mdt_body *body; int rc = 0; - ENTRY; spin_lock(&lli->lli_sa_lock); if (unlikely(sa_received_empty(sai))) { @@ -713,7 +708,6 @@ static int ll_statahead_interpret(struct ptlrpc_request *req, struct ll_statahead_info *sai = NULL; struct ll_sa_entry *entry; int wakeup; - ENTRY; if (it_disposition(it, DISP_LOOKUP_NEG)) rc = -ENOENT; @@ -852,7 +846,6 @@ static int do_sa_lookup(struct inode *dir, struct ll_sa_entry *entry) struct ldlm_enqueue_info *einfo; struct obd_capa *capas[2]; int rc; - ENTRY; rc = sa_args_init(dir, NULL, entry, &minfo, &einfo, capas); if (rc) @@ -885,7 +878,6 @@ static int do_sa_revalidate(struct inode *dir, struct ll_sa_entry *entry, struct ldlm_enqueue_info *einfo; struct obd_capa *capas[2]; int rc; - ENTRY; if (unlikely(inode == NULL)) RETURN(1); @@ -934,7 +926,6 @@ static void ll_statahead_one(struct dentry *parent, const char* entry_name, struct ll_sa_entry *entry; int rc; int rc1; - ENTRY; entry = ll_sa_entry_alloc(sai, sai->sai_index, entry_name, entry_name_len); @@ -979,7 +970,6 @@ static int ll_agl_thread(void *arg) struct ll_statahead_info *sai = ll_sai_get(plli->lli_sai); struct ptlrpc_thread *thread = &sai->sai_agl_thread; struct l_wait_info lwi = { 0 }; - ENTRY; CDEBUG(D_READA, "agl thread started: [pid %d] [parent %.*s]\n", current_pid(), parent->d_name.len, parent->d_name.name); @@ -1038,7 +1028,6 @@ static void ll_start_agl(struct dentry *parent, struct ll_statahead_info *sai) struct l_wait_info lwi = { 0 }; struct ll_inode_info *plli; task_t *task; - ENTRY; CDEBUG(D_READA, "start agl thread: [pid %d] [parent %.*s]\n", current_pid(), parent->d_name.len, parent->d_name.name); @@ -1074,7 +1063,6 @@ static int ll_statahead_thread(void *arg) int rc = 0; struct ll_dir_chain chain; struct l_wait_info lwi = { 0 }; - ENTRY; CDEBUG(D_READA, "statahead thread started: [pid %d] [parent %.*s]\n", current_pid(), parent->d_name.len, parent->d_name.name); @@ -1369,7 +1357,6 @@ static int is_first_dirent(struct inode *dir, struct dentry *dentry) __u64 pos = 0; int dot_de; int rc = LS_NONE_FIRST_DE; - ENTRY; ll_dir_chain_init(&chain); page = ll_get_dir_page(dir, pos, &chain); @@ -1481,7 +1468,6 @@ ll_sai_unplug(struct ll_statahead_info *sai, struct ll_sa_entry *entry) struct ptlrpc_thread *thread = &sai->sai_thread; struct ll_sb_info *sbi = ll_i2sbi(sai->sai_inode); int hit; - ENTRY; if (entry != NULL && entry->se_stat == SA_ENTRY_SUCC) hit = 1; @@ -1540,7 +1526,6 @@ int do_statahead_enter(struct inode *dir, struct dentry **dentryp, struct l_wait_info lwi = { 0 }; int rc = 0; struct ll_inode_info *plli; - ENTRY; LASSERT(lli->lli_opendir_pid == current_pid()); diff --git a/drivers/staging/lustre/lustre/llite/symlink.c b/drivers/staging/lustre/lustre/llite/symlink.c index 9208afb95f12..f64982afe6dc 100644 --- a/drivers/staging/lustre/lustre/llite/symlink.c +++ b/drivers/staging/lustre/lustre/llite/symlink.c @@ -50,7 +50,6 @@ static int ll_readlink_internal(struct inode *inode, int rc, symlen = i_size_read(inode) + 1; struct mdt_body *body; struct md_op_data *op_data; - ENTRY; *request = NULL; @@ -122,7 +121,6 @@ static int ll_readlink(struct dentry *dentry, char *buffer, int buflen) struct ptlrpc_request *request; char *symname; int rc; - ENTRY; CDEBUG(D_VFSTRACE, "VFS Op\n"); @@ -144,7 +142,6 @@ static void *ll_follow_link(struct dentry *dentry, struct nameidata *nd) struct ptlrpc_request *request = NULL; int rc; char *symname; - ENTRY; CDEBUG(D_VFSTRACE, "VFS Op\n"); /* Limit the recursive symlink depth to 5 instead of default diff --git a/drivers/staging/lustre/lustre/llite/vvp_dev.c b/drivers/staging/lustre/lustre/llite/vvp_dev.c index 9254b990d31c..760595f89e60 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_dev.c +++ b/drivers/staging/lustre/lustre/llite/vvp_dev.c @@ -224,7 +224,6 @@ int cl_sb_fini(struct super_block *sb) int refcheck; int result; - ENTRY; sbi = ll_s2sbi(sb); env = cl_env_get(&refcheck); if (!IS_ERR(env)) { diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index 50a4c9104f6d..27ddadf7cca6 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -176,7 +176,6 @@ static int vvp_mmap_locks(const struct lu_env *env, unsigned long seg; ssize_t count; int result; - ENTRY; LASSERT(io->ci_type == CIT_READ || io->ci_type == CIT_WRITE); @@ -255,7 +254,6 @@ static int vvp_io_rw_lock(const struct lu_env *env, struct cl_io *io, int ast_flags = 0; LASSERT(io->ci_type == CIT_READ || io->ci_type == CIT_WRITE); - ENTRY; ccc_io_update_iov(env, cio, io); @@ -274,7 +272,6 @@ static int vvp_io_read_lock(const struct lu_env *env, struct ll_inode_info *lli = ll_i2info(ccc_object_inode(io->ci_obj)); int result; - ENTRY; /* XXX: Layer violation, we shouldn't see lsm at llite level. */ if (lli->lli_has_smd) /* lsm-less file doesn't need to lock */ result = vvp_io_rw_lock(env, io, CLM_READ, @@ -556,8 +553,6 @@ static int vvp_io_write_start(const struct lu_env *env, loff_t pos = io->u.ci_wr.wr.crw_pos; size_t cnt = io->u.ci_wr.wr.crw_count; - ENTRY; - if (!can_populate_pages(env, io, inode)) return 0; @@ -807,8 +802,6 @@ static int vvp_io_read_page(const struct lu_env *env, CLOBINVRNT(env, obj, ccc_object_invariant(obj)); LASSERT(slice->cpl_obj == obj); - ENTRY; - if (sbi->ll_ra_info.ra_max_pages_per_file && sbi->ll_ra_info.ra_max_pages) ras_update(sbi, inode, ras, page->cp_index, @@ -923,8 +916,6 @@ static int vvp_io_prepare_write(const struct lu_env *env, int result; - ENTRY; - LINVRNT(cl_page_is_vmlocked(env, pg)); LASSERT(vmpage->mapping->host == ccc_object_inode(obj)); @@ -965,8 +956,6 @@ static int vvp_io_commit_write(const struct lu_env *env, int tallyop; loff_t size; - ENTRY; - LINVRNT(cl_page_is_vmlocked(env, pg)); LASSERT(vmpage->mapping->host == inode); @@ -1122,7 +1111,6 @@ int vvp_io_init(const struct lu_env *env, struct cl_object *obj, int result; CLOBINVRNT(env, obj, ccc_object_invariant(obj)); - ENTRY; CL_IO_SLICE_CLEAN(cio, cui_cl); cl_io_slice_add(io, &cio->cui_cl, obj, &vvp_io_ops); diff --git a/drivers/staging/lustre/lustre/llite/vvp_lock.c b/drivers/staging/lustre/lustre/llite/vvp_lock.c index 9b8712bccd92..a48cd5984557 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_lock.c +++ b/drivers/staging/lustre/lustre/llite/vvp_lock.c @@ -63,7 +63,6 @@ static unsigned long vvp_lock_weigh(const struct lu_env *env, { struct ccc_object *cob = cl2ccc(slice->cls_obj); - ENTRY; RETURN(atomic_read(&cob->cob_mmap_cnt) > 0 ? ~0UL >> 2 : 0); } diff --git a/drivers/staging/lustre/lustre/llite/vvp_page.c b/drivers/staging/lustre/lustre/llite/vvp_page.c index 4568e69bb9f0..522632b525fb 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_page.c +++ b/drivers/staging/lustre/lustre/llite/vvp_page.c @@ -218,7 +218,6 @@ static int vvp_page_prep_read(const struct lu_env *env, const struct cl_page_slice *slice, struct cl_io *unused) { - ENTRY; /* Skip the page already marked as PG_uptodate. */ RETURN(PageUptodate(cl2vm_page(slice)) ? -EALREADY : 0); } @@ -274,7 +273,6 @@ static void vvp_page_completion_read(const struct lu_env *env, struct page *vmpage = cp->cpg_page; struct cl_page *page = cl_page_top(slice->cpl_page); struct inode *inode = ccc_object_inode(page->cp_obj); - ENTRY; LASSERT(PageLocked(vmpage)); CL_PAGE_HEADER(D_PAGE, env, page, "completing READ with %d\n", ioret); @@ -301,7 +299,6 @@ static void vvp_page_completion_write(const struct lu_env *env, struct ccc_page *cp = cl2ccc_page(slice); struct cl_page *pg = slice->cpl_page; struct page *vmpage = cp->cpg_page; - ENTRY; LASSERT(ergo(pg->cp_sync_io != NULL, PageLocked(vmpage))); LASSERT(PageWriteback(vmpage)); diff --git a/drivers/staging/lustre/lustre/llite/xattr.c b/drivers/staging/lustre/lustre/llite/xattr.c index 2e3ff6d088bc..c501ac934499 100644 --- a/drivers/staging/lustre/lustre/llite/xattr.c +++ b/drivers/staging/lustre/lustre/llite/xattr.c @@ -118,7 +118,6 @@ int ll_setxattr_common(struct inode *inode, const char *name, ext_acl_xattr_header *acl = NULL; #endif const char *pv = value; - ENTRY; xattr_type = get_xattr_type(name); rc = xattr_type_filter(sbi, xattr_type); @@ -287,7 +286,6 @@ int ll_getxattr_common(struct inode *inode, const char *name, void *xdata; struct obd_capa *oc; struct rmtacl_ctl_entry *rce = NULL; - ENTRY; CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p)\n", inode->i_ino, inode->i_generation, inode); diff --git a/drivers/staging/lustre/lustre/lmv/lmv_fld.c b/drivers/staging/lustre/lustre/lmv/lmv_fld.c index 08a5b69dc90d..7ca3fb50a962 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_fld.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_fld.c @@ -57,8 +57,6 @@ int lmv_fld_lookup(struct lmv_obd *lmv, mdsno_t *mds) { int rc; - ENTRY; - /* FIXME: Currently ZFS still use local seq for ROOT unfortunately, and * this fid_is_local check should be removed once LU-2240 is fixed */ diff --git a/drivers/staging/lustre/lustre/lmv/lmv_intent.c b/drivers/staging/lustre/lustre/lmv/lmv_intent.c index 4bc8c6a5d6f2..3d0d1acddb13 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_intent.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_intent.c @@ -69,7 +69,6 @@ static int lmv_intent_remote(struct obd_export *exp, void *lmm, struct mdt_body *body; int pmode; int rc = 0; - ENTRY; body = req_capsule_server_get(&(*reqp)->rq_pill, &RMF_MDT_BODY); if (body == NULL) @@ -168,7 +167,6 @@ int lmv_intent_open(struct obd_export *exp, struct md_op_data *op_data, struct lmv_tgt_desc *tgt; struct mdt_body *body; int rc; - ENTRY; tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid1); if (IS_ERR(tgt)) @@ -252,7 +250,6 @@ int lmv_intent_lookup(struct obd_export *exp, struct md_op_data *op_data, struct lmv_tgt_desc *tgt = NULL; struct mdt_body *body; int rc = 0; - ENTRY; tgt = lmv_locate_mds(lmv, op_data, &op_data->op_fid1); if (IS_ERR(tgt)) @@ -300,7 +297,6 @@ int lmv_intent_lock(struct obd_export *exp, struct md_op_data *op_data, { struct obd_device *obd = exp->exp_obd; int rc; - ENTRY; LASSERT(it != NULL); LASSERT(fid_is_sane(&op_data->op_fid1)); diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 1987d4bae9b4..2970f584539d 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -80,7 +80,6 @@ static int lmv_set_mdc_active(struct lmv_obd *lmv, struct obd_uuid *uuid, struct obd_device *obd; int i; int rc = 0; - ENTRY; CDEBUG(D_INFO, "Searching in lmv %p for uuid %s (activate=%d)\n", lmv, uuid->uuid, activate); @@ -140,7 +139,6 @@ static int lmv_notify(struct obd_device *obd, struct obd_device *watched, struct lmv_obd *lmv = &obd->u.lmv; struct obd_uuid *uuid; int rc = 0; - ENTRY; if (strcmp(watched->obd_type->typ_name, LUSTRE_MDC_NAME)) { CERROR("unexpected notification of %s %s!\n", @@ -202,7 +200,6 @@ static int lmv_connect(const struct lu_env *env, struct lmv_obd *lmv = &obd->u.lmv; struct lustre_handle conn = { 0 }; int rc = 0; - ENTRY; /* * We don't want to actually do the underlying connections more than @@ -291,7 +288,6 @@ static int lmv_init_ea_size(struct obd_export *exp, int easize, int i; int rc = 0; int change = 0; - ENTRY; if (lmv->max_easize < easize) { lmv->max_easize = easize; @@ -342,7 +338,6 @@ int lmv_connect_mdc(struct obd_device *obd, struct lmv_tgt_desc *tgt) struct obd_export *mdc_exp; struct lu_fld_target target; int rc; - ENTRY; mdc_obd = class_find_client_obd(&tgt->ltd_uuid, LUSTRE_MDC_NAME, &obd->obd_uuid); @@ -452,7 +447,6 @@ static int lmv_add_target(struct obd_device *obd, struct obd_uuid *uuidp, struct lmv_obd *lmv = &obd->u.lmv; struct lmv_tgt_desc *tgt; int rc = 0; - ENTRY; CDEBUG(D_CONFIG, "Target uuid: %s. index %d\n", uuidp->uuid, index); @@ -551,7 +545,6 @@ int lmv_check_connect(struct obd_device *obd) int i; int rc; int easize; - ENTRY; if (lmv->connected) RETURN(0); @@ -618,7 +611,6 @@ static int lmv_disconnect_mdc(struct obd_device *obd, struct lmv_tgt_desc *tgt) struct lmv_obd *lmv = &obd->u.lmv; struct obd_device *mdc_obd; int rc; - ENTRY; LASSERT(tgt != NULL); LASSERT(obd != NULL); @@ -663,7 +655,6 @@ static int lmv_disconnect(struct obd_export *exp) struct lmv_obd *lmv = &obd->u.lmv; int rc; int i; - ENTRY; if (!lmv->tgts) goto out_local; @@ -828,7 +819,6 @@ static int lmv_hsm_ct_unregister(struct lmv_obd *lmv, unsigned int cmd, int len, struct lustre_kernelcomm *lk, void *uarg) { int i, rc = 0; - ENTRY; /* unregister request (call from llapi_hsm_copytool_fini) */ for (i = 0; i < lmv->desc.ld_tgt_count; i++) { @@ -852,7 +842,6 @@ static int lmv_hsm_ct_register(struct lmv_obd *lmv, unsigned int cmd, int len, int i, j, err; int rc = 0; bool any_set = false; - ENTRY; /* All or nothing: try to register to all MDS. * In case of failure, unregister from previous MDS, @@ -911,7 +900,6 @@ static int lmv_iocontrol(unsigned int cmd, struct obd_export *exp, int rc = 0; int set = 0; int count = lmv->desc.ld_tgt_count; - ENTRY; if (count == 0) RETURN(-ENOTTY); @@ -1215,7 +1203,6 @@ static int lmv_placement_policy(struct obd_device *obd, mdsno_t *mds) { struct lmv_obd *lmv = &obd->u.lmv; - ENTRY; LASSERT(mds != NULL); @@ -1257,7 +1244,6 @@ int __lmv_fid_alloc(struct lmv_obd *lmv, struct lu_fid *fid, { struct lmv_tgt_desc *tgt; int rc; - ENTRY; tgt = lmv_get_target(lmv, mds); if (IS_ERR(tgt)) @@ -1294,7 +1280,6 @@ int lmv_fid_alloc(struct obd_export *exp, struct lu_fid *fid, struct lmv_obd *lmv = &obd->u.lmv; mdsno_t mds = 0; int rc; - ENTRY; LASSERT(op_data != NULL); LASSERT(fid != NULL); @@ -1321,7 +1306,6 @@ static int lmv_setup(struct obd_device *obd, struct lustre_cfg *lcfg) struct lprocfs_static_vars lvars; struct lmv_desc *desc; int rc; - ENTRY; if (LUSTRE_CFG_BUFLEN(lcfg, 1) < 1) { CERROR("LMV setup requires a descriptor\n"); @@ -1379,7 +1363,6 @@ out: static int lmv_cleanup(struct obd_device *obd) { struct lmv_obd *lmv = &obd->u.lmv; - ENTRY; fld_client_fini(&lmv->lmv_fld); if (lmv->tgts != NULL) { @@ -1402,7 +1385,6 @@ static int lmv_process_config(struct obd_device *obd, obd_count len, void *buf) int gen; __u32 index; int rc; - ENTRY; switch (lcfg->lcfg_command) { case LCFG_ADD_MDC: @@ -1435,7 +1417,6 @@ static int lmv_statfs(const struct lu_env *env, struct obd_export *exp, struct obd_statfs *temp; int rc = 0; int i; - ENTRY; rc = lmv_check_connect(obd); if (rc) @@ -1489,7 +1470,6 @@ static int lmv_getstatus(struct obd_export *exp, struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; int rc; - ENTRY; rc = lmv_check_connect(obd); if (rc) @@ -1508,7 +1488,6 @@ static int lmv_getxattr(struct obd_export *exp, const struct lu_fid *fid, struct lmv_obd *lmv = &obd->u.lmv; struct lmv_tgt_desc *tgt; int rc; - ENTRY; rc = lmv_check_connect(obd); if (rc) @@ -1534,7 +1513,6 @@ static int lmv_setxattr(struct obd_export *exp, const struct lu_fid *fid, struct lmv_obd *lmv = &obd->u.lmv; struct lmv_tgt_desc *tgt; int rc; - ENTRY; rc = lmv_check_connect(obd); if (rc) @@ -1558,7 +1536,6 @@ static int lmv_getattr(struct obd_export *exp, struct md_op_data *op_data, struct lmv_obd *lmv = &obd->u.lmv; struct lmv_tgt_desc *tgt; int rc; - ENTRY; rc = lmv_check_connect(obd); if (rc) @@ -1584,7 +1561,6 @@ static int lmv_null_inode(struct obd_export *exp, const struct lu_fid *fid) struct lmv_obd *lmv = &obd->u.lmv; int i; int rc; - ENTRY; rc = lmv_check_connect(obd); if (rc) @@ -1613,7 +1589,6 @@ static int lmv_find_cbdata(struct obd_export *exp, const struct lu_fid *fid, struct lmv_obd *lmv = &obd->u.lmv; int i; int rc; - ENTRY; rc = lmv_check_connect(obd); if (rc) @@ -1645,7 +1620,6 @@ static int lmv_close(struct obd_export *exp, struct md_op_data *op_data, struct lmv_obd *lmv = &obd->u.lmv; struct lmv_tgt_desc *tgt; int rc; - ENTRY; rc = lmv_check_connect(obd); if (rc) @@ -1684,7 +1658,6 @@ int lmv_create(struct obd_export *exp, struct md_op_data *op_data, struct lmv_obd *lmv = &obd->u.lmv; struct lmv_tgt_desc *tgt; int rc; - ENTRY; rc = lmv_check_connect(obd); if (rc) @@ -1725,7 +1698,6 @@ static int lmv_done_writing(struct obd_export *exp, struct lmv_obd *lmv = &obd->u.lmv; struct lmv_tgt_desc *tgt; int rc; - ENTRY; rc = lmv_check_connect(obd); if (rc) @@ -1755,7 +1727,6 @@ lmv_enqueue_remote(struct obd_export *exp, struct ldlm_enqueue_info *einfo, struct mdt_body *body; int rc = 0; int pmode; - ENTRY; body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); LASSERT(body != NULL); @@ -1809,7 +1780,6 @@ lmv_enqueue(struct obd_export *exp, struct ldlm_enqueue_info *einfo, struct lmv_obd *lmv = &obd->u.lmv; struct lmv_tgt_desc *tgt; int rc; - ENTRY; rc = lmv_check_connect(obd); if (rc) @@ -1845,7 +1815,6 @@ lmv_getattr_name(struct obd_export *exp,struct md_op_data *op_data, struct lmv_tgt_desc *tgt; struct mdt_body *body; int rc; - ENTRY; rc = lmv_check_connect(obd); if (rc) @@ -1906,7 +1875,6 @@ static int lmv_early_cancel(struct obd_export *exp, struct md_op_data *op_data, struct lmv_tgt_desc *tgt; ldlm_policy_data_t policy = {{0}}; int rc = 0; - ENTRY; if (!fid_is_sane(fid)) RETURN(0); @@ -1942,7 +1910,6 @@ static int lmv_link(struct obd_export *exp, struct md_op_data *op_data, struct lmv_obd *lmv = &obd->u.lmv; struct lmv_tgt_desc *tgt; int rc; - ENTRY; rc = lmv_check_connect(obd); if (rc) @@ -1984,7 +1951,6 @@ static int lmv_rename(struct obd_export *exp, struct md_op_data *op_data, struct lmv_tgt_desc *src_tgt; struct lmv_tgt_desc *tgt_tgt; int rc; - ENTRY; LASSERT(oldlen != 0); @@ -2052,7 +2018,6 @@ static int lmv_setattr(struct obd_export *exp, struct md_op_data *op_data, struct lmv_obd *lmv = &obd->u.lmv; struct lmv_tgt_desc *tgt; int rc = 0; - ENTRY; rc = lmv_check_connect(obd); if (rc) @@ -2079,7 +2044,6 @@ static int lmv_sync(struct obd_export *exp, const struct lu_fid *fid, struct lmv_obd *lmv = &obd->u.lmv; struct lmv_tgt_desc *tgt; int rc; - ENTRY; rc = lmv_check_connect(obd); if (rc) @@ -2206,7 +2170,6 @@ static int lmv_readpage(struct obd_export *exp, struct md_op_data *op_data, int ncfspgs; /* pages read in PAGE_CACHE_SIZE */ int nlupgs; /* pages read in LU_PAGE_SIZE */ struct lmv_tgt_desc *tgt; - ENTRY; rc = lmv_check_connect(obd); if (rc) @@ -2245,7 +2208,6 @@ static int lmv_unlink(struct obd_export *exp, struct md_op_data *op_data, struct lmv_tgt_desc *tgt = NULL; struct mdt_body *body; int rc; - ENTRY; rc = lmv_check_connect(obd); if (rc) @@ -2352,7 +2314,6 @@ static int lmv_get_info(const struct lu_env *env, struct obd_export *exp, struct obd_device *obd; struct lmv_obd *lmv; int rc = 0; - ENTRY; obd = class_exp2obd(exp); if (obd == NULL) { @@ -2415,7 +2376,6 @@ int lmv_set_info_async(const struct lu_env *env, struct obd_export *exp, struct obd_device *obd; struct lmv_obd *lmv; int rc = 0; - ENTRY; obd = class_exp2obd(exp); if (obd == NULL) { @@ -2455,7 +2415,6 @@ int lmv_packmd(struct obd_export *exp, struct lov_mds_md **lmmp, struct lmv_stripe_md *lsmp; int mea_size; int i; - ENTRY; mea_size = lmv_get_easize(lmv); if (!lmmp) @@ -2505,7 +2464,6 @@ int lmv_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, int mea_size; int i; __u32 magic; - ENTRY; mea_size = lmv_get_easize(lmv); if (lsmp == NULL) @@ -2559,7 +2517,6 @@ static int lmv_cancel_unused(struct obd_export *exp, const struct lu_fid *fid, int rc = 0; int err; int i; - ENTRY; LASSERT(fid != NULL); @@ -2581,7 +2538,6 @@ int lmv_set_lock_data(struct obd_export *exp, __u64 *lockh, void *data, { struct lmv_obd *lmv = &exp->exp_obd->u.lmv; int rc; - ENTRY; rc = md_set_lock_data(lmv->tgts[0]->ltd_exp, lockh, data, bits); RETURN(rc); @@ -2596,7 +2552,6 @@ ldlm_mode_t lmv_lock_match(struct obd_export *exp, __u64 flags, struct lmv_obd *lmv = &obd->u.lmv; ldlm_mode_t rc; int i; - ENTRY; CDEBUG(D_INODE, "Lock match for "DFID"\n", PFID(fid)); @@ -2634,7 +2589,6 @@ int lmv_free_lustre_md(struct obd_export *exp, struct lustre_md *md) { struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; - ENTRY; if (md->mea) obd_free_memmd(exp, (void *)&md->mea); @@ -2648,7 +2602,6 @@ int lmv_set_open_replay_data(struct obd_export *exp, struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; struct lmv_tgt_desc *tgt; - ENTRY; tgt = lmv_find_target(lmv, &och->och_fid); if (IS_ERR(tgt)) @@ -2663,7 +2616,6 @@ int lmv_clear_open_replay_data(struct obd_export *exp, struct obd_device *obd = exp->exp_obd; struct lmv_obd *lmv = &obd->u.lmv; struct lmv_tgt_desc *tgt; - ENTRY; tgt = lmv_find_target(lmv, &och->och_fid); if (IS_ERR(tgt)) @@ -2681,7 +2633,6 @@ static int lmv_get_remote_perm(struct obd_export *exp, struct lmv_obd *lmv = &obd->u.lmv; struct lmv_tgt_desc *tgt; int rc; - ENTRY; rc = lmv_check_connect(obd); if (rc) @@ -2702,7 +2653,6 @@ static int lmv_renew_capa(struct obd_export *exp, struct obd_capa *oc, struct lmv_obd *lmv = &obd->u.lmv; struct lmv_tgt_desc *tgt; int rc; - ENTRY; rc = lmv_check_connect(obd); if (rc) @@ -2733,7 +2683,6 @@ int lmv_intent_getattr_async(struct obd_export *exp, struct lmv_obd *lmv = &obd->u.lmv; struct lmv_tgt_desc *tgt = NULL; int rc; - ENTRY; rc = lmv_check_connect(obd); if (rc) @@ -2754,7 +2703,6 @@ int lmv_revalidate_lock(struct obd_export *exp, struct lookup_intent *it, struct lmv_obd *lmv = &obd->u.lmv; struct lmv_tgt_desc *tgt; int rc; - ENTRY; rc = lmv_check_connect(obd); if (rc) @@ -2781,7 +2729,6 @@ int lmv_quotactl(struct obd_device *unused, struct obd_export *exp, struct lmv_tgt_desc *tgt = lmv->tgts[0]; int rc = 0, i; __u64 curspace, curinodes; - ENTRY; if (!lmv->desc.ld_tgt_count || !tgt->ltd_active) { CERROR("master lmv inactive\n"); @@ -2828,7 +2775,6 @@ int lmv_quotacheck(struct obd_device *unused, struct obd_export *exp, struct lmv_obd *lmv = &obd->u.lmv; struct lmv_tgt_desc *tgt; int i, rc = 0; - ENTRY; for (i = 0; i < lmv->desc.ld_tgt_count; i++) { int err; diff --git a/drivers/staging/lustre/lustre/lov/lov_dev.c b/drivers/staging/lustre/lustre/lov/lov_dev.c index f94f8d9d33d7..5d1b52284526 100644 --- a/drivers/staging/lustre/lustre/lov/lov_dev.c +++ b/drivers/staging/lustre/lustre/lov/lov_dev.c @@ -122,7 +122,6 @@ static void lov_req_completion(const struct lu_env *env, { struct lov_req *lr; - ENTRY; lr = cl2lov_req(slice); OBD_SLAB_FREE_PTR(lr, lov_req_kmem); EXIT; @@ -260,7 +259,6 @@ static int lov_req_init(const struct lu_env *env, struct cl_device *dev, struct lov_req *lr; int result; - ENTRY; OBD_SLAB_ALLOC_PTR_GFP(lr, lov_req_kmem, __GFP_IO); if (lr != NULL) { cl_req_slice_add(req, &lr->lr_cl, dev, &lov_req_ops); @@ -311,7 +309,6 @@ static void lov_cl_del_target(const struct lu_env *env, struct lu_device *dev, __u32 index) { struct lov_device *ld = lu2lov_dev(dev); - ENTRY; if (ld->ld_target[index] != NULL) { cl_stack_fini(env, lovsub2cl_dev(ld->ld_target[index])); @@ -360,7 +357,6 @@ static int lov_expand_targets(const struct lu_env *env, struct lov_device *dev) __u32 tgt_size; __u32 sub_size; - ENTRY; result = 0; tgt_size = dev->ld_lov->lov_tgt_size; sub_size = dev->ld_target_nr; @@ -404,7 +400,6 @@ static int lov_cl_add_target(const struct lu_env *env, struct lu_device *dev, struct lovsub_device *lsd; struct cl_device *cl; int rc; - ENTRY; obd_getref(obd); diff --git a/drivers/staging/lustre/lustre/lov/lov_io.c b/drivers/staging/lustre/lustre/lov/lov_io.c index b316ce8cfeac..0ef2293a65a0 100644 --- a/drivers/staging/lustre/lustre/lov/lov_io.c +++ b/drivers/staging/lustre/lustre/lov/lov_io.c @@ -59,7 +59,6 @@ static inline void lov_sub_exit(struct lov_io_sub *sub) static void lov_io_sub_fini(const struct lu_env *env, struct lov_io *lio, struct lov_io_sub *sub) { - ENTRY; if (sub->sub_io != NULL) { if (sub->sub_io_initialized) { lov_sub_enter(sub); @@ -149,7 +148,6 @@ static int lov_io_sub_init(const struct lu_env *env, struct lov_io *lio, LASSERT(sub->sub_io == NULL); LASSERT(sub->sub_env == NULL); LASSERT(sub->sub_stripe < lio->lis_stripe_count); - ENTRY; result = 0; sub->sub_io_initialized = 0; @@ -220,7 +218,6 @@ struct lov_io_sub *lov_sub_get(const struct lu_env *env, struct lov_io_sub *sub = &lio->lis_subs[stripe]; LASSERT(stripe < lio->lis_stripe_count); - ENTRY; if (!sub->sub_io_initialized) { sub->sub_stripe = stripe; @@ -249,7 +246,6 @@ static int lov_page_stripe(const struct cl_page *page) { struct lovsub_object *subobj; - ENTRY; subobj = lu2lovsub( lu_object_locate(page->cp_child->cp_obj->co_lu.lo_header, &lovsub_device_type)); @@ -268,7 +264,6 @@ struct lov_io_sub *lov_page_subio(const struct lu_env *env, struct lov_io *lio, LASSERT(cl2lov(slice->cpl_obj) == lio->lis_object); LASSERT(lsm != NULL); LASSERT(lio->lis_nr_subios > 0); - ENTRY; stripe = lov_page_stripe(page); RETURN(lov_sub_get(env, lio, stripe)); @@ -282,7 +277,6 @@ static int lov_io_subio_init(const struct lu_env *env, struct lov_io *lio, int result; LASSERT(lio->lis_object != NULL); - ENTRY; /* * Need to be optimized, we can't afford to allocate a piece of memory @@ -303,8 +297,6 @@ static int lov_io_subio_init(const struct lu_env *env, struct lov_io *lio, static void lov_io_slice_init(struct lov_io *lio, struct lov_object *obj, struct cl_io *io) { - ENTRY; - io->ci_result = 0; lio->lis_object = obj; @@ -363,7 +355,6 @@ static void lov_io_fini(const struct lu_env *env, const struct cl_io_slice *ios) struct lov_object *lov = cl2lov(ios->cis_obj); int i; - ENTRY; if (lio->lis_subs != NULL) { for (i = 0; i < lio->lis_nr_subios; i++) lov_io_sub_fini(env, lio, &lio->lis_subs[i]); @@ -397,7 +388,6 @@ static int lov_io_iter_init(const struct lu_env *env, int stripe; int rc = 0; - ENTRY; endpos = lov_offset_mod(lio->lis_endpos, -1); for (stripe = 0; stripe < lio->lis_stripe_count; stripe++) { if (!lov_stripe_intersects(lsm, stripe, lio->lis_pos, @@ -435,7 +425,6 @@ static int lov_io_rw_iter_init(const struct lu_env *env, unsigned long ssize = lsm->lsm_stripe_size; LASSERT(io->ci_type == CIT_READ || io->ci_type == CIT_WRITE); - ENTRY; /* fast path for common case. */ if (lio->lis_nr_subios != 1 && !cl_io_is_append(io)) { @@ -468,7 +457,6 @@ static int lov_io_call(const struct lu_env *env, struct lov_io *lio, struct lov_io_sub *sub; int rc = 0; - ENTRY; list_for_each_entry(sub, &lio->lis_active, sub_linkage) { lov_sub_enter(sub); rc = iofunc(sub->sub_env, sub->sub_io); @@ -484,19 +472,16 @@ static int lov_io_call(const struct lu_env *env, struct lov_io *lio, static int lov_io_lock(const struct lu_env *env, const struct cl_io_slice *ios) { - ENTRY; RETURN(lov_io_call(env, cl2lov_io(env, ios), cl_io_lock)); } static int lov_io_start(const struct lu_env *env, const struct cl_io_slice *ios) { - ENTRY; RETURN(lov_io_call(env, cl2lov_io(env, ios), cl_io_start)); } static int lov_io_end_wrapper(const struct lu_env *env, struct cl_io *io) { - ENTRY; /* * It's possible that lov_io_start() wasn't called against this * sub-io, either because previous sub-io failed, or upper layer @@ -535,7 +520,6 @@ static void lov_io_iter_fini(const struct lu_env *env, struct lov_io *lio = cl2lov_io(env, ios); int rc; - ENTRY; rc = lov_io_call(env, lio, lov_io_iter_fini_wrapper); LASSERT(rc == 0); while (!list_empty(&lio->lis_active)) @@ -548,7 +532,6 @@ static void lov_io_unlock(const struct lu_env *env, { int rc; - ENTRY; rc = lov_io_call(env, cl2lov_io(env, ios), lov_io_unlock_wrapper); LASSERT(rc == 0); EXIT; @@ -596,7 +579,7 @@ static int lov_io_submit(const struct lu_env *env, int rc = 0; int alloc = !(current->flags & PF_MEMALLOC); - ENTRY; + if (lio->lis_active_subios == 1) { int idx = lio->lis_single_subio_index; struct lov_io_sub *sub; @@ -696,7 +679,6 @@ static int lov_io_prepare_write(const struct lu_env *env, struct lov_io_sub *sub; int result; - ENTRY; sub = lov_page_subio(env, lio, slice); if (!IS_ERR(sub)) { result = cl_io_prepare_write(sub->sub_env, sub->sub_io, @@ -717,7 +699,6 @@ static int lov_io_commit_write(const struct lu_env *env, struct lov_io_sub *sub; int result; - ENTRY; sub = lov_page_subio(env, lio, slice); if (!IS_ERR(sub)) { result = cl_io_commit_write(sub->sub_env, sub->sub_io, @@ -735,7 +716,6 @@ static int lov_io_fault_start(const struct lu_env *env, struct lov_io *lio; struct lov_io_sub *sub; - ENTRY; fio = &ios->cis_io->u.ci_fault; lio = cl2lov_io(env, ios); sub = lov_sub_get(env, lio, lov_page_stripe(fio->ft_page)); @@ -750,7 +730,6 @@ static void lov_io_fsync_end(const struct lu_env *env, struct lov_io *lio = cl2lov_io(env, ios); struct lov_io_sub *sub; unsigned int *written = &ios->cis_io->u.ci_fsync.fi_nr_written; - ENTRY; *written = 0; list_for_each_entry(sub, &lio->lis_active, sub_linkage) { @@ -839,7 +818,6 @@ static void lov_empty_io_fini(const struct lu_env *env, const struct cl_io_slice *ios) { struct lov_object *lov = cl2lov(ios->cis_obj); - ENTRY; if (atomic_dec_and_test(&lov->lo_active_ios)) wake_up_all(&lov->lo_waitq); @@ -913,7 +891,6 @@ int lov_io_init_raid0(const struct lu_env *env, struct cl_object *obj, struct lov_io *lio = lov_env_io(env); struct lov_object *lov = cl2lov(obj); - ENTRY; INIT_LIST_HEAD(&lio->lis_active); lov_io_slice_init(lio, lov, io); if (io->ci_result == 0) { @@ -932,7 +909,6 @@ int lov_io_init_empty(const struct lu_env *env, struct cl_object *obj, struct lov_object *lov = cl2lov(obj); struct lov_io *lio = lov_env_io(env); int result; - ENTRY; lio->lis_object = lov; switch (io->ci_type) { @@ -970,7 +946,6 @@ int lov_io_init_released(const struct lu_env *env, struct cl_object *obj, struct lov_object *lov = cl2lov(obj); struct lov_io *lio = lov_env_io(env); int result; - ENTRY; LASSERT(lov->lo_lsm != NULL); lio->lis_object = lov; diff --git a/drivers/staging/lustre/lustre/lov/lov_lock.c b/drivers/staging/lustre/lustre/lov/lov_lock.c index bdf3334e0c9f..7cda7b6efc1e 100644 --- a/drivers/staging/lustre/lustre/lov/lov_lock.c +++ b/drivers/staging/lustre/lustre/lov/lov_lock.c @@ -110,7 +110,6 @@ static void lov_sublock_adopt(const struct lu_env *env, struct lov_lock *lck, LASSERT(cl_lock_is_mutexed(parent)); LASSERT(cl_lock_is_mutexed(sublock)); - ENTRY; lsl = cl2sub_lock(sublock); /* @@ -145,7 +144,6 @@ static struct cl_lock *lov_sublock_alloc(const struct lu_env *env, struct lov_lock_link *link; LASSERT(idx < lck->lls_nr); - ENTRY; OBD_SLAB_ALLOC_PTR_GFP(link, lov_lock_link_kmem, __GFP_IO); if (link != NULL) { @@ -187,7 +185,6 @@ static void lov_sublock_unlock(const struct lu_env *env, struct cl_lock_closure *closure, struct lov_sublock_env *subenv) { - ENTRY; lov_sublock_env_put(subenv); lsl->lss_active = NULL; cl_lock_disclosure(env, closure); @@ -203,7 +200,6 @@ static int lov_sublock_lock(const struct lu_env *env, struct lovsub_lock *sublock; struct cl_lock *child; int result = 0; - ENTRY; LASSERT(list_empty(&closure->clc_list)); @@ -267,8 +263,6 @@ static int lov_subresult(int result, int rc) int result_rank; int rc_rank; - ENTRY; - LASSERTF(result <= 0 || result == CLO_REPEAT || result == CLO_WAIT, "result = %d", result); LASSERTF(rc <= 0 || rc == CLO_REPEAT || rc == CLO_WAIT, @@ -307,8 +301,6 @@ static int lov_lock_sub_init(const struct lu_env *env, struct lov_layout_raid0 *r0 = lov_r0(loo); struct cl_lock *parent = lck->lls_cl.cls_lock; - ENTRY; - lck->lls_orig = parent->cll_descr; file_start = cl_offset(lov2cl(loo), parent->cll_descr.cld_start); file_end = cl_offset(lov2cl(loo), parent->cll_descr.cld_end + 1) - 1; @@ -405,7 +397,6 @@ static int lov_sublock_release(const struct lu_env *env, struct lov_lock *lck, struct cl_lock *parent = lck->lls_cl.cls_lock; LASSERT(cl_lock_is_mutexed(parent)); - ENTRY; if (lck->lls_sub[i].sub_flags & LSF_HELD) { struct cl_lock *sublock; @@ -451,7 +442,6 @@ static void lov_sublock_hold(const struct lu_env *env, struct lov_lock *lck, struct cl_lock *parent = lck->lls_cl.cls_lock; LASSERT(cl_lock_is_mutexed(parent)); - ENTRY; if (!(lck->lls_sub[i].sub_flags & LSF_HELD)) { struct cl_lock *sublock; @@ -477,7 +467,6 @@ static void lov_lock_fini(const struct lu_env *env, struct lov_lock *lck; int i; - ENTRY; lck = cl2lov_lock(slice); LASSERT(lck->lls_nr_filled == 0); if (lck->lls_sub != NULL) { @@ -500,7 +489,6 @@ static int lov_lock_enqueue_wait(const struct lu_env *env, { struct cl_lock *lock = lck->lls_cl.cls_lock; int result; - ENTRY; LASSERT(cl_lock_is_mutexed(lock)); @@ -522,7 +510,6 @@ static int lov_lock_enqueue_one(const struct lu_env *env, struct lov_lock *lck, struct cl_io *io, __u32 enqflags, int last) { int result; - ENTRY; /* first, try to enqueue a sub-lock ... */ result = cl_enqueue_try(env, sublock, io, enqflags); @@ -600,8 +587,6 @@ static int lov_lock_enqueue(const struct lu_env *env, int result; enum cl_lock_state minstate; - ENTRY; - for (result = 0, minstate = CLS_FREEING, i = 0; i < lck->lls_nr; ++i) { int rc; struct lovsub_lock *sub; @@ -691,8 +676,6 @@ static int lov_lock_unuse(const struct lu_env *env, int i; int result; - ENTRY; - for (result = 0, i = 0; i < lck->lls_nr; ++i) { int rc; struct lovsub_lock *sub; @@ -740,8 +723,6 @@ static void lov_lock_cancel(const struct lu_env *env, int i; int result; - ENTRY; - for (result = 0, i = 0; i < lck->lls_nr; ++i) { int rc; struct lovsub_lock *sub; @@ -802,8 +783,6 @@ static int lov_lock_wait(const struct lu_env *env, int result; int i; - ENTRY; - again: for (result = 0, minstate = CLS_FREEING, i = 0, reenqueued = 0; i < lck->lls_nr; ++i) { @@ -851,7 +830,6 @@ static int lov_lock_use(const struct lu_env *env, int i; LASSERT(slice->cls_lock->cll_state == CLS_INTRANSIT); - ENTRY; for (result = 0, i = 0; i < lck->lls_nr; ++i) { int rc; @@ -1016,8 +994,6 @@ static int lov_lock_fits_into(const struct lu_env *env, LASSERT(cl_object_same(need->cld_obj, slice->cls_obj)); LASSERT(lov->lls_nr > 0); - ENTRY; - /* for top lock, it's necessary to match enq flags otherwise it will * run into problem if a sublock is missing and reenqueue. */ if (need->cld_enq_flags != lov->lls_orig.cld_enq_flags) @@ -1066,7 +1042,6 @@ void lov_lock_unlink(const struct lu_env *env, LASSERT(cl_lock_is_mutexed(parent)); LASSERT(cl_lock_is_mutexed(sub->lss_cl.cls_lock)); - ENTRY; list_del_init(&link->lll_list); LASSERT(lck->lls_sub[link->lll_idx].sub_lock == sub); @@ -1087,7 +1062,6 @@ struct lov_lock_link *lov_lock_link_find(const struct lu_env *env, struct lov_lock_link *scan; LASSERT(cl_lock_is_mutexed(sub->lss_cl.cls_lock)); - ENTRY; list_for_each_entry(scan, &sub->lss_parents, lll_list) { if (scan->lll_super == lck) @@ -1120,7 +1094,6 @@ static void lov_lock_delete(const struct lu_env *env, int i; LASSERT(slice->cls_lock->cll_state == CLS_FREEING); - ENTRY; for (i = 0; i < lck->lls_nr; ++i) { struct lov_lock_sub *lls = &lck->lls_sub[i]; @@ -1192,7 +1165,6 @@ int lov_lock_init_raid0(const struct lu_env *env, struct cl_object *obj, struct lov_lock *lck; int result; - ENTRY; OBD_SLAB_ALLOC_PTR_GFP(lck, lov_lock_kmem, __GFP_IO); if (lck != NULL) { cl_lock_slice_add(lock, &lck->lls_cl, obj, &lov_lock_ops); @@ -1228,7 +1200,6 @@ int lov_lock_init_empty(const struct lu_env *env, struct cl_object *obj, struct lov_lock *lck; int result = -ENOMEM; - ENTRY; OBD_SLAB_ALLOC_PTR_GFP(lck, lov_lock_kmem, __GFP_IO); if (lck != NULL) { cl_lock_slice_add(lock, &lck->lls_cl, obj, &lov_empty_lock_ops); diff --git a/drivers/staging/lustre/lustre/lov/lov_log.c b/drivers/staging/lustre/lustre/lov/lov_log.c index 63b7f8d3182f..349579b59b6d 100644 --- a/drivers/staging/lustre/lustre/lov/lov_log.c +++ b/drivers/staging/lustre/lustre/lov/lov_log.c @@ -71,7 +71,6 @@ static int lov_llog_origin_add(const struct lu_env *env, struct obd_device *obd = ctxt->loc_obd; struct lov_obd *lov = &obd->u.lov; int i, rc = 0, cookies = 0; - ENTRY; LASSERTF(logcookies && numcookies >= lsm->lsm_stripe_count, "logcookies %p, numcookies %d lsm->lsm_stripe_count %d \n", @@ -129,7 +128,6 @@ static int lov_llog_origin_connect(struct llog_ctxt *ctxt, struct obd_device *obd = ctxt->loc_obd; struct lov_obd *lov = &obd->u.lov; int i, rc = 0, err = 0; - ENTRY; obd_getref(obd); for (i = 0; i < lov->desc.ld_tgt_count; i++) { @@ -167,7 +165,6 @@ static int lov_llog_repl_cancel(const struct lu_env *env, struct lov_obd *lov; struct obd_device *obd = ctxt->loc_obd; int rc = 0, i; - ENTRY; LASSERT(lsm != NULL); LASSERT(count == lsm->lsm_stripe_count); @@ -212,7 +209,6 @@ int lov_llog_init(struct obd_device *obd, struct obd_llog_group *olg, struct lov_obd *lov = &obd->u.lov; struct obd_device *child; int i, rc = 0; - ENTRY; LASSERT(olg == &obd->obd_olg); rc = llog_setup(NULL, obd, olg, LLOG_MDS_OST_ORIG_CTXT, disk_obd, @@ -261,8 +257,6 @@ int lov_llog_finish(struct obd_device *obd, int count) { struct llog_ctxt *ctxt; - ENTRY; - /* cleanup our llogs only if the ctxts have been setup * (client lov doesn't setup, mds lov does). */ ctxt = llog_get_context(obd, LLOG_MDS_OST_ORIG_CTXT); diff --git a/drivers/staging/lustre/lustre/lov/lov_merge.c b/drivers/staging/lustre/lustre/lov/lov_merge.c index ddbac1220263..f062460aaf5c 100644 --- a/drivers/staging/lustre/lustre/lov/lov_merge.c +++ b/drivers/staging/lustre/lustre/lov/lov_merge.c @@ -127,7 +127,6 @@ int lov_merge_lvb(struct obd_export *exp, int rc; __u64 kms; - ENTRY; lov_stripe_lock(lsm); rc = lov_merge_lvb_kms(lsm, lvb, &kms); lov_stripe_unlock(lsm); @@ -147,7 +146,6 @@ int lov_adjust_kms(struct obd_export *exp, struct lov_stripe_md *lsm, struct lov_oinfo *loi; int stripe = 0; __u64 kms; - ENTRY; LASSERT(spin_is_locked(&lsm->lsm_lock)); LASSERT(lsm->lsm_lock_owner == current_pid()); diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c index c7c1a8cc2592..ba5bf1c1f146 100644 --- a/drivers/staging/lustre/lustre/lov/lov_obd.c +++ b/drivers/staging/lustre/lustre/lov/lov_obd.c @@ -133,7 +133,6 @@ int lov_connect_obd(struct obd_device *obd, __u32 index, int activate, struct obd_import *imp; proc_dir_entry_t *lov_proc_dir; int rc; - ENTRY; if (!lov->lov_tgts[index]) RETURN(-EINVAL); @@ -227,7 +226,6 @@ static int lov_connect(const struct lu_env *env, struct lov_tgt_desc *tgt; struct lustre_handle conn; int i, rc; - ENTRY; CDEBUG(D_CONFIG, "connect #%d\n", lov->lov_connects); @@ -279,7 +277,6 @@ static int lov_disconnect_obd(struct obd_device *obd, struct lov_tgt_desc *tgt) struct lov_obd *lov = &obd->u.lov; struct obd_device *osc_obd; int rc; - ENTRY; osc_obd = class_exp2obd(tgt->ltd_exp); CDEBUG(D_CONFIG, "%s: disconnecting target %s\n", @@ -323,7 +320,6 @@ static int lov_disconnect(struct obd_export *exp) struct obd_device *obd = class_exp2obd(exp); struct lov_obd *lov = &obd->u.lov; int i, rc; - ENTRY; if (!lov->lov_tgts) goto out; @@ -366,7 +362,6 @@ static int lov_set_osc_active(struct obd_device *obd, struct obd_uuid *uuid, struct lov_obd *lov = &obd->u.lov; struct lov_tgt_desc *tgt; int index, activate, active; - ENTRY; CDEBUG(D_INFO, "Searching in lov %p for uuid %s event(%d)\n", lov, uuid->uuid, ev); @@ -446,7 +441,6 @@ static int lov_notify(struct obd_device *obd, struct obd_device *watched, { int rc = 0; struct lov_obd *lov = &obd->u.lov; - ENTRY; down_read(&lov->lov_notify_lock); if (!lov->lov_connects) { @@ -530,7 +524,6 @@ static int lov_add_target(struct obd_device *obd, struct obd_uuid *uuidp, struct lov_tgt_desc *tgt; struct obd_device *tgt_obd; int rc; - ENTRY; CDEBUG(D_CONFIG, "uuid:%s idx:%d gen:%d active:%d\n", uuidp->uuid, index, gen, active); @@ -664,7 +657,6 @@ int lov_del_target(struct obd_device *obd, __u32 index, struct lov_obd *lov = &obd->u.lov; int count = lov->desc.ld_tgt_count; int rc = 0; - ENTRY; if (index >= count) { CERROR("LOV target index %d >= number of LOV OBDs %d.\n", @@ -780,7 +772,6 @@ int lov_setup(struct obd_device *obd, struct lustre_cfg *lcfg) struct lov_desc *desc; struct lov_obd *lov = &obd->u.lov; int rc; - ENTRY; if (LUSTRE_CFG_BUFLEN(lcfg, 1) < 1) { CERROR("LOV setup requires a descriptor\n"); @@ -859,8 +850,6 @@ static int lov_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage) int rc = 0; struct lov_obd *lov = &obd->u.lov; - ENTRY; - switch (stage) { case OBD_CLEANUP_EARLY: { int i; @@ -886,7 +875,6 @@ static int lov_cleanup(struct obd_device *obd) struct lov_obd *lov = &obd->u.lov; struct list_head *pos, *tmp; struct pool_desc *pool; - ENTRY; list_for_each_safe(pos, tmp, &lov->lov_pool_list) { pool = list_entry(pos, struct pool_desc, pool_list); @@ -934,7 +922,6 @@ int lov_process_config_base(struct obd_device *obd, struct lustre_cfg *lcfg, struct obd_uuid obd_uuid; int cmd; int rc = 0; - ENTRY; switch(cmd = lcfg->lcfg_command) { case LCFG_LOV_ADD_OBD: @@ -1000,7 +987,6 @@ static int lov_recreate(struct obd_export *exp, struct obdo *src_oa, struct lov_obd *lov = &exp->exp_obd->u.lov; unsigned ost_idx; int rc, i; - ENTRY; LASSERT(src_oa->o_valid & OBD_MD_FLFLAGS && src_oa->o_flags & OBD_FL_RECREATE_OBJS); @@ -1042,7 +1028,6 @@ static int lov_create(const struct lu_env *env, struct obd_export *exp, { struct lov_obd *lov; int rc = 0; - ENTRY; LASSERT(ea != NULL); if (exp == NULL) @@ -1088,7 +1073,6 @@ static int lov_destroy(const struct lu_env *env, struct obd_export *exp, struct list_head *pos; struct lov_obd *lov; int rc = 0, err = 0; - ENTRY; ASSERT_LSM_MAGIC(lsm); @@ -1144,7 +1128,6 @@ static int lov_getattr(const struct lu_env *env, struct obd_export *exp, struct list_head *pos; struct lov_obd *lov; int err = 0, rc = 0; - ENTRY; LASSERT(oinfo); ASSERT_LSM_MAGIC(oinfo->oi_md); @@ -1190,7 +1173,6 @@ static int lov_getattr_interpret(struct ptlrpc_request_set *rqset, { struct lov_request_set *lovset = (struct lov_request_set *)data; int err; - ENTRY; /* don't do attribute merge if this aysnc op failed */ if (rc) @@ -1207,7 +1189,6 @@ static int lov_getattr_async(struct obd_export *exp, struct obd_info *oinfo, struct list_head *pos; struct lov_request *req; int rc = 0, err; - ENTRY; LASSERT(oinfo); ASSERT_LSM_MAGIC(oinfo->oi_md); @@ -1266,7 +1247,6 @@ static int lov_setattr(const struct lu_env *env, struct obd_export *exp, struct list_head *pos; struct lov_request *req; int err = 0, rc = 0; - ENTRY; LASSERT(oinfo); ASSERT_LSM_MAGIC(oinfo->oi_md); @@ -1315,7 +1295,6 @@ static int lov_setattr_interpret(struct ptlrpc_request_set *rqset, { struct lov_request_set *lovset = (struct lov_request_set *)data; int err; - ENTRY; if (rc) atomic_set(&lovset->set_completes, 0); @@ -1334,7 +1313,6 @@ static int lov_setattr_async(struct obd_export *exp, struct obd_info *oinfo, struct list_head *pos; struct lov_obd *lov; int rc = 0; - ENTRY; LASSERT(oinfo); ASSERT_LSM_MAGIC(oinfo->oi_md); @@ -1399,7 +1377,6 @@ static int lov_punch_interpret(struct ptlrpc_request_set *rqset, { struct lov_request_set *lovset = (struct lov_request_set *)data; int err; - ENTRY; if (rc) atomic_set(&lovset->set_completes, 0); @@ -1419,7 +1396,6 @@ static int lov_punch(const struct lu_env *env, struct obd_export *exp, struct list_head *pos; struct lov_request *req; int rc = 0; - ENTRY; LASSERT(oinfo); ASSERT_LSM_MAGIC(oinfo->oi_md); @@ -1465,7 +1441,6 @@ static int lov_sync_interpret(struct ptlrpc_request_set *rqset, { struct lov_request_set *lovset = data; int err; - ENTRY; if (rc) atomic_set(&lovset->set_completes, 0); @@ -1482,7 +1457,6 @@ static int lov_sync(const struct lu_env *env, struct obd_export *exp, struct list_head *pos; struct lov_request *req; int rc = 0; - ENTRY; ASSERT_LSM_MAGIC(oinfo->oi_md); LASSERT(rqset != NULL); @@ -1571,7 +1545,6 @@ static int lov_brw(int cmd, struct obd_export *exp, struct obd_info *oinfo, struct list_head *pos; struct lov_obd *lov = &exp->exp_obd->u.lov; int err, rc = 0; - ENTRY; ASSERT_LSM_MAGIC(oinfo->oi_md); @@ -1608,7 +1581,7 @@ static int lov_enqueue_interpret(struct ptlrpc_request_set *rqset, void *data, int rc) { struct lov_request_set *lovset = (struct lov_request_set *)data; - ENTRY; + rc = lov_fini_enqueue_set(lovset, lovset->set_ei->ei_mode, rc, rqset); RETURN(rc); } @@ -1623,7 +1596,6 @@ static int lov_enqueue(struct obd_export *exp, struct obd_info *oinfo, struct list_head *pos; struct lov_obd *lov; ldlm_error_t rc; - ENTRY; LASSERT(oinfo); ASSERT_LSM_MAGIC(oinfo->oi_md); @@ -1667,7 +1639,6 @@ static int lov_change_cbdata(struct obd_export *exp, { struct lov_obd *lov; int rc = 0, i; - ENTRY; ASSERT_LSM_MAGIC(lsm); @@ -1702,7 +1673,6 @@ static int lov_find_cbdata(struct obd_export *exp, { struct lov_obd *lov; int rc = 0, i; - ENTRY; ASSERT_LSM_MAGIC(lsm); @@ -1738,7 +1708,6 @@ static int lov_cancel(struct obd_export *exp, struct lov_stripe_md *lsm, struct lov_obd *lov; struct lustre_handle *lov_lockhp; int err = 0, rc = 0; - ENTRY; ASSERT_LSM_MAGIC(lsm); @@ -1778,7 +1747,6 @@ static int lov_cancel_unused(struct obd_export *exp, { struct lov_obd *lov; int rc = 0, i; - ENTRY; if (!exp || !exp->exp_obd) RETURN(-ENODEV); @@ -1834,7 +1802,6 @@ int lov_statfs_interpret(struct ptlrpc_request_set *rqset, void *data, int rc) { struct lov_request_set *lovset = (struct lov_request_set *)data; int err; - ENTRY; if (rc) atomic_set(&lovset->set_completes, 0); @@ -1852,7 +1819,6 @@ static int lov_statfs_async(struct obd_export *exp, struct obd_info *oinfo, struct list_head *pos; struct lov_obd *lov; int rc = 0; - ENTRY; LASSERT(oinfo != NULL); LASSERT(oinfo->oi_osfs != NULL); @@ -1890,8 +1856,6 @@ static int lov_statfs(const struct lu_env *env, struct obd_export *exp, struct ptlrpc_request_set *set = NULL; struct obd_info oinfo = { { { 0 } } }; int rc = 0; - ENTRY; - /* for obdclass we forbid using obd_statfs_rqset, but prefer using async * statfs requests */ @@ -1916,7 +1880,6 @@ static int lov_iocontrol(unsigned int cmd, struct obd_export *exp, int len, struct lov_obd *lov = &obddev->u.lov; int i = 0, rc = 0, count = lov->desc.ld_tgt_count; struct obd_uuid *uuidp; - ENTRY; switch (cmd) { case IOC_OBD_STATFS: { @@ -2469,7 +2432,6 @@ static int lov_get_info(const struct lu_env *env, struct obd_export *exp, struct obd_device *obddev = class_exp2obd(exp); struct lov_obd *lov = &obddev->u.lov; int i, rc; - ENTRY; if (!vallen || !val) RETURN(-EFAULT); @@ -2568,7 +2530,6 @@ static int lov_set_info_async(const struct lu_env *env, struct obd_export *exp, unsigned incr, check_uuid, do_inactive, no_set; unsigned next_id = 0, mds_con = 0, capa = 0; - ENTRY; incr = check_uuid = do_inactive = no_set = 0; if (set == NULL) { @@ -2719,7 +2680,6 @@ static int lov_quotactl(struct obd_device *obd, struct obd_export *exp, __u64 curspace = 0; __u64 bhardlimit = 0; int i, rc = 0; - ENTRY; if (oqctl->qc_cmd != LUSTRE_Q_QUOTAON && oqctl->qc_cmd != LUSTRE_Q_QUOTAOFF && @@ -2778,7 +2738,6 @@ static int lov_quotacheck(struct obd_device *obd, struct obd_export *exp, { struct lov_obd *lov = &obd->u.lov; int i, rc = 0; - ENTRY; obd_getref(obd); @@ -2870,7 +2829,6 @@ int __init lov_init(void) { struct lprocfs_static_vars lvars = { 0 }; int rc; - ENTRY; /* print an address of _any_ initialized kernel symbol from this * module, to allow debugging with gdb that doesn't support data diff --git a/drivers/staging/lustre/lustre/lov/lov_object.c b/drivers/staging/lustre/lustre/lov/lov_object.c index e7cc6502237f..3bf8c0c08b6b 100644 --- a/drivers/staging/lustre/lustre/lov/lov_object.c +++ b/drivers/staging/lustre/lustre/lov/lov_object.c @@ -116,7 +116,6 @@ static struct cl_object *lov_sub_find(const struct lu_env *env, { struct lu_object *o; - ENTRY; o = lu_object_find_at(env, cl2lu_dev(dev), fid, &conf->coc_lu); LASSERT(ergo(!IS_ERR(o), o->lo_dev->ld_type == &lovsub_device_type)); RETURN(lu2cl(o)); @@ -204,8 +203,6 @@ static int lov_init_raid0(const struct lu_env *env, struct lu_fid *ofid = <i->lti_fid; struct lov_layout_raid0 *r0 = &state->raid0; - ENTRY; - if (lsm->lsm_magic != LOV_MAGIC_V1 && lsm->lsm_magic != LOV_MAGIC_V3) { dump_lsm(D_ERROR, lsm); LASSERTF(0, "magic mismatch, expected %d/%d, actual %d.\n", @@ -338,8 +335,6 @@ static int lov_delete_raid0(const struct lu_env *env, struct lov_object *lov, struct lov_stripe_md *lsm = lov->lo_lsm; int i; - ENTRY; - dump_lsm(D_INODE, lsm); lov_layout_wait(env, lov); @@ -371,7 +366,6 @@ static void lov_fini_raid0(const struct lu_env *env, struct lov_object *lov, union lov_layout_state *state) { struct lov_layout_raid0 *r0 = &state->raid0; - ENTRY; if (r0->lo_sub != NULL) { OBD_FREE_LARGE(r0->lo_sub, r0->lo_nr * sizeof r0->lo_sub[0]); @@ -387,7 +381,6 @@ static void lov_fini_raid0(const struct lu_env *env, struct lov_object *lov, static void lov_fini_released(const struct lu_env *env, struct lov_object *lov, union lov_layout_state *state) { - ENTRY; dump_lsm(D_INODE, lov->lo_lsm); lov_free_memmd(&lov->lo_lsm); EXIT; @@ -453,8 +446,6 @@ static int lov_attr_get_raid0(const struct lu_env *env, struct cl_object *obj, struct cl_attr *lov_attr = &r0->lo_attr; int result = 0; - ENTRY; - /* this is called w/o holding type guard mutex, so it must be inside * an on going IO otherwise lsm may be replaced. * LU-2117: it turns out there exists one exception. For mmaped files, @@ -634,7 +625,6 @@ static void lov_conf_unlock(struct lov_object *lov) static int lov_layout_wait(const struct lu_env *env, struct lov_object *lov) { struct l_wait_info lwi = { 0 }; - ENTRY; while (atomic_read(&lov->lo_active_ios) > 0) { CDEBUG(D_INODE, "file:"DFID" wait for active IO, now: %d.\n", @@ -661,7 +651,6 @@ static int lov_layout_change(const struct lu_env *unused, void *cookie; struct lu_env *env; int refcheck; - ENTRY; LASSERT(0 <= lov->lo_type && lov->lo_type < ARRAY_SIZE(lov_dispatch)); @@ -721,7 +710,6 @@ int lov_object_init(const struct lu_env *env, struct lu_object *obj, const struct lov_layout_operations *ops; int result; - ENTRY; init_rwsem(&lov->lo_type_guard); atomic_set(&lov->lo_active_ios, 0); init_waitqueue_head(&lov->lo_waitq); @@ -743,7 +731,6 @@ static int lov_conf_set(const struct lu_env *env, struct cl_object *obj, struct lov_stripe_md *lsm = NULL; struct lov_object *lov = cl2lov(obj); int result = 0; - ENTRY; lov_conf_lock(lov); if (conf->coc_opc == OBJECT_CONF_INVALIDATE) { @@ -791,7 +778,6 @@ static void lov_object_delete(const struct lu_env *env, struct lu_object *obj) { struct lov_object *lov = lu2lov(obj); - ENTRY; LOV_2DISPATCH_VOID(lov, llo_delete, env, lov, &lov->u); EXIT; } @@ -800,7 +786,6 @@ static void lov_object_free(const struct lu_env *env, struct lu_object *obj) { struct lov_object *lov = lu2lov(obj); - ENTRY; LOV_2DISPATCH_VOID(lov, llo_fini, env, lov, &lov->u); lu_object_fini(obj); OBD_SLAB_FREE_PTR(lov, lov_object_kmem); @@ -887,7 +872,6 @@ struct lu_object *lov_object_alloc(const struct lu_env *env, struct lov_object *lov; struct lu_object *obj; - ENTRY; OBD_SLAB_ALLOC_PTR_GFP(lov, lov_object_kmem, __GFP_IO); if (lov != NULL) { obj = lov2lu(lov); @@ -958,7 +942,6 @@ int lov_read_and_clear_async_rc(struct cl_object *clob) { struct lu_object *luobj; int rc = 0; - ENTRY; luobj = lu_object_locate(&cl_object_header(clob)->coh_lu, &lov_device_type); diff --git a/drivers/staging/lustre/lustre/lov/lov_offset.c b/drivers/staging/lustre/lustre/lov/lov_offset.c index f62b7e53b665..079ad5c90566 100644 --- a/drivers/staging/lustre/lustre/lov/lov_offset.c +++ b/drivers/staging/lustre/lustre/lov/lov_offset.c @@ -52,7 +52,6 @@ obd_size lov_stripe_size(struct lov_stripe_md *lsm, obd_size ost_size, obd_off swidth; obd_size lov_size; int magic = lsm->lsm_magic; - ENTRY; if (ost_size == 0) RETURN(0); diff --git a/drivers/staging/lustre/lustre/lov/lov_pack.c b/drivers/staging/lustre/lustre/lov/lov_pack.c index 9c99e4a2c5d8..5edcf8e28c0e 100644 --- a/drivers/staging/lustre/lustre/lov/lov_pack.c +++ b/drivers/staging/lustre/lustre/lov/lov_pack.c @@ -143,7 +143,6 @@ int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmmp, int lmm_size, lmm_magic; int i; int cplen = 0; - ENTRY; if (lsm) { lmm_magic = lsm->lsm_magic; @@ -309,7 +308,6 @@ int lov_alloc_memmd(struct lov_stripe_md **lsmp, __u16 stripe_count, int pattern, int magic) { int i, lsm_size; - ENTRY; CDEBUG(D_INFO, "alloc lsm, stripe_count %d\n", stripe_count); @@ -363,7 +361,6 @@ int lov_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, __u16 stripe_count; __u32 magic; __u32 pattern; - ENTRY; /* If passed an MDS struct use values from there, otherwise defaults */ if (lmm) { @@ -420,7 +417,6 @@ static int __lov_setstripe(struct obd_export *exp, int max_lmm_size, __u16 stripe_count; int rc; int cplen = 0; - ENTRY; rc = lov_lum_swab_if_needed(lumv3, &lmm_magic, lump); if (rc) @@ -546,8 +542,6 @@ int lov_setea(struct obd_export *exp, struct lov_stripe_md **lsmp, obd_id last_id = 0; struct lov_user_ost_data_v1 *lmm_objects; - ENTRY; - if (lump->lmm_magic == LOV_USER_MAGIC_V3) lmm_objects = ((struct lov_user_md_v3 *)lump)->lmm_objects; else @@ -600,7 +594,6 @@ int lov_getstripe(struct obd_export *exp, struct lov_stripe_md *lsm, int rc, lmm_size; int lum_size; mm_segment_t seg; - ENTRY; if (!lsm) RETURN(-ENODATA); diff --git a/drivers/staging/lustre/lustre/lov/lov_page.c b/drivers/staging/lustre/lustre/lov/lov_page.c index 65790d684720..f8b364f1e632 100644 --- a/drivers/staging/lustre/lustre/lov/lov_page.c +++ b/drivers/staging/lustre/lustre/lov/lov_page.c @@ -69,7 +69,6 @@ static void lov_page_fini(const struct lu_env *env, struct cl_page *sub = lov_sub_page(slice); LINVRNT(lov_page_invariant(slice)); - ENTRY; if (sub != NULL) { LASSERT(sub->cp_state == CPS_FREEING); @@ -90,7 +89,6 @@ static int lov_page_own(const struct lu_env *env, LINVRNT(lov_page_invariant(slice)); LINVRNT(!cl2lov_page(slice)->lps_invalid); - ENTRY; sub = lov_page_subio(env, lio, slice); if (!IS_ERR(sub)) { @@ -117,7 +115,6 @@ static int lov_page_cache_add(const struct lu_env *env, LINVRNT(lov_page_invariant(slice)); LINVRNT(!cl2lov_page(slice)->lps_invalid); - ENTRY; sub = lov_page_subio(env, lio, slice); if (!IS_ERR(sub)) { @@ -172,7 +169,6 @@ int lov_page_init_raid0(const struct lu_env *env, struct cl_object *obj, obd_off suboff; int stripe; int rc; - ENTRY; offset = cl_offset(obj, page->cp_index); stripe = lov_stripe_number(loo->lo_lsm, offset); @@ -221,7 +217,6 @@ int lov_page_init_empty(const struct lu_env *env, struct cl_object *obj, { struct lov_page *lpg = cl_object_page_slice(obj, page); void *addr; - ENTRY; cl_page_slice_add(page, &lpg->lps_cl, obj, &lov_empty_page_ops); addr = kmap(vmpage); diff --git a/drivers/staging/lustre/lustre/lov/lov_pool.c b/drivers/staging/lustre/lustre/lov/lov_pool.c index a96f90880c64..63b94661702e 100644 --- a/drivers/staging/lustre/lustre/lov/lov_pool.c +++ b/drivers/staging/lustre/lustre/lov/lov_pool.c @@ -322,8 +322,6 @@ void lov_dump_pool(int level, struct pool_desc *pool) #define LOV_POOL_INIT_COUNT 2 int lov_ost_pool_init(struct ost_pool *op, unsigned int count) { - ENTRY; - if (count == 0) count = LOV_POOL_INIT_COUNT; op->op_array = NULL; @@ -366,7 +364,6 @@ int lov_ost_pool_extend(struct ost_pool *op, unsigned int min_count) int lov_ost_pool_add(struct ost_pool *op, __u32 idx, unsigned int min_count) { int rc = 0, i; - ENTRY; down_write(&op->op_rw_sem); @@ -391,7 +388,6 @@ out: int lov_ost_pool_remove(struct ost_pool *op, __u32 idx) { int i; - ENTRY; down_write(&op->op_rw_sem); @@ -412,8 +408,6 @@ int lov_ost_pool_remove(struct ost_pool *op, __u32 idx) int lov_ost_pool_free(struct ost_pool *op) { - ENTRY; - if (op->op_size == 0) RETURN(0); @@ -434,7 +428,6 @@ int lov_pool_new(struct obd_device *obd, char *poolname) struct lov_obd *lov; struct pool_desc *new_pool; int rc; - ENTRY; lov = &(obd->u.lov); @@ -513,7 +506,6 @@ int lov_pool_del(struct obd_device *obd, char *poolname) { struct lov_obd *lov; struct pool_desc *pool; - ENTRY; lov = &(obd->u.lov); @@ -547,7 +539,6 @@ int lov_pool_add(struct obd_device *obd, char *poolname, char *ostname) struct pool_desc *pool; unsigned int lov_idx; int rc; - ENTRY; lov = &(obd->u.lov); @@ -594,7 +585,6 @@ int lov_pool_remove(struct obd_device *obd, char *poolname, char *ostname) struct pool_desc *pool; unsigned int lov_idx; int rc = 0; - ENTRY; lov = &(obd->u.lov); @@ -636,7 +626,6 @@ out: int lov_check_index_in_pool(__u32 idx, struct pool_desc *pool) { int i, rc; - ENTRY; /* caller may no have a ref on pool if it got the pool * without calling lov_find_pool() (e.g. go through the lov pool diff --git a/drivers/staging/lustre/lustre/lov/lov_request.c b/drivers/staging/lustre/lustre/lov/lov_request.c index 13f1637bc700..fc1cd898f5c9 100644 --- a/drivers/staging/lustre/lustre/lov/lov_request.c +++ b/drivers/staging/lustre/lustre/lov/lov_request.c @@ -60,7 +60,6 @@ static void lov_init_set(struct lov_request_set *set) void lov_finish_set(struct lov_request_set *set) { struct list_head *pos, *n; - ENTRY; LASSERT(set); list_for_each_safe(pos, n, &set->set_list) { @@ -122,7 +121,6 @@ int lov_update_common_set(struct lov_request_set *set, struct lov_request *req, int rc) { struct lov_obd *lov = &set->set_exp->exp_obd->u.lov; - ENTRY; lov_update_set(set, req, rc); @@ -232,7 +230,6 @@ int lov_update_enqueue_set(struct lov_request *req, __u32 mode, int rc) struct lustre_handle *lov_lockhp; struct obd_info *oi = set->set_oi; struct lov_oinfo *loi; - ENTRY; LASSERT(oi != NULL); @@ -275,7 +272,6 @@ static int enqueue_done(struct lov_request_set *set, __u32 mode) struct lov_obd *lov = &set->set_exp->exp_obd->u.lov; int completes = atomic_read(&set->set_completes); int rc = 0; - ENTRY; /* enqueue/match success, just return */ if (completes && completes == atomic_read(&set->set_success)) @@ -312,7 +308,6 @@ int lov_fini_enqueue_set(struct lov_request_set *set, __u32 mode, int rc, struct ptlrpc_request_set *rqset) { int ret = 0; - ENTRY; if (set == NULL) RETURN(0); @@ -369,7 +364,6 @@ int lov_prep_enqueue_set(struct obd_export *exp, struct obd_info *oinfo, struct lov_obd *lov = &exp->exp_obd->u.lov; struct lov_request_set *set; int i, rc = 0; - ENTRY; OBD_ALLOC(set, sizeof(*set)); if (set == NULL) @@ -454,7 +448,6 @@ out_set: int lov_fini_match_set(struct lov_request_set *set, __u32 mode, int flags) { int rc = 0; - ENTRY; if (set == NULL) RETURN(0); @@ -477,7 +470,6 @@ int lov_prep_match_set(struct obd_export *exp, struct obd_info *oinfo, struct lov_obd *lov = &exp->exp_obd->u.lov; struct lov_request_set *set; int i, rc = 0; - ENTRY; OBD_ALLOC(set, sizeof(*set)); if (set == NULL) @@ -544,7 +536,6 @@ out_set: int lov_fini_cancel_set(struct lov_request_set *set) { int rc = 0; - ENTRY; if (set == NULL) RETURN(0); @@ -565,7 +556,6 @@ int lov_prep_cancel_set(struct obd_export *exp, struct obd_info *oinfo, { struct lov_request_set *set; int i, rc = 0; - ENTRY; OBD_ALLOC(set, sizeof(*set)); if (set == NULL) @@ -628,7 +618,6 @@ static int common_attr_done(struct lov_request_set *set) struct lov_request *req; struct obdo *tmp_oa; int rc = 0, attrset = 0; - ENTRY; LASSERT(set->set_oi != NULL); @@ -680,7 +669,6 @@ static int brw_done(struct lov_request_set *set) struct lov_oinfo *loi = NULL; struct list_head *pos; struct lov_request *req; - ENTRY; list_for_each (pos, &set->set_list) { req = list_entry(pos, struct lov_request, rq_link); @@ -700,7 +688,6 @@ static int brw_done(struct lov_request_set *set) int lov_fini_brw_set(struct lov_request_set *set) { int rc = 0; - ENTRY; if (set == NULL) RETURN(0); @@ -727,7 +714,6 @@ int lov_prep_brw_set(struct obd_export *exp, struct obd_info *oinfo, struct lov_request_set *set; struct lov_obd *lov = &exp->exp_obd->u.lov; int rc = 0, i, shift; - ENTRY; OBD_ALLOC(set, sizeof(*set)); if (set == NULL) @@ -838,7 +824,6 @@ out: int lov_fini_getattr_set(struct lov_request_set *set) { int rc = 0; - ENTRY; if (set == NULL) RETURN(0); @@ -867,7 +852,6 @@ int lov_prep_getattr_set(struct obd_export *exp, struct obd_info *oinfo, struct lov_request_set *set; struct lov_obd *lov = &exp->exp_obd->u.lov; int rc = 0, i; - ENTRY; OBD_ALLOC(set, sizeof(*set)); if (set == NULL) @@ -921,8 +905,6 @@ out_set: int lov_fini_destroy_set(struct lov_request_set *set) { - ENTRY; - if (set == NULL) RETURN(0); LASSERT(set->set_exp); @@ -943,7 +925,6 @@ int lov_prep_destroy_set(struct obd_export *exp, struct obd_info *oinfo, struct lov_request_set *set; struct lov_obd *lov = &exp->exp_obd->u.lov; int rc = 0, i; - ENTRY; OBD_ALLOC(set, sizeof(*set)); if (set == NULL) @@ -996,7 +977,6 @@ out_set: int lov_fini_setattr_set(struct lov_request_set *set) { int rc = 0; - ENTRY; if (set == NULL) RETURN(0); @@ -1015,7 +995,6 @@ int lov_update_setattr_set(struct lov_request_set *set, { struct lov_obd *lov = &req->rq_rqset->set_exp->exp_obd->u.lov; struct lov_stripe_md *lsm = req->rq_rqset->set_oi->oi_md; - ENTRY; lov_update_set(set, req, rc); @@ -1056,7 +1035,6 @@ int lov_prep_setattr_set(struct obd_export *exp, struct obd_info *oinfo, struct lov_request_set *set; struct lov_obd *lov = &exp->exp_obd->u.lov; int rc = 0, i; - ENTRY; OBD_ALLOC(set, sizeof(*set)); if (set == NULL) @@ -1122,7 +1100,6 @@ out_set: int lov_fini_punch_set(struct lov_request_set *set) { int rc = 0; - ENTRY; if (set == NULL) RETURN(0); @@ -1144,7 +1121,6 @@ int lov_update_punch_set(struct lov_request_set *set, { struct lov_obd *lov = &req->rq_rqset->set_exp->exp_obd->u.lov; struct lov_stripe_md *lsm = req->rq_rqset->set_oi->oi_md; - ENTRY; lov_update_set(set, req, rc); @@ -1182,7 +1158,6 @@ int lov_prep_punch_set(struct obd_export *exp, struct obd_info *oinfo, struct lov_request_set *set; struct lov_obd *lov = &exp->exp_obd->u.lov; int rc = 0, i; - ENTRY; OBD_ALLOC(set, sizeof(*set)); if (set == NULL) @@ -1247,7 +1222,6 @@ out_set: int lov_fini_sync_set(struct lov_request_set *set) { int rc = 0; - ENTRY; if (set == NULL) RETURN(0); @@ -1281,7 +1255,6 @@ int lov_prep_sync_set(struct obd_export *exp, struct obd_info *oinfo, struct lov_request_set *set; struct lov_obd *lov = &exp->exp_obd->u.lov; int rc = 0, i; - ENTRY; OBD_ALLOC_PTR(set); if (set == NULL) @@ -1347,8 +1320,6 @@ out_set: int lov_fini_statfs(struct obd_device *obd, struct obd_statfs *osfs,int success) { - ENTRY; - if (success) { __u32 expected_stripes = lov_get_stripecnt(&obd->u.lov, LOV_MAGIC, 0); @@ -1370,7 +1341,6 @@ int lov_fini_statfs(struct obd_device *obd, struct obd_statfs *osfs,int success) int lov_fini_statfs_set(struct lov_request_set *set) { int rc = 0; - ENTRY; if (set == NULL) RETURN(0); @@ -1450,7 +1420,6 @@ static int cb_statfs_update(void *cookie, int rc) struct lov_tgt_desc *tgt; struct obd_device *lovobd, *tgtobd; int success; - ENTRY; lovreq = container_of(oinfo, struct lov_request, rq_oi); set = lovreq->rq_rqset; @@ -1497,7 +1466,6 @@ int lov_prep_statfs_set(struct obd_device *obd, struct obd_info *oinfo, struct lov_request_set *set; struct lov_obd *lov = &obd->u.lov; int rc = 0, i; - ENTRY; OBD_ALLOC(set, sizeof(*set)); if (set == NULL) diff --git a/drivers/staging/lustre/lustre/lov/lovsub_dev.c b/drivers/staging/lustre/lustre/lov/lovsub_dev.c index 204ecd0b8639..05ad75e210d5 100644 --- a/drivers/staging/lustre/lustre/lov/lovsub_dev.c +++ b/drivers/staging/lustre/lustre/lov/lovsub_dev.c @@ -55,7 +55,6 @@ static void lovsub_req_completion(const struct lu_env *env, { struct lovsub_req *lsr; - ENTRY; lsr = cl2lovsub_req(slice); OBD_SLAB_FREE_PTR(lsr, lovsub_req_kmem); EXIT; @@ -73,7 +72,6 @@ static void lovsub_req_attr_set(const struct lu_env *env, { struct lovsub_object *subobj; - ENTRY; subobj = cl2lovsub(obj); /* * There is no OBD_MD_* flag for obdo::o_stripe_idx, so set it @@ -101,7 +99,6 @@ static int lovsub_device_init(const struct lu_env *env, struct lu_device *d, struct lu_device_type *ldt; int rc; - ENTRY; next->ld_site = d->ld_site; ldt = next->ld_type; LASSERT(ldt != NULL); @@ -123,7 +120,6 @@ static struct lu_device *lovsub_device_fini(const struct lu_env *env, struct lu_device *next; struct lovsub_device *lsd; - ENTRY; lsd = lu2lovsub_dev(d); next = cl2lu_dev(lsd->acid_next); lsd->acid_super = NULL; diff --git a/drivers/staging/lustre/lustre/lov/lovsub_lock.c b/drivers/staging/lustre/lustre/lov/lovsub_lock.c index 03bab17ccc64..b73ad7a96669 100644 --- a/drivers/staging/lustre/lustre/lov/lovsub_lock.c +++ b/drivers/staging/lustre/lustre/lov/lovsub_lock.c @@ -57,7 +57,6 @@ static void lovsub_lock_fini(const struct lu_env *env, { struct lovsub_lock *lsl; - ENTRY; lsl = cl2lovsub_lock(slice); LASSERT(list_empty(&lsl->lss_parents)); OBD_SLAB_FREE_PTR(lsl, lovsub_lock_kmem); @@ -68,7 +67,6 @@ static void lovsub_parent_lock(const struct lu_env *env, struct lov_lock *lov) { struct cl_lock *parent; - ENTRY; parent = lov->lls_cl.cls_lock; cl_lock_get(parent); lu_ref_add(&parent->cll_reference, "lovsub-parent", current); @@ -80,7 +78,6 @@ static void lovsub_parent_unlock(const struct lu_env *env, struct lov_lock *lov) { struct cl_lock *parent; - ENTRY; parent = lov->lls_cl.cls_lock; cl_lock_mutex_put(env, lov->lls_cl.cls_lock); lu_ref_del(&parent->cll_reference, "lovsub-parent", current); @@ -101,7 +98,6 @@ static void lovsub_lock_state(const struct lu_env *env, struct lov_lock_link *scan; LASSERT(cl_lock_is_mutexed(slice->cls_lock)); - ENTRY; list_for_each_entry(scan, &sub->lss_parents, lll_list) { struct lov_lock *lov = scan->lll_super; @@ -127,8 +123,6 @@ static unsigned long lovsub_lock_weigh(const struct lu_env *env, struct lov_lock *lov; unsigned long dumbbell; - ENTRY; - LASSERT(cl_lock_is_mutexed(slice->cls_lock)); if (!list_empty(&lock->lss_parents)) { @@ -162,7 +156,6 @@ static void lovsub_lock_descr_map(const struct cl_lock_descr *in, pgoff_t start; pgoff_t end; - ENTRY; start = in->cld_start; end = in->cld_end; @@ -241,8 +234,6 @@ static int lovsub_lock_modify(const struct lu_env *env, struct lov_lock *lov; int result = 0; - ENTRY; - LASSERT(cl_lock_mode_match(d->cld_mode, s->cls_lock->cll_descr.cld_mode)); list_for_each_entry(scan, &lock->lss_parents, lll_list) { @@ -267,7 +258,6 @@ static int lovsub_lock_closure(const struct lu_env *env, int result; LASSERT(cl_lock_is_mutexed(slice->cls_lock)); - ENTRY; sub = cl2lovsub_lock(slice); result = 0; @@ -290,7 +280,6 @@ static int lovsub_lock_delete_one(const struct lu_env *env, { struct cl_lock *parent; int result; - ENTRY; parent = lov->lls_cl.cls_lock; if (parent->cll_error) @@ -403,7 +392,6 @@ static void lovsub_lock_delete(const struct lu_env *env, LASSERT(cl_lock_is_mutexed(child)); - ENTRY; /* * Destruction of a sub-lock might take multiple iterations, because * when the last sub-lock of a given top-lock is deleted, top-lock is @@ -471,7 +459,6 @@ int lovsub_lock_init(const struct lu_env *env, struct cl_object *obj, struct lovsub_lock *lsk; int result; - ENTRY; OBD_SLAB_ALLOC_PTR_GFP(lsk, lovsub_lock_kmem, __GFP_IO); if (lsk != NULL) { INIT_LIST_HEAD(&lsk->lss_parents); diff --git a/drivers/staging/lustre/lustre/lov/lovsub_object.c b/drivers/staging/lustre/lustre/lov/lovsub_object.c index 1b83d9081c40..7264ba31b9e6 100644 --- a/drivers/staging/lustre/lustre/lov/lovsub_object.c +++ b/drivers/staging/lustre/lustre/lov/lovsub_object.c @@ -61,7 +61,6 @@ int lovsub_object_init(const struct lu_env *env, struct lu_object *obj, int result; - ENTRY; under = &dev->acid_next->cd_lu_dev; below = under->ld_ops->ldo_object_alloc(env, obj->lo_header, under); if (below != NULL) { @@ -78,7 +77,6 @@ static void lovsub_object_free(const struct lu_env *env, struct lu_object *obj) { struct lovsub_object *los = lu2lovsub(obj); struct lov_object *lov = los->lso_super; - ENTRY; /* We can't assume lov was assigned here, because of the shadow * object handling in lu_object_find. @@ -110,7 +108,6 @@ static int lovsub_attr_set(const struct lu_env *env, struct cl_object *obj, { struct lov_object *lov = cl2lovsub(obj)->lso_super; - ENTRY; lov_r0(lov)->lo_attr_valid = 0; RETURN(0); } @@ -121,7 +118,6 @@ static int lovsub_object_glimpse(const struct lu_env *env, { struct lovsub_object *los = cl2lovsub(obj); - ENTRY; RETURN(cl_object_glimpse(env, &los->lso_super->lo_cl, lvb)); } @@ -150,7 +146,6 @@ struct lu_object *lovsub_object_alloc(const struct lu_env *env, struct lovsub_object *los; struct lu_object *obj; - ENTRY; OBD_SLAB_ALLOC_PTR_GFP(los, lovsub_object_kmem, __GFP_IO); if (los != NULL) { struct cl_object_header *hdr; diff --git a/drivers/staging/lustre/lustre/lov/lovsub_page.c b/drivers/staging/lustre/lustre/lov/lovsub_page.c index bc9e683968da..3a738eca5692 100644 --- a/drivers/staging/lustre/lustre/lov/lovsub_page.c +++ b/drivers/staging/lustre/lustre/lov/lovsub_page.c @@ -63,7 +63,6 @@ int lovsub_page_init(const struct lu_env *env, struct cl_object *obj, struct cl_page *page, struct page *unused) { struct lovsub_page *lsb = cl_object_page_slice(obj, page); - ENTRY; cl_page_slice_add(page, &lsb->lsb_cl, obj, &lovsub_page_ops); RETURN(0); diff --git a/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c b/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c index d342e976317b..71f62695b926 100644 --- a/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c +++ b/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c @@ -203,7 +203,6 @@ int lustre_rename(struct dentry *dir, struct vfsmount *mnt, { struct dentry *dchild_old, *dchild_new; int err = 0; - ENTRY; ASSERT_KERNEL_CTXT("kernel doing rename outside kernel context\n"); CDEBUG(D_INODE, "renaming file %.*s to %.*s\n", diff --git a/drivers/staging/lustre/lustre/mdc/lproc_mdc.c b/drivers/staging/lustre/lustre/mdc/lproc_mdc.c index 75300847f912..30a8a1b2428d 100644 --- a/drivers/staging/lustre/lustre/mdc/lproc_mdc.c +++ b/drivers/staging/lustre/lustre/mdc/lproc_mdc.c @@ -92,7 +92,6 @@ static ssize_t mdc_kuc_write(struct file *file, const char *buffer, struct hsm_action_item *hai; int len; int fd, rc; - ENTRY; rc = lprocfs_write_helper(buffer, count, &fd); if (rc) diff --git a/drivers/staging/lustre/lustre/mdc/mdc_lib.c b/drivers/staging/lustre/lustre/mdc/mdc_lib.c index 2e5c7cef61ce..4ab3b95faf8b 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_lib.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_lib.c @@ -505,7 +505,7 @@ void mdc_close_pack(struct ptlrpc_request *req, struct md_op_data *op_data) static int mdc_req_avail(struct client_obd *cli, struct mdc_cache_waiter *mcw) { int rc; - ENTRY; + client_obd_list_lock(&cli->cl_loi_list_lock); rc = list_empty(&mcw->mcw_entry); client_obd_list_unlock(&cli->cl_loi_list_lock); diff --git a/drivers/staging/lustre/lustre/mdc/mdc_locks.c b/drivers/staging/lustre/lustre/mdc/mdc_locks.c index 803c390e1c35..9025075d105b 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_locks.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_locks.c @@ -115,7 +115,6 @@ int mdc_set_lock_data(struct obd_export *exp, __u64 *lockh, void *data, { struct ldlm_lock *lock; struct inode *new_inode = data; - ENTRY; if(bits) *bits = 0; @@ -154,7 +153,6 @@ ldlm_mode_t mdc_lock_match(struct obd_export *exp, __u64 flags, { struct ldlm_res_id res_id; ldlm_mode_t rc; - ENTRY; fid_build_reg_res_name(fid, &res_id); rc = ldlm_lock_match(class_exp2obd(exp)->obd_namespace, flags, @@ -173,8 +171,6 @@ int mdc_cancel_unused(struct obd_export *exp, struct obd_device *obd = class_exp2obd(exp); int rc; - ENTRY; - fid_build_reg_res_name(fid, &res_id); rc = ldlm_cli_cancel_unused_resource(obd->obd_namespace, &res_id, policy, mode, flags, opaque); @@ -187,7 +183,6 @@ int mdc_null_inode(struct obd_export *exp, struct ldlm_res_id res_id; struct ldlm_resource *res; struct ldlm_namespace *ns = class_exp2obd(exp)->obd_namespace; - ENTRY; LASSERTF(ns != NULL, "no namespace passed\n"); @@ -215,7 +210,6 @@ int mdc_find_cbdata(struct obd_export *exp, { struct ldlm_res_id res_id; int rc = 0; - ENTRY; fid_build_reg_res_name((struct lu_fid*)fid, &res_id); rc = ldlm_resource_iterate(class_exp2obd(exp)->obd_namespace, &res_id, @@ -281,7 +275,6 @@ static struct ptlrpc_request *mdc_intent_open_pack(struct obd_export *exp, int count = 0; int mode; int rc; - ENTRY; it->it_create_mode = (it->it_create_mode & ~S_IFMT) | S_IFREG; @@ -362,7 +355,6 @@ static struct ptlrpc_request *mdc_intent_unlink_pack(struct obd_export *exp, struct obd_device *obddev = class_exp2obd(exp); struct ldlm_intent *lit; int rc; - ENTRY; req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_LDLM_INTENT_UNLINK); @@ -407,7 +399,6 @@ static struct ptlrpc_request *mdc_intent_getattr_pack(struct obd_export *exp, OBD_MD_FLRMTPERM : OBD_MD_FLACL); struct ldlm_intent *lit; int rc; - ENTRY; req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_LDLM_INTENT_GETATTR); @@ -450,7 +441,6 @@ static struct ptlrpc_request *mdc_intent_layout_pack(struct obd_export *exp, struct ldlm_intent *lit; struct layout_intent *layout; int rc; - ENTRY; req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_LDLM_INTENT_LAYOUT); @@ -485,7 +475,6 @@ mdc_enqueue_pack(struct obd_export *exp, int lvb_len) { struct ptlrpc_request *req; int rc; - ENTRY; req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_LDLM_ENQUEUE); if (req == NULL) @@ -516,7 +505,6 @@ static int mdc_finish_enqueue(struct obd_export *exp, struct ldlm_lock *lock; void *lvb_data = NULL; int lvb_len = 0; - ENTRY; LASSERT(rc >= 0); /* Similarly, if we're going to replay this request, we don't want to @@ -738,7 +726,6 @@ int mdc_enqueue(struct obd_export *exp, struct ldlm_enqueue_info *einfo, int generation, resends = 0; struct ldlm_reply *lockrep; enum lvb_type lvb_type = 0; - ENTRY; LASSERTF(!it || einfo->ei_type == LDLM_IBITS, "lock type %d\n", einfo->ei_type); @@ -890,7 +877,6 @@ static int mdc_finish_intent_lock(struct obd_export *exp, struct mdt_body *mdt_body; struct ldlm_lock *lock; int rc; - ENTRY; LASSERT(request != NULL); LASSERT(request != LP_POISON); @@ -1006,7 +992,6 @@ int mdc_revalidate_lock(struct obd_export *exp, struct lookup_intent *it, struct lustre_handle lockh; ldlm_policy_data_t policy; ldlm_mode_t mode; - ENTRY; if (it->d.lustre.it_lock_handle) { lockh.cookie = it->d.lustre.it_lock_handle; @@ -1076,7 +1061,7 @@ int mdc_intent_lock(struct obd_export *exp, struct md_op_data *op_data, { struct lustre_handle lockh; int rc = 0; - ENTRY; + LASSERT(it); CDEBUG(D_DLMTRACE, "(name: %.*s,"DFID") in obj "DFID @@ -1153,7 +1138,6 @@ static int mdc_intent_getattr_async_interpret(const struct lu_env *env, struct obd_device *obddev; struct ldlm_reply *lockrep; __u64 flags = LDLM_FL_HAS_INTENT; - ENTRY; it = &minfo->mi_it; lockh = &minfo->mi_lockh; @@ -1210,7 +1194,6 @@ int mdc_intent_getattr_async(struct obd_export *exp, }; int rc = 0; __u64 flags = LDLM_FL_HAS_INTENT; - ENTRY; CDEBUG(D_DLMTRACE,"name: %.*s in inode "DFID", intent: %s flags %#o\n", op_data->op_namelen, op_data->op_name, PFID(&op_data->op_fid1), diff --git a/drivers/staging/lustre/lustre/mdc/mdc_reint.c b/drivers/staging/lustre/lustre/mdc/mdc_reint.c index 5e25a07c52bd..be007a36f7df 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_reint.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_reint.c @@ -75,7 +75,6 @@ int mdc_resource_get_unused(struct obd_export *exp, struct lu_fid *fid, struct ldlm_res_id res_id; struct ldlm_resource *res; int count; - ENTRY; /* Return, i.e. cancel nothing, only if ELC is supported (flag in * export) but disabled through procfs (flag in NS). @@ -111,7 +110,6 @@ int mdc_setattr(struct obd_export *exp, struct md_op_data *op_data, struct obd_device *obd = exp->exp_obd; int count = 0, rc; __u64 bits; - ENTRY; LASSERT(op_data != NULL); @@ -217,7 +215,6 @@ int mdc_create(struct obd_export *exp, struct md_op_data *op_data, struct obd_import *import = exp->exp_obd->u.cli.cl_import; int generation = import->imp_generation; LIST_HEAD(cancels); - ENTRY; /* For case if upper layer did not alloc fid, do it now. */ if (!fid_is_sane(&op_data->op_fid2)) { @@ -325,7 +322,6 @@ int mdc_unlink(struct obd_export *exp, struct md_op_data *op_data, struct obd_device *obd = class_exp2obd(exp); struct ptlrpc_request *req = *request; int count = 0, rc; - ENTRY; LASSERT(req == NULL); @@ -380,7 +376,6 @@ int mdc_link(struct obd_export *exp, struct md_op_data *op_data, struct obd_device *obd = exp->exp_obd; struct ptlrpc_request *req; int count = 0, rc; - ENTRY; if ((op_data->op_flags & MF_MDC_CANCEL_FID2) && (fid_is_sane(&op_data->op_fid2))) @@ -428,7 +423,6 @@ int mdc_rename(struct obd_export *exp, struct md_op_data *op_data, struct obd_device *obd = exp->exp_obd; struct ptlrpc_request *req; int count = 0, rc; - ENTRY; if ((op_data->op_flags & MF_MDC_CANCEL_FID1) && (fid_is_sane(&op_data->op_fid1))) diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 2dabfc01d224..f9e9184908ea 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -65,7 +65,6 @@ int mdc_unpack_capa(struct obd_export *exp, struct ptlrpc_request *req, { struct lustre_capa *capa; struct obd_capa *c; - ENTRY; /* swabbed already in mdc_enqueue */ capa = req_capsule_server_get(&req->rq_pill, field); @@ -109,7 +108,6 @@ static int send_getstatus(struct obd_import *imp, struct lu_fid *rootfid, struct ptlrpc_request *req; struct mdt_body *body; int rc; - ENTRY; req = ptlrpc_request_alloc_pack(imp, &RQF_MDS_GETSTATUS, LUSTRE_MDS_VERSION, MDS_GETSTATUS); @@ -172,7 +170,6 @@ static int mdc_getattr_common(struct obd_export *exp, struct mdt_body *body; void *eadata; int rc; - ENTRY; /* Request message already built. */ rc = ptlrpc_queue_wait(req); @@ -220,7 +217,6 @@ int mdc_getattr(struct obd_export *exp, struct md_op_data *op_data, { struct ptlrpc_request *req; int rc; - ENTRY; /* Single MDS without an LMV case */ if (op_data->op_flags & MF_GET_MDT_IDX) { @@ -265,7 +261,6 @@ int mdc_getattr_name(struct obd_export *exp, struct md_op_data *op_data, { struct ptlrpc_request *req; int rc; - ENTRY; *request = NULL; req = ptlrpc_request_alloc(class_exp2cliimp(exp), @@ -314,8 +309,6 @@ static int mdc_is_subdir(struct obd_export *exp, struct ptlrpc_request *req; int rc; - ENTRY; - *request = NULL; req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp), &RQF_MDS_IS_SUBDIR, LUSTRE_MDS_VERSION, @@ -345,7 +338,6 @@ static int mdc_xattr_common(struct obd_export *exp,const struct req_format *fmt, int xattr_namelen = 0; char *tmp; int rc; - ENTRY; *request = NULL; req = ptlrpc_request_alloc(class_exp2cliimp(exp), fmt); @@ -453,7 +445,6 @@ static int mdc_unpack_acl(struct ptlrpc_request *req, struct lustre_md *md) struct posix_acl *acl; void *buf; int rc; - ENTRY; if (!body->aclsize) RETURN(0); @@ -490,7 +481,6 @@ int mdc_get_lustre_md(struct obd_export *exp, struct ptlrpc_request *req, { struct req_capsule *pill = &req->rq_pill; int rc; - ENTRY; LASSERT(md); memset(md, 0, sizeof(*md)); @@ -629,7 +619,6 @@ out: int mdc_free_lustre_md(struct obd_export *exp, struct lustre_md *md) { - ENTRY; RETURN(0); } @@ -644,7 +633,6 @@ void mdc_replay_open(struct ptlrpc_request *req) struct obd_client_handle *och; struct lustre_handle old; struct mdt_body *body; - ENTRY; if (mod == NULL) { DEBUG_REQ(D_ERROR, req, @@ -722,7 +710,6 @@ int mdc_set_open_replay_data(struct obd_export *exp, struct mdt_rec_create *rec; struct mdt_body *body; struct obd_import *imp = open_req->rq_import; - ENTRY; if (!open_req->rq_replay) RETURN(0); @@ -779,7 +766,6 @@ int mdc_clear_open_replay_data(struct obd_export *exp, struct obd_client_handle *och) { struct md_open_data *mod = och->och_mod; - ENTRY; /** * It is possible to not have \var mod in a case of eviction between @@ -819,7 +805,6 @@ int mdc_close(struct obd_export *exp, struct md_op_data *op_data, struct obd_device *obd = class_exp2obd(exp); struct ptlrpc_request *req; int rc; - ENTRY; *request = NULL; req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_MDS_CLOSE); @@ -921,7 +906,6 @@ int mdc_done_writing(struct obd_export *exp, struct md_op_data *op_data, struct obd_device *obd = class_exp2obd(exp); struct ptlrpc_request *req; int rc; - ENTRY; req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_MDS_DONE_WRITING); @@ -993,7 +977,6 @@ int mdc_readpage(struct obd_export *exp, struct md_op_data *op_data, int resends = 0; struct l_wait_info lwi; int rc; - ENTRY; *request = NULL; init_waitqueue_head(&waitq); @@ -1075,7 +1058,6 @@ static int mdc_statfs(const struct lu_env *env, struct obd_statfs *msfs; struct obd_import *imp = NULL; int rc; - ENTRY; /* * Since the request might also come from lprocfs, so we need @@ -1174,7 +1156,6 @@ static int mdc_ioc_hsm_progress(struct obd_export *exp, struct hsm_progress_kernel *req_hpk; struct ptlrpc_request *req; int rc; - ENTRY; req = ptlrpc_request_alloc_pack(imp, &RQF_MDS_HSM_PROGRESS, LUSTRE_MDS_VERSION, MDS_HSM_PROGRESS); @@ -1205,7 +1186,6 @@ static int mdc_ioc_hsm_ct_register(struct obd_import *imp, __u32 archives) __u32 *archive_mask; struct ptlrpc_request *req; int rc; - ENTRY; req = ptlrpc_request_alloc_pack(imp, &RQF_MDS_HSM_CT_REGISTER, LUSTRE_MDS_VERSION, @@ -1239,7 +1219,6 @@ static int mdc_ioc_hsm_current_action(struct obd_export *exp, struct hsm_current_action *req_hca; struct ptlrpc_request *req; int rc; - ENTRY; req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_MDS_HSM_ACTION); @@ -1280,7 +1259,6 @@ static int mdc_ioc_hsm_ct_unregister(struct obd_import *imp) { struct ptlrpc_request *req; int rc; - ENTRY; req = ptlrpc_request_alloc_pack(imp, &RQF_MDS_HSM_CT_UNREGISTER, LUSTRE_MDS_VERSION, @@ -1306,7 +1284,6 @@ static int mdc_ioc_hsm_state_get(struct obd_export *exp, struct hsm_user_state *req_hus; struct ptlrpc_request *req; int rc; - ENTRY; req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_MDS_HSM_STATE_GET); @@ -1349,7 +1326,6 @@ static int mdc_ioc_hsm_state_set(struct obd_export *exp, struct hsm_state_set *req_hss; struct ptlrpc_request *req; int rc; - ENTRY; req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_MDS_HSM_STATE_SET); @@ -1393,7 +1369,6 @@ static int mdc_ioc_hsm_request(struct obd_export *exp, struct hsm_user_item *req_hui; char *req_opaque; int rc; - ENTRY; req = ptlrpc_request_alloc(imp, &RQF_MDS_HSM_REQUEST); if (req == NULL) @@ -1473,7 +1448,6 @@ static int changelog_kkuc_cb(const struct lu_env *env, struct llog_handle *llh, struct llog_changelog_rec *rec = (struct llog_changelog_rec *)hdr; struct kuc_hdr *lh; int len, rc; - ENTRY; if (rec->cr_hdr.lrh_type != CHANGELOG_REC) { rc = -EINVAL; @@ -1605,7 +1579,6 @@ static int mdc_quotacheck(struct obd_device *unused, struct obd_export *exp, struct ptlrpc_request *req; struct obd_quotactl *body; int rc; - ENTRY; req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp), &RQF_MDS_QUOTACHECK, LUSTRE_MDS_VERSION, @@ -1633,7 +1606,6 @@ static int mdc_quota_poll_check(struct obd_export *exp, { struct client_obd *cli = &exp->exp_obd->u.cli; int rc; - ENTRY; qchk->obd_uuid = cli->cl_target_uuid; memcpy(qchk->obd_type, LUSTRE_MDS_NAME, strlen(LUSTRE_MDS_NAME)); @@ -1651,7 +1623,6 @@ static int mdc_quotactl(struct obd_device *unused, struct obd_export *exp, struct ptlrpc_request *req; struct obd_quotactl *oqc; int rc; - ENTRY; req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp), &RQF_MDS_QUOTACTL, LUSTRE_MDS_VERSION, @@ -1689,7 +1660,6 @@ static int mdc_ioc_swap_layouts(struct obd_export *exp, struct ptlrpc_request *req; int rc, count; struct mdc_swap_layouts *msl, *payload; - ENTRY; msl = op_data->op_data; @@ -1747,7 +1717,6 @@ static int mdc_iocontrol(unsigned int cmd, struct obd_export *exp, int len, struct obd_import *imp = obd->u.cli.cl_import; struct llog_ctxt *ctxt; int rc; - ENTRY; if (!try_module_get(THIS_MODULE)) { CERROR("Can't get module. Is it alive?"); @@ -1897,7 +1866,6 @@ int mdc_get_info_rpc(struct obd_export *exp, struct ptlrpc_request *req; char *tmp; int rc = -EINVAL; - ENTRY; req = ptlrpc_request_alloc(imp, &RQF_MDS_GET_INFO); if (req == NULL) @@ -2010,7 +1978,6 @@ static int mdc_hsm_copytool_send(int len, void *val) struct kuc_hdr *lh = (struct kuc_hdr *)val; struct hsm_action_list *hal = (struct hsm_action_list *)(lh + 1); int rc; - ENTRY; if (len < sizeof(*lh) + sizeof(*hal)) { CERROR("Short HSM message %d < %d\n", len, @@ -2075,7 +2042,6 @@ int mdc_set_info_async(const struct lu_env *env, { struct obd_import *imp = class_exp2cliimp(exp); int rc; - ENTRY; if (KEY_IS(KEY_READ_ONLY)) { if (vallen != sizeof(int)) @@ -2171,7 +2137,6 @@ static int mdc_pin(struct obd_export *exp, const struct lu_fid *fid, struct ptlrpc_request *req; struct mdt_body *body; int rc; - ENTRY; req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_MDS_PIN); if (req == NULL) @@ -2224,7 +2189,6 @@ static int mdc_unpin(struct obd_export *exp, struct obd_client_handle *handle, struct ptlrpc_request *req; struct mdt_body *body; int rc; - ENTRY; req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp), &RQF_MDS_UNPIN, LUSTRE_MDS_VERSION, MDS_UNPIN); @@ -2256,7 +2220,6 @@ int mdc_sync(struct obd_export *exp, const struct lu_fid *fid, { struct ptlrpc_request *req; int rc; - ENTRY; *request = NULL; req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_MDS_SYNC); @@ -2341,7 +2304,7 @@ int mdc_fid_alloc(struct obd_export *exp, struct lu_fid *fid, { struct client_obd *cli = &exp->exp_obd->u.cli; struct lu_client_seq *seq = cli->cl_seq; - ENTRY; + RETURN(seq_client_alloc_fid(NULL, seq, fid)); } @@ -2386,7 +2349,6 @@ static int mdc_setup(struct obd_device *obd, struct lustre_cfg *cfg) struct client_obd *cli = &obd->u.cli; struct lprocfs_static_vars lvars = { 0 }; int rc; - ENTRY; OBD_ALLOC(cli->cl_rpc_lock, sizeof (*cli->cl_rpc_lock)); if (!cli->cl_rpc_lock) @@ -2437,7 +2399,6 @@ static int mdc_init_ea_size(struct obd_export *exp, int easize, { struct obd_device *obd = exp->exp_obd; struct client_obd *cli = &obd->u.cli; - ENTRY; if (cli->cl_max_mds_easize < easize) cli->cl_max_mds_easize = easize; @@ -2454,7 +2415,6 @@ static int mdc_init_ea_size(struct obd_export *exp, int easize, static int mdc_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage) { int rc = 0; - ENTRY; switch (stage) { case OBD_CLEANUP_EARLY: @@ -2495,8 +2455,6 @@ static int mdc_llog_init(struct obd_device *obd, struct obd_llog_group *olg, struct llog_ctxt *ctxt; int rc; - ENTRY; - LASSERT(olg == &obd->obd_olg); rc = llog_setup(NULL, obd, olg, LLOG_CHANGELOG_REPL_CTXT, tgt, @@ -2515,8 +2473,6 @@ static int mdc_llog_finish(struct obd_device *obd, int count) { struct llog_ctxt *ctxt; - ENTRY; - ctxt = llog_get_context(obd, LLOG_CHANGELOG_REPL_CTXT); if (ctxt) llog_cleanup(NULL, ctxt); @@ -2550,7 +2506,6 @@ int mdc_get_remote_perm(struct obd_export *exp, const struct lu_fid *fid, { struct ptlrpc_request *req; int rc; - ENTRY; LASSERT(client_is_remote(exp)); @@ -2589,7 +2544,6 @@ static int mdc_interpret_renew_capa(const struct lu_env *env, struct mdc_renew_capa_args *ra = args; struct mdt_body *body = NULL; struct lustre_capa *capa; - ENTRY; if (status) GOTO(out, capa = ERR_PTR(status)); @@ -2615,7 +2569,6 @@ static int mdc_renew_capa(struct obd_export *exp, struct obd_capa *oc, { struct ptlrpc_request *req; struct mdc_renew_capa_args *ra; - ENTRY; req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp), &RQF_MDS_GETATTR, LUSTRE_MDS_VERSION, MDS_GETATTR); diff --git a/drivers/staging/lustre/lustre/mgc/libmgc.c b/drivers/staging/lustre/lustre/mgc/libmgc.c index 442146cc7e60..412f5882225d 100644 --- a/drivers/staging/lustre/lustre/mgc/libmgc.c +++ b/drivers/staging/lustre/lustre/mgc/libmgc.c @@ -56,7 +56,6 @@ static int mgc_setup(struct obd_device *obd, struct lustre_cfg *lcfg) { int rc; - ENTRY; ptlrpcd_addref(); @@ -85,7 +84,6 @@ err_decref: static int mgc_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage) { int rc = 0; - ENTRY; switch (stage) { case OBD_CLEANUP_EARLY: @@ -103,7 +101,6 @@ static int mgc_cleanup(struct obd_device *obd) { struct client_obd *cli = &obd->u.cli; int rc; - ENTRY; LASSERT(cli->cl_mgc_vfsmnt == NULL); @@ -118,7 +115,6 @@ static int mgc_llog_init(struct obd_device *obd, struct obd_llog_group *olg, { struct llog_ctxt *ctxt; int rc; - ENTRY; LASSERT(olg == &obd->obd_olg); rc = llog_setup(NULL, obd, olg, LLOG_CONFIG_REPL_CTXT, tgt, @@ -137,7 +133,6 @@ static int mgc_llog_finish(struct obd_device *obd, int count) { struct llog_ctxt *ctxt; - ENTRY; ctxt = llog_get_context(obd, LLOG_CONFIG_REPL_CTXT); if (ctxt) diff --git a/drivers/staging/lustre/lustre/mgc/mgc_request.c b/drivers/staging/lustre/lustre/mgc/mgc_request.c index 51677678fc75..069681507129 100644 --- a/drivers/staging/lustre/lustre/mgc/mgc_request.c +++ b/drivers/staging/lustre/lustre/mgc/mgc_request.c @@ -118,7 +118,6 @@ static DEFINE_SPINLOCK(config_list_lock); /* Take a reference to a config log */ static int config_log_get(struct config_llog_data *cld) { - ENTRY; atomic_inc(&cld->cld_refcount); CDEBUG(D_INFO, "log %s refs %d\n", cld->cld_logname, atomic_read(&cld->cld_refcount)); @@ -129,8 +128,6 @@ static int config_log_get(struct config_llog_data *cld) we can free the config log data */ static void config_log_put(struct config_llog_data *cld) { - ENTRY; - CDEBUG(D_INFO, "log %s refs %d\n", cld->cld_logname, atomic_read(&cld->cld_refcount)); LASSERT(atomic_read(&cld->cld_refcount) > 0); @@ -164,7 +161,6 @@ struct config_llog_data *config_log_find(char *logname, struct config_llog_data *cld; struct config_llog_data *found = NULL; void * instance; - ENTRY; LASSERT(logname != NULL); @@ -198,7 +194,6 @@ struct config_llog_data *do_config_log_add(struct obd_device *obd, { struct config_llog_data *cld; int rc; - ENTRY; CDEBUG(D_MGC, "do adding config log %s:%p\n", logname, cfg ? cfg->cfg_instance : 0); @@ -296,7 +291,6 @@ static int config_log_add(struct obd_device *obd, char *logname, struct config_llog_data *sptlrpc_cld; char seclogname[32]; char *ptr; - ENTRY; CDEBUG(D_MGC, "adding config log %s:%p\n", logname, cfg->cfg_instance); @@ -357,7 +351,6 @@ static int config_log_end(char *logname, struct config_llog_instance *cfg) struct config_llog_data *cld_sptlrpc = NULL; struct config_llog_data *cld_recover = NULL; int rc = 0; - ENTRY; cld = config_log_find(logname, cfg); if (cld == NULL) @@ -415,7 +408,6 @@ int lprocfs_mgc_rd_ir_state(struct seq_file *m, void *data) struct obd_import *imp = obd->u.cli.cl_import; struct obd_connect_data *ocd = &imp->imp_connect_data; struct config_llog_data *cld; - ENTRY; seq_printf(m, "imperative_recovery: %s\n", OCD_HAS_FLAG(ocd, IMP_RECOV) ? "ENABLED" : "DISABLED"); @@ -445,7 +437,6 @@ static DECLARE_COMPLETION(rq_exit); static void do_requeue(struct config_llog_data *cld) { - ENTRY; LASSERT(atomic_read(&cld->cld_refcount) > 0); /* Do not run mgc_process_log on a disconnected export or an @@ -474,7 +465,6 @@ static void do_requeue(struct config_llog_data *cld) static int mgc_requeue_thread(void *data) { int rc = 0; - ENTRY; CDEBUG(D_MGC, "Starting requeue thread\n"); @@ -563,8 +553,6 @@ static int mgc_requeue_thread(void *data) We are responsible for dropping the config log reference from here on out. */ static void mgc_requeue_add(struct config_llog_data *cld) { - ENTRY; - CDEBUG(D_INFO, "log %s: requeue (r=%d sp=%d st=%x)\n", cld->cld_logname, atomic_read(&cld->cld_refcount), cld->cld_stopping, rq_state); @@ -605,7 +593,6 @@ static int mgc_fs_setup(struct obd_device *obd, struct super_block *sb, struct dentry *dentry; char *label; int err = 0; - ENTRY; LASSERT(lsi); LASSERT(lsi->lsi_srv_mnt == mnt); @@ -668,7 +655,6 @@ static int mgc_fs_cleanup(struct obd_device *obd) { struct client_obd *cli = &obd->u.cli; int rc = 0; - ENTRY; LASSERT(cli->cl_mgc_vfsmnt != NULL); @@ -694,7 +680,6 @@ static atomic_t mgc_count = ATOMIC_INIT(0); static int mgc_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage) { int rc = 0; - ENTRY; switch (stage) { case OBD_CLEANUP_EARLY: @@ -726,7 +711,6 @@ static int mgc_cleanup(struct obd_device *obd) { struct client_obd *cli = &obd->u.cli; int rc; - ENTRY; LASSERT(cli->cl_mgc_vfsmnt == NULL); @@ -747,7 +731,6 @@ static int mgc_setup(struct obd_device *obd, struct lustre_cfg *lcfg) { struct lprocfs_static_vars lvars; int rc; - ENTRY; ptlrpcd_addref(); @@ -798,7 +781,6 @@ static int mgc_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc, struct lustre_handle lockh; struct config_llog_data *cld = (struct config_llog_data *)data; int rc = 0; - ENTRY; switch (flag) { case LDLM_CB_BLOCKING: @@ -862,7 +844,6 @@ static int mgc_set_mgs_param(struct obd_export *exp, struct ptlrpc_request *req; struct mgs_send_param *req_msp, *rep_msp; int rc; - ENTRY; req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp), &RQF_MGS_SET_INFO, LUSTRE_MGS_VERSION, @@ -909,7 +890,6 @@ static int mgc_enqueue(struct obd_export *exp, struct lov_stripe_md *lsm, struct ptlrpc_request *req; int short_limit = cld_is_sptlrpc(cld); int rc; - ENTRY; CDEBUG(D_MGC, "Enqueue for %s (res "LPX64")\n", cld->cld_logname, cld->cld_resid.name[0]); @@ -944,8 +924,6 @@ static int mgc_enqueue(struct obd_export *exp, struct lov_stripe_md *lsm, static int mgc_cancel(struct obd_export *exp, struct lov_stripe_md *md, __u32 mode, struct lustre_handle *lockh) { - ENTRY; - ldlm_lock_decref(lockh, mode); RETURN(0); @@ -969,7 +947,6 @@ static int mgc_target_register(struct obd_export *exp, struct ptlrpc_request *req; struct mgs_target_info *req_mti, *rep_mti; int rc; - ENTRY; req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp), &RQF_MGS_TARGET_REG, LUSTRE_MGS_VERSION, @@ -1007,7 +984,6 @@ int mgc_set_info_async(const struct lu_env *env, struct obd_export *exp, void *val, struct ptlrpc_request_set *set) { int rc = -EINVAL; - ENTRY; /* Turn off initial_recov after we try all backup servers once */ if (KEY_IS(KEY_INIT_RECOV_BACKUP)) { @@ -1179,7 +1155,6 @@ static int mgc_llog_init(struct obd_device *obd, struct obd_llog_group *olg, { struct llog_ctxt *ctxt; int rc; - ENTRY; LASSERT(olg == &obd->obd_olg); @@ -1208,8 +1183,6 @@ static int mgc_llog_finish(struct obd_device *obd, int count) { struct llog_ctxt *ctxt; - ENTRY; - ctxt = llog_get_context(obd, LLOG_CONFIG_REPL_CTXT); if (ctxt) llog_cleanup(NULL, ctxt); @@ -1242,7 +1215,6 @@ static int mgc_apply_recover_logs(struct obd_device *mgc, int pos; int rc = 0; int off = 0; - ENTRY; LASSERT(cfg->cfg_instance != NULL); LASSERT(cfg->cfg_sb == cfg->cfg_instance); @@ -1443,7 +1415,6 @@ static int mgc_process_recover_log(struct obd_device *obd, int i; int ealen; int rc; - ENTRY; /* allocate buffer for bulk transfer. * if this is the first time for this mgs to read logs, @@ -1586,8 +1557,6 @@ static int mgc_process_cfg_log(struct obd_device *mgc, int rc = 0, must_pop = 0; bool sptlrpc_started = false; - ENTRY; - LASSERT(cld); LASSERT(mutex_is_locked(&cld->cld_lock)); @@ -1663,7 +1632,6 @@ int mgc_process_log(struct obd_device *mgc, struct config_llog_data *cld) struct lustre_handle lockh = { 0 }; __u64 flags = LDLM_FL_NO_LRU; int rc = 0, rcl; - ENTRY; LASSERT(cld); @@ -1737,7 +1705,6 @@ static int mgc_process_config(struct obd_device *obd, obd_count len, void *buf) struct config_llog_instance *cfg = NULL; char *logname; int rc = 0; - ENTRY; switch(lcfg->lcfg_command) { case LCFG_LOV_ADD_OBD: { diff --git a/drivers/staging/lustre/lustre/obdclass/acl.c b/drivers/staging/lustre/lustre/obdclass/acl.c index c2a6702c9f2c..66fdd661cafc 100644 --- a/drivers/staging/lustre/lustre/obdclass/acl.c +++ b/drivers/staging/lustre/lustre/obdclass/acl.c @@ -144,7 +144,6 @@ lustre_posix_acl_xattr_2ext(posix_acl_xattr_header *header, int size) { int count, i, esize; ext_acl_xattr_header *new; - ENTRY; if (unlikely(size < 0)) RETURN(ERR_PTR(-EINVAL)); @@ -178,7 +177,6 @@ int lustre_posix_acl_xattr_filter(posix_acl_xattr_header *header, int size, int count, i, j, rc = 0; __u32 id; posix_acl_xattr_header *new; - ENTRY; if (unlikely(size < 0)) RETURN(-EINVAL); @@ -302,7 +300,6 @@ int lustre_acl_xattr_merge2posix(posix_acl_xattr_header *posix_header, int size, posix_acl_xattr_entry pe = {ACL_MASK, 0, ACL_UNDEFINED_ID}; posix_acl_xattr_header *new; ext_acl_xattr_entry *ee, ae; - ENTRY; lustre_posix_acl_cpu_to_le(&pe, &pe); ee = lustre_ext_acl_xattr_search(ext_header, &pe, &pos); @@ -420,7 +417,6 @@ lustre_acl_xattr_merge2ext(posix_acl_xattr_header *posix_header, int size, posix_acl_xattr_entry pae; ext_acl_xattr_header *new; ext_acl_xattr_entry *ee, eae; - ENTRY; if (unlikely(size < 0)) RETURN(ERR_PTR(-EINVAL)); diff --git a/drivers/staging/lustre/lustre/obdclass/capa.c b/drivers/staging/lustre/lustre/obdclass/capa.c index 5eea9bec054a..60eb94d48ea8 100644 --- a/drivers/staging/lustre/lustre/obdclass/capa.c +++ b/drivers/staging/lustre/lustre/obdclass/capa.c @@ -276,7 +276,6 @@ int capa_encrypt_id(__u32 *d, __u32 *s, __u8 *key, int keylen) unsigned int min; int rc; char alg[CRYPTO_MAX_ALG_NAME+1] = "aes"; - ENTRY; /* passing "aes" in a variable instead of a constant string keeps gcc * 4.3.2 happy */ @@ -329,7 +328,6 @@ int capa_decrypt_id(__u32 *d, __u32 *s, __u8 *key, int keylen) unsigned int min; int rc; char alg[CRYPTO_MAX_ALG_NAME+1] = "aes"; - ENTRY; /* passing "aes" in a variable instead of a constant string keeps gcc * 4.3.2 happy */ diff --git a/drivers/staging/lustre/lustre/obdclass/cl_io.c b/drivers/staging/lustre/lustre/obdclass/cl_io.c index f3f03154f094..96a299b4fb91 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_io.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_io.c @@ -106,7 +106,6 @@ void cl_io_fini(const struct lu_env *env, struct cl_io *io) LINVRNT(cl_io_type_is_valid(io->ci_type)); LINVRNT(cl_io_invariant(io)); - ENTRY; while (!list_empty(&io->ci_layers)) { slice = container_of(io->ci_layers.prev, struct cl_io_slice, @@ -157,7 +156,6 @@ static int cl_io_init0(const struct lu_env *env, struct cl_io *io, LINVRNT(io->ci_state == CIS_ZERO || io->ci_state == CIS_FINI); LINVRNT(cl_io_type_is_valid(iot)); LINVRNT(cl_io_invariant(io)); - ENTRY; io->ci_type = iot; INIT_LIST_HEAD(&io->ci_lockset.cls_todo); @@ -228,7 +226,6 @@ int cl_io_rw_init(const struct lu_env *env, struct cl_io *io, { LINVRNT(iot == CIT_READ || iot == CIT_WRITE); LINVRNT(io->ci_obj != NULL); - ENTRY; LU_OBJECT_HEADER(D_VFSTRACE, env, &io->ci_obj->co_lu, "io range: %u ["LPU64", "LPU64") %u %u\n", @@ -288,7 +285,6 @@ static void cl_io_locks_sort(struct cl_io *io) { int done = 0; - ENTRY; /* hidden treasure: bubble sort for now. */ do { struct cl_io_lock_link *curr; @@ -339,7 +335,6 @@ int cl_queue_match(const struct list_head *queue, { struct cl_io_lock_link *scan; - ENTRY; list_for_each_entry(scan, queue, cill_linkage) { if (cl_lock_descr_match(&scan->cill_descr, need)) RETURN(+1); @@ -353,7 +348,6 @@ static int cl_queue_merge(const struct list_head *queue, { struct cl_io_lock_link *scan; - ENTRY; list_for_each_entry(scan, queue, cill_linkage) { if (cl_lock_descr_cmp(&scan->cill_descr, need)) continue; @@ -388,8 +382,6 @@ static int cl_lockset_lock_one(const struct lu_env *env, struct cl_lock *lock; int result; - ENTRY; - lock = cl_lock_request(env, io, &link->cill_descr, "io", io); if (!IS_ERR(lock)) { @@ -412,7 +404,6 @@ static void cl_lock_link_fini(const struct lu_env *env, struct cl_io *io, { struct cl_lock *lock = link->cill_lock; - ENTRY; list_del_init(&link->cill_linkage); if (lock != NULL) { cl_lock_release(env, lock, "io", io); @@ -431,7 +422,6 @@ static int cl_lockset_lock(const struct lu_env *env, struct cl_io *io, struct cl_lock *lock; int result; - ENTRY; result = 0; list_for_each_entry_safe(link, temp, &set->cls_todo, cill_linkage) { if (!cl_lockset_match(set, &link->cill_descr)) { @@ -474,7 +464,6 @@ int cl_io_lock(const struct lu_env *env, struct cl_io *io) LINVRNT(io->ci_state == CIS_IT_STARTED); LINVRNT(cl_io_invariant(io)); - ENTRY; cl_io_for_each(scan, io) { if (scan->cis_iop->op[io->ci_type].cio_lock == NULL) continue; @@ -508,7 +497,6 @@ void cl_io_unlock(const struct lu_env *env, struct cl_io *io) LASSERT(CIS_IT_STARTED <= io->ci_state && io->ci_state < CIS_UNLOCKED); LINVRNT(cl_io_invariant(io)); - ENTRY; set = &io->ci_lockset; list_for_each_entry_safe(link, temp, &set->cls_todo, cill_linkage) @@ -547,7 +535,6 @@ int cl_io_iter_init(const struct lu_env *env, struct cl_io *io) LINVRNT(io->ci_state == CIS_INIT || io->ci_state == CIS_IT_ENDED); LINVRNT(cl_io_invariant(io)); - ENTRY; result = 0; cl_io_for_each(scan, io) { if (scan->cis_iop->op[io->ci_type].cio_iter_init == NULL) @@ -576,7 +563,6 @@ void cl_io_iter_fini(const struct lu_env *env, struct cl_io *io) LINVRNT(io->ci_state == CIS_UNLOCKED); LINVRNT(cl_io_invariant(io)); - ENTRY; cl_io_for_each_reverse(scan, io) { if (scan->cis_iop->op[io->ci_type].cio_iter_fini != NULL) scan->cis_iop->op[io->ci_type].cio_iter_fini(env, scan); @@ -598,8 +584,6 @@ void cl_io_rw_advance(const struct lu_env *env, struct cl_io *io, size_t nob) LINVRNT(cl_io_is_loopable(io)); LINVRNT(cl_io_invariant(io)); - ENTRY; - io->u.ci_rw.crw_pos += nob; io->u.ci_rw.crw_count -= nob; @@ -621,7 +605,6 @@ int cl_io_lock_add(const struct lu_env *env, struct cl_io *io, { int result; - ENTRY; if (cl_lockset_merge(&io->ci_lockset, &link->cill_descr)) result = +1; else { @@ -647,7 +630,6 @@ int cl_io_lock_alloc_add(const struct lu_env *env, struct cl_io *io, struct cl_io_lock_link *link; int result; - ENTRY; OBD_ALLOC_PTR(link); if (link != NULL) { link->cill_descr = *descr; @@ -673,7 +655,6 @@ int cl_io_start(const struct lu_env *env, struct cl_io *io) LINVRNT(cl_io_is_loopable(io)); LINVRNT(io->ci_state == CIS_LOCKED); LINVRNT(cl_io_invariant(io)); - ENTRY; io->ci_state = CIS_IO_GOING; cl_io_for_each(scan, io) { @@ -700,7 +681,6 @@ void cl_io_end(const struct lu_env *env, struct cl_io *io) LINVRNT(cl_io_is_loopable(io)); LINVRNT(io->ci_state == CIS_IO_GOING); LINVRNT(cl_io_invariant(io)); - ENTRY; cl_io_for_each_reverse(scan, io) { if (scan->cis_iop->op[io->ci_type].cio_end != NULL) @@ -774,7 +754,6 @@ int cl_io_read_page(const struct lu_env *env, struct cl_io *io, LINVRNT(io->ci_state == CIS_IO_GOING || io->ci_state == CIS_LOCKED); LINVRNT(cl_page_in_io(page, io)); LINVRNT(cl_io_invariant(io)); - ENTRY; queue = &io->ci_queue; @@ -827,7 +806,6 @@ int cl_io_prepare_write(const struct lu_env *env, struct cl_io *io, LINVRNT(io->ci_state == CIS_IO_GOING || io->ci_state == CIS_LOCKED); LINVRNT(cl_io_invariant(io)); LASSERT(cl_page_in_io(page, io)); - ENTRY; cl_io_for_each_reverse(scan, io) { if (scan->cis_iop->cio_prepare_write != NULL) { @@ -867,7 +845,6 @@ int cl_io_commit_write(const struct lu_env *env, struct cl_io *io, */ LASSERT(cl_page_is_owned(page, io) || page->cp_parent != NULL); LASSERT(cl_page_in_io(page, io)); - ENTRY; cl_io_for_each(scan, io) { if (scan->cis_iop->cio_commit_write != NULL) { @@ -903,7 +880,6 @@ int cl_io_submit_rw(const struct lu_env *env, struct cl_io *io, int result = 0; LINVRNT(crt < ARRAY_SIZE(scan->cis_iop->req_op)); - ENTRY; cl_io_for_each(scan, io) { if (scan->cis_iop->req_op[crt].cio_submit == NULL) @@ -1009,7 +985,6 @@ int cl_io_loop(const struct lu_env *env, struct cl_io *io) int result = 0; LINVRNT(cl_io_is_loopable(io)); - ENTRY; do { size_t nob; @@ -1064,7 +1039,6 @@ void cl_io_slice_add(struct cl_io *io, struct cl_io_slice *slice, LASSERT((linkage->prev == NULL && linkage->next == NULL) || list_empty(linkage)); - ENTRY; list_add_tail(linkage, &io->ci_layers); slice->cis_io = io; @@ -1080,7 +1054,6 @@ EXPORT_SYMBOL(cl_io_slice_add); */ void cl_page_list_init(struct cl_page_list *plist) { - ENTRY; plist->pl_nr = 0; INIT_LIST_HEAD(&plist->pl_pages); plist->pl_owner = current; @@ -1093,7 +1066,6 @@ EXPORT_SYMBOL(cl_page_list_init); */ void cl_page_list_add(struct cl_page_list *plist, struct cl_page *page) { - ENTRY; /* it would be better to check that page is owned by "current" io, but * it is not passed here. */ LASSERT(page->cp_owner != NULL); @@ -1120,7 +1092,6 @@ void cl_page_list_del(const struct lu_env *env, LASSERT(plist->pl_nr > 0); LINVRNT(plist->pl_owner == current); - ENTRY; list_del_init(&page->cp_batch); lockdep_off(); mutex_unlock(&page->cp_mutex); @@ -1142,7 +1113,6 @@ void cl_page_list_move(struct cl_page_list *dst, struct cl_page_list *src, LINVRNT(dst->pl_owner == current); LINVRNT(src->pl_owner == current); - ENTRY; list_move_tail(&page->cp_batch, &dst->pl_pages); --src->pl_nr; ++dst->pl_nr; @@ -1163,7 +1133,6 @@ void cl_page_list_splice(struct cl_page_list *list, struct cl_page_list *head) LINVRNT(list->pl_owner == current); LINVRNT(head->pl_owner == current); - ENTRY; cl_page_list_for_each_safe(page, tmp, list) cl_page_list_move(head, list, page); EXIT; @@ -1184,7 +1153,6 @@ void cl_page_list_disown(const struct lu_env *env, LINVRNT(plist->pl_owner == current); - ENTRY; cl_page_list_for_each_safe(page, temp, plist) { LASSERT(plist->pl_nr > 0); @@ -1220,7 +1188,6 @@ void cl_page_list_fini(const struct lu_env *env, struct cl_page_list *plist) LINVRNT(plist->pl_owner == current); - ENTRY; cl_page_list_for_each_safe(page, temp, plist) cl_page_list_del(env, plist, page); LASSERT(plist->pl_nr == 0); @@ -1241,7 +1208,6 @@ int cl_page_list_own(const struct lu_env *env, LINVRNT(plist->pl_owner == current); - ENTRY; result = 0; cl_page_list_for_each_safe(page, temp, plist) { LASSERT(index <= page->cp_index); @@ -1279,7 +1245,6 @@ void cl_page_list_discard(const struct lu_env *env, struct cl_io *io, struct cl_page *page; LINVRNT(plist->pl_owner == current); - ENTRY; cl_page_list_for_each(page, plist) cl_page_discard(env, io, page); EXIT; @@ -1296,7 +1261,6 @@ int cl_page_list_unmap(const struct lu_env *env, struct cl_io *io, int result; LINVRNT(plist->pl_owner == current); - ENTRY; result = 0; cl_page_list_for_each(page, plist) { result = cl_page_unmap(env, io, page); @@ -1312,7 +1276,6 @@ EXPORT_SYMBOL(cl_page_list_unmap); */ void cl_2queue_init(struct cl_2queue *queue) { - ENTRY; cl_page_list_init(&queue->c2_qin); cl_page_list_init(&queue->c2_qout); EXIT; @@ -1324,7 +1287,6 @@ EXPORT_SYMBOL(cl_2queue_init); */ void cl_2queue_add(struct cl_2queue *queue, struct cl_page *page) { - ENTRY; cl_page_list_add(&queue->c2_qin, page); EXIT; } @@ -1336,7 +1298,6 @@ EXPORT_SYMBOL(cl_2queue_add); void cl_2queue_disown(const struct lu_env *env, struct cl_io *io, struct cl_2queue *queue) { - ENTRY; cl_page_list_disown(env, io, &queue->c2_qin); cl_page_list_disown(env, io, &queue->c2_qout); EXIT; @@ -1349,7 +1310,6 @@ EXPORT_SYMBOL(cl_2queue_disown); void cl_2queue_discard(const struct lu_env *env, struct cl_io *io, struct cl_2queue *queue) { - ENTRY; cl_page_list_discard(env, io, &queue->c2_qin); cl_page_list_discard(env, io, &queue->c2_qout); EXIT; @@ -1372,7 +1332,6 @@ EXPORT_SYMBOL(cl_2queue_assume); */ void cl_2queue_fini(const struct lu_env *env, struct cl_2queue *queue) { - ENTRY; cl_page_list_fini(env, &queue->c2_qout); cl_page_list_fini(env, &queue->c2_qin); EXIT; @@ -1384,7 +1343,6 @@ EXPORT_SYMBOL(cl_2queue_fini); */ void cl_2queue_init_page(struct cl_2queue *queue, struct cl_page *page) { - ENTRY; cl_2queue_init(queue); cl_2queue_add(queue, page); EXIT; @@ -1398,7 +1356,6 @@ EXPORT_SYMBOL(cl_2queue_init_page); */ struct cl_io *cl_io_top(struct cl_io *io) { - ENTRY; while (io->ci_parent != NULL) io = io->ci_parent; RETURN(io); @@ -1426,7 +1383,6 @@ void cl_req_slice_add(struct cl_req *req, struct cl_req_slice *slice, struct cl_device *dev, const struct cl_req_operations *ops) { - ENTRY; list_add_tail(&slice->crs_linkage, &req->crq_layers); slice->crs_dev = dev; slice->crs_ops = ops; @@ -1443,7 +1399,6 @@ static void cl_req_free(const struct lu_env *env, struct cl_req *req) LASSERT(req->crq_nrpages == 0); LINVRNT(list_empty(&req->crq_layers)); LINVRNT(equi(req->crq_nrobjs > 0, req->crq_o != NULL)); - ENTRY; if (req->crq_o != NULL) { for (i = 0; i < req->crq_nrobjs; ++i) { @@ -1468,7 +1423,6 @@ static int cl_req_init(const struct lu_env *env, struct cl_req *req, struct cl_page_slice *slice; int result; - ENTRY; result = 0; page = cl_page_top(page); do { @@ -1494,7 +1448,6 @@ void cl_req_completion(const struct lu_env *env, struct cl_req *req, int rc) { struct cl_req_slice *slice; - ENTRY; /* * for the lack of list_for_each_entry_reverse_safe()... */ @@ -1519,7 +1472,6 @@ struct cl_req *cl_req_alloc(const struct lu_env *env, struct cl_page *page, struct cl_req *req; LINVRNT(nr_objects > 0); - ENTRY; OBD_ALLOC_PTR(req); if (req != NULL) { @@ -1554,7 +1506,6 @@ void cl_req_page_add(const struct lu_env *env, struct cl_req_obj *rqo; int i; - ENTRY; page = cl_page_top(page); LASSERT(list_empty(&page->cp_flight)); @@ -1588,7 +1539,6 @@ void cl_req_page_done(const struct lu_env *env, struct cl_page *page) { struct cl_req *req = page->cp_req; - ENTRY; page = cl_page_top(page); LASSERT(!list_empty(&page->cp_flight)); @@ -1611,7 +1561,6 @@ int cl_req_prep(const struct lu_env *env, struct cl_req *req) int result; const struct cl_req_slice *slice; - ENTRY; /* * Check that the caller of cl_req_alloc() didn't lie about the number * of objects. @@ -1644,7 +1593,6 @@ void cl_req_attr_set(const struct lu_env *env, struct cl_req *req, int i; LASSERT(!list_empty(&req->crq_pages)); - ENTRY; /* Take any page to use as a model. */ page = list_entry(req->crq_pages.next, struct cl_page, cp_flight); @@ -1676,7 +1624,6 @@ EXPORT_SYMBOL(cl_req_attr_set); */ void cl_sync_io_init(struct cl_sync_io *anchor, int nrpages) { - ENTRY; init_waitqueue_head(&anchor->csi_waitq); atomic_set(&anchor->csi_sync_nr, nrpages); atomic_set(&anchor->csi_barrier, nrpages > 0); @@ -1696,7 +1643,6 @@ int cl_sync_io_wait(const struct lu_env *env, struct cl_io *io, struct l_wait_info lwi = LWI_TIMEOUT_INTR(cfs_time_seconds(timeout), NULL, NULL, NULL); int rc; - ENTRY; LASSERT(timeout >= 0); @@ -1735,7 +1681,6 @@ EXPORT_SYMBOL(cl_sync_io_wait); */ void cl_sync_io_note(struct cl_sync_io *anchor, int ioret) { - ENTRY; if (anchor->csi_sync_rc == 0 && ioret < 0) anchor->csi_sync_rc = ioret; /* diff --git a/drivers/staging/lustre/lustre/obdclass/cl_lock.c b/drivers/staging/lustre/lustre/obdclass/cl_lock.c index 958c1e531cfb..adcf78954117 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_lock.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_lock.c @@ -191,7 +191,6 @@ void cl_lock_slice_add(struct cl_lock *lock, struct cl_lock_slice *slice, struct cl_object *obj, const struct cl_lock_operations *ops) { - ENTRY; slice->cls_lock = lock; list_add_tail(&slice->cls_linkage, &lock->cll_layers); slice->cls_obj = obj; @@ -254,7 +253,6 @@ static void cl_lock_free(const struct lu_env *env, struct cl_lock *lock) LINVRNT(!cl_lock_is_mutexed(lock)); - ENTRY; cl_lock_trace(D_DLMTRACE, env, "free lock", lock); might_sleep(); while (!list_empty(&lock->cll_layers)) { @@ -290,7 +288,6 @@ void cl_lock_put(const struct lu_env *env, struct cl_lock *lock) struct cl_object *obj; LINVRNT(cl_lock_invariant(env, lock)); - ENTRY; obj = lock->cll_descr.cld_obj; LINVRNT(obj != NULL); @@ -366,7 +363,6 @@ static struct cl_lock *cl_lock_alloc(const struct lu_env *env, struct cl_lock *lock; struct lu_object_header *head; - ENTRY; OBD_SLAB_ALLOC_PTR_GFP(lock, cl_lock_kmem, __GFP_IO); if (lock != NULL) { atomic_set(&lock->cll_ref, 1); @@ -468,7 +464,6 @@ static int cl_lock_fits_into(const struct lu_env *env, const struct cl_lock_slice *slice; LINVRNT(cl_lock_invariant_trusted(env, lock)); - ENTRY; list_for_each_entry(slice, &lock->cll_layers, cls_linkage) { if (slice->cls_ops->clo_fits_into != NULL && !slice->cls_ops->clo_fits_into(env, slice, need, io)) @@ -485,8 +480,6 @@ static struct cl_lock *cl_lock_lookup(const struct lu_env *env, struct cl_lock *lock; struct cl_object_header *head; - ENTRY; - head = cl_object_header(obj); LINVRNT(spin_is_locked(&head->coh_lock_guard)); CS_LOCK_INC(obj, lookup); @@ -528,8 +521,6 @@ static struct cl_lock *cl_lock_find(const struct lu_env *env, struct cl_object *obj; struct cl_lock *lock; - ENTRY; - obj = need->cld_obj; head = cl_object_header(obj); @@ -630,7 +621,6 @@ const struct cl_lock_slice *cl_lock_at(const struct cl_lock *lock, const struct cl_lock_slice *slice; LINVRNT(cl_lock_invariant_trusted(NULL, lock)); - ENTRY; list_for_each_entry(slice, &lock->cll_layers, cls_linkage) { if (slice->cls_obj->co_lu.lo_dev->ld_type == dtype) @@ -705,7 +695,6 @@ int cl_lock_mutex_try(const struct lu_env *env, struct cl_lock *lock) int result; LINVRNT(cl_lock_invariant_trusted(env, lock)); - ENTRY; result = 0; if (lock->cll_guarder == current) { @@ -784,7 +773,6 @@ static void cl_lock_cancel0(const struct lu_env *env, struct cl_lock *lock) { LINVRNT(cl_lock_is_mutexed(lock)); LINVRNT(cl_lock_invariant(env, lock)); - ENTRY; if (!(lock->cll_flags & CLF_CANCELLED)) { const struct cl_lock_slice *slice; @@ -806,7 +794,6 @@ static void cl_lock_delete0(const struct lu_env *env, struct cl_lock *lock) LINVRNT(cl_lock_is_mutexed(lock)); LINVRNT(cl_lock_invariant(env, lock)); - ENTRY; if (lock->cll_state < CLS_FREEING) { LASSERT(lock->cll_state != CLS_INTRANSIT); cl_lock_state_set(env, lock, CLS_FREEING); @@ -886,7 +873,6 @@ void cl_lock_hold_release(const struct lu_env *env, struct cl_lock *lock, LINVRNT(cl_lock_invariant(env, lock)); LASSERT(lock->cll_holds > 0); - ENTRY; cl_lock_trace(D_DLMTRACE, env, "hold release lock", lock); lu_ref_del(&lock->cll_holders, scope, source); cl_lock_hold_mod(env, lock, -1); @@ -939,7 +925,6 @@ int cl_lock_state_wait(const struct lu_env *env, struct cl_lock *lock) sigset_t blocked; int result; - ENTRY; LINVRNT(cl_lock_is_mutexed(lock)); LINVRNT(cl_lock_invariant(env, lock)); LASSERT(lock->cll_depth == 1); @@ -985,7 +970,6 @@ static void cl_lock_state_signal(const struct lu_env *env, struct cl_lock *lock, { const struct cl_lock_slice *slice; - ENTRY; LINVRNT(cl_lock_is_mutexed(lock)); LINVRNT(cl_lock_invariant(env, lock)); @@ -1005,7 +989,6 @@ static void cl_lock_state_signal(const struct lu_env *env, struct cl_lock *lock, */ void cl_lock_signal(const struct lu_env *env, struct cl_lock *lock) { - ENTRY; cl_lock_trace(D_DLMTRACE, env, "state signal lock", lock); cl_lock_state_signal(env, lock, lock->cll_state); EXIT; @@ -1025,7 +1008,6 @@ EXPORT_SYMBOL(cl_lock_signal); void cl_lock_state_set(const struct lu_env *env, struct cl_lock *lock, enum cl_lock_state state) { - ENTRY; LASSERT(lock->cll_state <= state || (lock->cll_state == CLS_CACHED && (state == CLS_HELD || /* lock found in cache */ @@ -1084,7 +1066,6 @@ int cl_use_try(const struct lu_env *env, struct cl_lock *lock, int atomic) int result; enum cl_lock_state state; - ENTRY; cl_lock_trace(D_DLMTRACE, env, "use lock", lock); LASSERT(lock->cll_state == CLS_CACHED); @@ -1144,7 +1125,6 @@ static int cl_enqueue_kick(const struct lu_env *env, int result; const struct cl_lock_slice *slice; - ENTRY; result = -ENOSYS; list_for_each_entry(slice, &lock->cll_layers, cls_linkage) { if (slice->cls_ops->clo_enqueue != NULL) { @@ -1176,7 +1156,6 @@ int cl_enqueue_try(const struct lu_env *env, struct cl_lock *lock, { int result; - ENTRY; cl_lock_trace(D_DLMTRACE, env, "enqueue lock", lock); do { LINVRNT(cl_lock_is_mutexed(lock)); @@ -1235,7 +1214,6 @@ int cl_lock_enqueue_wait(const struct lu_env *env, { struct cl_lock *conflict; int rc = 0; - ENTRY; LASSERT(cl_lock_is_mutexed(lock)); LASSERT(lock->cll_state == CLS_QUEUING); @@ -1274,8 +1252,6 @@ static int cl_enqueue_locked(const struct lu_env *env, struct cl_lock *lock, { int result; - ENTRY; - LINVRNT(cl_lock_is_mutexed(lock)); LINVRNT(cl_lock_invariant(env, lock)); LASSERT(lock->cll_holds > 0); @@ -1315,8 +1291,6 @@ int cl_enqueue(const struct lu_env *env, struct cl_lock *lock, { int result; - ENTRY; - cl_lock_lockdep_acquire(env, lock, enqflags); cl_lock_mutex_get(env, lock); result = cl_enqueue_locked(env, lock, io, enqflags); @@ -1346,7 +1320,6 @@ int cl_unuse_try(const struct lu_env *env, struct cl_lock *lock) int result; enum cl_lock_state state = CLS_NEW; - ENTRY; cl_lock_trace(D_DLMTRACE, env, "unuse lock", lock); if (lock->cll_users > 1) { @@ -1411,7 +1384,6 @@ EXPORT_SYMBOL(cl_unuse_try); static void cl_unuse_locked(const struct lu_env *env, struct cl_lock *lock) { int result; - ENTRY; result = cl_unuse_try(env, lock); if (result) @@ -1425,7 +1397,6 @@ static void cl_unuse_locked(const struct lu_env *env, struct cl_lock *lock) */ void cl_unuse(const struct lu_env *env, struct cl_lock *lock) { - ENTRY; cl_lock_mutex_get(env, lock); cl_unuse_locked(env, lock); cl_lock_mutex_put(env, lock); @@ -1449,7 +1420,6 @@ int cl_wait_try(const struct lu_env *env, struct cl_lock *lock) const struct cl_lock_slice *slice; int result; - ENTRY; cl_lock_trace(D_DLMTRACE, env, "wait lock try", lock); do { LINVRNT(cl_lock_is_mutexed(lock)); @@ -1506,7 +1476,6 @@ int cl_wait(const struct lu_env *env, struct cl_lock *lock) { int result; - ENTRY; cl_lock_mutex_get(env, lock); LINVRNT(cl_lock_invariant(env, lock)); @@ -1544,7 +1513,6 @@ unsigned long cl_lock_weigh(const struct lu_env *env, struct cl_lock *lock) unsigned long pound; unsigned long ounce; - ENTRY; LINVRNT(cl_lock_is_mutexed(lock)); LINVRNT(cl_lock_invariant(env, lock)); @@ -1579,7 +1547,6 @@ int cl_lock_modify(const struct lu_env *env, struct cl_lock *lock, struct cl_object_header *hdr = cl_object_header(obj); int result; - ENTRY; cl_lock_trace(D_DLMTRACE, env, "modify lock", lock); /* don't allow object to change */ LASSERT(obj == desc->cld_obj); @@ -1642,7 +1609,6 @@ int cl_lock_closure_build(const struct lu_env *env, struct cl_lock *lock, const struct cl_lock_slice *slice; int result; - ENTRY; LINVRNT(cl_lock_is_mutexed(closure->clc_origin)); LINVRNT(cl_lock_invariant(env, closure->clc_origin)); @@ -1674,7 +1640,7 @@ int cl_lock_enclosure(const struct lu_env *env, struct cl_lock *lock, struct cl_lock_closure *closure) { int result = 0; - ENTRY; + cl_lock_trace(D_DLMTRACE, env, "enclosure lock", lock); if (!cl_lock_mutex_try(env, lock)) { /* @@ -1766,7 +1732,6 @@ void cl_lock_delete(const struct lu_env *env, struct cl_lock *lock) LASSERT(ergo(cl_lock_nesting(lock) == CNL_TOP, cl_lock_nr_mutexed(env) == 1)); - ENTRY; cl_lock_trace(D_DLMTRACE, env, "delete lock", lock); if (lock->cll_holds == 0) cl_lock_delete0(env, lock); @@ -1791,7 +1756,6 @@ void cl_lock_error(const struct lu_env *env, struct cl_lock *lock, int error) LINVRNT(cl_lock_is_mutexed(lock)); LINVRNT(cl_lock_invariant(env, lock)); - ENTRY; if (lock->cll_error == 0 && error != 0) { cl_lock_trace(D_DLMTRACE, env, "set lock error", lock); lock->cll_error = error; @@ -1819,7 +1783,6 @@ void cl_lock_cancel(const struct lu_env *env, struct cl_lock *lock) LINVRNT(cl_lock_is_mutexed(lock)); LINVRNT(cl_lock_invariant(env, lock)); - ENTRY; cl_lock_trace(D_DLMTRACE, env, "cancel lock", lock); if (lock->cll_holds == 0) cl_lock_cancel0(env, lock); @@ -1843,8 +1806,6 @@ struct cl_lock *cl_lock_at_pgoff(const struct lu_env *env, struct cl_lock *lock; struct cl_lock_descr *need; - ENTRY; - head = cl_object_header(obj); need = &cl_env_info(env)->clt_descr; lock = NULL; @@ -1979,7 +1940,6 @@ int cl_lock_discard_pages(const struct lu_env *env, struct cl_lock *lock) int result; LINVRNT(cl_lock_invariant(env, lock)); - ENTRY; io->ci_obj = cl_object_top(descr->cld_obj); io->ci_ignore_layout = 1; @@ -2018,7 +1978,6 @@ void cl_locks_prune(const struct lu_env *env, struct cl_object *obj, int cancel) struct cl_object_header *head; struct cl_lock *lock; - ENTRY; head = cl_object_header(obj); /* * If locks are destroyed without cancellation, all pages must be @@ -2070,8 +2029,6 @@ static struct cl_lock *cl_lock_hold_mutex(const struct lu_env *env, { struct cl_lock *lock; - ENTRY; - while (1) { lock = cl_lock_find(env, io, need); if (IS_ERR(lock)) @@ -2103,8 +2060,6 @@ struct cl_lock *cl_lock_hold(const struct lu_env *env, const struct cl_io *io, { struct cl_lock *lock; - ENTRY; - lock = cl_lock_hold_mutex(env, io, need, scope, source); if (!IS_ERR(lock)) cl_lock_mutex_put(env, lock); @@ -2124,7 +2079,6 @@ struct cl_lock *cl_lock_request(const struct lu_env *env, struct cl_io *io, int rc; __u32 enqflags = need->cld_enq_flags; - ENTRY; do { lock = cl_lock_hold_mutex(env, io, need, scope, source); if (IS_ERR(lock)) @@ -2170,7 +2124,6 @@ void cl_lock_hold_add(const struct lu_env *env, struct cl_lock *lock, LINVRNT(cl_lock_invariant(env, lock)); LASSERT(lock->cll_state != CLS_FREEING); - ENTRY; cl_lock_hold_mod(env, lock, +1); cl_lock_get(lock); lu_ref_add(&lock->cll_holders, scope, source); @@ -2187,7 +2140,6 @@ void cl_lock_unhold(const struct lu_env *env, struct cl_lock *lock, const char *scope, const void *source) { LINVRNT(cl_lock_invariant(env, lock)); - ENTRY; cl_lock_hold_release(env, lock, scope, source); lu_ref_del(&lock->cll_reference, scope, source); cl_lock_put(env, lock); @@ -2202,7 +2154,6 @@ void cl_lock_release(const struct lu_env *env, struct cl_lock *lock, const char *scope, const void *source) { LINVRNT(cl_lock_invariant(env, lock)); - ENTRY; cl_lock_trace(D_DLMTRACE, env, "release lock", lock); cl_lock_mutex_get(env, lock); cl_lock_hold_release(env, lock, scope, source); @@ -2218,7 +2169,6 @@ void cl_lock_user_add(const struct lu_env *env, struct cl_lock *lock) LINVRNT(cl_lock_is_mutexed(lock)); LINVRNT(cl_lock_invariant(env, lock)); - ENTRY; cl_lock_used_mod(env, lock, +1); EXIT; } @@ -2230,7 +2180,6 @@ void cl_lock_user_del(const struct lu_env *env, struct cl_lock *lock) LINVRNT(cl_lock_invariant(env, lock)); LASSERT(lock->cll_users > 0); - ENTRY; cl_lock_used_mod(env, lock, -1); if (lock->cll_users == 0) wake_up_all(&lock->cll_wq); diff --git a/drivers/staging/lustre/lustre/obdclass/cl_object.c b/drivers/staging/lustre/lustre/obdclass/cl_object.c index cdb5fba04591..2abc4b5ddb37 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_object.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_object.c @@ -79,7 +79,6 @@ int cl_object_header_init(struct cl_object_header *h) { int result; - ENTRY; result = lu_object_header_init(&h->coh_lu); if (result == 0) { spin_lock_init(&h->coh_page_guard); @@ -222,7 +221,6 @@ int cl_object_attr_get(const struct lu_env *env, struct cl_object *obj, int result; LASSERT(spin_is_locked(cl_object_attr_guard(obj))); - ENTRY; top = obj->co_lu.lo_header; result = 0; @@ -254,7 +252,6 @@ int cl_object_attr_set(const struct lu_env *env, struct cl_object *obj, int result; LASSERT(spin_is_locked(cl_object_attr_guard(obj))); - ENTRY; top = obj->co_lu.lo_header; result = 0; @@ -287,7 +284,6 @@ int cl_object_glimpse(const struct lu_env *env, struct cl_object *obj, struct lu_object_header *top; int result; - ENTRY; top = obj->co_lu.lo_header; result = 0; list_for_each_entry_reverse(obj, &top->loh_layers, @@ -316,7 +312,6 @@ int cl_conf_set(const struct lu_env *env, struct cl_object *obj, struct lu_object_header *top; int result; - ENTRY; top = obj->co_lu.lo_header; result = 0; list_for_each_entry(obj, &top->loh_layers, co_lu.lo_linkage) { @@ -362,7 +357,6 @@ EXPORT_SYMBOL(cl_object_kill); */ void cl_object_prune(const struct lu_env *env, struct cl_object *obj) { - ENTRY; cl_pages_prune(env, obj); cl_locks_prune(env, obj, 1); EXIT; @@ -941,7 +935,6 @@ EXPORT_SYMBOL(cl_env_nested_put); */ void cl_attr2lvb(struct ost_lvb *lvb, const struct cl_attr *attr) { - ENTRY; lvb->lvb_size = attr->cat_size; lvb->lvb_mtime = attr->cat_mtime; lvb->lvb_atime = attr->cat_atime; @@ -958,7 +951,6 @@ EXPORT_SYMBOL(cl_attr2lvb); */ void cl_lvb2attr(struct cl_attr *attr, const struct ost_lvb *lvb) { - ENTRY; attr->cat_size = lvb->lvb_size; attr->cat_mtime = lvb->lvb_mtime; attr->cat_atime = lvb->lvb_atime; diff --git a/drivers/staging/lustre/lustre/obdclass/cl_page.c b/drivers/staging/lustre/lustre/obdclass/cl_page.c index d9ca5d500570..3c6cf202bbd9 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_page.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_page.c @@ -108,7 +108,6 @@ cl_page_at_trusted(const struct cl_page *page, const struct lu_device_type *dtype) { const struct cl_page_slice *slice; - ENTRY; page = cl_page_top_trusted((struct cl_page *)page); do { @@ -167,7 +166,6 @@ int cl_page_gang_lookup(const struct lu_env *env, struct cl_object *obj, unsigned int j; int res = CLP_GANG_OKAY; int tree_lock = 1; - ENTRY; idx = start; hdr = cl_object_header(obj); @@ -258,7 +256,6 @@ static void cl_page_free(const struct lu_env *env, struct cl_page *page) PASSERT(env, page, page->cp_parent == NULL); PASSERT(env, page, page->cp_state == CPS_FREEING); - ENTRY; might_sleep(); while (!list_empty(&page->cp_layers)) { struct cl_page_slice *slice; @@ -295,7 +292,6 @@ static struct cl_page *cl_page_alloc(const struct lu_env *env, struct cl_page *page; struct lu_object_header *head; - ENTRY; OBD_ALLOC_GFP(page, cl_object_header(o)->coh_page_bufsize, __GFP_IO); if (page != NULL) { @@ -365,8 +361,6 @@ static struct cl_page *cl_page_find0(const struct lu_env *env, LASSERT(type == CPT_CACHEABLE || type == CPT_TRANSIENT); might_sleep(); - ENTRY; - hdr = cl_object_header(o); CS_PAGE_INC(o, lookup); @@ -554,7 +548,6 @@ static void cl_page_state_set0(const struct lu_env *env, } }; - ENTRY; old = page->cp_state; PASSERT(env, page, allowed_transitions[old][state]); CL_PAGE_HEADER(D_TRACE, env, page, "%d -> %d\n", old, state); @@ -586,7 +579,6 @@ static void cl_page_state_set(const struct lu_env *env, */ void cl_page_get(struct cl_page *page) { - ENTRY; cl_page_get_trust(page); EXIT; } @@ -605,7 +597,6 @@ void cl_page_put(const struct lu_env *env, struct cl_page *page) { PASSERT(env, page, atomic_read(&page->cp_ref) > !!page->cp_parent); - ENTRY; CL_PAGE_HEADER(D_TRACE, env, page, "%d\n", atomic_read(&page->cp_ref)); @@ -657,7 +648,6 @@ struct cl_page *cl_vmpage_page(struct page *vmpage, struct cl_object *obj) struct cl_page *top; struct cl_page *page; - ENTRY; KLASSERT(PageLocked(vmpage)); /* @@ -786,7 +776,6 @@ static int cl_page_invoke(const struct lu_env *env, { PINVRNT(env, page, cl_object_same(page->cp_obj, io->ci_obj)); - ENTRY; RETURN(CL_PAGE_INVOKE(env, page, op, (const struct lu_env *, const struct cl_page_slice *, struct cl_io *), @@ -798,7 +787,6 @@ static void cl_page_invoid(const struct lu_env *env, { PINVRNT(env, page, cl_object_same(page->cp_obj, io->ci_obj)); - ENTRY; CL_PAGE_INVOID(env, page, op, (const struct lu_env *, const struct cl_page_slice *, struct cl_io *), io); @@ -807,7 +795,6 @@ static void cl_page_invoid(const struct lu_env *env, static void cl_page_owner_clear(struct cl_page *page) { - ENTRY; for (page = cl_page_top(page); page != NULL; page = page->cp_child) { if (page->cp_owner != NULL) { LASSERT(page->cp_owner->ci_owned_nr > 0); @@ -821,7 +808,6 @@ static void cl_page_owner_clear(struct cl_page *page) static void cl_page_owner_set(struct cl_page *page) { - ENTRY; for (page = cl_page_top(page); page != NULL; page = page->cp_child) { LASSERT(page->cp_owner != NULL); page->cp_owner->ci_owned_nr++; @@ -834,7 +820,6 @@ void cl_page_disown0(const struct lu_env *env, { enum cl_page_state state; - ENTRY; state = pg->cp_state; PINVRNT(env, pg, state == CPS_OWNED || state == CPS_FREEING); PINVRNT(env, pg, cl_page_invariant(pg)); @@ -860,7 +845,6 @@ void cl_page_disown0(const struct lu_env *env, int cl_page_is_owned(const struct cl_page *pg, const struct cl_io *io) { LINVRNT(cl_object_same(pg->cp_obj, io->ci_obj)); - ENTRY; RETURN(pg->cp_state == CPS_OWNED && pg->cp_owner == io); } EXPORT_SYMBOL(cl_page_is_owned); @@ -892,7 +876,6 @@ static int cl_page_own0(const struct lu_env *env, struct cl_io *io, PINVRNT(env, pg, !cl_page_is_owned(pg, io)); - ENTRY; pg = cl_page_top(pg); io = cl_io_top(io); @@ -961,7 +944,6 @@ void cl_page_assume(const struct lu_env *env, { PINVRNT(env, pg, cl_object_same(pg->cp_obj, io->ci_obj)); - ENTRY; pg = cl_page_top(pg); io = cl_io_top(io); @@ -992,7 +974,6 @@ void cl_page_unassume(const struct lu_env *env, PINVRNT(env, pg, cl_page_is_owned(pg, io)); PINVRNT(env, pg, cl_page_invariant(pg)); - ENTRY; pg = cl_page_top(pg); io = cl_io_top(io); cl_page_owner_clear(pg); @@ -1021,7 +1002,6 @@ void cl_page_disown(const struct lu_env *env, { PINVRNT(env, pg, cl_page_is_owned(pg, io)); - ENTRY; pg = cl_page_top(pg); io = cl_io_top(io); cl_page_disown0(env, io, pg); @@ -1058,7 +1038,6 @@ static void cl_page_delete0(const struct lu_env *env, struct cl_page *pg, int radix) { struct cl_page *tmp = pg; - ENTRY; PASSERT(env, pg, pg == cl_page_top(pg)); PASSERT(env, pg, pg->cp_state != CPS_FREEING); @@ -1135,7 +1114,6 @@ static void cl_page_delete0(const struct lu_env *env, struct cl_page *pg, void cl_page_delete(const struct lu_env *env, struct cl_page *pg) { PINVRNT(env, pg, cl_page_invariant(pg)); - ENTRY; cl_page_delete0(env, pg, 1); EXIT; } @@ -1187,7 +1165,6 @@ int cl_page_is_vmlocked(const struct lu_env *env, const struct cl_page *pg) int result; const struct cl_page_slice *slice; - ENTRY; pg = cl_page_top_trusted((struct cl_page *)pg); slice = container_of(pg->cp_layers.next, const struct cl_page_slice, cpl_linkage); @@ -1205,7 +1182,6 @@ EXPORT_SYMBOL(cl_page_is_vmlocked); static enum cl_page_state cl_req_type_state(enum cl_req_type crt) { - ENTRY; RETURN(crt == CRT_WRITE ? CPS_PAGEOUT : CPS_PAGEIN); } @@ -1215,7 +1191,6 @@ static void cl_page_io_start(const struct lu_env *env, /* * Page is queued for IO, change its state. */ - ENTRY; cl_page_owner_clear(pg); cl_page_state_set(env, pg, cl_req_type_state(crt)); EXIT; @@ -1281,7 +1256,6 @@ void cl_page_completion(const struct lu_env *env, PASSERT(env, pg, pg->cp_req == NULL); PASSERT(env, pg, pg->cp_state == cl_req_type_state(crt)); - ENTRY; CL_PAGE_HEADER(D_TRACE, env, pg, "%d %d\n", crt, ioret); if (crt == CRT_READ && ioret == 0) { PASSERT(env, pg, !(pg->cp_flags & CPF_READ_COMPLETED)); @@ -1329,7 +1303,6 @@ int cl_page_make_ready(const struct lu_env *env, struct cl_page *pg, PINVRNT(env, pg, crt < CRT_NR); - ENTRY; if (crt >= CRT_NR) RETURN(-EINVAL); result = CL_PAGE_INVOKE(env, pg, CL_PAGE_OP(io[crt].cpo_make_ready), @@ -1366,8 +1339,6 @@ int cl_page_cache_add(const struct lu_env *env, struct cl_io *io, PINVRNT(env, pg, cl_page_is_owned(pg, io)); PINVRNT(env, pg, cl_page_invariant(pg)); - ENTRY; - if (crt >= CRT_NR) RETURN(-EINVAL); @@ -1400,8 +1371,6 @@ int cl_page_flush(const struct lu_env *env, struct cl_io *io, PINVRNT(env, pg, cl_page_is_owned(pg, io)); PINVRNT(env, pg, cl_page_invariant(pg)); - ENTRY; - result = cl_page_invoke(env, io, pg, CL_PAGE_OP(cpo_flush)); CL_PAGE_HEADER(D_TRACE, env, pg, "%d\n", result); @@ -1423,7 +1392,6 @@ int cl_page_is_under_lock(const struct lu_env *env, struct cl_io *io, PINVRNT(env, page, cl_page_invariant(page)); - ENTRY; rc = CL_PAGE_INVOKE(env, page, CL_PAGE_OP(cpo_is_under_lock), (const struct lu_env *, const struct cl_page_slice *, struct cl_io *), @@ -1453,7 +1421,6 @@ int cl_pages_prune(const struct lu_env *env, struct cl_object *clobj) struct cl_io *io; int result; - ENTRY; info = cl_env_info(env); io = &info->clt_io; @@ -1587,7 +1554,6 @@ void cl_page_slice_add(struct cl_page *page, struct cl_page_slice *slice, struct cl_object *obj, const struct cl_page_operations *ops) { - ENTRY; list_add_tail(&slice->cpl_linkage, &page->cp_layers); slice->cpl_obj = obj; slice->cpl_ops = ops; diff --git a/drivers/staging/lustre/lustre/obdclass/class_obd.c b/drivers/staging/lustre/lustre/obdclass/class_obd.c index deebf806cde0..07d7d2e7c543 100644 --- a/drivers/staging/lustre/lustre/obdclass/class_obd.c +++ b/drivers/staging/lustre/lustre/obdclass/class_obd.c @@ -112,7 +112,6 @@ int lustre_get_jobid(char *jobid) { int jobid_len = JOBSTATS_JOBID_SIZE; int rc = 0; - ENTRY; memset(jobid, 0, JOBSTATS_JOBID_SIZE); /* Jobstats isn't enabled */ @@ -194,7 +193,6 @@ int class_resolve_dev_name(__u32 len, const char *name) int rc; int dev; - ENTRY; if (!len || !name) { CERROR("No name passed,!\n"); GOTO(out, rc = -EINVAL); @@ -225,7 +223,6 @@ int class_handle_ioctl(unsigned int cmd, unsigned long arg) struct libcfs_debug_ioctl_data *debug_data; struct obd_device *obd = NULL; int err = 0, len = 0; - ENTRY; /* only for debugging */ if (cmd == LIBCFS_IOC_DEBUG_MASK) { @@ -639,7 +636,6 @@ static void cleanup_obdclass(void) int lustre_unregister_fs(void); __u64 memory_leaked, pages_leaked; __u64 memory_max, pages_max; - ENTRY; lustre_unregister_fs(); diff --git a/drivers/staging/lustre/lustre/obdclass/dt_object.c b/drivers/staging/lustre/lustre/obdclass/dt_object.c index 1c962dd3bd2f..0d4eca7a55f5 100644 --- a/drivers/staging/lustre/lustre/obdclass/dt_object.c +++ b/drivers/staging/lustre/lustre/obdclass/dt_object.c @@ -219,7 +219,6 @@ struct dt_object *dt_locate_at(const struct lu_env *env, struct lu_device *top_dev) { struct lu_object *lo, *n; - ENTRY; lo = lu_object_find_at(env, top_dev, fid, NULL); if (IS_ERR(lo)) @@ -376,8 +375,6 @@ struct dt_object *dt_find_or_create(const struct lu_env *env, struct thandle *th; int rc; - ENTRY; - dto = dt_locate(env, dt, fid); if (IS_ERR(dto)) RETURN(dto); @@ -659,7 +656,6 @@ static int dt_index_page_build(const struct lu_env *env, union lu_page *lp, struct lu_idxpage *lip = &lp->lp_idx; char *entry; int rc, size; - ENTRY; /* no support for variable key & record size for now */ LASSERT((ii->ii_flags & II_FL_VARKEY) == 0); @@ -763,7 +759,6 @@ int dt_index_walk(const struct lu_env *env, struct dt_object *obj, const struct dt_it_ops *iops; unsigned int pageidx, nob, nlupgs = 0; int rc; - ENTRY; LASSERT(rdpg->rp_pages != NULL); LASSERT(obj->do_index_ops != NULL); @@ -855,7 +850,6 @@ int dt_index_read(const struct lu_env *env, struct dt_device *dev, const struct dt_index_features *feat; struct dt_object *obj; int rc; - ENTRY; /* rp_count shouldn't be null and should be a multiple of the container * size */ diff --git a/drivers/staging/lustre/lustre/obdclass/genops.c b/drivers/staging/lustre/lustre/obdclass/genops.c index ea041a34f5f7..b2ec1067a29d 100644 --- a/drivers/staging/lustre/lustre/obdclass/genops.c +++ b/drivers/staging/lustre/lustre/obdclass/genops.c @@ -163,7 +163,6 @@ int class_register_type(struct obd_ops *dt_ops, struct md_ops *md_ops, { struct obd_type *type; int rc = 0; - ENTRY; /* sanity check */ LASSERT(strnlen(name, CLASS_MAX_NAME) < CLASS_MAX_NAME); @@ -231,7 +230,6 @@ EXPORT_SYMBOL(class_register_type); int class_unregister_type(const char *name) { struct obd_type *type = class_search_type(name); - ENTRY; if (!type) { CERROR("unknown obd type\n"); @@ -285,7 +283,6 @@ struct obd_device *class_newdev(const char *type_name, const char *name) struct obd_type *type = NULL; int i; int new_obd_minor = 0; - ENTRY; if (strlen(name) >= MAX_OBD_NAME) { CERROR("name/uuid must be < %u bytes long\n", MAX_OBD_NAME); @@ -635,7 +632,6 @@ EXPORT_SYMBOL(class_notify_sptlrpc_conf); void obd_cleanup_caches(void) { - ENTRY; if (obd_device_cachep) { kmem_cache_destroy(obd_device_cachep); obd_device_cachep = NULL; @@ -657,8 +653,6 @@ void obd_cleanup_caches(void) int obd_init_caches(void) { - ENTRY; - LASSERT(obd_device_cachep == NULL); obd_device_cachep = kmem_cache_create("ll_obd_dev_cache", sizeof(struct obd_device), @@ -696,7 +690,6 @@ int obd_init_caches(void) struct obd_export *class_conn2export(struct lustre_handle *conn) { struct obd_export *export; - ENTRY; if (!conn) { CDEBUG(D_CACHE, "looking for null handle\n"); @@ -757,7 +750,6 @@ EXPORT_SYMBOL(class_conn2cliimp); static void class_export_destroy(struct obd_export *exp) { struct obd_device *obd = exp->exp_obd; - ENTRY; LASSERT_ATOMIC_ZERO(&exp->exp_refcount); LASSERT(obd != NULL); @@ -828,7 +820,6 @@ struct obd_export *class_new_export(struct obd_device *obd, struct obd_export *export; cfs_hash_t *hash = NULL; int rc = 0; - ENTRY; OBD_ALLOC_PTR(export); if (!export) @@ -936,8 +927,6 @@ EXPORT_SYMBOL(class_unlink_export); /* Import management functions */ void class_import_destroy(struct obd_import *imp) { - ENTRY; - CDEBUG(D_IOCTL, "destroying import %p for %s\n", imp, imp->imp_obd->obd_name); @@ -983,8 +972,6 @@ EXPORT_SYMBOL(class_import_get); void class_import_put(struct obd_import *imp) { - ENTRY; - LASSERT(list_empty(&imp->imp_zombie_chain)); LASSERT_ATOMIC_GT_LT(&imp->imp_refcount, 0, LI_POISON); @@ -1121,7 +1108,6 @@ int class_connect(struct lustre_handle *conn, struct obd_device *obd, LASSERT(conn != NULL); LASSERT(obd != NULL); LASSERT(cluuid != NULL); - ENTRY; export = class_new_export(obd, cluuid); if (IS_ERR(export)) @@ -1188,7 +1174,6 @@ void class_export_recovery_cleanup(struct obd_export *exp) int class_disconnect(struct obd_export *export) { int already_disconnected; - ENTRY; if (export == NULL) { CWARN("attempting to free NULL export %p\n", export); @@ -1243,7 +1228,6 @@ static void class_disconnect_export_list(struct list_head *list, { int rc; struct obd_export *exp; - ENTRY; /* It's possible that an export may disconnect itself, but * nothing else will be added to this list. */ @@ -1287,7 +1271,6 @@ static void class_disconnect_export_list(struct list_head *list, void class_disconnect_exports(struct obd_device *obd) { struct list_head work_list; - ENTRY; /* Move all of the exports from obd_exports to a work list, en masse. */ INIT_LIST_HEAD(&work_list); @@ -1316,7 +1299,6 @@ void class_disconnect_stale_exports(struct obd_device *obd, struct list_head work_list; struct obd_export *exp, *n; int evicted = 0; - ENTRY; INIT_LIST_HEAD(&work_list); spin_lock(&obd->obd_dev_lock); @@ -1585,7 +1567,6 @@ void obd_zombie_impexp_cull(void) { struct obd_import *import; struct obd_export *export; - ENTRY; do { spin_lock(&obd_zombie_impexp_lock); diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c index 9fe53f3a98ce..a3cb92f6ae9c 100644 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c +++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c @@ -83,7 +83,6 @@ int obd_ioctl_getdata(char **buf, int *len, void *arg) struct obd_ioctl_data *data; int err; int offset = 0; - ENTRY; err = copy_from_user(&hdr, (void *)arg, sizeof(hdr)); if ( err ) @@ -169,8 +168,6 @@ EXPORT_SYMBOL(obd_ioctl_popdata); /* opening /dev/obd */ static int obd_class_open(struct inode * inode, struct file * file) { - ENTRY; - try_module_get(THIS_MODULE); RETURN(0); } @@ -178,8 +175,6 @@ static int obd_class_open(struct inode * inode, struct file * file) /* closing /dev/obd */ static int obd_class_release(struct inode * inode, struct file * file) { - ENTRY; - module_put(THIS_MODULE); RETURN(0); } @@ -189,7 +184,6 @@ static long obd_class_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { int err = 0; - ENTRY; /* Allow non-root access for OBD_IOC_PING_TARGET - used by lfs check */ if (!cfs_capable(CFS_CAP_SYS_ADMIN) && (cmd != OBD_IOC_PING_TARGET)) @@ -386,7 +380,6 @@ struct file_operations obd_device_list_fops = { int class_procfs_init(void) { int rc = 0; - ENTRY; obd_sysctl_init(); proc_lustre_root = lprocfs_register("fs/lustre", NULL, @@ -407,7 +400,6 @@ out: int class_procfs_clean(void) { - ENTRY; if (proc_lustre_root) { lprocfs_remove(&proc_lustre_root); } diff --git a/drivers/staging/lustre/lustre/obdclass/llog.c b/drivers/staging/lustre/lustre/obdclass/llog.c index b1d215e56991..a154cc5e5753 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog.c +++ b/drivers/staging/lustre/lustre/obdclass/llog.c @@ -111,7 +111,6 @@ int llog_cancel_rec(const struct lu_env *env, struct llog_handle *loghandle, { struct llog_log_hdr *llh = loghandle->lgh_hdr; int rc = 0; - ENTRY; CDEBUG(D_RPCTRACE, "Canceling %d in log "DOSTID"\n", index, POSTID(&loghandle->lgh_id.lgl_oi)); @@ -206,7 +205,6 @@ int llog_init_handle(const struct lu_env *env, struct llog_handle *handle, struct llog_log_hdr *llh; int rc; - ENTRY; LASSERT(handle->lgh_hdr == NULL); OBD_ALLOC_PTR(llh); @@ -277,7 +275,6 @@ int llog_copy_handler(const struct lu_env *env, char *cfg_buf = (char*) (rec + 1); struct lustre_cfg *lcfg; int rc = 0; - ENTRY; /* Append all records */ local_rec.lrh_len -= sizeof(*rec) + sizeof(struct llog_rec_tail); @@ -306,8 +303,6 @@ static int llog_process_thread(void *arg) int saved_index = 0; int last_called_index = 0; - ENTRY; - LASSERT(llh); OBD_ALLOC(buf, LLOG_CHUNK_SIZE); @@ -457,8 +452,6 @@ int llog_process_or_fork(const struct lu_env *env, struct llog_process_info *lpi; int rc; - ENTRY; - OBD_ALLOC_PTR(lpi); if (lpi == NULL) { CERROR("cannot alloc pointer\n"); @@ -516,7 +509,6 @@ int llog_reverse_process(const struct lu_env *env, struct llog_process_cat_data *cd = catdata; void *buf; int rc = 0, first_index = 1, index, idx; - ENTRY; OBD_ALLOC(buf, LLOG_CHUNK_SIZE); if (!buf) @@ -617,8 +609,6 @@ int llog_exist(struct llog_handle *loghandle) struct llog_operations *lop; int rc; - ENTRY; - rc = llog_handle2ops(loghandle, &lop); if (rc) RETURN(rc); @@ -636,8 +626,6 @@ int llog_declare_create(const struct lu_env *env, struct llog_operations *lop; int raised, rc; - ENTRY; - rc = llog_handle2ops(loghandle, &lop); if (rc) RETURN(rc); @@ -660,8 +648,6 @@ int llog_create(const struct lu_env *env, struct llog_handle *handle, struct llog_operations *lop; int raised, rc; - ENTRY; - rc = llog_handle2ops(handle, &lop); if (rc) RETURN(rc); @@ -686,8 +672,6 @@ int llog_declare_write_rec(const struct lu_env *env, struct llog_operations *lop; int raised, rc; - ENTRY; - rc = llog_handle2ops(handle, &lop); if (rc) RETURN(rc); @@ -712,8 +696,6 @@ int llog_write_rec(const struct lu_env *env, struct llog_handle *handle, struct llog_operations *lop; int raised, rc, buflen; - ENTRY; - rc = llog_handle2ops(handle, &lop); if (rc) RETURN(rc); @@ -746,8 +728,6 @@ int llog_add(const struct lu_env *env, struct llog_handle *lgh, { int raised, rc; - ENTRY; - if (lgh->lgh_logops->lop_add == NULL) RETURN(-EOPNOTSUPP); @@ -766,8 +746,6 @@ int llog_declare_add(const struct lu_env *env, struct llog_handle *lgh, { int raised, rc; - ENTRY; - if (lgh->lgh_logops->lop_declare_add == NULL) RETURN(-EOPNOTSUPP); @@ -792,8 +770,6 @@ int llog_open_create(const struct lu_env *env, struct llog_ctxt *ctxt, struct thandle *th; int rc; - ENTRY; - rc = llog_open(env, ctxt, res, logid, name, LLOG_OPEN_NEW); if (rc) RETURN(rc); @@ -838,8 +814,6 @@ int llog_erase(const struct lu_env *env, struct llog_ctxt *ctxt, struct llog_handle *handle; int rc = 0, rc2; - ENTRY; - /* nothing to erase */ if (name == NULL && logid == NULL) RETURN(0); @@ -870,8 +844,6 @@ int llog_write(const struct lu_env *env, struct llog_handle *loghandle, { int rc; - ENTRY; - LASSERT(loghandle); LASSERT(loghandle->lgh_ctxt); @@ -916,8 +888,6 @@ int llog_open(const struct lu_env *env, struct llog_ctxt *ctxt, int raised; int rc; - ENTRY; - LASSERT(ctxt); LASSERT(ctxt->loc_logops); @@ -951,8 +921,6 @@ int llog_close(const struct lu_env *env, struct llog_handle *loghandle) struct llog_operations *lop; int rc; - ENTRY; - rc = llog_handle2ops(loghandle, &lop); if (rc) GOTO(out, rc); diff --git a/drivers/staging/lustre/lustre/obdclass/llog_cat.c b/drivers/staging/lustre/lustre/obdclass/llog_cat.c index cf00b2f550ac..08b950802ae7 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog_cat.c +++ b/drivers/staging/lustre/lustre/obdclass/llog_cat.c @@ -67,7 +67,6 @@ static int llog_cat_new_log(const struct lu_env *env, struct llog_log_hdr *llh; struct llog_logid_rec rec = { { 0 }, }; int rc, index, bitmap_size; - ENTRY; llh = cathandle->lgh_hdr; bitmap_size = LLOG_BITMAP_SIZE(llh); @@ -155,8 +154,6 @@ int llog_cat_id2handle(const struct lu_env *env, struct llog_handle *cathandle, struct llog_handle *loghandle; int rc = 0; - ENTRY; - if (cathandle == NULL) RETURN(-EBADF); @@ -217,8 +214,6 @@ int llog_cat_close(const struct lu_env *env, struct llog_handle *cathandle) struct llog_handle *loghandle, *n; int rc; - ENTRY; - list_for_each_entry_safe(loghandle, n, &cathandle->u.chd.chd_head, u.phd.phd_entry) { struct llog_log_hdr *llh = loghandle->lgh_hdr; @@ -272,7 +267,6 @@ static struct llog_handle *llog_cat_current_log(struct llog_handle *cathandle, struct thandle *th) { struct llog_handle *loghandle = NULL; - ENTRY; down_read_nested(&cathandle->lgh_lock, LLOGH_CAT); loghandle = cathandle->u.chd.chd_current_log; @@ -332,7 +326,6 @@ int llog_cat_add_rec(const struct lu_env *env, struct llog_handle *cathandle, { struct llog_handle *loghandle; int rc; - ENTRY; LASSERT(rec->lrh_len <= LLOG_CHUNK_SIZE); loghandle = llog_cat_current_log(cathandle, th); @@ -383,8 +376,6 @@ int llog_cat_declare_add_rec(const struct lu_env *env, struct llog_handle *loghandle, *next; int rc = 0; - ENTRY; - if (cathandle->u.chd.chd_current_log == NULL) { /* declare new plain llog */ down_write(&cathandle->lgh_lock); @@ -498,8 +489,6 @@ int llog_cat_cancel_records(const struct lu_env *env, { int i, index, rc = 0, failed = 0; - ENTRY; - for (i = 0; i < count; i++, cookies++) { struct llog_handle *loghandle; struct llog_logid *lgl = &cookies->lgc_lgl; @@ -545,7 +534,6 @@ int llog_cat_process_cb(const struct lu_env *env, struct llog_handle *cat_llh, struct llog_handle *llh; int rc; - ENTRY; if (rec->lrh_type != LLOG_LOGID_MAGIC) { CERROR("invalid record in catalog\n"); RETURN(-EINVAL); @@ -592,7 +580,6 @@ int llog_cat_process_or_fork(const struct lu_env *env, struct llog_process_data d; struct llog_log_hdr *llh = cat_llh->lgh_hdr; int rc; - ENTRY; LASSERT(llh->llh_flags & LLOG_F_IS_CAT); d.lpd_data = data; @@ -672,7 +659,6 @@ int llog_cat_reverse_process(const struct lu_env *env, struct llog_process_cat_data cd; struct llog_log_hdr *llh = cat_llh->lgh_hdr; int rc; - ENTRY; LASSERT(llh->llh_flags & LLOG_F_IS_CAT); d.lpd_data = data; @@ -709,7 +695,6 @@ int llog_cat_set_first_idx(struct llog_handle *cathandle, int index) { struct llog_log_hdr *llh = cathandle->lgh_hdr; int i, bitmap_size, idx; - ENTRY; bitmap_size = LLOG_BITMAP_SIZE(llh); if (llh->llh_cat_idx == (index - 1)) { @@ -774,8 +759,6 @@ int cat_cancel_cb(const struct lu_env *env, struct llog_handle *cathandle, struct llog_log_hdr *llh; int rc; - ENTRY; - if (rec->lrh_type != LLOG_LOGID_MAGIC) { CERROR("invalid record in catalog\n"); RETURN(-EINVAL); diff --git a/drivers/staging/lustre/lustre/obdclass/llog_ioctl.c b/drivers/staging/lustre/lustre/obdclass/llog_ioctl.c index 0732874e26c5..1c83ec217ad5 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog_ioctl.c +++ b/drivers/staging/lustre/lustre/obdclass/llog_ioctl.c @@ -45,7 +45,6 @@ static int str2logid(struct llog_logid *logid, char *str, int len) char *start, *end, *endp; __u64 id, seq; - ENTRY; start = str; if (*start != '#') RETURN(-EINVAL); @@ -96,8 +95,6 @@ static int llog_check_cb(const struct lu_env *env, struct llog_handle *handle, char *endp; int cur_index, rc = 0; - ENTRY; - if (ioc_data && ioc_data->ioc_inllen1 > 0) { l = 0; remains = ioc_data->ioc_inllen4 + @@ -182,7 +179,6 @@ static int llog_print_cb(const struct lu_env *env, struct llog_handle *handle, char *endp; int cur_index; - ENTRY; if (ioc_data != NULL && ioc_data->ioc_inllen1 > 0) { l = 0; remains = ioc_data->ioc_inllen4 + @@ -244,8 +240,6 @@ static int llog_remove_log(const struct lu_env *env, struct llog_handle *cat, struct llog_handle *log; int rc; - ENTRY; - rc = llog_cat_id2handle(env, cat, &log, logid); if (rc) { CDEBUG(D_IOCTL, "cannot find log #"DOSTID"#%08x\n", @@ -271,7 +265,6 @@ static int llog_delete_cb(const struct lu_env *env, struct llog_handle *handle, struct llog_logid_rec *lir = (struct llog_logid_rec *)rec; int rc; - ENTRY; if (rec->lrh_type != LLOG_LOGID_MAGIC) RETURN(-EINVAL); rc = llog_remove_log(env, handle, &lir->lid_id); @@ -287,8 +280,6 @@ int llog_ioctl(const struct lu_env *env, struct llog_ctxt *ctxt, int cmd, int rc = 0; struct llog_handle *handle = NULL; - ENTRY; - if (*data->ioc_inlbuf1 == '#') { rc = str2logid(&logid, data->ioc_inlbuf1, data->ioc_inllen1); if (rc) diff --git a/drivers/staging/lustre/lustre/obdclass/llog_lvfs.c b/drivers/staging/lustre/lustre/obdclass/llog_lvfs.c index 7e12dc62141f..6543ba9b9e3d 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog_lvfs.c +++ b/drivers/staging/lustre/lustre/obdclass/llog_lvfs.c @@ -64,7 +64,6 @@ static int llog_lvfs_pad(struct obd_device *obd, struct l_file *file, struct llog_rec_hdr rec = { 0 }; struct llog_rec_tail tail; int rc; - ENTRY; LASSERT(len >= LLOG_MIN_REC_SIZE && (len & 0x7) == 0); @@ -97,8 +96,6 @@ static int llog_lvfs_write_blob(struct obd_device *obd, struct l_file *file, loff_t saved_off = file->f_pos; int buflen = rec->lrh_len; - ENTRY; - file->f_pos = off; if (buflen == 0) @@ -148,7 +145,6 @@ static int llog_lvfs_read_blob(struct obd_device *obd, struct l_file *file, { loff_t offset = off; int rc; - ENTRY; rc = fsfilt_read_record(obd, file, buf, size, &offset); if (rc) { @@ -163,7 +159,6 @@ static int llog_lvfs_read_header(const struct lu_env *env, { struct obd_device *obd; int rc; - ENTRY; LASSERT(sizeof(*handle->lgh_hdr) == LLOG_CHUNK_SIZE); @@ -223,7 +218,6 @@ static int llog_lvfs_write_rec(const struct lu_env *env, struct obd_device *obd; struct file *file; size_t left; - ENTRY; llh = loghandle->lgh_hdr; file = loghandle->lgh_file; @@ -391,7 +385,6 @@ static int llog_lvfs_next_block(const struct lu_env *env, int len) { int rc; - ENTRY; if (len == 0 || len & (LLOG_CHUNK_SIZE - 1)) RETURN(-EINVAL); @@ -484,7 +477,6 @@ static int llog_lvfs_prev_block(const struct lu_env *env, { __u64 cur_offset; int rc; - ENTRY; if (len == 0 || len & (LLOG_CHUNK_SIZE - 1)) RETURN(-EINVAL); @@ -593,8 +585,6 @@ static int llog_lvfs_open(const struct lu_env *env, struct llog_handle *handle, struct obd_device *obd; int rc = 0; - ENTRY; - LASSERT(ctxt); LASSERT(ctxt->loc_exp); LASSERT(ctxt->loc_exp->exp_obd); @@ -688,8 +678,6 @@ static int llog_lvfs_create(const struct lu_env *env, int rc = 0; int open_flags = O_RDWR | O_CREAT | O_LARGEFILE; - ENTRY; - LASSERT(ctxt); LASSERT(ctxt->loc_exp); obd = ctxt->loc_exp->exp_obd; @@ -744,8 +732,6 @@ static int llog_lvfs_close(const struct lu_env *env, { int rc; - ENTRY; - if (handle->lgh_file == NULL) RETURN(0); rc = filp_close(handle->lgh_file, 0); @@ -772,7 +758,6 @@ static int llog_lvfs_destroy(const struct lu_env *env, void *th; struct inode *inode; int rc, rc1; - ENTRY; dir = MOUNT_CONFIGS_DIR; diff --git a/drivers/staging/lustre/lustre/obdclass/llog_obd.c b/drivers/staging/lustre/lustre/obdclass/llog_obd.c index 7e2290796315..7d6c94b463a3 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog_obd.c +++ b/drivers/staging/lustre/lustre/obdclass/llog_obd.c @@ -110,7 +110,6 @@ int llog_cleanup(const struct lu_env *env, struct llog_ctxt *ctxt) struct l_wait_info lwi = LWI_INTR(LWI_ON_SIGNAL_NOOP, NULL); struct obd_llog_group *olg; int rc, idx; - ENTRY; LASSERT(ctxt != NULL); LASSERT(ctxt != LP_POISON); @@ -149,7 +148,6 @@ int llog_setup(const struct lu_env *env, struct obd_device *obd, { struct llog_ctxt *ctxt; int rc = 0; - ENTRY; if (index < 0 || index >= LLOG_MAX_CTXTS) RETURN(-EINVAL); @@ -217,7 +215,6 @@ EXPORT_SYMBOL(llog_setup); int llog_sync(struct llog_ctxt *ctxt, struct obd_export *exp, int flags) { int rc = 0; - ENTRY; if (!ctxt) RETURN(0); @@ -234,7 +231,6 @@ int llog_obd_add(const struct lu_env *env, struct llog_ctxt *ctxt, struct llog_cookie *logcookies, int numcookies) { int raised, rc; - ENTRY; if (!ctxt) { CERROR("No ctxt\n"); @@ -261,7 +257,6 @@ int llog_cancel(const struct lu_env *env, struct llog_ctxt *ctxt, struct llog_cookie *cookies, int flags) { int rc; - ENTRY; if (!ctxt) { CERROR("No ctxt\n"); @@ -278,7 +273,7 @@ int obd_llog_init(struct obd_device *obd, struct obd_llog_group *olg, struct obd_device *disk_obd, int *index) { int rc; - ENTRY; + OBD_CHECK_DT_OP(obd, llog_init, 0); OBD_COUNTER_INCREMENT(obd, llog_init); @@ -290,7 +285,7 @@ EXPORT_SYMBOL(obd_llog_init); int obd_llog_finish(struct obd_device *obd, int count) { int rc; - ENTRY; + OBD_CHECK_DT_OP(obd, llog_finish, 0); OBD_COUNTER_INCREMENT(obd, llog_finish); diff --git a/drivers/staging/lustre/lustre/obdclass/llog_osd.c b/drivers/staging/lustre/lustre/obdclass/llog_osd.c index 87d5012cfc56..5569d8d55e00 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog_osd.c +++ b/drivers/staging/lustre/lustre/obdclass/llog_osd.c @@ -93,8 +93,6 @@ static int llog_osd_pad(const struct lu_env *env, struct dt_object *o, struct llog_thread_info *lgi = llog_info(env); int rc; - ENTRY; - LASSERT(th); LASSERT(off); LASSERT(len >= LLOG_MIN_REC_SIZE && (len & 0x7) == 0); @@ -133,8 +131,6 @@ static int llog_osd_write_blob(const struct lu_env *env, struct dt_object *o, int buflen = rec->lrh_len; int rc; - ENTRY; - LASSERT(env); LASSERT(o); @@ -210,8 +206,6 @@ static int llog_osd_read_header(const struct lu_env *env, struct llog_thread_info *lgi; int rc; - ENTRY; - LASSERT(sizeof(*handle->lgh_hdr) == LLOG_CHUNK_SIZE); o = handle->lgh_obj; @@ -278,8 +272,6 @@ static int llog_osd_declare_write_rec(const struct lu_env *env, struct dt_object *o; int rc; - ENTRY; - LASSERT(env); LASSERT(th); LASSERT(loghandle); @@ -329,8 +321,6 @@ static int llog_osd_write_rec(const struct lu_env *env, struct dt_object *o; size_t left; - ENTRY; - LASSERT(env); llh = loghandle->lgh_hdr; LASSERT(llh); @@ -537,8 +527,6 @@ static int llog_osd_next_block(const struct lu_env *env, struct dt_device *dt; int rc; - ENTRY; - LASSERT(env); LASSERT(lgi); @@ -664,8 +652,6 @@ static int llog_osd_prev_block(const struct lu_env *env, loff_t cur_offset; int rc; - ENTRY; - if (len == 0 || len & (LLOG_CHUNK_SIZE - 1)) RETURN(-EINVAL); @@ -794,8 +780,6 @@ static int llog_osd_open(const struct lu_env *env, struct llog_handle *handle, struct local_oid_storage *los; int rc = 0; - ENTRY; - LASSERT(env); LASSERT(ctxt); LASSERT(ctxt->loc_exp); @@ -887,8 +871,6 @@ static int llog_osd_declare_create(const struct lu_env *env, struct dt_object *o; int rc; - ENTRY; - LASSERT(res->lgh_obj); LASSERT(th); @@ -937,8 +919,6 @@ static int llog_osd_create(const struct lu_env *env, struct llog_handle *res, struct dt_object *o; int rc = 0; - ENTRY; - LASSERT(env); o = res->lgh_obj; LASSERT(o); @@ -988,8 +968,6 @@ static int llog_osd_close(const struct lu_env *env, struct llog_handle *handle) struct local_oid_storage *los; int rc = 0; - ENTRY; - LASSERT(handle->lgh_obj); lu_object_put(env, &handle->lgh_obj->do_lu); @@ -1014,8 +992,6 @@ static int llog_osd_destroy(const struct lu_env *env, char *name = NULL; int rc; - ENTRY; - ctxt = loghandle->lgh_ctxt; LASSERT(ctxt); @@ -1090,8 +1066,6 @@ static int llog_osd_setup(const struct lu_env *env, struct obd_device *obd, struct llog_ctxt *ctxt; int rc = 0; - ENTRY; - LASSERT(obd); LASSERT(olg->olg_ctxts[ctxt_idx]); @@ -1171,8 +1145,6 @@ int llog_osd_get_cat_list(const struct lu_env *env, struct dt_device *d, struct thandle *th; int rc, size; - ENTRY; - LASSERT(d); size = sizeof(*idarray) * count; diff --git a/drivers/staging/lustre/lustre/obdclass/llog_swab.c b/drivers/staging/lustre/lustre/obdclass/llog_swab.c index a75b04ee5272..5cf15d20bb1f 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog_swab.c +++ b/drivers/staging/lustre/lustre/obdclass/llog_swab.c @@ -88,7 +88,6 @@ EXPORT_SYMBOL(lustre_swab_llog_id); void lustre_swab_llogd_body (struct llogd_body *d) { - ENTRY; print_llogd_body(d); lustre_swab_llog_id(&d->lgd_logid); __swab32s (&d->lgd_ctxt_idx); @@ -298,7 +297,6 @@ static void print_llog_hdr(struct llog_log_hdr *h) void lustre_swab_llog_hdr (struct llog_log_hdr *h) { - ENTRY; print_llog_hdr(h); lustre_swab_llog_rec(&h->llh_hdr); @@ -311,7 +309,6 @@ EXPORT_SYMBOL(lustre_swab_llog_hdr); static void print_lustre_cfg(struct lustre_cfg *lcfg) { int i; - ENTRY; if (!(libcfs_debug & D_OTHER)) /* don't loop on nothing */ return; @@ -334,7 +331,6 @@ static void print_lustre_cfg(struct lustre_cfg *lcfg) void lustre_swab_lustre_cfg(struct lustre_cfg *lcfg) { int i; - ENTRY; __swab32s(&lcfg->lcfg_version); @@ -377,7 +373,6 @@ struct cfg_marker32 { void lustre_swab_cfg_marker(struct cfg_marker *marker, int swab, int size) { struct cfg_marker32 *cm32 = (struct cfg_marker32*)marker; - ENTRY; if (swab) { __swab32s(&marker->cm_step); diff --git a/drivers/staging/lustre/lustre/obdclass/llog_test.c b/drivers/staging/lustre/lustre/obdclass/llog_test.c index d397f781ec43..d3fd2461a07a 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog_test.c +++ b/drivers/staging/lustre/lustre/obdclass/llog_test.c @@ -105,8 +105,6 @@ static int llog_test_1(const struct lu_env *env, int rc; int rc2; - ENTRY; - CWARN("1a: create a log with name: %s\n", name); ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT); LASSERT(ctxt); @@ -146,8 +144,6 @@ static int llog_test_2(const struct lu_env *env, struct obd_device *obd, struct llog_logid logid; int rc; - ENTRY; - CWARN("2a: re-open a log with name: %s\n", name); ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT); LASSERT(ctxt); @@ -224,8 +220,6 @@ static int llog_test_3(const struct lu_env *env, struct obd_device *obd, int rc, i; int num_recs = 1; /* 1 for the header */ - ENTRY; - lgr.lgr_hdr.lrh_len = lgr.lgr_tail.lrt_len = sizeof(lgr); lgr.lgr_hdr.lrh_type = LLOG_GEN_REC; @@ -328,8 +322,6 @@ static int llog_test_4(const struct lu_env *env, struct obd_device *obd) char *buf; struct llog_rec_hdr rec; - ENTRY; - ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT); LASSERT(ctxt); @@ -505,8 +497,6 @@ static int llog_test_5(const struct lu_env *env, struct obd_device *obd) struct llog_mini_rec lmr; struct llog_ctxt *ctxt; - ENTRY; - ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT); LASSERT(ctxt); @@ -728,8 +718,6 @@ static int llog_test_7_sub(const struct lu_env *env, struct llog_ctxt *ctxt) int rc = 0, i, process_count; int num_recs = 0; - ENTRY; - rc = llog_open_create(env, ctxt, &llh, NULL, NULL); if (rc) { CERROR("7_sub: create log failed\n"); @@ -813,8 +801,6 @@ static int llog_test_7(const struct lu_env *env, struct obd_device *obd) struct llog_ctxt *ctxt; int rc; - ENTRY; - ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT); CWARN("7a: test llog_logid_rec\n"); @@ -908,7 +894,6 @@ static int llog_run_tests(const struct lu_env *env, struct obd_device *obd) int rc, err; char name[10]; - ENTRY; ctxt = llog_get_context(obd, LLOG_TEST_ORIG_CTXT); LASSERT(ctxt); @@ -970,8 +955,6 @@ static int llog_test_cleanup(struct obd_device *obd) struct lu_env env; int rc; - ENTRY; - rc = lu_env_init(&env, LCT_LOCAL | LCT_MG_THREAD); if (rc) RETURN(rc); @@ -993,8 +976,6 @@ static int llog_test_setup(struct obd_device *obd, struct lustre_cfg *lcfg) struct lu_context test_session; int rc; - ENTRY; - if (lcfg->lcfg_bufcount < 2) { CERROR("requires a TARGET OBD name\n"); RETURN(-EINVAL); diff --git a/drivers/staging/lustre/lustre/obdclass/local_storage.c b/drivers/staging/lustre/lustre/obdclass/local_storage.c index e1db7abd300a..6d8d7e7aec50 100644 --- a/drivers/staging/lustre/lustre/obdclass/local_storage.c +++ b/drivers/staging/lustre/lustre/obdclass/local_storage.c @@ -45,8 +45,6 @@ static int ls_object_init(const struct lu_env *env, struct lu_object *o, struct lu_object *below; struct lu_device *under; - ENTRY; - ls = container_of0(o->lo_dev, struct ls_device, ls_top_dev.dd_lu_dev); under = &ls->ls_osd->dd_lu_dev; below = under->ld_ops->ldo_object_alloc(env, o->lo_header, under); @@ -143,8 +141,6 @@ struct ls_device *ls_device_get(struct dt_device *dev) { struct ls_device *ls; - ENTRY; - mutex_lock(&ls_list_mutex); ls = __ls_find_dev(dev); if (ls) @@ -224,8 +220,6 @@ int local_object_declare_create(const struct lu_env *env, struct dt_thread_info *dti = dt_info(env); int rc; - ENTRY; - /* update fid generation file */ if (los != NULL) { LASSERT(dt_object_exists(los->los_obj)); @@ -255,8 +249,6 @@ int local_object_create(const struct lu_env *env, obd_id lastid; int rc; - ENTRY; - rc = dt_create(env, o, attr, NULL, dof, th); if (rc) RETURN(rc); @@ -588,8 +580,6 @@ int local_object_unlink(const struct lu_env *env, struct dt_device *dt, struct thandle *th; int rc; - ENTRY; - rc = dt_lookup_dir(env, parent, name, &dti->dti_fid); if (rc == -ENOENT) RETURN(0); @@ -761,8 +751,6 @@ int local_oid_storage_init(const struct lu_env *env, struct dt_device *dev, __u32 first_oid = fid_oid(first_fid); int rc = 0; - ENTRY; - ls = ls_device_get(dev); if (IS_ERR(ls)) RETURN(PTR_ERR(ls)); diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c index e57a922eda59..090b669c35d1 100644 --- a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c +++ b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c @@ -900,7 +900,6 @@ void lprocfs_free_per_client_stats(struct obd_device *obd) { cfs_hash_t *hash = obd->obd_nid_stats_hash; struct nid_stat *stat; - ENTRY; /* we need extra list - because hash_exit called to early */ /* not need locking because all clients is died */ @@ -1498,7 +1497,6 @@ EXPORT_SYMBOL(lprocfs_nid_stats_clear_read); static int lprocfs_nid_stats_clear_write_cb(void *obj, void *data) { struct nid_stat *stat = obj; - ENTRY; CDEBUG(D_INFO,"refcnt %d\n", atomic_read(&stat->nid_exp_ref_count)); if (atomic_read(&stat->nid_exp_ref_count) == 1) { @@ -1543,7 +1541,6 @@ int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *nid, int *newnid) proc_dir_entry_t *entry; char *buffer = NULL; int rc = 0; - ENTRY; *newnid = 0; @@ -1910,7 +1907,6 @@ int lprocfs_seq_create(proc_dir_entry_t *parent, void *data) { struct proc_dir_entry *entry; - ENTRY; /* Disallow secretly (un)writable entries. */ LASSERT((seq_fops->write == NULL) == ((mode & 0222) == 0)); diff --git a/drivers/staging/lustre/lustre/obdclass/lu_object.c b/drivers/staging/lustre/lustre/obdclass/lu_object.c index 896f24a8b3b6..9efa8dc255b5 100644 --- a/drivers/staging/lustre/lustre/obdclass/lu_object.c +++ b/drivers/staging/lustre/lustre/obdclass/lu_object.c @@ -202,7 +202,6 @@ static struct lu_object *lu_object_alloc(const struct lu_env *env, struct list_head *layers; int clean; int result; - ENTRY; /* * Create top-level object slice. This will also create @@ -980,7 +979,6 @@ int lu_site_init(struct lu_site *s, struct lu_device *top) char name[16]; int bits; int i; - ENTRY; memset(s, 0, sizeof *s); bits = lu_htable_order(); diff --git a/drivers/staging/lustre/lustre/obdclass/lustre_handles.c b/drivers/staging/lustre/lustre/obdclass/lustre_handles.c index 69d6499ef731..de80aea70721 100644 --- a/drivers/staging/lustre/lustre/obdclass/lustre_handles.c +++ b/drivers/staging/lustre/lustre/obdclass/lustre_handles.c @@ -65,7 +65,6 @@ void class_handle_hash(struct portals_handle *h, struct portals_handle_ops *ops) { struct handle_bucket *bucket; - ENTRY; LASSERT(h != NULL); LASSERT(list_empty(&h->h_link)); @@ -139,7 +138,6 @@ EXPORT_SYMBOL(class_handle_unhash); void class_handle_hash_back(struct portals_handle *h) { struct handle_bucket *bucket; - ENTRY; bucket = handle_hash + (h->h_cookie & HANDLE_HASH_MASK); @@ -157,7 +155,6 @@ void *class_handle2object(__u64 cookie) struct handle_bucket *bucket; struct portals_handle *h; void *retval = NULL; - ENTRY; LASSERT(handle_hash != NULL); diff --git a/drivers/staging/lustre/lustre/obdclass/lustre_peer.c b/drivers/staging/lustre/lustre/obdclass/lustre_peer.c index 2fa2589dc8eb..81ced81d32af 100644 --- a/drivers/staging/lustre/lustre/obdclass/lustre_peer.c +++ b/drivers/staging/lustre/lustre/obdclass/lustre_peer.c @@ -191,7 +191,6 @@ int class_check_uuid(struct obd_uuid *uuid, __u64 nid) { struct uuid_nid_data *entry; int found = 0; - ENTRY; CDEBUG(D_INFO, "check if uuid %s has %s.\n", obd_uuid2str(uuid), libcfs_nid2str(nid)); diff --git a/drivers/staging/lustre/lustre/obdclass/md_attrs.c b/drivers/staging/lustre/lustre/obdclass/md_attrs.c index b71344a04c7e..03795f3cbd71 100644 --- a/drivers/staging/lustre/lustre/obdclass/md_attrs.c +++ b/drivers/staging/lustre/lustre/obdclass/md_attrs.c @@ -99,7 +99,6 @@ EXPORT_SYMBOL(lustre_som_swab); int lustre_buf2som(void *buf, int rc, struct md_som_data *msd) { struct som_attrs *attrs = (struct som_attrs *)buf; - ENTRY; if (rc == 0 || rc == -ENODATA) /* no SOM attributes */ @@ -156,7 +155,6 @@ EXPORT_SYMBOL(lustre_hsm_swab); int lustre_buf2hsm(void *buf, int rc, struct md_hsm *mh) { struct hsm_attrs *attrs = (struct hsm_attrs *)buf; - ENTRY; if (rc == 0 || rc == -ENODATA) /* no HSM attributes */ @@ -188,7 +186,6 @@ EXPORT_SYMBOL(lustre_buf2hsm); void lustre_hsm2buf(void *buf, struct md_hsm *mh) { struct hsm_attrs *attrs = (struct hsm_attrs *)buf; - ENTRY; /* copy HSM attributes */ attrs->hsm_compat = mh->mh_compat; diff --git a/drivers/staging/lustre/lustre/obdclass/obd_config.c b/drivers/staging/lustre/lustre/obdclass/obd_config.c index 8b5eb6c3b078..278e7d2e103f 100644 --- a/drivers/staging/lustre/lustre/obdclass/obd_config.c +++ b/drivers/staging/lustre/lustre/obdclass/obd_config.c @@ -335,7 +335,6 @@ int class_attach(struct lustre_cfg *lcfg) struct obd_device *obd = NULL; char *typename, *name, *uuid; int rc, len; - ENTRY; if (!LUSTRE_CFG_BUFLEN(lcfg, 1)) { CERROR("No type passed!\n"); @@ -449,7 +448,6 @@ int class_setup(struct obd_device *obd, struct lustre_cfg *lcfg) { int err = 0; struct obd_export *exp; - ENTRY; LASSERT(obd != NULL); LASSERTF(obd == class_num2obd(obd->obd_minor), @@ -572,8 +570,6 @@ EXPORT_SYMBOL(class_setup); */ int class_detach(struct obd_device *obd, struct lustre_cfg *lcfg) { - ENTRY; - if (obd->obd_set_up) { CERROR("OBD device %d still set up\n", obd->obd_minor); RETURN(-EBUSY); @@ -604,7 +600,6 @@ int class_cleanup(struct obd_device *obd, struct lustre_cfg *lcfg) { int err = 0; char *flag; - ENTRY; OBD_RACE(OBD_FAIL_LDLM_RECOV_CLIENTS); @@ -767,7 +762,6 @@ int class_add_conn(struct obd_device *obd, struct lustre_cfg *lcfg) struct obd_import *imp; struct obd_uuid uuid; int rc; - ENTRY; if (LUSTRE_CFG_BUFLEN(lcfg, 1) < 1 || LUSTRE_CFG_BUFLEN(lcfg, 1) > sizeof(struct obd_uuid)) { @@ -803,7 +797,6 @@ int class_del_conn(struct obd_device *obd, struct lustre_cfg *lcfg) struct obd_import *imp; struct obd_uuid uuid; int rc; - ENTRY; if (LUSTRE_CFG_BUFLEN(lcfg, 1) < 1 || LUSTRE_CFG_BUFLEN(lcfg, 1) > sizeof(struct obd_uuid)) { @@ -834,7 +827,6 @@ struct lustre_profile *class_get_profile(const char * prof) { struct lustre_profile *lprof; - ENTRY; list_for_each_entry(lprof, &lustre_profile_list, lp_list) { if (!strcmp(lprof->lp_profile, prof)) { RETURN(lprof); @@ -853,7 +845,6 @@ int class_add_profile(int proflen, char *prof, int osclen, char *osc, { struct lustre_profile *lprof; int err = 0; - ENTRY; CDEBUG(D_CONFIG, "Add profile %s\n", prof); @@ -899,7 +890,6 @@ out: void class_del_profile(const char *prof) { struct lustre_profile *lprof; - ENTRY; CDEBUG(D_CONFIG, "Del profile %s\n", prof); @@ -920,7 +910,6 @@ EXPORT_SYMBOL(class_del_profile); void class_del_profiles(void) { struct lustre_profile *lprof, *n; - ENTRY; list_for_each_entry_safe(lprof, n, &lustre_profile_list, lp_list) { list_del(&lprof->lp_list); @@ -936,7 +925,6 @@ EXPORT_SYMBOL(class_del_profiles); static int class_set_global(char *ptr, int val, struct lustre_cfg *lcfg) { - ENTRY; if (class_match_param(ptr, PARAM_AT_MIN, NULL) == 0) at_min = val; else if (class_match_param(ptr, PARAM_AT_MAX, NULL) == 0) @@ -991,7 +979,6 @@ struct lustre_cfg *lustre_cfg_rename(struct lustre_cfg *cfg, char *value = NULL; int name_len = 0; int new_len = 0; - ENTRY; if (cfg == NULL || new_name == NULL) RETURN(ERR_PTR(-EINVAL)); @@ -1244,7 +1231,6 @@ int class_process_proc_param(char *prefix, struct lprocfs_vars *lvars, int matched = 0, j = 0; int rc = 0; int skip = 0; - ENTRY; if (lcfg->lcfg_command != LCFG_PARAM) { CERROR("Unknown command: %d\n", lcfg->lcfg_command); @@ -1335,7 +1321,6 @@ int class_config_llog_handler(const struct lu_env *env, int cfg_len = rec->lrh_len; char *cfg_buf = (char*) (rec + 1); int rc = 0; - ENTRY; //class_config_dump_handler(handle, rec, data); @@ -1527,7 +1512,6 @@ int class_config_parse_llog(const struct lu_env *env, struct llog_ctxt *ctxt, struct llog_handle *llh; llog_cb_t callback; int rc; - ENTRY; CDEBUG(D_INFO, "looking up llog %s\n", name); rc = llog_open(env, ctxt, &llh, NULL, name, LLOG_OPEN_EXISTS); @@ -1574,8 +1558,6 @@ int class_config_parse_rec(struct llog_rec_hdr *rec, char *buf, int size) char *end = buf + size; int rc = 0; - ENTRY; - LASSERT(rec->lrh_type == OBD_CFG_REC); rc = lustre_cfg_sanity_check(lcfg, rec->lrh_len); if (rc < 0) @@ -1620,8 +1602,6 @@ int class_config_dump_handler(const struct lu_env *env, char *outstr; int rc = 0; - ENTRY; - OBD_ALLOC(outstr, 256); if (outstr == NULL) RETURN(-ENOMEM); @@ -1644,8 +1624,6 @@ int class_config_dump_llog(const struct lu_env *env, struct llog_ctxt *ctxt, struct llog_handle *llh; int rc; - ENTRY; - LCONSOLE_INFO("Dumping config log %s\n", name); rc = llog_open(env, ctxt, &llh, NULL, name, LLOG_OPEN_EXISTS); @@ -1674,7 +1652,6 @@ int class_manual_cleanup(struct obd_device *obd) struct lustre_cfg *lcfg; struct lustre_cfg_bufs bufs; int rc; - ENTRY; if (!obd) { CERROR("empty cleanup\n"); diff --git a/drivers/staging/lustre/lustre/obdclass/obd_mount.c b/drivers/staging/lustre/lustre/obdclass/obd_mount.c index 533a49395f32..607dfa7fa6ac 100644 --- a/drivers/staging/lustre/lustre/obdclass/obd_mount.c +++ b/drivers/staging/lustre/lustre/obdclass/obd_mount.c @@ -80,7 +80,6 @@ int lustre_process_log(struct super_block *sb, char *logname, struct lustre_sb_info *lsi = s2lsi(sb); struct obd_device *mgc = lsi->lsi_mgc; int rc; - ENTRY; LASSERT(mgc); LASSERT(cfg); @@ -130,7 +129,6 @@ int lustre_end_log(struct super_block *sb, char *logname, struct lustre_sb_info *lsi = s2lsi(sb); struct obd_device *mgc = lsi->lsi_mgc; int rc; - ENTRY; if (!mgc) RETURN(-ENOENT); @@ -223,7 +221,6 @@ int lustre_start_mgc(struct super_block *sb) char *ptr; int recov_bk; int rc = 0, i = 0, j, len; - ENTRY; LASSERT(lsi->lsi_lmd); @@ -485,7 +482,6 @@ static int lustre_stop_mgc(struct super_block *sb) struct obd_device *obd; char *niduuid = 0, *ptr = 0; int i, rc = 0, len = 0; - ENTRY; if (!lsi) RETURN(-ENOENT); @@ -555,7 +551,6 @@ out: struct lustre_sb_info *lustre_init_lsi(struct super_block *sb) { struct lustre_sb_info *lsi; - ENTRY; OBD_ALLOC_PTR(lsi); if (!lsi) @@ -582,7 +577,6 @@ struct lustre_sb_info *lustre_init_lsi(struct super_block *sb) static int lustre_free_lsi(struct super_block *sb) { struct lustre_sb_info *lsi = s2lsi(sb); - ENTRY; LASSERT(lsi != NULL); CDEBUG(D_MOUNT, "Freeing lsi %p\n", lsi); @@ -631,7 +625,6 @@ static int lustre_free_lsi(struct super_block *sb) int lustre_put_lsi(struct super_block *sb) { struct lustre_sb_info *lsi = s2lsi(sb); - ENTRY; LASSERT(lsi != NULL); @@ -764,7 +757,6 @@ EXPORT_SYMBOL(server_name2index); int lustre_common_put_super(struct super_block *sb) { int rc; - ENTRY; CDEBUG(D_MOUNT, "dropping sb %p\n", sb); @@ -820,7 +812,6 @@ int lustre_check_exclusion(struct super_block *sb, char *svname) struct lustre_mount_data *lmd = lsi->lsi_lmd; __u32 index; int i, rc; - ENTRY; rc = server_name2index(svname, &index, NULL); if (rc != LDD_F_SV_TYPE_OST) @@ -845,7 +836,6 @@ static int lmd_make_exclusion(struct lustre_mount_data *lmd, const char *ptr) const char *s1 = ptr, *s2; __u32 index, *exclude_list; int rc = 0, devmax; - ENTRY; /* The shortest an ost name can be is 8 chars: -OST0000. We don't actually know the fsname at this time, so in fact @@ -997,7 +987,6 @@ static int lmd_parse(char *options, struct lustre_mount_data *lmd) char *s1, *s2, *devname = NULL; struct lustre_mount_data *raw = (struct lustre_mount_data *)options; int rc = 0; - ENTRY; LASSERT(lmd); if (!options) { @@ -1204,7 +1193,6 @@ int lustre_fill_super(struct super_block *sb, void *data, int silent) struct lustre_mount_data2 *lmd2 = data; struct lustre_sb_info *lsi; int rc; - ENTRY; CDEBUG(D_MOUNT|D_VFSTRACE, "VFS Op: sb %p\n", sb); diff --git a/drivers/staging/lustre/lustre/obdecho/echo.c b/drivers/staging/lustre/lustre/obdecho/echo.c index 9e64939af9dc..e0f49b083f7f 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo.c +++ b/drivers/staging/lustre/lustre/obdecho/echo.c @@ -96,8 +96,6 @@ static int echo_init_export(struct obd_export *exp) static int echo_destroy_export(struct obd_export *exp) { - ENTRY; - target_destroy_export(exp); ldlm_destroy_export(exp); @@ -151,7 +149,6 @@ static int echo_destroy(const struct lu_env *env, struct obd_export *exp, { struct obd_device *obd = class_exp2obd(exp); - ENTRY; if (!obd) { CERROR("invalid client cookie "LPX64"\n", exp->exp_handle.h_cookie); @@ -178,7 +175,6 @@ static int echo_getattr(const struct lu_env *env, struct obd_export *exp, struct obd_device *obd = class_exp2obd(exp); obd_id id = ostid_id(&oinfo->oi_oa->o_oi); - ENTRY; if (!obd) { CERROR("invalid client cookie "LPX64"\n", exp->exp_handle.h_cookie); @@ -203,7 +199,6 @@ static int echo_setattr(const struct lu_env *env, struct obd_export *exp, { struct obd_device *obd = class_exp2obd(exp); - ENTRY; if (!obd) { CERROR("invalid client cookie "LPX64"\n", exp->exp_handle.h_cookie); @@ -410,7 +405,6 @@ static int echo_preprw(const struct lu_env *env, int cmd, int tot_bytes = 0; int rc = 0; int i, left; - ENTRY; obd = export->exp_obd; if (obd == NULL) @@ -487,7 +481,6 @@ static int echo_commitrw(const struct lu_env *env, int cmd, struct obd_device *obd; int pgs = 0; int i; - ENTRY; obd = export->exp_obd; if (obd == NULL) @@ -565,7 +558,6 @@ static int echo_setup(struct obd_device *obd, struct lustre_cfg *lcfg) __u64 lock_flags = 0; struct ldlm_res_id res_id = {.name = {1}}; char ns_name[48]; - ENTRY; obd->u.echo.eo_obt.obt_magic = OBT_MAGIC; spin_lock_init(&obd->u.echo.eo_lock); @@ -606,7 +598,6 @@ static int echo_setup(struct obd_device *obd, struct lustre_cfg *lcfg) static int echo_cleanup(struct obd_device *obd) { int leaked; - ENTRY; lprocfs_obd_cleanup(obd); lprocfs_free_obd_stats(obd); diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c index 2e52ef2f92a9..6fc0396f6cbb 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c @@ -313,7 +313,6 @@ static void echo_page_fini(const struct lu_env *env, struct echo_page *ep = cl2echo_page(slice); struct echo_object *eco = cl2echo_obj(slice->cpl_obj); struct page *vmpage = ep->ep_vmpage; - ENTRY; atomic_dec(&eco->eo_npages); page_cache_release(vmpage); @@ -409,7 +408,6 @@ static int echo_page_init(const struct lu_env *env, struct cl_object *obj, { struct echo_page *ep = cl_object_page_slice(obj, page); struct echo_object *eco = cl2echo_obj(obj); - ENTRY; ep->ep_vmpage = vmpage; page_cache_get(vmpage); @@ -430,7 +428,6 @@ static int echo_lock_init(const struct lu_env *env, const struct cl_io *unused) { struct echo_lock *el; - ENTRY; OBD_SLAB_ALLOC_PTR_GFP(el, echo_lock_kmem, __GFP_IO); if (el != NULL) { @@ -468,7 +465,6 @@ static int echo_object_init(const struct lu_env *env, struct lu_object *obj, struct echo_device *ed = cl2echo_dev(lu2cl_dev(obj->lo_dev)); struct echo_client_obd *ec = ed->ed_ec; struct echo_object *eco = cl2echo_obj(lu2cl(obj)); - ENTRY; if (ed->ed_next) { struct lu_object *below; @@ -511,8 +507,6 @@ static int echo_alloc_memmd(struct echo_device *ed, { int lsm_size; - ENTRY; - /* If export is lov/osc then use their obd method */ if (ed->ed_next != NULL) return obd_alloc_memmd(ed->ed_ec->ec_exp, lsmp); @@ -541,8 +535,6 @@ static int echo_free_memmd(struct echo_device *ed, struct lov_stripe_md **lsmp) { int lsm_size; - ENTRY; - /* If export is lov/osc then use their obd method */ if (ed->ed_next != NULL) return obd_free_memmd(ed->ed_ec->ec_exp, lsmp); @@ -560,7 +552,6 @@ static void echo_object_free(const struct lu_env *env, struct lu_object *obj) { struct echo_object *eco = cl2echo_obj(lu2cl(obj)); struct echo_client_obd *ec = eco->eo_dev->ed_ec; - ENTRY; LASSERT(atomic_read(&eco->eo_npages) == 0); @@ -607,7 +598,6 @@ static struct lu_object *echo_object_alloc(const struct lu_env *env, { struct echo_object *eco; struct lu_object *obj = NULL; - ENTRY; /* we're the top dev. */ LASSERT(hdr == NULL); @@ -738,7 +728,6 @@ static int echo_fid_init(struct echo_device *ed, char *obd_name, { char *prefix; int rc; - ENTRY; OBD_ALLOC_PTR(ed->ed_cl_seq); if (ed->ed_cl_seq == NULL) @@ -770,7 +759,6 @@ out_free_seq: static int echo_fid_fini(struct obd_device *obddev) { struct echo_device *ed = obd2echo_dev(obddev); - ENTRY; if (ed->ed_cl_seq != NULL) { seq_client_fini(ed->ed_cl_seq); @@ -793,7 +781,6 @@ static struct lu_device *echo_device_alloc(const struct lu_env *env, const char *tgt_type_name; int rc; int cleanup = 0; - ENTRY; OBD_ALLOC_PTR(ed); if (ed == NULL) @@ -1077,7 +1064,6 @@ static struct echo_object *cl_echo_object_find(struct echo_device *d, struct lu_fid *fid; int refcheck; int rc; - ENTRY; LASSERT(lsmp); lsm = *lsmp; @@ -1140,7 +1126,6 @@ static int cl_echo_object_put(struct echo_object *eco) struct lu_env *env; struct cl_object *obj = echo_obj2cl(eco); int refcheck; - ENTRY; env = cl_env_get(&refcheck); if (IS_ERR(env)) @@ -1168,7 +1153,6 @@ static int cl_echo_enqueue0(struct lu_env *env, struct echo_object *eco, struct cl_lock_descr *descr; struct echo_thread_info *info; int rc = -ENOMEM; - ENTRY; info = echo_env_info(env); io = &info->eti_io; @@ -1213,7 +1197,6 @@ static int cl_echo_enqueue(struct echo_object *eco, obd_off start, obd_off end, struct cl_io *io; int refcheck; int result; - ENTRY; env = cl_env_get(&refcheck); if (IS_ERR(env)) @@ -1244,7 +1227,6 @@ static int cl_echo_cancel0(struct lu_env *env, struct echo_device *ed, struct echo_lock *ecl = NULL; struct list_head *el; int found = 0, still_used = 0; - ENTRY; LASSERT(ec != NULL); spin_lock(&ec->ec_lock); @@ -1274,7 +1256,6 @@ static int cl_echo_cancel(struct echo_device *ed, __u64 cookie) struct lu_env *env; int refcheck; int rc; - ENTRY; env = cl_env_get(&refcheck); if (IS_ERR(env)) @@ -1292,7 +1273,6 @@ static int cl_echo_async_brw(const struct lu_env *env, struct cl_io *io, struct cl_page *clp; struct cl_page *temp; int result = 0; - ENTRY; cl_page_list_for_each_safe(clp, temp, &queue->c2_qin) { int rc; @@ -1319,7 +1299,6 @@ static int cl_echo_object_brw(struct echo_object *eco, int rw, obd_off offset, int refcheck; int rc; int i; - ENTRY; LASSERT((offset & ~CFS_PAGE_MASK) == 0); LASSERT(ed->ed_next != NULL); @@ -1468,8 +1447,6 @@ static int echo_big_lmm_get(const struct lu_env *env, struct md_object *o, struct echo_thread_info *info = echo_env_info(env); int rc; - ENTRY; - LASSERT(ma->ma_lmm_size > 0); rc = mo_xattr_get(env, o, &LU_BUF_NULL, XATTR_NAME_LOV); @@ -1518,8 +1495,6 @@ int echo_attr_get_complex(const struct lu_env *env, struct md_object *next, int need = ma->ma_need; int rc = 0, rc2; - ENTRY; - ma->ma_valid = 0; if (need & MA_INODE) { @@ -1588,8 +1563,6 @@ echo_md_create_internal(const struct lu_env *env, struct echo_device *ed, struct lu_object_conf conf = { .loc_flags = LOC_F_NEW }; int rc; - ENTRY; - rc = mdo_lookup(env, parent, lname, fid2, spec); if (rc == 0) return -EEXIST; @@ -1664,8 +1637,6 @@ static int echo_create_md_object(const struct lu_env *env, int rc = 0; int i; - ENTRY; - if (ec_parent == NULL) return -1; parent = lu_object_locate(ec_parent->lo_header, ld->ld_type); @@ -1732,7 +1703,6 @@ static struct lu_object *echo_md_lookup(const struct lu_env *env, struct lu_fid *fid = &info->eti_fid; struct lu_object *child; int rc; - ENTRY; CDEBUG(D_INFO, "lookup %s in parent "DFID" %p\n", lname->ln_name, PFID(fid), parent); @@ -1764,8 +1734,6 @@ static int echo_setattr_object(const struct lu_env *env, int rc = 0; int i; - ENTRY; - if (ec_parent == NULL) return -1; parent = lu_object_locate(ec_parent->lo_header, ld->ld_type); @@ -1829,8 +1797,6 @@ static int echo_getattr_object(const struct lu_env *env, int rc = 0; int i; - ENTRY; - if (ec_parent == NULL) return -1; parent = lu_object_locate(ec_parent->lo_header, ld->ld_type); @@ -1932,8 +1898,6 @@ static int echo_md_destroy_internal(const struct lu_env *env, struct lu_object *child; int rc; - ENTRY; - ec_child = echo_md_lookup(env, ed, parent, lname); if (IS_ERR(ec_child)) { CERROR("Can't find child %s: rc = %ld\n", lname->ln_name, @@ -1977,7 +1941,6 @@ static int echo_destroy_object(const struct lu_env *env, struct lu_object *parent; int rc = 0; int i; - ENTRY; parent = lu_object_locate(ec_parent->lo_header, ld->ld_type); if (parent == NULL) @@ -2029,7 +1992,6 @@ static struct lu_object *echo_resolve_path(const struct lu_env *env, struct lu_object *parent = NULL; struct lu_object *child = NULL; int rc = 0; - ENTRY; /*Only support MDD layer right now*/ rc = md->md_ops->mdo_root_get(env, md, fid); @@ -2134,7 +2096,6 @@ static int echo_md_handler(struct echo_device *ed, int command, char *name = NULL; int namelen = data->ioc_plen2; int rc = 0; - ENTRY; if (ld == NULL) { CERROR("MD echo client is not being initialized properly\n"); @@ -2248,7 +2209,6 @@ static int echo_create_object(const struct lu_env *env, struct echo_device *ed, struct lov_stripe_md *lsm = NULL; int rc; int created = 0; - ENTRY; if ((oa->o_valid & OBD_MD_FLID) == 0 && /* no obj id */ (on_target || /* set_stripe */ @@ -2338,7 +2298,6 @@ static int echo_get_object(struct echo_object **ecop, struct echo_device *ed, struct lov_stripe_md *lsm = NULL; struct echo_object *eco; int rc; - ENTRY; if ((oa->o_valid & OBD_MD_FLID) == 0 || ostid_id(&oa->o_oi) == 0) { /* disallow use of object id 0 */ @@ -2481,7 +2440,6 @@ static int echo_client_kbrw(struct echo_device *ed, int rw, struct obdo *oa, int verify; int gfp_mask; int brw_flags = 0; - ENTRY; verify = (ostid_id(&oa->o_oi) != ECHO_PERSISTENT_OBJID && (oa->o_valid & OBD_MD_FLFLAGS) != 0 && @@ -2577,8 +2535,6 @@ static int echo_client_prep_commit(const struct lu_env *env, obd_size npages, tot_pages; int i, ret = 0, brw_flags = 0; - ENTRY; - if (count <= 0 || (count & (~CFS_PAGE_MASK)) != 0 || (lsm != NULL && ostid_id(&lsm->lsm_oi) != ostid_id(&oa->o_oi))) RETURN(-EINVAL); @@ -2682,7 +2638,6 @@ static int echo_client_brw_ioctl(const struct lu_env *env, int rw, int rc; int async = 1; long test_mode; - ENTRY; LASSERT(oa->o_valid & OBD_MD_FLGROUP); @@ -2736,7 +2691,6 @@ echo_client_enqueue(struct obd_export *exp, struct obdo *oa, struct echo_object *eco; obd_off end; int rc; - ENTRY; if (ed->ed_next == NULL) RETURN(-EOPNOTSUPP); @@ -2792,7 +2746,6 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len, int rw = OBD_BRW_READ; int rc = 0; int i; - ENTRY; memset(&dummy_oti, 0, sizeof(dummy_oti)); @@ -3009,7 +2962,6 @@ static int echo_client_setup(const struct lu_env *env, struct obd_uuid echo_uuid = { "ECHO_UUID" }; struct obd_connect_data *ocd = NULL; int rc; - ENTRY; if (lcfg->lcfg_bufcount < 2 || LUSTRE_CFG_BUFLEN(lcfg, 1) < 1) { CERROR("requires a TARGET OBD name\n"); @@ -3075,7 +3027,6 @@ static int echo_client_cleanup(struct obd_device *obddev) struct echo_device *ed = obd2echo_dev(obddev); struct echo_client_obd *ec = &obddev->u.echo_client; int rc; - ENTRY; /*Do nothing for Metadata echo client*/ if (ed == NULL ) @@ -3108,7 +3059,6 @@ static int echo_client_connect(const struct lu_env *env, int rc; struct lustre_handle conn = { 0 }; - ENTRY; rc = class_connect(&conn, src, cluuid); if (rc == 0) { *exp = class_conn2export(&conn); @@ -3125,7 +3075,6 @@ static int echo_client_disconnect(struct obd_export *exp) struct ec_lock *ecl; #endif int rc; - ENTRY; if (exp == NULL) GOTO(out, rc = -EINVAL); @@ -3200,7 +3149,6 @@ static int __init obdecho_init(void) struct lprocfs_static_vars lvars; int rc; - ENTRY; LCONSOLE_INFO("Echo OBD driver; http://www.lustre.org/\n"); LASSERT(PAGE_CACHE_SIZE % OBD_ECHO_BLOCK_SIZE == 0); diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c index 6b0a842dfca0..3e71f41bbb5e 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cache.c +++ b/drivers/staging/lustre/lustre/osc/osc_cache.c @@ -540,7 +540,6 @@ int osc_extent_release(const struct lu_env *env, struct osc_extent *ext) { struct osc_object *obj = ext->oe_obj; int rc = 0; - ENTRY; LASSERT(atomic_read(&ext->oe_users) > 0); LASSERT(sanity_check(ext) == 0); @@ -602,7 +601,6 @@ struct osc_extent *osc_extent_find(const struct lu_env *env, int ppc_bits; /* pages per chunk bits */ int chunk_mask; int rc; - ENTRY; cur = osc_extent_alloc(obj); if (cur == NULL) @@ -805,7 +803,6 @@ int osc_extent_finish(const struct lu_env *env, struct osc_extent *ext, int blocksize = cli->cl_import->imp_obd->obd_osfs.os_bsize ? : 4096; __u64 last_off = 0; int last_count = -1; - ENTRY; OSC_EXTENT_DUMP(D_CACHE, ext, "extent finished.\n"); @@ -870,7 +867,6 @@ static int osc_extent_wait(const struct lu_env *env, struct osc_extent *ext, struct l_wait_info lwi = LWI_TIMEOUT_INTR(cfs_time_seconds(600), NULL, LWI_ON_SIGNAL_NOOP, NULL); int rc = 0; - ENTRY; osc_object_lock(obj); LASSERT(sanity_check_nolock(ext) == 0); @@ -925,7 +921,6 @@ static int osc_extent_truncate(struct osc_extent *ext, pgoff_t trunc_index, int grants = 0; int nr_pages = 0; int rc = 0; - ENTRY; LASSERT(sanity_check(ext) == 0); LASSERT(ext->oe_state == OES_TRUNC); @@ -1036,7 +1031,6 @@ static int osc_extent_make_ready(const struct lu_env *env, struct osc_object *obj = ext->oe_obj; int page_count = 0; int rc; - ENTRY; /* we're going to grab page lock, so object lock must not be taken. */ LASSERT(sanity_check(ext) == 0); @@ -1115,7 +1109,6 @@ static int osc_extent_expand(struct osc_extent *ext, pgoff_t index, int *grants) pgoff_t end_index; int chunksize = 1 << cli->cl_chunkbits; int rc = 0; - ENTRY; LASSERT(ext->oe_max_end >= index && ext->oe_start <= index); osc_object_lock(obj); @@ -1207,7 +1200,6 @@ static int osc_make_ready(const struct lu_env *env, struct osc_async_page *oap, LASSERT(cmd == OBD_BRW_WRITE); /* no cached reads */ - ENTRY; result = cl_page_make_ready(env, page, CRT_WRITE); if (result == 0) opg->ops_submit_time = cfs_time_current(); @@ -1255,8 +1247,6 @@ static int osc_completion(const struct lu_env *env, struct osc_async_page *oap, enum cl_req_type crt; int srvlock; - ENTRY; - cmd &= ~OBD_BRW_NOQUOTA; LASSERT(equi(page->cp_state == CPS_PAGEIN, cmd == OBD_BRW_READ)); LASSERT(equi(page->cp_state == CPS_PAGEOUT, cmd == OBD_BRW_WRITE)); @@ -1338,8 +1328,6 @@ static void osc_consume_write_grant(struct client_obd *cli, static void osc_release_write_grant(struct client_obd *cli, struct brw_page *pga) { - ENTRY; - LASSERT(spin_is_locked(&cli->cl_loi_list_lock.lock)); if (!(pga->flag & OBD_BRW_FROM_GRANT)) { EXIT; @@ -1503,7 +1491,6 @@ static int osc_enter_cache(const struct lu_env *env, struct client_obd *cli, struct osc_cache_waiter ocw; struct l_wait_info lwi = LWI_INTR(LWI_ON_SIGNAL_NOOP, NULL); int rc = -EDQUOT; - ENTRY; OSC_DUMP_GRANT(cli, "need:%d.\n", bytes); @@ -1570,7 +1557,6 @@ void osc_wake_cache_waiters(struct client_obd *cli) struct list_head *l, *tmp; struct osc_cache_waiter *ocw; - ENTRY; list_for_each_safe(l, tmp, &cli->cl_cache_waiters) { ocw = list_entry(l, struct osc_cache_waiter, ocw_entry); list_del_init(&ocw->ocw_entry); @@ -1613,7 +1599,6 @@ static int osc_makes_rpc(struct client_obd *cli, struct osc_object *osc, int cmd) { int invalid_import = 0; - ENTRY; /* if we have an invalid import we want to drain the queued pages * by forcing them through rpcs that immediately fail and complete @@ -1757,7 +1742,6 @@ static void osc_ap_completion(const struct lu_env *env, struct client_obd *cli, struct lov_oinfo *loi = osc->oo_oinfo; __u64 xid = 0; - ENTRY; if (oap->oap_request != NULL) { xid = ptlrpc_req_xid(oap->oap_request); ptlrpc_req_finished(oap->oap_request); @@ -1795,7 +1779,6 @@ static int try_to_add_extent_for_io(struct client_obd *cli, int *pc, unsigned int *max_pages) { struct osc_extent *tmp; - ENTRY; EASSERT((ext->oe_state == OES_CACHE || ext->oe_state == OES_LOCK_DONE), ext); @@ -1913,7 +1896,6 @@ osc_send_write_rpc(const struct lu_env *env, struct client_obd *cli, obd_count page_count = 0; int srvlock = 0; int rc = 0; - ENTRY; LASSERT(osc_object_is_locked(osc)); @@ -1985,7 +1967,6 @@ osc_send_read_rpc(const struct lu_env *env, struct client_obd *cli, int page_count = 0; unsigned int max_pages = cli->cl_max_pages_per_rpc; int rc = 0; - ENTRY; LASSERT(osc_object_is_locked(osc)); list_for_each_entry_safe(ext, next, @@ -2023,8 +2004,6 @@ osc_send_read_rpc(const struct lu_env *env, struct client_obd *cli, * we could be sending. These lists are maintained by osc_makes_rpc(). */ static struct osc_object *osc_next_obj(struct client_obd *cli) { - ENTRY; - /* First return objects that have blocked locks so that they * will be flushed quickly and other clients can get the lock, * then objects which have pages ready to be stuffed into RPCs */ @@ -2060,7 +2039,6 @@ static void osc_check_rpcs(const struct lu_env *env, struct client_obd *cli, { struct osc_object *osc; int rc = 0; - ENTRY; while ((osc = osc_next_obj(cli)) != NULL) { struct cl_object *obj = osc2cl(osc); @@ -2167,7 +2145,6 @@ int osc_prep_async_page(struct osc_object *osc, struct osc_page *ops, { struct obd_export *exp = osc_export(osc); struct osc_async_page *oap = &ops->ops_oap; - ENTRY; if (!page) return cfs_size_round(sizeof(*oap)); @@ -2206,7 +2183,6 @@ int osc_queue_async_io(const struct lu_env *env, struct cl_io *io, int cmd = OBD_BRW_WRITE; int need_release = 0; int rc = 0; - ENTRY; if (oap->oap_magic != OAP_MAGIC) RETURN(-EINVAL); @@ -2361,7 +2337,6 @@ int osc_teardown_async_page(const struct lu_env *env, struct osc_async_page *oap = &ops->ops_oap; struct osc_extent *ext = NULL; int rc = 0; - ENTRY; LASSERT(oap->oap_magic == OAP_MAGIC); @@ -2406,7 +2381,6 @@ int osc_flush_async_page(const struct lu_env *env, struct cl_io *io, struct osc_async_page *oap = &ops->ops_oap; bool unplug = false; int rc = 0; - ENTRY; osc_object_lock(obj); ext = osc_extent_lookup(obj, index); @@ -2484,7 +2458,6 @@ int osc_cancel_async_page(const struct lu_env *env, struct osc_page *ops) pgoff_t index = oap2cl_page(oap)->cp_index; int rc = -EBUSY; int cmd; - ENTRY; LASSERT(!oap->oap_interrupted); oap->oap_interrupted = 1; @@ -2541,7 +2514,6 @@ int osc_queue_sync_pages(const struct lu_env *env, struct osc_object *obj, int mppr = cli->cl_max_pages_per_rpc; pgoff_t start = CL_PAGE_EOF; pgoff_t end = 0; - ENTRY; list_for_each_entry(oap, list, oap_pending_item) { struct cl_page *cp = oap2cl_page(oap); @@ -2601,7 +2573,6 @@ int osc_cache_truncate_start(const struct lu_env *env, struct osc_io *oio, LIST_HEAD(list); int result = 0; bool partial; - ENTRY; /* pages with index greater or equal to index will be truncated. */ index = cl_index(osc2cl(obj), size); @@ -2758,7 +2729,6 @@ int osc_cache_wait_range(const struct lu_env *env, struct osc_object *obj, struct osc_extent *ext; pgoff_t index = start; int result = 0; - ENTRY; again: osc_object_lock(obj); @@ -2815,7 +2785,6 @@ int osc_cache_writeback_range(const struct lu_env *env, struct osc_object *obj, LIST_HEAD(discard_list); bool unplug = false; int result = 0; - ENTRY; osc_object_lock(obj); ext = osc_extent_search(obj, start); diff --git a/drivers/staging/lustre/lustre/osc/osc_dev.c b/drivers/staging/lustre/lustre/osc/osc_dev.c index 4208ddfd73b3..4059591f25b0 100644 --- a/drivers/staging/lustre/lustre/osc/osc_dev.c +++ b/drivers/staging/lustre/lustre/osc/osc_dev.c @@ -171,7 +171,6 @@ LU_TYPE_INIT_FINI(osc, &osc_key, &osc_session_key); static int osc_cl_process_config(const struct lu_env *env, struct lu_device *d, struct lustre_cfg *cfg) { - ENTRY; RETURN(osc_process_config_base(d->ld_obd, cfg)); } diff --git a/drivers/staging/lustre/lustre/osc/osc_io.c b/drivers/staging/lustre/lustre/osc/osc_io.c index 342c46e2c91d..60e5c9d5cfa0 100644 --- a/drivers/staging/lustre/lustre/osc/osc_io.c +++ b/drivers/staging/lustre/lustre/osc/osc_io.c @@ -261,7 +261,6 @@ static int osc_io_prepare_write(const struct lu_env *env, struct obd_import *imp = class_exp2cliimp(dev->od_exp); struct osc_io *oio = cl2osc_io(env, ios); int result = 0; - ENTRY; /* * This implements OBD_BRW_CHECK logic from old client. @@ -288,7 +287,6 @@ static int osc_io_commit_write(const struct lu_env *env, struct osc_page *opg = cl2osc_page(slice); struct osc_object *obj = cl2osc(opg->ops_cl.cpl_obj); struct osc_async_page *oap = &opg->ops_oap; - ENTRY; LASSERT(to > 0); /* @@ -315,8 +313,6 @@ static int osc_io_fault_start(const struct lu_env *env, struct cl_io *io; struct cl_fault_io *fio; - ENTRY; - io = ios->cis_io; fio = &io->u.ci_fault; CDEBUG(D_INFO, "%lu %d %d\n", @@ -517,7 +513,6 @@ static int osc_io_read_start(const struct lu_env *env, struct cl_object *obj = slice->cis_obj; struct cl_attr *attr = &osc_env_info(env)->oti_attr; int result = 0; - ENTRY; if (oio->oi_lockless == 0) { cl_object_attr_lock(obj); @@ -539,7 +534,6 @@ static int osc_io_write_start(const struct lu_env *env, struct cl_object *obj = slice->cis_obj; struct cl_attr *attr = &osc_env_info(env)->oti_attr; int result = 0; - ENTRY; if (oio->oi_lockless == 0) { OBD_FAIL_TIMEOUT(OBD_FAIL_OSC_DELAY_SETTIME, 1); @@ -565,7 +559,6 @@ static int osc_fsync_ost(const struct lu_env *env, struct osc_object *obj, struct lov_oinfo *loi = obj->oo_oinfo; struct osc_async_cbargs *cbargs = &oio->oi_cbarg; int rc = 0; - ENTRY; memset(oa, 0, sizeof(*oa)); oa->o_oi = loi->loi_oi; @@ -598,7 +591,6 @@ static int osc_io_fsync_start(const struct lu_env *env, pgoff_t start = cl_index(obj, fio->fi_start); pgoff_t end = cl_index(obj, fio->fi_end); int result = 0; - ENTRY; if (fio->fi_end == OBD_OBJECT_EOF) end = CL_PAGE_EOF; diff --git a/drivers/staging/lustre/lustre/osc/osc_lock.c b/drivers/staging/lustre/lustre/osc/osc_lock.c index 98478d24f9be..a13215dd4a9e 100644 --- a/drivers/staging/lustre/lustre/osc/osc_lock.c +++ b/drivers/staging/lustre/lustre/osc/osc_lock.c @@ -343,8 +343,6 @@ static void osc_lock_lvb_update(const struct lu_env *env, struct osc_lock *olck, struct cl_attr *attr; unsigned valid; - ENTRY; - if (!(olck->ols_flags & LDLM_FL_LVB_READY)) RETURN_EXIT; @@ -412,7 +410,6 @@ static void osc_lock_granted(const struct lu_env *env, struct osc_lock *olck, LASSERT(dlmlock->l_granted_mode == dlmlock->l_req_mode); - ENTRY; if (olck->ols_state < OLS_GRANTED) { lock = olck->ols_cl.cls_lock; ext = &dlmlock->l_policy_data.l_extent; @@ -450,8 +447,6 @@ static void osc_lock_upcall0(const struct lu_env *env, struct osc_lock *olck) { struct ldlm_lock *dlmlock; - ENTRY; - dlmlock = ldlm_handle2lock_long(&olck->ols_handle, 0); LASSERT(dlmlock != NULL); @@ -497,7 +492,6 @@ static int osc_lock_upcall(void *cookie, int errcode) struct lu_env *env; struct cl_env_nest nest; - ENTRY; env = cl_env_nested_get(&nest); if (!IS_ERR(env)) { int rc; @@ -1023,7 +1017,6 @@ static int osc_lock_enqueue_wait(const struct lu_env *env, struct cl_lock *conflict= NULL; int lockless = osc_lock_is_lockless(olck); int rc = 0; - ENTRY; LASSERT(cl_lock_is_mutexed(lock)); @@ -1118,7 +1111,6 @@ static int osc_lock_enqueue(const struct lu_env *env, struct osc_lock *ols = cl2osc_lock(slice); struct cl_lock *lock = ols->ols_cl.cls_lock; int result; - ENTRY; LASSERT(cl_lock_is_mutexed(lock)); LASSERTF(ols->ols_state == OLS_NEW, @@ -1262,7 +1254,6 @@ static int osc_lock_flush(struct osc_lock *ols, int discard) struct cl_env_nest nest; struct lu_env *env; int result = 0; - ENTRY; env = cl_env_nested_get(&nest); if (!IS_ERR(env)) { diff --git a/drivers/staging/lustre/lustre/osc/osc_object.c b/drivers/staging/lustre/lustre/osc/osc_object.c index ca94e6331381..5d6c7630784c 100644 --- a/drivers/staging/lustre/lustre/osc/osc_object.c +++ b/drivers/staging/lustre/lustre/osc/osc_object.c @@ -191,7 +191,6 @@ static int osc_object_glimpse(const struct lu_env *env, { struct lov_oinfo *oinfo = cl2osc(obj)->oo_oinfo; - ENTRY; lvb->lvb_size = oinfo->loi_kms; lvb->lvb_blocks = oinfo->loi_lvb.lvb_blocks; RETURN(0); diff --git a/drivers/staging/lustre/lustre/osc/osc_page.c b/drivers/staging/lustre/lustre/osc/osc_page.c index baba959a7450..5f51dfa3a3e0 100644 --- a/drivers/staging/lustre/lustre/osc/osc_page.c +++ b/drivers/staging/lustre/lustre/osc/osc_page.c @@ -219,7 +219,6 @@ static int osc_page_cache_add(const struct lu_env *env, struct osc_io *oio = osc_env_io(env); struct osc_page *opg = cl2osc_page(slice); int result; - ENTRY; LINVRNT(osc_page_protected(env, opg, CLM_WRITE, 0)); @@ -294,7 +293,6 @@ static int osc_page_is_under_lock(const struct lu_env *env, struct cl_lock *lock; int result = -ENODATA; - ENTRY; lock = cl_lock_at_page(env, slice->cpl_obj, slice->cpl_page, NULL, 1, 0); if (lock != NULL) { @@ -421,7 +419,6 @@ static void osc_page_delete(const struct lu_env *env, LINVRNT(opg->ops_temp || osc_page_protected(env, opg, CLM_READ, 1)); - ENTRY; CDEBUG(D_TRACE, "%p\n", opg); osc_page_transfer_put(env, opg); rc = osc_teardown_async_page(env, obj, opg); @@ -481,7 +478,7 @@ static int osc_page_flush(const struct lu_env *env, { struct osc_page *opg = cl2osc_page(slice); int rc = 0; - ENTRY; + rc = osc_flush_async_page(env, io, opg); RETURN(rc); } @@ -666,7 +663,6 @@ int osc_lru_shrink(struct client_obd *cli, int target) int count = 0; int index = 0; int rc = 0; - ENTRY; LASSERT(atomic_read(&cli->cl_lru_in_list) >= 0); if (atomic_read(&cli->cl_lru_in_list) == 0 || target <= 0) @@ -881,7 +877,6 @@ static int osc_lru_reserve(const struct lu_env *env, struct osc_object *obj, struct l_wait_info lwi = LWI_INTR(LWI_ON_SIGNAL_NOOP, NULL); struct client_obd *cli = osc_cli(obj); int rc = 0; - ENTRY; if (cli->cl_cache == NULL) /* shall not be in LRU */ RETURN(0); diff --git a/drivers/staging/lustre/lustre/osc/osc_quota.c b/drivers/staging/lustre/lustre/osc/osc_quota.c index 69caab76ced3..b178e213eecd 100644 --- a/drivers/staging/lustre/lustre/osc/osc_quota.c +++ b/drivers/staging/lustre/lustre/osc/osc_quota.c @@ -45,7 +45,6 @@ static inline struct osc_quota_info *osc_oqi_alloc(obd_uid id) int osc_quota_chkdq(struct client_obd *cli, const unsigned int qid[]) { int type; - ENTRY; for (type = 0; type < MAXQUOTAS; type++) { struct osc_quota_info *oqi; @@ -79,7 +78,6 @@ int osc_quota_setdq(struct client_obd *cli, const unsigned int qid[], { int type; int rc = 0; - ENTRY; if ((valid & (OBD_MD_FLUSRQUOTA | OBD_MD_FLGRPQUOTA)) == 0) RETURN(0); @@ -211,7 +209,6 @@ int osc_quota_setup(struct obd_device *obd) { struct client_obd *cli = &obd->u.cli; int i, type; - ENTRY; for (type = 0; type < MAXQUOTAS; type++) { cli->cl_quota_hash[type] = cfs_hash_create("QUOTA_HASH", @@ -240,7 +237,6 @@ int osc_quota_cleanup(struct obd_device *obd) { struct client_obd *cli = &obd->u.cli; int type; - ENTRY; for (type = 0; type < MAXQUOTAS; type++) cfs_hash_putref(cli->cl_quota_hash[type]); @@ -254,7 +250,6 @@ int osc_quotactl(struct obd_device *unused, struct obd_export *exp, struct ptlrpc_request *req; struct obd_quotactl *oqc; int rc; - ENTRY; req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp), &RQF_OST_QUOTACTL, LUSTRE_OST_VERSION, @@ -292,7 +287,6 @@ int osc_quotacheck(struct obd_device *unused, struct obd_export *exp, struct ptlrpc_request *req; struct obd_quotactl *body; int rc; - ENTRY; req = ptlrpc_request_alloc_pack(class_exp2cliimp(exp), &RQF_OST_QUOTACHECK, LUSTRE_OST_VERSION, @@ -319,7 +313,6 @@ int osc_quota_poll_check(struct obd_export *exp, struct if_quotacheck *qchk) { struct client_obd *cli = &exp->exp_obd->u.cli; int rc; - ENTRY; qchk->obd_uuid = cli->cl_target_uuid; memcpy(qchk->obd_type, LUSTRE_OST_NAME, strlen(LUSTRE_OST_NAME)); diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index fea04ca8ba6a..a27bbb5c1240 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -69,7 +69,6 @@ static int osc_packmd(struct obd_export *exp, struct lov_mds_md **lmmp, struct lov_stripe_md *lsm) { int lmm_size; - ENTRY; lmm_size = sizeof(**lmmp); if (lmmp == NULL) @@ -101,7 +100,6 @@ static int osc_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, { int lsm_size; struct obd_import *imp = class_exp2cliimp(exp); - ENTRY; if (lmm != NULL) { if (lmm_bytes < sizeof(*lmm)) { @@ -202,7 +200,6 @@ static int osc_getattr_interpret(const struct lu_env *env, struct osc_async_args *aa, int rc) { struct ost_body *body; - ENTRY; if (rc != 0) GOTO(out, rc); @@ -232,7 +229,6 @@ static int osc_getattr_async(struct obd_export *exp, struct obd_info *oinfo, struct ptlrpc_request *req; struct osc_async_args *aa; int rc; - ENTRY; req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_OST_GETATTR); if (req == NULL) @@ -264,7 +260,6 @@ static int osc_getattr(const struct lu_env *env, struct obd_export *exp, struct ptlrpc_request *req; struct ost_body *body; int rc; - ENTRY; req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_OST_GETATTR); if (req == NULL) @@ -308,7 +303,6 @@ static int osc_setattr(const struct lu_env *env, struct obd_export *exp, struct ptlrpc_request *req; struct ost_body *body; int rc; - ENTRY; LASSERT(oinfo->oi_oa->o_valid & OBD_MD_FLGROUP); @@ -349,7 +343,6 @@ static int osc_setattr_interpret(const struct lu_env *env, struct osc_setattr_args *sa, int rc) { struct ost_body *body; - ENTRY; if (rc != 0) GOTO(out, rc); @@ -373,7 +366,6 @@ int osc_setattr_async_base(struct obd_export *exp, struct obd_info *oinfo, struct ptlrpc_request *req; struct osc_setattr_args *sa; int rc; - ENTRY; req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_OST_SETATTR); if (req == NULL) @@ -431,7 +423,6 @@ int osc_real_create(struct obd_export *exp, struct obdo *oa, struct ost_body *body; struct lov_stripe_md *lsm; int rc; - ENTRY; LASSERT(oa); LASSERT(ea); @@ -517,7 +508,6 @@ int osc_punch_base(struct obd_export *exp, struct obd_info *oinfo, struct osc_setattr_args *sa; struct ost_body *body; int rc; - ENTRY; req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_OST_PUNCH); if (req == NULL) @@ -571,7 +561,6 @@ static int osc_sync_interpret(const struct lu_env *env, { struct osc_fsync_args *fa = arg; struct ost_body *body; - ENTRY; if (rc) GOTO(out, rc); @@ -596,7 +585,6 @@ int osc_sync_base(struct obd_export *exp, struct obd_info *oinfo, struct ost_body *body; struct osc_fsync_args *fa; int rc; - ENTRY; req = ptlrpc_request_alloc(class_exp2cliimp(exp), &RQF_OST_SYNC); if (req == NULL) @@ -637,8 +625,6 @@ static int osc_sync(const struct lu_env *env, struct obd_export *exp, struct obd_info *oinfo, obd_size start, obd_size end, struct ptlrpc_request_set *set) { - ENTRY; - if (!oinfo->oi_oa) { CDEBUG(D_INFO, "oa NULL\n"); RETURN(-EINVAL); @@ -662,7 +648,6 @@ static int osc_resource_get_unused(struct obd_export *exp, struct obdo *oa, struct ldlm_res_id res_id; struct ldlm_resource *res; int count; - ENTRY; /* Return, i.e. cancel nothing, only if ELC is supported (flag in * export) but disabled through procfs (flag in NS). @@ -720,7 +705,6 @@ int osc_create(const struct lu_env *env, struct obd_export *exp, struct obd_trans_info *oti) { int rc = 0; - ENTRY; LASSERT(oa); LASSERT(ea); @@ -760,7 +744,6 @@ static int osc_destroy(const struct lu_env *env, struct obd_export *exp, struct ost_body *body; LIST_HEAD(cancels); int rc, count; - ENTRY; if (!oa) { CDEBUG(D_INFO, "oa NULL\n"); @@ -948,7 +931,6 @@ int osc_shrink_grant_to_target(struct client_obd *cli, __u64 target_bytes) { int rc = 0; struct ost_body *body; - ENTRY; client_obd_list_lock(&cli->cl_loi_list_lock); /* Don't shrink if we are already above or below the desired limit @@ -1256,7 +1238,6 @@ static int osc_brw_prep_request(int cmd, struct client_obd *cli,struct obdo *oa, struct req_capsule *pill; struct brw_page *pg_prev; - ENTRY; if (OBD_FAIL_CHECK(OBD_FAIL_OSC_BRW_PREP_REQ)) RETURN(-ENOMEM); /* Recoverable */ if (OBD_FAIL_CHECK(OBD_FAIL_OSC_BRW_PREP_REQ2)) @@ -1496,7 +1477,6 @@ static int osc_brw_fini_request(struct ptlrpc_request *req, int rc) struct client_obd *cli = aa->aa_cli; struct ost_body *body; __u32 client_cksum = 0; - ENTRY; if (rc < 0 && rc != -EDQUOT) { DEBUG_REQ(D_INFO, req, "Failed request with rc = %d\n", rc); @@ -1655,8 +1635,6 @@ static int osc_brw_internal(int cmd, struct obd_export *exp, struct obdo *oa, int generation, resends = 0; struct l_wait_info lwi; - ENTRY; - init_waitqueue_head(&waitq); generation = exp->exp_obd->u.cli.cl_import->imp_generation; @@ -1720,7 +1698,6 @@ static int osc_brw_redo_request(struct ptlrpc_request *request, struct ptlrpc_request *new_req; struct osc_brw_async_args *new_aa; struct osc_async_page *oap; - ENTRY; DEBUG_REQ(rc == -EINPROGRESS ? D_RPCTRACE : D_ERROR, request, "redo for recoverable error %d", rc); @@ -1873,7 +1850,6 @@ static int osc_brw(int cmd, struct obd_export *exp, struct obd_info *oinfo, struct obd_import *imp = class_exp2cliimp(exp); struct client_obd *cli; int rc, page_count_orig; - ENTRY; LASSERT((imp != NULL) && (imp->imp_obd != NULL)); cli = &imp->imp_obd->u.cli; @@ -1946,7 +1922,6 @@ static int brw_interpret(const struct lu_env *env, struct osc_extent *tmp; struct cl_object *obj = NULL; struct client_obd *cli = aa->aa_cli; - ENTRY; rc = osc_brw_fini_request(req, rc); CDEBUG(D_INODE, "request %p aa %p rc %d\n", req, aa, rc); @@ -2072,7 +2047,6 @@ int osc_build_rpc(const struct lu_env *env, struct client_obd *cli, int rc; LIST_HEAD(rpc_list); - ENTRY; LASSERT(!list_empty(ext_list)); /* add pages into rpc_list to build BRW rpc */ @@ -2337,7 +2311,6 @@ static int osc_enqueue_fini(struct ptlrpc_request *req, struct ost_lvb *lvb, __u64 *flags, int agl, int rc) { int intent = *flags & LDLM_FL_HAS_INTENT; - ENTRY; if (intent) { /* The request was created before ldlm_cli_enqueue call. */ @@ -2496,7 +2469,6 @@ int osc_enqueue_base(struct obd_export *exp, struct ldlm_res_id *res_id, int match_lvb = (agl != 0 ? 0 : LDLM_FL_LVB_READY); ldlm_mode_t mode; int rc; - ENTRY; /* Filesystem lock extents are extended to page boundaries so that * dealing with the page cache is a little smoother. */ @@ -2633,7 +2605,6 @@ static int osc_enqueue(struct obd_export *exp, struct obd_info *oinfo, { struct ldlm_res_id res_id; int rc; - ENTRY; ostid_build_res_name(&oinfo->oi_md->lsm_oi, &res_id); rc = osc_enqueue_base(exp, &res_id, &oinfo->oi_flags, &oinfo->oi_policy, @@ -2652,7 +2623,6 @@ int osc_match_base(struct obd_export *exp, struct ldlm_res_id *res_id, struct obd_device *obd = exp->exp_obd; int lflags = *flags; ldlm_mode_t rc; - ENTRY; if (OBD_FAIL_CHECK(OBD_FAIL_OSC_MATCH)) RETURN(-EIO); @@ -2690,8 +2660,6 @@ int osc_match_base(struct obd_export *exp, struct ldlm_res_id *res_id, int osc_cancel_base(struct lustre_handle *lockh, __u32 mode) { - ENTRY; - if (unlikely(mode == LCK_GROUP)) ldlm_lock_decref_and_cancel(lockh, mode); else @@ -2703,7 +2671,6 @@ int osc_cancel_base(struct lustre_handle *lockh, __u32 mode) static int osc_cancel(struct obd_export *exp, struct lov_stripe_md *md, __u32 mode, struct lustre_handle *lockh) { - ENTRY; RETURN(osc_cancel_base(lockh, mode)); } @@ -2728,7 +2695,6 @@ static int osc_statfs_interpret(const struct lu_env *env, struct osc_async_args *aa, int rc) { struct obd_statfs *msfs; - ENTRY; if (rc == -EBADR) /* The request has in fact never been sent @@ -2764,7 +2730,6 @@ static int osc_statfs_async(struct obd_export *exp, struct ptlrpc_request *req; struct osc_async_args *aa; int rc; - ENTRY; /* We could possibly pass max_age in the request (as an absolute * timestamp or a "seconds.usec ago") so the target can avoid doing @@ -2808,7 +2773,6 @@ static int osc_statfs(const struct lu_env *env, struct obd_export *exp, struct ptlrpc_request *req; struct obd_import *imp = NULL; int rc; - ENTRY; /*Since the request might also come from lprocfs, so we need *sync this with client_disconnect_export Bug15684*/ @@ -2876,7 +2840,6 @@ static int osc_getstripe(struct lov_stripe_md *lsm, struct lov_user_md *lump) struct lov_user_md_v3 lum, *lumk; struct lov_user_ost_data_v1 *lmm_objects; int rc = 0, lum_size; - ENTRY; if (!lsm) RETURN(-ENODATA); @@ -2934,7 +2897,6 @@ static int osc_iocontrol(unsigned int cmd, struct obd_export *exp, int len, struct obd_device *obd = exp->exp_obd; struct obd_ioctl_data *data = karg; int err = 0; - ENTRY; if (!try_module_get(THIS_MODULE)) { CERROR("Can't get module. Is it alive?"); @@ -3018,7 +2980,6 @@ static int osc_get_info(const struct lu_env *env, struct obd_export *exp, obd_count keylen, void *key, __u32 *vallen, void *val, struct lov_stripe_md *lsm) { - ENTRY; if (!vallen || !val) RETURN(-EFAULT); @@ -3159,7 +3120,6 @@ static int osc_set_info_async(const struct lu_env *env, struct obd_export *exp, struct obd_import *imp = class_exp2cliimp(exp); char *tmp; int rc; - ENTRY; OBD_FAIL_TIMEOUT(OBD_FAIL_OSC_SHUTDOWN, 10); @@ -3282,8 +3242,6 @@ static int osc_llog_finish(struct obd_device *obd, int count) { struct llog_ctxt *ctxt; - ENTRY; - ctxt = llog_get_context(obd, LLOG_MDS_OST_ORIG_CTXT); if (ctxt) { llog_cat_close(NULL, ctxt->loc_handle); @@ -3371,7 +3329,6 @@ static int osc_import_event(struct obd_device *obd, struct client_obd *cli; int rc = 0; - ENTRY; LASSERT(imp->imp_obd == obd); switch (event) { @@ -3480,7 +3437,6 @@ int osc_setup(struct obd_device *obd, struct lustre_cfg *lcfg) struct client_obd *cli = &obd->u.cli; void *handler; int rc; - ENTRY; rc = ptlrpcd_addref(); if (rc) @@ -3533,7 +3489,6 @@ out_ptlrpcd: static int osc_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage) { int rc = 0; - ENTRY; switch (stage) { case OBD_CLEANUP_EARLY: { @@ -3580,8 +3535,6 @@ int osc_cleanup(struct obd_device *obd) struct client_obd *cli = &obd->u.cli; int rc; - ENTRY; - /* lru cleanup */ if (cli->cl_cache != NULL) { LASSERT(atomic_read(&cli->cl_cache->ccc_users) > 0); @@ -3673,7 +3626,6 @@ int __init osc_init(void) { struct lprocfs_static_vars lvars = { 0 }; int rc; - ENTRY; /* print an address of _any_ initialized kernel symbol from this * module, to allow debugging with gdb that doesn't support data diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index 22f7e654c9d8..b860db61e854 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -137,7 +137,6 @@ struct ptlrpc_bulk_desc *ptlrpc_prep_bulk_imp(struct ptlrpc_request *req, struct obd_import *imp = req->rq_import; struct ptlrpc_bulk_desc *desc; - ENTRY; LASSERT(type == BULK_PUT_SINK || type == BULK_GET_SOURCE); desc = ptlrpc_new_bulk(npages, max_brw, type, portal); if (desc == NULL) @@ -187,7 +186,6 @@ EXPORT_SYMBOL(__ptlrpc_prep_bulk_page); void __ptlrpc_free_bulk(struct ptlrpc_bulk_desc *desc, int unpin) { int i; - ENTRY; LASSERT(desc != NULL); LASSERT(desc->bd_iov_count != LI_POISON); /* not freed already */ @@ -336,7 +334,6 @@ static int ptlrpc_at_recv_early_reply(struct ptlrpc_request *req) struct ptlrpc_request *early_req; time_t olddl; int rc; - ENTRY; req->rq_early = 0; spin_unlock(&req->rq_lock); @@ -547,7 +544,6 @@ static int __ptlrpc_request_bufs_pack(struct ptlrpc_request *request, { struct obd_import *imp = request->rq_import; int rc; - ENTRY; if (unlikely(ctx)) request->rq_cli_ctx = sptlrpc_cli_ctx_get(ctx); @@ -822,7 +818,6 @@ struct ptlrpc_request_set *ptlrpc_prep_set(void) { struct ptlrpc_request_set *set; - ENTRY; OBD_ALLOC(set, sizeof *set); if (!set) RETURN(NULL); @@ -883,7 +878,6 @@ void ptlrpc_set_destroy(struct ptlrpc_request_set *set) struct list_head *next; int expected_phase; int n = 0; - ENTRY; /* Requests on the set should either all be completed, or all be new */ expected_phase = (atomic_read(&set->set_remaining) == 0) ? @@ -1027,7 +1021,6 @@ static int ptlrpc_import_delay_req(struct obd_import *imp, struct ptlrpc_request *req, int *status) { int delay = 0; - ENTRY; LASSERT (status != NULL); *status = 0; @@ -1120,7 +1113,6 @@ static int ptlrpc_console_allow(struct ptlrpc_request *req) static int ptlrpc_check_status(struct ptlrpc_request *req) { int err; - ENTRY; err = lustre_msg_get_status(req->rq_repmsg); if (lustre_msg_get_type(req->rq_repmsg) == PTL_RPC_MSG_ERR) { @@ -1156,7 +1148,6 @@ static void ptlrpc_save_versions(struct ptlrpc_request *req) struct lustre_msg *repmsg = req->rq_repmsg; struct lustre_msg *reqmsg = req->rq_reqmsg; __u64 *versions = lustre_msg_get_versions(repmsg); - ENTRY; if (lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY) return; @@ -1183,7 +1174,6 @@ static int after_reply(struct ptlrpc_request *req) int rc; struct timeval work_start; long timediff; - ENTRY; LASSERT(obd != NULL); /* repbuf must be unlinked */ @@ -1372,7 +1362,6 @@ static int ptlrpc_send_new_req(struct ptlrpc_request *req) { struct obd_import *imp = req->rq_import; int rc; - ENTRY; LASSERT(req->rq_phase == RQ_PHASE_NEW); if (req->rq_sent && (req->rq_sent > cfs_time_current_sec()) && @@ -1447,7 +1436,6 @@ static int ptlrpc_send_new_req(struct ptlrpc_request *req) static inline int ptlrpc_set_producer(struct ptlrpc_request_set *set) { int remaining, rc; - ENTRY; LASSERT(set->set_producer != NULL); @@ -1478,7 +1466,6 @@ int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set) { struct list_head *tmp, *next; int force_timer_recalc = 0; - ENTRY; if (atomic_read(&set->set_remaining) == 0) RETURN(1); @@ -1847,7 +1834,6 @@ int ptlrpc_expire_one_request(struct ptlrpc_request *req, int async_unlink) { struct obd_import *imp = req->rq_import; int rc = 0; - ENTRY; spin_lock(&req->rq_lock); req->rq_timedout = 1; @@ -1919,7 +1905,6 @@ int ptlrpc_expired_set(void *data) struct ptlrpc_request_set *set = data; struct list_head *tmp; time_t now = cfs_time_current_sec(); - ENTRY; LASSERT(set != NULL); @@ -2006,7 +1991,6 @@ int ptlrpc_set_next_timeout(struct ptlrpc_request_set *set) int timeout = 0; struct ptlrpc_request *req; int deadline; - ENTRY; SIGNAL_MASK_ASSERT(); /* XXX BUG 1511 */ @@ -2061,7 +2045,6 @@ int ptlrpc_set_wait(struct ptlrpc_request_set *set) struct ptlrpc_request *req; struct l_wait_info lwi; int rc, timeout; - ENTRY; if (set->set_producer) (void)ptlrpc_set_producer(set); @@ -2185,7 +2168,6 @@ EXPORT_SYMBOL(ptlrpc_set_wait); */ static void __ptlrpc_free_req(struct ptlrpc_request *request, int locked) { - ENTRY; if (request == NULL) { EXIT; return; @@ -2263,7 +2245,6 @@ EXPORT_SYMBOL(ptlrpc_req_finished_with_imp_lock); */ static int __ptlrpc_req_finished(struct ptlrpc_request *request, int locked) { - ENTRY; if (request == NULL) RETURN(1); @@ -2397,7 +2378,6 @@ void ptlrpc_free_committed(struct obd_import *imp) struct list_head *tmp, *saved; struct ptlrpc_request *req; struct ptlrpc_request *last_req = NULL; /* temporary fire escape */ - ENTRY; LASSERT(imp != NULL); @@ -2463,7 +2443,6 @@ free_req: void ptlrpc_cleanup_client(struct obd_import *imp) { - ENTRY; EXIT; return; } @@ -2517,7 +2496,6 @@ EXPORT_SYMBOL(ptlrpc_restart_req); */ struct ptlrpc_request *ptlrpc_request_addref(struct ptlrpc_request *req) { - ENTRY; atomic_inc(&req->rq_refcount); RETURN(req); } @@ -2588,7 +2566,6 @@ int ptlrpc_queue_wait(struct ptlrpc_request *req) { struct ptlrpc_request_set *set; int rc; - ENTRY; LASSERT(req->rq_set == NULL); LASSERT(!req->rq_receiving_reply); @@ -2629,7 +2606,6 @@ static int ptlrpc_replay_interpret(const struct lu_env *env, struct ptlrpc_replay_async_args *aa = data; struct obd_import *imp = req->rq_import; - ENTRY; atomic_dec(&imp->imp_replay_inflight); if (!ptlrpc_client_replied(req)) { @@ -2721,7 +2697,6 @@ static int ptlrpc_replay_interpret(const struct lu_env *env, int ptlrpc_replay_req(struct ptlrpc_request *req) { struct ptlrpc_replay_async_args *aa; - ENTRY; LASSERT(req->rq_import->imp_state == LUSTRE_IMP_REPLAY); @@ -2761,7 +2736,6 @@ EXPORT_SYMBOL(ptlrpc_replay_req); void ptlrpc_abort_inflight(struct obd_import *imp) { struct list_head *tmp, *n; - ENTRY; /* Make sure that no new requests get processed for this import. * ptlrpc_{queue,set}_wait must (and does) hold imp_lock while testing @@ -2969,7 +2943,6 @@ void *ptlrpcd_alloc_work(struct obd_import *imp, { struct ptlrpc_request *req = NULL; struct ptlrpc_work_async_args *args; - ENTRY; might_sleep(); diff --git a/drivers/staging/lustre/lustre/ptlrpc/connection.c b/drivers/staging/lustre/lustre/ptlrpc/connection.c index a0757f372be5..c5c1d52094c8 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/connection.c +++ b/drivers/staging/lustre/lustre/ptlrpc/connection.c @@ -49,7 +49,6 @@ ptlrpc_connection_get(lnet_process_id_t peer, lnet_nid_t self, struct obd_uuid *uuid) { struct ptlrpc_connection *conn, *conn2; - ENTRY; conn = cfs_hash_lookup(conn_hash, &peer); if (conn) @@ -92,7 +91,6 @@ EXPORT_SYMBOL(ptlrpc_connection_get); int ptlrpc_connection_put(struct ptlrpc_connection *conn) { int rc = 0; - ENTRY; if (!conn) RETURN(rc); @@ -129,8 +127,6 @@ EXPORT_SYMBOL(ptlrpc_connection_put); struct ptlrpc_connection * ptlrpc_connection_addref(struct ptlrpc_connection *conn) { - ENTRY; - atomic_inc(&conn->c_refcount); CDEBUG(D_INFO, "conn=%p refcount %d to %s\n", conn, atomic_read(&conn->c_refcount), @@ -142,8 +138,6 @@ EXPORT_SYMBOL(ptlrpc_connection_addref); int ptlrpc_connection_init(void) { - ENTRY; - conn_hash = cfs_hash_create("CONN_HASH", HASH_CONN_CUR_BITS, HASH_CONN_MAX_BITS, @@ -159,7 +153,6 @@ int ptlrpc_connection_init(void) EXPORT_SYMBOL(ptlrpc_connection_init); void ptlrpc_connection_fini(void) { - ENTRY; cfs_hash_putref(conn_hash); EXIT; } diff --git a/drivers/staging/lustre/lustre/ptlrpc/events.c b/drivers/staging/lustre/lustre/ptlrpc/events.c index 0264c102cb3e..d736a2730106 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/events.c +++ b/drivers/staging/lustre/lustre/ptlrpc/events.c @@ -55,7 +55,6 @@ void request_out_callback(lnet_event_t *ev) { struct ptlrpc_cb_id *cbid = ev->md.user_ptr; struct ptlrpc_request *req = cbid->cbid_arg; - ENTRY; LASSERT (ev->type == LNET_EVENT_SEND || ev->type == LNET_EVENT_UNLINK); @@ -90,7 +89,6 @@ void reply_in_callback(lnet_event_t *ev) { struct ptlrpc_cb_id *cbid = ev->md.user_ptr; struct ptlrpc_request *req = cbid->cbid_arg; - ENTRY; DEBUG_REQ(D_NET, req, "type %d, status %d", ev->type, ev->status); @@ -177,7 +175,6 @@ void client_bulk_callback (lnet_event_t *ev) struct ptlrpc_cb_id *cbid = ev->md.user_ptr; struct ptlrpc_bulk_desc *desc = cbid->cbid_arg; struct ptlrpc_request *req; - ENTRY; LASSERT ((desc->bd_type == BULK_PUT_SINK && ev->type == LNET_EVENT_PUT) || @@ -289,7 +286,6 @@ void request_in_callback(lnet_event_t *ev) struct ptlrpc_service_part *svcpt = rqbd->rqbd_svcpt; struct ptlrpc_service *service = svcpt->scp_service; struct ptlrpc_request *req; - ENTRY; LASSERT (ev->type == LNET_EVENT_PUT || ev->type == LNET_EVENT_UNLINK); @@ -389,7 +385,6 @@ void reply_out_callback(lnet_event_t *ev) struct ptlrpc_cb_id *cbid = ev->md.user_ptr; struct ptlrpc_reply_state *rs = cbid->cbid_arg; struct ptlrpc_service_part *svcpt = rs->rs_svcpt; - ENTRY; LASSERT (ev->type == LNET_EVENT_SEND || ev->type == LNET_EVENT_ACK || diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_bulk.c b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_bulk.c index ed95bbba95ca..6e3439542295 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_bulk.c +++ b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_bulk.c @@ -68,7 +68,6 @@ int gss_cli_ctx_wrap_bulk(struct ptlrpc_cli_ctx *ctx, __u32 maj; int offset; int rc; - ENTRY; LASSERT(req->rq_pack_bulk); LASSERT(req->rq_bulk_read || req->rq_bulk_write); @@ -171,7 +170,6 @@ int gss_cli_ctx_unwrap_bulk(struct ptlrpc_cli_ctx *ctx, rawobj_t token; __u32 maj; int roff, voff; - ENTRY; LASSERT(req->rq_pack_bulk); LASSERT(req->rq_bulk_read || req->rq_bulk_write); @@ -318,7 +316,6 @@ int gss_cli_prep_bulk(struct ptlrpc_request *req, struct ptlrpc_bulk_desc *desc) { int rc; - ENTRY; LASSERT(req->rq_cli_ctx); LASSERT(req->rq_pack_bulk); @@ -341,7 +338,6 @@ int gss_svc_prep_bulk(struct ptlrpc_request *req, struct gss_svc_reqctx *grctx; struct ptlrpc_bulk_sec_desc *bsd; int rc; - ENTRY; LASSERT(req->rq_svc_ctx); LASSERT(req->rq_pack_bulk); @@ -372,7 +368,6 @@ int gss_svc_unwrap_bulk(struct ptlrpc_request *req, struct ptlrpc_bulk_sec_desc *bsdr, *bsdv; rawobj_t token; __u32 maj; - ENTRY; LASSERT(req->rq_svc_ctx); LASSERT(req->rq_pack_bulk); @@ -444,7 +439,6 @@ int gss_svc_wrap_bulk(struct ptlrpc_request *req, rawobj_t token; __u32 maj; int rc; - ENTRY; LASSERT(req->rq_svc_ctx); LASSERT(req->rq_pack_bulk); diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_cli_upcall.c b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_cli_upcall.c index 142c789b1bc6..ca0640c1e947 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_cli_upcall.c +++ b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_cli_upcall.c @@ -378,7 +378,6 @@ int gss_do_ctx_fini_rpc(struct gss_cli_ctx *gctx) struct ptlrpc_request *req; struct ptlrpc_user_desc *pud; int rc; - ENTRY; LASSERT(atomic_read(&ctx->cc_refcount) > 0); diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_keyring.c b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_keyring.c index bb571ae51054..07faa0e0516b 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_keyring.c +++ b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_keyring.c @@ -524,7 +524,6 @@ void rvs_sec_install_root_ctx_kr(struct ptlrpc_sec *sec, struct gss_sec_keyring *gsec_kr = sec2gsec_keyring(sec); struct ptlrpc_cli_ctx *ctx; cfs_time_t now; - ENTRY; LASSERT(sec_is_reverse(sec)); @@ -569,7 +568,6 @@ struct ptlrpc_sec * gss_sec_create_kr(struct obd_import *imp, struct sptlrpc_flavor *sf) { struct gss_sec_keyring *gsec_kr; - ENTRY; OBD_ALLOC(gsec_kr, sizeof(*gsec_kr)); if (gsec_kr == NULL) @@ -683,7 +681,6 @@ struct ptlrpc_cli_ctx * gss_sec_lookup_ctx_kr(struct ptlrpc_sec *sec, char *coinfo; int coinfo_size; char *co_flags = ""; - ENTRY; LASSERT(imp != NULL); @@ -891,7 +888,6 @@ void flush_spec_ctx_cache_kr(struct ptlrpc_sec *sec, struct hlist_head freelist = HLIST_HEAD_INIT; struct hlist_node *next; struct ptlrpc_cli_ctx *ctx; - ENTRY; gsec_kr = sec2gsec_keyring(sec); @@ -937,8 +933,6 @@ static int gss_sec_flush_ctx_cache_kr(struct ptlrpc_sec *sec, uid_t uid, int grace, int force) { - ENTRY; - CDEBUG(D_SEC, "sec %p(%d, nctx %d), uid %d, grace %d, force %d\n", sec, atomic_read(&sec->ps_refcount), atomic_read(&sec->ps_nctx), @@ -959,7 +953,6 @@ void gss_sec_gc_ctx_kr(struct ptlrpc_sec *sec) struct hlist_head freelist = HLIST_HEAD_INIT; struct hlist_node *next; struct ptlrpc_cli_ctx *ctx; - ENTRY; CWARN("running gc\n"); @@ -993,7 +986,6 @@ int gss_sec_display_kr(struct ptlrpc_sec *sec, struct seq_file *seq) struct ptlrpc_cli_ctx *ctx; struct gss_cli_ctx *gctx; time_t now = cfs_time_current_sec(); - ENTRY; spin_lock(&sec->ps_lock); hlist_for_each_entry_safe(ctx, next, @@ -1148,7 +1140,6 @@ static int gss_kt_instantiate(struct key *key, const void *data, size_t datalen) { int rc; - ENTRY; if (data != NULL || datalen != 0) { CERROR("invalid: data %p, len %lu\n", data, (long)datalen); @@ -1198,7 +1189,6 @@ int gss_kt_update(struct key *key, const void *data, size_t datalen) rawobj_t tmpobj = RAWOBJ_EMPTY; __u32 datalen32 = (__u32) datalen; int rc; - ENTRY; if (data == NULL || datalen == 0) { CWARN("invalid: data %p, len %lu\n", data, (long)datalen); @@ -1316,7 +1306,6 @@ int gss_kt_match(const struct key *key, const void *desc) static void gss_kt_destroy(struct key *key) { - ENTRY; LASSERT(key->payload.data == NULL); CDEBUG(D_SEC, "destroy key %p\n", key); EXIT; diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_krb5_mech.c b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_krb5_mech.c index 91da7637756d..4847f11b797a 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_krb5_mech.c +++ b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_krb5_mech.c @@ -890,7 +890,6 @@ int krb5_encrypt_rawobjs(struct ll_crypto_cipher *tfm, __u8 local_iv[16] = {0}, *buf; __u32 datalen = 0; int i, rc; - ENTRY; buf = outobj->data; desc.tfm = tfm; diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_pipefs.c b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_pipefs.c index 3df7257b7fa0..105d0d8bca9e 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_pipefs.c +++ b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_pipefs.c @@ -262,7 +262,6 @@ void gss_sec_ctx_replace_pf(struct gss_sec *gsec, struct hlist_node *next; HLIST_HEAD(freelist); unsigned int hash; - ENTRY; gsec_pf = container_of(gsec, struct gss_sec_pipefs, gsp_base); @@ -297,7 +296,6 @@ int gss_install_rvs_cli_ctx_pf(struct gss_sec *gsec, struct vfs_cred vcred; struct ptlrpc_cli_ctx *cli_ctx; int rc; - ENTRY; vcred.vc_uid = 0; vcred.vc_gid = 0; @@ -324,7 +322,6 @@ void gss_ctx_cache_gc_pf(struct gss_sec_pipefs *gsec_pf, struct ptlrpc_cli_ctx *ctx; struct hlist_node *next; int i; - ENTRY; sec = &gsec_pf->gsp_base.gs_base; @@ -347,7 +344,6 @@ struct ptlrpc_sec* gss_sec_create_pf(struct obd_import *imp, { struct gss_sec_pipefs *gsec_pf; int alloc_size, hash_size, i; - ENTRY; #define GSS_SEC_PIPEFS_CTX_HASH_SIZE (32) @@ -423,7 +419,6 @@ struct ptlrpc_cli_ctx * gss_sec_lookup_ctx_pf(struct ptlrpc_sec *sec, struct hlist_node *next; HLIST_HEAD(freelist); unsigned int hash, gc = 0, found = 0; - ENTRY; might_sleep(); @@ -545,7 +540,6 @@ int gss_sec_flush_ctx_cache_pf(struct ptlrpc_sec *sec, struct hlist_node *next; HLIST_HEAD(freelist); int i, busy = 0; - ENTRY; might_sleep_if(grace); @@ -704,7 +698,6 @@ void upcall_msg_delist(struct gss_upcall_msg *msg) static void gss_release_msg(struct gss_upcall_msg *gmsg) { - ENTRY; LASSERT(atomic_read(&gmsg->gum_refcount) > 0); if (!atomic_dec_and_test(&gmsg->gum_refcount)) { @@ -809,7 +802,6 @@ ssize_t gss_pipe_upcall(struct file *filp, struct rpc_pipe_msg *msg, char *data = (char *)msg->data + msg->copied; ssize_t mlen = msg->len; ssize_t left; - ENTRY; if (mlen > buflen) mlen = buflen; @@ -835,7 +827,6 @@ ssize_t gss_pipe_downcall(struct file *filp, const char *src, size_t mlen) int datalen; int timeout, rc; __u32 mechidx, seq, gss_err; - ENTRY; mechidx = (__u32) (long) rpci->private; LASSERT(mechidx < MECH_MAX); @@ -949,7 +940,6 @@ void gss_pipe_destroy_msg(struct rpc_pipe_msg *msg) struct gss_upcall_msg *gmsg; struct gss_upcall_msg_data *gumd; static cfs_time_t ratelimit = 0; - ENTRY; LASSERT(list_empty(&msg->list)); @@ -988,7 +978,6 @@ void gss_pipe_release(struct inode *inode) { struct rpc_inode *rpci = RPC_I(inode); __u32 idx; - ENTRY; idx = (__u32) (long) rpci->private; LASSERT(idx < MECH_MAX); @@ -1041,7 +1030,6 @@ int gss_ctx_refresh_pf(struct ptlrpc_cli_ctx *ctx) struct gss_sec *gsec; struct gss_upcall_msg *gmsg; int rc = 0; - ENTRY; might_sleep(); diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_svc_upcall.c b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_svc_upcall.c index 31b50ea19c25..243f110cce34 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_svc_upcall.c +++ b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_svc_upcall.c @@ -259,8 +259,6 @@ static int rsi_parse(struct cache_detail *cd, char *mesg, int mlen) struct rsi rsii, *rsip = NULL; time_t expiry; int status = -EINVAL; - ENTRY; - memset(&rsii, 0, sizeof(rsii)); @@ -662,7 +660,6 @@ static void rsc_flush(rsc_entry_match *match, long data) struct cache_head **ch; struct rsc *rscp; int n; - ENTRY; write_lock(&rsc_cache.hash_lock); for (n = 0; n < RSC_HASHMAX; n++) { @@ -744,7 +741,6 @@ int gss_svc_upcall_install_rvs_ctx(struct obd_import *imp, unsigned long ctx_expiry; __u32 major; int rc; - ENTRY; memset(&rsci, 0, sizeof(rsci)); @@ -855,7 +851,6 @@ int gss_svc_upcall_handle_init(struct ptlrpc_request *req, struct gss_rep_header *rephdr; int first_check = 1; int rc = SECSVC_DROP; - ENTRY; memset(&rsikey, 0, sizeof(rsikey)); rsikey.lustre_svc = lustre_svc; diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/sec_gss.c b/drivers/staging/lustre/lustre/ptlrpc/gss/sec_gss.c index ebca858ca183..0553965cc368 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/gss/sec_gss.c +++ b/drivers/staging/lustre/lustre/ptlrpc/gss/sec_gss.c @@ -280,7 +280,6 @@ __u32 gss_unseal_msg(struct gss_ctx *mechctx, __u8 *clear_buf; int clear_buflen; __u32 major; - ENTRY; if (msgbuf->lm_bufcount != 2) { CERROR("invalid bufcount %d\n", msgbuf->lm_bufcount); @@ -646,7 +645,6 @@ int gss_cli_ctx_sign(struct ptlrpc_cli_ctx *ctx, struct gss_cli_ctx *gctx = ctx2gctx(ctx); __u32 flags = 0, seq, svc; int rc; - ENTRY; LASSERT(req->rq_reqbuf); LASSERT(req->rq_reqbuf->lm_bufcount >= 2); @@ -765,7 +763,6 @@ int gss_cli_ctx_verify(struct ptlrpc_cli_ctx *ctx, struct lustre_msg *msg = req->rq_repdata; __u32 major; int pack_bulk, swabbed, rc = 0; - ENTRY; LASSERT(req->rq_cli_ctx == ctx); LASSERT(msg); @@ -889,7 +886,6 @@ int gss_cli_ctx_seal(struct ptlrpc_cli_ctx *ctx, struct gss_header *ghdr; __u32 buflens[2], major; int wiresize, rc; - ENTRY; LASSERT(req->rq_clrbuf); LASSERT(req->rq_cli_ctx == ctx); @@ -988,7 +984,6 @@ int gss_cli_ctx_unseal(struct ptlrpc_cli_ctx *ctx, struct lustre_msg *msg = req->rq_repdata; int msglen, pack_bulk, swabbed, rc; __u32 major; - ENTRY; LASSERT(req->rq_cli_ctx == ctx); LASSERT(req->rq_ctx_init == 0); @@ -1148,7 +1143,6 @@ int gss_sec_create_common(struct gss_sec *gsec, void gss_sec_destroy_common(struct gss_sec *gsec) { struct ptlrpc_sec *sec = &gsec->gs_base; - ENTRY; LASSERT(sec->ps_import); LASSERT(atomic_read(&sec->ps_refcount) == 0); @@ -1260,7 +1254,6 @@ int gss_alloc_reqbuf_intg(struct ptlrpc_sec *sec, int bufsize, txtsize; int bufcnt = 2; __u32 buflens[5]; - ENTRY; /* * on-wire data layout: @@ -1342,7 +1335,6 @@ int gss_alloc_reqbuf_priv(struct ptlrpc_sec *sec, __u32 ibuflens[3], wbuflens[2]; int ibufcnt; int clearsize, wiresize; - ENTRY; LASSERT(req->rq_clrbuf == NULL); LASSERT(req->rq_clrbuf_len == 0); @@ -1442,7 +1434,6 @@ void gss_free_reqbuf(struct ptlrpc_sec *sec, struct ptlrpc_request *req) { int privacy; - ENTRY; LASSERT(!req->rq_pool || req->rq_reqbuf); privacy = SPTLRPC_FLVR_SVC(req->rq_flvr.sf_rpc) == SPTLRPC_SVC_PRIV; @@ -1578,7 +1569,6 @@ int gss_alloc_repbuf(struct ptlrpc_sec *sec, int msgsize) { int svc = SPTLRPC_FLVR_SVC(req->rq_flvr.sf_rpc); - ENTRY; LASSERT(!req->rq_pack_bulk || (req->rq_bulk_read || req->rq_bulk_write)); @@ -1891,7 +1881,6 @@ int gss_svc_sign(struct ptlrpc_request *req, { __u32 flags = 0; int rc; - ENTRY; LASSERT(rs->rs_msg == lustre_msg_buf(rs->rs_repbuf, 1, 0)); @@ -1933,7 +1922,6 @@ int gss_pack_err_notify(struct ptlrpc_request *req, __u32 major, __u32 minor) struct gss_err_header *ghdr; int replen = sizeof(struct ptlrpc_body); int rc; - ENTRY; //if (OBD_FAIL_CHECK_ORSET(OBD_FAIL_SVCGSS_ERR_NOTIFY, OBD_FAIL_ONCE)) // RETURN(-EINVAL); @@ -1978,7 +1966,6 @@ int gss_svc_handle_init(struct ptlrpc_request *req, __u32 lustre_svc; __u32 *secdata, seclen; int swabbed, rc; - ENTRY; CDEBUG(D_SEC, "processing gss init(%d) request from %s\n", gw->gw_proc, libcfs_nid2str(req->rq_peer.nid)); @@ -2094,7 +2081,6 @@ int gss_svc_verify_request(struct ptlrpc_request *req, struct lustre_msg *msg = req->rq_reqbuf; int offset = 2; int swabbed; - ENTRY; *major = GSS_S_COMPLETE; @@ -2174,7 +2160,6 @@ int gss_svc_unseal_request(struct ptlrpc_request *req, struct gss_svc_ctx *gctx = grctx->src_ctx; struct lustre_msg *msg = req->rq_reqbuf; int swabbed, msglen, offset = 1; - ENTRY; if (gss_check_seq_num(&gctx->gsc_seqdata, gw->gw_seq, 0)) { CERROR("phase 0: discard replayed req: seq %u\n", gw->gw_seq); @@ -2249,7 +2234,6 @@ int gss_svc_handle_data(struct ptlrpc_request *req, struct gss_svc_reqctx *grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx); __u32 major = 0; int rc = 0; - ENTRY; grctx->src_ctx = gss_svc_upcall_get_ctx(req, gw); if (!grctx->src_ctx) { @@ -2294,7 +2278,6 @@ int gss_svc_handle_destroy(struct ptlrpc_request *req, { struct gss_svc_reqctx *grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx); __u32 major; - ENTRY; req->rq_ctx_fini = 1; req->rq_no_reply = 1; @@ -2343,7 +2326,6 @@ int gss_svc_accept(struct ptlrpc_sec_policy *policy, struct ptlrpc_request *req) struct gss_svc_reqctx *grctx; struct gss_wire_ctx *gw; int swabbed, rc; - ENTRY; LASSERT(req->rq_reqbuf); LASSERT(req->rq_svc_ctx == NULL); @@ -2434,7 +2416,6 @@ int gss_svc_accept(struct ptlrpc_sec_policy *policy, struct ptlrpc_request *req) void gss_svc_invalidate_ctx(struct ptlrpc_svc_ctx *svc_ctx) { struct gss_svc_reqctx *grctx; - ENTRY; if (svc_ctx == NULL) { EXIT; @@ -2496,7 +2477,6 @@ int gss_svc_alloc_rs(struct ptlrpc_request *req, int msglen) __u32 ibuflens[2], buflens[4]; int ibufcnt = 0, bufcnt; int txtsize, wmsg_size, rs_size; - ENTRY; LASSERT(msglen % 8 == 0); @@ -2619,7 +2599,6 @@ static int gss_svc_seal(struct ptlrpc_request *req, int token_buflen; __u32 buflens[2], major; int msglen, rc; - ENTRY; /* get clear data length. note embedded lustre_msg might * have been shrinked */ @@ -2712,7 +2691,6 @@ int gss_svc_authorize(struct ptlrpc_request *req) struct gss_svc_reqctx *grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx); struct gss_wire_ctx *gw = &grctx->src_wirectx; int early, rc; - ENTRY; early = (req->rq_packed_final == 0); diff --git a/drivers/staging/lustre/lustre/ptlrpc/import.c b/drivers/staging/lustre/lustre/ptlrpc/import.c index 47a3c0512739..3b1137b9ac9d 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/import.c +++ b/drivers/staging/lustre/lustre/ptlrpc/import.c @@ -195,7 +195,6 @@ int ptlrpc_set_import_discon(struct obd_import *imp, __u32 conn_cnt) /* Must be called with imp_lock held! */ static void ptlrpc_deactivate_and_unlock_import(struct obd_import *imp) { - ENTRY; LASSERT(spin_is_locked(&imp->imp_lock)); CDEBUG(D_HA, "setting import %s INVALID\n", obd2cli_tgt(imp->imp_obd)); @@ -394,8 +393,6 @@ EXPORT_SYMBOL(ptlrpc_activate_import); void ptlrpc_fail_import(struct obd_import *imp, __u32 conn_cnt) { - ENTRY; - LASSERT(!imp->imp_dlm_fake); if (ptlrpc_set_import_discon(imp, conn_cnt)) { @@ -461,7 +458,6 @@ static int import_select_connection(struct obd_import *imp) struct obd_export *dlmexp; char *target_start; int target_len, tried_all = 1; - ENTRY; spin_lock(&imp->imp_lock); @@ -602,7 +598,6 @@ int ptlrpc_connect_import(struct obd_import *imp) (char *)&imp->imp_connect_data }; struct ptlrpc_connect_async_args *aa; int rc; - ENTRY; spin_lock(&imp->imp_lock); if (imp->imp_state == LUSTRE_IMP_CLOSED) { @@ -756,7 +751,6 @@ static int ptlrpc_connect_interpret(const struct lu_env *env, struct obd_connect_data *ocd; struct obd_export *exp; int ret; - ENTRY; spin_lock(&imp->imp_lock); if (imp->imp_state == LUSTRE_IMP_CLOSED) { @@ -1183,7 +1177,6 @@ static int completed_replay_interpret(const struct lu_env *env, struct ptlrpc_request *req, void * data, int rc) { - ENTRY; atomic_dec(&req->rq_import->imp_replay_inflight); if (req->rq_status == 0 && !req->rq_import->imp_vbr_failed) { @@ -1212,7 +1205,6 @@ static int completed_replay_interpret(const struct lu_env *env, static int signal_completed_replay(struct obd_import *imp) { struct ptlrpc_request *req; - ENTRY; if (unlikely(OBD_FAIL_CHECK(OBD_FAIL_PTLRPC_FINISH_REPLAY))) RETURN(0); @@ -1248,8 +1240,6 @@ static int ptlrpc_invalidate_import_thread(void *data) { struct obd_import *imp = data; - ENTRY; - unshare_fs_struct(); CDEBUG(D_HA, "thread invalidate import %s to %s@%s\n", @@ -1297,7 +1287,6 @@ int ptlrpc_import_recovery_state_machine(struct obd_import *imp) char *target_start; int target_len; - ENTRY; if (imp->imp_state == LUSTRE_IMP_EVICTED) { deuuidify(obd2cli_tgt(imp->imp_obd), NULL, &target_start, &target_len); @@ -1401,7 +1390,6 @@ int ptlrpc_disconnect_import(struct obd_import *imp, int noclose) struct ptlrpc_request *req; int rq_opc, rc = 0; int nowait = imp->imp_obd->obd_force; - ENTRY; if (nowait) GOTO(set_state, rc); @@ -1482,8 +1470,6 @@ EXPORT_SYMBOL(ptlrpc_disconnect_import); void ptlrpc_cleanup_imp(struct obd_import *imp) { - ENTRY; - spin_lock(&imp->imp_lock); IMPORT_SET_STATE_NOLOCK(imp, LUSTRE_IMP_CLOSED); imp->imp_generation++; diff --git a/drivers/staging/lustre/lustre/ptlrpc/llog_client.c b/drivers/staging/lustre/lustre/ptlrpc/llog_client.c index 367ca8ef7d60..b3db05583641 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/llog_client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/llog_client.c @@ -85,7 +85,6 @@ static int llog_client_open(const struct lu_env *env, struct llog_ctxt *ctxt = lgh->lgh_ctxt; struct ptlrpc_request *req = NULL; int rc; - ENTRY; LLOG_CLIENT_ENTRY(ctxt, imp); @@ -147,7 +146,6 @@ static int llog_client_destroy(const struct lu_env *env, struct ptlrpc_request *req = NULL; struct llogd_body *body; int rc; - ENTRY; LLOG_CLIENT_ENTRY(loghandle->lgh_ctxt, imp); req = ptlrpc_request_alloc_pack(imp, &RQF_LLOG_ORIGIN_HANDLE_DESTROY, @@ -184,7 +182,6 @@ static int llog_client_next_block(const struct lu_env *env, struct llogd_body *body; void *ptr; int rc; - ENTRY; LLOG_CLIENT_ENTRY(loghandle->lgh_ctxt, imp); req = ptlrpc_request_alloc_pack(imp, &RQF_LLOG_ORIGIN_HANDLE_NEXT_BLOCK, @@ -238,7 +235,6 @@ static int llog_client_prev_block(const struct lu_env *env, struct llogd_body *body; void *ptr; int rc; - ENTRY; LLOG_CLIENT_ENTRY(loghandle->lgh_ctxt, imp); req = ptlrpc_request_alloc_pack(imp, &RQF_LLOG_ORIGIN_HANDLE_PREV_BLOCK, @@ -287,7 +283,6 @@ static int llog_client_read_header(const struct lu_env *env, struct llog_log_hdr *hdr; struct llog_rec_hdr *llh_hdr; int rc; - ENTRY; LLOG_CLIENT_ENTRY(handle->lgh_ctxt, imp); req = ptlrpc_request_alloc_pack(imp,&RQF_LLOG_ORIGIN_HANDLE_READ_HEADER, diff --git a/drivers/staging/lustre/lustre/ptlrpc/llog_net.c b/drivers/staging/lustre/lustre/ptlrpc/llog_net.c index a81f557d7794..963223d3ed1f 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/llog_net.c +++ b/drivers/staging/lustre/lustre/ptlrpc/llog_net.c @@ -57,7 +57,6 @@ int llog_initiator_connect(struct llog_ctxt *ctxt) { struct obd_import *new_imp; - ENTRY; LASSERT(ctxt); new_imp = ctxt->loc_obd->u.cli.cl_import; diff --git a/drivers/staging/lustre/lustre/ptlrpc/llog_server.c b/drivers/staging/lustre/lustre/ptlrpc/llog_server.c index bc1fcd8c7e73..b5aec5e84ee6 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/llog_server.c +++ b/drivers/staging/lustre/lustre/ptlrpc/llog_server.c @@ -71,8 +71,6 @@ int llog_origin_handle_open(struct ptlrpc_request *req) char *name = NULL; int rc; - ENTRY; - body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY); if (body == NULL) RETURN(-EFAULT); @@ -127,8 +125,6 @@ int llog_origin_handle_destroy(struct ptlrpc_request *req) struct llog_ctxt *ctxt; int rc; - ENTRY; - body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY); if (body == NULL) RETURN(-EFAULT); @@ -169,8 +165,6 @@ int llog_origin_handle_next_block(struct ptlrpc_request *req) void *ptr; int rc; - ENTRY; - body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY); if (body == NULL) RETURN(-EFAULT); @@ -230,8 +224,6 @@ int llog_origin_handle_prev_block(struct ptlrpc_request *req) void *ptr; int rc; - ENTRY; - body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY); if (body == NULL) RETURN(-EFAULT); @@ -290,8 +282,6 @@ int llog_origin_handle_read_header(struct ptlrpc_request *req) __u32 flags; int rc; - ENTRY; - body = req_capsule_client_get(&req->rq_pill, &RMF_LLOGD_BODY); if (body == NULL) RETURN(-EFAULT); @@ -336,7 +326,6 @@ EXPORT_SYMBOL(llog_origin_handle_read_header); int llog_origin_handle_close(struct ptlrpc_request *req) { - ENTRY; /* Nothing to do */ RETURN(0); } @@ -352,7 +341,6 @@ int llog_origin_handle_cancel(struct ptlrpc_request *req) struct llog_handle *cathandle; struct inode *inode; void *handle; - ENTRY; logcookies = req_capsule_client_get(&req->rq_pill, &RMF_LOGCOOKIES); num_cookies = req_capsule_get_size(&req->rq_pill, &RMF_LOGCOOKIES, diff --git a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c index 2bd0d985bf1d..602ce679508b 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c +++ b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c @@ -480,7 +480,6 @@ static int ptlrpc_lprocfs_nrs_seq_show(struct seq_file *m, void *n) bool hp = false; int i; int rc = 0; - ENTRY; /** * Serialize NRS core lprocfs operations with policy registration/ @@ -638,7 +637,6 @@ static ssize_t ptlrpc_lprocfs_nrs_seq_write(struct file *file, const char *buffe char *cmd_copy = NULL; char *token; int rc = 0; - ENTRY; if (count >= LPROCFS_NRS_WR_MAX_CMD) GOTO(out, rc = -EINVAL); @@ -1217,7 +1215,6 @@ int lprocfs_wr_ping(struct file *file, const char *buffer, struct obd_device *obd = ((struct seq_file *)file->private_data)->private; struct ptlrpc_request *req; int rc; - ENTRY; LPROCFS_CLIMP_CHECK(obd); req = ptlrpc_prep_ping(obd->u.cli.cl_import); diff --git a/drivers/staging/lustre/lustre/ptlrpc/niobuf.c b/drivers/staging/lustre/lustre/ptlrpc/niobuf.c index 5f1b889e5277..b5b5b486edbf 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/niobuf.c +++ b/drivers/staging/lustre/lustre/ptlrpc/niobuf.c @@ -54,7 +54,6 @@ static int ptl_send_buf (lnet_handle_md_t *mdh, void *base, int len, { int rc; lnet_md_t md; - ENTRY; LASSERT (portal != 0); LASSERT (conn != NULL); @@ -122,7 +121,6 @@ int ptlrpc_register_bulk(struct ptlrpc_request *req) __u64 xid; lnet_handle_me_t me_h; lnet_md_t md; - ENTRY; if (OBD_FAIL_CHECK(OBD_FAIL_PTLRPC_BULK_GET_NET)) RETURN(0); @@ -247,7 +245,6 @@ int ptlrpc_unregister_bulk(struct ptlrpc_request *req, int async) wait_queue_head_t *wq; struct l_wait_info lwi; int rc; - ENTRY; LASSERT(!in_interrupt()); /* might sleep */ @@ -456,7 +453,6 @@ EXPORT_SYMBOL(ptlrpc_reply); int ptlrpc_send_error(struct ptlrpc_request *req, int may_be_difficult) { int rc; - ENTRY; if (req->rq_no_reply) RETURN(0); @@ -498,7 +494,6 @@ int ptl_send_rpc(struct ptlrpc_request *request, int noreply) lnet_handle_me_t reply_me_h; lnet_md_t reply_md; struct obd_device *obd = request->rq_import->imp_obd; - ENTRY; if (OBD_FAIL_CHECK(OBD_FAIL_PTLRPC_DROP_RPC)) RETURN(0); diff --git a/drivers/staging/lustre/lustre/ptlrpc/nrs.c b/drivers/staging/lustre/lustre/ptlrpc/nrs.c index 1996431e35ff..352c0f1af471 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/nrs.c +++ b/drivers/staging/lustre/lustre/ptlrpc/nrs.c @@ -91,7 +91,6 @@ static int nrs_policy_ctl_locked(struct ptlrpc_nrs_policy *policy, static void nrs_policy_stop0(struct ptlrpc_nrs_policy *policy) { struct ptlrpc_nrs *nrs = policy->pol_nrs; - ENTRY; if (policy->pol_desc->pd_ops->op_policy_stop != NULL) { spin_unlock(&nrs->nrs_lock); @@ -118,7 +117,6 @@ static void nrs_policy_stop0(struct ptlrpc_nrs_policy *policy) static int nrs_policy_stop_locked(struct ptlrpc_nrs_policy *policy) { struct ptlrpc_nrs *nrs = policy->pol_nrs; - ENTRY; if (nrs->nrs_policy_fallback == policy && !nrs->nrs_stopping) RETURN(-EPERM); @@ -158,7 +156,6 @@ static int nrs_policy_stop_locked(struct ptlrpc_nrs_policy *policy) static void nrs_policy_stop_primary(struct ptlrpc_nrs *nrs) { struct ptlrpc_nrs_policy *tmp = nrs->nrs_policy_primary; - ENTRY; if (tmp == NULL) { /** @@ -203,7 +200,6 @@ static int nrs_policy_start_locked(struct ptlrpc_nrs_policy *policy) { struct ptlrpc_nrs *nrs = policy->pol_nrs; int rc = 0; - ENTRY; /** * Don't allow multiple starting which is too complex, and has no real @@ -644,7 +640,6 @@ static int nrs_policy_ctl(struct ptlrpc_nrs *nrs, char *name, { struct ptlrpc_nrs_policy *policy; int rc = 0; - ENTRY; spin_lock(&nrs->nrs_lock); @@ -690,7 +685,6 @@ out: static int nrs_policy_unregister(struct ptlrpc_nrs *nrs, char *name) { struct ptlrpc_nrs_policy *policy = NULL; - ENTRY; spin_lock(&nrs->nrs_lock); @@ -751,7 +745,6 @@ static int nrs_policy_register(struct ptlrpc_nrs *nrs, struct ptlrpc_nrs_policy *tmp; struct ptlrpc_service_part *svcpt = nrs->nrs_svcpt; int rc; - ENTRY; LASSERT(svcpt != NULL); LASSERT(desc->pd_ops != NULL); @@ -844,7 +837,6 @@ static void ptlrpc_nrs_req_add_nolock(struct ptlrpc_request *req) static void ptlrpc_nrs_hpreq_add_nolock(struct ptlrpc_request *req) { int opc = lustre_msg_get_opc(req->rq_reqmsg); - ENTRY; spin_lock(&req->rq_lock); req->rq_hp = 1; @@ -891,7 +883,6 @@ static int nrs_register_policies_locked(struct ptlrpc_nrs *nrs) struct ptlrpc_service_part *svcpt = nrs->nrs_svcpt; struct ptlrpc_service *svc = svcpt->scp_service; int rc = -EINVAL; - ENTRY; LASSERT(mutex_is_locked(&nrs_core.nrs_mutex)); @@ -966,7 +957,6 @@ static int nrs_svcpt_setup_locked(struct ptlrpc_service_part *svcpt) { struct ptlrpc_nrs *nrs; int rc; - ENTRY; LASSERT(mutex_is_locked(&nrs_core.nrs_mutex)); @@ -1012,7 +1002,6 @@ static void nrs_svcpt_cleanup_locked(struct ptlrpc_service_part *svcpt) struct ptlrpc_nrs_policy *tmp; int rc; bool hp = false; - ENTRY; LASSERT(mutex_is_locked(&nrs_core.nrs_mutex)); @@ -1051,7 +1040,6 @@ again: static struct ptlrpc_nrs_pol_desc *nrs_policy_find_desc_locked(const char *name) { struct ptlrpc_nrs_pol_desc *tmp; - ENTRY; list_for_each_entry(tmp, &nrs_core.nrs_policies, pd_list) { if (strncmp(tmp->pd_name, name, NRS_POL_NAME_MAX) == 0) @@ -1079,7 +1067,6 @@ static int nrs_policy_unregister_locked(struct ptlrpc_nrs_pol_desc *desc) struct ptlrpc_service_part *svcpt; int i; int rc = 0; - ENTRY; LASSERT(mutex_is_locked(&nrs_core.nrs_mutex)); LASSERT(mutex_is_locked(&ptlrpc_all_services_mutex)); @@ -1143,7 +1130,6 @@ int ptlrpc_nrs_policy_register(struct ptlrpc_nrs_pol_conf *conf) struct ptlrpc_service *svc; struct ptlrpc_nrs_pol_desc *desc; int rc = 0; - ENTRY; LASSERT(conf != NULL); LASSERT(conf->nc_ops != NULL); @@ -1296,7 +1282,6 @@ int ptlrpc_nrs_policy_unregister(struct ptlrpc_nrs_pol_conf *conf) { struct ptlrpc_nrs_pol_desc *desc; int rc; - ENTRY; LASSERT(conf != NULL); @@ -1630,7 +1615,6 @@ void ptlrpc_nrs_req_hp_move(struct ptlrpc_request *req) struct ptlrpc_nrs_request *nrq = &req->rq_nrq; struct ptlrpc_nrs_resource *res1[NRS_RES_MAX]; struct ptlrpc_nrs_resource *res2[NRS_RES_MAX]; - ENTRY; /** * Obtain the high-priority NRS head resources. @@ -1696,7 +1680,6 @@ int ptlrpc_nrs_policy_control(const struct ptlrpc_service *svc, struct ptlrpc_service_part *svcpt; int i; int rc = 0; - ENTRY; LASSERT(opc != PTLRPC_NRS_CTL_INVALID); @@ -1745,7 +1728,6 @@ extern struct ptlrpc_nrs_pol_conf nrs_conf_fifo; int ptlrpc_nrs_init(void) { int rc; - ENTRY; mutex_init(&nrs_core.nrs_mutex); INIT_LIST_HEAD(&nrs_core.nrs_policies); diff --git a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c index 9c20d0c60678..aae4fd67152a 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c @@ -329,7 +329,6 @@ int lustre_pack_reply_v2(struct ptlrpc_request *req, int count, { struct ptlrpc_reply_state *rs; int msg_len, rc; - ENTRY; LASSERT(req->rq_reply_state == NULL); @@ -574,7 +573,6 @@ static int lustre_unpack_msg_v2(struct lustre_msg_v2 *m, int len) int __lustre_unpack_msg(struct lustre_msg *m, int len) { int required_len, rc; - ENTRY; /* We can provide a slightly better error log, if we check the * message magic and version first. In the future, struct @@ -1616,7 +1614,6 @@ int do_set_info_async(struct obd_import *imp, struct ptlrpc_request *req; char *tmp; int rc; - ENTRY; req = ptlrpc_request_alloc(imp, &RQF_OBD_SET_INFO); if (req == NULL) @@ -2166,7 +2163,6 @@ static void lustre_swab_lmm_oi(struct ost_id *oi) static void lustre_swab_lov_user_md_common(struct lov_user_md_v1 *lum) { - ENTRY; __swab32s(&lum->lmm_magic); __swab32s(&lum->lmm_pattern); lustre_swab_lmm_oi(&lum->lmm_oi); @@ -2179,7 +2175,6 @@ static void lustre_swab_lov_user_md_common(struct lov_user_md_v1 *lum) void lustre_swab_lov_user_md_v1(struct lov_user_md_v1 *lum) { - ENTRY; CDEBUG(D_IOCTL, "swabbing lov_user_md v1\n"); lustre_swab_lov_user_md_common(lum); EXIT; @@ -2188,7 +2183,6 @@ EXPORT_SYMBOL(lustre_swab_lov_user_md_v1); void lustre_swab_lov_user_md_v3(struct lov_user_md_v3 *lum) { - ENTRY; CDEBUG(D_IOCTL, "swabbing lov_user_md v3\n"); lustre_swab_lov_user_md_common((struct lov_user_md_v1 *)lum); /* lmm_pool_name nothing to do with char */ @@ -2198,7 +2192,6 @@ EXPORT_SYMBOL(lustre_swab_lov_user_md_v3); void lustre_swab_lov_mds_md(struct lov_mds_md *lmm) { - ENTRY; CDEBUG(D_IOCTL, "swabbing lov_mds_md\n"); __swab32s(&lmm->lmm_magic); __swab32s(&lmm->lmm_pattern); @@ -2214,7 +2207,7 @@ void lustre_swab_lov_user_md_objects(struct lov_user_ost_data *lod, int stripe_count) { int i; - ENTRY; + for (i = 0; i < stripe_count; i++) { lustre_swab_ost_id(&(lod[i].l_ost_oi)); __swab32s(&(lod[i].l_ost_gen)); diff --git a/drivers/staging/lustre/lustre/ptlrpc/pinger.c b/drivers/staging/lustre/lustre/ptlrpc/pinger.c index 79e7d0852e95..74372914e850 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pinger.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pinger.c @@ -75,7 +75,6 @@ int ptlrpc_obd_ping(struct obd_device *obd) { int rc; struct ptlrpc_request *req; - ENTRY; req = ptlrpc_prep_ping(obd->u.cli.cl_import); if (req == NULL) @@ -94,7 +93,6 @@ EXPORT_SYMBOL(ptlrpc_obd_ping); int ptlrpc_ping(struct obd_import *imp) { struct ptlrpc_request *req; - ENTRY; req = ptlrpc_prep_ping(imp); if (req == NULL) { @@ -297,7 +295,6 @@ static void ptlrpc_pinger_process_import(struct obd_import *imp, static int ptlrpc_pinger_main(void *arg) { struct ptlrpc_thread *thread = (struct ptlrpc_thread *)arg; - ENTRY; /* Record that the thread is running */ thread_set_flags(thread, SVC_RUNNING); @@ -375,7 +372,6 @@ int ptlrpc_start_pinger(void) { struct l_wait_info lwi = { 0 }; int rc; - ENTRY; if (!thread_is_init(&pinger_thread) && !thread_is_stopped(&pinger_thread)) @@ -413,7 +409,6 @@ int ptlrpc_stop_pinger(void) { struct l_wait_info lwi = { 0 }; int rc = 0; - ENTRY; if (!thread_is_init(&pinger_thread) && !thread_is_stopped(&pinger_thread)) @@ -452,7 +447,6 @@ void ptlrpc_pinger_commit_expected(struct obd_import *imp) int ptlrpc_pinger_add_import(struct obd_import *imp) { - ENTRY; if (!list_empty(&imp->imp_pinger_chain)) RETURN(-EALREADY); @@ -475,7 +469,6 @@ EXPORT_SYMBOL(ptlrpc_pinger_add_import); int ptlrpc_pinger_del_import(struct obd_import *imp) { - ENTRY; if (list_empty(&imp->imp_pinger_chain)) RETURN(-ENOENT); @@ -652,7 +645,6 @@ static int ping_evictor_main(void *arg) struct obd_export *exp; struct l_wait_info lwi = { 0 }; time_t expire_time; - ENTRY; unshare_fs_struct(); diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_module.c b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_module.c index f6ea80f0b105..e8163805e685 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_module.c +++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_module.c @@ -54,7 +54,6 @@ extern struct mutex ptlrpcd_mutex; __init int ptlrpc_init(void) { int rc, cleanup_phase = 0; - ENTRY; lustre_assert_wire_constants(); #if RS_DEBUG diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c index 5a66a1be4228..e0ee38e80ae2 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c +++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c @@ -268,7 +268,6 @@ static int ptlrpcd_check(struct lu_env *env, struct ptlrpcd_ctl *pc) struct ptlrpc_request_set *set = pc->pc_set; int rc = 0; int rc2; - ENTRY; if (atomic_read(&set->set_new_count)) { spin_lock(&set->set_new_req_lock); @@ -383,7 +382,6 @@ static int ptlrpcd(void *arg) struct ptlrpc_request_set *set = pc->pc_set; struct lu_env env = { .le_ses = NULL }; int rc, exit = 0; - ENTRY; unshare_fs_struct(); #if defined(CONFIG_SMP) @@ -501,7 +499,6 @@ static int ptlrpcd_bind(int index, int max) #if defined(CONFIG_NUMA) cpumask_t mask; #endif - ENTRY; LASSERT(index <= max - 1); pc = &ptlrpcds->pd_threads[index]; @@ -604,7 +601,6 @@ int ptlrpcd_start(int index, int max, const char *name, struct ptlrpcd_ctl *pc) { int rc; int env = 0; - ENTRY; /* * Do not allow start second thread for one pc. @@ -668,8 +664,6 @@ out: void ptlrpcd_stop(struct ptlrpcd_ctl *pc, int force) { - ENTRY; - if (!test_bit(LIOD_START, &pc->pc_flags)) { CWARN("Thread for pc %p was not started\n", pc); goto out; @@ -687,7 +681,6 @@ out: void ptlrpcd_free(struct ptlrpcd_ctl *pc) { struct ptlrpc_request_set *set = pc->pc_set; - ENTRY; if (!test_bit(LIOD_START, &pc->pc_flags)) { CWARN("Thread for pc %p was not started\n", pc); @@ -722,7 +715,6 @@ out: static void ptlrpcd_fini(void) { int i; - ENTRY; if (ptlrpcds != NULL) { for (i = 0; i < ptlrpcds->pd_nthreads; i++) @@ -743,7 +735,6 @@ static int ptlrpcd_init(void) int nthreads = num_online_cpus(); char name[16]; int size, i = -1, j, rc = 0; - ENTRY; if (max_ptlrpcds > 0 && max_ptlrpcds < nthreads) nthreads = max_ptlrpcds; @@ -806,7 +797,6 @@ out: int ptlrpcd_addref(void) { int rc = 0; - ENTRY; mutex_lock(&ptlrpcd_mutex); if (++ptlrpcd_users == 1) diff --git a/drivers/staging/lustre/lustre/ptlrpc/recover.c b/drivers/staging/lustre/lustre/ptlrpc/recover.c index 2960889834a2..29a9f0acc672 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/recover.c +++ b/drivers/staging/lustre/lustre/ptlrpc/recover.c @@ -60,8 +60,6 @@ */ void ptlrpc_initiate_recovery(struct obd_import *imp) { - ENTRY; - CDEBUG(D_HA, "%s: starting recovery\n", obd2cli_tgt(imp->imp_obd)); ptlrpc_connect_import(imp); @@ -78,7 +76,6 @@ int ptlrpc_replay_next(struct obd_import *imp, int *inflight) struct list_head *tmp, *pos; struct ptlrpc_request *req = NULL; __u64 last_transno; - ENTRY; *inflight = 0; @@ -152,8 +149,6 @@ int ptlrpc_resend(struct obd_import *imp) { struct ptlrpc_request *req, *next; - ENTRY; - /* As long as we're in recovery, nothing should be added to the sending * list, so we don't need to hold the lock during this iteration and * resend process. @@ -203,7 +198,6 @@ EXPORT_SYMBOL(ptlrpc_wake_delayed); void ptlrpc_request_handle_notconn(struct ptlrpc_request *failed_req) { struct obd_import *imp = failed_req->rq_import; - ENTRY; CDEBUG(D_HA, "import %s of %s@%s abruptly disconnected: reconnecting\n", imp->imp_obd->obd_name, obd2cli_tgt(imp->imp_obd), @@ -246,7 +240,6 @@ int ptlrpc_set_import_active(struct obd_import *imp, int active) struct obd_device *obd = imp->imp_obd; int rc = 0; - ENTRY; LASSERT(obd); /* When deactivating, mark import invalid, and abort in-flight @@ -287,7 +280,6 @@ EXPORT_SYMBOL(ptlrpc_set_import_active); int ptlrpc_recover_import(struct obd_import *imp, char *new_uuid, int async) { int rc = 0; - ENTRY; spin_lock(&imp->imp_lock); if (imp->imp_state == LUSTRE_IMP_NEW || imp->imp_deactive || diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec.c b/drivers/staging/lustre/lustre/ptlrpc/sec.c index 349c57b6d78a..9ec7157e7fd9 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec.c @@ -396,7 +396,6 @@ int sptlrpc_req_get_ctx(struct ptlrpc_request *req) struct obd_import *imp = req->rq_import; struct ptlrpc_sec *sec; int rc; - ENTRY; LASSERT(!req->rq_cli_ctx); LASSERT(imp); @@ -428,8 +427,6 @@ int sptlrpc_req_get_ctx(struct ptlrpc_request *req) */ void sptlrpc_req_put_ctx(struct ptlrpc_request *req, int sync) { - ENTRY; - LASSERT(req); LASSERT(req->rq_cli_ctx); @@ -520,7 +517,6 @@ int sptlrpc_req_replace_dead_ctx(struct ptlrpc_request *req) struct ptlrpc_cli_ctx *oldctx = req->rq_cli_ctx; struct ptlrpc_cli_ctx *newctx; int rc; - ENTRY; LASSERT(oldctx); @@ -639,7 +635,6 @@ int sptlrpc_req_refresh_ctx(struct ptlrpc_request *req, long timeout) struct ptlrpc_sec *sec; struct l_wait_info lwi; int rc; - ENTRY; LASSERT(ctx); @@ -889,7 +884,6 @@ int sptlrpc_import_check_ctx(struct obd_import *imp) struct ptlrpc_cli_ctx *ctx; struct ptlrpc_request *req = NULL; int rc; - ENTRY; might_sleep(); @@ -941,7 +935,6 @@ int sptlrpc_cli_wrap_request(struct ptlrpc_request *req) { struct ptlrpc_cli_ctx *ctx = req->rq_cli_ctx; int rc = 0; - ENTRY; LASSERT(ctx); LASSERT(ctx->cc_sec); @@ -984,7 +977,6 @@ static int do_cli_unwrap_reply(struct ptlrpc_request *req) { struct ptlrpc_cli_ctx *ctx = req->rq_cli_ctx; int rc; - ENTRY; LASSERT(ctx); LASSERT(ctx->cc_sec); @@ -1096,7 +1088,6 @@ int sptlrpc_cli_unwrap_early_reply(struct ptlrpc_request *req, char *early_buf; int early_bufsz, early_size; int rc; - ENTRY; OBD_ALLOC_PTR(early_req); if (early_req == NULL) @@ -1285,7 +1276,6 @@ struct ptlrpc_sec * sptlrpc_sec_create(struct obd_import *imp, struct ptlrpc_sec_policy *policy; struct ptlrpc_sec *sec; char str[32]; - ENTRY; if (svc_ctx) { LASSERT(imp->imp_dlm_fake == 1); @@ -1406,7 +1396,6 @@ int sptlrpc_import_sec_adapt(struct obd_import *imp, enum lustre_sec_part sp; char str[24]; int rc = 0; - ENTRY; might_sleep(); @@ -1669,7 +1658,6 @@ int sptlrpc_cli_alloc_repbuf(struct ptlrpc_request *req, int msgsize) { struct ptlrpc_cli_ctx *ctx = req->rq_cli_ctx; struct ptlrpc_sec_policy *policy; - ENTRY; LASSERT(ctx); LASSERT(ctx->cc_sec); @@ -1690,7 +1678,6 @@ void sptlrpc_cli_free_repbuf(struct ptlrpc_request *req) { struct ptlrpc_cli_ctx *ctx = req->rq_cli_ctx; struct ptlrpc_sec_policy *policy; - ENTRY; LASSERT(ctx); LASSERT(ctx->cc_sec); @@ -2033,7 +2020,6 @@ int sptlrpc_svc_unwrap_request(struct ptlrpc_request *req) struct ptlrpc_sec_policy *policy; struct lustre_msg *msg = req->rq_reqbuf; int rc; - ENTRY; LASSERT(msg); LASSERT(req->rq_reqmsg == NULL); @@ -2093,7 +2079,6 @@ int sptlrpc_svc_alloc_rs(struct ptlrpc_request *req, int msglen) struct ptlrpc_sec_policy *policy; struct ptlrpc_reply_state *rs; int rc; - ENTRY; LASSERT(req->rq_svc_ctx); LASSERT(req->rq_svc_ctx->sc_policy); @@ -2132,7 +2117,6 @@ int sptlrpc_svc_wrap_reply(struct ptlrpc_request *req) { struct ptlrpc_sec_policy *policy; int rc; - ENTRY; LASSERT(req->rq_svc_ctx); LASSERT(req->rq_svc_ctx->sc_policy); @@ -2153,7 +2137,6 @@ void sptlrpc_svc_free_rs(struct ptlrpc_reply_state *rs) { struct ptlrpc_sec_policy *policy; unsigned int prealloc; - ENTRY; LASSERT(rs->rs_svc_ctx); LASSERT(rs->rs_svc_ctx->sc_policy); diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_config.c b/drivers/staging/lustre/lustre/ptlrpc/sec_config.c index a45a3929b59f..f12bdeb8b1f8 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec_config.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec_config.c @@ -661,7 +661,6 @@ static int __sptlrpc_process_config(struct lustre_cfg *lcfg, char fsname[MTI_NAME_MAXLEN]; struct sptlrpc_rule rule; int rc; - ENTRY; target = lustre_cfg_string(lcfg, 1); if (target == NULL) { @@ -905,7 +904,6 @@ EXPORT_SYMBOL(sptlrpc_target_choose_flavor); void sptlrpc_conf_client_adapt(struct obd_device *obd) { struct obd_import *imp; - ENTRY; LASSERT(strcmp(obd->obd_type->typ_name, LUSTRE_MDC_NAME) == 0 || strcmp(obd->obd_type->typ_name, LUSTRE_OSC_NAME) ==0); @@ -1011,7 +1009,6 @@ int sptlrpc_target_local_copy_conf(struct obd_device *obd, struct lvfs_run_ctxt saved; struct dentry *dentry; int rc; - ENTRY; ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT); if (ctxt == NULL) @@ -1068,7 +1065,6 @@ static int local_read_handler(const struct lu_env *env, struct sptlrpc_conf *conf = (struct sptlrpc_conf *) data; struct lustre_cfg *lcfg = (struct lustre_cfg *)(rec + 1); int cfg_len, rc; - ENTRY; if (rec->lrh_type != OBD_CFG_REC) { CERROR("unhandled lrh_type: %#x\n", rec->lrh_type); @@ -1100,7 +1096,6 @@ int sptlrpc_target_local_read_conf(struct obd_device *obd, struct llog_ctxt *ctxt; struct lvfs_run_ctxt saved; int rc; - ENTRY; LASSERT(conf->sc_updated == 0 && conf->sc_local == 0); @@ -1160,7 +1155,6 @@ int sptlrpc_conf_target_get_rules(struct obd_device *obd, enum lustre_sec_part sp_dst; char fsname[MTI_NAME_MAXLEN]; int rc = 0; - ENTRY; if (strcmp(obd->obd_type->typ_name, LUSTRE_MDT_NAME) == 0) { sp_dst = LUSTRE_SP_MDT; diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c b/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c index f552d2f182b1..f5fbdbe0c85e 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c @@ -192,7 +192,6 @@ int plain_ctx_sign(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req) { struct lustre_msg *msg = req->rq_reqbuf; struct plain_header *phdr; - ENTRY; msg->lm_secflvr = req->rq_flvr.sf_rpc; @@ -219,7 +218,6 @@ int plain_ctx_verify(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req) struct plain_header *phdr; __u32 cksum; int swabbed; - ENTRY; if (msg->lm_bufcount != PLAIN_PACK_SEGMENTS) { CERROR("unexpected reply buf count %u\n", msg->lm_bufcount); @@ -417,7 +415,6 @@ static void plain_destroy_sec(struct ptlrpc_sec *sec) { struct plain_sec *plsec = sec2plsec(sec); - ENTRY; LASSERT(sec->ps_policy == &plain_policy); LASSERT(sec->ps_import); @@ -445,7 +442,6 @@ struct ptlrpc_sec *plain_create_sec(struct obd_import *imp, struct plain_sec *plsec; struct ptlrpc_sec *sec; struct ptlrpc_cli_ctx *ctx; - ENTRY; LASSERT(SPTLRPC_FLVR_POLICY(sf->sf_rpc) == SPTLRPC_POLICY_PLAIN); @@ -491,7 +487,6 @@ struct ptlrpc_cli_ctx *plain_lookup_ctx(struct ptlrpc_sec *sec, { struct plain_sec *plsec = sec2plsec(sec); struct ptlrpc_cli_ctx *ctx; - ENTRY; read_lock(&plsec->pls_lock); ctx = plsec->pls_ctx; @@ -526,7 +521,6 @@ int plain_flush_ctx_cache(struct ptlrpc_sec *sec, { struct plain_sec *plsec = sec2plsec(sec); struct ptlrpc_cli_ctx *ctx; - ENTRY; /* do nothing unless caller want to flush for 'all' */ if (uid != -1) @@ -549,7 +543,6 @@ int plain_alloc_reqbuf(struct ptlrpc_sec *sec, { __u32 buflens[PLAIN_PACK_SEGMENTS] = { 0, }; int alloc_len; - ENTRY; buflens[PLAIN_PACK_HDR_OFF] = sizeof(struct plain_header); buflens[PLAIN_PACK_MSG_OFF] = msgsize; @@ -592,7 +585,6 @@ static void plain_free_reqbuf(struct ptlrpc_sec *sec, struct ptlrpc_request *req) { - ENTRY; if (!req->rq_pool) { OBD_FREE_LARGE(req->rq_reqbuf, req->rq_reqbuf_len); req->rq_reqbuf = NULL; @@ -608,7 +600,6 @@ int plain_alloc_repbuf(struct ptlrpc_sec *sec, { __u32 buflens[PLAIN_PACK_SEGMENTS] = { 0, }; int alloc_len; - ENTRY; buflens[PLAIN_PACK_HDR_OFF] = sizeof(struct plain_header); buflens[PLAIN_PACK_MSG_OFF] = msgsize; @@ -637,7 +628,6 @@ static void plain_free_repbuf(struct ptlrpc_sec *sec, struct ptlrpc_request *req) { - ENTRY; OBD_FREE_LARGE(req->rq_repbuf, req->rq_repbuf_len); req->rq_repbuf = NULL; req->rq_repbuf_len = 0; @@ -652,7 +642,6 @@ int plain_enlarge_reqbuf(struct ptlrpc_sec *sec, struct lustre_msg *newbuf; int oldsize; int newmsg_size, newbuf_size; - ENTRY; LASSERT(req->rq_reqbuf); LASSERT(req->rq_reqbuf_len >= req->rq_reqlen); @@ -715,7 +704,6 @@ int plain_accept(struct ptlrpc_request *req) struct lustre_msg *msg = req->rq_reqbuf; struct plain_header *phdr; int swabbed; - ENTRY; LASSERT(SPTLRPC_FLVR_POLICY(req->rq_flvr.sf_rpc) == SPTLRPC_POLICY_PLAIN); @@ -787,7 +775,6 @@ int plain_alloc_rs(struct ptlrpc_request *req, int msgsize) struct ptlrpc_reply_state *rs; __u32 buflens[PLAIN_PACK_SEGMENTS] = { 0, }; int rs_size = sizeof(*rs); - ENTRY; LASSERT(msgsize % 8 == 0); @@ -827,8 +814,6 @@ int plain_alloc_rs(struct ptlrpc_request *req, int msgsize) static void plain_free_rs(struct ptlrpc_reply_state *rs) { - ENTRY; - LASSERT(atomic_read(&rs->rs_svc_ctx->sc_refcount) > 1); atomic_dec(&rs->rs_svc_ctx->sc_refcount); @@ -844,7 +829,6 @@ int plain_authorize(struct ptlrpc_request *req) struct lustre_msg_v2 *msg = rs->rs_repbuf; struct plain_header *phdr; int len; - ENTRY; LASSERT(rs); LASSERT(msg); diff --git a/drivers/staging/lustre/lustre/ptlrpc/service.c b/drivers/staging/lustre/lustre/ptlrpc/service.c index 87bd63858b1c..68afbc5db223 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/service.c +++ b/drivers/staging/lustre/lustre/ptlrpc/service.c @@ -369,7 +369,6 @@ static void rs_batch_fini(struct rs_batch *b) void ptlrpc_dispatch_difficult_reply(struct ptlrpc_reply_state *rs) { struct ptlrpc_hr_thread *hrt; - ENTRY; LASSERT(list_empty(&rs->rs_list)); @@ -386,8 +385,6 @@ void ptlrpc_dispatch_difficult_reply(struct ptlrpc_reply_state *rs) void ptlrpc_schedule_difficult_reply(struct ptlrpc_reply_state *rs) { - ENTRY; - LASSERT(spin_is_locked(&rs->rs_svcpt->scp_rep_lock)); LASSERT(spin_is_locked(&rs->rs_lock)); LASSERT (rs->rs_difficult); @@ -409,7 +406,6 @@ void ptlrpc_commit_replies(struct obd_export *exp) { struct ptlrpc_reply_state *rs, *nxt; DECLARE_RS_BATCH(batch); - ENTRY; rs_batch_init(&batch); /* Find any replies that have been committed and get their service @@ -702,7 +698,6 @@ ptlrpc_register_service(struct ptlrpc_service_conf *conf, int cpt; int rc; int i; - ENTRY; LASSERT(conf->psc_buf.bc_nbufs > 0); LASSERT(conf->psc_buf.bc_buf_size >= @@ -1037,8 +1032,6 @@ static void ptlrpc_update_export_timer(struct obd_export *exp, long extra_delay) struct obd_export *oldest_exp; time_t oldest_time, new_time; - ENTRY; - LASSERT(exp); /* Compensate for slow machines, etc, by faking our request time @@ -1261,7 +1254,6 @@ static int ptlrpc_at_send_early_reply(struct ptlrpc_request *req) cfs_duration_t olddl = req->rq_deadline - cfs_time_current_sec(); time_t newdl; int rc; - ENTRY; /* deadline is when the client expects us to reply, margin is the difference between clients' and servers' expectations */ @@ -1401,7 +1393,6 @@ static int ptlrpc_at_check_timed(struct ptlrpc_service_part *svcpt) time_t now = cfs_time_current_sec(); cfs_duration_t delay; int first, counter = 0; - ENTRY; spin_lock(&svcpt->scp_at_lock); if (svcpt->scp_at_check == 0) { @@ -1503,7 +1494,6 @@ static int ptlrpc_server_hpreq_init(struct ptlrpc_service_part *svcpt, struct ptlrpc_request *req) { int rc = 0; - ENTRY; if (svcpt->scp_service->srv_ops.so_hpreq_handler) { rc = svcpt->scp_service->srv_ops.so_hpreq_handler(req); @@ -1547,7 +1537,6 @@ static int ptlrpc_server_hpreq_init(struct ptlrpc_service_part *svcpt, /** Remove the request from the export list. */ static void ptlrpc_server_hpreq_fini(struct ptlrpc_request *req) { - ENTRY; if (req->rq_export && req->rq_ops) { /* refresh lock timeout again so that client has more * room to send lock cancel RPC. */ @@ -1589,7 +1578,6 @@ static int ptlrpc_server_request_add(struct ptlrpc_service_part *svcpt, struct ptlrpc_request *req) { int rc; - ENTRY; rc = ptlrpc_server_hpreq_init(svcpt, req); if (rc < 0) @@ -1703,7 +1691,6 @@ static struct ptlrpc_request * ptlrpc_server_request_get(struct ptlrpc_service_part *svcpt, bool force) { struct ptlrpc_request *req = NULL; - ENTRY; spin_lock(&svcpt->scp_req_lock); @@ -1753,7 +1740,6 @@ ptlrpc_server_handle_req_in(struct ptlrpc_service_part *svcpt, struct ptlrpc_request *req; __u32 deadline; int rc; - ENTRY; spin_lock(&svcpt->scp_lock); if (list_empty(&svcpt->scp_req_incoming)) { @@ -1900,7 +1886,6 @@ ptlrpc_server_handle_request(struct ptlrpc_service_part *svcpt, long timediff; int rc; int fail_opc = 0; - ENTRY; request = ptlrpc_server_request_get(svcpt, false); if (request == NULL) @@ -2057,7 +2042,6 @@ ptlrpc_handle_rs(struct ptlrpc_reply_state *rs) struct obd_export *exp; int nlocks; int been_handled; - ENTRY; exp = rs->rs_export; @@ -2294,7 +2278,6 @@ static int ptlrpc_main(void *arg) #endif struct lu_env *env; int counter = 0, rc = 0; - ENTRY; thread->t_pid = current_pid(); unshare_fs_struct(); @@ -2560,7 +2543,6 @@ static int ptlrpc_start_hr_threads(void) struct ptlrpc_hr_partition *hrp; int i; int j; - ENTRY; cfs_percpt_for_each(hrp, i, ptlrpc_hr.hr_partitions) { int rc = 0; @@ -2594,8 +2576,6 @@ static void ptlrpc_svcpt_stop_threads(struct ptlrpc_service_part *svcpt) struct ptlrpc_thread *thread; LIST_HEAD (zombie); - ENTRY; - CDEBUG(D_INFO, "Stopping threads for service %s\n", svcpt->scp_service->srv_name); @@ -2645,7 +2625,6 @@ void ptlrpc_stop_all_threads(struct ptlrpc_service *svc) { struct ptlrpc_service_part *svcpt; int i; - ENTRY; ptlrpc_service_for_each_part(svcpt, i, svc) { if (svcpt->scp_service != NULL) @@ -2661,7 +2640,6 @@ int ptlrpc_start_threads(struct ptlrpc_service *svc) int rc = 0; int i; int j; - ENTRY; /* We require 2 threads min, see note in ptlrpc_server_handle_request */ LASSERT(svc->srv_nthrs_cpt_init >= PTLRPC_NTHRS_INIT); @@ -2694,7 +2672,6 @@ int ptlrpc_start_thread(struct ptlrpc_service_part *svcpt, int wait) struct ptlrpc_thread *thread; struct ptlrpc_service *svc; int rc; - ENTRY; LASSERT(svcpt != NULL); @@ -2801,7 +2778,6 @@ int ptlrpc_hr_init(void) int i; int j; int weight; - ENTRY; memset(&ptlrpc_hr, 0, sizeof(ptlrpc_hr)); ptlrpc_hr.hr_cpt_table = cfs_cpt_table; @@ -3068,8 +3044,6 @@ ptlrpc_service_free(struct ptlrpc_service *svc) int ptlrpc_unregister_service(struct ptlrpc_service *service) { - ENTRY; - CDEBUG(D_NET, "%s: tearing down\n", service->srv_name); service->srv_is_stopping = 1; From e05e02e42092dc5e432a9c84d46bd3109808172d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 2 Aug 2013 18:20:34 +0800 Subject: [PATCH 1327/3400] staging: lustre: remove RETURN_EXIT macro We have a kernel-wide function tracing system, so use that instead of rolling a custom one just for one filesystem. Cc: Peng Tao Cc: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../lustre/include/linux/libcfs/libcfs_debug.h | 6 ------ drivers/staging/lustre/lustre/llite/dcache.c | 2 +- drivers/staging/lustre/lustre/llite/statahead.c | 14 +++++++------- drivers/staging/lustre/lustre/lov/lov_io.c | 1 - drivers/staging/lustre/lustre/mgc/mgc_request.c | 2 +- drivers/staging/lustre/lustre/osc/osc_lock.c | 2 +- drivers/staging/lustre/lustre/ptlrpc/nrs.c | 5 ----- drivers/staging/lustre/lustre/ptlrpc/service.c | 4 ++-- 8 files changed, 12 insertions(+), 24 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h index feb7a6bc6efe..17189d9e3cba 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h @@ -314,12 +314,6 @@ do { \ CDEBUG(D_TRACE, "Process leaving\n"); \ } while(0) -#define RETURN_EXIT \ -do { \ - EXIT; \ - return; \ -} while (0) - extern int libcfs_debug_msg(struct libcfs_debug_msg_data *msgdata, const char *format1, ...) __attribute__ ((format (printf, 2, 3))); diff --git a/drivers/staging/lustre/lustre/llite/dcache.c b/drivers/staging/lustre/lustre/llite/dcache.c index 628fae410bdb..484af85f97d6 100644 --- a/drivers/staging/lustre/lustre/llite/dcache.c +++ b/drivers/staging/lustre/lustre/llite/dcache.c @@ -63,7 +63,7 @@ static void ll_release(struct dentry *de) LASSERT(de != NULL); lld = ll_d2d(de); if (lld == NULL) /* NFS copies the de->d_op methods (bug 4655) */ - RETURN_EXIT; + return; if (lld->lld_it) { ll_intent_release(lld->lld_it); diff --git a/drivers/staging/lustre/lustre/llite/statahead.c b/drivers/staging/lustre/lustre/llite/statahead.c index be1c3a888702..772e4ce31e6b 100644 --- a/drivers/staging/lustre/lustre/llite/statahead.c +++ b/drivers/staging/lustre/lustre/llite/statahead.c @@ -516,7 +516,7 @@ static void ll_sai_put(struct ll_statahead_info *sai) /* It is race case, the interpret callback just hold * a reference count */ spin_unlock(&lli->lli_sa_lock); - RETURN_EXIT; + return; } LASSERT(lli->lli_opendir_key == NULL); @@ -564,7 +564,7 @@ static void ll_agl_trigger(struct inode *inode, struct ll_statahead_info *sai) if (is_omitted_entry(sai, index + 1)) { lli->lli_agl_index = 0; iput(inode); - RETURN_EXIT; + return; } /* Someone is in glimpse (sync or async), do nothing. */ @@ -572,7 +572,7 @@ static void ll_agl_trigger(struct inode *inode, struct ll_statahead_info *sai) if (rc == 0) { lli->lli_agl_index = 0; iput(inode); - RETURN_EXIT; + return; } /* @@ -593,7 +593,7 @@ static void ll_agl_trigger(struct inode *inode, struct ll_statahead_info *sai) up_write(&lli->lli_glimpse_sem); lli->lli_agl_index = 0; iput(inode); - RETURN_EXIT; + return; } CDEBUG(D_READA, "Handling (init) async glimpse: inode = " @@ -628,7 +628,7 @@ static void ll_post_statahead(struct ll_statahead_info *sai) spin_lock(&lli->lli_sa_lock); if (unlikely(sa_received_empty(sai))) { spin_unlock(&lli->lli_sa_lock); - RETURN_EXIT; + return; } entry = sa_first_received_entry(sai); atomic_inc(&entry->se_refcount); @@ -930,7 +930,7 @@ static void ll_statahead_one(struct dentry *parent, const char* entry_name, entry = ll_sa_entry_alloc(sai, sai->sai_index, entry_name, entry_name_len); if (IS_ERR(entry)) - RETURN_EXIT; + return; dentry = d_lookup(parent, &entry->se_qstr); if (!dentry) { @@ -1038,7 +1038,7 @@ static void ll_start_agl(struct dentry *parent, struct ll_statahead_info *sai) if (IS_ERR(task)) { CERROR("can't start ll_agl thread, rc: %ld\n", PTR_ERR(task)); thread_set_flags(thread, SVC_STOPPED); - RETURN_EXIT; + return; } l_wait_event(thread->t_ctl_waitq, diff --git a/drivers/staging/lustre/lustre/lov/lov_io.c b/drivers/staging/lustre/lustre/lov/lov_io.c index 0ef2293a65a0..10e36c908443 100644 --- a/drivers/staging/lustre/lustre/lov/lov_io.c +++ b/drivers/staging/lustre/lustre/lov/lov_io.c @@ -742,7 +742,6 @@ static void lov_io_fsync_end(const struct lu_env *env, if (subio->ci_result == 0) *written += subio->u.ci_fsync.fi_nr_written; } - RETURN_EXIT; } static const struct cl_io_operations lov_io_ops = { diff --git a/drivers/staging/lustre/lustre/mgc/mgc_request.c b/drivers/staging/lustre/lustre/mgc/mgc_request.c index 069681507129..6512b7f4d3dc 100644 --- a/drivers/staging/lustre/lustre/mgc/mgc_request.c +++ b/drivers/staging/lustre/lustre/mgc/mgc_request.c @@ -561,7 +561,7 @@ static void mgc_requeue_add(struct config_llog_data *cld) mutex_lock(&cld->cld_lock); if (cld->cld_stopping || cld->cld_lostlock) { mutex_unlock(&cld->cld_lock); - RETURN_EXIT; + return; } /* this refcount will be released in mgc_requeue_thread. */ config_log_get(cld); diff --git a/drivers/staging/lustre/lustre/osc/osc_lock.c b/drivers/staging/lustre/lustre/osc/osc_lock.c index a13215dd4a9e..ef6f1bb9150b 100644 --- a/drivers/staging/lustre/lustre/osc/osc_lock.c +++ b/drivers/staging/lustre/lustre/osc/osc_lock.c @@ -344,7 +344,7 @@ static void osc_lock_lvb_update(const struct lu_env *env, struct osc_lock *olck, unsigned valid; if (!(olck->ols_flags & LDLM_FL_LVB_READY)) - RETURN_EXIT; + return; lvb = &olck->ols_lvb; obj = olck->ols_cl.cls_obj; diff --git a/drivers/staging/lustre/lustre/ptlrpc/nrs.c b/drivers/staging/lustre/lustre/ptlrpc/nrs.c index 352c0f1af471..afc52326b1cb 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/nrs.c +++ b/drivers/staging/lustre/lustre/ptlrpc/nrs.c @@ -158,11 +158,6 @@ static void nrs_policy_stop_primary(struct ptlrpc_nrs *nrs) struct ptlrpc_nrs_policy *tmp = nrs->nrs_policy_primary; if (tmp == NULL) { - /** - * XXX: This should really be RETURN_EXIT, but the latter does - * not currently print anything out, and possibly should be - * fixed to do so. - */ EXIT; return; } diff --git a/drivers/staging/lustre/lustre/ptlrpc/service.c b/drivers/staging/lustre/lustre/ptlrpc/service.c index 68afbc5db223..1a73f8a57b41 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/service.c +++ b/drivers/staging/lustre/lustre/ptlrpc/service.c @@ -1043,7 +1043,7 @@ static void ptlrpc_update_export_timer(struct obd_export *exp, long extra_delay) /* Do not pay attention on 1sec or smaller renewals. */ new_time = cfs_time_current_sec() + extra_delay; if (exp->exp_last_request_time + 1 /*second */ >= new_time) - RETURN_EXIT; + return; exp->exp_last_request_time = new_time; CDEBUG(D_HA, "updating export %s at "CFS_TIME_T" exp %p\n", @@ -1058,7 +1058,7 @@ static void ptlrpc_update_export_timer(struct obd_export *exp, long extra_delay) if (list_empty(&exp->exp_obd_chain_timed)) { /* this one is not timed */ spin_unlock(&exp->exp_obd->obd_dev_lock); - RETURN_EXIT; + return; } list_move_tail(&exp->exp_obd_chain_timed, From 4a678f037475edd362a18fc3c4616d6222be3042 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Fri, 2 Aug 2013 10:19:15 +0200 Subject: [PATCH 1328/3400] regulators: max8660: use i2c_id->driver_data rather than ->name Introduce an enum and denote the device type via struct i2c_id's driver_data field rather than comparing strings. Signed-off-by: Daniel Mack Signed-off-by: Mark Brown --- drivers/regulator/max8660.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c index bfd41084c7df..5a734fc9618c 100644 --- a/drivers/regulator/max8660.c +++ b/drivers/regulator/max8660.c @@ -305,6 +305,11 @@ static const struct regulator_desc max8660_reg[] = { }, }; +enum { + MAX8660 = 0, + MAX8661 = 1, +}; + static int max8660_probe(struct i2c_client *client, const struct i2c_device_id *i2c_id) { @@ -313,6 +318,7 @@ static int max8660_probe(struct i2c_client *client, struct regulator_config config = { }; struct max8660 *max8660; int boot_on, i, id, ret = -EINVAL; + unsigned int type; if (pdata->num_subdevs > MAX8660_V_END) { dev_err(&client->dev, "Too many regulators found!\n"); @@ -327,6 +333,7 @@ static int max8660_probe(struct i2c_client *client, max8660->client = client; rdev = max8660->rdev; + type = i2c_id->driver_data; if (pdata->en34_is_high) { /* Simulate always on */ @@ -376,7 +383,7 @@ static int max8660_probe(struct i2c_client *client, break; case MAX8660_V7: - if (!strcmp(i2c_id->name, "max8661")) { + if (type == MAX8661) { dev_err(&client->dev, "Regulator not on this chip!\n"); goto err_out; } @@ -431,8 +438,8 @@ static int max8660_remove(struct i2c_client *client) } static const struct i2c_device_id max8660_id[] = { - { "max8660", 0 }, - { "max8661", 0 }, + { .name = "max8660", .driver_data = MAX8660 }, + { .name = "max8661", .driver_data = MAX8661 }, { } }; MODULE_DEVICE_TABLE(i2c, max8660_id); From de492e8de8d05f29cc496871d42763d0a8a74610 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Fri, 2 Aug 2013 10:19:16 +0200 Subject: [PATCH 1329/3400] regulators: max8660: add a shorthand to &client->dev No functional change, just makes the code shorter. [Resolved conflict with platdata patch -- broonie] Signed-off-by: Daniel Mack Signed-off-by: Mark Brown --- drivers/regulator/max8660.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c index 5a734fc9618c..74c11aa00c8a 100644 --- a/drivers/regulator/max8660.c +++ b/drivers/regulator/max8660.c @@ -314,18 +314,19 @@ static int max8660_probe(struct i2c_client *client, const struct i2c_device_id *i2c_id) { struct regulator_dev **rdev; - struct max8660_platform_data *pdata = dev_get_platdata(&client->dev); + struct device *dev = &client->dev; + struct max8660_platform_data *pdata = dev_get_platdata(dev); struct regulator_config config = { }; struct max8660 *max8660; int boot_on, i, id, ret = -EINVAL; unsigned int type; if (pdata->num_subdevs > MAX8660_V_END) { - dev_err(&client->dev, "Too many regulators found!\n"); + dev_err(dev, "Too many regulators found!\n"); return -EINVAL; } - max8660 = devm_kzalloc(&client->dev, sizeof(struct max8660) + + max8660 = devm_kzalloc(dev, sizeof(struct max8660) + sizeof(struct regulator_dev *) * MAX8660_V_END, GFP_KERNEL); if (!max8660) @@ -384,7 +385,7 @@ static int max8660_probe(struct i2c_client *client, case MAX8660_V7: if (type == MAX8661) { - dev_err(&client->dev, "Regulator not on this chip!\n"); + dev_err(dev, "Regulator not on this chip!\n"); goto err_out; } @@ -393,7 +394,7 @@ static int max8660_probe(struct i2c_client *client, break; default: - dev_err(&client->dev, "invalid regulator %s\n", + dev_err(dev, "invalid regulator %s\n", pdata->subdevs[i].name); goto err_out; } @@ -404,14 +405,14 @@ static int max8660_probe(struct i2c_client *client, id = pdata->subdevs[i].id; - config.dev = &client->dev; + config.dev = dev; config.init_data = pdata->subdevs[i].platform_data; config.driver_data = max8660; rdev[i] = regulator_register(&max8660_reg[id], &config); if (IS_ERR(rdev[i])) { ret = PTR_ERR(rdev[i]); - dev_err(&client->dev, "failed to register %s\n", + dev_err(dev, "failed to register %s\n", max8660_reg[id].name); goto err_unregister; } From 6b8430c3f3090b8b805eb1fbe58390229d2dd067 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 1 Aug 2013 19:59:56 +0800 Subject: [PATCH 1330/3400] regulator: pfuze100: Fix off-by-one for max_register setting max_register should be register count - 1. Signed-off-by: Axel Lin Reviewed-by: Robin Gong Signed-off-by: Mark Brown --- drivers/regulator/pfuze100-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c index bda55617092b..ba67b2c4e2e7 100644 --- a/drivers/regulator/pfuze100-regulator.c +++ b/drivers/regulator/pfuze100-regulator.c @@ -332,7 +332,7 @@ static int pfuze_identify(struct pfuze_chip *pfuze_chip) static const struct regmap_config pfuze_regmap_config = { .reg_bits = 8, .val_bits = 8, - .max_register = PFUZE_NUMREGS, + .max_register = PFUZE_NUMREGS - 1, .cache_type = REGCACHE_RBTREE, }; From b6aa23ccaea1548cfb404b41129717f13443bccf Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Thu, 1 Aug 2013 16:08:57 -0600 Subject: [PATCH 1331/3400] spi: fix SPI_BIT_MASK so it always fits into 32-bits On a 64-bit platform, ~0UL fills 64-bits, which causes SPI_BIT_MASK(32) not to fit into 32 bits. This causes a warning when the result is assigned to a 32-bit variable. Use ~0U instead to prevent this. This fixes: drivers/spi/spi-gpio.c: In function 'spi_gpio_probe': drivers/spi/spi-gpio.c:446:2: warning: large integer implicitly truncated to unsigned type [-Woverflow] Reported-by: kbuild test robot Signed-off-by: Stephen Warren Signed-off-by: Mark Brown --- include/linux/spi/spi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 28e440be1c07..c920c2f4dad5 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -309,7 +309,7 @@ struct spi_master { /* bitmask of supported bits_per_word for transfers */ u32 bits_per_word_mask; #define SPI_BPW_MASK(bits) BIT((bits) - 1) -#define SPI_BIT_MASK(bits) (((bits) == 32) ? ~0UL : (BIT(bits) - 1)) +#define SPI_BIT_MASK(bits) (((bits) == 32) ? ~0U : (BIT(bits) - 1)) #define SPI_BPW_RANGE_MASK(min, max) (SPI_BIT_MASK(max) - SPI_BIT_MASK(min - 1)) /* other constraints relevant to this driver */ From 30ce1987160e64f58d92359ee11999e1218a45b9 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Fri, 2 Aug 2013 10:37:27 +0200 Subject: [PATCH 1332/3400] usb: gadget: at91_udc: add missing clk_put on fclk and iclk This patch adds missing clk_put on fclk and iclk in case the probe function fails after these clocks have been retrieved. Signed-off-by: Boris BREZILLON Signed-off-by: Felipe Balbi --- drivers/usb/gadget/at91_udc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index d237429dd93a..94d1d3cacce8 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -1851,6 +1851,10 @@ fail3: fail2: free_irq(udc->udp_irq, udc); fail1: + if (!IS_ERR(udc->fclk)) + clk_put(udc->fclk); + if (!IS_ERR(udc->iclk)) + clk_put(udc->iclk); iounmap(udc->udp_baseaddr); fail0a: if (cpu_is_at91rm9200()) From c0aefc75ce2512bc308a89ca3cb7bece63c1128f Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Fri, 2 Aug 2013 10:37:34 +0200 Subject: [PATCH 1333/3400] usb: gadget: at91_udc: add usb_clk for transition to common clk framework The AT91 PMC (Power Management Controller) provides an USB clock used by USB Full Speed host (ohci) and USB Full Speed device (udc). The usb drivers (ohci and udc) must configure this clock to 48Mhz. This configuration was formely done in mach-at91/clock.c, but this implementation will be removed when moving to common clk framework. This patch adds support for usb clock retrieval and configuration, and is backward compatible with the current at91 clk implementation (if usb clk is not found, it does not configure/enable it). Signed-off-by: Boris BREZILLON Signed-off-by: Felipe Balbi --- drivers/usb/gadget/at91_udc.c | 17 +++++++++++++++-- drivers/usb/gadget/at91_udc.h | 2 +- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index 94d1d3cacce8..4cc4fd6d1473 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -870,6 +870,11 @@ static void clk_on(struct at91_udc *udc) if (udc->clocked) return; udc->clocked = 1; + + if (IS_ENABLED(CONFIG_COMMON_CLK)) { + clk_set_rate(udc->uclk, 48000000); + clk_prepare_enable(udc->uclk); + } clk_prepare_enable(udc->iclk); clk_prepare_enable(udc->fclk); } @@ -882,6 +887,8 @@ static void clk_off(struct at91_udc *udc) udc->gadget.speed = USB_SPEED_UNKNOWN; clk_disable_unprepare(udc->fclk); clk_disable_unprepare(udc->iclk); + if (IS_ENABLED(CONFIG_COMMON_CLK)) + clk_disable_unprepare(udc->uclk); } /* @@ -1774,10 +1781,12 @@ static int at91udc_probe(struct platform_device *pdev) /* get interface and function clocks */ udc->iclk = clk_get(dev, "udc_clk"); udc->fclk = clk_get(dev, "udpck"); - if (IS_ERR(udc->iclk) || IS_ERR(udc->fclk)) { + if (IS_ENABLED(CONFIG_COMMON_CLK)) + udc->uclk = clk_get(dev, "usb_clk"); + if (IS_ERR(udc->iclk) || IS_ERR(udc->fclk) || + (IS_ENABLED(CONFIG_COMMON_CLK) && IS_ERR(udc->uclk))) { DBG("clocks missing\n"); retval = -ENODEV; - /* NOTE: we "know" here that refcounts on these are NOPs */ goto fail1; } @@ -1851,6 +1860,8 @@ fail3: fail2: free_irq(udc->udp_irq, udc); fail1: + if (IS_ENABLED(CONFIG_COMMON_CLK) && !IS_ERR(udc->uclk)) + clk_put(udc->uclk); if (!IS_ERR(udc->fclk)) clk_put(udc->fclk); if (!IS_ERR(udc->iclk)) @@ -1898,6 +1909,8 @@ static int __exit at91udc_remove(struct platform_device *pdev) clk_put(udc->iclk); clk_put(udc->fclk); + if (IS_ENABLED(CONFIG_COMMON_CLK)) + clk_put(udc->uclk); return 0; } diff --git a/drivers/usb/gadget/at91_udc.h b/drivers/usb/gadget/at91_udc.h index e647d1c2ada4..017524663381 100644 --- a/drivers/usb/gadget/at91_udc.h +++ b/drivers/usb/gadget/at91_udc.h @@ -126,7 +126,7 @@ struct at91_udc { unsigned active_suspend:1; u8 addr; struct at91_udc_data board; - struct clk *iclk, *fclk; + struct clk *iclk, *fclk, *uclk; struct platform_device *pdev; struct proc_dir_entry *pde; void __iomem *udp_baseaddr; From 70a0f6032985f156bd7e957cfec99c3dd3d592a2 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 23 Jul 2013 10:57:47 +0300 Subject: [PATCH 1334/3400] ARM: OMAP: dss-common: fix Panda's DVI DDC channel Panda's DVI connector's DDC pins are connected to OMAP's third i2c bus. With non-DT, the bus number was 3, and that is what is used in the dss-common.c which contains the platform data for Panda's DVI. However, with DT, the bus number is 2. As we now only have DT boot for Panda, we have to change the bus number to make DVI EDID read operational. Signed-off-by: Tomi Valkeinen Acked-by: Tony Lindgren --- arch/arm/mach-omap2/dss-common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/dss-common.c b/arch/arm/mach-omap2/dss-common.c index 393aeefaebb0..043e5705f2a6 100644 --- a/arch/arm/mach-omap2/dss-common.c +++ b/arch/arm/mach-omap2/dss-common.c @@ -42,7 +42,7 @@ /* Using generic display panel */ static struct tfp410_platform_data omap4_dvi_panel = { - .i2c_bus_num = 3, + .i2c_bus_num = 2, .power_down_gpio = PANDA_DVI_TFP410_POWER_DOWN_GPIO, }; From e2b0509908aa5e874a1837a733422b6e8b8502b8 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 2 Aug 2013 15:03:42 +0200 Subject: [PATCH 1335/3400] spi: rspi: provide port addresses to dmaengine driver via slave configuration Don't rely on shdma dhaengine driver getting DMA slave addresses from its slave configuration. Instead provide those addresses, using a dmaengine_slave_config() call. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mark Brown --- drivers/spi/spi-rspi.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index b44a6ac3cec9..5f122d9d2063 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -664,12 +664,13 @@ static irqreturn_t rspi_irq(int irq, void *_sr) static int rspi_request_dma(struct rspi_data *rspi, struct platform_device *pdev) { + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); struct rspi_plat_data *rspi_pd = pdev->dev.platform_data; dma_cap_mask_t mask; struct dma_slave_config cfg; int ret; - if (!rspi_pd) + if (!res || !rspi_pd) return 0; /* The driver assumes no error. */ rspi->dma_width_16bit = rspi_pd->dma_width_16bit; @@ -683,6 +684,8 @@ static int rspi_request_dma(struct rspi_data *rspi, if (rspi->chan_rx) { cfg.slave_id = rspi_pd->dma_rx_id; cfg.direction = DMA_DEV_TO_MEM; + cfg.dst_addr = 0; + cfg.src_addr = res->start + RSPI_SPDR; ret = dmaengine_slave_config(rspi->chan_rx, &cfg); if (!ret) dev_info(&pdev->dev, "Use DMA when rx.\n"); @@ -698,6 +701,8 @@ static int rspi_request_dma(struct rspi_data *rspi, if (rspi->chan_tx) { cfg.slave_id = rspi_pd->dma_tx_id; cfg.direction = DMA_MEM_TO_DEV; + cfg.dst_addr = res->start + RSPI_SPDR; + cfg.src_addr = 0; ret = dmaengine_slave_config(rspi->chan_tx, &cfg); if (!ret) dev_info(&pdev->dev, "Use DMA when tx\n"); From abe4c51afda02423c81da6f1eaaa50b733f1ecc2 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Fri, 2 Aug 2013 12:59:44 +0200 Subject: [PATCH 1336/3400] regulators: max8660: add DT bindings This patch adds devicetree bindings for max8660, along with some documentation. Signed-off-by: Daniel Mack Signed-off-by: Mark Brown --- .../devicetree/bindings/regulator/max8660.txt | 47 +++++++++++ drivers/regulator/max8660.c | 82 ++++++++++++++++++- include/linux/regulator/max8660.h | 2 +- 3 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 Documentation/devicetree/bindings/regulator/max8660.txt diff --git a/Documentation/devicetree/bindings/regulator/max8660.txt b/Documentation/devicetree/bindings/regulator/max8660.txt new file mode 100644 index 000000000000..8ba994d8a142 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/max8660.txt @@ -0,0 +1,47 @@ +Maxim MAX8660 voltage regulator + +Required properties: +- compatible: must be one of "maxim,max8660", "maxim,max8661" +- reg: I2C slave address, usually 0x34 +- any required generic properties defined in regulator.txt + +Example: + + i2c_master { + max8660@34 { + compatible = "maxim,max8660"; + reg = <0x34>; + + regulators { + regulator@0 { + regulator-compatible= "V3(DCDC)"; + regulator-min-microvolt = <725000>; + regulator-max-microvolt = <1800000>; + }; + + regulator@1 { + regulator-compatible= "V4(DCDC)"; + regulator-min-microvolt = <725000>; + regulator-max-microvolt = <1800000>; + }; + + regulator@2 { + regulator-compatible= "V5(LDO)"; + regulator-min-microvolt = <1700000>; + regulator-max-microvolt = <2000000>; + }; + + regulator@3 { + regulator-compatible= "V6(LDO)"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + }; + + regulator@4 { + regulator-compatible= "V7(LDO)"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + }; + }; + }; + }; diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c index 74c11aa00c8a..a4f2f1a38342 100644 --- a/drivers/regulator/max8660.c +++ b/drivers/regulator/max8660.c @@ -44,6 +44,9 @@ #include #include #include +#include +#include +#include #define MAX8660_DCDC_MIN_UV 725000 #define MAX8660_DCDC_MAX_UV 1800000 @@ -310,6 +313,63 @@ enum { MAX8661 = 1, }; +#ifdef CONFIG_OF +static const struct of_device_id max8660_dt_ids[] = { + { .compatible = "maxim,max8660", .data = (void *) MAX8660 }, + { .compatible = "maxim,max8661", .data = (void *) MAX8661 }, + { } +}; +MODULE_DEVICE_TABLE(of, max8660_dt_ids); + +static int max8660_pdata_from_dt(struct device *dev, + struct device_node **of_node, + struct max8660_platform_data *pdata) +{ + int matched, i; + struct device_node *np; + struct max8660_subdev_data *sub; + struct of_regulator_match rmatch[ARRAY_SIZE(max8660_reg)]; + + np = of_find_node_by_name(dev->of_node, "regulators"); + if (!np) { + dev_err(dev, "missing 'regulators' subnode in DT\n"); + return -EINVAL; + } + + for (i = 0; i < ARRAY_SIZE(rmatch); i++) + rmatch[i].name = max8660_reg[i].name; + + matched = of_regulator_match(dev, np, rmatch, ARRAY_SIZE(rmatch)); + if (matched <= 0) + return matched; + + pdata->subdevs = devm_kzalloc(dev, sizeof(struct max8660_subdev_data) * + matched, GFP_KERNEL); + if (!pdata->subdevs) + return -ENOMEM; + + pdata->num_subdevs = matched; + sub = pdata->subdevs; + + for (i = 0; i < matched; i++) { + sub->id = i; + sub->name = rmatch[i].name; + sub->platform_data = rmatch[i].init_data; + of_node[i] = rmatch[i].of_node; + sub++; + } + + return 0; +} +#else +static inline int max8660_pdata_from_dt(struct device *dev, + struct device_node **of_node, + struct max8660_platform_data **pdata) +{ + return 0; +} +#endif + static int max8660_probe(struct i2c_client *client, const struct i2c_device_id *i2c_id) { @@ -319,8 +379,28 @@ static int max8660_probe(struct i2c_client *client, struct regulator_config config = { }; struct max8660 *max8660; int boot_on, i, id, ret = -EINVAL; + struct device_node *of_node[MAX8660_V_END]; unsigned int type; + if (dev->of_node && !pdata) { + const struct of_device_id *id; + struct max8660_platform_data pdata_of; + + id = of_match_device(of_match_ptr(max8660_dt_ids), dev); + if (!id) + return -ENODEV; + + ret = max8660_pdata_from_dt(dev, of_node, &pdata_of); + if (ret < 0) + return ret; + + pdata = &pdata_of; + type = (unsigned int) id->data; + } else { + type = i2c_id->driver_data; + memset(of_node, 0, sizeof(of_node)); + } + if (pdata->num_subdevs > MAX8660_V_END) { dev_err(dev, "Too many regulators found!\n"); return -EINVAL; @@ -334,7 +414,6 @@ static int max8660_probe(struct i2c_client *client, max8660->client = client; rdev = max8660->rdev; - type = i2c_id->driver_data; if (pdata->en34_is_high) { /* Simulate always on */ @@ -407,6 +486,7 @@ static int max8660_probe(struct i2c_client *client, config.dev = dev; config.init_data = pdata->subdevs[i].platform_data; + config.of_node = of_node[i]; config.driver_data = max8660; rdev[i] = regulator_register(&max8660_reg[id], &config); diff --git a/include/linux/regulator/max8660.h b/include/linux/regulator/max8660.h index 9936763621c7..f8a6a4844864 100644 --- a/include/linux/regulator/max8660.h +++ b/include/linux/regulator/max8660.h @@ -39,7 +39,7 @@ enum { */ struct max8660_subdev_data { int id; - char *name; + const char *name; struct regulator_init_data *platform_data; }; From eca396d7a5bdcc1fd67b1b12f737c213ac78a6f4 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Thu, 1 Aug 2013 12:07:13 +0200 Subject: [PATCH 1337/3400] iwl4965: set power mode early If device was put into a sleep and system was restarted or module reloaded, we have to wake device up before sending other commands. Otherwise it will fail to start with Microcode error. Cc: stable@vger.kernel.org Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/4965-mac.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index b9b2bb51e605..f0b7794fca3e 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -5334,6 +5334,9 @@ il4965_alive_start(struct il_priv *il) il->active_rate = RATES_MASK; + il_power_update_mode(il, true); + D_INFO("Updated power mode\n"); + if (il_is_associated(il)) { struct il_rxon_cmd *active_rxon = (struct il_rxon_cmd *)&il->active; @@ -5364,9 +5367,6 @@ il4965_alive_start(struct il_priv *il) D_INFO("ALIVE processing complete.\n"); wake_up(&il->wait_command_queue); - il_power_update_mode(il, true); - D_INFO("Updated power mode\n"); - return; restart: From 788f7a56fce1bcb2067b62b851a086fca48a0056 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Thu, 1 Aug 2013 12:07:55 +0200 Subject: [PATCH 1338/3400] iwl4965: reset firmware after rfkill off Using rfkill switch can make firmware unstable, what cause various Microcode errors and kernel warnings. Reseting firmware just after rfkill off (radio on) helped with that. Resolve: https://bugzilla.redhat.com/show_bug.cgi?id=977053 Reported-and-tested-by: Justin Pearce Cc: stable@vger.kernel.org Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/iwlegacy/4965-mac.c | 10 +++++----- drivers/net/wireless/iwlegacy/common.c | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index f0b7794fca3e..f2ed62e37340 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -4460,12 +4460,12 @@ il4965_irq_tasklet(struct il_priv *il) * is killed. Hence update the killswitch state here. The * rfkill handler will care about restarting if needed. */ - if (!test_bit(S_ALIVE, &il->status)) { - if (hw_rf_kill) - set_bit(S_RFKILL, &il->status); - else - clear_bit(S_RFKILL, &il->status); + if (hw_rf_kill) { + set_bit(S_RFKILL, &il->status); + } else { + clear_bit(S_RFKILL, &il->status); wiphy_rfkill_set_hw_state(il->hw->wiphy, hw_rf_kill); + il_force_reset(il, true); } handled |= CSR_INT_BIT_RF_KILL; diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index 3195aad440dd..b03e22ef5462 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c @@ -4660,6 +4660,7 @@ il_force_reset(struct il_priv *il, bool external) return 0; } +EXPORT_SYMBOL(il_force_reset); int il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, From 6431f5d7c6025f8b007af06ea090de308f7e6881 Mon Sep 17 00:00:00 2001 From: "Sumit.Saxena@lsi.com" Date: Tue, 16 Jul 2013 02:26:05 +0530 Subject: [PATCH 1339/3400] [SCSI] megaraid_sas: megaraid_sas driver init fails in kdump kernel Problem: When Hardware IOMMU is on, megaraid_sas driver initialization fails in kdump kernel with LSI MegaRAID controller(device id-0x73). Actually this issue needs fix in firmware, but for firmware running in field, this driver fix is proposed to resolve the issue. At firmware initialization time, if firmware does not come to ready state, driver will reset the adapter and retry for firmware transition to ready state unconditionally(not only executed for kdump kernel). Signed-off-by: Sumit Saxena Signed-off-by: Kashyap Desai Cc: stable@vger.kernel.org Signed-off-by: James Bottomley --- drivers/scsi/megaraid/megaraid_sas_base.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 0177295599e0..1f0ca68409d4 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -3547,11 +3547,21 @@ static int megasas_init_fw(struct megasas_instance *instance) break; } - /* - * We expect the FW state to be READY - */ - if (megasas_transition_to_ready(instance, 0)) - goto fail_ready_state; + if (megasas_transition_to_ready(instance, 0)) { + atomic_set(&instance->fw_reset_no_pci_access, 1); + instance->instancet->adp_reset + (instance, instance->reg_set); + atomic_set(&instance->fw_reset_no_pci_access, 0); + dev_info(&instance->pdev->dev, + "megasas: FW restarted successfully from %s!\n", + __func__); + + /*waitting for about 30 second before retry*/ + ssleep(30); + + if (megasas_transition_to_ready(instance, 0)) + goto fail_ready_state; + } /* * MSI-X host index 0 is common for all adapter. From e09056b25c38357df5c01985a0b3af608bccbfc0 Mon Sep 17 00:00:00 2001 From: Chris Leech Date: Tue, 23 Jul 2013 13:04:58 -0700 Subject: [PATCH 1340/3400] [SCSI] fnic: BUG: sleeping function called from invalid context during probe I hit this during driver probe with the latest fnic updates (this trace is from a backport into a distro kernel, but the issue is the same). > BUG: sleeping function called from invalid context at mm/slab.c:3113 > in_atomic(): 0, irqs_disabled(): 1, pid: 610, name: work_for_cpu > INFO: lockdep is turned off. > irq event stamp: 0 > hardirqs last enabled at (0): [<(null)>] (null) > hardirqs last disabled at (0): [] > copy_process+0x5e5/0x1670 > softirqs last enabled at (0): [] > copy_process+0x5e5/0x1670 > softirqs last disabled at (0): [<(null)>] (null) > Pid: 610, comm: work_for_cpu Not tainted > Call Trace: > [] ? print_irqtrace_events+0xd0/0xe0 > [] ? __might_sleep+0xf7/0x130 > [] ? kmem_cache_alloc_trace+0x20b/0x2d0 > [] ? __create_workqueue_key+0x3e/0x1d0 > [] ? __create_workqueue_key+0x3e/0x1d0 > [] ? fnic_probe+0x977/0x11aa [fnic] > [] ? fnic_probe+0x9a3/0x11aa [fnic] > [] ? do_work_for_cpu+0x0/0x30 > [] ? local_pci_probe+0x17/0x20 > [] ? do_work_for_cpu+0x18/0x30 > [] ? kthread+0x96/0xa0 > [] ? child_rip+0xa/0x20 > [] ? _spin_unlock_irq+0x30/0x40 > [] ? restore_args+0x0/0x30 > [] ? kthread+0x0/0xa0 > [] ? child_rip+0x0/0x20 The problem is in this hunk of "FIP VLAN Discovery Feature Support" (d3c995f1dcf938f1084388d92b8fb97bec366566) create_singlethreaded_workqueue cannot be called with irqs disabled @@ -620,7 +634,29 @@ static int __devinit fnic_probe(struct pci_dev *pdev, vnic_dev_packet_filter(fnic->vdev, 1, 1, 0, 0, 0); vnic_dev_add_addr(fnic->vdev, FIP_ALL_ENODE_MACS); vnic_dev_add_addr(fnic->vdev, fnic->ctlr.ctl_src_addr); + fnic->set_vlan = fnic_set_vlan; fcoe_ctlr_init(&fnic->ctlr, FIP_MODE_AUTO); + setup_timer(&fnic->fip_timer, fnic_fip_notify_timer, + (unsigned long)fnic); + spin_lock_init(&fnic->vlans_lock); + INIT_WORK(&fnic->fip_frame_work, fnic_handle_fip_frame); + INIT_WORK(&fnic->event_work, fnic_handle_event); + skb_queue_head_init(&fnic->fip_frame_queue); + spin_lock_irqsave(&fnic_list_lock, flags); + if (!fnic_fip_queue) { + fnic_fip_queue = + create_singlethread_workqueue("fnic_fip_q"); + if (!fnic_fip_queue) { + spin_unlock_irqrestore(&fnic_list_lock, flags); + printk(KERN_ERR PFX "fnic FIP work queue " + "create failed\n"); + err = -ENOMEM; + goto err_out_free_max_pool; + } + } + spin_unlock_irqrestore(&fnic_list_lock, flags); + INIT_LIST_HEAD(&fnic->evlist); + INIT_LIST_HEAD(&fnic->vlans); } else { shost_printk(KERN_INFO, fnic->lport->host, "firmware uses non-FIP mode\n"); The attempts to make fnic_fip_queue a single instance for the driver while it's being created in probe look awkward anyway, why is this not created in fnic_init_module like the event workqueue? Signed-off-by: Chris Leech Tested-by: Anantha Tungarakodi Acked-by: Hiral Patel Signed-off-by: James Bottomley --- drivers/scsi/fnic/fnic.h | 2 +- drivers/scsi/fnic/fnic_main.c | 22 +++++++++------------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h index b6d1f92ed33c..c18c68150e9f 100644 --- a/drivers/scsi/fnic/fnic.h +++ b/drivers/scsi/fnic/fnic.h @@ -38,7 +38,7 @@ #define DRV_NAME "fnic" #define DRV_DESCRIPTION "Cisco FCoE HBA Driver" -#define DRV_VERSION "1.5.0.22" +#define DRV_VERSION "1.5.0.23" #define PFX DRV_NAME ": " #define DFX DRV_NAME "%d: " diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c index 5f09d1814d26..42e15ee6e1bb 100644 --- a/drivers/scsi/fnic/fnic_main.c +++ b/drivers/scsi/fnic/fnic_main.c @@ -642,19 +642,6 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) INIT_WORK(&fnic->fip_frame_work, fnic_handle_fip_frame); INIT_WORK(&fnic->event_work, fnic_handle_event); skb_queue_head_init(&fnic->fip_frame_queue); - spin_lock_irqsave(&fnic_list_lock, flags); - if (!fnic_fip_queue) { - fnic_fip_queue = - create_singlethread_workqueue("fnic_fip_q"); - if (!fnic_fip_queue) { - spin_unlock_irqrestore(&fnic_list_lock, flags); - printk(KERN_ERR PFX "fnic FIP work queue " - "create failed\n"); - err = -ENOMEM; - goto err_out_free_max_pool; - } - } - spin_unlock_irqrestore(&fnic_list_lock, flags); INIT_LIST_HEAD(&fnic->evlist); INIT_LIST_HEAD(&fnic->vlans); } else { @@ -960,6 +947,13 @@ static int __init fnic_init_module(void) spin_lock_init(&fnic_list_lock); INIT_LIST_HEAD(&fnic_list); + fnic_fip_queue = create_singlethread_workqueue("fnic_fip_q"); + if (!fnic_fip_queue) { + printk(KERN_ERR PFX "fnic FIP work queue create failed\n"); + err = -ENOMEM; + goto err_create_fip_workq; + } + fnic_fc_transport = fc_attach_transport(&fnic_fc_functions); if (!fnic_fc_transport) { printk(KERN_ERR PFX "fc_attach_transport error\n"); @@ -978,6 +972,8 @@ static int __init fnic_init_module(void) err_pci_register: fc_release_transport(fnic_fc_transport); err_fc_transport: + destroy_workqueue(fnic_fip_queue); +err_create_fip_workq: destroy_workqueue(fnic_event_queue); err_create_fnic_workq: kmem_cache_destroy(fnic_io_req_cache); From 7562523e84ddc742fe1f9db8bd76b01acca89f6b Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Tue, 30 Jul 2013 22:58:34 -0400 Subject: [PATCH 1341/3400] [SCSI] Don't attempt to send extended INQUIRY command if skip_vpd_pages is set If a device has the skip_vpd_pages flag set we should simply fail the scsi_get_vpd_page() call. Signed-off-by: Martin K. Petersen Acked-by: Alan Stern Tested-by: Stuart Foster Cc: stable@vger.kernel.org Signed-off-by: James Bottomley --- drivers/scsi/scsi.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 3b1ea34e1f5a..eaa808e6ba91 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -1031,6 +1031,9 @@ int scsi_get_vpd_page(struct scsi_device *sdev, u8 page, unsigned char *buf, { int i, result; + if (sdev->skip_vpd_pages) + goto fail; + /* Ask for all the pages supported by this device */ result = scsi_vpd_inquiry(sdev, buf, 0, buf_len); if (result) From 23f14e79ace301c1e46b52344ce02e72254c57b6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 3 Aug 2013 06:01:58 +0800 Subject: [PATCH 1342/3400] staging: lustre: remove EXIT macro We have a kernel-wide function tracing system, so use that instead of rolling a custom one just for one filesystem. Cc: Peng Tao Cc: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../include/linux/libcfs/libcfs_debug.h | 5 ---- .../lustre/lnet/klnds/socklnd/socklnd_cb.c | 6 ---- .../lnet/klnds/socklnd/socklnd_lib-linux.c | 2 -- drivers/staging/lustre/lnet/lnet/lib-msg.c | 1 - .../staging/lustre/lustre/fid/fid_request.c | 3 -- drivers/staging/lustre/lustre/fld/fld_cache.c | 8 ----- .../staging/lustre/lustre/fld/fld_request.c | 5 ---- .../lustre/lustre/include/lustre_cfg.h | 1 - .../lustre/lustre/include/lustre_lib.h | 1 - .../lustre/lustre/include/lustre_mdc.h | 4 +-- .../staging/lustre/lustre/include/obd_class.h | 6 ---- .../lustre/lustre/lclient/lcommon_cl.c | 1 - .../lustre/lustre/ldlm/interval_tree.c | 4 --- .../staging/lustre/lustre/ldlm/ldlm_flock.c | 4 --- drivers/staging/lustre/lustre/ldlm/ldlm_lib.c | 7 ----- .../staging/lustre/lustre/ldlm/ldlm_lock.c | 30 ------------------- .../staging/lustre/lustre/ldlm/ldlm_lockd.c | 6 ---- .../staging/lustre/lustre/ldlm/ldlm_pool.c | 4 --- .../staging/lustre/lustre/ldlm/ldlm_request.c | 5 ---- .../lustre/lustre/ldlm/ldlm_resource.c | 4 --- drivers/staging/lustre/lustre/libcfs/hash.c | 2 -- .../lustre/lustre/libcfs/linux/linux-debug.c | 2 -- .../lustre/lustre/libcfs/upcall_cache.c | 3 -- drivers/staging/lustre/lustre/llite/dcache.c | 5 ---- drivers/staging/lustre/lustre/llite/dir.c | 4 --- drivers/staging/lustre/lustre/llite/file.c | 7 ----- .../staging/lustre/lustre/llite/llite_capa.c | 1 - .../staging/lustre/lustre/llite/llite_close.c | 7 ----- .../staging/lustre/lustre/llite/llite_lib.c | 20 ------------- .../staging/lustre/lustre/llite/llite_mmap.c | 3 -- .../staging/lustre/lustre/llite/llite_nfs.c | 2 -- drivers/staging/lustre/lustre/llite/namei.c | 3 -- drivers/staging/lustre/lustre/llite/rw.c | 1 - .../staging/lustre/lustre/llite/statahead.c | 15 ---------- drivers/staging/lustre/lustre/llite/vvp_io.c | 1 - .../staging/lustre/lustre/llite/vvp_page.c | 3 -- drivers/staging/lustre/lustre/llite/xattr.c | 1 - .../staging/lustre/lustre/lmv/lmv_intent.c | 1 - drivers/staging/lustre/lustre/lmv/lmv_obd.c | 4 --- drivers/staging/lustre/lustre/lov/lov_dev.c | 2 -- drivers/staging/lustre/lustre/lov/lov_io.c | 7 ----- drivers/staging/lustre/lustre/lov/lov_lock.c | 6 ---- .../staging/lustre/lustre/lov/lov_object.c | 6 ---- drivers/staging/lustre/lustre/lov/lov_page.c | 2 -- drivers/staging/lustre/lustre/lov/lov_pool.c | 7 ----- .../staging/lustre/lustre/lov/lov_request.c | 1 - .../staging/lustre/lustre/lov/lovsub_dev.c | 2 -- .../staging/lustre/lustre/lov/lovsub_lock.c | 6 ---- .../staging/lustre/lustre/lov/lovsub_object.c | 1 - drivers/staging/lustre/lustre/mdc/mdc_locks.c | 1 - .../staging/lustre/lustre/mdc/mdc_request.c | 10 ------- .../staging/lustre/lustre/mgc/mgc_request.c | 6 ---- drivers/staging/lustre/lustre/obdclass/acl.c | 3 -- drivers/staging/lustre/lustre/obdclass/capa.c | 4 --- .../staging/lustre/lustre/obdclass/cl_io.c | 30 ------------------- .../staging/lustre/lustre/obdclass/cl_lock.c | 21 ------------- .../lustre/lustre/obdclass/cl_object.c | 3 -- .../staging/lustre/lustre/obdclass/cl_page.c | 19 ------------ .../lustre/lustre/obdclass/class_obd.c | 2 -- .../staging/lustre/lustre/obdclass/genops.c | 8 ----- .../lustre/obdclass/linux/linux-module.c | 1 - .../staging/lustre/lustre/obdclass/llog_cat.c | 1 - .../staging/lustre/lustre/obdclass/llog_osd.c | 1 - .../lustre/lustre/obdclass/llog_swab.c | 6 ---- .../lustre/lustre/obdclass/lprocfs_status.c | 1 - .../lustre/lustre/obdclass/lustre_handles.c | 3 -- .../lustre/lustre/obdclass/obd_config.c | 2 -- .../lustre/lustre/obdecho/echo_client.c | 7 ----- drivers/staging/lustre/lustre/osc/osc_cache.c | 10 ------- drivers/staging/lustre/lustre/osc/osc_lock.c | 3 -- drivers/staging/lustre/lustre/osc/osc_page.c | 1 - .../staging/lustre/lustre/osc/osc_request.c | 4 --- drivers/staging/lustre/lustre/ptlrpc/client.c | 14 --------- .../staging/lustre/lustre/ptlrpc/connection.c | 5 ++-- drivers/staging/lustre/lustre/ptlrpc/events.c | 7 ----- .../lustre/lustre/ptlrpc/gss/gss_keyring.c | 4 --- .../lustre/lustre/ptlrpc/gss/gss_pipefs.c | 7 ----- .../lustre/lustre/ptlrpc/gss/gss_svc_upcall.c | 1 - .../lustre/lustre/ptlrpc/gss/sec_gss.c | 7 ----- drivers/staging/lustre/lustre/ptlrpc/import.c | 5 ---- .../lustre/lustre/ptlrpc/llog_client.c | 4 --- .../lustre/lustre/ptlrpc/llog_server.c | 4 --- drivers/staging/lustre/lustre/ptlrpc/nrs.c | 8 ----- .../lustre/lustre/ptlrpc/pack_generic.c | 5 ---- drivers/staging/lustre/lustre/ptlrpc/pinger.c | 1 - .../staging/lustre/lustre/ptlrpc/ptlrpcd.c | 8 +---- .../staging/lustre/lustre/ptlrpc/recover.c | 5 ---- drivers/staging/lustre/lustre/ptlrpc/sec.c | 3 -- .../staging/lustre/lustre/ptlrpc/sec_config.c | 1 - .../staging/lustre/lustre/ptlrpc/sec_plain.c | 4 --- .../staging/lustre/lustre/ptlrpc/service.c | 11 ------- 91 files changed, 4 insertions(+), 479 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h index 17189d9e3cba..e0ed2cf6e208 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h @@ -309,11 +309,6 @@ do { \ # error "Unkown compiler" #endif /* __GNUC__ */ -#define EXIT \ -do { \ - CDEBUG(D_TRACE, "Process leaving\n"); \ -} while(0) - extern int libcfs_debug_msg(struct libcfs_debug_msg_data *msgdata, const char *format1, ...) __attribute__ ((format (printf, 2, 3))); diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c index 6a538497f9f8..cdaaca372719 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c @@ -400,8 +400,6 @@ ksocknal_tx_done (lnet_ni_t *ni, ksock_tx_t *tx) ksocknal_free_tx (tx); if (lnetmsg != NULL) /* KSOCK_MSG_NOOP go without lnetmsg */ lnet_finalize (ni, lnetmsg, rc); - - EXIT; } void @@ -1577,8 +1575,6 @@ void ksocknal_read_callback (ksock_conn_t *conn) wake_up (&sched->kss_waitq); } spin_unlock_bh(&sched->kss_lock); - - EXIT; } /* @@ -1607,8 +1603,6 @@ void ksocknal_write_callback (ksock_conn_t *conn) } spin_unlock_bh(&sched->kss_lock); - - EXIT; } ksock_proto_t * diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.c index 6cfcf7758c04..27392d8b3bfe 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib-linux.c @@ -977,8 +977,6 @@ ksocknal_data_ready (struct sock *sk, int n) ksocknal_read_callback(conn); read_unlock(&ksocknal_data.ksnd_global_lock); - - EXIT; } static void diff --git a/drivers/staging/lustre/lnet/lnet/lib-msg.c b/drivers/staging/lustre/lnet/lnet/lib-msg.c index 214bf38745ae..fc7ba42a4dd1 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-msg.c +++ b/drivers/staging/lustre/lnet/lnet/lib-msg.c @@ -52,7 +52,6 @@ lnet_build_unlink_event (lnet_libmd_t *md, lnet_event_t *ev) ev->type = LNET_EVENT_UNLINK; lnet_md_deconstruct(md, &ev->md); lnet_md2handle(&ev->md_handle, md); - EXIT; } /* diff --git a/drivers/staging/lustre/lustre/fid/fid_request.c b/drivers/staging/lustre/lustre/fid/fid_request.c index 59ff87cea083..5d25a336b852 100644 --- a/drivers/staging/lustre/lustre/fid/fid_request.c +++ b/drivers/staging/lustre/lustre/fid/fid_request.c @@ -133,7 +133,6 @@ static int seq_client_rpc(struct lu_client_seq *seq, CDEBUG_LIMIT(debug_mask, "%s: Allocated %s-sequence "DRANGE"]\n", seq->lcs_name, opcname, PRANGE(output)); - EXIT; out_req: ptlrpc_req_finished(req); return rc; @@ -407,7 +406,6 @@ static void seq_client_proc_fini(struct lu_client_seq *seq) lprocfs_remove(&seq->lcs_proc_dir); seq->lcs_proc_dir = NULL; } - EXIT; #endif /* LPROCFS */ } @@ -495,7 +493,6 @@ void seq_client_fini(struct lu_client_seq *seq) } seq->lcs_srv = NULL; - EXIT; } EXPORT_SYMBOL(seq_client_fini); diff --git a/drivers/staging/lustre/lustre/fld/fld_cache.c b/drivers/staging/lustre/lustre/fld/fld_cache.c index 9f9f9b5c6290..b1672f773066 100644 --- a/drivers/staging/lustre/lustre/fld/fld_cache.c +++ b/drivers/staging/lustre/lustre/fld/fld_cache.c @@ -118,8 +118,6 @@ void fld_cache_fini(struct fld_cache *cache) CDEBUG(D_INFO, " Cache hits: "LPU64"%%\n", pct); OBD_FREE_PTR(cache); - - EXIT; } /** @@ -196,8 +194,6 @@ restart_fixup: c_range->lsr_end == n_range->lsr_end) fld_cache_entry_delete(cache, f_curr); } - - EXIT; } /** @@ -255,8 +251,6 @@ void fld_cache_flush(struct fld_cache *cache) cache->fci_cache_size = 0; fld_cache_shrink(cache); write_unlock(&cache->fci_lock); - - EXIT; } /** @@ -276,7 +270,6 @@ void fld_cache_punch_hole(struct fld_cache *cache, OBD_ALLOC_GFP(fldt, sizeof *fldt, GFP_ATOMIC); if (!fldt) { OBD_FREE_PTR(f_new); - EXIT; /* overlap is not allowed, so dont mess up list. */ return; } @@ -299,7 +292,6 @@ void fld_cache_punch_hole(struct fld_cache *cache, fld_cache_entry_add(cache, fldt, &f_new->fce_list); /* no need to fixup */ - EXIT; } /** diff --git a/drivers/staging/lustre/lustre/fld/fld_request.c b/drivers/staging/lustre/lustre/fld/fld_request.c index 0c928dea899e..9fe004681abd 100644 --- a/drivers/staging/lustre/lustre/fld/fld_request.c +++ b/drivers/staging/lustre/lustre/fld/fld_request.c @@ -316,7 +316,6 @@ void fld_client_proc_fini(struct lu_client_fld *fld) lprocfs_remove(&fld->lcf_proc_dir); fld->lcf_proc_dir = NULL; } - EXIT; } #else static int fld_client_proc_init(struct lu_client_fld *fld) @@ -377,7 +376,6 @@ int fld_client_init(struct lu_client_fld *fld, rc = fld_client_proc_init(fld); if (rc) GOTO(out, rc); - EXIT; out: if (rc) fld_client_fini(fld); @@ -408,8 +406,6 @@ void fld_client_fini(struct lu_client_fld *fld) fld_cache_fini(fld->lcf_cache); fld->lcf_cache = NULL; } - - EXIT; } EXPORT_SYMBOL(fld_client_fini); @@ -458,7 +454,6 @@ int fld_client_rpc(struct obd_export *exp, if (prange == NULL) GOTO(out_req, rc = -EFAULT); *range = *prange; - EXIT; out_req: ptlrpc_req_finished(req); return rc; diff --git a/drivers/staging/lustre/lustre/include/lustre_cfg.h b/drivers/staging/lustre/lustre/include/lustre_cfg.h index 5004c9079a8b..46d5aaf17893 100644 --- a/drivers/staging/lustre/lustre/include/lustre_cfg.h +++ b/drivers/staging/lustre/lustre/include/lustre_cfg.h @@ -253,7 +253,6 @@ static inline void lustre_cfg_free(struct lustre_cfg *lcfg) len = lustre_cfg_len(lcfg->lcfg_bufcount, lcfg->lcfg_buflens); OBD_FREE(lcfg, len); - EXIT; return; } diff --git a/drivers/staging/lustre/lustre/include/lustre_lib.h b/drivers/staging/lustre/lustre/include/lustre_lib.h index 007b2ddc7a9c..e77a74540da7 100644 --- a/drivers/staging/lustre/lustre/include/lustre_lib.h +++ b/drivers/staging/lustre/lustre/include/lustre_lib.h @@ -261,7 +261,6 @@ int obd_ioctl_popdata(void *arg, void *data, int len); static inline void obd_ioctl_freedata(char *buf, int len) { OBD_FREE_LARGE(buf, len); - EXIT; return; } diff --git a/drivers/staging/lustre/lustre/include/lustre_mdc.h b/drivers/staging/lustre/lustre/include/lustre_mdc.h index e09646ade9d3..19000259a5e4 100644 --- a/drivers/staging/lustre/lustre/include/lustre_mdc.h +++ b/drivers/staging/lustre/lustre/include/lustre_mdc.h @@ -124,7 +124,7 @@ static inline void mdc_put_rpc_lock(struct mdc_rpc_lock *lck, { if (it != NULL && (it->it_op == IT_GETATTR || it->it_op == IT_LOOKUP || it->it_op == IT_LAYOUT)) - goto out; + return; if (lck->rpcl_it == MDC_FAKE_RPCL_IT) { /* OBD_FAIL_MDC_RPCS_SEM */ mutex_lock(&lck->rpcl_mutex); @@ -141,8 +141,6 @@ static inline void mdc_put_rpc_lock(struct mdc_rpc_lock *lck, } mutex_unlock(&lck->rpcl_mutex); - out: - EXIT; } static inline void mdc_update_max_ea_from_body(struct obd_export *exp, diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h index c42996ba4f9c..c10477f5faf5 100644 --- a/drivers/staging/lustre/lustre/include/obd_class.h +++ b/drivers/staging/lustre/lustre/include/obd_class.h @@ -649,8 +649,6 @@ static inline void obd_cleanup_client_import(struct obd_device *obd) obd->u.cli.cl_import = NULL; } up_write(&obd->u.cli.cl_sem); - - EXIT; } static inline int @@ -1099,7 +1097,6 @@ static inline void obd_getref(struct obd_device *obd) OBD_COUNTER_INCREMENT(obd, getref); OBP(obd, getref)(obd); } - EXIT; } static inline void obd_putref(struct obd_device *obd) @@ -1108,7 +1105,6 @@ static inline void obd_putref(struct obd_device *obd) OBD_COUNTER_INCREMENT(obd, putref); OBP(obd, putref)(obd); } - EXIT; } static inline int obd_init_export(struct obd_export *exp) @@ -1525,14 +1521,12 @@ static inline void obd_import_event(struct obd_device *obd, { if (!obd) { CERROR("NULL device\n"); - EXIT; return; } if (obd->obd_set_up && OBP(obd, import_event)) { OBD_COUNTER_INCREMENT(obd, import_event); OBP(obd, import_event)(obd, imp, event); } - EXIT; } static inline int obd_llog_connect(struct obd_export *exp, diff --git a/drivers/staging/lustre/lustre/lclient/lcommon_cl.c b/drivers/staging/lustre/lustre/lclient/lcommon_cl.c index 1d3c2340227b..41168c2cbdf6 100644 --- a/drivers/staging/lustre/lustre/lclient/lcommon_cl.c +++ b/drivers/staging/lustre/lustre/lclient/lcommon_cl.c @@ -674,7 +674,6 @@ void ccc_lock_state(const struct lu_env *env, lock->cll_descr.cld_end == CL_PAGE_EOF) cl_merge_lvb(env, inode); } - EXIT; } /***************************************************************************** diff --git a/drivers/staging/lustre/lustre/ldlm/interval_tree.c b/drivers/staging/lustre/lustre/ldlm/interval_tree.c index 7de620aa295f..400d28ef703c 100644 --- a/drivers/staging/lustre/lustre/ldlm/interval_tree.c +++ b/drivers/staging/lustre/lustre/ldlm/interval_tree.c @@ -361,7 +361,6 @@ static void interval_insert_color(struct interval_node *node, } (*root)->in_color = INTERVAL_BLACK; - EXIT; } struct interval_node *interval_insert(struct interval_node *node, @@ -476,7 +475,6 @@ static void interval_erase_color(struct interval_node *node, } if (node) node->in_color = INTERVAL_BLACK; - EXIT; } /* @@ -498,7 +496,6 @@ static void update_maxhigh(struct interval_node *node, break; node = node->in_parent; } - EXIT; } void interval_erase(struct interval_node *node, @@ -570,7 +567,6 @@ void interval_erase(struct interval_node *node, color: if (color == INTERVAL_BLACK) interval_erase_color(child, parent, root); - EXIT; } EXPORT_SYMBOL(interval_erase); diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c index b263121e2bf0..9e61144ea24f 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c @@ -160,7 +160,6 @@ ldlm_flock_destroy(struct ldlm_lock *lock, ldlm_mode_t mode, __u64 flags) } ldlm_lock_destroy_nolock(lock); - EXIT; } /** @@ -553,8 +552,6 @@ ldlm_flock_interrupted_wait(void *data) /* client side - set flag to prevent lock from being put on LRU list */ lock->l_flags |= LDLM_FL_CBPENDING; unlock_res_and_lock(lock); - - EXIT; } /** @@ -840,6 +837,5 @@ void ldlm_destroy_flock_export(struct obd_export *exp) cfs_hash_putref(exp->exp_flock_hash); exp->exp_flock_hash = NULL; } - EXIT; } EXPORT_SYMBOL(ldlm_destroy_flock_export); diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c index d77156a98ad8..4b03e7d8d3ae 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c @@ -525,8 +525,6 @@ int client_connect_import(const struct lu_env *env, ptlrpc_pinger_add_import(imp); - EXIT; - if (rc) { out_ldlm: cli->cl_conn_count--; @@ -597,8 +595,6 @@ int client_disconnect_export(struct obd_export *exp) ptlrpc_invalidate_import(imp); - EXIT; - out_disconnect: /* Use server style - class_disconnect should be always called for * o_disconnect. */ @@ -667,7 +663,6 @@ void target_send_reply(struct ptlrpc_request *req, int rc, int fail_id) struct obd_export *exp; if (req->rq_no_reply) { - EXIT; return; } @@ -676,7 +671,6 @@ void target_send_reply(struct ptlrpc_request *req, int rc, int fail_id) if (rs == NULL || !rs->rs_difficult) { /* no notifiers */ target_send_reply_msg (req, rc, fail_id); - EXIT; return; } @@ -747,7 +741,6 @@ void target_send_reply(struct ptlrpc_request *req, int rc, int fail_id) } spin_unlock(&rs->rs_lock); spin_unlock(&svcpt->scp_rep_lock); - EXIT; } EXPORT_SYMBOL(target_send_reply); diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c index 6b214d2ca562..e0877b20eb94 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c @@ -218,8 +218,6 @@ void ldlm_lock_put(struct ldlm_lock *lock) lu_ref_fini(&lock->l_reference); OBD_FREE_RCU(lock, sizeof(*lock), &lock->l_handle); } - - EXIT; } EXPORT_SYMBOL(ldlm_lock_put); @@ -259,7 +257,6 @@ int ldlm_lock_remove_from_lru(struct ldlm_lock *lock) spin_lock(&ns->ns_lock); rc = ldlm_lock_remove_from_lru_nolock(lock); spin_unlock(&ns->ns_lock); - EXIT; return rc; } @@ -289,7 +286,6 @@ void ldlm_lock_add_to_lru(struct ldlm_lock *lock) spin_lock(&ns->ns_lock); ldlm_lock_add_to_lru_nolock(lock); spin_unlock(&ns->ns_lock); - EXIT; } /** @@ -302,7 +298,6 @@ void ldlm_lock_touch_in_lru(struct ldlm_lock *lock) if (lock->l_flags & LDLM_FL_NS_SRV) { LASSERT(list_empty(&lock->l_lru)); - EXIT; return; } @@ -312,7 +307,6 @@ void ldlm_lock_touch_in_lru(struct ldlm_lock *lock) ldlm_lock_add_to_lru_nolock(lock); } spin_unlock(&ns->ns_lock); - EXIT; } /** @@ -348,7 +342,6 @@ int ldlm_lock_destroy_internal(struct ldlm_lock *lock) if (lock->l_flags & LDLM_FL_DESTROYED) { LASSERT(list_empty(&lock->l_lru)); - EXIT; return 0; } lock->l_flags |= LDLM_FL_DESTROYED; @@ -376,7 +369,6 @@ int ldlm_lock_destroy_internal(struct ldlm_lock *lock) if (lock->l_export && lock->l_completion_ast) lock->l_completion_ast(lock, 0); #endif - EXIT; return 1; } @@ -396,7 +388,6 @@ void ldlm_lock_destroy(struct ldlm_lock *lock) lu_ref_del(&lock->l_reference, "hash", lock); LDLM_LOCK_RELEASE(lock); } - EXIT; } /** @@ -412,7 +403,6 @@ void ldlm_lock_destroy_nolock(struct ldlm_lock *lock) lu_ref_del(&lock->l_reference, "hash", lock); LDLM_LOCK_RELEASE(lock); } - EXIT; } /* this is called by portals_handle2object with the handle lock taken */ @@ -723,7 +713,6 @@ void ldlm_add_ast_work_item(struct ldlm_lock *lock, struct ldlm_lock *new, ldlm_add_bl_work_item(lock, new, work_list); else ldlm_add_cp_work_item(lock, work_list); - EXIT; } /** @@ -902,8 +891,6 @@ void ldlm_lock_decref_internal(struct ldlm_lock *lock, __u32 mode) LDLM_DEBUG(lock, "do not add lock into lru list"); unlock_res_and_lock(lock); } - - EXIT; } /** @@ -985,7 +972,6 @@ static void search_granted_lock(struct list_head *queue, prev->res_link = &mode_end->l_res_link; prev->mode_link = &mode_end->l_sl_mode; prev->policy_link = &req->l_sl_policy; - EXIT; return; } else if (lock->l_resource->lr_type == LDLM_IBITS) { for (;;) { @@ -1004,7 +990,6 @@ static void search_granted_lock(struct list_head *queue, &policy_end->l_sl_mode; prev->policy_link = &policy_end->l_sl_policy; - EXIT; return; } @@ -1023,7 +1008,6 @@ static void search_granted_lock(struct list_head *queue, prev->res_link = &mode_end->l_res_link; prev->mode_link = &mode_end->l_sl_mode; prev->policy_link = &req->l_sl_policy; - EXIT; return; } else { LDLM_ERROR(lock,"is not LDLM_PLAIN or LDLM_IBITS lock"); @@ -1036,7 +1020,6 @@ static void search_granted_lock(struct list_head *queue, prev->res_link = queue->prev; prev->mode_link = &req->l_sl_mode; prev->policy_link = &req->l_sl_policy; - EXIT; return; } @@ -1073,8 +1056,6 @@ static void ldlm_granted_list_add_lock(struct ldlm_lock *lock, list_add(&lock->l_sl_mode, prev->mode_link); if (&lock->l_sl_policy != prev->policy_link) list_add(&lock->l_sl_policy, prev->policy_link); - - EXIT; } /** @@ -1089,7 +1070,6 @@ static void ldlm_grant_lock_with_skiplist(struct ldlm_lock *lock) search_granted_lock(&lock->l_resource->lr_granted, lock, &prev); ldlm_granted_list_add_lock(lock, &prev); - EXIT; } /** @@ -1124,7 +1104,6 @@ void ldlm_grant_lock(struct ldlm_lock *lock, struct list_head *work_list) ldlm_add_ast_work_item(lock, NULL, work_list); ldlm_pool_add(&ldlm_res_to_ns(res)->ns_pool, lock); - EXIT; } /** @@ -1322,7 +1301,6 @@ ldlm_mode_t ldlm_lock_match(struct ldlm_namespace *ns, __u64 flags, if (lock != NULL) GOTO(out, rc = 1); - EXIT; out: unlock_res(res); LDLM_RESOURCE_DELREF(res); @@ -1424,8 +1402,6 @@ ldlm_mode_t ldlm_revalidate_lock_handle(struct lustre_handle *lockh, ldlm_lock_addref_internal_nolock(lock, mode); } - EXIT; - out: if (lock != NULL) { unlock_res_and_lock(lock); @@ -1936,7 +1912,6 @@ void ldlm_reprocess_all_ns(struct ldlm_namespace *ns) cfs_hash_for_each_nolock(ns->ns_rs_hash, ldlm_reprocess_res, NULL); } - EXIT; } EXPORT_SYMBOL(ldlm_reprocess_all_ns); @@ -1957,7 +1932,6 @@ void ldlm_reprocess_all(struct ldlm_resource *res) "LDLM_NAMESPACE_SERVER resource type lock.\n"); LBUG(); } - EXIT; } /** @@ -2035,8 +2009,6 @@ void ldlm_lock_cancel(struct ldlm_lock *lock) * if not to zero out lock->l_granted_mode */ lock->l_granted_mode = LCK_MINMODE; unlock_res_and_lock(lock); - - EXIT; } EXPORT_SYMBOL(ldlm_lock_cancel); @@ -2142,8 +2114,6 @@ void ldlm_lock_downgrade(struct ldlm_lock *lock, int new_mode) ldlm_grant_lock(lock, NULL); unlock_res_and_lock(lock); ldlm_reprocess_all(lock->l_resource); - - EXIT; } EXPORT_SYMBOL(ldlm_lock_downgrade); diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c index adab8b81c852..cce0ad70f162 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c @@ -171,7 +171,6 @@ void ldlm_handle_bl_callback(struct ldlm_namespace *ns, LDLM_DEBUG(lock, "client blocking callback handler END"); LDLM_LOCK_RELEASE(lock); - EXIT; } /** @@ -353,12 +352,10 @@ static void ldlm_handle_gl_callback(struct ptlrpc_request *req, if (ldlm_bl_to_thread_lock(ns, NULL, lock)) ldlm_handle_bl_callback(ns, NULL, lock); - EXIT; return; } unlock_res_and_lock(lock); LDLM_LOCK_RELEASE(lock); - EXIT; } static int ldlm_callback_reply(struct ptlrpc_request *req, int rc) @@ -933,8 +930,6 @@ void ldlm_put_ref(void) ldlm_refcount--; } mutex_unlock(&ldlm_ref_mutex); - - EXIT; } EXPORT_SYMBOL(ldlm_put_ref); @@ -1031,7 +1026,6 @@ void ldlm_destroy_export(struct obd_export *exp) exp->exp_lock_hash = NULL; ldlm_destroy_flock_export(exp); - EXIT; } EXPORT_SYMBOL(ldlm_destroy_export); diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c b/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c index 5a1d11e0159a..e500506c8683 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c @@ -810,7 +810,6 @@ static int ldlm_pool_proc_init(struct ldlm_pool *pl) "recalc_timing", "sec"); rc = lprocfs_register_stats(pl->pl_proc_dir, "stats", pl->pl_stats); - EXIT; out_free_name: OBD_FREE(var_name, MAX_STRING_SIZE + 1); return rc; @@ -877,7 +876,6 @@ void ldlm_pool_fini(struct ldlm_pool *pl) * any abnormal using cases. */ POISON(pl, 0x5a, sizeof(*pl)); - EXIT; } EXPORT_SYMBOL(ldlm_pool_fini); @@ -1370,7 +1368,6 @@ static int ldlm_pools_thread_start(void) static void ldlm_pools_thread_stop(void) { if (ldlm_pools_thread == NULL) { - EXIT; return; } @@ -1385,7 +1382,6 @@ static void ldlm_pools_thread_stop(void) wait_for_completion(&ldlm_pools_comp); OBD_FREE_PTR(ldlm_pools_thread); ldlm_pools_thread = NULL; - EXIT; } int ldlm_pools_init(void) diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c index 0b6dc6a288a5..6c2b94536d82 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_request.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_request.c @@ -456,7 +456,6 @@ int ldlm_cli_enqueue_local(struct ldlm_namespace *ns, lock->l_completion_ast(lock, *flags, NULL); LDLM_DEBUG(lock, "client-side local enqueue handler, new lock created"); - EXIT; out: LDLM_LOCK_RELEASE(lock); out_nolock: @@ -689,7 +688,6 @@ int ldlm_cli_enqueue_fini(struct obd_export *exp, struct ptlrpc_request *req, } LDLM_DEBUG(lock, "client-side enqueue END"); - EXIT; cleanup: if (cleanup_phase == 1 && rc) failed_lock_cleanup(ns, lock, mode); @@ -1083,7 +1081,6 @@ int ldlm_cli_convert(struct lustre_handle *lockh, int new_mode, __u32 *flags) } else { rc = LUSTRE_EDEADLK; } - EXIT; out: LDLM_LOCK_PUT(lock); ptlrpc_req_finished(req); @@ -1168,7 +1165,6 @@ static void ldlm_cancel_pack(struct ptlrpc_request *req, packed++; } CDEBUG(D_DLMTRACE, "%d locks packed\n", packed); - EXIT; } /** @@ -1253,7 +1249,6 @@ int ldlm_cli_cancel_req(struct obd_export *exp, struct list_head *cancels, } ptlrpc_req_finished(req); - EXIT; out: return sent ? sent : rc; } diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c index 8b2b3fa16112..f4d367c5978f 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c @@ -862,7 +862,6 @@ void ldlm_namespace_free_prior(struct ldlm_namespace *ns, int rc; if (!ns) { - EXIT; return; } @@ -887,7 +886,6 @@ void ldlm_namespace_free_prior(struct ldlm_namespace *ns, rc = __ldlm_namespace_free(ns, 1); LASSERT(rc == 0); } - EXIT; } /** @@ -898,7 +896,6 @@ void ldlm_namespace_free_prior(struct ldlm_namespace *ns, void ldlm_namespace_free_post(struct ldlm_namespace *ns) { if (!ns) { - EXIT; return; } @@ -917,7 +914,6 @@ void ldlm_namespace_free_post(struct ldlm_namespace *ns) LASSERT(list_empty(&ns->ns_list_chain)); OBD_FREE_PTR(ns); ldlm_put_ref(); - EXIT; } /** diff --git a/drivers/staging/lustre/lustre/libcfs/hash.c b/drivers/staging/lustre/lustre/libcfs/hash.c index bc7497a9b064..87f52563eab0 100644 --- a/drivers/staging/lustre/lustre/libcfs/hash.c +++ b/drivers/staging/lustre/lustre/libcfs/hash.c @@ -1149,8 +1149,6 @@ cfs_hash_destroy(cfs_hash_t *hs) i = cfs_hash_with_bigname(hs) ? CFS_HASH_BIGNAME_LEN : CFS_HASH_NAME_LEN; LIBCFS_FREE(hs, offsetof(cfs_hash_t, hs_name[i])); - - EXIT; } cfs_hash_t *cfs_hash_getref(cfs_hash_t *hs) diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c index 3e61a0d4574b..ec3d97664b1b 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c @@ -95,8 +95,6 @@ void libcfs_run_debug_log_upcall(char *file) CDEBUG(D_HA, "Invoked LNET debug log upcall %s %s\n", argv[0], argv[1]); } - - EXIT; } void libcfs_run_upcall(char **argv) diff --git a/drivers/staging/lustre/lustre/libcfs/upcall_cache.c b/drivers/staging/lustre/lustre/libcfs/upcall_cache.c index 7663fb568371..9b15c7c4e446 100644 --- a/drivers/staging/lustre/lustre/libcfs/upcall_cache.c +++ b/drivers/staging/lustre/lustre/libcfs/upcall_cache.c @@ -273,7 +273,6 @@ void upcall_cache_put_entry(struct upcall_cache *cache, struct upcall_cache_entry *entry) { if (!entry) { - EXIT; return; } @@ -281,7 +280,6 @@ void upcall_cache_put_entry(struct upcall_cache *cache, spin_lock(&cache->uc_lock); put_entry(cache, entry); spin_unlock(&cache->uc_lock); - EXIT; } EXPORT_SYMBOL(upcall_cache_put_entry); @@ -374,7 +372,6 @@ static void cache_flush(struct upcall_cache *cache, int force) } } spin_unlock(&cache->uc_lock); - EXIT; } void upcall_cache_flush_idle(struct upcall_cache *cache) diff --git a/drivers/staging/lustre/lustre/llite/dcache.c b/drivers/staging/lustre/lustre/llite/dcache.c index 484af85f97d6..ff74783ef9d3 100644 --- a/drivers/staging/lustre/lustre/llite/dcache.c +++ b/drivers/staging/lustre/lustre/llite/dcache.c @@ -73,8 +73,6 @@ static void ll_release(struct dentry *de) LASSERT(lld->lld_mnt_count == 0); de->d_fsdata = NULL; call_rcu(&lld->lld_rcu_head, free_dentry_data); - - EXIT; } /* Compare if two dentries are the same. Don't match if the existing dentry @@ -267,7 +265,6 @@ void ll_intent_release(struct lookup_intent *it) it->d.lustre.it_disposition = 0; it->d.lustre.it_data = NULL; - EXIT; } void ll_invalidate_aliases(struct inode *inode) @@ -298,8 +295,6 @@ void ll_invalidate_aliases(struct inode *inode) d_lustre_invalidate(dentry, 0); } ll_unlock_dcache(inode); - - EXIT; } int ll_revalidate_it_finish(struct ptlrpc_request *request, diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 55256812ae20..09bdd3d1e6e6 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -237,7 +237,6 @@ static int ll_dir_filler(void *_hash, struct page *page0) if (page_pool != &page0) OBD_FREE(page_pool, sizeof(struct page *) * max_pages); - EXIT; return rc; } @@ -1300,7 +1299,6 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg) GOTO(out_free, rc); } ptlrpc_req_finished(request); - EXIT; out_free: obd_ioctl_freedata(buf, len); return rc; @@ -1522,7 +1520,6 @@ out_rmdir: GOTO(out_req, rc = -EFAULT); } - EXIT; out_req: ptlrpc_req_finished(request); if (filename) @@ -1587,7 +1584,6 @@ out_rmdir: if (copy_to_user(&lumd->lmd_st, &st, sizeof(st))) GOTO(free_lsm, rc = -EFAULT); - EXIT; free_lsm: obd_free_memmd(sbi->ll_dt_exp, &lsm); free_lmm: diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 79f5394ac6b2..7f5435b18b65 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -111,7 +111,6 @@ out: ll_pack_inode2opdata(inode, op_data, &och->och_fh); ll_prep_md_op_data(op_data, inode, NULL, NULL, 0, 0, LUSTRE_OPC_ANY, NULL); - EXIT; } static int ll_close_inode_openhandle(struct obd_export *md_exp, @@ -177,9 +176,7 @@ static int ll_close_inode_openhandle(struct obd_export *md_exp, inode->i_ino, rc); } - EXIT; out: - if (exp_connect_som(exp) && !epoch_close && S_ISREG(inode->i_mode) && (och->och_flags & FMODE_WRITE)) { ll_queue_done_writing(inode, LLIF_DONE_WRITING); @@ -1690,7 +1687,6 @@ int ll_data_version(struct inode *inode, __u64 *data_version, } OBD_FREE_PTR(obdo); - EXIT; out: ccc_inode_lsm_put(inode, lsm); RETURN(rc); @@ -2939,8 +2935,6 @@ static int ll_layout_fetch(struct inode *inode, struct ldlm_lock *lock) lock->l_lvb_len = lmmsize; unlock_res_and_lock(lock); - EXIT; - out: ptlrpc_req_finished(req); return rc; @@ -3029,7 +3023,6 @@ static int ll_layout_lock_set(struct lustre_handle *lockh, ldlm_mode_t mode, /* refresh layout failed, need to wait */ wait_layout = rc == -EBUSY; - EXIT; out: LDLM_LOCK_PUT(lock); diff --git a/drivers/staging/lustre/lustre/llite/llite_capa.c b/drivers/staging/lustre/lustre/llite/llite_capa.c index 061a0a574b5d..3b4f7f82dd42 100644 --- a/drivers/staging/lustre/lustre/llite/llite_capa.c +++ b/drivers/staging/lustre/lustre/llite/llite_capa.c @@ -568,7 +568,6 @@ int ll_update_capa(struct obd_capa *ocapa, struct lustre_capa *capa) if (capa_for_oss(capa)) inode_add_oss_capa(inode, ocapa); DEBUG_CAPA(D_SEC, capa, "renew"); - EXIT; retry: list_del_init(&ocapa->c_list); sort_add_capa(ocapa, ll_capa_list); diff --git a/drivers/staging/lustre/lustre/llite/llite_close.c b/drivers/staging/lustre/lustre/llite/llite_close.c index 20481d8329b0..a9cd75f16e94 100644 --- a/drivers/staging/lustre/lustre/llite/llite_close.c +++ b/drivers/staging/lustre/lustre/llite/llite_close.c @@ -56,7 +56,6 @@ void vvp_write_pending(struct ccc_object *club, struct ccc_page *page) list_add(&page->cpg_pending_linkage, &club->cob_pending_list); spin_unlock(&lli->lli_lock); - EXIT; } /** records that a write has completed */ @@ -73,7 +72,6 @@ void vvp_write_complete(struct ccc_object *club, struct ccc_page *page) spin_unlock(&lli->lli_lock); if (rc) ll_queue_done_writing(club->cob_inode, 0); - EXIT; } /** Queues DONE_WRITING if @@ -116,7 +114,6 @@ void ll_queue_done_writing(struct inode *inode, unsigned long flags) spin_unlock(&lcq->lcq_lock); } spin_unlock(&lli->lli_lock); - EXIT; } /** Pack SOM attributes info @opdata for CLOSE, DONE_WRITING rpc. */ @@ -136,7 +133,6 @@ void ll_done_writing_attr(struct inode *inode, struct md_op_data *op_data) op_data->op_attr.ia_valid |= ATTR_MTIME_SET | ATTR_CTIME_SET | ATTR_ATIME_SET | ATTR_SIZE | ATTR_BLOCKS; } - EXIT; } /** Closes ioepoch and packs Size-on-MDS attribute if needed into @op_data. */ @@ -204,7 +200,6 @@ void ll_ioepoch_close(struct inode *inode, struct md_op_data *op_data, spin_unlock(&lli->lli_lock); ll_done_writing_attr(inode, op_data); - EXIT; out: return; } @@ -293,7 +288,6 @@ static void ll_done_writing(struct inode *inode) OBD_ALLOC_PTR(op_data); if (op_data == NULL) { CERROR("can't allocate op_data\n"); - EXIT; return; } @@ -317,7 +311,6 @@ out: md_clear_open_replay_data(ll_i2sbi(inode)->ll_md_exp, och); OBD_FREE_PTR(och); } - EXIT; } static struct ll_inode_info *ll_close_next_lli(struct ll_close_queue *lcq) diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 141243658d7c..71b8fd9ff1a7 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -152,7 +152,6 @@ void ll_free_sbi(struct super_block *sb) spin_unlock(&ll_sb_lock); OBD_FREE(sbi, sizeof(*sbi)); } - EXIT; } static struct dentry_operations ll_d_root_ops = { @@ -700,8 +699,6 @@ void client_common_put_super(struct super_block *sb) obd_fid_fini(sbi->ll_md_exp->exp_obd); obd_disconnect(sbi->ll_md_exp); sbi->ll_md_exp = NULL; - - EXIT; } void ll_kill_super(struct super_block *sb) @@ -720,7 +717,6 @@ void ll_kill_super(struct super_block *sb) sb->s_dev = sbi->ll_sdev_orig; sbi->ll_umounting = 1; } - EXIT; } char *ll_read_opt(const char *opt, char *data) @@ -1112,8 +1108,6 @@ void ll_put_super(struct super_block *sb) lustre_common_put_super(sb); module_put(THIS_MODULE); - - EXIT; } /* client_put_super */ struct inode *ll_inode_from_resource_lock(struct ldlm_lock *lock) @@ -1227,8 +1221,6 @@ void ll_clear_inode(struct inode *inode) */ cl_inode_fini(inode); lli->lli_has_smd = false; - - EXIT; } int ll_md_setattr(struct dentry *dentry, struct md_op_data *op_data, @@ -1469,7 +1461,6 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr) * setting times to past, but it is necessary due to possible * time de-synchronization between MDT inode and OST objects */ rc = ll_setattr_ost(inode, attr); - EXIT; out: if (op_data) { if (op_data->op_ioepoch) { @@ -1803,21 +1794,16 @@ void ll_read_inode2(struct inode *inode, void *opaque) inode->i_op = &ll_file_inode_operations; inode->i_fop = sbi->ll_fop; inode->i_mapping->a_ops = (struct address_space_operations *)&ll_aops; - EXIT; } else if (S_ISDIR(inode->i_mode)) { inode->i_op = &ll_dir_inode_operations; inode->i_fop = &ll_dir_operations; - EXIT; } else if (S_ISLNK(inode->i_mode)) { inode->i_op = &ll_fast_symlink_inode_operations; - EXIT; } else { inode->i_op = &ll_special_inode_operations; init_special_inode(inode, inode->i_mode, inode->i_rdev); - - EXIT; } } @@ -1847,8 +1833,6 @@ void ll_delete_inode(struct inode *inode) ll_clear_inode(inode); clear_inode(inode); - - EXIT; } int ll_iocontrol(struct inode *inode, struct file *file, @@ -1974,7 +1958,6 @@ void ll_umount_begin(struct super_block *sb) if (obd == NULL) { CERROR("Invalid MDC connection handle "LPX64"\n", sbi->ll_md_exp->exp_handle.h_cookie); - EXIT; return; } obd->obd_force = 1; @@ -1983,7 +1966,6 @@ void ll_umount_begin(struct super_block *sb) if (obd == NULL) { CERROR("Invalid LOV connection handle "LPX64"\n", sbi->ll_dt_exp->exp_handle.h_cookie); - EXIT; return; } obd->obd_force = 1; @@ -2004,8 +1986,6 @@ void ll_umount_begin(struct super_block *sb) * schedule() and sleep one second if needed, and hope. */ schedule(); - - EXIT; } int ll_remount_fs(struct super_block *sb, int *flags, char *data) diff --git a/drivers/staging/lustre/lustre/llite/llite_mmap.c b/drivers/staging/lustre/lustre/llite/llite_mmap.c index d98a40f61bfc..26a5247cbc29 100644 --- a/drivers/staging/lustre/lustre/llite/llite_mmap.c +++ b/drivers/staging/lustre/lustre/llite/llite_mmap.c @@ -249,7 +249,6 @@ static int ll_page_mkwrite0(struct vm_area_struct *vma, struct page *vmpage, spin_unlock(&lli->lli_lock); } } - EXIT; out_io: cl_io_fini(env, io); @@ -432,7 +431,6 @@ static void ll_vm_open(struct vm_area_struct * vma) LASSERT(vma->vm_file); LASSERT(atomic_read(&vob->cob_mmap_cnt) >= 0); atomic_inc(&vob->cob_mmap_cnt); - EXIT; } /** @@ -446,7 +444,6 @@ static void ll_vm_close(struct vm_area_struct *vma) LASSERT(vma->vm_file); atomic_dec(&vob->cob_mmap_cnt); LASSERT(atomic_read(&vob->cob_mmap_cnt) >= 0); - EXIT; } diff --git a/drivers/staging/lustre/lustre/llite/llite_nfs.c b/drivers/staging/lustre/lustre/llite/llite_nfs.c index d2661bb20db6..8b1a76da6c86 100644 --- a/drivers/staging/lustre/lustre/llite/llite_nfs.c +++ b/drivers/staging/lustre/lustre/llite/llite_nfs.c @@ -245,8 +245,6 @@ static int ll_get_name(struct dentry *dentry, char *name, mutex_unlock(&dir->i_mutex); if (!rc && !lgd.lgd_found) rc = -ENOENT; - EXIT; - out: return rc; } diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c index cc0d0a70bd1f..494561af27c7 100644 --- a/drivers/staging/lustre/lustre/llite/namei.c +++ b/drivers/staging/lustre/lustre/llite/namei.c @@ -714,7 +714,6 @@ static struct inode *ll_create_node(struct inode *dir, const char *name, CDEBUG(D_DLMTRACE, "setting l_ast_data to inode %p (%lu/%u)\n", inode, inode->i_ino, inode->i_generation); ll_set_lock_data(sbi->ll_md_exp, inode, it, NULL); - EXIT; out: ptlrpc_req_finished(request); return inode; @@ -814,7 +813,6 @@ static int ll_new_node(struct inode *dir, struct qstr *name, d_instantiate(dchild, inode); } - EXIT; err_exit: ptlrpc_req_finished(request); @@ -923,7 +921,6 @@ static int ll_link_generic(struct inode *src, struct inode *dir, ll_update_times(request, dir); ll_stats_ops_tally(sbi, LPROC_LL_LINK, 1); - EXIT; out: ptlrpc_req_finished(request); RETURN(err); diff --git a/drivers/staging/lustre/lustre/llite/rw.c b/drivers/staging/lustre/lustre/llite/rw.c index 41430004e270..b20f8b4635ce 100644 --- a/drivers/staging/lustre/lustre/llite/rw.c +++ b/drivers/staging/lustre/lustre/llite/rw.c @@ -1123,7 +1123,6 @@ void ras_update(struct ll_sb_info *sbi, struct inode *inode, if ((ras->ras_consecutive_requests > 1 || stride_detect) && !ras->ras_request_index) ras_increase_window(inode, ras, ra); - EXIT; out_unlock: RAS_CDEBUG(ras); ras->ras_request_index++; diff --git a/drivers/staging/lustre/lustre/llite/statahead.c b/drivers/staging/lustre/lustre/llite/statahead.c index 772e4ce31e6b..2fa29b3d94fa 100644 --- a/drivers/staging/lustre/lustre/llite/statahead.c +++ b/drivers/staging/lustre/lustre/llite/statahead.c @@ -547,8 +547,6 @@ static void ll_sai_put(struct ll_statahead_info *sai) iput(inode); OBD_FREE_PTR(sai); } - - EXIT; } /* Do NOT forget to drop inode refcount when into sai_entries_agl. */ @@ -609,8 +607,6 @@ static void ll_agl_trigger(struct inode *inode, struct ll_statahead_info *sai) PFID(&lli->lli_fid), index, rc); iput(inode); - - EXIT; } static void ll_post_statahead(struct ll_statahead_info *sai) @@ -685,8 +681,6 @@ static void ll_post_statahead(struct ll_statahead_info *sai) if (agl_should_run(sai, child)) ll_agl_add(sai, child, entry->se_index); - EXIT; - out: /* The "ll_sa_entry_to_stated()" will drop related ldlm ibits lock * reference count by calling "ll_intent_drop_lock()" in spite of the @@ -757,8 +751,6 @@ static int ll_statahead_interpret(struct ptlrpc_request *req, wake_up(&sai->sai_thread.t_ctl_waitq); } - EXIT; - out: if (rc != 0) { ll_intent_release(it); @@ -956,8 +948,6 @@ static void ll_statahead_one(struct dentry *parent, const char* entry_name, sai->sai_index++; /* drop one refcount on entry by ll_sa_entry_alloc */ ll_sa_entry_put(sai, entry); - - EXIT; } static int ll_agl_thread(void *arg) @@ -1044,7 +1034,6 @@ static void ll_start_agl(struct dentry *parent, struct ll_statahead_info *sai) l_wait_event(thread->t_ctl_waitq, thread_is_running(thread) || thread_is_stopped(thread), &lwi); - EXIT; } static int ll_statahead_thread(void *arg) @@ -1245,7 +1234,6 @@ do_it: */ } } - EXIT; out: if (sai->sai_agl_valid) { @@ -1455,7 +1443,6 @@ static int is_first_dirent(struct inode *dir, struct dentry *dentry) ll_release_page(page, 1); } } - EXIT; out: ll_dir_chain_fini(&chain); @@ -1502,8 +1489,6 @@ ll_sai_unplug(struct ll_statahead_info *sai, struct ll_sa_entry *entry) if (!thread_is_stopped(thread)) wake_up(&thread->t_ctl_waitq); - - EXIT; } /** diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c index 27ddadf7cca6..c5827b4e1665 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_io.c +++ b/drivers/staging/lustre/lustre/llite/vvp_io.c @@ -764,7 +764,6 @@ static int vvp_io_fault_start(const struct lu_env *env, lu_ref_add(&page->cp_reference, "fault", io); fio->ft_page = page; - EXIT; out: /* return unlocked vmpage to avoid deadlocking */ diff --git a/drivers/staging/lustre/lustre/llite/vvp_page.c b/drivers/staging/lustre/lustre/llite/vvp_page.c index 522632b525fb..78729190e74b 100644 --- a/drivers/staging/lustre/lustre/llite/vvp_page.c +++ b/drivers/staging/lustre/lustre/llite/vvp_page.c @@ -288,8 +288,6 @@ static void vvp_page_completion_read(const struct lu_env *env, if (page->cp_sync_io == NULL) unlock_page(vmpage); - - EXIT; } static void vvp_page_completion_write(const struct lu_env *env, @@ -326,7 +324,6 @@ static void vvp_page_completion_write(const struct lu_env *env, vvp_vmpage_error(ccc_object_inode(pg->cp_obj), vmpage, ioret); end_page_writeback(vmpage); - EXIT; } /** diff --git a/drivers/staging/lustre/lustre/llite/xattr.c b/drivers/staging/lustre/lustre/llite/xattr.c index c501ac934499..cf1bb4fc36e6 100644 --- a/drivers/staging/lustre/lustre/llite/xattr.c +++ b/drivers/staging/lustre/lustre/llite/xattr.c @@ -413,7 +413,6 @@ do_getxattr: memcpy(buffer, xdata, body->eadatasize); rc = body->eadatasize; } - EXIT; out: ptlrpc_req_finished(req); return rc; diff --git a/drivers/staging/lustre/lustre/lmv/lmv_intent.c b/drivers/staging/lustre/lustre/lmv/lmv_intent.c index 3d0d1acddb13..9d97b5b8a35b 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_intent.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_intent.c @@ -140,7 +140,6 @@ static int lmv_intent_remote(struct obd_export *exp, void *lmm, it->d.lustre.it_lock_handle = plock.cookie; it->d.lustre.it_lock_mode = pmode; - EXIT; out_free_op_data: OBD_FREE_PTR(op_data); out: diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 2970f584539d..48d80331f031 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -118,7 +118,6 @@ static int lmv_set_mdc_active(struct lmv_obd *lmv, struct obd_uuid *uuid, CDEBUG(D_INFO, "Marking OBD %p %sactive\n", obd, activate ? "" : "in"); lmv_activate_target(lmv, tgt, activate); - EXIT; out_lmv_lock: spin_unlock(&lmv->lmv_lock); @@ -1267,7 +1266,6 @@ int __lmv_fid_alloc(struct lmv_obd *lmv, struct lu_fid *fid, rc = 0; } - EXIT; out: mutex_unlock(&tgt->ltd_fid_mutex); return rc; @@ -1457,7 +1455,6 @@ static int lmv_statfs(const struct lu_env *env, struct obd_export *exp, } } - EXIT; out_free_temp: OBD_FREE(temp, sizeof(*temp)); return rc; @@ -1764,7 +1761,6 @@ lmv_enqueue_remote(struct obd_export *exp, struct ldlm_enqueue_info *einfo, rc = md_enqueue(tgt->ltd_exp, einfo, it, rdata, lockh, lmm, lmmsize, NULL, extra_lock_flags); OBD_FREE_PTR(rdata); - EXIT; out: ldlm_lock_decref(&plock, pmode); return rc; diff --git a/drivers/staging/lustre/lustre/lov/lov_dev.c b/drivers/staging/lustre/lustre/lov/lov_dev.c index 5d1b52284526..285164116c8a 100644 --- a/drivers/staging/lustre/lustre/lov/lov_dev.c +++ b/drivers/staging/lustre/lustre/lov/lov_dev.c @@ -124,7 +124,6 @@ static void lov_req_completion(const struct lu_env *env, lr = cl2lov_req(slice); OBD_SLAB_FREE_PTR(lr, lov_req_kmem); - EXIT; } static const struct cl_req_operations lov_req_ops = { @@ -314,7 +313,6 @@ static void lov_cl_del_target(const struct lu_env *env, struct lu_device *dev, cl_stack_fini(env, lovsub2cl_dev(ld->ld_target[index])); ld->ld_target[index] = NULL; } - EXIT; } static struct lov_device_emerg **lov_emerg_alloc(int nr) diff --git a/drivers/staging/lustre/lustre/lov/lov_io.c b/drivers/staging/lustre/lustre/lov/lov_io.c index 10e36c908443..8b978c36ab4c 100644 --- a/drivers/staging/lustre/lustre/lov/lov_io.c +++ b/drivers/staging/lustre/lustre/lov/lov_io.c @@ -78,7 +78,6 @@ static void lov_io_sub_fini(const struct lu_env *env, struct lov_io *lio, cl_env_put(sub->sub_env, &sub->sub_refcheck); sub->sub_env = NULL; } - EXIT; } static void lov_io_sub_inherit(struct cl_io *io, struct lov_io *lio, @@ -345,8 +344,6 @@ static void lov_io_slice_init(struct lov_io *lio, default: LBUG(); } - - EXIT; } static void lov_io_fini(const struct lu_env *env, const struct cl_io_slice *ios) @@ -366,7 +363,6 @@ static void lov_io_fini(const struct lu_env *env, const struct cl_io_slice *ios) LASSERT(atomic_read(&lov->lo_active_ios) > 0); if (atomic_dec_and_test(&lov->lo_active_ios)) wake_up_all(&lov->lo_waitq); - EXIT; } static obd_off lov_offset_mod(obd_off val, int delta) @@ -524,7 +520,6 @@ static void lov_io_iter_fini(const struct lu_env *env, LASSERT(rc == 0); while (!list_empty(&lio->lis_active)) list_del_init(lio->lis_active.next); - EXIT; } static void lov_io_unlock(const struct lu_env *env, @@ -534,7 +529,6 @@ static void lov_io_unlock(const struct lu_env *env, rc = lov_io_call(env, cl2lov_io(env, ios), lov_io_unlock_wrapper); LASSERT(rc == 0); - EXIT; } @@ -820,7 +814,6 @@ static void lov_empty_io_fini(const struct lu_env *env, if (atomic_dec_and_test(&lov->lo_active_ios)) wake_up_all(&lov->lo_waitq); - EXIT; } static void lov_empty_impossible(const struct lu_env *env, diff --git a/drivers/staging/lustre/lustre/lov/lov_lock.c b/drivers/staging/lustre/lustre/lov/lov_lock.c index 7cda7b6efc1e..757d6dec5245 100644 --- a/drivers/staging/lustre/lustre/lov/lov_lock.c +++ b/drivers/staging/lustre/lustre/lov/lov_lock.c @@ -131,7 +131,6 @@ static void lov_sublock_adopt(const struct lu_env *env, struct lov_lock *lck, rc = lov_sublock_modify(env, lck, lsl, &sublock->cll_descr, idx); LASSERT(rc == 0); /* there is no way this can fail, currently */ - EXIT; } static struct cl_lock *lov_sublock_alloc(const struct lu_env *env, @@ -188,7 +187,6 @@ static void lov_sublock_unlock(const struct lu_env *env, lov_sublock_env_put(subenv); lsl->lss_active = NULL; cl_lock_disclosure(env, closure); - EXIT; } static int lov_sublock_lock(const struct lu_env *env, @@ -458,7 +456,6 @@ static void lov_sublock_hold(const struct lu_env *env, struct lov_lock *lck, cl_lock_user_add(env, sublock); cl_lock_put(env, sublock); } - EXIT; } static void lov_lock_fini(const struct lu_env *env, @@ -480,7 +477,6 @@ static void lov_lock_fini(const struct lu_env *env, lck->lls_nr * sizeof lck->lls_sub[0]); } OBD_SLAB_FREE_PTR(lck, lov_lock_kmem); - EXIT; } static int lov_lock_enqueue_wait(const struct lu_env *env, @@ -1052,7 +1048,6 @@ void lov_lock_unlink(const struct lu_env *env, lu_ref_del(&parent->cll_reference, "lov-child", sub->lss_cl.cls_lock); cl_lock_put(env, parent); OBD_SLAB_FREE_PTR(link, lov_lock_link_kmem); - EXIT; } struct lov_lock_link *lov_lock_link_find(const struct lu_env *env, @@ -1123,7 +1118,6 @@ static void lov_lock_delete(const struct lu_env *env, } cl_lock_closure_fini(closure); - EXIT; } static int lov_lock_print(const struct lu_env *env, void *cookie, diff --git a/drivers/staging/lustre/lustre/lov/lov_object.c b/drivers/staging/lustre/lustre/lov/lov_object.c index 3bf8c0c08b6b..f869849135cf 100644 --- a/drivers/staging/lustre/lustre/lov/lov_object.c +++ b/drivers/staging/lustre/lustre/lov/lov_object.c @@ -374,8 +374,6 @@ static void lov_fini_raid0(const struct lu_env *env, struct lov_object *lov, dump_lsm(D_INODE, lov->lo_lsm); lov_free_memmd(&lov->lo_lsm); - - EXIT; } static void lov_fini_released(const struct lu_env *env, struct lov_object *lov, @@ -383,7 +381,6 @@ static void lov_fini_released(const struct lu_env *env, struct lov_object *lov, { dump_lsm(D_INODE, lov->lo_lsm); lov_free_memmd(&lov->lo_lsm); - EXIT; } static int lov_print_empty(const struct lu_env *env, void *cookie, @@ -767,7 +764,6 @@ static int lov_conf_set(const struct lu_env *env, struct cl_object *obj, } lov->lo_layout_invalid = lov_layout_change(env, lov, conf); - EXIT; out: lov_conf_unlock(lov); @@ -779,7 +775,6 @@ static void lov_object_delete(const struct lu_env *env, struct lu_object *obj) struct lov_object *lov = lu2lov(obj); LOV_2DISPATCH_VOID(lov, llo_delete, env, lov, &lov->u); - EXIT; } static void lov_object_free(const struct lu_env *env, struct lu_object *obj) @@ -789,7 +784,6 @@ static void lov_object_free(const struct lu_env *env, struct lu_object *obj) LOV_2DISPATCH_VOID(lov, llo_fini, env, lov, &lov->u); lu_object_fini(obj); OBD_SLAB_FREE_PTR(lov, lov_object_kmem); - EXIT; } static int lov_object_print(const struct lu_env *env, void *cookie, diff --git a/drivers/staging/lustre/lustre/lov/lov_page.c b/drivers/staging/lustre/lustre/lov/lov_page.c index f8b364f1e632..220e78f19ea7 100644 --- a/drivers/staging/lustre/lustre/lov/lov_page.c +++ b/drivers/staging/lustre/lustre/lov/lov_page.c @@ -77,7 +77,6 @@ static void lov_page_fini(const struct lu_env *env, slice->cpl_page->cp_child = NULL; cl_page_put(env, sub); } - EXIT; } static int lov_page_own(const struct lu_env *env, @@ -201,7 +200,6 @@ int lov_page_init_raid0(const struct lu_env *env, struct cl_object *obj, LASSERT(0); } - EXIT; out: return rc; } diff --git a/drivers/staging/lustre/lustre/lov/lov_pool.c b/drivers/staging/lustre/lustre/lov/lov_pool.c index 63b94661702e..e52f14c88f90 100644 --- a/drivers/staging/lustre/lustre/lov/lov_pool.c +++ b/drivers/staging/lustre/lustre/lov/lov_pool.c @@ -68,7 +68,6 @@ void lov_pool_putref(struct pool_desc *pool) lov_ost_pool_free(&(pool->pool_rr.lqr_pool)); lov_ost_pool_free(&(pool->pool_obds)); OBD_FREE_PTR(pool); - EXIT; } } @@ -333,7 +332,6 @@ int lov_ost_pool_init(struct ost_pool *op, unsigned int count) op->op_size = 0; RETURN(-ENOMEM); } - EXIT; return 0; } @@ -379,7 +377,6 @@ int lov_ost_pool_add(struct ost_pool *op, __u32 idx, unsigned int min_count) /* ost not found we add it */ op->op_array[op->op_count] = idx; op->op_count++; - EXIT; out: up_write(&op->op_rw_sem); return rc; @@ -397,7 +394,6 @@ int lov_ost_pool_remove(struct ost_pool *op, __u32 idx) (op->op_count - i - 1) * sizeof(op->op_array[0])); op->op_count--; up_write(&op->op_rw_sem); - EXIT; return 0; } } @@ -571,7 +567,6 @@ int lov_pool_add(struct obd_device *obd, char *poolname, char *ostname) CDEBUG(D_CONFIG, "Added %s to "LOV_POOLNAMEF" as member %d\n", ostname, poolname, pool_tgt_count(pool)); - EXIT; out: obd_putref(obd); lov_pool_putref(pool); @@ -616,7 +611,6 @@ int lov_pool_remove(struct obd_device *obd, char *poolname, char *ostname) CDEBUG(D_CONFIG, "%s removed from "LOV_POOLNAMEF"\n", ostname, poolname); - EXIT; out: obd_putref(obd); lov_pool_putref(pool); @@ -640,7 +634,6 @@ int lov_check_index_in_pool(__u32 idx, struct pool_desc *pool) GOTO(out, rc = 0); } rc = -ENOENT; - EXIT; out: up_read(&pool_tgt_rw_sem(pool)); diff --git a/drivers/staging/lustre/lustre/lov/lov_request.c b/drivers/staging/lustre/lustre/lov/lov_request.c index fc1cd898f5c9..d975fc550d85 100644 --- a/drivers/staging/lustre/lustre/lov/lov_request.c +++ b/drivers/staging/lustre/lustre/lov/lov_request.c @@ -86,7 +86,6 @@ void lov_finish_set(struct lov_request_set *set) lov_llh_put(set->set_lockh); OBD_FREE(set, sizeof(*set)); - EXIT; } int lov_set_finished(struct lov_request_set *set, int idempotent) diff --git a/drivers/staging/lustre/lustre/lov/lovsub_dev.c b/drivers/staging/lustre/lustre/lov/lovsub_dev.c index 05ad75e210d5..67cb287031fc 100644 --- a/drivers/staging/lustre/lustre/lov/lovsub_dev.c +++ b/drivers/staging/lustre/lustre/lov/lovsub_dev.c @@ -57,7 +57,6 @@ static void lovsub_req_completion(const struct lu_env *env, lsr = cl2lovsub_req(slice); OBD_SLAB_FREE_PTR(lsr, lovsub_req_kmem); - EXIT; } /** @@ -78,7 +77,6 @@ static void lovsub_req_attr_set(const struct lu_env *env, * unconditionally. It never changes anyway. */ attr->cra_oa->o_stripe_idx = subobj->lso_index; - EXIT; } static const struct cl_req_operations lovsub_req_ops = { diff --git a/drivers/staging/lustre/lustre/lov/lovsub_lock.c b/drivers/staging/lustre/lustre/lov/lovsub_lock.c index b73ad7a96669..9a6b8c851a08 100644 --- a/drivers/staging/lustre/lustre/lov/lovsub_lock.c +++ b/drivers/staging/lustre/lustre/lov/lovsub_lock.c @@ -60,7 +60,6 @@ static void lovsub_lock_fini(const struct lu_env *env, lsl = cl2lovsub_lock(slice); LASSERT(list_empty(&lsl->lss_parents)); OBD_SLAB_FREE_PTR(lsl, lovsub_lock_kmem); - EXIT; } static void lovsub_parent_lock(const struct lu_env *env, struct lov_lock *lov) @@ -71,7 +70,6 @@ static void lovsub_parent_lock(const struct lu_env *env, struct lov_lock *lov) cl_lock_get(parent); lu_ref_add(&parent->cll_reference, "lovsub-parent", current); cl_lock_mutex_get(env, parent); - EXIT; } static void lovsub_parent_unlock(const struct lu_env *env, struct lov_lock *lov) @@ -82,7 +80,6 @@ static void lovsub_parent_unlock(const struct lu_env *env, struct lov_lock *lov) cl_lock_mutex_put(env, lov->lls_cl.cls_lock); lu_ref_del(&parent->cll_reference, "lovsub-parent", current); cl_lock_put(env, parent); - EXIT; } /** @@ -109,7 +106,6 @@ static void lovsub_lock_state(const struct lu_env *env, lovsub_parent_unlock(env, lov); } } - EXIT; } /** @@ -177,7 +173,6 @@ static void lovsub_lock_descr_map(const struct cl_lock_descr *in, } out->cld_start = start; out->cld_end = end; - EXIT; } /** @@ -422,7 +417,6 @@ static void lovsub_lock_delete(const struct lu_env *env, } } } while (restart); - EXIT; } static int lovsub_lock_print(const struct lu_env *env, void *cookie, diff --git a/drivers/staging/lustre/lustre/lov/lovsub_object.c b/drivers/staging/lustre/lustre/lov/lovsub_object.c index 7264ba31b9e6..13938c41a728 100644 --- a/drivers/staging/lustre/lustre/lov/lovsub_object.c +++ b/drivers/staging/lustre/lustre/lov/lovsub_object.c @@ -92,7 +92,6 @@ static void lovsub_object_free(const struct lu_env *env, struct lu_object *obj) lu_object_fini(obj); lu_object_header_fini(&los->lso_header.coh_lu); OBD_SLAB_FREE_PTR(los, lovsub_object_kmem); - EXIT; } static int lovsub_object_print(const struct lu_env *env, void *cookie, diff --git a/drivers/staging/lustre/lustre/mdc/mdc_locks.c b/drivers/staging/lustre/lustre/mdc/mdc_locks.c index 9025075d105b..b818cd987fa9 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_locks.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_locks.c @@ -1167,7 +1167,6 @@ static int mdc_intent_getattr_async_interpret(const struct lu_env *env, GOTO(out, rc); rc = mdc_finish_intent_lock(exp, req, &minfo->mi_data, it, lockh); - EXIT; out: OBD_FREE_PTR(einfo); diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index f9e9184908ea..7da6eb8e8da5 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -139,7 +139,6 @@ static int send_getstatus(struct obd_import *imp, struct lu_fid *rootfid, "root fid="DFID", last_committed="LPU64"\n", PFID(rootfid), lustre_msg_get_last_committed(req->rq_repmsg)); - EXIT; out: ptlrpc_req_finished(req); return rc; @@ -597,7 +596,6 @@ int mdc_get_lustre_md(struct obd_export *exp, struct ptlrpc_request *req, md->oss_capa = oc; } - EXIT; out: if (rc) { if (md->oss_capa) { @@ -637,7 +635,6 @@ void mdc_replay_open(struct ptlrpc_request *req) if (mod == NULL) { DEBUG_REQ(D_ERROR, req, "Can't properly replay without open data."); - EXIT; return; } @@ -671,7 +668,6 @@ void mdc_replay_open(struct ptlrpc_request *req) DEBUG_REQ(D_HA, close_req, "updating close body with new fh"); epoch->handle = body->handle; } - EXIT; } void mdc_commit_open(struct ptlrpc_request *req) @@ -1096,7 +1092,6 @@ static int mdc_statfs(const struct lu_env *env, GOTO(out, rc = -EPROTO); *osfs = *msfs; - EXIT; out: ptlrpc_req_finished(req); output: @@ -1249,7 +1244,6 @@ static int mdc_ioc_hsm_current_action(struct obd_export *exp, *hca = *req_hca; - EXIT; out: ptlrpc_req_finished(req); return rc; @@ -1313,7 +1307,6 @@ static int mdc_ioc_hsm_state_get(struct obd_export *exp, *hus = *req_hus; - EXIT; out: ptlrpc_req_finished(req); return rc; @@ -1354,7 +1347,6 @@ static int mdc_ioc_hsm_state_set(struct obd_export *exp, rc = mdc_queue_wait(req); GOTO(out, rc); - EXIT; out: ptlrpc_req_finished(req); return rc; @@ -1702,7 +1694,6 @@ static int mdc_ioc_swap_layouts(struct obd_export *exp, rc = ptlrpc_queue_wait(req); if (rc) GOTO(out, rc); - EXIT; out: ptlrpc_req_finished(req); @@ -2558,7 +2549,6 @@ static int mdc_interpret_renew_capa(const struct lu_env *env, capa = req_capsule_server_get(&req->rq_pill, &RMF_CAPA2); if (!capa) GOTO(out, capa = ERR_PTR(-EFAULT)); - EXIT; out: ra->ra_cb(ra->ra_oc, capa); return 0; diff --git a/drivers/staging/lustre/lustre/mgc/mgc_request.c b/drivers/staging/lustre/lustre/mgc/mgc_request.c index 6512b7f4d3dc..99a4099e2e0f 100644 --- a/drivers/staging/lustre/lustre/mgc/mgc_request.c +++ b/drivers/staging/lustre/lustre/mgc/mgc_request.c @@ -149,8 +149,6 @@ static void config_log_put(struct config_llog_data *cld) class_export_put(cld->cld_mgcexp); OBD_FREE(cld, sizeof(*cld) + strlen(cld->cld_logname) + 1); } - - EXIT; } /* Find a config log by name */ @@ -451,8 +449,6 @@ static void do_requeue(struct config_llog_data *cld) cld->cld_logname); } up_read(&cld->cld_mgcexp->exp_obd->u.cli.cl_sem); - - EXIT; } /* this timeout represents how many seconds MGC should wait before @@ -579,7 +575,6 @@ static void mgc_requeue_add(struct config_llog_data *cld) spin_unlock(&config_list_lock); wake_up(&rq_waitq); } - EXIT; } /********************** class fns **********************/ @@ -1596,7 +1591,6 @@ static int mgc_process_cfg_log(struct obd_device *mgc, be updated here. */ rc = class_config_parse_llog(NULL, ctxt, cld->cld_logname, &cld->cld_cfg); - EXIT; out_pop: llog_ctxt_put(ctxt); diff --git a/drivers/staging/lustre/lustre/obdclass/acl.c b/drivers/staging/lustre/lustre/obdclass/acl.c index 66fdd661cafc..33bdf279868a 100644 --- a/drivers/staging/lustre/lustre/obdclass/acl.c +++ b/drivers/staging/lustre/lustre/obdclass/acl.c @@ -226,7 +226,6 @@ int lustre_posix_acl_xattr_filter(posix_acl_xattr_header *header, int size, *out = new; rc = 0; } - EXIT; _out: if (rc) { @@ -394,7 +393,6 @@ int lustre_acl_xattr_merge2posix(posix_acl_xattr_header *posix_header, int size, *out = new; rc = 0; } - EXIT; _out: if (rc) { @@ -528,7 +526,6 @@ lustre_acl_xattr_merge2ext(posix_acl_xattr_header *posix_header, int size, new->a_count = cpu_to_le32(j); /* free unused space. */ rc = lustre_ext_acl_xattr_reduce_space(&new, ext_count); - EXIT; out: if (rc) { diff --git a/drivers/staging/lustre/lustre/obdclass/capa.c b/drivers/staging/lustre/lustre/obdclass/capa.c index 60eb94d48ea8..9c5a05b1c507 100644 --- a/drivers/staging/lustre/lustre/obdclass/capa.c +++ b/drivers/staging/lustre/lustre/obdclass/capa.c @@ -311,8 +311,6 @@ int capa_encrypt_id(__u32 *d, __u32 *s, __u8 *key, int keylen) GOTO(out, rc); } - EXIT; - out: ll_crypto_free_blkcipher(tfm); return rc; @@ -364,8 +362,6 @@ int capa_decrypt_id(__u32 *d, __u32 *s, __u8 *key, int keylen) GOTO(out, rc); } - EXIT; - out: ll_crypto_free_blkcipher(tfm); return rc; diff --git a/drivers/staging/lustre/lustre/obdclass/cl_io.c b/drivers/staging/lustre/lustre/obdclass/cl_io.c index 96a299b4fb91..d5b0bb8bed82 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_io.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_io.c @@ -143,7 +143,6 @@ void cl_io_fini(const struct lu_env *env, struct cl_io *io) default: LBUG(); } - EXIT; } EXPORT_SYMBOL(cl_io_fini); @@ -321,7 +320,6 @@ static void cl_io_locks_sort(struct cl_io *io) prev = curr; } } while (!done); - EXIT; } /** @@ -411,7 +409,6 @@ static void cl_lock_link_fini(const struct lu_env *env, struct cl_io *io, } if (link->cill_fini != NULL) link->cill_fini(env, link); - EXIT; } static int cl_lockset_lock(const struct lu_env *env, struct cl_io *io, @@ -515,7 +512,6 @@ void cl_io_unlock(const struct lu_env *env, struct cl_io *io) } io->ci_state = CIS_UNLOCKED; LASSERT(!cl_env_info(env)->clt_counters[CNL_TOP].ctc_nr_locks_acquired); - EXIT; } EXPORT_SYMBOL(cl_io_unlock); @@ -568,7 +564,6 @@ void cl_io_iter_fini(const struct lu_env *env, struct cl_io *io) scan->cis_iop->op[io->ci_type].cio_iter_fini(env, scan); } io->ci_state = CIS_IT_ENDED; - EXIT; } EXPORT_SYMBOL(cl_io_iter_fini); @@ -593,7 +588,6 @@ void cl_io_rw_advance(const struct lu_env *env, struct cl_io *io, size_t nob) scan->cis_iop->op[io->ci_type].cio_advance(env, scan, nob); } - EXIT; } EXPORT_SYMBOL(cl_io_rw_advance); @@ -688,7 +682,6 @@ void cl_io_end(const struct lu_env *env, struct cl_io *io) /* TODO: error handling. */ } io->ci_state = CIS_IO_FINISHED; - EXIT; } EXPORT_SYMBOL(cl_io_end); @@ -1044,7 +1037,6 @@ void cl_io_slice_add(struct cl_io *io, struct cl_io_slice *slice, slice->cis_io = io; slice->cis_obj = obj; slice->cis_iop = ops; - EXIT; } EXPORT_SYMBOL(cl_io_slice_add); @@ -1057,7 +1049,6 @@ void cl_page_list_init(struct cl_page_list *plist) plist->pl_nr = 0; INIT_LIST_HEAD(&plist->pl_pages); plist->pl_owner = current; - EXIT; } EXPORT_SYMBOL(cl_page_list_init); @@ -1079,7 +1070,6 @@ void cl_page_list_add(struct cl_page_list *plist, struct cl_page *page) ++plist->pl_nr; lu_ref_add_at(&page->cp_reference, &page->cp_queue_ref, "queue", plist); cl_page_get(page); - EXIT; } EXPORT_SYMBOL(cl_page_list_add); @@ -1099,7 +1089,6 @@ void cl_page_list_del(const struct lu_env *env, --plist->pl_nr; lu_ref_del_at(&page->cp_reference, &page->cp_queue_ref, "queue", plist); cl_page_put(env, page); - EXIT; } EXPORT_SYMBOL(cl_page_list_del); @@ -1118,7 +1107,6 @@ void cl_page_list_move(struct cl_page_list *dst, struct cl_page_list *src, ++dst->pl_nr; lu_ref_set_at(&page->cp_reference, &page->cp_queue_ref, "queue", src, dst); - EXIT; } EXPORT_SYMBOL(cl_page_list_move); @@ -1135,7 +1123,6 @@ void cl_page_list_splice(struct cl_page_list *list, struct cl_page_list *head) cl_page_list_for_each_safe(page, tmp, list) cl_page_list_move(head, list, page); - EXIT; } EXPORT_SYMBOL(cl_page_list_splice); @@ -1174,7 +1161,6 @@ void cl_page_list_disown(const struct lu_env *env, plist); cl_page_put(env, page); } - EXIT; } EXPORT_SYMBOL(cl_page_list_disown); @@ -1191,7 +1177,6 @@ void cl_page_list_fini(const struct lu_env *env, struct cl_page_list *plist) cl_page_list_for_each_safe(page, temp, plist) cl_page_list_del(env, plist, page); LASSERT(plist->pl_nr == 0); - EXIT; } EXPORT_SYMBOL(cl_page_list_fini); @@ -1247,7 +1232,6 @@ void cl_page_list_discard(const struct lu_env *env, struct cl_io *io, LINVRNT(plist->pl_owner == current); cl_page_list_for_each(page, plist) cl_page_discard(env, io, page); - EXIT; } EXPORT_SYMBOL(cl_page_list_discard); @@ -1278,7 +1262,6 @@ void cl_2queue_init(struct cl_2queue *queue) { cl_page_list_init(&queue->c2_qin); cl_page_list_init(&queue->c2_qout); - EXIT; } EXPORT_SYMBOL(cl_2queue_init); @@ -1288,7 +1271,6 @@ EXPORT_SYMBOL(cl_2queue_init); void cl_2queue_add(struct cl_2queue *queue, struct cl_page *page) { cl_page_list_add(&queue->c2_qin, page); - EXIT; } EXPORT_SYMBOL(cl_2queue_add); @@ -1300,7 +1282,6 @@ void cl_2queue_disown(const struct lu_env *env, { cl_page_list_disown(env, io, &queue->c2_qin); cl_page_list_disown(env, io, &queue->c2_qout); - EXIT; } EXPORT_SYMBOL(cl_2queue_disown); @@ -1312,7 +1293,6 @@ void cl_2queue_discard(const struct lu_env *env, { cl_page_list_discard(env, io, &queue->c2_qin); cl_page_list_discard(env, io, &queue->c2_qout); - EXIT; } EXPORT_SYMBOL(cl_2queue_discard); @@ -1334,7 +1314,6 @@ void cl_2queue_fini(const struct lu_env *env, struct cl_2queue *queue) { cl_page_list_fini(env, &queue->c2_qout); cl_page_list_fini(env, &queue->c2_qin); - EXIT; } EXPORT_SYMBOL(cl_2queue_fini); @@ -1345,7 +1324,6 @@ void cl_2queue_init_page(struct cl_2queue *queue, struct cl_page *page) { cl_2queue_init(queue); cl_2queue_add(queue, page); - EXIT; } EXPORT_SYMBOL(cl_2queue_init_page); @@ -1387,7 +1365,6 @@ void cl_req_slice_add(struct cl_req *req, struct cl_req_slice *slice, slice->crs_dev = dev; slice->crs_ops = ops; slice->crs_req = req; - EXIT; } EXPORT_SYMBOL(cl_req_slice_add); @@ -1413,7 +1390,6 @@ static void cl_req_free(const struct lu_env *env, struct cl_req *req) OBD_FREE(req->crq_o, req->crq_nrobjs * sizeof req->crq_o[0]); } OBD_FREE_PTR(req); - EXIT; } static int cl_req_init(const struct lu_env *env, struct cl_req *req, @@ -1459,7 +1435,6 @@ void cl_req_completion(const struct lu_env *env, struct cl_req *req, int rc) slice->crs_ops->cro_completion(env, slice, rc); } cl_req_free(env, req); - EXIT; } EXPORT_SYMBOL(cl_req_completion); @@ -1528,7 +1503,6 @@ void cl_req_page_add(const struct lu_env *env, } } LASSERT(i < req->crq_nrobjs); - EXIT; } EXPORT_SYMBOL(cl_req_page_add); @@ -1547,7 +1521,6 @@ void cl_req_page_done(const struct lu_env *env, struct cl_page *page) list_del_init(&page->cp_flight); --req->crq_nrpages; page->cp_req = NULL; - EXIT; } EXPORT_SYMBOL(cl_req_page_done); @@ -1611,7 +1584,6 @@ void cl_req_attr_set(const struct lu_env *env, struct cl_req *req, attr + i, flags); } } - EXIT; } EXPORT_SYMBOL(cl_req_attr_set); @@ -1628,7 +1600,6 @@ void cl_sync_io_init(struct cl_sync_io *anchor, int nrpages) atomic_set(&anchor->csi_sync_nr, nrpages); atomic_set(&anchor->csi_barrier, nrpages > 0); anchor->csi_sync_rc = 0; - EXIT; } EXPORT_SYMBOL(cl_sync_io_init); @@ -1694,6 +1665,5 @@ void cl_sync_io_note(struct cl_sync_io *anchor, int ioret) /* it's safe to nuke or reuse anchor now */ atomic_set(&anchor->csi_barrier, 0); } - EXIT; } EXPORT_SYMBOL(cl_sync_io_note); diff --git a/drivers/staging/lustre/lustre/obdclass/cl_lock.c b/drivers/staging/lustre/lustre/obdclass/cl_lock.c index adcf78954117..581e7da07bc5 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_lock.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_lock.c @@ -195,7 +195,6 @@ void cl_lock_slice_add(struct cl_lock *lock, struct cl_lock_slice *slice, list_add_tail(&slice->cls_linkage, &lock->cll_layers); slice->cls_obj = obj; slice->cls_ops = ops; - EXIT; } EXPORT_SYMBOL(cl_lock_slice_add); @@ -271,7 +270,6 @@ static void cl_lock_free(const struct lu_env *env, struct cl_lock *lock) lu_ref_fini(&lock->cll_holders); mutex_destroy(&lock->cll_guard); OBD_SLAB_FREE_PTR(lock, cl_lock_kmem); - EXIT; } /** @@ -301,7 +299,6 @@ void cl_lock_put(const struct lu_env *env, struct cl_lock *lock) } CS_LOCK_DEC(obj, busy); } - EXIT; } EXPORT_SYMBOL(cl_lock_put); @@ -783,7 +780,6 @@ static void cl_lock_cancel0(const struct lu_env *env, struct cl_lock *lock) slice->cls_ops->clo_cancel(env, slice); } } - EXIT; } static void cl_lock_delete0(const struct lu_env *env, struct cl_lock *lock) @@ -823,7 +819,6 @@ static void cl_lock_delete0(const struct lu_env *env, struct cl_lock *lock) * existing references goes away. */ } - EXIT; } /** @@ -896,7 +891,6 @@ void cl_lock_hold_release(const struct lu_env *env, struct cl_lock *lock, cl_lock_delete0(env, lock); } } - EXIT; } EXPORT_SYMBOL(cl_lock_hold_release); @@ -977,7 +971,6 @@ static void cl_lock_state_signal(const struct lu_env *env, struct cl_lock *lock, if (slice->cls_ops->clo_state != NULL) slice->cls_ops->clo_state(env, slice, state); wake_up_all(&lock->cll_wq); - EXIT; } /** @@ -991,7 +984,6 @@ void cl_lock_signal(const struct lu_env *env, struct cl_lock *lock) { cl_lock_trace(D_DLMTRACE, env, "state signal lock", lock); cl_lock_state_signal(env, lock, lock->cll_state); - EXIT; } EXPORT_SYMBOL(cl_lock_signal); @@ -1023,7 +1015,6 @@ void cl_lock_state_set(const struct lu_env *env, struct cl_lock *lock, cl_lock_state_signal(env, lock, state); lock->cll_state = state; } - EXIT; } EXPORT_SYMBOL(cl_lock_state_set); @@ -1388,8 +1379,6 @@ static void cl_unuse_locked(const struct lu_env *env, struct cl_lock *lock) result = cl_unuse_try(env, lock); if (result) CL_LOCK_DEBUG(D_ERROR, env, lock, "unuse return %d\n", result); - - EXIT; } /** @@ -1401,7 +1390,6 @@ void cl_unuse(const struct lu_env *env, struct cl_lock *lock) cl_unuse_locked(env, lock); cl_lock_mutex_put(env, lock); cl_lock_lockdep_release(env, lock); - EXIT; } EXPORT_SYMBOL(cl_unuse); @@ -1737,7 +1725,6 @@ void cl_lock_delete(const struct lu_env *env, struct cl_lock *lock) cl_lock_delete0(env, lock); else lock->cll_flags |= CLF_DOOMED; - EXIT; } EXPORT_SYMBOL(cl_lock_delete); @@ -1763,7 +1750,6 @@ void cl_lock_error(const struct lu_env *env, struct cl_lock *lock, int error) cl_lock_cancel(env, lock); cl_lock_delete(env, lock); } - EXIT; } EXPORT_SYMBOL(cl_lock_error); @@ -1788,7 +1774,6 @@ void cl_lock_cancel(const struct lu_env *env, struct cl_lock *lock) cl_lock_cancel0(env, lock); else lock->cll_flags |= CLF_CANCELPEND; - EXIT; } EXPORT_SYMBOL(cl_lock_cancel); @@ -2018,7 +2003,6 @@ again: spin_lock(&head->coh_lock_guard); } spin_unlock(&head->coh_lock_guard); - EXIT; } EXPORT_SYMBOL(cl_locks_prune); @@ -2128,7 +2112,6 @@ void cl_lock_hold_add(const struct lu_env *env, struct cl_lock *lock, cl_lock_get(lock); lu_ref_add(&lock->cll_holders, scope, source); lu_ref_add(&lock->cll_reference, scope, source); - EXIT; } EXPORT_SYMBOL(cl_lock_hold_add); @@ -2143,7 +2126,6 @@ void cl_lock_unhold(const struct lu_env *env, struct cl_lock *lock, cl_lock_hold_release(env, lock, scope, source); lu_ref_del(&lock->cll_reference, scope, source); cl_lock_put(env, lock); - EXIT; } EXPORT_SYMBOL(cl_lock_unhold); @@ -2160,7 +2142,6 @@ void cl_lock_release(const struct lu_env *env, struct cl_lock *lock, cl_lock_mutex_put(env, lock); lu_ref_del(&lock->cll_reference, scope, source); cl_lock_put(env, lock); - EXIT; } EXPORT_SYMBOL(cl_lock_release); @@ -2170,7 +2151,6 @@ void cl_lock_user_add(const struct lu_env *env, struct cl_lock *lock) LINVRNT(cl_lock_invariant(env, lock)); cl_lock_used_mod(env, lock, +1); - EXIT; } EXPORT_SYMBOL(cl_lock_user_add); @@ -2183,7 +2163,6 @@ void cl_lock_user_del(const struct lu_env *env, struct cl_lock *lock) cl_lock_used_mod(env, lock, -1); if (lock->cll_users == 0) wake_up_all(&lock->cll_wq); - EXIT; } EXPORT_SYMBOL(cl_lock_user_del); diff --git a/drivers/staging/lustre/lustre/obdclass/cl_object.c b/drivers/staging/lustre/lustre/obdclass/cl_object.c index 2abc4b5ddb37..ea1758065c62 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_object.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_object.c @@ -359,7 +359,6 @@ void cl_object_prune(const struct lu_env *env, struct cl_object *obj) { cl_pages_prune(env, obj); cl_locks_prune(env, obj, 1); - EXIT; } EXPORT_SYMBOL(cl_object_prune); @@ -940,7 +939,6 @@ void cl_attr2lvb(struct ost_lvb *lvb, const struct cl_attr *attr) lvb->lvb_atime = attr->cat_atime; lvb->lvb_ctime = attr->cat_ctime; lvb->lvb_blocks = attr->cat_blocks; - EXIT; } EXPORT_SYMBOL(cl_attr2lvb); @@ -956,7 +954,6 @@ void cl_lvb2attr(struct cl_attr *attr, const struct ost_lvb *lvb) attr->cat_atime = lvb->lvb_atime; attr->cat_ctime = lvb->lvb_ctime; attr->cat_blocks = lvb->lvb_blocks; - EXIT; } EXPORT_SYMBOL(cl_lvb2attr); diff --git a/drivers/staging/lustre/lustre/obdclass/cl_page.c b/drivers/staging/lustre/lustre/obdclass/cl_page.c index 3c6cf202bbd9..028c72028fd5 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_page.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_page.c @@ -271,7 +271,6 @@ static void cl_page_free(const struct lu_env *env, struct cl_page *page) cl_object_put(env, obj); lu_ref_fini(&page->cp_reference); OBD_FREE(page, pagesize); - EXIT; } /** @@ -560,7 +559,6 @@ static void cl_page_state_set0(const struct lu_env *env, CS_PAGESTATE_INC(page->cp_obj, state); cl_page_state_set_trust(page, state); } - EXIT; } static void cl_page_state_set(const struct lu_env *env, @@ -580,7 +578,6 @@ static void cl_page_state_set(const struct lu_env *env, void cl_page_get(struct cl_page *page) { cl_page_get_trust(page); - EXIT; } EXPORT_SYMBOL(cl_page_get); @@ -612,8 +609,6 @@ void cl_page_put(const struct lu_env *env, struct cl_page *page) */ cl_page_free(env, page); } - - EXIT; } EXPORT_SYMBOL(cl_page_put); @@ -790,7 +785,6 @@ static void cl_page_invoid(const struct lu_env *env, CL_PAGE_INVOID(env, page, op, (const struct lu_env *, const struct cl_page_slice *, struct cl_io *), io); - EXIT; } static void cl_page_owner_clear(struct cl_page *page) @@ -803,7 +797,6 @@ static void cl_page_owner_clear(struct cl_page *page) page->cp_task = NULL; } } - EXIT; } static void cl_page_owner_set(struct cl_page *page) @@ -812,7 +805,6 @@ static void cl_page_owner_set(struct cl_page *page) LASSERT(page->cp_owner != NULL); page->cp_owner->ci_owned_nr++; } - EXIT; } void cl_page_disown0(const struct lu_env *env, @@ -836,7 +828,6 @@ void cl_page_disown0(const struct lu_env *env, (const struct lu_env *, const struct cl_page_slice *, struct cl_io *), io); - EXIT; } /** @@ -953,7 +944,6 @@ void cl_page_assume(const struct lu_env *env, pg->cp_task = current; cl_page_owner_set(pg); cl_page_state_set(env, pg, CPS_OWNED); - EXIT; } EXPORT_SYMBOL(cl_page_assume); @@ -982,7 +972,6 @@ void cl_page_unassume(const struct lu_env *env, (const struct lu_env *, const struct cl_page_slice *, struct cl_io *), io); - EXIT; } EXPORT_SYMBOL(cl_page_unassume); @@ -1005,7 +994,6 @@ void cl_page_disown(const struct lu_env *env, pg = cl_page_top(pg); io = cl_io_top(io); cl_page_disown0(env, io, pg); - EXIT; } EXPORT_SYMBOL(cl_page_disown); @@ -1082,8 +1070,6 @@ static void cl_page_delete0(const struct lu_env *env, struct cl_page *pg, cl_page_put(env, tmp); } } - - EXIT; } /** @@ -1115,7 +1101,6 @@ void cl_page_delete(const struct lu_env *env, struct cl_page *pg) { PINVRNT(env, pg, cl_page_invariant(pg)); cl_page_delete0(env, pg, 1); - EXIT; } EXPORT_SYMBOL(cl_page_delete); @@ -1193,7 +1178,6 @@ static void cl_page_io_start(const struct lu_env *env, */ cl_page_owner_clear(pg); cl_page_state_set(env, pg, cl_req_type_state(crt)); - EXIT; } /** @@ -1282,8 +1266,6 @@ void cl_page_completion(const struct lu_env *env, if (anchor) cl_sync_io_note(anchor, ioret); - - EXIT; } EXPORT_SYMBOL(cl_page_completion); @@ -1558,7 +1540,6 @@ void cl_page_slice_add(struct cl_page *page, struct cl_page_slice *slice, slice->cpl_obj = obj; slice->cpl_ops = ops; slice->cpl_page = page; - EXIT; } EXPORT_SYMBOL(cl_page_slice_add); diff --git a/drivers/staging/lustre/lustre/obdclass/class_obd.c b/drivers/staging/lustre/lustre/obdclass/class_obd.c index 07d7d2e7c543..09933b2f2aff 100644 --- a/drivers/staging/lustre/lustre/obdclass/class_obd.c +++ b/drivers/staging/lustre/lustre/obdclass/class_obd.c @@ -675,8 +675,6 @@ static void cleanup_obdclass(void) CDEBUG((pages_leaked) ? D_ERROR : D_INFO, "obd_memory_pages max: "LPU64", leaked: "LPU64"\n", pages_max, pages_leaked); - - EXIT; } MODULE_AUTHOR("Sun Microsystems, Inc. "); diff --git a/drivers/staging/lustre/lustre/obdclass/genops.c b/drivers/staging/lustre/lustre/obdclass/genops.c index b2ec1067a29d..c9180656dfd4 100644 --- a/drivers/staging/lustre/lustre/obdclass/genops.c +++ b/drivers/staging/lustre/lustre/obdclass/genops.c @@ -648,7 +648,6 @@ void obd_cleanup_caches(void) kmem_cache_destroy(capa_cachep); capa_cachep = NULL; } - EXIT; } int obd_init_caches(void) @@ -769,7 +768,6 @@ static void class_export_destroy(struct obd_export *exp) class_decref(obd, "export", exp); OBD_FREE_RCU(exp, sizeof(*exp), &exp->exp_handle); - EXIT; } static void export_handle_addref(void *export) @@ -947,7 +945,6 @@ void class_import_destroy(struct obd_import *imp) LASSERT(imp->imp_sec == NULL); class_decref(imp->imp_obd, "import", imp); OBD_FREE_RCU(imp, sizeof(*imp), &imp->imp_handle); - EXIT; } static void import_handle_addref(void *import) @@ -986,7 +983,6 @@ void class_import_put(struct obd_import *imp) /* catch possible import put race */ LASSERT_ATOMIC_GE_LT(&imp->imp_refcount, 0, LI_POISON); - EXIT; } EXPORT_SYMBOL(class_import_put); @@ -1265,7 +1261,6 @@ static void class_disconnect_export_list(struct list_head *list, obd_export_nid2str(exp), exp, rc); class_export_put(exp); } - EXIT; } void class_disconnect_exports(struct obd_device *obd) @@ -1287,7 +1282,6 @@ void class_disconnect_exports(struct obd_device *obd) } else CDEBUG(D_HA, "OBD device %d (%p) has no exports\n", obd->obd_minor, obd); - EXIT; } EXPORT_SYMBOL(class_disconnect_exports); @@ -1338,7 +1332,6 @@ void class_disconnect_stale_exports(struct obd_device *obd, class_disconnect_export_list(&work_list, exp_flags_from_obd(obd) | OBD_OPT_ABORT_RECOV); - EXIT; } EXPORT_SYMBOL(class_disconnect_stale_exports); @@ -1605,7 +1598,6 @@ void obd_zombie_impexp_cull(void) cond_resched(); } while (import != NULL || export != NULL); - EXIT; } static struct completion obd_zombie_start; diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c index a3cb92f6ae9c..95de95e628be 100644 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c +++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c @@ -149,7 +149,6 @@ int obd_ioctl_getdata(char **buf, int *len, void *arg) data->ioc_inlbuf4 = &data->ioc_bulk[0] + offset; } - EXIT; return 0; } EXPORT_SYMBOL(obd_ioctl_getdata); diff --git a/drivers/staging/lustre/lustre/obdclass/llog_cat.c b/drivers/staging/lustre/lustre/obdclass/llog_cat.c index 08b950802ae7..020af54e68af 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog_cat.c +++ b/drivers/staging/lustre/lustre/obdclass/llog_cat.c @@ -202,7 +202,6 @@ int llog_cat_id2handle(const struct lu_env *env, struct llog_handle *cathandle, loghandle->u.phd.phd_cookie.lgc_lgl = cathandle->lgh_id; loghandle->u.phd.phd_cookie.lgc_index = loghandle->lgh_hdr->llh_cat_idx; - EXIT; out: llog_handle_get(loghandle); *res = loghandle; diff --git a/drivers/staging/lustre/lustre/obdclass/llog_osd.c b/drivers/staging/lustre/lustre/obdclass/llog_osd.c index 5569d8d55e00..7ab6f59c0dc5 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog_osd.c +++ b/drivers/staging/lustre/lustre/obdclass/llog_osd.c @@ -1221,7 +1221,6 @@ out_trans: GOTO(out, rc); } - EXIT; out: lu_object_put(env, &o->do_lu); RETURN(rc); diff --git a/drivers/staging/lustre/lustre/obdclass/llog_swab.c b/drivers/staging/lustre/lustre/obdclass/llog_swab.c index 5cf15d20bb1f..24ca099b01da 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog_swab.c +++ b/drivers/staging/lustre/lustre/obdclass/llog_swab.c @@ -97,7 +97,6 @@ void lustre_swab_llogd_body (struct llogd_body *d) __swab32s (&d->lgd_len); __swab64s (&d->lgd_cur_offset); print_llogd_body(d); - EXIT; } EXPORT_SYMBOL(lustre_swab_llogd_body); @@ -302,7 +301,6 @@ void lustre_swab_llog_hdr (struct llog_log_hdr *h) lustre_swab_llog_rec(&h->llh_hdr); print_llog_hdr(h); - EXIT; } EXPORT_SYMBOL(lustre_swab_llog_hdr); @@ -325,7 +323,6 @@ static void print_lustre_cfg(struct lustre_cfg *lcfg) for (i = 0; i < lcfg->lcfg_bufcount; i++) CDEBUG(D_OTHER, "\tlcfg->lcfg_buflens[%d]: %d\n", i, lcfg->lcfg_buflens[i]); - EXIT; } void lustre_swab_lustre_cfg(struct lustre_cfg *lcfg) @@ -337,7 +334,6 @@ void lustre_swab_lustre_cfg(struct lustre_cfg *lcfg) if (lcfg->lcfg_version != LUSTRE_CFG_VERSION) { CERROR("not swabbing lustre_cfg version %#x (expecting %#x)\n", lcfg->lcfg_version, LUSTRE_CFG_VERSION); - EXIT; return; } @@ -350,7 +346,6 @@ void lustre_swab_lustre_cfg(struct lustre_cfg *lcfg) __swab32s(&lcfg->lcfg_buflens[i]); print_lustre_cfg(lcfg); - EXIT; return; } EXPORT_SYMBOL(lustre_swab_lustre_cfg); @@ -413,7 +408,6 @@ void lustre_swab_cfg_marker(struct cfg_marker *marker, int swab, int size) __swab64s(&marker->cm_canceltime); } - EXIT; return; } EXPORT_SYMBOL(lustre_swab_cfg_marker); diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c index 090b669c35d1..eaf45cb07b32 100644 --- a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c +++ b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c @@ -910,7 +910,6 @@ void lprocfs_free_per_client_stats(struct obd_device *obd) cfs_hash_del(hash, &stat->nid, &stat->nid_hash); lprocfs_free_client_stats(stat); } - EXIT; } EXPORT_SYMBOL(lprocfs_free_per_client_stats); diff --git a/drivers/staging/lustre/lustre/obdclass/lustre_handles.c b/drivers/staging/lustre/lustre/obdclass/lustre_handles.c index de80aea70721..a748d8e70ec9 100644 --- a/drivers/staging/lustre/lustre/obdclass/lustre_handles.c +++ b/drivers/staging/lustre/lustre/obdclass/lustre_handles.c @@ -99,7 +99,6 @@ void class_handle_hash(struct portals_handle *h, CDEBUG(D_INFO, "added object %p with handle "LPX64" to hash\n", h, h->h_cookie); - EXIT; } EXPORT_SYMBOL(class_handle_hash); @@ -145,8 +144,6 @@ void class_handle_hash_back(struct portals_handle *h) list_add_rcu(&h->h_link, &bucket->head); h->h_in = 1; spin_unlock(&bucket->lock); - - EXIT; } EXPORT_SYMBOL(class_handle_hash_back); diff --git a/drivers/staging/lustre/lustre/obdclass/obd_config.c b/drivers/staging/lustre/lustre/obdclass/obd_config.c index 278e7d2e103f..6981f3ce63f3 100644 --- a/drivers/staging/lustre/lustre/obdclass/obd_config.c +++ b/drivers/staging/lustre/lustre/obdclass/obd_config.c @@ -902,7 +902,6 @@ void class_del_profile(const char *prof) OBD_FREE(lprof->lp_md, strlen(lprof->lp_md) + 1); OBD_FREE(lprof, sizeof *lprof); } - EXIT; } EXPORT_SYMBOL(class_del_profile); @@ -919,7 +918,6 @@ void class_del_profiles(void) OBD_FREE(lprof->lp_md, strlen(lprof->lp_md) + 1); OBD_FREE(lprof, sizeof *lprof); } - EXIT; } EXPORT_SYMBOL(class_del_profiles); diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c index 6fc0396f6cbb..80e3a951b95a 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c @@ -316,7 +316,6 @@ static void echo_page_fini(const struct lu_env *env, atomic_dec(&eco->eo_npages); page_cache_release(vmpage); - EXIT; } static int echo_page_prep(const struct lu_env *env, @@ -565,7 +564,6 @@ static void echo_object_free(const struct lu_env *env, struct lu_object *obj) if (eco->eo_lsm) echo_free_memmd(eco->eo_dev, &eco->eo_lsm); OBD_SLAB_FREE_PTR(eco, echo_object_kmem); - EXIT; } static int echo_object_print(const struct lu_env *env, void *cookie, @@ -1214,7 +1212,6 @@ static int cl_echo_enqueue(struct echo_object *eco, obd_off start, obd_off end, result = cl_echo_enqueue0(env, eco, start, end, mode, cookie, 0); cl_io_fini(env, io); - EXIT; out: cl_env_put(env, &refcheck); return result; @@ -1366,7 +1363,6 @@ static int cl_echo_object_brw(struct echo_object *eco, int rw, obd_off offset, } cl_echo_cancel0(env, ed, lh.cookie); - EXIT; error_lock: cl_2queue_discard(env, io, queue); cl_2queue_disown(env, io, queue); @@ -1597,7 +1593,6 @@ echo_md_create_internal(const struct lu_env *env, struct echo_device *ed, } CDEBUG(D_RPCTRACE, "End creating object "DFID" %s %p rc = %d\n", PFID(lu_object_fid(&parent->mo_lu)), lname->ln_name, parent, rc); - EXIT; out_put: lu_object_put(env, ec_child); return rc; @@ -2280,7 +2275,6 @@ static int echo_create_object(const struct lu_env *env, struct echo_device *ed, cl_echo_object_put(eco); CDEBUG(D_INFO, "oa oid "DOSTID"\n", POSTID(&oa->o_oi)); - EXIT; failed: if (created && rc) @@ -2938,7 +2932,6 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len, GOTO (out, rc = -ENOTTY); } - EXIT; out: lu_env_fini(env); OBD_FREE_PTR(env); diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c index 3e71f41bbb5e..daaab369c88b 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cache.c +++ b/drivers/staging/lustre/lustre/osc/osc_cache.c @@ -781,7 +781,6 @@ restart: goto restart; } - EXIT; out: osc_extent_put(env, cur); @@ -1136,7 +1135,6 @@ static int osc_extent_expand(struct osc_extent *ext, pgoff_t index, int *grants) LASSERT(*grants >= 0); EASSERTF(osc_extent_is_overlapped(obj, ext) == 0, ext, "overlapped after expanding for %lu.\n", index); - EXIT; out: osc_object_unlock(obj); @@ -1330,7 +1328,6 @@ static void osc_release_write_grant(struct client_obd *cli, { LASSERT(spin_is_locked(&cli->cl_loi_list_lock.lock)); if (!(pga->flag & OBD_BRW_FROM_GRANT)) { - EXIT; return; } @@ -1342,7 +1339,6 @@ static void osc_release_write_grant(struct client_obd *cli, atomic_dec(&obd_dirty_transit_pages); cli->cl_dirty_transit -= PAGE_CACHE_SIZE; } - EXIT; } /** @@ -1544,7 +1540,6 @@ static int osc_enter_cache(const struct lu_env *env, struct client_obd *cli, if (osc_enter_cache_try(cli, oap, bytes, 0)) GOTO(out, rc = 0); } - EXIT; out: client_obd_list_unlock(&cli->cl_loi_list_lock); OSC_DUMP_GRANT(cli, "returned %d.\n", rc); @@ -1582,8 +1577,6 @@ wakeup: wake_up(&ocw->ocw_waitq); } - - EXIT; } static int osc_max_rpc_in_flight(struct client_obd *cli, struct osc_object *osc) @@ -1765,8 +1758,6 @@ static void osc_ap_completion(const struct lu_env *env, struct client_obd *cli, if (rc) CERROR("completion on oap %p obj %p returns %d.\n", oap, osc, rc); - - EXIT; } /** @@ -2430,7 +2421,6 @@ int osc_flush_async_page(const struct lu_env *env, struct cl_io *io, unplug = true; } rc = 0; - EXIT; out: osc_object_unlock(obj); diff --git a/drivers/staging/lustre/lustre/osc/osc_lock.c b/drivers/staging/lustre/lustre/osc/osc_lock.c index ef6f1bb9150b..d8fb36780070 100644 --- a/drivers/staging/lustre/lustre/osc/osc_lock.c +++ b/drivers/staging/lustre/lustre/osc/osc_lock.c @@ -390,8 +390,6 @@ static void osc_lock_lvb_update(const struct lu_env *env, struct osc_lock *olck, cl_object_attr_set(env, obj, attr, valid); cl_object_attr_unlock(obj); - - EXIT; } /** @@ -439,7 +437,6 @@ static void osc_lock_granted(const struct lu_env *env, struct osc_lock *olck, LINVRNT(osc_lock_invariant(olck)); lock_res_and_lock(dlmlock); } - EXIT; } static void osc_lock_upcall0(const struct lu_env *env, struct osc_lock *olck) diff --git a/drivers/staging/lustre/lustre/osc/osc_page.c b/drivers/staging/lustre/lustre/osc/osc_page.c index 5f51dfa3a3e0..6aa59e93a047 100644 --- a/drivers/staging/lustre/lustre/osc/osc_page.c +++ b/drivers/staging/lustre/lustre/osc/osc_page.c @@ -437,7 +437,6 @@ static void osc_page_delete(const struct lu_env *env, spin_unlock(&obj->oo_seatbelt); osc_lru_del(osc_cli(obj), opg, true); - EXIT; } void osc_page_clip(const struct lu_env *env, const struct cl_page_slice *slice, diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index a27bbb5c1240..1f73a698baef 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -291,7 +291,6 @@ static int osc_getattr(const struct lu_env *env, struct obd_export *exp, oinfo->oi_oa->o_blksize = cli_brw_size(exp->exp_obd); oinfo->oi_oa->o_valid |= OBD_MD_FLBLKSZ; - EXIT; out: ptlrpc_req_finished(req); return rc; @@ -332,7 +331,6 @@ static int osc_setattr(const struct lu_env *env, struct obd_export *exp, lustre_get_wire_obdo(&req->rq_import->imp_connect_data, oinfo->oi_oa, &body->oa); - EXIT; out: ptlrpc_req_finished(req); RETURN(rc); @@ -2202,7 +2200,6 @@ int osc_build_rpc(const struct lu_env *env, struct client_obd *cli, */ ptlrpcd_add_req(req, pol, -1); rc = 0; - EXIT; out: if (mem_tight != 0) @@ -2822,7 +2819,6 @@ static int osc_statfs(const struct lu_env *env, struct obd_export *exp, *osfs = *msfs; - EXIT; out: ptlrpc_req_finished(req); return rc; diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index b860db61e854..9bcfc4f65356 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -206,7 +206,6 @@ void __ptlrpc_free_bulk(struct ptlrpc_bulk_desc *desc, int unpin) OBD_FREE(desc, offsetof(struct ptlrpc_bulk_desc, bd_iov[desc->bd_max_iov])); - EXIT; } EXPORT_SYMBOL(__ptlrpc_free_bulk); @@ -919,7 +918,6 @@ void ptlrpc_set_destroy(struct ptlrpc_request_set *set) LASSERT(atomic_read(&set->set_remaining) == 0); ptlrpc_reqset_put(set); - EXIT; } EXPORT_SYMBOL(ptlrpc_set_destroy); @@ -1156,8 +1154,6 @@ static void ptlrpc_save_versions(struct ptlrpc_request *req) lustre_msg_set_versions(reqmsg, versions); CDEBUG(D_INFO, "Client save versions ["LPX64"/"LPX64"]\n", versions[0], versions[1]); - - EXIT; } /** @@ -2169,7 +2165,6 @@ EXPORT_SYMBOL(ptlrpc_set_wait); static void __ptlrpc_free_req(struct ptlrpc_request *request, int locked) { if (request == NULL) { - EXIT; return; } @@ -2222,7 +2217,6 @@ static void __ptlrpc_free_req(struct ptlrpc_request *request, int locked) __ptlrpc_free_req_to_pool(request); else OBD_FREE(request, sizeof(*request)); - EXIT; } static int __ptlrpc_req_finished(struct ptlrpc_request *request, int locked); @@ -2388,7 +2382,6 @@ void ptlrpc_free_committed(struct obd_import *imp) imp->imp_generation == imp->imp_last_generation_checked) { CDEBUG(D_INFO, "%s: skip recheck: last_committed "LPU64"\n", imp->imp_obd->obd_name, imp->imp_peer_committed_transno); - EXIT; return; } CDEBUG(D_RPCTRACE, "%s: committing for last_committed "LPU64" gen %d\n", @@ -2436,15 +2429,10 @@ free_req: list_del_init(&req->rq_replay_list); __ptlrpc_req_finished(req, 1); } - - EXIT; - return; } void ptlrpc_cleanup_client(struct obd_import *imp) { - EXIT; - return; } EXPORT_SYMBOL(ptlrpc_cleanup_client); @@ -2783,8 +2771,6 @@ void ptlrpc_abort_inflight(struct obd_import *imp) ptlrpc_free_committed(imp); spin_unlock(&imp->imp_lock); - - EXIT; } EXPORT_SYMBOL(ptlrpc_abort_inflight); diff --git a/drivers/staging/lustre/lustre/ptlrpc/connection.c b/drivers/staging/lustre/lustre/ptlrpc/connection.c index c5c1d52094c8..37a1e20ea716 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/connection.c +++ b/drivers/staging/lustre/lustre/ptlrpc/connection.c @@ -79,7 +79,6 @@ ptlrpc_connection_get(lnet_process_id_t peer, lnet_nid_t self, OBD_FREE_PTR(conn); conn = conn2; } - EXIT; out: CDEBUG(D_INFO, "conn=%p refcount %d to %s\n", conn, atomic_read(&conn->c_refcount), @@ -152,9 +151,9 @@ int ptlrpc_connection_init(void) } EXPORT_SYMBOL(ptlrpc_connection_init); -void ptlrpc_connection_fini(void) { +void ptlrpc_connection_fini(void) +{ cfs_hash_putref(conn_hash); - EXIT; } EXPORT_SYMBOL(ptlrpc_connection_fini); diff --git a/drivers/staging/lustre/lustre/ptlrpc/events.c b/drivers/staging/lustre/lustre/ptlrpc/events.c index d736a2730106..58d089c3fef4 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/events.c +++ b/drivers/staging/lustre/lustre/ptlrpc/events.c @@ -78,8 +78,6 @@ void request_out_callback(lnet_event_t *ev) } ptlrpc_req_finished(req); - - EXIT; } /* @@ -164,7 +162,6 @@ out_wake: * since we don't have our own ref */ ptlrpc_client_wake_req(req); spin_unlock(&req->rq_lock); - EXIT; } /* @@ -217,7 +214,6 @@ void client_bulk_callback (lnet_event_t *ev) ptlrpc_client_wake_req(desc->bd_req); spin_unlock(&desc->bd_lock); - EXIT; } /* @@ -374,7 +370,6 @@ void request_in_callback(lnet_event_t *ev) wake_up(&svcpt->scp_waitq); spin_unlock(&svcpt->scp_lock); - EXIT; } /* @@ -395,7 +390,6 @@ void reply_out_callback(lnet_event_t *ev) * net's ref on 'rs' */ LASSERT (ev->unlinked); ptlrpc_rs_decref(rs); - EXIT; return; } @@ -416,7 +410,6 @@ void reply_out_callback(lnet_event_t *ev) spin_unlock(&rs->rs_lock); spin_unlock(&svcpt->scp_rep_lock); } - EXIT; } diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_keyring.c b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_keyring.c index 07faa0e0516b..5c51b82933af 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_keyring.c +++ b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_keyring.c @@ -926,7 +926,6 @@ void flush_spec_ctx_cache_kr(struct ptlrpc_sec *sec, spin_unlock(&sec->ps_lock); dispose_ctx_list_kr(&freelist); - EXIT; } static @@ -974,8 +973,6 @@ void gss_sec_gc_ctx_kr(struct ptlrpc_sec *sec) spin_unlock(&sec->ps_lock); dispose_ctx_list_kr(&freelist); - EXIT; - return; } static @@ -1308,7 +1305,6 @@ void gss_kt_destroy(struct key *key) { LASSERT(key->payload.data == NULL); CDEBUG(D_SEC, "destroy key %p\n", key); - EXIT; } static diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_pipefs.c b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_pipefs.c index 105d0d8bca9e..f2bd67f54f56 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_pipefs.c +++ b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_pipefs.c @@ -286,7 +286,6 @@ void gss_sec_ctx_replace_pf(struct gss_sec *gsec, spin_unlock(&gsec->gs_base.ps_lock); ctx_list_destroy_pf(&freelist); - EXIT; } static @@ -334,7 +333,6 @@ void gss_ctx_cache_gc_pf(struct gss_sec_pipefs *gsec_pf, } sec->ps_gc_next = cfs_time_current_sec() + sec->ps_gc_interval; - EXIT; } static @@ -701,7 +699,6 @@ void gss_release_msg(struct gss_upcall_msg *gmsg) LASSERT(atomic_read(&gmsg->gum_refcount) > 0); if (!atomic_dec_and_test(&gmsg->gum_refcount)) { - EXIT; return; } @@ -714,7 +711,6 @@ void gss_release_msg(struct gss_upcall_msg *gmsg) LASSERT(list_empty(&gmsg->gum_list)); LASSERT(list_empty(&gmsg->gum_base.list)); OBD_FREE_PTR(gmsg); - EXIT; } static @@ -945,7 +941,6 @@ void gss_pipe_destroy_msg(struct rpc_pipe_msg *msg) /* normally errno is >= 0 */ if (msg->errno >= 0) { - EXIT; return; } @@ -970,7 +965,6 @@ void gss_pipe_destroy_msg(struct rpc_pipe_msg *msg) } gss_msg_fail_ctx(gmsg); gss_release_msg(gmsg); - EXIT; } static @@ -1009,7 +1003,6 @@ void gss_pipe_release(struct inode *inode) upcall_list_lock(idx); } upcall_list_unlock(idx); - EXIT; } static struct rpc_pipe_ops gss_upcall_ops = { diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_svc_upcall.c b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_svc_upcall.c index 243f110cce34..245044b6d77a 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/gss/gss_svc_upcall.c +++ b/drivers/staging/lustre/lustre/ptlrpc/gss/gss_svc_upcall.c @@ -681,7 +681,6 @@ static void rsc_flush(rsc_entry_match *match, long data) } } write_unlock(&rsc_cache.hash_lock); - EXIT; } static int match_uid(struct rsc *rscp, long uid) diff --git a/drivers/staging/lustre/lustre/ptlrpc/gss/sec_gss.c b/drivers/staging/lustre/lustre/ptlrpc/gss/sec_gss.c index 0553965cc368..95e4536f0484 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/gss/sec_gss.c +++ b/drivers/staging/lustre/lustre/ptlrpc/gss/sec_gss.c @@ -1157,8 +1157,6 @@ void gss_sec_destroy_common(struct gss_sec *gsec) if (SPTLRPC_FLVR_BULK_SVC(sec->ps_flvr.sf_rpc) == SPTLRPC_BULK_SVC_PRIV) sptlrpc_enc_pool_del_user(); - - EXIT; } void gss_sec_kill(struct ptlrpc_sec *sec) @@ -1462,8 +1460,6 @@ release_reqbuf: req->rq_reqbuf = NULL; req->rq_reqbuf_len = 0; } - - EXIT; } static int do_alloc_repbuf(struct ptlrpc_request *req, int bufsize) @@ -2418,7 +2414,6 @@ void gss_svc_invalidate_ctx(struct ptlrpc_svc_ctx *svc_ctx) struct gss_svc_reqctx *grctx; if (svc_ctx == NULL) { - EXIT; return; } @@ -2427,8 +2422,6 @@ void gss_svc_invalidate_ctx(struct ptlrpc_svc_ctx *svc_ctx) CWARN("gss svc invalidate ctx %p(%u)\n", grctx->src_ctx, grctx->src_ctx->gsc_uid); gss_svc_upcall_destroy_ctx(grctx->src_ctx); - - EXIT; } static inline diff --git a/drivers/staging/lustre/lustre/ptlrpc/import.c b/drivers/staging/lustre/lustre/ptlrpc/import.c index 3b1137b9ac9d..b8a00f562597 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/import.c +++ b/drivers/staging/lustre/lustre/ptlrpc/import.c @@ -204,8 +204,6 @@ static void ptlrpc_deactivate_and_unlock_import(struct obd_import *imp) ptlrpc_abort_inflight(imp); obd_import_event(imp->imp_obd, imp, IMP_EVENT_INACTIVE); - - EXIT; } /* @@ -414,7 +412,6 @@ void ptlrpc_fail_import(struct obd_import *imp, __u32 conn_cnt) ptlrpc_pinger_wake_up(); } - EXIT; } EXPORT_SYMBOL(ptlrpc_fail_import); @@ -1475,8 +1472,6 @@ void ptlrpc_cleanup_imp(struct obd_import *imp) imp->imp_generation++; spin_unlock(&imp->imp_lock); ptlrpc_abort_inflight(imp); - - EXIT; } EXPORT_SYMBOL(ptlrpc_cleanup_imp); diff --git a/drivers/staging/lustre/lustre/ptlrpc/llog_client.c b/drivers/staging/lustre/lustre/ptlrpc/llog_client.c index b3db05583641..d771cb9f129f 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/llog_client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/llog_client.c @@ -132,7 +132,6 @@ static int llog_client_open(const struct lu_env *env, lgh->lgh_id = body->lgd_logid; lgh->lgh_ctxt = ctxt; - EXIT; out: LLOG_CLIENT_EXIT(ctxt, imp); ptlrpc_req_finished(req); @@ -218,7 +217,6 @@ static int llog_client_next_block(const struct lu_env *env, *cur_offset = body->lgd_cur_offset; memcpy(buf, ptr, len); - EXIT; out: ptlrpc_req_finished(req); err_exit: @@ -266,7 +264,6 @@ static int llog_client_prev_block(const struct lu_env *env, GOTO(out, rc =-EFAULT); memcpy(buf, ptr, len); - EXIT; out: ptlrpc_req_finished(req); err_exit: @@ -321,7 +318,6 @@ static int llog_client_read_header(const struct lu_env *env, CERROR("you may need to re-run lconf --write_conf.\n"); rc = -EIO; } - EXIT; out: ptlrpc_req_finished(req); err_exit: diff --git a/drivers/staging/lustre/lustre/ptlrpc/llog_server.c b/drivers/staging/lustre/lustre/ptlrpc/llog_server.c index b5aec5e84ee6..711cbd1ecc29 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/llog_server.c +++ b/drivers/staging/lustre/lustre/ptlrpc/llog_server.c @@ -106,7 +106,6 @@ int llog_origin_handle_open(struct ptlrpc_request *req) body = req_capsule_server_get(&req->rq_pill, &RMF_LLOGD_BODY); body->lgd_logid = loghandle->lgh_id; - EXIT; out_close: llog_origin_close(req->rq_svc_thread->t_env, loghandle); out_pop: @@ -202,7 +201,6 @@ int llog_origin_handle_next_block(struct ptlrpc_request *req) &repbody->lgd_cur_offset, ptr, LLOG_CHUNK_SIZE); if (rc) GOTO(out_close, rc); - EXIT; out_close: llog_origin_close(req->rq_svc_thread->t_env, loghandle); out_pop: @@ -261,7 +259,6 @@ int llog_origin_handle_prev_block(struct ptlrpc_request *req) if (rc) GOTO(out_close, rc); - EXIT; out_close: llog_origin_close(req->rq_svc_thread->t_env, loghandle); out_pop: @@ -314,7 +311,6 @@ int llog_origin_handle_read_header(struct ptlrpc_request *req) hdr = req_capsule_server_get(&req->rq_pill, &RMF_LLOG_LOG_HDR); *hdr = *loghandle->lgh_hdr; - EXIT; out_close: llog_origin_close(req->rq_svc_thread->t_env, loghandle); out_pop: diff --git a/drivers/staging/lustre/lustre/ptlrpc/nrs.c b/drivers/staging/lustre/lustre/ptlrpc/nrs.c index afc52326b1cb..226c9c088064 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/nrs.c +++ b/drivers/staging/lustre/lustre/ptlrpc/nrs.c @@ -110,8 +110,6 @@ static void nrs_policy_stop0(struct ptlrpc_nrs_policy *policy) if (atomic_dec_and_test(&policy->pol_desc->pd_refs)) module_put(policy->pol_desc->pd_owner); - - EXIT; } static int nrs_policy_stop_locked(struct ptlrpc_nrs_policy *policy) @@ -158,7 +156,6 @@ static void nrs_policy_stop_primary(struct ptlrpc_nrs *nrs) struct ptlrpc_nrs_policy *tmp = nrs->nrs_policy_primary; if (tmp == NULL) { - EXIT; return; } @@ -169,7 +166,6 @@ static void nrs_policy_stop_primary(struct ptlrpc_nrs *nrs) if (tmp->pol_ref == 0) nrs_policy_stop0(tmp); - EXIT; } /** @@ -839,7 +835,6 @@ static void ptlrpc_nrs_hpreq_add_nolock(struct ptlrpc_request *req) if (opc != OBD_PING) DEBUG_REQ(D_NET, req, "high priority req"); spin_unlock(&req->rq_lock); - EXIT; } /** @@ -1020,8 +1015,6 @@ again: if (hp) OBD_FREE_PTR(nrs); - - EXIT; } /** @@ -1639,7 +1632,6 @@ out: * returned false. */ nrs_resource_put_safe(res1); - EXIT; } /** diff --git a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c index aae4fd67152a..d722c6451cea 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c @@ -2170,14 +2170,12 @@ static void lustre_swab_lov_user_md_common(struct lov_user_md_v1 *lum) __swab16s(&lum->lmm_stripe_count); __swab16s(&lum->lmm_stripe_offset); print_lum(lum); - EXIT; } void lustre_swab_lov_user_md_v1(struct lov_user_md_v1 *lum) { CDEBUG(D_IOCTL, "swabbing lov_user_md v1\n"); lustre_swab_lov_user_md_common(lum); - EXIT; } EXPORT_SYMBOL(lustre_swab_lov_user_md_v1); @@ -2186,7 +2184,6 @@ void lustre_swab_lov_user_md_v3(struct lov_user_md_v3 *lum) CDEBUG(D_IOCTL, "swabbing lov_user_md v3\n"); lustre_swab_lov_user_md_common((struct lov_user_md_v1 *)lum); /* lmm_pool_name nothing to do with char */ - EXIT; } EXPORT_SYMBOL(lustre_swab_lov_user_md_v3); @@ -2199,7 +2196,6 @@ void lustre_swab_lov_mds_md(struct lov_mds_md *lmm) __swab32s(&lmm->lmm_stripe_size); __swab16s(&lmm->lmm_stripe_count); __swab16s(&lmm->lmm_layout_gen); - EXIT; } EXPORT_SYMBOL(lustre_swab_lov_mds_md); @@ -2213,7 +2209,6 @@ void lustre_swab_lov_user_md_objects(struct lov_user_ost_data *lod, __swab32s(&(lod[i].l_ost_gen)); __swab32s(&(lod[i].l_ost_idx)); } - EXIT; } EXPORT_SYMBOL(lustre_swab_lov_user_md_objects); diff --git a/drivers/staging/lustre/lustre/ptlrpc/pinger.c b/drivers/staging/lustre/lustre/ptlrpc/pinger.c index 74372914e850..481963df2023 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/pinger.c +++ b/drivers/staging/lustre/lustre/ptlrpc/pinger.c @@ -350,7 +350,6 @@ static int ptlrpc_pinger_main(void *arg) thread_is_event(thread), &lwi); if (thread_test_and_clear_flags(thread, SVC_STOPPING)) { - EXIT; break; } else { /* woken after adding import to reset timer */ diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c index e0ee38e80ae2..8b654abd8f73 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c +++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c @@ -666,16 +666,13 @@ void ptlrpcd_stop(struct ptlrpcd_ctl *pc, int force) { if (!test_bit(LIOD_START, &pc->pc_flags)) { CWARN("Thread for pc %p was not started\n", pc); - goto out; + return; } set_bit(LIOD_STOP, &pc->pc_flags); if (force) set_bit(LIOD_FORCE, &pc->pc_flags); wake_up(&pc->pc_set->set_waitq); - -out: - EXIT; } void ptlrpcd_free(struct ptlrpcd_ctl *pc) @@ -709,7 +706,6 @@ out: pc->pc_partners = NULL; } pc->pc_npartners = 0; - EXIT; } static void ptlrpcd_fini(void) @@ -726,8 +722,6 @@ static void ptlrpcd_fini(void) OBD_FREE(ptlrpcds, ptlrpcds->pd_size); ptlrpcds = NULL; } - - EXIT; } static int ptlrpcd_init(void) diff --git a/drivers/staging/lustre/lustre/ptlrpc/recover.c b/drivers/staging/lustre/lustre/ptlrpc/recover.c index 29a9f0acc672..682d97143c34 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/recover.c +++ b/drivers/staging/lustre/lustre/ptlrpc/recover.c @@ -62,8 +62,6 @@ void ptlrpc_initiate_recovery(struct obd_import *imp) { CDEBUG(D_HA, "%s: starting recovery\n", obd2cli_tgt(imp->imp_obd)); ptlrpc_connect_import(imp); - - EXIT; } /** @@ -224,8 +222,6 @@ void ptlrpc_request_handle_notconn(struct ptlrpc_request *failed_req) if (!failed_req->rq_no_resend) failed_req->rq_resend = 1; spin_unlock(&failed_req->rq_lock); - - EXIT; } /** @@ -329,7 +325,6 @@ int ptlrpc_recover_import(struct obd_import *imp, char *new_uuid, int async) CDEBUG(D_HA, "%s: recovery finished\n", obd2cli_tgt(imp->imp_obd)); } - EXIT; out: return rc; diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec.c b/drivers/staging/lustre/lustre/ptlrpc/sec.c index 9ec7157e7fd9..82b1c3ac05a4 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec.c @@ -441,7 +441,6 @@ void sptlrpc_req_put_ctx(struct ptlrpc_request *req, int sync) sptlrpc_cli_ctx_put(req->rq_cli_ctx, sync); req->rq_cli_ctx = NULL; - EXIT; } static @@ -1691,7 +1690,6 @@ void sptlrpc_cli_free_repbuf(struct ptlrpc_request *req) policy = ctx->cc_sec->ps_policy; policy->sp_cops->free_repbuf(ctx->cc_sec, req); req->rq_repmsg = NULL; - EXIT; } int sptlrpc_cli_install_rvs_ctx(struct obd_import *imp, @@ -2149,7 +2147,6 @@ void sptlrpc_svc_free_rs(struct ptlrpc_reply_state *rs) if (prealloc) lustre_put_emerg_rs(rs); - EXIT; } void sptlrpc_svc_ctx_addref(struct ptlrpc_request *req) diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_config.c b/drivers/staging/lustre/lustre/ptlrpc/sec_config.c index f12bdeb8b1f8..665cf1b2171d 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec_config.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec_config.c @@ -922,7 +922,6 @@ void sptlrpc_conf_client_adapt(struct obd_device *obd) } up_read(&obd->u.cli.cl_sem); - EXIT; } EXPORT_SYMBOL(sptlrpc_conf_client_adapt); diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c b/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c index f5fbdbe0c85e..ed33a7fecb46 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c @@ -425,7 +425,6 @@ void plain_destroy_sec(struct ptlrpc_sec *sec) class_import_put(sec->ps_import); OBD_FREE_PTR(plsec); - EXIT; } static @@ -590,7 +589,6 @@ void plain_free_reqbuf(struct ptlrpc_sec *sec, req->rq_reqbuf = NULL; req->rq_reqbuf_len = 0; } - EXIT; } static @@ -631,7 +629,6 @@ void plain_free_repbuf(struct ptlrpc_sec *sec, OBD_FREE_LARGE(req->rq_repbuf, req->rq_repbuf_len); req->rq_repbuf = NULL; req->rq_repbuf_len = 0; - EXIT; } static @@ -819,7 +816,6 @@ void plain_free_rs(struct ptlrpc_reply_state *rs) if (!rs->rs_prealloc) OBD_FREE_LARGE(rs, rs->rs_size); - EXIT; } static diff --git a/drivers/staging/lustre/lustre/ptlrpc/service.c b/drivers/staging/lustre/lustre/ptlrpc/service.c index 1a73f8a57b41..190c83f170df 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/service.c +++ b/drivers/staging/lustre/lustre/ptlrpc/service.c @@ -379,7 +379,6 @@ void ptlrpc_dispatch_difficult_reply(struct ptlrpc_reply_state *rs) spin_unlock(&hrt->hrt_lock); wake_up(&hrt->hrt_waitq); - EXIT; } void @@ -391,14 +390,12 @@ ptlrpc_schedule_difficult_reply(struct ptlrpc_reply_state *rs) rs->rs_scheduled_ever = 1; /* flag any notification attempt */ if (rs->rs_scheduled) { /* being set up or already notified */ - EXIT; return; } rs->rs_scheduled = 1; list_del_init(&rs->rs_list); ptlrpc_dispatch_difficult_reply(rs); - EXIT; } EXPORT_SYMBOL(ptlrpc_schedule_difficult_reply); @@ -425,7 +422,6 @@ void ptlrpc_commit_replies(struct obd_export *exp) } spin_unlock(&exp->exp_uncommitted_replies_lock); rs_batch_fini(&batch); - EXIT; } EXPORT_SYMBOL(ptlrpc_commit_replies); @@ -1071,7 +1067,6 @@ static void ptlrpc_update_export_timer(struct obd_export *exp, long extra_delay) if (exp->exp_obd->obd_recovering) { /* be nice to everyone during recovery */ - EXIT; return; } @@ -1100,8 +1095,6 @@ static void ptlrpc_update_export_timer(struct obd_export *exp, long extra_delay) exp->exp_obd->obd_eviction_timer = 0; } } - - EXIT; } /** @@ -1547,7 +1540,6 @@ static void ptlrpc_server_hpreq_fini(struct ptlrpc_request *req) list_del_init(&req->rq_exp_list); spin_unlock_bh(&req->rq_export->exp_rpc_lock); } - EXIT; } static int ptlrpc_hpreq_check(struct ptlrpc_request *req) @@ -2615,7 +2607,6 @@ static void ptlrpc_svcpt_stop_threads(struct ptlrpc_service_part *svcpt) list_del(&thread->t_link); OBD_FREE_PTR(thread); } - EXIT; } /** @@ -2630,8 +2621,6 @@ void ptlrpc_stop_all_threads(struct ptlrpc_service *svc) if (svcpt->scp_service != NULL) ptlrpc_svcpt_stop_threads(svcpt); } - - EXIT; } EXPORT_SYMBOL(ptlrpc_stop_all_threads); From f2a230bd4e1ac4b54ec59dc0b2a246bfe3e89ffe Mon Sep 17 00:00:00 2001 From: Wei Yang Date: Fri, 2 Aug 2013 17:31:03 +0800 Subject: [PATCH 1343/3400] PCI: Enumerate subordinate buses, not devices, in pci_bus_get_depth() Normally, on one PCI bus there would be more devices than bridges. When calculating the depth of a PCI bus, it would be more time efficient to enumerating through the child buses instead of the child devices. Also by doing so, the code seems more self explaining. Previously, it went through the devices and checked whether a bridge introduced a child bus or not, which needs more background knowledge to understand it. This patch calculates the depth by enumerating the bus hierarchy. Signed-off-by: Wei Yang Signed-off-by: Bjorn Helgaas --- drivers/pci/setup-bus.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index d254e2379533..6dbe5629c8b4 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1300,15 +1300,12 @@ static void pci_bus_dump_resources(struct pci_bus *bus) static int __init pci_bus_get_depth(struct pci_bus *bus) { int depth = 0; - struct pci_dev *dev; + struct pci_bus *child_bus; - list_for_each_entry(dev, &bus->devices, bus_list) { + list_for_each_entry(child_bus, &bus->children, node){ int ret; - struct pci_bus *b = dev->subordinate; - if (!b) - continue; - ret = pci_bus_get_depth(b); + ret = pci_bus_get_depth(child_bus); if (ret + 1 > depth) depth = ret + 1; } From 496f70cf6507be96397d319b1b7d3946d51d9932 Mon Sep 17 00:00:00 2001 From: Wei Yang Date: Fri, 2 Aug 2013 17:31:04 +0800 Subject: [PATCH 1344/3400] PCI: Add comments for pbus_size_mem() parameters This patch fills in the missing description for two parameters of pbus_size_mem(). Signed-off-by: Wei Yang Signed-off-by: Bjorn Helgaas --- drivers/pci/setup-bus.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 6dbe5629c8b4..939ca1b9af92 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -838,6 +838,8 @@ static inline resource_size_t calculate_mem_align(resource_size_t *aligns, * pbus_size_mem() - size the memory window of a given bus * * @bus : the bus + * @mask: mask the resource flag, then compare it with type + * @type: the type of free resource from bridge * @min_size : the minimum memory window that must to be allocated * @add_size : additional optional memory window * @realloc_head : track the additional memory window on this list From 11251a869e84b2a3224955fe149dd33a16805cbf Mon Sep 17 00:00:00 2001 From: Wei Yang Date: Fri, 2 Aug 2013 17:31:05 +0800 Subject: [PATCH 1345/3400] PCI: Fix types in pbus_size_io() This patch changes the type of "size" to resource_size_t and makes the corresponding dev_printk() change. [bhelgaas: changelog] Signed-off-by: Wei Yang Signed-off-by: Bjorn Helgaas --- drivers/pci/setup-bus.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 939ca1b9af92..d4f1ad956fad 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -747,7 +747,7 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size, { struct pci_dev *dev; struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO); - unsigned long size = 0, size0 = 0, size1 = 0; + resource_size_t size = 0, size0 = 0, size1 = 0; resource_size_t children_add_size = 0; resource_size_t min_align, io_align, align; @@ -807,8 +807,9 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size, add_to_list(realloc_head, bus->self, b_res, size1-size0, min_align); dev_printk(KERN_DEBUG, &bus->self->dev, "bridge window " - "%pR to %pR add_size %lx\n", b_res, - &bus->busn_res, size1-size0); + "%pR to %pR add_size %llx\n", b_res, + &bus->busn_res, + (unsigned long long)size1-size0); } } From 5ef76da644bf346d29200007d8d3779e7009dabb Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Fri, 2 Aug 2013 14:05:20 +0200 Subject: [PATCH 1346/3400] fbdev: simplefb: add init through platform_data If we create proper platform-devices in x86 boot-code, we can use simplefb for VBE or EFI framebuffers, too. However, there is normally no OF support so we introduce a platform_data object so x86 boot-code can pass the parameters via plain old platform-data. This also removes the OF dependency as it is not needed. The headers provide proper dummies for the case OF is disabled. Furthermore, we move the FORMAT-definitions to the common platform header so initialization code can use it to transform "struct screen_info" to the right format-name. Signed-off-by: David Herrmann Link: http://lkml.kernel.org/r/1375445127-15480-2-git-send-email-dh.herrmann@gmail.com Reviewed-by: Stephen Warren Signed-off-by: H. Peter Anvin --- drivers/video/Kconfig | 5 +-- drivers/video/simplefb.c | 48 ++++++++++++++++------ include/linux/platform_data/simplefb.h | 56 ++++++++++++++++++++++++++ 3 files changed, 93 insertions(+), 16 deletions(-) create mode 100644 include/linux/platform_data/simplefb.h diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 4cf1e1dd5621..34c3d960634d 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -2457,7 +2457,7 @@ config FB_HYPERV config FB_SIMPLE bool "Simple framebuffer support" - depends on (FB = y) && OF + depends on (FB = y) select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -2469,8 +2469,7 @@ config FB_SIMPLE pre-allocated frame buffer surface. Configuration re: surface address, size, and format must be provided - through device tree, or potentially plain old platform data in the - future. + through device tree, or plain old platform data. source "drivers/video/omap/Kconfig" source "drivers/video/omap2/Kconfig" diff --git a/drivers/video/simplefb.c b/drivers/video/simplefb.c index e2e9e3e61b72..588698986ce1 100644 --- a/drivers/video/simplefb.c +++ b/drivers/video/simplefb.c @@ -24,6 +24,7 @@ #include #include #include +#include #include static struct fb_fix_screeninfo simplefb_fix = { @@ -73,18 +74,7 @@ static struct fb_ops simplefb_ops = { .fb_imageblit = cfb_imageblit, }; -struct simplefb_format { - const char *name; - u32 bits_per_pixel; - struct fb_bitfield red; - struct fb_bitfield green; - struct fb_bitfield blue; - struct fb_bitfield transp; -}; - -static struct simplefb_format simplefb_formats[] = { - { "r5g6b5", 16, {11, 5}, {5, 6}, {0, 5}, {0, 0} }, -}; +static struct simplefb_format simplefb_formats[] = SIMPLEFB_FORMATS; struct simplefb_params { u32 width; @@ -139,6 +129,33 @@ static int simplefb_parse_dt(struct platform_device *pdev, return 0; } +static int simplefb_parse_pd(struct platform_device *pdev, + struct simplefb_params *params) +{ + struct simplefb_platform_data *pd = pdev->dev.platform_data; + int i; + + params->width = pd->width; + params->height = pd->height; + params->stride = pd->stride; + + params->format = NULL; + for (i = 0; i < ARRAY_SIZE(simplefb_formats); i++) { + if (strcmp(pd->format, simplefb_formats[i].name)) + continue; + + params->format = &simplefb_formats[i]; + break; + } + + if (!params->format) { + dev_err(&pdev->dev, "Invalid format value\n"); + return -EINVAL; + } + + return 0; +} + static int simplefb_probe(struct platform_device *pdev) { int ret; @@ -149,7 +166,12 @@ static int simplefb_probe(struct platform_device *pdev) if (fb_get_options("simplefb", NULL)) return -ENODEV; - ret = simplefb_parse_dt(pdev, ¶ms); + ret = -ENODEV; + if (pdev->dev.platform_data) + ret = simplefb_parse_pd(pdev, ¶ms); + else if (pdev->dev.of_node) + ret = simplefb_parse_dt(pdev, ¶ms); + if (ret) return ret; diff --git a/include/linux/platform_data/simplefb.h b/include/linux/platform_data/simplefb.h new file mode 100644 index 000000000000..5fa2c5e02ab8 --- /dev/null +++ b/include/linux/platform_data/simplefb.h @@ -0,0 +1,56 @@ +/* + * simplefb.h - Simple Framebuffer Device + * + * Copyright (C) 2013 David Herrmann + * + * 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 __PLATFORM_DATA_SIMPLEFB_H__ +#define __PLATFORM_DATA_SIMPLEFB_H__ + +#include +#include +#include + +/* format array, use it to initialize a "struct simplefb_format" array */ +#define SIMPLEFB_FORMATS \ +{ \ + { "r5g6b5", 16, {11, 5}, {5, 6}, {0, 5}, {0, 0}, DRM_FORMAT_RGB565 }, \ +} + +/* + * Data-Format for Simple-Framebuffers + * @name: unique 0-terminated name that can be used to identify the mode + * @red,green,blue: Offsets and sizes of the single RGB parts + * @transp: Offset and size of the alpha bits. length=0 means no alpha + * @fourcc: 32bit DRM four-CC code (see drm_fourcc.h) + */ +struct simplefb_format { + const char *name; + u32 bits_per_pixel; + struct fb_bitfield red; + struct fb_bitfield green; + struct fb_bitfield blue; + struct fb_bitfield transp; + u32 fourcc; +}; + +/* + * Simple-Framebuffer description + * If the arch-boot code creates simple-framebuffers without DT support, it + * can pass the width, height, stride and format via this platform-data object. + * The framebuffer location must be given as IORESOURCE_MEM resource. + * @format must be a format as described in "struct simplefb_format" above. + */ +struct simplefb_platform_data { + u32 width; + u32 height; + u32 stride; + const char *format; +}; + +#endif /* __PLATFORM_DATA_SIMPLEFB_H__ */ From df0960ab2d95543a7c162b04b2064991666adbad Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Fri, 2 Aug 2013 14:05:21 +0200 Subject: [PATCH 1347/3400] fbdev: simplefb: mark as fw and allocate apertures fbdev-core uses FBINFO_MISC_FIRMWARE to mark drivers that use firmware framebuffers. Furthermore, we now allocate apertures for the fbinfo device. Both information is used by remove_conflicting_framebuffers() to remove a fbdev device whenever a real driver is loaded. This is used heavily on x86 for VGA/vesa/EFI framebuffers, but is also of great use for all other systems. Especially with x86 support for simplefb, this information is needed to unload simplefb before a real hw-driver (like i915, radeon, nouveau) is loaded. Signed-off-by: David Herrmann Link: http://lkml.kernel.org/r/1375445127-15480-3-git-send-email-dh.herrmann@gmail.com Tested-by: Stephen Warren Signed-off-by: H. Peter Anvin --- drivers/video/simplefb.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/video/simplefb.c b/drivers/video/simplefb.c index 588698986ce1..8d7810613058 100644 --- a/drivers/video/simplefb.c +++ b/drivers/video/simplefb.c @@ -202,8 +202,16 @@ static int simplefb_probe(struct platform_device *pdev) info->var.blue = params.format->blue; info->var.transp = params.format->transp; + info->apertures = alloc_apertures(1); + if (!info->apertures) { + framebuffer_release(info); + return -ENOMEM; + } + info->apertures->ranges[0].base = info->fix.smem_start; + info->apertures->ranges[0].size = info->fix.smem_len; + info->fbops = &simplefb_ops; - info->flags = FBINFO_DEFAULT; + info->flags = FBINFO_DEFAULT | FBINFO_MISC_FIRMWARE; info->screen_base = devm_ioremap(&pdev->dev, info->fix.smem_start, info->fix.smem_len); if (!info->screen_base) { From e3263ab389a7bc9398c3d366819d6f39b9cfd677 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Fri, 2 Aug 2013 14:05:22 +0200 Subject: [PATCH 1348/3400] x86: provide platform-devices for boot-framebuffers The current situation regarding boot-framebuffers (VGA, VESA/VBE, EFI) on x86 causes troubles when loading multiple fbdev drivers. The global "struct screen_info" does not provide any state-tracking about which drivers use the FBs. request_mem_region() theoretically works, but unfortunately vesafb/efifb ignore it due to quirks for broken boards. Avoid this by creating a platform framebuffer devices with a pointer to the "struct screen_info" as platform-data. Drivers can now create platform-drivers and the driver-core will refuse multiple drivers being active simultaneously. We keep the screen_info available for backwards-compatibility. Drivers can be converted in follow-up patches. Different devices are created for VGA/VESA/EFI FBs to allow multiple drivers to be loaded on distro kernels. We create: - "vesa-framebuffer" for VBE/VESA graphics FBs - "efi-framebuffer" for EFI FBs - "platform-framebuffer" for everything else This allows to load vesafb, efifb and others simultaneously and each picks up only the supported FB types. Apart from platform-framebuffer devices, this also introduces a compatibility option for "simple-framebuffer" drivers which recently got introduced for OF based systems. If CONFIG_X86_SYSFB is selected, we try to match the screen_info against a simple-framebuffer supported format. If we succeed, we create a "simple-framebuffer" device instead of a platform-framebuffer. This allows to reuse the simplefb.c driver across architectures and also to introduce a SimpleDRM driver. There is no need to have vesafb.c, efifb.c, simplefb.c and more just to have architecture specific quirks in their setup-routines. Instead, we now move the architecture specific quirks into x86-setup and provide a generic simple-framebuffer. For backwards-compatibility (if strange formats are used), we still allow vesafb/efifb to be loaded simultaneously and pick up all remaining devices. Signed-off-by: David Herrmann Link: http://lkml.kernel.org/r/1375445127-15480-4-git-send-email-dh.herrmann@gmail.com Tested-by: Stephen Warren Signed-off-by: H. Peter Anvin --- arch/x86/Kconfig | 26 +++++++++ arch/x86/include/asm/sysfb.h | 41 ++++++++++++++ arch/x86/kernel/Makefile | 2 + arch/x86/kernel/sysfb.c | 71 ++++++++++++++++++++++++ arch/x86/kernel/sysfb_simplefb.c | 95 ++++++++++++++++++++++++++++++++ 5 files changed, 235 insertions(+) create mode 100644 arch/x86/include/asm/sysfb.h create mode 100644 arch/x86/kernel/sysfb.c create mode 100644 arch/x86/kernel/sysfb_simplefb.c diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index b32ebf92b0ce..5c56559e0c50 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -2270,6 +2270,32 @@ config RAPIDIO source "drivers/rapidio/Kconfig" +config X86_SYSFB + bool "Mark VGA/VBE/EFI FB as generic system framebuffer" + help + Firmwares often provide initial graphics framebuffers so the BIOS, + bootloader or kernel can show basic video-output during boot for + user-guidance and debugging. Historically, x86 used the VESA BIOS + Extensions and EFI-framebuffers for this, which are mostly limited + to x86. + This option, if enabled, marks VGA/VBE/EFI framebuffers as generic + framebuffers so the new generic system-framebuffer drivers can be + used on x86. If the framebuffer is not compatible with the generic + modes, it is adverticed as fallback platform framebuffer so legacy + drivers like efifb, vesafb and uvesafb can pick it up. + If this option is not selected, all system framebuffers are always + marked as fallback platform framebuffers as usual. + + Note: Legacy fbdev drivers, including vesafb, efifb, uvesafb, will + not be able to pick up generic system framebuffers if this option + is selected. You are highly encouraged to enable simplefb as + replacement if you select this option. simplefb can correctly deal + with generic system framebuffers. But you should still keep vesafb + and others enabled as fallback if a system framebuffer is + incompatible with simplefb. + + If unsure, say Y. + endmenu diff --git a/arch/x86/include/asm/sysfb.h b/arch/x86/include/asm/sysfb.h new file mode 100644 index 000000000000..2395fe03f56b --- /dev/null +++ b/arch/x86/include/asm/sysfb.h @@ -0,0 +1,41 @@ +#ifndef _ARCH_X86_KERNEL_SYSFB_H +#define _ARCH_X86_KERNEL_SYSFB_H + +/* + * Generic System Framebuffers on x86 + * Copyright (c) 2012-2013 David Herrmann + * + * 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 + +#ifdef CONFIG_X86_SYSFB + +bool parse_mode(const struct screen_info *si, + struct simplefb_platform_data *mode); +int create_simplefb(const struct screen_info *si, + const struct simplefb_platform_data *mode); + +#else /* CONFIG_X86_SYSFB */ + +static inline bool parse_mode(const struct screen_info *si, + struct simplefb_platform_data *mode) +{ + return false; +} + +static inline int create_simplefb(const struct screen_info *si, + const struct simplefb_platform_data *mode) +{ + return -EINVAL; +} + +#endif /* CONFIG_X86_SYSFB */ + +#endif /* _ARCH_X86_KERNEL_SYSFB_H */ diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 88d99ea77723..90ecdc5d471a 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -103,6 +103,8 @@ obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o obj-$(CONFIG_OF) += devicetree.o obj-$(CONFIG_UPROBES) += uprobes.o +obj-y += sysfb.o +obj-$(CONFIG_X86_SYSFB) += sysfb_simplefb.o obj-$(CONFIG_PERF_EVENTS) += perf_regs.o obj-$(CONFIG_TRACING) += tracepoint.o diff --git a/arch/x86/kernel/sysfb.c b/arch/x86/kernel/sysfb.c new file mode 100644 index 000000000000..7f30e194eb52 --- /dev/null +++ b/arch/x86/kernel/sysfb.c @@ -0,0 +1,71 @@ +/* + * Generic System Framebuffers on x86 + * Copyright (c) 2012-2013 David Herrmann + * + * 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. + */ + +/* + * Simple-Framebuffer support for x86 systems + * Create a platform-device for any available boot framebuffer. The + * simple-framebuffer platform device is already available on DT systems, so + * this module parses the global "screen_info" object and creates a suitable + * platform device compatible with the "simple-framebuffer" DT object. If + * the framebuffer is incompatible, we instead create a legacy + * "vesa-framebuffer", "efi-framebuffer" or "platform-framebuffer" device and + * pass the screen_info as platform_data. This allows legacy drivers + * to pick these devices up without messing with simple-framebuffer drivers. + * The global "screen_info" is still valid at all times. + * + * If CONFIG_X86_SYSFB is not selected, we never register "simple-framebuffer" + * platform devices, but only use legacy framebuffer devices for + * backwards compatibility. + * + * TODO: We set the dev_id field of all platform-devices to 0. This allows + * other x86 OF/DT parsers to create such devices, too. However, they must + * start at offset 1 for this to work. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static __init int sysfb_init(void) +{ + struct screen_info *si = &screen_info; + struct simplefb_platform_data mode; + struct platform_device *pd; + const char *name; + bool compatible; + int ret; + + /* try to create a simple-framebuffer device */ + compatible = parse_mode(si, &mode); + if (compatible) { + ret = create_simplefb(si, &mode); + if (!ret) + return 0; + } + + /* if the FB is incompatible, create a legacy framebuffer device */ + if (si->orig_video_isVGA == VIDEO_TYPE_EFI) + name = "efi-framebuffer"; + else if (si->orig_video_isVGA == VIDEO_TYPE_VLFB) + name = "vesa-framebuffer"; + else + name = "platform-framebuffer"; + + pd = platform_device_register_resndata(NULL, name, 0, + NULL, 0, si, sizeof(*si)); + return IS_ERR(pd) ? PTR_ERR(pd) : 0; +} + +device_initcall(sysfb_init); diff --git a/arch/x86/kernel/sysfb_simplefb.c b/arch/x86/kernel/sysfb_simplefb.c new file mode 100644 index 000000000000..22513e96b012 --- /dev/null +++ b/arch/x86/kernel/sysfb_simplefb.c @@ -0,0 +1,95 @@ +/* + * Generic System Framebuffers on x86 + * Copyright (c) 2012-2013 David Herrmann + * + * 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. + */ + +/* + * simple-framebuffer probing + * Try to convert "screen_info" into a "simple-framebuffer" compatible mode. + * If the mode is incompatible, we return "false" and let the caller create + * legacy nodes instead. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static const char simplefb_resname[] = "BOOTFB"; +static const struct simplefb_format formats[] = SIMPLEFB_FORMATS; + +/* try parsing x86 screen_info into a simple-framebuffer mode struct */ +__init bool parse_mode(const struct screen_info *si, + struct simplefb_platform_data *mode) +{ + const struct simplefb_format *f; + __u8 type; + unsigned int i; + + type = si->orig_video_isVGA; + if (type != VIDEO_TYPE_VLFB && type != VIDEO_TYPE_EFI) + return false; + + for (i = 0; i < ARRAY_SIZE(formats); ++i) { + f = &formats[i]; + if (si->lfb_depth == f->bits_per_pixel && + si->red_size == f->red.length && + si->red_pos == f->red.offset && + si->green_size == f->green.length && + si->green_pos == f->green.offset && + si->blue_size == f->blue.length && + si->blue_pos == f->blue.offset && + si->rsvd_size == f->transp.length && + si->rsvd_pos == f->transp.offset) { + mode->format = f->name; + mode->width = si->lfb_width; + mode->height = si->lfb_height; + mode->stride = si->lfb_linelength; + return true; + } + } + + return false; +} + +__init int create_simplefb(const struct screen_info *si, + const struct simplefb_platform_data *mode) +{ + struct platform_device *pd; + struct resource res; + unsigned long len; + + /* don't use lfb_size as it may contain the whole VMEM instead of only + * the part that is occupied by the framebuffer */ + len = mode->height * mode->stride; + len = PAGE_ALIGN(len); + if (len > si->lfb_size << 16) { + printk(KERN_WARNING "sysfb: VRAM smaller than advertised\n"); + return -EINVAL; + } + + /* setup IORESOURCE_MEM as framebuffer memory */ + memset(&res, 0, sizeof(res)); + res.flags = IORESOURCE_MEM; + res.name = simplefb_resname; + res.start = si->lfb_base; + res.end = si->lfb_base + len - 1; + if (res.end <= res.start) + return -EINVAL; + + pd = platform_device_register_resndata(NULL, "simple-framebuffer", 0, + &res, 1, mode, sizeof(*mode)); + if (IS_ERR(pd)) + return PTR_ERR(pd); + + return 0; +} From 2995e506276bfdc7311eb02db8b2aa1a61a4b849 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Fri, 2 Aug 2013 14:05:23 +0200 Subject: [PATCH 1349/3400] x86: sysfb: move EFI quirks from efifb to sysfb The EFI FB quirks from efifb.c are useful for simple-framebuffer devices as well. Apply them by default so we can convert efifb.c to use efi-framebuffer platform devices. Signed-off-by: David Herrmann Link: http://lkml.kernel.org/r/1375445127-15480-5-git-send-email-dh.herrmann@gmail.com Signed-off-by: H. Peter Anvin --- arch/x86/include/asm/sysfb.h | 57 +++++++++ arch/x86/kernel/Makefile | 1 + arch/x86/kernel/sysfb.c | 3 + arch/x86/kernel/sysfb_efi.c | 214 ++++++++++++++++++++++++++++++++ drivers/video/efifb.c | 234 ++--------------------------------- 5 files changed, 282 insertions(+), 227 deletions(-) create mode 100644 arch/x86/kernel/sysfb_efi.c diff --git a/arch/x86/include/asm/sysfb.h b/arch/x86/include/asm/sysfb.h index 2395fe03f56b..2aeb3e25579c 100644 --- a/arch/x86/include/asm/sysfb.h +++ b/arch/x86/include/asm/sysfb.h @@ -15,6 +15,63 @@ #include #include +enum { + M_I17, /* 17-Inch iMac */ + M_I20, /* 20-Inch iMac */ + M_I20_SR, /* 20-Inch iMac (Santa Rosa) */ + M_I24, /* 24-Inch iMac */ + M_I24_8_1, /* 24-Inch iMac, 8,1th gen */ + M_I24_10_1, /* 24-Inch iMac, 10,1th gen */ + M_I27_11_1, /* 27-Inch iMac, 11,1th gen */ + M_MINI, /* Mac Mini */ + M_MINI_3_1, /* Mac Mini, 3,1th gen */ + M_MINI_4_1, /* Mac Mini, 4,1th gen */ + M_MB, /* MacBook */ + M_MB_2, /* MacBook, 2nd rev. */ + M_MB_3, /* MacBook, 3rd rev. */ + M_MB_5_1, /* MacBook, 5th rev. */ + M_MB_6_1, /* MacBook, 6th rev. */ + M_MB_7_1, /* MacBook, 7th rev. */ + M_MB_SR, /* MacBook, 2nd gen, (Santa Rosa) */ + M_MBA, /* MacBook Air */ + M_MBA_3, /* Macbook Air, 3rd rev */ + M_MBP, /* MacBook Pro */ + M_MBP_2, /* MacBook Pro 2nd gen */ + M_MBP_2_2, /* MacBook Pro 2,2nd gen */ + M_MBP_SR, /* MacBook Pro (Santa Rosa) */ + M_MBP_4, /* MacBook Pro, 4th gen */ + M_MBP_5_1, /* MacBook Pro, 5,1th gen */ + M_MBP_5_2, /* MacBook Pro, 5,2th gen */ + M_MBP_5_3, /* MacBook Pro, 5,3rd gen */ + M_MBP_6_1, /* MacBook Pro, 6,1th gen */ + M_MBP_6_2, /* MacBook Pro, 6,2th gen */ + M_MBP_7_1, /* MacBook Pro, 7,1th gen */ + M_MBP_8_2, /* MacBook Pro, 8,2nd gen */ + M_UNKNOWN /* placeholder */ +}; + +struct efifb_dmi_info { + char *optname; + unsigned long base; + int stride; + int width; + int height; + int flags; +}; + +#ifdef CONFIG_EFI + +extern struct efifb_dmi_info efifb_dmi_list[]; +void sysfb_apply_efi_quirks(void); + +#else /* CONFIG_EFI */ + +static inline void sysfb_apply_efi_quirks(void) +{ +} + +#endif /* CONFIG_EFI */ + #ifdef CONFIG_X86_SYSFB bool parse_mode(const struct screen_info *si, diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 90ecdc5d471a..a5408b965c9d 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -105,6 +105,7 @@ obj-$(CONFIG_OF) += devicetree.o obj-$(CONFIG_UPROBES) += uprobes.o obj-y += sysfb.o obj-$(CONFIG_X86_SYSFB) += sysfb_simplefb.o +obj-$(CONFIG_EFI) += sysfb_efi.o obj-$(CONFIG_PERF_EVENTS) += perf_regs.o obj-$(CONFIG_TRACING) += tracepoint.o diff --git a/arch/x86/kernel/sysfb.c b/arch/x86/kernel/sysfb.c index 7f30e194eb52..193ec2ce46c7 100644 --- a/arch/x86/kernel/sysfb.c +++ b/arch/x86/kernel/sysfb.c @@ -47,6 +47,8 @@ static __init int sysfb_init(void) bool compatible; int ret; + sysfb_apply_efi_quirks(); + /* try to create a simple-framebuffer device */ compatible = parse_mode(si, &mode); if (compatible) { @@ -68,4 +70,5 @@ static __init int sysfb_init(void) return IS_ERR(pd) ? PTR_ERR(pd) : 0; } +/* must execute after PCI subsystem for EFI quirks */ device_initcall(sysfb_init); diff --git a/arch/x86/kernel/sysfb_efi.c b/arch/x86/kernel/sysfb_efi.c new file mode 100644 index 000000000000..b285d4e8c68e --- /dev/null +++ b/arch/x86/kernel/sysfb_efi.c @@ -0,0 +1,214 @@ +/* + * Generic System Framebuffers on x86 + * Copyright (c) 2012-2013 David Herrmann + * + * EFI Quirks Copyright (c) 2006 Edgar Hucek + * + * 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. + */ + +/* + * EFI Quirks + * Several EFI systems do not correctly advertise their boot framebuffers. + * Hence, we use this static table of known broken machines and fix up the + * information so framebuffer drivers can load corectly. + */ + +#include +#include +#include +#include +#include +#include +#include +#include